Condividi tramite


Usare OpenTelemetry con Funzioni di Azure

Importante

Il supporto di OpenTelemetry per Funzioni di Azure è attualmente in anteprima e l'app deve essere ospitata in un piano a consumo Flex per usare OpenTelemetry.

Questo articolo illustra come configurare l'app per le funzioni per esportare i dati di log e traccia in un formato OpenTelemetry. Funzioni di Azure genera dati di telemetria sulle esecuzioni delle funzioni sia dal processo host di Funzioni che dal processo di lavoro specifico del linguaggio in cui viene eseguito il codice della funzione. Per impostazione predefinita, questi dati di telemetria vengono inviati ad Application Insights usando Application Insights SDK. È tuttavia possibile scegliere di esportare questi dati usando la semantica OpenTelemetry. Anche se è ancora possibile usare un formato OpenTelemetry per inviare i dati ad Application Insights, è ora possibile esportare gli stessi dati in qualsiasi altro endpoint conforme a OpenTelemetry.

Suggerimento

Poiché questo articolo è destinato al linguaggio di sviluppo preferito, ricordarsi di scegliere il linguaggio corretto nella parte superiore dell'articolo.

Attualmente non è disponibile alcun supporto OpenTelemetry ottimizzato per i client per le app Java.

OpenTelemetry non è attualmente supportato per le app in-process C#.

È possibile ottenere questi vantaggi abilitando OpenTelemetry nell'app per le funzioni:

  • Correlazione tra tracce e log generati sia nell'host che nel codice dell'applicazione.
  • Generazione coerente basata su standard di dati di telemetria esportabili.
  • Si integra con altri provider che possono utilizzare dati conformi a OpenTeleletry.

OpenTelemetry è abilitato a livello di app per le funzioni, sia nella configurazione host (host.json) che nel progetto di codice. Funzioni offre anche un'esperienza ottimizzata per il client per l'esportazione dei dati OpenTelemetry dal codice della funzione in esecuzione in un processo di lavoro specifico del linguaggio.

1. Abilitare OpenTelemetry nell'host funzioni

Quando si abilita l'output OpenTelemetry nel file di host.json dell'app per le funzioni, l'host esporta l'output di OpenTelemetry indipendentemente dallo stack di linguaggio usato dall'app.

Per abilitare l'output openTelemetry dall'host di Funzioni, aggiornare il file di host.json nel progetto di codice per aggiungere un "telemetryMode": "openTelemetry" elemento alla raccolta radice. Con OpenTelemetry abilitato, il file di host.json potrebbe essere simile al seguente:

{
    "version": "2.0",
    "logging": {
        "applicationInsights": {
            "samplingSettings": {
                "isEnabled": true,
                "excludedTypes": "Request"
            },
            "enableLiveMetricsFilters": true
        }
    },
    "telemetryMode": "openTelemetry"
}

2. Configurare le impostazioni dell'applicazione

Quando OpenTelemetry è abilitato nel file host.json, gli endpoint a cui vengono inviati i dati vengono determinati in base alle impostazioni dell'applicazione supportate da OpenTelemetry sono disponibili nelle variabili di ambiente dell'app.

Creare impostazioni dell'applicazione specifiche nell'app per le funzioni in base alla destinazione di output OpenTelemetry. Quando vengono fornite le impostazioni di connessione sia per Application Insights che per un utilità di esportazione OTLP (OpenTelemetry Protocol), i dati OpenTelemetry vengono inviati a entrambi gli endpoint.

APPLICATIONINSIGHTS_CONNECTION_STRING: il stringa di connessione per un'area di lavoro di Application Insights. Quando questa impostazione esiste, i dati OpenTelemetry vengono inviati all'area di lavoro. Questa impostazione è la stessa usata per connettersi ad Application Insights senza OpenTelemetry abilitato. Se l'app non ha già questa impostazione, potrebbe essere necessario abilitare l'integrazione di Application Insights.

3. Abilitare OpenTelemetry nell'app

Con l'host di Funzioni configurato per l'uso di OpenTelemetry, è necessario aggiornare anche il codice dell'applicazione per l'output dei dati OpenTelemetry. L'abilitazione di OpenTelemetry sia nell'host che nel codice dell'applicazione consente una migliore correlazione tra tracce e log generati sia dal processo host di Funzioni che dal processo di lavoro del linguaggio.

Il modo in cui si instrumenta l'applicazione per usare OpenTelemetry dipende dall'endpoint OpenTelemetry di destinazione:

  1. Eseguire questi comandi per installare gli assembly necessari nell'app:

    dotnet add package Microsoft.Azure.Functions.Worker.OpenTelemetry --version 1.0.0-preview1 
    dotnet add package OpenTelemetry.Extensions.Hosting 
    dotnet add package Azure.Monitor.OpenTelemetry.AspNetCore  
    
  2. Nel file di progetto Program.cs aggiungere questa using istruzione:

    using Azure.Monitor.OpenTelemetry.AspNetCore; 
    
  3. Nel delegato aggiungere questa configurazione del ConfigureServices servizio:

    services.AddOpenTelemetry()
    .UseFunctionsWorkerDefaults()
    .UseAzureMonitor();
    

    Per esportare in entrambi gli endpoint OpenTelemetry, chiamare sia UseAzureMonitor che UseOtlpExporter.

Le ottimizzazioni del ruolo di lavoro Java non sono ancora disponibili per OpenTelemetry, quindi non è necessario configurare nel codice Java.

  1. Installare questi pacchetti npm nel progetto:

    npm install @opentelemetry/api 
    npm install @opentelemetry/auto-instrumentations-node 
    npm install @azure/monitor-opentelemetry-exporter 
    
  1. Creare un file di codice nel progetto, copiare e incollare il codice seguente in questo nuovo file e salvare il file come src/index.js:

    const { app } = require('@azure/functions');
    const { AzureMonitorLogExporter, AzureMonitorTraceExporter } = require('@azure/monitor-opentelemetry-exporter');
    const { context: otelContext, propagation } = require('@opentelemetry/api');
    const { SeverityNumber } = require('@opentelemetry/api-logs');
    const { getNodeAutoInstrumentations, getResourceDetectors } = require('@opentelemetry/auto-instrumentations-node');
    const { registerInstrumentations } = require('@opentelemetry/instrumentation');
    const { detectResourcesSync } = require('@opentelemetry/resources');
    const { LoggerProvider, SimpleLogRecordProcessor } = require('@opentelemetry/sdk-logs');
    const { NodeTracerProvider, SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-node');
    
    const resource = detectResourcesSync({ detectors: getResourceDetectors() });
    
    const tracerProvider = new NodeTracerProvider({ resource });
    tracerProvider.addSpanProcessor(new SimpleSpanProcessor(new AzureMonitorTraceExporter()));
    tracerProvider.register();
    
    const loggerProvider = new LoggerProvider({ resource });
    loggerProvider.addLogRecordProcessor(new SimpleLogRecordProcessor(new AzureMonitorLogExporter()));
    
    registerInstrumentations({ tracerProvider, loggerProvider, instrumentations: [getNodeAutoInstrumentations()] });
    
    // NOTE: The below code will soon be a part of a new package `@opentelemetry/instrumentation-azure-functions`
    // See here for more info: https://github.com/Azure/azure-functions-nodejs-library/issues/245
    app.setup({ capabilities: { WorkerOpenTelemetryEnabled: true } });
    
    const logger = loggerProvider.getLogger('default');
    app.hook.log((context) => {
        logger.emit({
            body: context.message,
            severityNumber: toOtelSeverityNumber(context.level),
            severityText: context.level,
        });
    });
    
    app.hook.preInvocation((context) => {
        context.functionHandler = otelContext.bind(
            propagation.extract(otelContext.active(), {
                traceparent: context.invocationContext.traceContext.traceParent,
                tracestate: context.invocationContext.traceContext.traceState,
            }),
            context.functionHandler
        );
    });
    
    function toOtelSeverityNumber(level) {
        switch (level) {
            case 'information':
                return SeverityNumber.INFO;
            case 'debug':
                return SeverityNumber.DEBUG;
            case 'error':
                return SeverityNumber.ERROR;
            case 'trace':
                return SeverityNumber.TRACE;
            case 'warning':
                return SeverityNumber.WARN;
            case 'critical':
                return SeverityNumber.FATAL;
            default:
                return SeverityNumber.UNSPECIFIED;
        }
    }
    
  2. Aggiornare il main campo nel file package.json in modo da includere questo nuovo src/index.js file, che potrebbe essere simile al seguente:

    "main": "src/{index.js,functions/*.js}"
    
  1. Creare un file di codice nel progetto, copiare e incollare il codice seguente in questo nuovo file e salvare il file come src/index.ts:

    import { app, LogLevel } from '@azure/functions';
    import { AzureMonitorLogExporter, AzureMonitorTraceExporter } from '@azure/monitor-opentelemetry-exporter';
    import { context as otelContext, propagation } from '@opentelemetry/api';
    import { SeverityNumber } from '@opentelemetry/api-logs';
    import { getNodeAutoInstrumentations, getResourceDetectors } from '@opentelemetry/auto-instrumentations-node';
    import { registerInstrumentations } from '@opentelemetry/instrumentation';
    import { detectResourcesSync } from '@opentelemetry/resources';
    import { LoggerProvider, SimpleLogRecordProcessor } from '@opentelemetry/sdk-logs';
    import { NodeTracerProvider, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node';
    
    const resource = detectResourcesSync({ detectors: getResourceDetectors() });
    
    const tracerProvider = new NodeTracerProvider({ resource });
    tracerProvider.addSpanProcessor(new SimpleSpanProcessor(new AzureMonitorTraceExporter()));
    tracerProvider.register();
    
    const loggerProvider = new LoggerProvider({ resource });
    loggerProvider.addLogRecordProcessor(new SimpleLogRecordProcessor(new AzureMonitorLogExporter()));
    
    registerInstrumentations({ tracerProvider, loggerProvider, instrumentations: [getNodeAutoInstrumentations()] });
    
    // NOTE: The below code will soon be a part of a new package `@opentelemetry/instrumentation-azure-functions`
    // See here for more info: https://github.com/Azure/azure-functions-nodejs-library/issues/245
    app.setup({ capabilities: { WorkerOpenTelemetryEnabled: true } });
    
    const logger = loggerProvider.getLogger('default');
    app.hook.log((context) => {
        logger.emit({
            body: context.message,
            severityNumber: toOtelSeverityNumber(context.level),
            severityText: context.level,
        });
    });
    
    app.hook.preInvocation((context) => {
        context.functionHandler = otelContext.bind(
            propagation.extract(otelContext.active(), {
                traceparent: context.invocationContext.traceContext.traceParent,
                tracestate: context.invocationContext.traceContext.traceState,
            }),
            context.functionHandler
        );
    });
    
    function toOtelSeverityNumber(level: LogLevel): SeverityNumber {
        switch (level) {
            case 'information':
                return SeverityNumber.INFO;
            case 'debug':
                return SeverityNumber.DEBUG;
            case 'error':
                return SeverityNumber.ERROR;
            case 'trace':
                return SeverityNumber.TRACE;
            case 'warning':
                return SeverityNumber.WARN;
            case 'critical':
                return SeverityNumber.FATAL;
            default:
                return SeverityNumber.UNSPECIFIED;
        }
    }
    
  2. Aggiornare il main campo nel file package.json in modo da includere l'output del nuovo src/index.ts file, che potrebbe essere simile al seguente:

    "main": "dist/src/{index.js,functions/*.js}"
    

Importante

L'output di OpenTelemetry in Application Insights dal ruolo di lavoro per la lingua non è attualmente supportato per le app di PowerShell. È invece possibile usare un endpoint di esportazione OTLP. Quando l'host è configurato per l'output OpenTelemetry in Application Insights, i log generati dal processo di lavoro di PowerShell vengono comunque inoltrati, ma la traccia distribuita non è attualmente supportata.

Queste istruzioni si applicano solo per un esportatore OTLP:

  1. Aggiungere un'impostazione dell'applicazione denominata OTEL_FUNCTIONS_WORKER_ENABLED con il valore .True

  2. Creare una cartella a livello Modules di app nella radice dell'app ed eseguire il comando seguente:

    Save-Module -Name AzureFunctions.PowerShell.OpenTelemetry.SDK
    

    In questo modo il modulo richiesto AzureFunctions.PowerShell.OpenTelemetry.SDK viene installato direttamente nell'app. Non è possibile usare il requirements.psd1 file per installare automaticamente questa dipendenza perché le dipendenze gestite non sono attualmente supportate nell'anteprima del piano a consumo Flex.

  3. Aggiungere questo codice al file profile.ps1:

    Import-Module AzureFunctions.PowerShell.OpenTelemetry.SDK -Force -ErrorAction Stop 
    Initialize-FunctionsOpenTelemetry 
    
  1. Aggiungere questa voce nel requirements.txt file:

    azure.monitor.opentelemetry
    
  2. Aggiungere questo codice al file del function_app.py punto di ingresso principale:

    from azure.monitor.opentelemetry import configure_azure_monitor 
    configure_azure_monitor() 
    

Considerazioni su OpenTelemetry

Quando si esportano i dati usando OpenTelemetry, tenere presenti queste considerazioni correnti.

  • Quando l'host è configurato per l'uso di OpenTelemetry, vengono esportati solo i log e le tracce. Le metriche host non sono attualmente esportate.

  • Non è attualmente possibile eseguire il progetto dell'app in locale usando Core Tools quando OpenTelemetry è abilitato nell'host. È attualmente necessario distribuire il codice in Azure per convalidare gli aggiornamenti correlati a OpenTelemetry.

  • Al momento, solo i trigger HTTP e i trigger basati su Azure SDK sono supportati con gli output OpenTelemetry.

Monitorare il piano a consumo Funzioni di Azure Flex