Dela via


Kontroll av telemetridata med konsolen

Även om konsolen inte är ett rekommenderat sätt att inspektera telemetridata är det ett enkelt och snabbt sätt att komma igång. Den här artikeln visar hur du matar ut telemetridata till konsolen för inspektion med minimal kernelkonfiguration.

Exportör

Exportörer ansvarar för att skicka telemetridata till ett mål. Läs mer om exportörer här. I det här exemplet använder vi konsolexportören för att mata ut telemetridata till konsolen.

Förutsättningar

  • En distribution av Azure OpenAI-chatten.
  • Den senaste .Net SDK för operativsystemet.

Kommentar

Semantisk kernelobservabilitet är ännu inte tillgängligt för Java.

Ställ in

Skapa ett nytt konsolprogram

I en terminal kör du följande kommando för att skapa ett nytt konsolprogram i C#:

dotnet new console -n TelemetryConsoleQuickstart

Navigera till den nyligen skapade projektkatalogen när kommandot har slutförts.

Installera de paket som krävs

  • Semantic Kernel

    dotnet add package Microsoft.SemanticKernel
    
  • OpenTelemetry Console Exporter

    dotnet add package OpenTelemetry.Exporter.Console
    

Skapa ett enkelt program med semantisk kernel

Öppna filen med din favoritredigerare från projektkatalogen Program.cs . Vi ska skapa ett enkelt program som använder semantisk kernel för att skicka en uppmaning till en modell för chattens slutförande. Ersätt det befintliga innehållet med följande kod och fyll i de nödvändiga värdena för deploymentName, endpointoch apiKey:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.SemanticKernel;
using OpenTelemetry;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

namespace TelemetryConsoleQuickstart
{
    class Program
    {
        static async Task Main(string[] args)
        {
            // Telemetry setup code goes here

            IKernelBuilder builder = Kernel.CreateBuilder();
            // builder.Services.AddSingleton(loggerFactory);
            builder.AddAzureOpenAIChatCompletion(
                deploymentName: "your-deployment-name",
                endpoint: "your-azure-openai-endpoint",
                apiKey: "your-azure-openai-api-key"
            );

            Kernel kernel = builder.Build();

            var answer = await kernel.InvokePromptAsync(
                "Why is the sky blue in one sentence?"
            );

            Console.WriteLine(answer);
        }
    }
}

Lägg till telemetri

Om du kör konsolappen nu bör du förvänta dig att se en mening som förklarar varför himlen är blå. Om du vill observera kerneln via telemetri ersätter du kommentaren // Telemetry setup code goes here med följande kod:

var resourceBuilder = ResourceBuilder
    .CreateDefault()
    .AddService("TelemetryConsoleQuickstart");

// Enable model diagnostics with sensitive data.
AppContext.SetSwitch("Microsoft.SemanticKernel.Experimental.GenAI.EnableOTelDiagnosticsSensitive", true);

using var traceProvider = Sdk.CreateTracerProviderBuilder()
    .SetResourceBuilder(resourceBuilder)
    .AddSource("Microsoft.SemanticKernel*")
    .AddConsoleExporter()
    .Build();

using var meterProvider = Sdk.CreateMeterProviderBuilder()
    .SetResourceBuilder(resourceBuilder)
    .AddMeter("Microsoft.SemanticKernel*")
    .AddConsoleExporter()
    .Build();

using var loggerFactory = LoggerFactory.Create(builder =>
{
    // Add OpenTelemetry as a logging provider
    builder.AddOpenTelemetry(options =>
    {
        options.SetResourceBuilder(resourceBuilder);
        options.AddConsoleExporter();
        // Format log messages. This is default to false.
        options.IncludeFormattedMessage = true;
        options.IncludeScopes = true;
    });
    builder.SetMinimumLevel(LogLevel.Information);
});

Ta slutligen bort kommentaren till raden // builder.Services.AddSingleton(loggerFactory); för att lägga till loggerfabriken i byggverktyget.

I kodfragmentet ovan skapar vi först en resursbyggare för att skapa resursinstanser. En resurs representerar entiteten som producerar telemetridata. Du kan läsa mer om resurser här. Resursverktyget till leverantörerna är valfritt. Om den inte anges används standardresursen med standardattribut.

Därefter aktiverar vi diagnostik med känsliga data. Det här är en experimentell funktion som gör att du kan aktivera diagnostik för AI-tjänsterna i semantisk kernel. När detta är aktiverat ser du ytterligare telemetridata, till exempel de uppmaningar som skickas till och de svar som tas emot från AI-modellerna, som betraktas som känsliga data. Om du inte vill inkludera känsliga data i telemetrin kan du använda en annan växel Microsoft.SemanticKernel.Experimental.GenAI.EnableOTelDiagnostics för att aktivera diagnostik med icke-känsliga data, till exempel modellnamnet, åtgärdsnamnet och tokenanvändningen osv.

Sedan skapar vi en tracer provider builder och en mätare provider builder. En leverantör ansvarar för att bearbeta telemetridata och skicka dem till exportörer. Vi prenumererar på Microsoft.SemanticKernel* källan för att ta emot telemetridata från semantiska kernelnamnområden. Vi lägger till en konsolexportör till både spårningsprovidern och mätarprovidern. Konsolexportören skickar telemetridata till konsolen.

Slutligen skapar vi en loggerfabrik och lägger till OpenTelemetry som en loggningsprovider som skickar loggdata till konsolen. Vi anger den lägsta loggnivån till Information och inkluderar formaterade meddelanden och omfång i loggutdata. Loggerfabriken läggs sedan till i byggaren.

Viktigt!

En provider ska vara en singleton och bör vara aktiv under hela programlivslängden. Providern ska tas bort när programmet stängs av.

Skapa en ny virtuell Python-miljö

python -m venv telemetry-console-quickstart

Aktivera den virtuella miljön.

telemetry-console-quickstart\Scripts\activate

Installera de paket som krävs

pip install semantic-kernel

Skapa ett enkelt Python-skript med semantisk kernel

Skapa ett nytt Python-skript och öppna det med din favoritredigerare.

New-Item -Path telemetry_console_quickstart.py -ItemType file

Vi ska skapa ett enkelt Python-skript som använder semantisk kernel för att skicka en uppmaning till en modell för chattens slutförande. Ersätt det befintliga innehållet med följande kod och fyll i de nödvändiga värdena för deployment_name, endpointoch api_key:

import asyncio
import logging

from opentelemetry._logs import set_logger_provider
from opentelemetry.metrics import set_meter_provider
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor, ConsoleLogExporter
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import ConsoleMetricExporter, PeriodicExportingMetricReader
from opentelemetry.sdk.metrics.view import DropAggregation, View
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
from opentelemetry.semconv.resource import ResourceAttributes
from opentelemetry.trace import set_tracer_provider

from semantic_kernel import Kernel
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion


# Telemetry setup code goes here

async def main():
    # Create a kernel and add a service
    kernel = Kernel()
    kernel.add_service(AzureChatCompletion(
        api_key="your-azure-openai-api-key",
        endpoint="your-azure-openai-endpoint",
        deployment_name="your-deployment-name"
    ))

    answer = await kernel.invoke_prompt("Why is the sky blue in one sentence?")
    print(answer)


if __name__ == "__main__":
    asyncio.run(main())

Lägg till telemetri

Miljövariabler

Som standard genererar kerneln inte intervall för AI-anslutningsappar, eftersom dessa intervall har gen_ai attribut som anses vara experimentella. Om du vill aktivera funktionen anger du miljövariabeln SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS eller SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS_SENSITIVE till true.

Viktigt!

Frågor och slutföranden betraktas som känsliga data. Semantisk kernel genererar inte dessa data från AI-anslutningsapparna om inte SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS_SENSITIVE miljövariabeln är inställd på true. Inställningen SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS till true genererar endast icke-känsliga data, till exempel modellnamnet, åtgärdsnamnet och tokenanvändningen.

Skapa en ny fil med namnet .env i samma katalog som skriptet och lägg till följande innehåll:

SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS_SENSITIVE=true

Kod

Om du kör skriptet nu bör du förvänta dig att se en mening som förklarar varför himlen är blå. Om du vill observera kerneln via telemetri ersätter du kommentaren # Telemetry setup code goes here med följande kod:

# Create a resource to represent the service/sample
resource = Resource.create({ResourceAttributes.SERVICE_NAME: "telemetry-console-quickstart"})


def set_up_logging():
    exporter = ConsoleLogExporter()

    # Create and set a global logger provider for the application.
    logger_provider = LoggerProvider(resource=resource)
    # Log processors are initialized with an exporter which is responsible
    # for sending the telemetry data to a particular backend.
    logger_provider.add_log_record_processor(BatchLogRecordProcessor(exporter))
    # Sets the global default logger provider
    set_logger_provider(logger_provider)

    # Create a logging handler to write logging records, in OTLP format, to the exporter.
    handler = LoggingHandler()
    # Add filters to the handler to only process records from semantic_kernel.
    handler.addFilter(logging.Filter("semantic_kernel"))
    # Attach the handler to the root logger. `getLogger()` with no arguments returns the root logger.
    # Events from all child loggers will be processed by this handler.
    logger = logging.getLogger()
    logger.addHandler(handler)
    logger.setLevel(logging.INFO)


def set_up_tracing():
    exporter = ConsoleSpanExporter()

    # Initialize a trace provider for the application. This is a factory for creating tracers.
    tracer_provider = TracerProvider(resource=resource)
    # Span processors are initialized with an exporter which is responsible
    # for sending the telemetry data to a particular backend.
    tracer_provider.add_span_processor(BatchSpanProcessor(exporter))
    # Sets the global default tracer provider
    set_tracer_provider(tracer_provider)


def set_up_metrics():
    exporter = ConsoleMetricExporter()

    # Initialize a metric provider for the application. This is a factory for creating meters.
    meter_provider = MeterProvider(
        metric_readers=[PeriodicExportingMetricReader(exporter, export_interval_millis=5000)],
        resource=resource,
        views=[
            # Dropping all instrument names except for those starting with "semantic_kernel"
            View(instrument_name="*", aggregation=DropAggregation()),
            View(instrument_name="semantic_kernel*"),
        ],
    )
    # Sets the global default meter provider
    set_meter_provider(meter_provider)


# This must be done before any other telemetry calls
set_up_logging()
set_up_tracing()
set_up_metrics()

I kodfragmentet ovan skapar vi först en resurs som representerar tjänsten. En resurs representerar entiteten som producerar telemetridata. Du kan läsa mer om resurser här. Sedan skapar vi tre funktioner för att konfigurera loggning, spårning och mått. Varje funktion skapar en provider för respektive telemetridata och lägger till en konsolexportör till providern.

Slutligen anropar vi de tre funktionerna för att konfigurera loggning, spårning och mått. Detta måste göras innan andra telemetrianrop.

Kommentar

Semantisk kernelobservabilitet är ännu inte tillgängligt för Java.

Kör

Kör konsolprogrammet med följande kommando:

dotnet run

Kör Python-skriptet med följande kommando:

python telemetry_console_quickstart.py

Kommentar

Semantisk kernelobservabilitet är ännu inte tillgängligt för Java.

Granska telemetridata

Loggposter

Du bör se flera loggposter i konsolens utdata. De ser ut ungefär så här:

LogRecord.Timestamp:               2024-09-12T21:48:35.2295938Z
LogRecord.TraceId:                 159d3f07664838f6abdad7af6a892cfa
LogRecord.SpanId:                  ac79a006da8a6215
LogRecord.TraceFlags:              Recorded
LogRecord.CategoryName:            Microsoft.SemanticKernel.KernelFunction
LogRecord.Severity:                Info
LogRecord.SeverityText:            Information
LogRecord.FormattedMessage:        Function InvokePromptAsync_290eb9bece084b00aea46b569174feae invoking.
LogRecord.Body:                    Function {FunctionName} invoking.
LogRecord.Attributes (Key:Value):
    FunctionName: InvokePromptAsync_290eb9bece084b00aea46b569174feae
    OriginalFormat (a.k.a Body): Function {FunctionName} invoking.

Resource associated with LogRecord:
service.name: TelemetryConsoleQuickstart
service.instance.id: a637dfc9-0e83-4435-9534-fb89902e64f8
telemetry.sdk.name: opentelemetry
telemetry.sdk.language: dotnet
telemetry.sdk.version: 1.9.0

Det finns två delar i varje loggpost:

  • Själva loggposten: innehåller tidsstämpeln och namnområdet där loggposten genererades, loggpostens allvarlighetsgrad och brödtext samt eventuella attribut som är associerade med loggposten.
  • Resursen som är associerad med loggposten: innehåller information om tjänsten, instansen och SDK:t som används för att generera loggposten.

Aktiviteter

Kommentar

Aktiviteter i .Net liknar intervall i OpenTelemetry. De används för att representera en arbetsenhet i programmet.

Du bör se flera aktiviteter i konsolens utdata. De ser ut ungefär så här:

Activity.TraceId:            159d3f07664838f6abdad7af6a892cfa
Activity.SpanId:             8c7c79bc1036eab3
Activity.TraceFlags:         Recorded
Activity.ParentSpanId:       ac79a006da8a6215
Activity.ActivitySourceName: Microsoft.SemanticKernel.Diagnostics
Activity.DisplayName:        chat.completions gpt-4o
Activity.Kind:               Client
Activity.StartTime:          2024-09-12T21:48:35.5717463Z
Activity.Duration:           00:00:02.3992014
Activity.Tags:
    gen_ai.operation.name: chat.completions
    gen_ai.system: openai
    gen_ai.request.model: gpt-4o
    gen_ai.response.prompt_tokens: 16
    gen_ai.response.completion_tokens: 29
    gen_ai.response.finish_reason: Stop
    gen_ai.response.id: chatcmpl-A6lxz14rKuQpQibmiCpzmye6z9rxC
Activity.Events:
    gen_ai.content.prompt [9/12/2024 9:48:35 PM +00:00]
        gen_ai.prompt: [{"role": "user", "content": "Why is the sky blue in one sentence?"}]
    gen_ai.content.completion [9/12/2024 9:48:37 PM +00:00]
        gen_ai.completion: [{"role": "Assistant", "content": "The sky appears blue because shorter blue wavelengths of sunlight are scattered in all directions by the gases and particles in the Earth\u0027s atmosphere more than other colors."}]
Resource associated with Activity:
    service.name: TelemetryConsoleQuickstart
    service.instance.id: a637dfc9-0e83-4435-9534-fb89902e64f8
    telemetry.sdk.name: opentelemetry
    telemetry.sdk.language: dotnet
    telemetry.sdk.version: 1.9.0

Det finns två delar i varje aktivitet:

  • Själva aktiviteten: innehåller span-ID och överordnat span-ID som APM-verktyg använder för att skapa spårningarna, aktivitetens varaktighet och eventuella taggar och händelser som är associerade med aktiviteten.
  • Resursen som är associerad med aktiviteten: innehåller information om tjänsten, instansen och SDK:t som används för att generera aktiviteten.

Viktigt!

Attributen som ska vara extra uppmärksamma på är de som börjar med gen_ai. Det här är attributen som anges i GenAI-semantiska konventioner.

Mått

Du bör se flera måttposter i konsolens utdata. De ser ut ungefär så här:

Metric Name: semantic_kernel.connectors.openai.tokens.prompt, Number of prompt tokens used, Unit: {token}, Meter: Microsoft.SemanticKernel.Connectors.OpenAI
(2024-09-12T21:48:37.9531072Z, 2024-09-12T21:48:38.0966737Z] LongSum
Value: 16

Här kan du se namnet, beskrivningen, enheten, tidsintervallet, typen, värdet för måttet och mätaren som måttet tillhör.

Kommentar

Ovanstående mått är ett räknarmått. En fullständig lista över måtttyper finns här. Beroende på typen av mått kan utdata variera.

Loggar

Du bör se flera loggposter i konsolens utdata. De ser ut ungefär så här:

{
    "body": "Function SyVCcBjaULqEhItH invoking.",
    "severity_number": "<SeverityNumber.INFO: 9>",
    "severity_text": "INFO",
    "attributes": {
        "code.filepath": "C:\\tmp\\telemetry-console-quickstart\\Lib\\site-packages\\semantic_kernel\\functions\\kernel_function_log_messages.py",
        "code.function": "log_function_invoking",
        "code.lineno": 19
    },
    "dropped_attributes": 0,
    "timestamp": "2024-09-13T17:55:45.504983Z",
    "observed_timestamp": "2024-09-13T17:55:45.504983Z",
    "trace_id": "0xe23e2c10785ea61ffc9f28be19482a80",
    "span_id": "0x686bd592e27661d7",
    "trace_flags": 1,
    "resource": {
        "attributes": {
            "telemetry.sdk.language": "python",
            "telemetry.sdk.name": "opentelemetry",
            "telemetry.sdk.version": "1.27.0",
            "service.name": "telemetry-console-quickstart"
        },
        "schema_url": ""
    }
}

Spänner över

Du bör se flera intervall i konsolens utdata. De ser ut ungefär så här:

{
    "name": "chat.completions gpt-4o",
    "context": {
        "trace_id": "0xe23e2c10785ea61ffc9f28be19482a80",
        "span_id": "0x8b20e9655610c3c9",
        "trace_state": "[]"
    },
    "kind": "SpanKind.INTERNAL",
    "parent_id": "0x686bd592e27661d7",
    "start_time": "2024-09-13T17:55:45.515198Z",
    "end_time": "2024-09-13T17:55:46.469471Z",
    "status": {
        "status_code": "UNSET"
    },
    "attributes": {
        "gen_ai.operation.name": "chat.completions",
        "gen_ai.system": "openai",
        "gen_ai.request.model": "gpt-4o",
        "gen_ai.response.id": "chatcmpl-A74oD7WGDjawnZ44SJZrj9fKrEv1B",
        "gen_ai.response.finish_reason": "FinishReason.STOP",
        "gen_ai.response.prompt_tokens": 16,
        "gen_ai.response.completion_tokens": 29
    },
    "events": [
        {
            "name": "gen_ai.content.prompt",
            "timestamp": "2024-09-13T17:55:45.515198Z",
            "attributes": {
                "gen_ai.prompt": "[{\"role\": \"user\", \"content\": \"Why is the sky blue in one sentence?\"}]"
            }
        },
        {
            "name": "gen_ai.content.completion",
            "timestamp": "2024-09-13T17:55:46.469471Z",
            "attributes": {
                "gen_ai.completion": "[{\"role\": \"assistant\", \"content\": \"The sky appears blue because shorter blue wavelengths of sunlight are scattered in all directions by the molecules and particles in the atmosphere more effectively than other colors.\"}]"
            }
        }
    ],
    "links": [],
    "resource": {
        "attributes": {
            "telemetry.sdk.language": "python",
            "telemetry.sdk.name": "opentelemetry",
            "telemetry.sdk.version": "1.27.0",
            "service.name": "telemetry-console-quickstart"
        },
        "schema_url": ""
    }
}

Var uppmärksam på attributen som börjar med gen_ai. Det här är attributen som anges i GenAI-semantiska konventioner. De ger användbar information om de begäranden som skickas till och de svar som tas emot från AI-modellerna.

Mått

Du bör se flera måttposter i konsolens utdata. De ser ut ungefär så här:

{
    "resource_metrics": [
        {
            "resource": {
                "attributes": {
                    "telemetry.sdk.language": "python",
                    "telemetry.sdk.name": "opentelemetry",
                    "telemetry.sdk.version": "1.27.0",
                    "service.name": "telemetry-console-quickstart"
                },
                "schema_url": ""
            },
            "scope_metrics": [
                {
                    "scope": {
                        "name": "semantic_kernel.functions.kernel_function",
                        "version": null,
                        "schema_url": "",
                        "attributes": null
                    },
                    "metrics": [
                        {
                            "name": "semantic_kernel.function.invocation.duration",
                            "description": "Measures the duration of a function's execution",
                            "unit": "s",
                            "data": {
                                "data_points": [
                                    {
                                        "attributes": {
                                            "semantic_kernel.function.name": "SyVCcBjaULqEhItH"
                                        },
                                        "start_time_unix_nano": 1726250146470468300,
                                        "time_unix_nano": 1726250146478526600,
                                        "count": 1,
                                        "sum": 0.9650602999900002,
                                        "bucket_counts": [
                                            0,
                                            1,
                                            0,
                                            0,
                                            0,
                                            0,
                                            0,
                                            0,
                                            0,
                                            0,
                                            0,
                                            0,
                                            0,
                                            0,
                                            0,
                                            0
                                        ],
                                        "explicit_bounds": [
                                            0.0,
                                            5.0,
                                            10.0,
                                            25.0,
                                            50.0,
                                            75.0,
                                            100.0,
                                            250.0,
                                            500.0,
                                            750.0,
                                            1000.0,
                                            2500.0,
                                            5000.0,
                                            7500.0,
                                            10000.0
                                        ],
                                        "min": 0.9650602999900002,
                                        "max": 0.9650602999900002
                                    }
                                ],
                                "aggregation_temporality": 2
                            }
                        }
                    ],
                    "schema_url": ""
                }
            ],
            "schema_url": ""
        }
    ]
}

Mätningen som visas ovan är ett histogrammått. En fullständig lista över måtttyper finns här.

Kommentar

Semantisk kernelobservabilitet är ännu inte tillgängligt för Java.

Nästa steg

Nu när du har matat ut telemetridata till konsolen kan du lära dig mer om hur du använder APM-verktyg för att visualisera och analysera telemetridata.