Monitoring NServiceBus endpoints with Application Insights

Component: NServiceBus
NuGet Package: NServiceBus (8-pre)
This page targets a pre-release version. Pre-releases are subject to change and samples are not guaranteed to be fully functional.

Azure Application Insights (App Insights) provides monitoring and alerting capabilities that can be leveraged to monitor the health of NServiceBus endpoints.

This sample shows how to capture NServiceBus OpenTelemetry traces and export them to App Insights. The sample simulates message load as well as a 10% failure rate on processing messages.

Prerequisites

This sample requires an App Insights connection string.

Although the sample uses Azure Application Insights, the solution itself does not require an Azure message transport. This example uses the Learning Transport but could be modified to run on any transport.

Running the sample

  1. Create an Application Insights resource in Azure
  2. Copy the connection string from the Azure portal dashboard into the sample
  3. Start the sample endpoint
  4. Press any key to send a message, or ESC to quit

Reviewing traces

  1. On the Azure portal dashboard, open the InvestigatePerformance panel
  2. Drill into the samples
  3. Review the custom properties

Timeline view of a trace in Application Insights

Reviewing meters

  1. Open the Azure portal dashboard for the configured Application Insight instance
  2. Navigate to MonitoringMetrics
  3. Add metrics with the following information:
  • Metric Namespace: azure.applicationinsights
  • Metrics:
    • nservicebus.messaging.successes
    • nservicebus.messaging.failures
    • nservicebus.messaging.fetches

Graph tracking success and failed metrics in Application Insights

It may take a few minutes for the meter data to populate to Azure. Meters will only appear on the dashboard once they have reported at least one value.

Code walk-through

The OpenTelemetry instrumentation is enabled on the endpoint.

var endpointConfiguration = new EndpointConfiguration(EndpointName);
endpointConfiguration.EnableOpenTelemetry();

Tracing

The endpoint configures an OpenTelemetry trace provider that includes the NServiceBus.Core source and exports traces to Azure Monitor.

var traceProvider = Sdk.CreateTracerProviderBuilder()
    .SetResourceBuilder(resourceBuilder)
    .AddSource("NServiceBus.Core")
    .AddAzureMonitorTraceExporter(o => o.ConnectionString = appInsightsConnectionString)
    .AddConsoleExporter()
    .Build();

Meters

The endpoint also configures an OpenTelemetry meter provider that includes the NServiceBus.Core meter and exports data to Azure Monitor.

var telemetryConfiguration = TelemetryConfiguration.CreateDefault();
telemetryConfiguration.ConnectionString = appInsightsConnectionString;
var telemetryClient = new TelemetryClient(telemetryConfiguration);
telemetryClient.Context.GlobalProperties["Endpoint"] = EndpointName;

var meterProvider = Sdk.CreateMeterProviderBuilder()
    .SetResourceBuilder(resourceBuilder)
    .AddMeter("NServiceBus.Core")
    .AddNServiceBusTelemetryClientExporter(telemetryClient)
    .AddConsoleExporter()
    .Build();

Meter shim

The Azure Monitor exporter package does not currently support exporting meter data. The sample includes custom code to collect the meter.

The custom meter exporter captures all meters that begin with nservicebus. of the long sum type, and forwards them to a TelemetryClient.

class NServiceBusTelemetryClientExporter : BaseExporter<Metric>
{
    readonly TelemetryClient telemetryClient;

    public NServiceBusTelemetryClientExporter(TelemetryClient telemetryClient)
    {
        this.telemetryClient = telemetryClient;
    }

    public override ExportResult Export(in Batch<Metric> batch)
    {
        foreach (var metric in batch)
        {
            if (!metric.Name.StartsWith("nservicebus.")) continue;
            if (metric.MetricType != MetricType.LongSum) continue;

            var telemetryMetric = telemetryClient.GetMetric(metric.Name, "QueueName");

            foreach (var dataPoint in metric.GetMetricPoints())
            {
                telemetryMetric.TrackValue(dataPoint.GetSumLong(), GetQueueName(dataPoint));
            }
        }
        return ExportResult.Success;
    }

    static string GetQueueName(MetricPoint metricPoint)
    {
        foreach (var tag in metricPoint.Tags)
        {
            if (tag.Key == "nservicebus.queue")
            {
                return (string)tag.Value;
            }
        }

        return "UNKNOWN";
    }
}

This exporter is installed into the meter provider builder with a custom extension method. The exporter is wrapped by a PeriodicExportingMetricReader instance that executes the exporter once every 10 seconds.

public static MeterProviderBuilder AddNServiceBusTelemetryClientExporter(
    this MeterProviderBuilder builder,
    TelemetryClient telemetryClient)
{
    var exporter = new NServiceBusTelemetryClientExporter(telemetryClient);
    var reader = new PeriodicExportingMetricReader(exporter, 10000)
    {
        TemporalityPreference = MetricReaderTemporalityPreference.Delta
    };

    return builder.AddReader(reader);
}
The shim passes QueueName as a custom dimension which allows filtering the graphs in Application Insights. Multi-dimensional metrics are not enabled by default. Check the Azure Monitor documentation for instructions on how to enable this feature.

Related Articles

  • OpenTelemetry
    Observability of NServiceBus endpoints with OpenTelemetry.

Last modified