Loading skill
Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Instrument applications with Azure Monitor and OpenTelemetry for JavaScript (@azure/monitor-opentelemetry). Use when adding distributed tracing, metrics, and logs to Node.js applications with Application Insights.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 76% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 37% | 0% |
| case-06 | ✗→✓ | ▲ Improved | -1% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 6% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 67% | 0% |
Auto-instrument Node.js applications with distributed tracing, metrics, and logs.
bash# 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
bashAPPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=...;IngestionEndpoint=... AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production
IMPORTANT: Call useAzureMonitor() BEFORE importing other modules.
typescriptimport { useAzureMonitor } from "@azure/monitor-opentelemetry"; useAzureMonitor({ azureMonitorExporterOptions: { connectionString: process.env.APPLICATIONINSIGHTS_CONNECTION_STRING } }); // Now import your application import express from "express"; const app = express();
bashnode --import @azure/monitor-opentelemetry/loader ./dist/index.js
package.json:
json{ "scripts": { "start": "node --import @azure/monitor-opentelemetry/loader ./dist/index.js" } }
typescriptimport { 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);
typescriptimport { 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(); }
typescriptimport { 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" }); });
typescriptimport { 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();
typescriptimport { 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);
typescriptimport { 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);
typescriptimport { DefaultAzureCredential, ManagedIdentityCredential } 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"; // Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential> const credential = new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]}); // Or use a specific credential directly in production: // See https://learn.microsoft.com/javascript/api/overview/azure/identity-readme?view=azure-node-latest#credential-classes // const credential = new ManagedIdentityCredential(); const client = new LogsIngestionClient(endpoint, credential); 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); } } }
typescriptimport { SpanProcessor, ReadableSpan } from "@opentelemetry/sdk-trace-base"; import { Span, Context, SpanKind, TraceFlags } from "@opentelemetry/api"; import { useAzureMonitor } from "@azure/monitor-opentelemetry"; class FilteringSpanProcessor implements SpanProcessor { forceFlush(): Promise<void> { return Promise.resolve(); } shutdown(): Promise<void> { return Promise.resolve(); } onStart(span: Span, context: Context): void {} onEnd(span: ReadableSpan): void { // Add custom attributes span.attributes["CustomDimension"] = "value"; // Filter out internal spans if (span.kind === SpanKind.INTERNAL) { span.spanContext().traceFlags = TraceFlags.NONE; } } } useAzureMonitor({ spanProcessors: [new FilteringSpanProcessor()] });
typescriptimport { 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 });
typescriptimport { useAzureMonitor, shutdownAzureMonitor } from "@azure/monitor-opentelemetry"; useAzureMonitor(); // On application shutdown process.on("SIGTERM", async () => { await shutdownAzureMonitor(); process.exit(0); });
typescriptimport { 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";
--import @azure/monitor-opentelemetry/loadershutdownAzureMonitor() to flush telemetryOther measured skills in the registry, with their headline benchmark lift.