Tutorial: Use GitLab Observability with a .NET application

Tier: Ultimate Offering: GitLab.com Status: Beta
History
The availability of this feature is controlled by a feature flag. For more information, see the history. This feature is available for testing, but not ready for production use.

In this tutorial, you’ll learn how to create, configure, instrument, and monitor a .NET Core application using GitLab Observability features.

Before you begin

To follow along this tutorial, you must have:

  • A GitLab Ultimate subscription for GitLab.com
  • A local installation of .NET
  • Basic knowledge of Git, .NET, and the core concepts of OpenTelemetry

Create a GitLab project

First, create a GitLab project and a corresponding access token.

  1. On the left sidebar, at the top, select Create new () and New project/repository.
  2. Select Create blank project.
  3. Enter the project details.
    • In the Project name field, enter dotnet-O11y-tutorial.
  4. Select Create project.
  5. In the dotnet-O11y-tutorial project, on the left sidebar, select Settings > Access tokens.
  6. Create a new access token with the Owner role and the read_api and write_observability scopes. Store the token value somewhere safe—you’ll need it later.

Create a .NET application

Next, we’ll create a .NET web application that we can instrument. For this tutorial, let’s create a toy application that returns animal emojis.

  1. Clone the dotnet-O11y-tutorial project and cd to the dotnet-O11y-tutorial directory.
  2. Create a web application by running:

    dotnet new web
    
  3. Create an animal controller file by running the following:

    touch AnimalController.cs
    
  4. Replace the contents of AnimalController.cs with the following:

    using Microsoft.AspNetCore.Mvc;
    
    public class AnimalsController : ControllerBase
    {
        private Dictionary<string, string> animals = new Dictionary<string, string>
        {
            { "dog", "🐶" },
            { "cat", "🐱" },
            { "fish", "🐟" }
        };
    
        private ILogger<AnimalsController> logger;
    
        public AnimalsController(ILogger<AnimalsController> logger)
        {
            this.logger = logger;
        }
    
        [HttpGet("/animals/{animal}")]
        public IActionResult GetAnimal([FromRoute] string animal)
        {
            if (animals.TryGetValue(animal, out string? emoji))
            {
                logger.LogInformation("Animal emoji found for: {animal}", animal);
                return Ok(emoji);
            }
            else
            {
                logger.LogInformation("Could not find animal emoji for: {animal}", animal);
                return NotFound("Animal not found");
            }
        }
    }
    
  5. In the Properties subdirectory, replace the contents of launchSettings.json with the following:

    {
      "$schema": "http://json.schemastore.org/launchsettings.json",
      "profiles": {
        "http": {
          "commandName": "Project",
          "dotnetRunMessages": true,
          "launchBrowser": true,
          "applicationUrl": "http://localhost:8080",
          "environmentVariables": {
            "ASPNETCORE_ENVIRONMENT": "Development"
          }
        }
      }
    }
    
  6. Replace the contents of Program.cs with the following:

    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddControllers();
    
    var app = builder.Build();
    
    app.MapControllers();
    
    app.Run();
    
  7. Build and run the application:

    dotnet build
    dotnet run
    
  8. Visit http://localhost:8080/animals/dog, and you should see the emoji 🐶.

Instrument the application

  1. Install the required OpenTelemetry packages:

    dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
    dotnet add package OpenTelemetry.Extensions.Hosting
    dotnet add package OpenTelemetry.Exporter.Console
    dotnet add package OpenTelemetry.Instrumentation.AspNetCore --prerelease
    dotnet add package OpenTelemetry.Instrumentation.Http --prerelease
    
  2. Replace the contents of Program.cs with the following:

    using OpenTelemetry.Exporter;
    using OpenTelemetry.Logs;
    using OpenTelemetry.Metrics;
    using OpenTelemetry.Resources;
    using OpenTelemetry.Trace;
    
    var builder = WebApplication.CreateBuilder(args);
    
    const string serviceName = "dotnet-O11y-tutorial";
    
    string otelHeaders = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_HEADERS") ?? "empty";
    string otelBaseUrl = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "empty";
    
    builder.Services.AddOpenTelemetry()
        .ConfigureResource(resource => resource.AddService(serviceName))
        .WithTracing(tracing => tracing
            .AddSource(serviceName)
            .AddHttpClientInstrumentation()
            .AddAspNetCoreInstrumentation()
            .AddOtlpExporter(options =>
            {
                options.Endpoint = new Uri(otelBaseUrl + "/traces");
                options.Headers = otelHeaders;
                options.Protocol = OtlpExportProtocol.HttpProtobuf;
            }))
        .WithMetrics(metrics => metrics
            .AddMeter(serviceName)
            .AddHttpClientInstrumentation()
            .AddAspNetCoreInstrumentation()
            .AddOtlpExporter(options =>
            {
                options.Endpoint = new Uri(otelBaseUrl + "/metrics");
                options.Headers = otelHeaders;
                options.Protocol = OtlpExportProtocol.HttpProtobuf;
            }))
        .WithLogging(logging => logging
            .AddConsoleExporter()
            .AddOtlpExporter(options =>
            {
                options.Endpoint = new Uri(otelBaseUrl + "/logs");
                options.Headers = otelHeaders;
                options.Protocol = OtlpExportProtocol.HttpProtobuf;
            }));
    
    builder.Services.AddControllers();
    
    var app = builder.Build();
    
    app.MapControllers();
    
    app.Run();
    
  3. Find your group ID:
    1. On the left sidebar, select Search or go to and find the top-level group with the dotnet-O11y-tutorial project. For example, if your project URL is https://gitlab.com/tankui/observability/dotnet-O11y-tutorial, the top-level group is tanuki.
    2. On the group overview page, in the upper-right corner, select Actions ().
    3. Select Copy group ID. Save the copied ID for later.
  4. Find your project ID:
    1. On the dotnet-O11y-tutorial project overview page, in the upper-right corner, select Actions ().
    2. Select Copy project ID. Save the copied ID for later.
  5. Configure and run your application with instrumentation:

    env OTEL_EXPORTER_OTLP_ENDPOINT="https://observe.gitlab.com/v3/{{GROUP_ID}}/{{PROJECT_ID}}/ingest" \
    OTEL_EXPORTER_OTLP_HEADERS="PRIVATE-TOKEN={{ACCESS_TOKEN}}" \
    OTEL_LOG_LEVEL="debug" \
    dotnet run
    
  6. Visit http://localhost:8080/animals/dog to generate some events.

View the information in GitLab

To view the exported information from your test project:

  1. On the left sidebar, select Search or go to and find your project.
  2. Select Monitor, then either Logs, Metrics, or Traces.