Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

OpenTelemetry & correlation support for Azure Functions

I have a project written in .net 6. I use Azure Function to send data to Service bus and MediatR. How can I add Open Telemetry to my Azure functions?

[Function("EBcktErroredFunction")]
  public Task EBcktErroredFunctionAsync([ServiceBusTrigger("e-bckt-errored", "bckts-creation-finalize")] EBcktErrored payload)
  {
    return _mediator.Send(
      new SyncBcktErroredToStoreCommand
      {
        SBcktId = payload.BcktId,
        EBcktId = payload.ExternalBcktId
      }
    );

Not related but in the bicep file it looks like this;

resource eBcktErroredSubscription 'Microsoft.ServiceBus/namespaces/topics/subscriptions' = {
  name: '${serviceBusName}/e-bckt-errored/${appName}'
  properties: {
    autoDeleteOnIdle: ''
    deadLetteringOnMessageExpiration: 
    defaultMessageTimeToLive: ''
    enableBatchedOperations: true
    lockDuration: ''
  }
}

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You can find a full example on GitHub and a corresponding discussion about "Using OpenTelemetry Sdk with Azure Functions".

Most relevant code (you should look at the full code for reference):

    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            // OpenTelemetry Resource to be associated with logs, metrics and traces
            var openTelemetryResourceBuilder = ResourceBuilder.CreateDefault().AddService("opentelemetry-service");

            // Enable Logging with OpenTelemetry
            builder.Services.AddLogging( (loggingBuilder) => 
                {
                    // Only Warning or above will be sent to Opentelemetry
                    loggingBuilder.AddFilter<OpenTelemetryLoggerProvider>("*", LogLevel.Warning);
                }
            );
            
            builder.Services.AddSingleton<ILoggerProvider, OpenTelemetryLoggerProvider>();
            builder.Services.Configure<OpenTelemetryLoggerOptions>( (openTelemetryLoggerOptions) =>
                {
                    openTelemetryLoggerOptions.SetResourceBuilder(openTelemetryResourceBuilder);
                    openTelemetryLoggerOptions.IncludeFormattedMessage = true;
                    openTelemetryLoggerOptions.AddConsoleExporter();
                }
            );

            // Enable Tracing with OpenTelemetry
            var openTelemetryTracerProvider = Sdk.CreateTracerProviderBuilder()
                .SetResourceBuilder(openTelemetryResourceBuilder)
                .SetSampler(new AlwaysOnSampler())
                .AddAspNetCoreInstrumentation()
                .AddConsoleExporter()
                .Build();
            builder.Services.AddSingleton(openTelemetryTracerProvider);

            // Enable Metrics with OpenTelemetry
            var openTelemetryMeterProvider = Sdk.CreateMeterProviderBuilder()
                .SetResourceBuilder(openTelemetryResourceBuilder)
                .AddAspNetCoreInstrumentation()
                .AddMeter(Function1.MyMeter.Name)
                .AddConsoleExporter(consoleOptions =>
                    {
                        consoleOptions.MetricReaderType = MetricReaderType.Periodic;
                        consoleOptions.AggregationTemporality = AggregationTemporality.Cumulative;
                        consoleOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = 10000;
                    })
                .Build();
            builder.Services.AddSingleton(openTelemetryMeterProvider);
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogWarning("C# HTTP trigger function processed a request.");
            MyCounter.Add(1, new("name", "apple"), new("color", "red"));

            string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            string responseMessage = string.IsNullOrEmpty(name)
                ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
                : $"Hello, {name}. This HTTP triggered function executed successfully.";

            log.LogWarning("Name is {name}", name);
            Activity.Current?.SetTag("name", name);

            return new OkObjectResult(responseMessage);
        }
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading