你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
本文介绍如何将函数应用配置为以 OpenTelemetry 格式导出日志和跟踪数据。 Azure Functions 从 Functions 主机进程和运行函数代码的语言特定的工作进程生成函数执行的遥测数据。 默认情况下,此遥测数据使用 Application Insights SDK 发送到 Application Insights。 但是,可以选择使用 OpenTelemetry 语义导出此数据。 虽然仍可以使用 OpenTelemetry 格式将数据发送到 Application Insights,但现在可以将相同的数据导出到任何其他符合 OpenTelemetry 的终结点。
通过在函数应用中启用 OpenTelemetry,可以获得这些优势:
- 在主机和应用程序代码中生成跟踪和日志之间的关联数据。
- 启用一致的、基于标准的可导出遥测数据生成。
- 与其他可以使用 OpenTelemetry 兼容数据的提供程序集成。
使用本文时,请记住以下注意事项:
试用 OpenTelemetry 教程,该教程旨在帮助你快速开始使用 OpenTelemetry 和 Azure Functions。 本文使用 Azure 开发人员 CLI (
azd) 创建和部署使用 OpenTelemetry 集成进行分布式跟踪的函数应用。由于本文针对的是你所选择的开发语言,因此请记住在文章顶部选择正确的语言。
- C# 进程内应用目前不受 OpenTelemetry 的支持。
- 在主机配置 (
host.json) 和代码项目中的函数应用级别均启用了 OpenTelemetry。 Functions 还提供客户端优化体验,用于从在特定于语言的工作进程中运行的函数代码导出 OpenTelemetry 数据。
在 Functions 主机中启用 OpenTelemetry
在函数应用的 host.json 文件中启用 OpenTelemetry 输出时,主机会导出 OpenTelemetry 输出,而不考虑应用使用的语言堆栈。
若要从 Functions 主机启用 OpenTelemetry 输出,请在代码项目中更新 host.json文件,以将 "telemetryMode": "OpenTelemetry" 元素添加到根集合。 启用 OpenTelemetry 后,host.json 文件可能如下所示:
{
"version": "2.0",
"telemetryMode": "OpenTelemetry",
...
}
配置应用程序设置
启用 host.json 文件中的 OpenTelemetry 时,应用的环境变量会根据可用的 OpenTelemetry 支持的应用程序设置来确定数据发送的终结点。
基于 OpenTelemetry 输出目标在函数应用中创建特定的应用程序设置。 为 Application Insights 和 OpenTelemetry 协议 (OTLP) 导出程序提供连接设置时,OpenTelemetry 数据将发送到这两个终结点。
APPLICATIONINSIGHTS_CONNECTION_STRING:Application Insights 工作区的连接字符串。 如果存在此设置,OpenTelemetry 数据将发送到该工作区。 使用相同的设置连接到未启用 OpenTelemetry 功能的 Application Insights。 如果应用还没有此设置,则可能需要启用 Application Insights 集成。
JAVA_APPLICATIONINSIGHTS_ENABLE_TELEMETRY:设置为 true 这样,Functions 主机允许 Java 工作进程直接流式传输 OpenTelemetry 日志,从而阻止重复的主机级条目。
PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY:设置为 true 这样,Functions 主机允许 Python 工作进程直接流式传输 OpenTelemetry 日志,从而阻止重复的主机级条目。
在应用中启用 OpenTelemetry
将 Functions 主机配置为使用 OpenTelemetry 后,更新应用程序代码以输出 OpenTelemetry 数据。 在主机和应用程序代码中启用 OpenTelemetry 时,可以在 Functions 主机进程和语言工作进程发出的跟踪和日志之间获得更好的关联。
检测应用程序以使用 OpenTelemetry 的方式取决于目标 OpenTelemetry 终结点:
本文中的示例假定应用使用 IHostApplicationBuilder,该版本在 2.x 版和更高版本的 Microsoft.Azure.Functions.Worker 中可用。 有关详细信息,请参阅 C# 独立辅助角色模型指南中的 版本 2.x 。
运行以下命令,以在应用中安装所需的程序集:
dotnet add package Microsoft.Azure.Functions.Worker.OpenTelemetry dotnet add package OpenTelemetry.Extensions.Hosting dotnet add package Azure.Monitor.OpenTelemetry.Exporter在 Program.cs 项目文件中,添加此
using语句:using Azure.Monitor.OpenTelemetry.Exporter;根据项目启动是使用
IHostBuilder还是IHostApplicationBuilder来配置 OpenTelemetry。 后者是在 .NET 隔离工作模型扩展的 v2.x 中引入的。在program.cs中,在
ConfigureFunctionsWebApplication之后添加此代码行:builder.Services.AddOpenTelemetry() .UseFunctionsWorkerDefaults() .UseAzureMonitorExporter();可以从同一应用导出到两个 OpenTelemetry 终结点。
将所需的库添加到应用。 添加库的方式取决于是使用 Maven 还是 Kotlin 进行部署,以及是否还要将数据发送到 Application Insights。
<dependency> <groupId>com.microsoft.azure.functions</groupId> <artifactId>azure-functions-java-opentelemetry</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>com.azure</groupId> <artifactId>azure-monitor-opentelemetry-autoconfigure</artifactId> <version>1.2.0</version> </dependency>(可选)添加此代码以创建自定义范围:
import com.microsoft.azure.functions.opentelemetry.FunctionsOpenTelemetry; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.context.Scope; Span span = FunctionsOpenTelemetry.startSpan( "com.contoso.PaymentFunction", // tracer name "validateCharge", // span name null, // parent = current context SpanKind.INTERNAL); try (Scope ignored = span.makeCurrent()) { // business logic here } finally { span.end(); }
在项目中安装以下 npm 包:
npm install @opentelemetry/api npm install @opentelemetry/auto-instrumentations-node npm install @azure/monitor-opentelemetry-exporter npm install @azure/functions-opentelemetry-instrumentation
在项目中创建代码文件,将此新文件中复制并粘贴以下代码,并将该文件另存为
src/index.js:const { AzureFunctionsInstrumentation } = require('@azure/functions-opentelemetry-instrumentation'); const { AzureMonitorLogExporter, AzureMonitorTraceExporter } = require('@azure/monitor-opentelemetry-exporter'); 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(), new AzureFunctionsInstrumentation()], });请在 package.json 文件中更新
main字段,以包含新src/index.js文件。 例如:"main": "src/{index.js,functions/*.js}"
在项目中创建代码文件,将此新文件中复制并粘贴以下代码,并将该文件另存为
src/index.ts:import { AzureFunctionsInstrumentation } from '@azure/functions-opentelemetry-instrumentation'; import { AzureMonitorLogExporter, AzureMonitorTraceExporter } from '@azure/monitor-opentelemetry-exporter'; 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(), new AzureFunctionsInstrumentation()], });更新 package.json 文件中的
main字段以包含此新src/index.ts文件的输出,如下所示:"main": "dist/src/{index.js,functions/*.js}"
重要说明
PowerShell 应用目前不支持从语言辅助角色将 OpenTelemetry 输出输出到 Application Insights。 你可能想要使用 OTLP 导出器终结点。 将主机配置为 OpenTelemetry 输出到 Application Insights 时,PowerShell 工作进程生成的日志仍会转发,但目前不支持分布式跟踪。
这些说明仅适用于 OTLP 导出程序:
添加名为
OTEL_FUNCTIONS_WORKER_ENABLED的应用程序设置,其值为True。在应用的根目录中创建应用级
Modules文件夹并运行以下命令:Save-Module -Name AzureFunctions.PowerShell.OpenTelemetry.SDK此命令直接在应用中安装所需的
AzureFunctions.PowerShell.OpenTelemetry.SDK模块。 无法使用requirements.psd1文件自动安装此依赖项,因为 Flex Consumption 计划预览版目前不支持托管依赖项。将此代码添加到 profile.ps1 文件:
Import-Module AzureFunctions.PowerShell.OpenTelemetry.SDK -Force -ErrorAction Stop Initialize-FunctionsOpenTelemetry
请确保这些库位于
requirements.txt文件中,无论是取消注释还是自行添加:azure-monitor-opentelemetry将此代码添加到
function_app.py主入口点文件:如果已在应用程序设置中添加
PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY=true,则可以跳过此步骤。 若要在不自动检测的情况下手动启用 Application Insights 集合,请将以下代码添加到应用:from azure.monitor.opentelemetry import configure_azure_monitor configure_azure_monitor()查看 Azure Monitor 发行版使用情况 文档,获取有关如何进一步配置 SDK 的选项。
OpenTelemetry 注意事项
使用 OpenTelemetry 导出数据时,请记住这些注意事项。
仅当遥测发送到 Azure Monitor 时,Azure 门户才支持
Recent function invocation跟踪。将主机配置为使用 OpenTelemetry 时,Azure 门户不支持日志流式处理。
如果将
telemetryMode设置为OpenTelemetry,则 host.json 部分中的logging.applicationInsights配置将不适用。
自定义范围会自动包括所有资源属性,并使用应用中配置的导出程序。
当您的应用程序在 Azure 外部运行时(包括在本地开发期间),资源检测器会默认将
service.name属性设置为java-function-app。在本地运行单元测试时,使用这些 Java 虚拟机(JVM)参数来禁用遥测:
-Dotel.traces.exporter=none-Dotel.metrics.exporter=none-Dotel.logs.exporter=none
- 无需手动注册中间件,Java 工作线程会自动发现它
OpenTelemetryInvocationMiddleware。
Troubleshooting
使用 OpenTelemetry 导出数据时,请记住这些常见问题和解决方案。
日志筛选
若要在函数应用中正确配置日志筛选,需要了解主机进程与工作进程之间的差异。
主机进程是 Azure Functions 运行时,用于管理触发器、缩放和生成系统级遥测,例如初始化日志、请求跟踪和运行时运行状况信息。
工作进程特定于语言,执行函数代码,并独立生成应用程序日志和遥测。
重要说明
host.json 中定义的筛选器仅适用于主机进程生成的日志。 必须使用针对语言的 OpenTelemetry 设置来筛选工作进程中的日志。
示例:筛选 host.json中所有提供程序的主机日志
使用此方法可为主机托管的所有提供程序设置全局日志级别:
{
"version": "2.0",
"telemetryMode": "OpenTelemetry",
"logging": {
"logLevel": {
"default": "Warning"
}
}
}
示例:仅筛选与 OpenTelemetry 日志记录器提供程序相关的日志
使用此方法仅针对 OpenTelemetry 日志记录器提供程序,不影响其他提供程序(如控制台或文件日志)。
{
"version": "2.0",
"telemetryMode": "OpenTelemetry",
"logging": {
"OpenTelemetry": {
"logLevel": {
"default": "Warning"
}
}
}
}
控制台日志输出
Functions 主机会自动捕获写入 stdout 或 stderr 的任何内容,并将其转发到遥测管道。 如果你在代码中使用 ConsoleExporter 或直接写入控制台,则遥测数据中可能会出现重复日志。
注释
为了避免重复的遥测条目,请勿在生产代码中添加 ConsoleExporter 或输出到控制台。
Microsoft Entra 身份验证
在 OpenTelemetry 中使用 Microsoft Entra 身份验证时,必须为主机进程和辅助进程单独配置身份验证。
若要为主机进程配置身份验证,请参阅 “需要Microsoft Entra 身份验证”。
若要为辅助进程配置身份验证,请参阅 “启用Microsoft Entra 身份验证”。
资源属性支持
Azure Monitor 中的资源属性支持目前为预览版。 若要启用此功能,请将 OTEL_DOTNET_AZURE_MONITOR_ENABLE_RESOURCE_METRICS 环境变量设置为 true。 此设置将资源属性引入到自定义指标表中。
重复的请求遥测
主机进程会自动发送请求遥测数据。 如果工作进程也使用请求跟踪库(例如 .NET 中的 AspNetCoreInstrumentation)进行工具化,则会报告相同的请求两次。
注释
由于 Azure Monitor Distro 通常包含 .NET 中的 AspNetCoreInstrumentation 和其他语言中的类似检测,因此应避免在工作进程中使用 Azure Monitor Distro,以防止重复遥测。
不包括日志记录范围
默认情况下,工作进程不在其日志中包括作用域。 若要启用授权范围,您必须在工作线程中显式配置此设置。 以下示例演示如何在 .NET 隔离环境中启用作用域:
builder.Logging.AddOpenTelemetry(b => b.IncludeScopes = true);
缺少请求遥测
HTTP、服务总线和事件中心等触发器依赖于分布式跟踪的上下文传播。 默认情况下,使用基于父级的采样。当传入请求或消息未被采样时,不会生成请求遥测数据。
重复 OperationId
在 Azure Functions 中,用于关联遥测数据的 OperationId 直接来自于传入请求或消息中 traceparent 的值。 如果多个调用重复使用相同的 traceparent 值,则它们都获得相同的 OperationId值。
使用环境变量配置 OpenTelemetry
可以使用其标准环境变量来配置 OpenTelemetry 行为。 这些变量提供一致的方式来控制不同语言和运行时的行为。 可以调整采样策略、导出程序设置和资源属性。 有关支持的环境变量的详细信息,请参阅 OpenTelemetry 文档。
使用诊断工具排查监控问题
Azure 门户中的 Azure Functions 诊断是用于检测和诊断潜在监视相关问题的有用资源。
若要访问应用中的诊断,请按以下步骤操作:
在 Azure 门户中,转到函数应用资源。
在左窗格中选择“诊断并解决问题”,然后搜索“函数应用缺少遥测 Application Insights 或 OpenTelemetry”工作流。
选择此工作流,选择引入方法,然后选择“ 下一步”。
查看疑难解答提供的指南和任何建议。
后续步骤
详细了解 OpenTelemetry 和监视 Azure Functions: