mcpField
A
azure-monitor-opentelemetry-ts

azure-monitor-opentelemetry-ts

github.com/sickn33云与 DevOps48.7k65 次安装今天更新
代码仓库

关于 azure-monitor-opentelemetry-ts

Azure Monitor OpenTelemetry SDK for TypeScript 可为 Node.js 应用采集跟踪、指标和日志。它支持自动插桩,也提供自定义导出器和遥测数据摄取方式。

主要功能

  1. 01Node.js 自动插桩
  2. 02导出跟踪、指标和日志
  3. 03添加自定义跟踪属性与指标
  4. 04配置采样和离线存储
  5. 05摄取自定义日志

适用场景

  1. 01采集 Node.js 服务的遥测数据
  2. 02添加自定义跨度和指标
  3. 03通过采样减少跟踪数据量
  4. 04将自定义日志发送到 Azure Monitor

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/sickn33/agentic-awesome-skills --skill azure-monitor-opentelemetry-ts

安装后在 Claude Code 中输入/azure-monitor-opentelemetry-ts确认已加载。

详细介绍

TypeScript 版 Azure Monitor OpenTelemetry SDK

通过分布式追踪、指标和日志,自动检测 Node.js 应用程序。

版本和数据边界

本文档介绍现有的 @azure/monitor-opentelemetry 发行版。Microsoft 当前的指导也为新采用场景提供了 @microsoft/opentelemetry;请勿同时初始化两者。所有 OpenTelemetry 包都应使用匹配的版本,并采用该版本的日志提供程序构造函数/处理器 API。配置获准的遥测数据目的地,移除个人身份信息(PII)和机密,并保护离线存储;自动检测可能会导出敏感的请求/日志数据。请参阅 Microsoft 启用指南。

安装

# Distro (recommended - auto-instrumentation)
npm install @azure/monitor-opentelemetry

# Low-level exporters (custom OpenTelemetry setup)
npm install @azure/monitor-opentelemetry-exporter

# Custom logs ingestion
npm install @azure/monitor-ingestion

环境变量

APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=...;IngestionEndpoint=...

快速入门(自动检测)

重要: 请在导入其他模块之前调用 useAzureMonitor()。

import { useAzureMonitor } from "@azure/monitor-opentelemetry";

useAzureMonitor({
  azureMonitorExporterOptions: {
    connectionString: process.env.APPLICATIONINSIGHTS_CONNECTION_STRING
  }
});

// Static ESM imports are hoisted; load the app after initialization.
const { default: express } = await import("express");
const app = express();

ESM 支持(Node.js 18.19+)

node --import @azure/monitor-opentelemetry/loader ./dist/index.js

package.json:

{
  "scripts": {
    "start": "node --import @azure/monitor-opentelemetry/loader ./dist/index.js"
  }
}

完整配置

import { useAzureMonitor, AzureMonitorOpenTelemetryOptions } from "@azure/monitor-opentelemetry";
import { resourceFromAttributes } from "@opentelemetry/resources";

const options: AzureMonitorOpenTelemetryOptions = {
  azureMonitorExporterOptions: {
    connectionString: process.env.APPLICATIONINSIGHTS_CONNECTION_STRING,
    storageDirectory: "/path/to/offline/storage",
    disableOfflineStorage: false
  },
  
  // Sampling
  samplingRatio: 1.0,  // 0-1, percentage of traces
  
  // Features
  enableLiveMetrics: true,
  enableStandardMetrics: true,
  enablePerformanceCounters: true,
  
  // Instrumentation libraries
  instrumentationOptions: {
    azureSdk: { enabled: true },
    http: { enabled: true },
    mongoDb: { enabled: true },
    mySql: { enabled: true },
    postgreSql: { enabled: true },
    redis: { enabled: true },
    bunyan: { enabled: false },
    winston: { enabled: false }
  },
  
  // Custom resource
  resource: resourceFromAttributes({ "service.name": "my-service" })
};

useAzureMonitor(options);

自定义追踪

import { trace } from "@opentelemetry/api";

const tracer = trace.getTracer("my-tracer");

const span = tracer.startSpan("doWork");
try {
  span.setAttribute("component", "worker");
  span.setAttribute("operation.id", "42");
  span.addEvent("processing started");
  
  // Your work here
  
} catch (error) {
  span.recordException(error as Error);
  span.setStatus({ code: 2, message: (error as Error).message });
} finally {
  span.end();
}

自定义指标

import { metrics } from "@opentelemetry/api";

const meter = metrics.getMeter("my-meter");

// Counter
const counter = meter.createCounter("requests_total");
counter.add(1, { route: "/api/users", method: "GET" });

// Histogram
const histogram = meter.createHistogram("request_duration_ms");
histogram.record(150, { route: "/api/users" });

// Observable Gauge
const gauge = meter.createObservableGauge("active_connections");
gauge.addCallback((result) => {
  result.observe(getActiveConnections(), { pool: "main" });
});

手动设置导出器

追踪导出器
import { AzureMonitorTraceExporter } from "@azure/monitor-opentelemetry-exporter";
import { NodeTracerProvider, BatchSpanProcessor } from "@opentelemetry/sdk-trace-node";

const exporter = new AzureMonitorTraceExporter({
  connectionString: process.env.APPLICATIONINSIGHTS_CONNECTION_STRING
});

const provider = new NodeTracerProvider({
  spanProcessors: [new BatchSpanProcessor(exporter)]
});

provider.register();
指标导出器
import { AzureMonitorMetricExporter } from "@azure/monitor-opentelemetry-exporter";
import { PeriodicExportingMetricReader, MeterProvider } from "@opentelemetry/sdk-metrics";
import { metrics } from "@opentelemetry/api";

const exporter = new AzureMonitorMetricExporter({
  connectionString: process.env.APPLICATIONINSIGHTS_CONNECTION_STRING
});

const meterProvider = new MeterProvider({
  readers: [new PeriodicExportingMetricReader({ exporter })]
});

metrics.setGlobalMeterProvider(meterProvider);
日志导出器
import { AzureMonitorLogExporter } from "@azure/monitor-opentelemetry-exporter";
import { BatchLogRecordProcessor, LoggerProvider } from "@opentelemetry/sdk-logs";
import { logs } from "@opentelemetry/api-logs";

const exporter = new AzureMonitorLogExporter({
  connectionString: process.env.APPLICATIONINSIGHTS_CONNECTION_STRING
});

const loggerProvider = new LoggerProvider();
loggerProvider.addLogRecordProcessor(new BatchLogRecordProcessor(exporter));

logs.setGlobalLoggerProvider(loggerProvider);

自定义日志引入

import { DefaultAzureCredential } from "@azure/identity";
import { LogsIngestionClient, isAggregateLogsUploadError } from "@azure/monitor-ingestion";

const endpoint = "https://<dce>.ingest.monitor.azure.com";
const ruleId = "<data-collection-rule-id>";
const streamName = "Custom-MyTable_CL";

const client = new LogsIngestionClient(endpoint, new DefaultAzureCredential());

const logs = [
  {
    Time: new Date().toISOString(),
    Computer: "Server1",
    Message: "Application started",
    Level: "Information"
  }
];

try {
  await client.upload(ruleId, streamName, logs);
} catch (error) {
  if (isAggregateLogsUploadError(error)) {
    for (const uploadError of error.errors) {
      console.error("Failed logs:", uploadError.failedLogs);
    }
  }
}

自定义 Span 处理

在 onStart 中通过 span.setAttribute() 丰富可写入的 Span。请勿在 onEnd 中修改 ReadableSpan.attributes 或 spanContext().traceFlags:已结束的 Span 为只读状态,这也不是可靠的导出过滤方式。请针对锁定的 SDK 版本使用受支持的采样器或经过审核的过滤导出器/处理器管线,并验证导出的数据。

采样

import { ApplicationInsightsSampler } from "@azure/monitor-opentelemetry-exporter";
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";

// Sample 75% of traces
const sampler = new ApplicationInsightsSampler(0.75);

const provider = new NodeTracerProvider({ sampler });

关闭

import { useAzureMonitor, shutdownAzureMonitor } from "@azure/monitor-opentelemetry";

useAzureMonitor();

// On application shutdown
process.on("SIGTERM", async () => {
  await shutdownAzureMonitor();
  process.exit(0);
});

关键类型

import {
  useAzureMonitor,
  shutdownAzureMonitor,
  AzureMonitorOpenTelemetryOptions,
  InstrumentationOptions
} from "@azure/monitor-opentelemetry";

import {
  AzureMonitorTraceExporter,
  AzureMonitorMetricExporter,
  AzureMonitorLogExporter,
  ApplicationInsightsSampler,
  AzureMonitorExporterOptions
} from "@azure/monitor-opentelemetry-exporter";

import {
  LogsIngestionClient,
  isAggregateLogsUploadError
} from "@azure/monitor-ingestion";

最佳实践

  1. 首先调用 useAzureMonitor() - 在导入其他模块之前
  2. ESM 项目使用 ESM 加载器 - --import @azure/monitor-opentelemetry/loader
  3. 启用离线存储 - 确保在断连场景下可靠地收集遥测数据
  4. 设置采样率 - 适用于高流量应用程序
  5. 添加自定义维度 - 使用 Span 处理器进行丰富
  6. 优雅关闭 - 调用 shutdownAzureMonitor() 刷新遥测数据

适用场景

当需要执行概述中所述的工作流或操作时,可使用此技能。

限制

  • 仅当任务明确符合上述范围时,才使用此技能。
  • 请勿将输出视为环境特定验证、测试或专家审核的替代品。
  • 如果缺少必要的输入、权限、安全边界或成功标准,请停止并请求澄清。

评论

支持 Markdown