Skip to content

Latest commit

 

History

195 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@microsoft/opentelemetry

npm version license API Docs

Microsoft OpenTelemetry distribution for Node.js — one import, one call, full observability across Azure Monitor, OTLP-compatible backends, and A365.

Getting Started

npm install @microsoft/opentelemetry

Important: Import and call useMicrosoftOpenTelemetry() as early as possible in your application entry point so instrumentations can patch libraries before they are loaded.

ESM Support

Note: This package requires Node.js 22.0.0 or later. Its ESM loader flow relies on --import and node:module.register(). For background on why startup ordering matters, see the OpenTelemetry ESM Support documentation.

For ESM applications, instrumentation hooks must be registered before any instrumented modules (for example http, express, axios, or loggers) are loaded. This is a fundamental ESM constraint: modules cannot be instrumented after they are already loaded.

This pattern is not reliable for auto-instrumentation:

import { useMicrosoftOpenTelemetry } from "@microsoft/opentelemetry";
useMicrosoftOpenTelemetry();

import express from "express";

Use --import so the loader is registered at process startup.

node --import @microsoft/opentelemetry/loader ./app.mjs

For example, in package.json:

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

If you prefer explicit telemetry configuration in a bootstrap file, preload that file instead:

telemetry.mjs:

import "@microsoft/opentelemetry/loader";
import { useMicrosoftOpenTelemetry } from "@microsoft/opentelemetry";

useMicrosoftOpenTelemetry({
  azureMonitor: {
    azureMonitorExporterOptions: {
      connectionString: process.env.APPLICATIONINSIGHTS_CONNECTION_STRING,
    },
    enableLiveMetrics: false,
  },
  instrumentationOptions: {
    bunyan: { enabled: true },
    winston: { enabled: true },
  },
});

Start your app:

node --import ./telemetry.mjs ./app.mjs

Your application code can keep regular static ESM imports in app.mjs.

A365

import { useMicrosoftOpenTelemetry } from "@microsoft/opentelemetry";

useMicrosoftOpenTelemetry({
  a365: {
    enabled: true,
    tokenResolver: (agentId, tenantId) => getToken(agentId, tenantId),
  },
});

When you enable the A365 HTTP exporter, durable delivery is enabled by default. Tune the durable store if you need a protected persistent volume or different bounds:

useMicrosoftOpenTelemetry({
  a365: {
    enabled: true,
    enableObservabilityExporter: true,
    tokenResolver: (agentId, tenantId, authScopes) => getToken(agentId, tenantId, authScopes),
    durableDelivery: {
      storageDirectory: process.env.A365_DURABLE_STORAGE_DIRECTORY,
      maxStorageBytes: 50 * 1024 * 1024,
      maxRecordAgeMilliseconds: 2 * 24 * 60 * 60 * 1000,
    },
  },
});

Set durableDelivery.enabled: false to force legacy network-only delivery.

With durable delivery enabled, retryable A365 exporter payloads (including HTTP 401, 408, 429, and 5xx responses) are stored as plaintext local files in a stable per-application partition and replayed with a freshly resolved token plus the exporter's current cluster/domain routing; durable files never store bearer tokens or authoritative route metadata. Delivery is at-least-once, so duplicates are possible. The SDK restricts durable storage to the current user and Administrators on Windows and uses owner-only 0700 directories and 0600 files on POSIX. Use a protected persistent volume if records must survive container or host restarts; ephemeral container storage only survives process restarts and still counts against the container's ephemeral-storage quota. If durable storage permissions cannot be secured, the exporter logs the initialization failure and degrades to network-only delivery; successful and non-retryable live sends still complete, but retryable results that cannot be persisted fail.

For A365 scenarios, scope APIs, baggage, hosting middleware, and official terminology alignment, see A365_DOCUMENTATION.md.

Azure Monitor

import { useMicrosoftOpenTelemetry } from "@microsoft/opentelemetry";

useMicrosoftOpenTelemetry({
  azureMonitor: {
    azureMonitorExporterOptions: {
      connectionString: process.env.APPLICATIONINSIGHTS_CONNECTION_STRING,
    },
  },
});

OTLP only (no Azure Monitor)

import { useMicrosoftOpenTelemetry } from "@microsoft/opentelemetry";

// Set OTEL_EXPORTER_OTLP_ENDPOINT in your environment
useMicrosoftOpenTelemetry();

That's it — traces, metrics, and logs are collected automatically with built-in instrumentations for HTTP, databases, and more.

Configuration

MicrosoftOpenTelemetryOptions

Option Type Default Description
resource Resource auto-detected OpenTelemetry Resource (service name, version, etc.)
samplingRatio number 1.0 Ratio of telemetry items to transmit (0.0–1.0)
tracesPerSecond number 5 Max traces per second. Set to 0 to use samplingRatio instead
instrumentationOptions InstrumentationOptions all enabled Toggle built-in instrumentations (see below)
spanProcessors SpanProcessor[] Additional span processors
logRecordProcessors LogRecordProcessor[] Additional log record processors
metricReaders MetricReader[] Additional metric readers
views ViewOptions[] Metric views
azureMonitor AzureMonitorOpenTelemetryOptions Azure Monitor backend config. When provided, Azure Monitor export is enabled
a365 A365Options A365 observability config
enableConsoleExporters boolean auto Enable console exporters for traces, metrics, and logs
enableSensitiveData boolean false Capture GenAI message content (prompts, completions, tool args/results, system instructions) on LangChain spans. Only enable in trusted, non-production environments

InstrumentationOptions

Most instrumentations use InstrumentationConfig shape ({ enabled?: boolean, ... }).

  • Built-in infra instrumentations (http, azureSdk, mongoDb, mySql, postgreSql, redis, redis4) are enabled by default.
  • Logging instrumentations (bunyan, winston, console) are disabled by default.
  • GenAI instrumentations (openaiAgents, langchain) are enabled by default.
  • When a365.enabled is true, non-GenAI instrumentations (http, azureSdk, DB/cache, and logging) are disabled by default unless explicitly set in instrumentationOptions.

Set enabled: true or enabled: false explicitly for predictable behavior.

Key Type Default Description
http InstrumentationConfig enabled HTTP client/server instrumentation
azureSdk InstrumentationConfig enabled Azure SDK instrumentation
mongoDb InstrumentationConfig enabled MongoDB instrumentation
mySql InstrumentationConfig enabled MySQL instrumentation
postgreSql InstrumentationConfig enabled PostgreSQL instrumentation
redis InstrumentationConfig enabled Redis instrumentation
redis4 InstrumentationConfig enabled Redis 4 instrumentation
bunyan InstrumentationConfig disabled Bunyan log instrumentation
winston InstrumentationConfig disabled Winston log instrumentation
console InstrumentationConfig disabled Console log instrumentation
openaiAgents OpenAIAgentsInstrumentationConfig enabled OpenAI Agents SDK instrumentation (requires @openai/agents)
langchain LangChainInstrumentationConfig enabled LangChain instrumentation (requires @langchain/core)

Turn instrumentations on/off

useMicrosoftOpenTelemetry({
  // Capture GenAI message content on LangChain spans (hidden by default).
  // Only enable in trusted, non-production environments.
  enableSensitiveData: true,
  instrumentationOptions: {
    // Disable specific built-in instrumentations
    http: { enabled: false },
    redis: { enabled: false },

    // Enable GenAI instrumentations
    openaiAgents: {
      enabled: true,
      isContentRecordingEnabled: true,
    },
    langchain: {
      enabled: true,
    },
  },
});

Capturing GenAI message content (enableSensitiveData)

LangChain instrumentation hides sensitive message content, prompts, completions, tool arguments/results, and system instructions, by default. Set the top-level enableSensitiveData: true to record it. Only enable content capture in trusted, non-production environments where capturing message content is intentional.

Disable most built-in auto-instrumentation:

useMicrosoftOpenTelemetry({
  instrumentationOptions: {
    http: { enabled: false },
    azureSdk: { enabled: false },
    azureFunctions: { enabled: false },
    mongoDb: { enabled: false },
    mySql: { enabled: false },
    postgreSql: { enabled: false },
    redis: { enabled: false },
    redis4: { enabled: false },
    bunyan: { enabled: false },
    winston: { enabled: false },
    openaiAgents: { enabled: false },
    langchain: { enabled: false },
  },
});

Console exporters

Use console exporters when validating local telemetry or debugging setup.

useMicrosoftOpenTelemetry({
  enableConsoleExporters: true,
});

Behavior:

  • enableConsoleExporters: true: always enable console exporters (traces, metrics, logs).
  • enableConsoleExporters: false: do not auto-add the standard console exporters.
  • Omitted: console exporters auto-enable only when no other exporter path is active.

azureMonitor options

Option Type Default Description
azureMonitorExporterOptions AzureMonitorExporterOptions Exporter config including connectionString, storageDirectory, disableOfflineStorage
enableLiveMetrics boolean true Enable Live Metrics streaming
enableStandardMetrics boolean true Enable standard metrics collection
enableTraceBasedSamplingForLogs boolean false Enable log sampling based on trace
enablePerformanceCounters boolean true Enable performance counter collection
browserSdkLoaderOptions BrowserSdkLoaderOptions disabled Application Insights browser SDK loader config (enabled, connectionString)

OTLP via environment variables

Set OTEL_EXPORTER_OTLP_ENDPOINT and OTLP export is enabled automatically — no code changes needed. Signal-specific variables (OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, etc.) override the base endpoint.

See the OpenTelemetry OTLP Exporter specification for the full list.

a365 options

Option Type Default Description
enabled boolean false Enable A365 observability. Registers the A365SpanProcessor for baggage/attribute enrichment of downstream exporters (Azure Monitor, OTLP, console). Does not send data to the A365 service on its own — set enableObservabilityExporter for that
enableObservabilityExporter boolean false Enable the A365 HTTP exporter (Agent365Exporter) to send spans to the A365 observability service. Requires enabled: true. Equivalent to ENABLE_A365_OBSERVABILITY_EXPORTER env var
tokenResolver (agentId, tenantId, authScopes?) => string | Promise<string> Token resolver for A365 service authentication. When both this and contextualTokenResolver are set, contextualTokenResolver takes precedence
contextualTokenResolver (context: TokenResolverContext) => string | null | Promise<string | null> Contextual token resolver with rich context including the agentic user ID. Takes precedence over tokenResolver when set
clusterCategory ClusterCategory "prod" Cluster category for endpoint resolution (local, dev, test, preprod, firstrelease, prod, gov, high, dod, mooncake, ex, rx)
domainOverride string Override the A365 observability service domain
authScopes string[] ["api://9b975845-388f-4429-889e-eab1ef63949c/.default"] OAuth scopes for A365 service authentication
observabilityScopeOverride string Single-string scope override (highest precedence). Equivalent to A365_OBSERVABILITY_SCOPES_OVERRIDE env var
logLevel string "none" A365 internal log level: none, info, warn, error, or pipe-separated combination. Overrides A365_OBSERVABILITY_LOG_LEVEL env var
useS2SEndpoint boolean false Use the S2S (service-to-service) endpoint path for export
durableDelivery Agent365DurableDeliveryOptions enabled with defaults Enabled-by-default local store-and-replay for retryable A365 HTTP export requests when the A365 HTTP exporter is active. Set durableDelivery.enabled: false to force network-only delivery. Replays use fresh tokens/current routing, records stay in bounded plaintext local storage, and storage-init failures degrade to network-only delivery

When A365 export is enabled, Microsoft OpenTelemetry defaults to GenAI-focused telemetry. To opt back into non-GenAI auto-instrumentation, set explicit overrides:

useMicrosoftOpenTelemetry({
  a365: {
    enabled: true,
    tokenResolver: (agentId, tenantId) => getToken(agentId, tenantId),
  },
  instrumentationOptions: {
    http: { enabled: true },
    azureSdk: { enabled: true },
    mongoDb: { enabled: true },
    mySql: { enabled: true },
    postgreSql: { enabled: true },
    redis: { enabled: true },
    redis4: { enabled: true },
    bunyan: { enabled: true },
    winston: { enabled: true },
  },
});

A365 hosting middleware setup

Hosting middleware is configured separately from a365 exporter options. To use A365 hosting middleware, attach it to your adapter explicitly.

Use the one-liner helper:

import { configureA365Hosting } from "@microsoft/opentelemetry";

configureA365Hosting(adapter);

By default this registers both BaggageMiddleware and OutputLoggingMiddleware.

OutputLoggingMiddleware captures outgoing message content as span attributes. If your responses may contain sensitive content, disable output logging:

configureA365Hosting(adapter, {
  enableBaggage: true,
  enableOutputLogging: false,
});

If you need explicit flags:

configureA365Hosting(adapter, {
  enableBaggage: true,
  enableOutputLogging: true,
});

For previously published package versions that do not include configureA365Hosting, use:

import { ObservabilityHostingManager } from "@microsoft/opentelemetry";

new ObservabilityHostingManager().configure(adapter as unknown as { use(...m: unknown[]): void }, {
  enableBaggage: true,
  enableOutputLogging: true,
});

A365 exporter tuning

Option Type Default Description
maxQueueSize number 2048 Maximum span queue size before drops occur
scheduledDelayMilliseconds number 5000 Delay (ms) between automatic batch flush attempts
exporterTimeoutMilliseconds number 90000 Maximum time (ms) for the entire export call
httpRequestTimeoutMilliseconds number 30000 HTTP request timeout (ms) when sending spans to A365 service
maxExportBatchSize number 512 Maximum number of spans per export batch
maxPayloadBytes number 900 * 1024 Maximum estimated payload size (bytes) per HTTP chunk

A365 durable delivery

Durable delivery applies only to the A365 HTTP exporter, so set both a365.enabled: true and a365.enableObservabilityExporter: true when you use it. Durable delivery is enabled by default; set durableDelivery.enabled: false to force legacy network-only delivery.

Option Type Default Description
enabled boolean true Durable delivery stays on unless you explicitly disable it
storageDirectory string auto Root directory for durable records. When omitted, the SDK probes LOCALAPPDATA, then TEMP, then os.tmpdir() on Windows and appends Microsoft/A365/otel-durable; on POSIX it probes TMPDIR, then /var/tmp, then /tmp and uses the single a365-otel-durable-<uid> leaf. Every base root then gets a stable per-application app-<hash> child
maxStorageBytes number 50 * 1024 * 1024 Maximum total bytes retained for pending and quarantined durable records
maxRecordAgeMilliseconds number 2 * 24 * 60 * 60 * 1000 Maximum record age before expiry pruning
replayIntervalMilliseconds number 2 * 60 * 1000 Delay between scheduled replay passes
maxReplayBatchSize number 10 Maximum records claimed per replay pass
leaseDurationMilliseconds number 2 * 60 * 1000 How long a claimed replay lease stays active before recovery
shutdownTimeoutMilliseconds number 10_000 Shared graceful-shutdown budget for accepted live exports and admitted durable handoff completion
tokenResolutionTimeoutMilliseconds number 30_000 Timeout for each replay token-resolution attempt

Operational notes:

  • Durable records are stored as plaintext JSON files. On POSIX, the SDK creates owner-only durable directories/files (0700 / 0600). On Windows, the SDK removes inherited ACLs and grants full control only to the current Windows identity and built-in Administrators. ACL hardening failures cause durable storage initialization to fail and the exporter to use network-only delivery.
  • Durable delivery is enabled by default when the A365 HTTP exporter is active. Set durableDelivery.enabled: false to force legacy network-only delivery.
  • Durable delivery is at-least-once. If a retryable request succeeds immediately before a crash or after replay, duplicates are possible and receivers must be idempotent.
  • Every replay attempt and forceFlush() pass resolves a fresh token and uses the exporter's current cluster/domain routing; durable files do not store bearer tokens or authoritative route metadata.
  • If durable storage cannot initialize, the exporter logs the error and continues in network-only mode. Successful and non-retryable live sends still complete, but retryable results that cannot be persisted are reported as failures.
  • If token resolution returns no token, throws, or times out, live delivery attempts to persist the record for replay and replay releases the claim without extending the shared transmission backoff.
  • Storage is bounded by both maxStorageBytes and maxRecordAgeMilliseconds; expired records are pruned first, then the oldest retained records are evicted until the new record fits.
  • Live delivery and replay share the same Retry-After / exponential-backoff transmission gate, so a retryable response (401, 408, 429, or 5xx) pauses both immediate sends and replay probes until the gate reopens.
  • If you run in containers and need records to survive container restarts, rescheduling, or host restarts outside the current container filesystem, set storageDirectory to a protected persistent volume and size maxStorageBytes within your platform's storage quota.
  • During shutdownMicrosoftOpenTelemetry(), the exporter first waits up to shutdownTimeoutMilliseconds for already accepted live exports to settle. When durable delivery is enabled, it also stops replay scheduling immediately, aborts in-flight durable HTTP, and uses the same deadline for already admitted durable handoff completion. Retryable aborted payloads stay on disk for replay on the next process or startup pass; shutdown does not drain the existing spool. If you use Agent365Exporter directly, you may call forceFlush() before shutdown for one bounded replay pass. The distro shutdown path does not call exporter.forceFlush(). When durable delivery is disabled—or durable storage never initialized and the exporter stayed network-only—shutdown still drains accepted live exports but does not replay or persist anything.

Example:

useMicrosoftOpenTelemetry({
  a365: {
    enabled: true,
    enableObservabilityExporter: true,
    tokenResolver: (agentId, tenantId, authScopes) => getToken(agentId, tenantId, authScopes),
    maxQueueSize: 4096,
    maxExportBatchSize: 1024,
    scheduledDelayMilliseconds: 10000,
    httpRequestTimeoutMilliseconds: 15000,
    durableDelivery: {
      storageDirectory: process.env.A365_DURABLE_STORAGE_DIRECTORY,
      maxStorageBytes: 50 * 1024 * 1024,
      maxRecordAgeMilliseconds: 2 * 24 * 60 * 60 * 1000,
    },
  },
});

A365 environment variables

A365 also reads the following environment overrides:

Environment Variable Description
ENABLE_A365_OBSERVABILITY_EXPORTER "true" / "false" — secondary toggle for the A365 HTTP exporter when a365 options are provided in code; it does not enable a365.enabled on its own
A365_OBSERVABILITY_SCOPES_OVERRIDE Space-separated list of OAuth scopes
A365_OBSERVABILITY_DOMAIN_OVERRIDE Override service domain
CLUSTER_CATEGORY Override cluster category
A365_OBSERVABILITY_LOG_LEVEL A365 internal logger filter level (none, info, warn, error, or pipe-delimited combination) — overrides observabilityLogLevel
A365_PER_REQUEST_MAX_TRACES Max buffered traces (default: 1000)
A365_PER_REQUEST_MAX_SPANS_PER_TRACE Max spans per trace (default: 5000)
A365_PER_REQUEST_MAX_CONCURRENT_EXPORTS Max concurrent exports (default: 20)
A365_PER_REQUEST_FLUSH_GRACE_MS Grace period after root span ends (default: 250)
A365_PER_REQUEST_MAX_TRACE_AGE_MS Max trace age before forced flush (default: 1800000)
A365_OBSERVABILITY_TOKEN_EXCHANGE_TIMEOUT_MS Per-attempt timeout (ms) for agentic token exchange; 0 or negative disables (default: 30000)

Example

import {
  useMicrosoftOpenTelemetry,
  shutdownMicrosoftOpenTelemetry,
} from "@microsoft/opentelemetry";
import { resourceFromAttributes } from "@opentelemetry/resources";

useMicrosoftOpenTelemetry({
  resource: resourceFromAttributes({ "service.name": "my-app" }),
  samplingRatio: 0.5,
  azureMonitor: {
    azureMonitorExporterOptions: {
      connectionString: process.env.APPLICATIONINSIGHTS_CONNECTION_STRING,
    },
  },
});

// On shutdown
await shutdownMicrosoftOpenTelemetry();

Guides

  • Fabric Getting Started — Send telemetry to Microsoft Fabric / Azure Data Explorer via OTLP + OTel Collector

Samples

See the samples/ directory for working TypeScript examples covering connection setup, custom metrics, custom traces, sampling, OTLP dual-export, and more.

Contributing

See CONTRIBUTING.md.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

Data Collection

As this SDK is designed to enable applications to perform data collection which is sent to the Microsoft collection endpoints the following is required to identify our privacy statement.

The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the repository. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices.

Internal Telemetry

Internal telemetry can be disabled by setting the environment variable APPLICATIONINSIGHTS_STATSBEAT_DISABLED to true.

Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft’s Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party’s policies.

Reporting Security Issues

See SECURITY.md for information on reporting vulnerabilities.

License

MIT

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages