Ispezione dei dati di telemetria con la console
Anche se la console non è un modo consigliato per esaminare i dati di telemetria, è un modo semplice e rapido per iniziare. Questo articolo illustra come restituire i dati di telemetria nella console per l'ispezione con una configurazione minima del kernel.
Esportatore
Gli esportatori sono responsabili dell'invio di dati di telemetria a una destinazione. Altre informazioni sugli esportatori sono disponibili qui. In questo esempio viene usato l'utilità di esportazione della console per restituire i dati di telemetria nella console.
Prerequisiti
- Distribuzione del completamento della chat OpenAI di Azure.
- La versione più recente di .Net SDK per il sistema operativo.
- Distribuzione del completamento della chat OpenAI di Azure.
- Python 3.10, 3.11 o 3.12 installato nel computer.
Nota
L'osservabilità del kernel semantico non è ancora disponibile per Java.
Attrezzaggio
Creare un nuovo progetto di applicazione console
In un terminale eseguire il comando seguente per creare una nuova applicazione console in C#:
dotnet new console -n TelemetryConsoleQuickstart
Passare alla directory del progetto appena creata al termine del comando.
Installare i pacchetti necessari
Kernel semantico
dotnet add package Microsoft.SemanticKernel
Utilità di esportazione della console OpenTelemetry
dotnet add package OpenTelemetry.Exporter.Console
Creare una semplice applicazione con il kernel semantico
Dalla directory del progetto aprire il file con l'editor Program.cs
preferito. Verrà creata una semplice applicazione che usa il kernel semantico per inviare una richiesta a un modello di completamento della chat. Sostituire il contenuto esistente con il codice seguente e immettere i valori obbligatori per deploymentName
, endpoint
e 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);
}
}
}
Aggiungere dati di telemetria
Se si esegue l'app console ora, è consigliabile vedere una frase che spiega perché il cielo è blu. Per osservare il kernel tramite telemetria, sostituire il // Telemetry setup code goes here
commento con il codice seguente:
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);
});
Rimuovere infine il commento dalla riga per aggiungere la factory // builder.Services.AddSingleton(loggerFactory);
del logger al generatore.
Nel frammento di codice precedente viene prima creato un generatore di risorse per la compilazione di istanze di risorse. Una risorsa rappresenta l'entità che produce dati di telemetria. Altre informazioni sulle risorse sono disponibili qui. Il generatore di risorse per i provider è facoltativo. Se non specificato, viene usata la risorsa predefinita con attributi predefiniti.
Successivamente, si attiva la diagnostica con i dati sensibili. Si tratta di una funzionalità sperimentale che consente di abilitare la diagnostica per i servizi di intelligenza artificiale nel kernel semantico. Con questa opzione attivata, verranno visualizzati dati di telemetria aggiuntivi, ad esempio le richieste inviate a e le risposte ricevute dai modelli di intelligenza artificiale, considerati dati sensibili. Se non si vogliono includere dati sensibili nei dati di telemetria, è possibile usare un'altra opzione Microsoft.SemanticKernel.Experimental.GenAI.EnableOTelDiagnostics
per abilitare la diagnostica con dati non sensibili, ad esempio il nome del modello, il nome dell'operazione e l'utilizzo del token e così via.
Quindi creiamo un generatore di provider di traccia e un generatore di provider di contatori. Un provider è responsabile dell'elaborazione dei dati di telemetria e dell'invio di piping agli esportatori. Si sottoscrive l'origine Microsoft.SemanticKernel*
per ricevere i dati di telemetria dagli spazi dei nomi semantici del kernel. Aggiungiamo un utilità di esportazione della console sia al provider di traccia che al provider di contatori. L'utilità di esportazione della console invia i dati di telemetria alla console.
Infine, si crea una factory del logger e si aggiunge OpenTelemetry come provider di registrazione che invia i dati di log alla console. È stato impostato il livello minimo di log su Information
e sono inclusi i messaggi formattati e gli ambiti nell'output del log. La factory del logger viene quindi aggiunta al generatore.
Importante
Un provider deve essere un singleton e deve essere attivo per l'intera durata dell'applicazione. Il provider deve essere eliminato quando l'applicazione viene arrestata.
Creare un nuovo ambiente virtuale Python
python -m venv telemetry-console-quickstart
Attivare l'ambiente virtuale.
telemetry-console-quickstart\Scripts\activate
Installare i pacchetti necessari
pip install semantic-kernel
Creare uno script Python semplice con il kernel semantico
Creare un nuovo script Python e aprirlo con l'editor preferito.
New-Item -Path telemetry_console_quickstart.py -ItemType file
Verrà creato un semplice script Python che usa il kernel semantico per inviare una richiesta a un modello di completamento della chat. Sostituire il contenuto esistente con il codice seguente e immettere i valori obbligatori per deployment_name
, endpoint
e 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())
Aggiungere dati di telemetria
Variabili di ambiente
Per impostazione predefinita, il kernel non genera intervalli per i connettori di intelligenza artificiale, perché questi intervalli contengono gen_ai
attributi considerati sperimentali. Per abilitare la funzionalità, impostare la variabile SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS
di ambiente o SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS_SENSITIVE
su true
.
Importante
I prompt e i completamenti sono considerati dati sensibili. Il kernel semantico non genererà questi dati dai connettori di intelligenza artificiale a meno che la SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS_SENSITIVE
variabile di ambiente non sia impostata su true
. L'impostazione su SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS
true
genererà solo dati non sensibili, ad esempio il nome del modello, il nome dell'operazione e l'utilizzo del token.
Creare un nuovo file denominato .env
nella stessa directory dello script e aggiungere il contenuto seguente:
SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS_SENSITIVE=true
Codice
Se si esegue lo script ora, si dovrebbe aspettare di vedere una frase che spiega perché il cielo è blu. Per osservare il kernel tramite telemetria, sostituire il # Telemetry setup code goes here
commento con il codice seguente:
# 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()
Nel frammento di codice precedente viene prima creata una risorsa per rappresentare il servizio. Una risorsa rappresenta l'entità che produce dati di telemetria. Altre informazioni sulle risorse sono disponibili qui. Verranno quindi create tre funzioni per configurare la registrazione, la traccia e le metriche. Ogni funzione crea un provider per i rispettivi dati di telemetria e aggiunge un utilità di esportazione della console al provider.
Infine, vengono chiamate le tre funzioni per configurare la registrazione, la traccia e le metriche. Questa operazione deve essere eseguita prima di qualsiasi altra chiamata di telemetria.
Nota
L'osservabilità del kernel semantico non è ancora disponibile per Java.
Run
Eseguire l'applicazione console con il comando seguente:
dotnet run
Eseguire lo script Python con il comando seguente:
python telemetry_console_quickstart.py
Nota
L'osservabilità del kernel semantico non è ancora disponibile per Java.
Esaminare i dati di telemetria
Record di log
Nell'output della console dovrebbero essere visualizzati più record di log. Hanno un aspetto simile al seguente:
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
Esistono due parti per ogni record di log:
- Il record di log stesso: contiene il timestamp e lo spazio dei nomi in cui è stato generato il record di log, la gravità e il corpo del record di log e tutti gli attributi associati al record di log.
- La risorsa associata al record di log contiene informazioni sul servizio, sull'istanza e sull'SDK usati per generare il record di log.
Attività
Nota
Le attività in .Net sono simili agli intervalli in OpenTelemetry. Vengono usati per rappresentare un'unità di lavoro nell'applicazione.
Nell'output della console dovrebbero essere visualizzate più attività. Hanno un aspetto simile al seguente:
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
Esistono due parti per ogni attività:
- L'attività stessa: contiene l'ID intervallo e l'ID intervallo padre usati dagli strumenti di APM per compilare le tracce, la durata dell'attività ed eventuali tag ed eventi associati all'attività.
- La risorsa associata all'attività contiene informazioni sul servizio, sull'istanza e sull'SDK usati per generare l'attività.
Importante
Gli attributi da prestare particolare attenzione sono quelli che iniziano con gen_ai
. Questi sono gli attributi specificati nelle convenzioni semantiche GenAI.
Metrica
Nell'output della console dovrebbero essere visualizzati più record delle metriche. Hanno un aspetto simile al seguente:
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
Qui è possibile visualizzare il nome, la descrizione, l'unità, l'intervallo di tempo, il tipo, il valore della metrica e il contatore a cui appartiene la metrica.
Nota
La metrica precedente è una metrica Counter. Per un elenco completo dei tipi di metrica, vedere qui. A seconda del tipo di metrica, l'output può variare.
Registri
Nell'output della console dovrebbero essere visualizzati più record di log. Hanno un aspetto simile al seguente:
{
"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": ""
}
}
Intervalli
Nell'output della console dovrebbero essere visualizzati più intervalli. Hanno un aspetto simile al seguente:
{
"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": ""
}
}
Prestare attenzione agli attributi che iniziano con gen_ai
. Questi sono gli attributi specificati nelle convenzioni semantiche GenAI. Forniscono informazioni utili sulle richieste inviate a e sulle risposte ricevute dai modelli di intelligenza artificiale.
Metrica
Nell'output della console dovrebbero essere visualizzati più record delle metriche. Hanno un aspetto simile al seguente:
{
"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": ""
}
]
}
La misurazione illustrata in precedenza è una metrica istogramma. Per un elenco completo dei tipi di metrica, vedere qui.
Nota
L'osservabilità del kernel semantico non è ancora disponibile per Java.
Passaggi successivi
Dopo aver restituito correttamente i dati di telemetria nella console, è possibile ottenere altre informazioni su come usare gli strumenti APM per visualizzare e analizzare i dati di telemetria.