Skip to content

.NET OpenTelemetry Instrumentation

This tutorial demonstrates how to instrument .NET applications to capture logs, metrics and traces using OpenTelemetry, and send them to Coralogix.

The OpenTelemetry .NET instrumentation for metrics, traces, and logs is currently stable. You can find the OpenTelemetry .NET SDK documentation here.

Note

The examples provided here do not represent a concrete standard for instrumenting .NET applications but serve as guides for basic implementation. You should review your codebase and determine the best approach to manual or auto instrumentation for your specific project.

Prerequisites

Auto-Instrumentation

The OpenTelemetry .NET Auto-Instrumentation enables you to send traces and metrics from .NET applications to Coralogix without modifying your source code.

Required Configuration

# Coralogix endpoint and authentication
export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingress.<CORALOGIX_REGION>.coralogix.com:443"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <your-api-key>"
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"

# Service identification
export OTEL_SERVICE_NAME="my-dotnet-service"
export OTEL_RESOURCE_ATTRIBUTES="application.name=my-app,cx.application.name=my-app,cx.subsystem.name=my-subsystem"

Replace <CORALOGIX_REGION> with your Coralogix domain: eu1, eu2, us1, us2, ap1, or ap2.

For complete setup instructions including profiler configuration, see the OpenTelemetry .NET Auto-Instrumentation GitHub repository and Zero Code Configuration methods and settings.

Manual Instrumentation

Before instrumenting logs, traces, or metrics, we will set up Coralogix details and a shared OpenTelemetry Resource. You'll reuse these across all signals.

1. Create a new .NET console application

dotnet new console -n CoralogixOtelExample
cd CoralogixOtelExample

2. Set the environment variables required for Coralogix

export CORALOGIX_API_KEY="<your-coralogix-api-key>"
export CORALOGIX_APP_NAME="my-app"
export CORALOGIX_SUBSYSTEM_NAME="my-subsystem"
export CORALOGIX_DOMAIN="EU1"

Domain Options: EU1, EU2, US1, US2, AP1, AP2

3. Install the necessary NuGet packages

dotnet add package OpenTelemetry --version 1.9.0
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol --version 1.9.0
dotnet add package OpenTelemetry.Extensions.Hosting --version 1.9.0
dotnet add package Microsoft.Extensions.Logging --version 8.0.0

We will add signal-specific packages later in the corresponding sections.

4. Set up Coralogix configuration and shared Resource

using System.Diagnostics;
using Microsoft.Extensions.Logging;
using OpenTelemetry;
using OpenTelemetry.Logs;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

namespace CoralogixOtelExample;

class Program
{
    private static readonly ActivitySource ActivitySource = new("CoralogixOtelExample", "1.0.0");

    static void Main(string[] args)
    {
        try
        {
            var config = LoadConfiguration();

            var resourceBuilder = BuildResourceAttributes(config);

            Console.WriteLine("OpenTelemetry configured successfully");
        }
        catch (InvalidOperationException ex)
        {
            Console.Error.WriteLine($"Configuration Error: {ex.Message}");
            Environment.Exit(1);
        }
    }

    private static CoralogixConfig LoadConfiguration()
    {
        var domain = Environment.GetEnvironmentVariable("CORALOGIX_DOMAIN") ?? "EU1";
        var apiKey = Environment.GetEnvironmentVariable("CORALOGIX_API_KEY");
        var applicationName = Environment.GetEnvironmentVariable("CORALOGIX_APP_NAME") ?? "dotnet-otel-example";
        var subsystemName = Environment.GetEnvironmentVariable("CORALOGIX_SUBSYSTEM_NAME") ?? "example-subsystem";

        if (string.IsNullOrWhiteSpace(apiKey))
        {
            throw new InvalidOperationException(
                "CORALOGIX_API_KEY is required. Set it via environment variable.");
        }

        return new CoralogixConfig
        {
            Domain = domain,
            ApiKey = apiKey,
            ApplicationName = applicationName,
            SubsystemName = subsystemName
        };
    }

    private static ResourceBuilder BuildResourceAttributes(CoralogixConfig config)
    {
        return ResourceBuilder.CreateDefault()
            .AddService(
                serviceName: config.SubsystemName,
                serviceNamespace: config.ApplicationName,
                serviceVersion: "1.0.0")
            .AddAttributes(new Dictionary<string, object>
            {
                ["cx.application.name"] = config.ApplicationName,
                ["cx.subsystem.name"] = config.SubsystemName
            });
    }
}

record CoralogixConfig
{
    public required string Domain { get; init; }
    public required string ApiKey { get; init; }
    public required string ApplicationName { get; init; }
    public required string SubsystemName { get; init; }
}

5. Running the example

dotnet run

Logs

For logging, we will initialize a LoggerProvider that integrates with the standard Microsoft.Extensions.Logging framework. This allows you to use familiar logging patterns while automatically exporting to Coralogix.

1. Configure the Logger Provider

// Add this method to the Program class
private static ILoggerFactory ConfigureLogging(ResourceBuilder resourceBuilder, CoralogixConfig config)
{
    return LoggerFactory.Create(builder =>
    {
        builder.SetMinimumLevel(LogLevel.Information);
        builder.AddOpenTelemetry(options =>
        {
            options.SetResourceBuilder(resourceBuilder);
            options.AddOtlpExporter(otlpOptions => ConfigureOtlpExporter(otlpOptions, config));
            options.IncludeFormattedMessage = true;
            options.IncludeScopes = true;
        });
    });
}

private static void ConfigureOtlpExporter(OpenTelemetry.Exporter.OtlpExporterOptions options, CoralogixConfig config)
{
    options.Endpoint = new Uri($"https://ingress.{config.Domain}.coralogix.com:443");
    options.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc;
    options.Headers = $"Authorization=Bearer {config.ApiKey}";
}

2. Use the logger to emit logs

static void Main(string[] args)
{
    try
    {
        var config = LoadConfiguration();
        var resourceBuilder = BuildResourceAttributes(config);

        using var loggerFactory = ConfigureLogging(resourceBuilder, config);
        var logger = loggerFactory.CreateLogger<Program>();

        // Emit logs
        logger.LogInformation("Hello from Coralogix .NET OpenTelemetry!");
        logger.LogWarning("This is a warning message");
        logger.LogError("This is an error message");

        // Structured logging
        logger.LogInformation("User {UserId} performed {Action}", "user-123", "login");

        // Give time for logs to be exported
        Thread.Sleep(5000);
    }
    catch (InvalidOperationException ex)
    {
        Console.Error.WriteLine($"Configuration Error: {ex.Message}");
        Environment.Exit(1);
    }
}

After a successful run, you can view your logs in the Coralogix Logs dashboard.

.NET OpenTelemetry Logging

Traces

For tracing, we will initialize an OpenTelemetry TracerProvider that provides ActivitySource to create spans. In this example, we'll manually instrument a simple operation.

1. Configure the Trace Provider

// Add this method to the Program class
private static TracerProvider ConfigureTracing(ResourceBuilder resourceBuilder, CoralogixConfig config)
{
    return Sdk.CreateTracerProviderBuilder()
        .SetResourceBuilder(resourceBuilder)
        .AddSource(ActivitySource.Name)
        .AddOtlpExporter(options => ConfigureOtlpExporter(options, config))
        .Build();
}

2. Create traces with spans

static void Main(string[] args)
{
    try
    {
        var config = LoadConfiguration();
        var resourceBuilder = BuildResourceAttributes(config);

        using var tracerProvider = ConfigureTracing(resourceBuilder, config);
        using var loggerFactory = ConfigureLogging(resourceBuilder, config);
        var logger = loggerFactory.CreateLogger<Program>();

        // Create a trace span
        using (var activity = ActivitySource.StartActivity("SampleOperation"))
        {
            activity?.SetTag("user.id", "user-123");
            activity?.SetTag("operation.type", "example");

            logger.LogInformation("Processing sample operation");

            activity?.SetStatus(ActivityStatusCode.Ok);
        }

        // Give time for telemetry to export
        Thread.Sleep(1000);
    }
    catch (InvalidOperationException ex)
    {
        Console.Error.WriteLine($"Configuration Error: {ex.Message}");
        Environment.Exit(1);
    }
}

You can view your traces in the Coralogix Tracing dashboard.

.NET OpenTelemetry Tracing

Metrics

For producing metrics, we will set up a MeterProvider, which lets us use a Meter to define and record metrics. Read more about supported metrics in the official documentation.

1. Install the necessary NuGet package for metrics

dotnet add package OpenTelemetry.Instrumentation.Runtime --version 1.9.0

2. Configure the Meter Provider

using OpenTelemetry.Metrics;

// Add this method to the Program class
private static MeterProvider ConfigureMetrics(ResourceBuilder resourceBuilder, CoralogixConfig config)
{
    return Sdk.CreateMeterProviderBuilder()
        .SetResourceBuilder(resourceBuilder)
        .AddMeter("CoralogixOtelExample")
        .AddRuntimeInstrumentation()
        .AddOtlpExporter(options => ConfigureOtlpExporter(options, config))
        .Build();
}

3. Create and record metrics

using System.Diagnostics.Metrics;

// Add to the Program class
private static readonly Meter Meter = new("CoralogixOtelExample", "1.0.0");

static void Main(string[] args)
{
    try
    {
        var config = LoadConfiguration();
        var resourceBuilder = BuildResourceAttributes(config);

        using var meterProvider = ConfigureMetrics(resourceBuilder, config);

        // Create a counter metric
        var requestCounter = Meter.CreateCounter<long>("sample.counter", "requests", "Sample counter metric");

        // Record some metrics
        for (int i = 0; i < 10; i++)
        {
            requestCounter.Add(1, new KeyValuePair<string, object?>("status", "success"));
        }

        // Give time for metrics to export
        Thread.Sleep(1000);
    }
    catch (InvalidOperationException ex)
    {
        Console.Error.WriteLine($"Configuration Error: {ex.Message}");
        Environment.Exit(1);
    }
}

You can view your metrics in the Coralogix Metrics dashboard.

.NET OpenTelemetry Metrics

Support

Need help?

Our world-class customer success team is available 24/7 to walk you through your setup and answer any questions that may come up.

Feel free to reach out to us via our in-app chat or by sending us an email at support@coralogix.com.

Was this helpful?