如何度量“handle”的调用时间方法在NServiceBus

本文关键字:调用 时间 方法 NServiceBus handle 何度量 度量 | 更新日期: 2023-09-27 17:51:04

我需要在IHandleMessages<>接口的每个实例中测量Handle方法的调用时间。我尝试使用温莎城堡拦截器,

public class NsbHandlerMeasurementInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        if (invocation.Method.Name == ExpressionExtender.GetMethodName<IHandleMessages<DummyType>>(b => b.Handle(null)))
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            invocation.Proceed();
            stopwatch.Stop();
            // save stopwatch.ElapsedMilliseconds value
        }
        else
        {
            invocation.Proceed();
        }
    }
}

安装代码:

container.Register(Component.For<NsbHandlerMeasurementInterceptor>());
container.Kernel.ComponentModelBuilder.AddContributor(new NsbWindsorModelConstructionContributor());
public class NsbWindsorModelConstructionContributor : IContributeComponentModelConstruction
{
    public void ProcessModel(global::Castle.MicroKernel.IKernel kernel, global::Castle.Core.ComponentModel model)
    {
        if (model.Services.Any(s => s.ImplementsGenericInterface(typeof(IHandleMessages<>))))
        {
            model.Interceptors.AddIfNotInCollection(new InterceptorReference(typeof(NsbHandlerMeasurementInterceptor)));    
        }
    }
}

但是从那一刻起Handle方法没有被触发

我知道NSB中的性能计数器,但我需要更具体的、面向类型的测量。这是可能的和可以实现的吗?

如何度量“handle”的调用时间方法在NServiceBus

确实有性能计数器,但如果这还不够,那么你可以在NServiceBus管道中创建自己的步骤。

http://docs.particular.net/nservicebus/pipeline/customizing

通过继承IBehavior<IncomingContext>创建自定义行为并实现接口。现在您可以访问IncomingContext参数,其中包含有关类型的信息。

看一下InvokeHandlersBehavior行为的实现。此行为调用实际的处理程序,并且可能需要包装它。

https://github.com/Particular/NServiceBus/blob/5.2.0/src/NServiceBus.Core/Unicast/Behaviors/InvokeHandlersBehavior.cs

class InvokeHandlersBehavior : IBehavior<IncomingContext>
{
    public void Invoke(IncomingContext context, Action next)
    {
        ActiveSagaInstance saga;
        if (context.TryGet(out saga) && saga.NotFound && saga.SagaType == context.MessageHandler.Instance.GetType())
        {
            next();
            return;
        }
        var messageHandler = context.MessageHandler;
        messageHandler.Invocation(messageHandler.Instance, context.IncomingLogicalMessage.Instance);
        next();
    }
}

然后你需要注册它,使它在管道中调用。

class NewStepInPipeline : RegisterStep
{
    public NewStepInPipeline()
        : base("NewStepInPipeline", typeof(SampleBehavior), "Logs a warning when processing takes too long")
    {
        // Optional: Specify where it needs to be invoked in the pipeline, for example InsertBefore or InsertAfter
        InsertBefore(WellKnownStep.InvokeHandlers);
    }
}
class NewStepInPipelineRegistration : INeedInitialization
{
    public void Customize(BusConfiguration busConfiguration)
    {
        // Register the new step in the pipeline
        busConfiguration.Pipeline.Register<NewStepInPipeline>();
    }
}

请注意,此代码需要v5版本。查看特定文档网站以获取其他版本的帮助。