Application Insights 的 SDK 统计信息(预览版)

Application Insights 提供 SDK 统计自定义指标,可帮助监视和排除丢失或意外的遥测行为。 当遥测未到达引入终结点时,SDK 统计信息可帮助识别发生了什么以及下一步该做什么。

这些自定义指标包括项成功、删除和重试的计数。 其中还包括“错误代码”和“重试代码”,用于解释原因并指导后续步骤。

SDK 统计信息工作簿中提供了可视化效果。

重要

预览功能在提供时没有附带服务级别协议,不建议用于生产工作负载。 有关详细信息,请参阅适用于 Azure 预览版的补充使用条款

先决条件

  • 已检测的 Node.js 或 Python 应用程序。
  • OpenTelemetry 发行版(Node.js 1.13.0+ / Python 1.8.0+)或 Application Insights 经典 API SDK 3.10.0+。
  • 设置为选择加入的环境变量。

SDK 统计信息概述

SDK 统计信息是按进程计数的,由 Application Insights 的 SDK 和代理作为自定义指标发出。 这些指标汇总了导出程序成功发送的遥测项数量、丢弃的项数量,以及被安排重试的项数量。

SDK 发布三个指标:

  • preview.item.success.count
  • preview.item.dropped.count
  • preview.item.retry.count

注释

重试计数表示尝试次数,并且永远不会递减。 对同一项的后续成功仅会体现在成功序列中。

尺寸

这些指标包括 customDimensions 中的维度和用于切片的标准 Application Insights 维度:

维度键 Description
telemetry_type 与计数关联的遥测类型。 值与 Application Insights 表(例如 REQUESTDEPENDENCYEXCEPTIONTRACECUSTOM_EVENTAVAILABILITY)一致。
drop.codedrop.reason 删除项的代码和简短原因。 该代码是引入终结点的 HTTP 状态或客户端代码,例如 CLIENT_EXCEPTION
retry.coderetry.reason 计划重试的代码和简短原因。 该代码是引入终结点的 HTTP 状态或客户端代码,例如 CLIENT_TIMEOUT
telemetry_success 对于 REQUESTDEPENDENCY,导出时遥测项的 success 值(truefalse)。
languageversion SDK 或代理语言和版本。
compute.type 计算环境,例如 aksappsvcfunctionsspringcloudvmunknown
sdkVersion SDK 版本字符串也可以在标签中获取。
cloud_RoleNamecloud_RoleInstance 可用于按服务和实例进行切片的资源维度。

每一行指标都表示导出时间间隔内的汇总计数。 在一个时间片内尝试的总次数等于该时间片内的 success + dropped

启用和配置 SDK 统计信息

当前覆盖范围需要选择加入,并且仅限于以下 SDK

  • Node.js
  • Python

通过在应用程序进程环境中设置环境变量 APPLICATIONINSIGHTS_SDKSTATS_ENABLED_PREVIEW=true 并重启应用程序来启用。

导出间隔

  • 默认导出间隔为 15 分钟
  • 使用 APPLICATIONINSIGHTS_SDKSTATS_EXPORT_INTERVAL 配置不同的间隔(以秒为单位)。
  • 最小间隔为一秒。

无需部署任何工作簿资源。 SDK 统计信息模板显示在 Application Insights 资源下的工作簿库中。 工作簿在 SDK 发出这些自定义指标之前会显示“无数据”

打开 SDK 统计信息工作簿

打开 Application Insights 资源,然后打开工作簿并选择 SDK 统计信息(预览版)。 该体验使用具有简化的视觉对象集的单个工作簿

SDK 统计信息默认工作簿的屏幕截图。

过滤 器

使用工作簿顶部的筛选器来限定视图的范围:

  • 时间范围:按时间窗口和箱大小筛选。
  • SDK 版本:按 sdkVersion 字段筛选。
  • 遥测类型:按 telemetry_type 维度筛选。
  • 删除原因和删除代码:按 drop.reasondrop.code 筛选。

工作簿视觉对象

该工作簿专注于一组简明的图表,以在上下文中呈现结果:

  • 删除率。 显示所选时间粒度的 dropped / (dropped + success)
  • 随时间推移的请求和依赖关系分析。 根据应用程序中项的 success 值拆分请求和依赖项遥测,然后在单独的条形图中显示“已发送”和“已删除”
    • 成功并发送和已删除。 将应用程序记录为成功的项和导出程序发送到 Application Insights 的项与导出程序删除的同一类别的项进行比较
    • 失败并发送与已删除。 将应用程序记录为失败的项和导出程序发送的项与导出程序删除的同一类别的项进行比较。 已失败,已删除中的峰值通常表示暂时性服务问题、限制或配置问题。
    • 使用删除原因、删除代码和 SDK 版本筛选器来隔离原因。 例如,如果“失败、删除”增加,请查看 429 限制或 401403 身份验证问题。
  • 时间桶向下钻取。 选择一个存储桶将打开一个细分视图,其中包含该期间的主要删除原因和代码。
  • 一段时间内导出结果。 将 successretrydropped 的计数一起绘制。

排查意外遥测行为问题

使用代码确定发生了什么以及接下来要执行的操作。 工作簿标注指示首先要查看的位置。

诊断删除代码

导出程序为无法交付的项目设置 drop.code。 使用以下指南。

注释

当引入终结点接受某些项并拒绝其他项时,可以看到 206 Partial Content。 被接受的项记为 success。 被拒绝的项记为 dropped,并附带相应的删除代码。

客户端删除代码

drop.code 实际含义 接下来应执行的操作
CLIENT_EXCEPTION 由于导出程序遇到异常或未收到响应,项遭到删除。 检查应用和导出程序日志。 验证域名系统 (DNS)、传输层安全性 (TLS)、代理、防火墙和出站 Internet 规则。 验证来自主机的终结点可访问性。
CLIENT_READONLY 本地持久化无法写入,因为文件系统为只读。 将持久化指向一个可写路径。 修复容器或虚拟机 (VM) 权限。 如果环境中不允许,请考虑禁用磁盘持久性。
CLIENT_PERSISTENCE_CAPACITY 本地持久性已满,无法缓冲新项。 增加磁盘配额或存储大小。 减小批次大小或引入速率。 请考虑抽样
CLIENT_STORAGE_DISABLED 本地持久性已禁用。 需要缓冲的项无法保存并被删除。 启用本地存储或横向扩展以减少压力。
*NON_RETRYABLE_STATUS_CODE 引入终结点返回不可重试的状态,例如 400401403404 使用 HTTP 代码表更正配置、凭据或遥测架构,然后重新部署。

引入终结点 HTTP 状态代码

HTTP 状态 典型原因 接下来应执行的操作
200 OK 所有项均已接受。 无需执行任何操作。
206 Partial Content 接受部分项,拒绝部分项。 检查导出器日志以获取逐项错误。 验证架构和大小。 如果有效负载接近大小限制,请减小批次大小。
307308 Redirect 重定向到特定于标记的终结点。 允许在环境中重定向。 如果重定向是永久性的,请将连接字符串更新到正确的区域。
400 Bad Request 无效的遥测或不支持的架构。 在某些情况下,Microsoft Entra 配置错误可以显示为 400。 验证有效负载大小和架构。 如果路由错误,请修复连接字符串或令牌受众。
401 Unauthorized 身份验证失败或令牌缺少所需的权限。 修复连接字符串或凭据。 确保标识具有正确的 Application Insights 角色和令牌范围。
402 Payment Required 超过每日上限。 调整每日上限、减少引入或增加采样。 等待重置。
403 Forbidden 权限或映射不正确。 更正角色分配或终结点映射。 确认资源和连接字符串属于同一环境。
404 Not Found 连接字符串指向错误的区域或资源。 将连接字符串更新到正确的资源和区域。
405 Method Not Allowed 不允许使用请求方法。 升级 SDK 并确认仅使用受支持的方法。
408 Request Timeout 网络超时。 检查网络延迟和防火墙规则。 适当时增加客户端超时。
413 Payload Too Large 批处理有效负载超出大小限制。 减小最大批大小。 考虑发送更频繁、更小的批次。
429 Too Many Requests 使用 Retry-After 进行限制。 降低发送速率。 尊重 Retry-After。 增加采样或横向扩展。
439 Daily Quota Exceeded (已弃用) 旧的配额信号。 与 402 相同。 优先监控 402。
5xx Server Error 暂时性服务错误。 需要恢复。 如果问题持续超过几分钟,请检查 Azure 状态并打开带有时间戳和区域的支持案例。
Other 无法识别。 从日志中捕获相关标识符 (ID),并打开支持案例。

诊断重试代码

导出程序会为计划稍后发送的项目设置 retry.code。 重试表示投递尝试尚未成功,而非最终删除。

retry.code 实际含义 接下来应执行的操作
CLIENT_EXCEPTION 运行时异常,例如网络故障阻止传递。 检查 DNS、代理、TLS 和防火墙。 查看导出程序日志以了解异常详细信息。
CLIENT_TIMEOUT 导出程序超时等待响应。 按需增加超时。 调查网络延迟和服务器响应能力。
*RETRYABLE_STATUS_CODE 引入终结点返回了可重试的 HTTP 状态(例如 4084295xx)。 预期最终恢复。 减少限制时的发送速率或采样。 留意 Retry-After 并遵守。

如何解释重试

每当导出程序计划再次发送遥测时,计数器 preview.item.retry.count 就会增加。 它反映了尝试次数,而不是最终结果。 计数器永远不会减少。 将其与成功和删除序列结合使用,了解交付运行状况

  • 仅仅重试次数上升并不意味着数据丢失。 项稍后即可成功发送。
  • 将重试次数与成功次数进行比较。 如果成功次数在重试次数激增后恢复,则问题可能是暂时性的。
  • 将重试次数与已删除次数进行比较。 如果重试次数增多而删除次数仍接近零,那么说明导出程序正在进行缓冲和恢复操作。
  • 持续出现大量重试,而成功次数却保持不变或呈下降趋势,这表明存在阻塞问题。 请参阅“成功次数是否未恢复”
按代码调查

retry.code 拆分重试指标以确定重试的原因。

retry.code 通常的含义 下一步要检查什么或执行哪些操作
CLIENT_TIMEOUT 导出程序超时等待响应。 适当时增加客户端超时。 检查延迟、代理和防火墙规则。
CLIENT_EXCEPTION 网络或运行时错误阻止传递。 查看导出程序日志。 验证 DNS、TLS、代理和出站网络配置。
408 请求在引入终结点超时。 调查网络路径和延迟。 请考虑较小的批次或更高的发送频率。
429 受引入限制,通常使用 Retry-After 降低发送速率或增加采样。 重试前应遵循 Retry-After
5xx 引入时的暂时性服务问题。 需要恢复。 继续使用退避重试。 检查 Azure 状态(如果问题仍然存在)。
如果成功次数未恢复

如果重试次数不断增加而成功率仍未恢复,则转向删除代码以找到阻止程序。 从配置和配额问题开始,例如 402(每日上限)、401403(身份验证或权限),以及客户端存储问题,例如 CLIENT_PERSISTENCE_CAPACITYCLIENT_READONLYCLIENT_STORAGE_DISABLED。 解决根本原因,然后确认删除次数回到零并且成功次数在下一个时段上升

成本和数据量

SDK 统计数据发送汇总的 customMetrics 记录。 工作负载发布的是计数器而不是每个遥测项,因此相对于应用程序遥测,数据量保持较低。 这些记录将作为 customMetrics 的标准 Application Insights 数据提取进行计费,并遵循保留设置。 导出程序会通过现有的引入渠道发送计数器。

规划公式

Estimated records per hour per instance ≈
  (#metrics emitted per interval)
  × (3600 / interval_seconds)
  × (distinct dimension combinations you use)

默认间隔为 15 分钟 ()interval_seconds = 900。 请使用 APPLICATIONINSIGHTS_SDKSTATS_EXPORT_INTERVAL 配置其他间隔。

在默认工作簿外部的 Azure Monitor 中使用 SDK 统计信息

可以将 SDK 统计信息自定义指标与其他 Azure Monitor 功能配合使用。

Azure 数据资源管理器

以下是 Kusto 查询语言 (KQL) 参考示例。

导出结果与时间

let g = 15m; // align with export interval for clearer charts
customMetrics
| where name in ("preview.item.success.count", "preview.item.dropped.count", "preview.item.retry.count")
| summarize 
    success = sumif(todouble(value), name == "preview.item.success.count"),
    dropped = sumif(todouble(value), name == "preview.item.dropped.count"),
    retry   = sumif(todouble(value), name == "preview.item.retry.count")
    by bin(timestamp, g)

随时间推移的比率

let g = 15m;
customMetrics
| where name in ("preview.item.dropped.count", "preview.item.success.count", "preview.item.retry.count")
| summarize 
    success = sumif(todouble(value), name == "preview.item.success.count"),
    dropped = sumif(todouble(value), name == "preview.item.dropped.count"),
    retry   = sumif(todouble(value), name == "preview.item.retry.count")
    by bin(timestamp, g)
| extend drop_rate = dropped / iff((success + dropped) == 0.0, 1.0, (success + dropped))
| extend retry_to_attempt_ratio = retry / iff((success + dropped) == 0.0, 1.0, (success + dropped))
| project timestamp, drop_rate, retry_to_attempt_ratio

随时间推移的请求和依赖关系分析(复制堆叠条形图)

let g = 15m;
// Successful request or dependency telemetry: sent vs dropped
let sent_success = (requests
| where success == true
| summarize c = count() by bin(timestamp, g)
| union (dependencies | where success == true | summarize c = count() by bin(timestamp, g))
| summarize sent = sum(c) by timestamp);
let dropped_success = (customMetrics
| where name == "preview.item.dropped.count"
| extend telemetry_type = tostring(customDimensions["telemetry_type"]),
        telemetry_success = tostring(customDimensions["telemetry_success"])
| where telemetry_type in ("REQUEST","DEPENDENCY") and telemetry_success == "true"
| summarize dropped = sum(todouble(value)) by bin(timestamp, g));
sent_success
| join kind=fullouter dropped_success on timestamp
| project timestamp, ["Successful - Sent"] = todouble(sent), ["Successful - Dropped"] = todouble(dropped)
| order by timestamp asc;

// Failed request or dependency telemetry: sent vs dropped
let sent_failed = (requests
| where success == false
| summarize c = count() by bin(timestamp, g)
| union (dependencies | where success == false | summarize c = count() by bin(timestamp, g))
| summarize sent = sum(c) by timestamp);
let dropped_failed = (customMetrics
| where name == "preview.item.dropped.count"
| extend telemetry_type = tostring(customDimensions["telemetry_type"]),
        telemetry_success = tostring(customDimensions["telemetry_success"])
| where telemetry_type in ("REQUEST","DEPENDENCY") and telemetry_success == "false"
| summarize dropped = sum(todouble(value)) by bin(timestamp, g));
sent_failed
| join kind=fullouter dropped_failed on timestamp
| project timestamp, ["Failed - Sent"] = todouble(sent), ["Failed - Dropped"] = todouble(dropped)
| order by timestamp asc

使用代码删除原因摘要

customMetrics
| where name == "preview.item.dropped.count"
| extend drop_reason = tostring(customDimensions["drop.reason"]),
        drop_code   = tostring(customDimensions["drop.code"])
| summarize total_dropped = sum(todouble(value)) by drop_reason, drop_code
| order by total_dropped desc

Alerts

创建用于监视比率或特定代码的日志警报。

// Drop rate over 5 minutes
let window = 5m;
customMetrics
| where timestamp >= ago(window)
| where name in ("preview.item.success.count", "preview.item.dropped.count")
| summarize 
    success = sumif(todouble(value), name == "preview.item.success.count"),
    dropped = sumif(todouble(value), name == "preview.item.dropped.count")
| extend drop_rate = dropped / iff((success + dropped) == 0.0, 1.0, (success + dropped))
| project drop_rate
// Over-quota daily cap (HTTP 402) in the last 10 minutes
let window = 10m;
customMetrics
| where timestamp >= ago(window)
| where name == "preview.item.dropped.count"
| extend drop_code = tostring(customDimensions["drop.code"])
| summarize dropped_402 = sum(todouble(value)) by drop_code
| where drop_code == "402" and dropped_402 > 0
| project dropped_402

小窍门

将 402 警报与每日上限指导配对,以便响应者可以调整上限或减少引入。

Power BI

使用 Azure Monitor 日志连接器将这些指标引入 Power BI

// Drop and retry ratios by hour
let window = 14d;
let g = 1h;
customMetrics
| where timestamp >= ago(window)
| where name in ("preview.item.success.count", "preview.item.dropped.count", "preview.item.retry.count")
| summarize 
    success = sumif(todouble(value), name == "preview.item.success.count"),
    dropped = sumif(todouble(value), name == "preview.item.dropped.count"),
    retry   = sumif(todouble(value), name == "preview.item.retry.count")
    by bin(timestamp, g)
| extend drop_rate = dropped / iff((success + dropped) == 0.0, 1.0, (success + dropped))
| extend retry_to_attempt_ratio = retry / iff((success + dropped) == 0.0, 1.0, (success + dropped))
| order by timestamp asc
// Dropped items by reason
let window = 14d;
let g = 1h;
customMetrics
| where timestamp >= ago(window)
| where name == "preview.item.dropped.count"
| extend drop_reason = tostring(customDimensions["drop.reason"])
| summarize dropped = sum(todouble(value)) by bin(timestamp, g), drop_reason
| order by timestamp asc

指标资源管理器

在指标中绘制这些 SDK 统计信息图表。

  1. 打开 Application Insights 资源。
  2. 打开“指标”
  3. 对于“指标命名空间”,请选择“基于日志的指标”
  4. 对于“指标”,请选择以下选项之一:
    • preview.item.success.count
    • preview.item.dropped.count
    • preview.item.retry.count
  5. (可选)将“汇总”设置为“总和”,以获得时间粒度总计。
  6. 使用拆分依据进行调查。 常见拆分:
    • drop.reason、drop.code
    • telemetry_type、sdkVersion
    • cloud_RoleName、cloud_RoleInstance

SDK 统计信息计数与日志有何不同?

不要期望这些计数器的值与 requestsdependencies 等表中的项目计数相等。 出现差异的原因如下:

  • 汇总时间。 统计数据按间隔和批次进行汇总。 日志存储的是单个项目,因此跨不同时段粒度的计数可能会发生漂移。
  • 采样和处理器。 SDK 应用采样和任何丢弃或修改遥测的处理器后,统计计数项目。 日志反映引入终结点接受的内容。
  • 部分成功。 引入终结点可以接受批次中的一部分,并拒绝其余部分。 导出器会在同一个时间区间内,将被接受的项记录为成功,而将被拒绝的项记录为删除。
  • 本地缓冲。 当导出程序进行重试时,它可以在稍后发送已缓冲的项。 统计信息所分配的删除、重试或成功计数的时间,并不总是与原始遥测数据的事件时间相匹配。
  • 超过配额或每日上限。 当资源超过其每日上限时,引入终结点将返回错误,系统会删除导出程序记录。 在上限窗口中,相应的应用程序遥测不会显示在日志中。
  • 范围。 统计信息涵盖导出程序行为。 日志涵盖端到端遥测,包括不影响导出程序成功的字段。