Compartilhar via


Usar o OpenTelemetry com o Azure Functions

Importante

O suporte do OpenTelemetry para o Azure Functions está atualmente em versão prévia e o seu aplicativo deve estar hospedado em um plano de Consumo Flex para usar o OpenTelemetry.

Este artigo mostra como configurar o seu aplicativo de funções para exportar dados de log e rastreamento em um formato OpenTelemetry. O Azure Functions gera dados de telemetria em suas execuções de função do processo de host do Functions e do processo de trabalho específico do idioma no qual o código de função é executado. Por padrão, esses dados de telemetria são enviados ao Application Insights usando o SDK do Application Insights. No entanto, você pode optar por exportar esses dados usando a semântica do OpenTelemetry. Embora você ainda possa usar um formato OpenTelemetry para enviar seus dados para o Application Insights, agora você também pode exportar os mesmos dados para qualquer outro ponto de extremidade compatível com OpenTelemetry.

Dica

Como este artigo é direcionado à linguagem de desenvolvimento escolhida, lembre-se de escolher o idioma correto na parte superior do artigo.

Atualmente, não há suporte do OpenTelemetry otimizado para cliente para aplicativos Java.

Atualmente, o OpenTelemetry não tem suporte para aplicativos em processo em C#.

Você pode obter esses benefícios habilitando o OpenTelemetry em seu aplicativo de funções:

  • Correlação entre rastreamentos e logs que estão sendo gerados no host e no código do aplicativo.
  • Geração consistente baseada em padrões de dados de telemetria exportáveis.
  • Integra-se a outros provedores que podem consumir dados compatíveis com OpenTeleletry.

O OpenTelemetry está habilitado no nível do aplicativo de funções, tanto na configuração do host (host.json) quanto no projeto de código. O Functions também fornece uma experiência otimizada para o cliente para exportar dados do OpenTelemetry do seu código de função em execução em um processo de trabalho específico do idioma.

1. Habilitar o OpenTelemetry no host do Functions

Quando você habilita a saída do OpenTelemetry no arquivo host.json do aplicativo de funções, o host exporta a saída do OpenTelemetry independentemente da pilha de idiomas usada pelo aplicativo.

Para habilitar a saída OpenTelemetry do host do Functions, atualize o arquivo host.json em seu projeto de código para adicionar um elemento "telemetryMode": "openTelemetry" à coleção raiz. Com o OpenTelemetry habilitado, o seu arquivo host.json pode ter esta aparência:

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

2. Definir as configurações do aplicativo

Quando o OpenTelemetry está habilitado no arquivo host.json, os pontos de extremidade para os quais os dados são enviados são determinados com base em quais configurações de aplicativo com suporte do OpenTelemetry estão disponíveis nas variáveis de ambiente do seu aplicativo.

Crie configurações de aplicativo específicas em seu aplicativo de funções com base no destino de saída do OpenTelemetry. Quando as configurações de conexão são fornecidas para o Application Insights e um exportador do protocolo OpenTelemetry (OTLP), os dados do OpenTelemetry são enviados para ambos os pontos de extremidade.

APPLICATIONINSIGHTS_CONNECTION_STRING: a cadeia de conexão de um workspace do Application Insights. Quando esta configuração existe, os dados do OpenTelemetry são enviados para o workspace. Esta configuração é a mesma usada para se conectar ao Application Insights sem o OpenTelemetry habilitado. Se o aplicativo ainda não tiver essa configuração, talvez seja necessário Habilitar a integração do Application Insights.

3. Habilitar o OpenTelemetry em seu aplicativo

Com o host do Functions configurado para usar o OpenTelemetry, você também deve atualizar o código do aplicativo para gerar dados do OpenTelemetry. Habilitar o OpenTelemetry no host e no código do aplicativo permite uma melhor correlação entre rastreamentos e logs emitidos tanto pelo processo de host do Functions quanto pelo processo de trabalho do idioma.

A maneira como você instrumenta o seu aplicativo para usar o OpenTelemetry depende do ponto de extremidade do OpenTelemetry de destino:

  1. Execute estes comandos para instalar os assemblies necessários em seu aplicativo:

    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. No arquivo de projeto Program.cs, adicione esta instrução using:

    using Azure.Monitor.OpenTelemetry.AspNetCore; 
    
  3. No delegado ConfigureServices, adicione esta configuração de serviço:

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

    Para exportar para os pontos de extremidade OpenTelemetry, chame UseAzureMonitor e UseOtlpExporter.

As otimizações de trabalho do Java ainda não estão disponíveis para o OpenTelemetry, portanto, não há nada a ser configurado no código Java.

  1. Instale estes pacotes npm em seu projeto:

    npm install @opentelemetry/api 
    npm install @opentelemetry/auto-instrumentations-node 
    npm install @azure/monitor-opentelemetry-exporter 
    
  1. Crie um arquivo de código em seu projeto, copie e cole o seguinte código neste novo arquivo e salve o arquivo como 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. Atualize o campo main em seu arquivo package.json para incluir este novo arquivo src/index.js, que pode ter esta aparência:

    "main": "src/{index.js,functions/*.js}"
    
  1. Crie um arquivo de código em seu projeto, copie e cole o seguinte código neste novo arquivo e salve o arquivo como 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. Atualize o campo main em seu arquivo package.json para incluir a saída deste novo arquivo src/index.ts, que pode ter esta aparência:

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

Importante

A saída do OpenTelemetry para o Application Insights da função de trabalho de idioma não tem suporte atualmente para aplicativos do PowerShell. Em vez disso, você pode querer usar um ponto de extremidade do exportador OTLP. Quando o host está configurado para a saída do OpenTelemetry para o Application Insights, os logs gerados pelo processo de trabalho do PowerShell ainda são encaminhados, mas não há suporte para rastreamento distribuído no momento.

Estas instruções se aplicam apenas a um exportador OTLP:

  1. Adicione uma configuração de aplicativo nomeada OTEL_FUNCTIONS_WORKER_ENABLED com o valor de True.

  2. Crie uma pasta no nível do aplicativoModules na raiz do aplicativo e execute o seguinte comando:

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

    Isso instala o módulo necessário AzureFunctions.PowerShell.OpenTelemetry.SDK diretamente em seu aplicativo. Não é possível usar o arquivo requirements.psd1 para instalar automaticamente esta dependência porque as dependências gerenciadas não têm suporte no momento na versão prévia do plano de Consumo Flex.

  3. Adicione este código ao arquivo profile.ps1:

    Import-Module AzureFunctions.PowerShell.OpenTelemetry.SDK -Force -ErrorAction Stop 
    Initialize-FunctionsOpenTelemetry 
    
  1. Adicione esta entrada ao arquivo requirements.txt:

    azure.monitor.opentelemetry
    
  2. Adicione este código ao arquivo de ponto de entrada principal do function_app.py:

    from azure.monitor.opentelemetry import configure_azure_monitor 
    configure_azure_monitor() 
    

Considerações sobre o OpenTelemetry

Ao exportar seus dados usando o OpenTelemetry, tenha estas considerações atuais em mente.

  • Quando o host é configurado para usar o OpenTelemetry, somente logs e rastreamentos são exportados. As métricas do host não são exportadas no momento.

  • No momento, não é possível executar o seu projeto de aplicativo localmente usando o Core Tools quando você tem o OpenTelemetry habilitado no host. No momento, você precisa implantar o seu código no Azure para validar suas atualizações relacionadas ao OpenTelemetry.

  • Neste momento, somente o gatilho HTTP e gatilhos baseados no SDK do Azure têm suporte com saídas do OpenTelemetry.

Monitorar o Azure FunctionsPlan de Consumo Flex