Delen via


Voorbeeld: OpenTelemetry gebruiken met Prometheus, Grafana en Jaeger

In dit voorbeeld wordt Prometheus gebruikt voor het verzamelen van metrische gegevens, Grafana voor het maken van een dashboard en Jaeger om gedistribueerde tracering weer te geven.

1. Het project maken

Maak een eenvoudig web-API-project met behulp van de ASP.NET Core Empty-sjabloon in Visual Studio of de volgende .NET CLI-opdracht:

dotnet new web

2. Metrische gegevens en activiteitsdefinities toevoegen

De volgende code definieert een nieuwe metrische waarde (greetings.count) voor het aantal keren dat de API is aangeroepen en een nieuwe activiteitsbron (OtPrGrYa.Example).

// Custom metrics for the application
var greeterMeter = new Meter("OtPrGrYa.Example", "1.0.0");
var countGreetings = greeterMeter.CreateCounter<int>("greetings.count", description: "Counts the number of greetings");

// Custom ActivitySource for the application
var greeterActivitySource = new ActivitySource("OtPrGrJa.Example");

3. Een API-eindpunt maken

app.MapGet("/", SendGreeting);
async Task<String> SendGreeting(ILogger<Program> logger)
{
    // Create a new Activity scoped to the method
    using var activity = greeterActivitySource.StartActivity("GreeterActivity");

    // Log a message
    logger.LogInformation("Sending greeting");

    // Increment the custom counter
    countGreetings.Add(1);

    // Add a tag to the Activity
    activity?.SetTag("greeting", "Hello World!");

    return "Hello World!";
}

Notitie

De API-definitie gebruikt niets specifieks voor OpenTelemetry. De .NET-API's worden gebruikt voor waarneembaarheid.

4. Verwijzen naar de OpenTelemetry-pakketten

Gebruik de NuGet-Pakketbeheer of opdrachtregel om de volgende NuGet-pakketten toe te voegen:

<ItemGroup>
    <PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.9.0" />
    <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.9.0" />
    <PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.9.0-beta.2" />
    <PackageReference Include="OpenTelemetry.Exporter.Zipkin" Version="1.9.0" />
    <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.9.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.9.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.9.0" />
</ItemGroup>

Notitie

Gebruik de nieuwste versies, omdat de OTel-API's voortdurend in ontwikkeling zijn.

5. OpenTelemetry configureren met de juiste providers

var tracingOtlpEndpoint = builder.Configuration["OTLP_ENDPOINT_URL"];
var otel = builder.Services.AddOpenTelemetry();

// Configure OpenTelemetry Resources with the application name
otel.ConfigureResource(resource => resource
    .AddService(serviceName: builder.Environment.ApplicationName));

// Add Metrics for ASP.NET Core and our custom metrics and export to Prometheus
otel.WithMetrics(metrics => metrics
    // Metrics provider from OpenTelemetry
    .AddAspNetCoreInstrumentation()
    .AddMeter(greeterMeter.Name)
    // Metrics provides by ASP.NET Core in .NET 8
    .AddMeter("Microsoft.AspNetCore.Hosting")
    .AddMeter("Microsoft.AspNetCore.Server.Kestrel")
    .AddPrometheusExporter());

// Add Tracing for ASP.NET Core and our custom ActivitySource and export to Jaeger
otel.WithTracing(tracing =>
{
    tracing.AddAspNetCoreInstrumentation();
    tracing.AddHttpClientInstrumentation();
    tracing.AddSource(greeterActivitySource.Name);
    if (tracingOtlpEndpoint != null)
    {
        tracing.AddOtlpExporter(otlpOptions =>
         {
             otlpOptions.Endpoint = new Uri(tracingOtlpEndpoint);
         });
    }
    else
    {
        tracing.AddConsoleExporter();
    }
});

Deze code maakt gebruik van ASP.NET Core-instrumentatie om metrische gegevens en activiteiten van ASP.NET Core op te halen. Ook worden de Metrics en ActivitySource providers geregistreerd voor respectievelijk metrische gegevens en tracering.

De code maakt gebruik van de Prometheus-exporteur voor metrische gegevens, die gebruikmaakt van ASP.NET Core om het eindpunt te hosten, dus u moet ook het volgende toevoegen:

// Configure the Prometheus scraping endpoint
app.MapPrometheusScrapingEndpoint();

6. Het project uitvoeren

Voer het project uit en open vervolgens de API met de browser of curl.

curl -k http://localhost:7275

Telkens wanneer u de pagina aanvraagt, wordt de telling verhoogd voor het aantal begroetingen dat is gedaan. U hebt toegang tot het eindpunt voor metrische gegevens met behulp van dezelfde basis-URL, met het pad /metrics.

6.1 Logboekuitvoer

De logboekregistratie-instructies van de code worden uitgevoerd met behulp van ILogger. De consoleprovider is standaard ingeschakeld, zodat de uitvoer wordt omgeleid naar de console.

Er zijn een aantal opties voor het uitgaan van logboeken vanuit .NET:

  • stdout en stderr uitvoer wordt omgeleid naar logboekbestanden door containersystemen zoals Kubernetes.
  • Met behulp van logboekbibliotheken die worden geïntegreerd met ILogger, zijn deze onder andere Serilog of NLog.
  • Het gebruik van logboekproviders voor OTel, zoals OTLP of de Azure Monitor-exporteur, wordt hieronder verder weergegeven.

6.2 Toegang tot de metrische gegevens

U hebt toegang tot de metrische gegevens met behulp van het /metrics eindpunt.

curl -k https://localhost:7275/
Hello World!

curl -k https://localhost:7275/metrics
# TYPE greetings_count counter
# HELP greetings_count Counts the number of greetings
greetings_count 1 1686894204856

# TYPE current_connections gauge
# HELP current_connections Number of connections that are currently active on the server.
current_connections{endpoint="127.0.0.1:7275"} 1 1686894204856
current_connections{endpoint="[::1]:7275"} 0 1686894204856
current_connections{endpoint="[::1]:5212"} 1 1686894204856
...

De uitvoer van metrische gegevens is een momentopname van de metrische gegevens op het moment dat het eindpunt wordt aangevraagd. De resultaten worden aangeboden in prometheus tentoonstellingsindeling, die door de mens leesbaar maar beter begrepen wordt door Prometheus. Dit onderwerp wordt behandeld in de volgende fase.

6.3 Toegang tot de tracering

Als u naar de console voor de server kijkt, ziet u de uitvoer van de consoletraceringexporteur, die de informatie uitvoert in een door mensen leesbare indeling. Er moeten twee activiteiten worden weergegeven, één van uw aangepaste ActivitySourceactiviteiten en de andere van ASP.NET Core:

Activity.TraceId:            2e00dd5e258d33fe691b965607b91d18
Activity.SpanId:             3b7a891f55b97f1a
Activity.TraceFlags:         Recorded
Activity.ParentSpanId:       645071fd0011faac
Activity.ActivitySourceName: OtPrGrYa.Example
Activity.DisplayName:        GreeterActivity
Activity.Kind:               Internal
Activity.StartTime:          2023-06-16T04:50:26.7675469Z
Activity.Duration:           00:00:00.0023974
Activity.Tags:
    greeting: Hello World!
Resource associated with Activity:
    service.name: OTel-Prometheus-Grafana-Jaeger
    service.instance.id: e1afb619-bc32-48d8-b71f-ee196dc2a76a
    telemetry.sdk.name: opentelemetry
    telemetry.sdk.language: dotnet
    telemetry.sdk.version: 1.5.0

Activity.TraceId:            2e00dd5e258d33fe691b965607b91d18
Activity.SpanId:             645071fd0011faac
Activity.TraceFlags:         Recorded
Activity.ActivitySourceName: Microsoft.AspNetCore
Activity.DisplayName:        /
Activity.Kind:               Server
Activity.StartTime:          2023-06-16T04:50:26.7672615Z
Activity.Duration:           00:00:00.0121259
Activity.Tags:
    net.host.name: localhost
    net.host.port: 7275
    http.method: GET
    http.scheme: https
    http.target: /
    http.url: https://localhost:7275/
    http.flavor: 1.1
    http.user_agent: curl/8.0.1
    http.status_code: 200
Resource associated with Activity:
    service.name: OTel-Prometheus-Grafana-Jaeger
    service.instance.id: e1afb619-bc32-48d8-b71f-ee196dc2a76a
    telemetry.sdk.name: opentelemetry
    telemetry.sdk.language: dotnet
    telemetry.sdk.version: 1.5.0

De eerste is de interne aangepaste activiteit die u hebt gemaakt. De tweede wordt gemaakt door ASP.NET voor de aanvraag en bevat tags voor de eigenschappen van de HTTP-aanvraag. U ziet dat beide hetzelfde TraceIdhebben, waarmee één transactie wordt geïdentificeerd en dat in een gedistribueerd systeem kan worden gebruikt om de traceringen van elke service die betrokken is bij een transactie te correleren. De id's worden verzonden als HTTP-headers. ASP.NET Core een TraceId als er geen aanwezig is wanneer er een aanvraag wordt ontvangen. HttpClient bevat standaard de headers voor uitgaande aanvragen. Elke activiteit heeft een SpanId, wat de combinatie is van TraceId en SpanId die elke activiteit uniek identificeert. De Greeter activiteit wordt gekoppeld aan de HTTP-activiteit via ParentSpanIdde activiteit, die wordt toegewezen aan de SpanId HTTP-activiteit.

In een latere fase voert u deze gegevens in Jaeger in om de gedistribueerde traceringen te visualiseren.

7. Metrische gegevens verzamelen met Prometheus

Prometheus is een verzameling, aggregatie en tijdreeksdatabasesysteem voor metrische gegevens. U configureert deze met de metrische eindpunten voor elke service en de waarden worden periodiek verwijderd en opgeslagen in de tijdreeksdatabase. Vervolgens kunt u ze analyseren en verwerken als dat nodig is.

De metrische gegevens die worden weergegeven in de Prometheus-indeling, zijn een momentopname van een bepaald tijdstip van de metrische gegevens van het proces. Telkens wanneer een aanvraag wordt ingediend bij het eindpunt voor metrische gegevens, worden de huidige waarden weergegeven. Hoewel huidige waarden interessant zijn, worden ze waardevoller in vergelijking met historische waarden om trends te bekijken en te detecteren of waarden afwijkend zijn. Vaak hebben services pieken in het gebruik op basis van het tijdstip van de dag of wereld evenementen, zoals een vakantie winkelen spree. Door de waarden te vergelijken met historische trends, kunt u detecteren of ze abnormaal zijn of als een metrische waarde na verloop van tijd langzaam slechter wordt.

Tijdens het proces worden geen geschiedenis van deze metrische momentopnamen opgeslagen. Het toevoegen van deze mogelijkheid aan het proces kan resource-intensief zijn. In een gedistribueerd systeem hebt u vaak meerdere exemplaren van elk knooppunt, dus u wilt de metrische gegevens uit alle knooppunten kunnen verzamelen en vervolgens aggregeren en vergelijken met hun historische waarden.

7.1 Prometheus installeren en configureren

Download Prometheus voor uw platform van https://prometheus.io/download/ en pak de inhoud van de download uit.

Kijk boven aan de uitvoer van de actieve server om het poortnummer voor het HTTP-eindpunt op te halen. Voorbeeld:

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: https://localhost:7275
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5212

Wijzig het YAML-configuratiebestand van Prometheus om de poort voor uw HTTP-scraping-eindpunt op te geven en stel een lager scraping-interval in. Voorbeeld:

  scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: "prometheus"

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    scrape_interval: 1s # poll very quickly for a more responsive demo
    static_configs:
      - targets: ["localhost:5212"]

Start Prometheus en kijk in de uitvoer voor de poort waarop deze wordt uitgevoerd, meestal 9090:

>prometheus.exe
...
ts=2023-06-16T05:29:02.789Z caller=web.go:562 level=info component=web msg="Start listening for connections" address=0.0.0.0:9090

Open deze URL in uw browser. In de gebruikersinterface van Prometheus kunt u nu query's uitvoeren op uw metrische gegevens. Gebruik de gemarkeerde knop in de volgende afbeelding om de Metrics Explorer te openen, waarin alle beschikbare metrische gegevens worden weergegeven.

Prometheus Metrics Explorer

Selecteer de greetings_count metrische waarde om een grafiek met waarden weer te geven.

Grafiek van greetings_count

8. Grafana gebruiken om een dashboard met metrische gegevens te maken

Grafana is een dashboardproduct dat dashboards en waarschuwingen kan maken op basis van Prometheus of andere gegevensbronnen.

Download en installeer de OSS-versie van Grafana door https://grafana.com/oss/grafana/ de instructies voor uw platform te volgen. Na de installatie wordt Grafana doorgaans uitgevoerd op poort 3000, dus open http://localhost:3000 deze in uw browser. U moet zich aanmelden; de standaardgebruikersnaam en het standaardwachtwoord zijn beide admin.

Kies verbindingen in het hamburgermenu en voer vervolgens de tekst prometheus in om uw eindpunttype te selecteren. Selecteer Een Prometheus-gegevensbron maken om een nieuwe gegevensbron toe te voegen.

Grafana-verbinding met prometheus

U moet de volgende eigenschappen instellen:

  • URL van Prometheus-server: http://localhost:9090/ de poort wijzigen indien van toepassing

Selecteer Opslaan en testen om de configuratie te controleren.

Zodra u een bericht krijgt dat het is gelukt, kunt u een dashboard configureren. Klik op de koppeling voor het bouwen van een dashboard die wordt weergegeven in de pop-up voor het succesbericht.

Selecteer Een visualisatie toevoegen en kies vervolgens de Prometheus-gegevensbron die u zojuist hebt toegevoegd als de gegevensbron.

De ontwerpfunctie voor dashboardvensters moet worden weergegeven. In de onderste helft van het scherm kunt u de query definiëren.

Grafana-query met behulp van greetings_count

Selecteer de greetings_count metrische waarde en selecteer vervolgens Query's uitvoeren om de resultaten te bekijken.

Met Grafana kunt u geavanceerde dashboards ontwerpen waarmee een willekeurig aantal metrische gegevens wordt bijgehouden.

Elke metrische waarde in .NET kan extra dimensies hebben. Dit zijn sleutel-waardeparen die kunnen worden gebruikt om de gegevens te partitioneren. De ASP.NET metrische gegevens bevatten allemaal een aantal dimensies die van toepassing zijn op de teller. De teller heeft Microsoft.AspNetCore.Hosting bijvoorbeeld current-requests de volgende dimensies:

Kenmerk Type Description Voorbeelden Aanwezigheid
method string HTTP-aanvraagmethode. GET; POST; HEAD Altijd
scheme string Het URI-schema waarmee het gebruikte protocol wordt geïdentificeerd. http; https Altijd
host string Naam van de lokale HTTP-server die de aanvraag heeft ontvangen. localhost Altijd
port int Poort van de lokale HTTP-server die de aanvraag heeft ontvangen. 8080 Toegevoegd indien niet standaard (80 voor http of 443 voor https)

De grafieken in Grafana worden meestal gepartitioneerd op basis van elke unieke combinatie van dimensies. De dimensies kunnen worden gebruikt in de Grafana-query's om de gegevens te filteren of aggregeren. Als u bijvoorbeeld graaft current_requests, ziet u waarden die zijn gepartitioneerd op basis van elke combinatie van dimensies. Als u alleen wilt filteren op basis van de host, voegt u een bewerking van Sum en gebruikt host u deze als labelwaarde.

Grafana current_requests per host

9. Gedistribueerde tracering met Jaeger

In stap 6 hebt u gezien dat gedistribueerde traceringsinformatie beschikbaar werd gesteld aan de console. Met deze informatie worden werkeenheden bijgehouden met activiteiten. Sommige activiteiten worden automatisch gemaakt door het platform, zoals de activiteiten van ASP.NET om de verwerking van een aanvraag aan te geven, en bibliotheken en app-code kunnen ook activiteiten maken. Het voorbeeld van begroetingen heeft een Greeter activiteit. De activiteiten worden gecorreleerd met behulp van de TraceId, SpanIden ParentId tags.

Elk proces in een gedistribueerd systeem produceert een eigen stroom activiteitsgegevens, en zoals metrische gegevens, hebt u een systeem nodig om de activiteiten te verzamelen, op te slaan en te correleren om het werk dat voor elke transactie is uitgevoerd te kunnen visualiseren. Jaeger is een opensource-project om deze verzameling en visualisatie in te schakelen.

Download het meest recente binaire distributiearchief van Jaeger voor uw platform van https://www.jaegertracing.io/download/.

Pak vervolgens de download uit naar een lokale locatie die gemakkelijk toegankelijk is. Voer het uitvoerbare bestand jaeger-all-in-one (.exe) uit:

./jaeger-all-in-one --collector.otlp.enabled

Bekijk de console-uitvoer om de poort te vinden waar wordt geluisterd naar OTLP-verkeer via gRPC. Voorbeeld:

{"level":"info","ts":1686963686.3854616,"caller":"otlpreceiver@v0.78.2/otlp.go:83","msg":"Starting GRPC server","endpoint":"0.0.0.0:4317"}

Deze uitvoer vertelt u dat deze luistert 0.0.0.0:4317, zodat u die poort kunt configureren als de bestemming voor uw OTLP-exporteur.

Open het AppSettings.json bestand voor ons project en voeg de volgende regel toe en wijzig indien van toepassing de poort.

"OTLP_ENDPOINT_URL" :  "http://localhost:4317/"

Start het begroetingsproces opnieuw, zodat deze de wijziging van de eigenschap kan ophalen en traceringsgegevens naar Jaeger kan leiden.

Nu moet u de Gebruikersinterface http://localhost:16686/ van Jaeger in een webbrowser kunnen zien.

Jaeger-query voor traceringen

Als u een lijst met traceringen wilt zien, selecteert u OTel-Prometheus-grafana-Jaeger in de vervolgkeuzelijst Service . Als u een trace selecteert, moet een Gantt-diagram van de activiteiten worden weergegeven als onderdeel van die trace. Als u op elk van de bewerkingen klikt, ziet u meer informatie over de activiteit.

Details van jaeger-bewerking

In een gedistribueerd systeem wilt u traceringen van alle processen verzenden naar dezelfde Jaeger-installatie, zodat deze de transacties in het systeem kan correleren.

U kunt uw app iets interessanter maken door deze HTTP-aanroepen naar zichzelf te laten uitvoeren.

  • Een HttpClient factory toevoegen aan de toepassing

    builder.Services.AddHttpClient();
    
  • Een nieuw eindpunt toevoegen voor het maken van geneste begroetingsgesprekken

    app.MapGet("/NestedGreeting", SendNestedGreeting);
    
  • Implementeer het eindpunt zodat er HTTP-aanroepen worden uitgevoerd die ook kunnen worden getraceerd. In dit geval roept het terug naar zichzelf in een kunstmatige lus (echt alleen van toepassing op demoscenario's).

    async Task SendNestedGreeting(int nestlevel, ILogger<Program> logger, HttpContext context, IHttpClientFactory clientFactory)
    {
        // Create a new Activity scoped to the method
        using var activity = greeterActivitySource.StartActivity("GreeterActivity");
    
        if (nestlevel <= 5)
        {
            // Log a message
            logger.LogInformation("Sending greeting, level {nestlevel}", nestlevel);
    
            // Increment the custom counter
            countGreetings.Add(1);
    
            // Add a tag to the Activity
            activity?.SetTag("nest-level", nestlevel);
    
            await context.Response.WriteAsync($"Nested Greeting, level: {nestlevel}\r\n");
    
            if (nestlevel > 0)
            {
                var request = context.Request;
                var url = new Uri($"{request.Scheme}://{request.Host}{request.Path}?nestlevel={nestlevel - 1}");
    
                // Makes an http call passing the activity information as http headers
                var nestedResult = await clientFactory.CreateClient().GetStringAsync(url);
                await context.Response.WriteAsync(nestedResult);
            }
        }
        else
        {
            // Log a message
            logger.LogError("Greeting nest level {nestlevel} too high", nestlevel);
            await context.Response.WriteAsync("Nest level too high, max is 5");
        }
    }
    

Dit resulteert in een interessantere grafiek met een piramidevorm voor de aanvragen, omdat elk niveau wacht op het antwoord van de vorige aanroep.

Geneste afhankelijkheidsresultaten van Jaeger