From b5214eadb779cddc2fdeb30f179fbed9524b12dd Mon Sep 17 00:00:00 2001 From: Brian Marks Date: Wed, 26 Aug 2026 21:04:37 -0400 Subject: [PATCH 1/3] Document OTel metrics lifecycle methods --- .../instrument/dd_sdks/api_support.mdoc.md | 52 ++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/hugo/content/en/opentelemetry/instrument/dd_sdks/api_support.mdoc.md b/hugo/content/en/opentelemetry/instrument/dd_sdks/api_support.mdoc.md index 88c3c793f8a..7760e370504 100644 --- a/hugo/content/en/opentelemetry/instrument/dd_sdks/api_support.mdoc.md +++ b/hugo/content/en/opentelemetry/instrument/dd_sdks/api_support.mdoc.md @@ -138,7 +138,7 @@ This approach works with the existing OpenTelemetry SDK. When you enable this fe - **Datadog SDK**: dd-trace-dotnet version 3.30.0 or later. {% /if %} {% if equals($prog_lang, "node_js") %} -- **Datadog SDK**: `dd-trace-js` version 5.81.0 or later. +- **Datadog SDK**: `dd-trace-js` version 7.0.0 or later for metrics life cycle methods. Basic OTel Metrics API support requires version 5.81.0 or later. - **OpenTelemetry API**: `@opentelemetry/api` version 1.0.0 to 1.10.0. (The Datadog SDK provides the implementation for this API). {% /if %} {% if equals($prog_lang, "python") %} @@ -163,7 +163,7 @@ The OpenTelemetry Metrics SDK for Ruby is currently in [alpha implementation](ht - **Rust**: MSRV 1.84 or later. {% /if %} {% if equals($prog_lang, "java") %} -- **Datadog SDK**: `dd-trace-java` version 1.61.0 or later. +- **Datadog SDK**: `dd-trace-java` version 1.66.0 or later for metrics life cycle methods. Basic OTel Metrics API support requires version 1.61.0 or later. {% /if %} - **An OTLP-compatible destination**: You must have a destination (Agent or Collector) listening on ports 4317 (gRPC) or 4318 (HTTP) to receive OTel metrics. {% if includes($prog_lang, ["dot_net", "node_js", "python", "ruby", "go", "java"]) %} @@ -493,6 +493,54 @@ counter.add(1, Attributes.builder().put("method", "GET").put("status_code", "200 ``` {% /if %} +{% if includes($prog_lang, ["node_js", "python", "java"]) %} + +### Flush metrics in short-lived processes + +Metrics are normally exported on a schedule. Before a short-lived process exits, call `forceFlush` to wait for metrics recorded so far. Call `shutdown` to perform a final export and stop the metric provider. + +{% if equals($prog_lang, "node_js") %} +Set `OTEL_EXPORTER_OTLP_METRICS_TIMEOUT` to bound each export. The value is in milliseconds. + +```javascript +const meterProvider = metrics.getMeterProvider(); + +await meterProvider.forceFlush(); +await meterProvider.shutdown(); +``` + +For TypeScript, cast the provider to the Datadog implementation type: + +```typescript +import type { opentelemetry as DatadogOpenTelemetry } from 'dd-trace'; + +const meterProvider = metrics.getMeterProvider() as DatadogOpenTelemetry.MeterProvider; +``` +{% /if %} + +{% if equals($prog_lang, "python") %} +```python +meter_provider = metrics.get_meter_provider() + +if not meter_provider.force_flush(timeout_millis=10_000): + raise RuntimeError("metric export timed out") + +meter_provider.shutdown(timeout_millis=10_000) +``` +{% /if %} + +{% if equals($prog_lang, "java") %} +```java +import datadog.trace.api.metrics.OpenTelemetryMetrics; +import java.util.concurrent.TimeUnit; + +boolean exported = OpenTelemetryMetrics.forceFlush().get(10, TimeUnit.SECONDS); +boolean finalExport = OpenTelemetryMetrics.shutdown().get(10, TimeUnit.SECONDS); +``` +{% /if %} + +{% /if %} + ### Create a histogram This example uses the OTel Metrics API to create a histogram to track request durations: From 9d07a8f479e0e4f033c9af563a8777b16a26f1b6 Mon Sep 17 00:00:00 2001 From: Munir Abdinur Date: Tue, 1 Sep 2026 16:07:18 -0400 Subject: [PATCH 2/3] Clarify OTel metrics lifecycle methods --- .../instrument/dd_sdks/api_support.mdoc.md | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/hugo/content/en/opentelemetry/instrument/dd_sdks/api_support.mdoc.md b/hugo/content/en/opentelemetry/instrument/dd_sdks/api_support.mdoc.md index 7760e370504..31287ff2081 100644 --- a/hugo/content/en/opentelemetry/instrument/dd_sdks/api_support.mdoc.md +++ b/hugo/content/en/opentelemetry/instrument/dd_sdks/api_support.mdoc.md @@ -497,16 +497,18 @@ counter.add(1, Attributes.builder().put("method", "GET").put("status_code", "200 ### Flush metrics in short-lived processes -Metrics are normally exported on a schedule. Before a short-lived process exits, call `forceFlush` to wait for metrics recorded so far. Call `shutdown` to perform a final export and stop the metric provider. +Metrics are normally exported on a schedule. `ForceFlush` and `Shutdown` are OpenTelemetry Metrics SDK life cycle operations, not Metrics API methods. Python exposes these operations through the OpenTelemetry SDK. The Datadog SDKs for Node.js and Java provide equivalent extensions. + +Before a short-lived process exits, call `forceFlush` to wait for metrics recorded so far. After recording is complete, call `shutdown` once to perform a final export and stop metrics export. Don't record more metrics after shutdown. {% if equals($prog_lang, "node_js") %} -Set `OTEL_EXPORTER_OTLP_METRICS_TIMEOUT` to bound each export. The value is in milliseconds. +Pass `timeoutMillis` to bound the operation. If the timeout expires, the Promise rejects, but queued export or shutdown work can continue. `OTEL_EXPORTER_OTLP_METRICS_TIMEOUT` is separate and bounds each OTLP HTTP request. Both values are in milliseconds. ```javascript const meterProvider = metrics.getMeterProvider(); -await meterProvider.forceFlush(); -await meterProvider.shutdown(); +await meterProvider.forceFlush({ timeoutMillis: 10_000 }); +await meterProvider.shutdown({ timeoutMillis: 10_000 }); ``` For TypeScript, cast the provider to the Datadog implementation type: @@ -523,10 +525,12 @@ const meterProvider = metrics.getMeterProvider() as DatadogOpenTelemetry.MeterPr meter_provider = metrics.get_meter_provider() if not meter_provider.force_flush(timeout_millis=10_000): - raise RuntimeError("metric export timed out") + raise RuntimeError("metric export failed or timed out") meter_provider.shutdown(timeout_millis=10_000) ``` + +`force_flush` returns `True` on success. Either operation can fail with an exception if a metric reader fails or its deadline expires. `shutdown` succeeds without a return value. {% /if %} {% if equals($prog_lang, "java") %} @@ -536,7 +540,13 @@ import java.util.concurrent.TimeUnit; boolean exported = OpenTelemetryMetrics.forceFlush().get(10, TimeUnit.SECONDS); boolean finalExport = OpenTelemetryMetrics.shutdown().get(10, TimeUnit.SECONDS); + +if (!exported || !finalExport) { + throw new IllegalStateException("Metric export failed or is unavailable"); +} ``` + +These methods are Datadog extensions and don't use or shut down an OpenTelemetry `SdkMeterProvider`. `shutdown()` performs a final export and stops the Datadog metrics export pipeline. A `false` result indicates that the operation failed or metrics export is unavailable. `get` can throw `TimeoutException`; its timeout bounds the caller's wait without cancelling the operation. {% /if %} {% /if %} From e484fd2bad0312048e485cc5d75f19c2672eab64 Mon Sep 17 00:00:00 2001 From: Munir Abdinur Date: Tue, 8 Sep 2026 15:21:18 -0400 Subject: [PATCH 3/3] Document OTel metrics shutdown --- .../instrument/dd_sdks/api_support.mdoc.md | 42 ++++++++----------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/hugo/content/en/opentelemetry/instrument/dd_sdks/api_support.mdoc.md b/hugo/content/en/opentelemetry/instrument/dd_sdks/api_support.mdoc.md index 8451bd98ad9..2f53b2c3414 100644 --- a/hugo/content/en/opentelemetry/instrument/dd_sdks/api_support.mdoc.md +++ b/hugo/content/en/opentelemetry/instrument/dd_sdks/api_support.mdoc.md @@ -138,7 +138,7 @@ This approach works with the existing OpenTelemetry SDK. When you enable this fe - **Datadog SDK**: dd-trace-dotnet version 3.30.0 or later. {% /if %} {% if equals($prog_lang, "node_js") %} -- **Datadog SDK**: `dd-trace-js` version 7.0.0 or later for metrics life cycle methods. Basic OTel Metrics API support requires version 5.81.0 or later. +- **Datadog SDK**: `dd-trace-js` version 7.0.0 or later for metrics shutdown. Basic OTel Metrics API support requires version 5.81.0 or later. - **OpenTelemetry API**: `@opentelemetry/api` version 1.0.0 to 1.10.0. (The Datadog SDK provides the implementation for this API). {% /if %} {% if equals($prog_lang, "python") %} @@ -163,7 +163,7 @@ The OpenTelemetry Metrics SDK for Ruby is currently in [alpha implementation](ht - **Rust**: MSRV 1.84 or later. {% /if %} {% if equals($prog_lang, "java") %} -- **Datadog SDK**: `dd-trace-java` version 1.66.0 or later for metrics life cycle methods. Basic OTel Metrics API support requires version 1.61.0 or later. +- **Datadog SDK**: `dd-trace-java` version 1.66.0 or later for metrics shutdown. Basic OTel Metrics API support requires version 1.61.0 or later. {% /if %} - **An OTLP-compatible destination**: You must have a destination (Agent or Collector) listening on ports 4317 (gRPC) or 4318 (HTTP) to receive OTel metrics. {% if includes($prog_lang, ["dot_net", "node_js", "python", "ruby", "go", "java"]) %} @@ -495,26 +495,20 @@ counter.add(1, Attributes.builder().put("method", "GET").put("status_code", "200 {% if includes($prog_lang, ["node_js", "python", "java"]) %} -### Flush metrics in short-lived processes +### Shut down metrics in short-lived processes -Metrics are normally exported on a schedule. `ForceFlush` and `Shutdown` are OpenTelemetry Metrics SDK life cycle operations, not Metrics API methods. Python exposes these operations through the OpenTelemetry SDK. The Datadog SDKs for Node.js and Java provide equivalent extensions. +Metrics are normally exported on a schedule. `Shutdown` is an OpenTelemetry Metrics SDK life cycle operation, not a Metrics API method. Python exposes this operation through the OpenTelemetry SDK. The Datadog SDKs for Node.js and Java provide equivalent extensions. -Before a short-lived process exits, call `forceFlush` to wait for metrics recorded so far. After recording is complete, call `shutdown` once to perform a final export and stop metrics export. Don't record more metrics after shutdown. +After recording is complete, call `shutdown` once to perform a final export and stop metrics export. Don't record more metrics after shutdown. {% if equals($prog_lang, "node_js") %} -The completion callback receives an error if the operation fails. `OTEL_EXPORTER_OTLP_METRICS_TIMEOUT` bounds each OTLP HTTP request in milliseconds. +The completion callback receives `null` on success or an error on failure. `OTEL_EXPORTER_OTLP_METRICS_TIMEOUT` bounds each OTLP HTTP request in milliseconds. ```javascript const meterProvider = metrics.getMeterProvider(); -meterProvider.forceFlush((error) => { - if (error) { - console.error('Failed to flush metrics', error); - return; - } - meterProvider.shutdown((error) => { - if (error) console.error('Failed to shut down metrics', error); - }); +meterProvider.shutdown((error) => { + if (error) console.error('Failed to shut down metrics', error); }); ``` @@ -523,7 +517,8 @@ For TypeScript, cast the provider to the Datadog implementation type: ```typescript import type { opentelemetry as DatadogOpenTelemetry } from 'dd-trace'; -const meterProvider = metrics.getMeterProvider() as DatadogOpenTelemetry.MeterProvider; +const meterProvider = metrics.getMeterProvider() as ReturnType & + DatadogOpenTelemetry.MeterProvider; ``` {% /if %} @@ -531,29 +526,28 @@ const meterProvider = metrics.getMeterProvider() as DatadogOpenTelemetry.MeterPr ```python meter_provider = metrics.get_meter_provider() -if not meter_provider.force_flush(timeout_millis=10_000): - raise RuntimeError("metric export failed or timed out") - meter_provider.shutdown(timeout_millis=10_000) ``` -`force_flush` returns `True` on success. Either operation can fail with an exception if a metric reader fails or its deadline expires. `shutdown` succeeds without a return value. +`shutdown` succeeds without a return value and can fail with an exception if a metric reader fails or its deadline expires. {% /if %} {% if equals($prog_lang, "java") %} ```java -import datadog.trace.api.metrics.OpenTelemetryMetrics; +import datadog.trace.api.metrics.DatadogMeterProvider; +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.metrics.MeterProvider; import java.util.concurrent.TimeUnit; -boolean exported = OpenTelemetryMetrics.forceFlush().get(10, TimeUnit.SECONDS); -boolean finalExport = OpenTelemetryMetrics.shutdown().get(10, TimeUnit.SECONDS); +MeterProvider meterProvider = GlobalOpenTelemetry.get().getMeterProvider(); +DatadogMeterProvider datadogMeterProvider = (DatadogMeterProvider) meterProvider; -if (!exported || !finalExport) { +if (!datadogMeterProvider.shutdown().join(10, TimeUnit.SECONDS).isSuccess()) { throw new IllegalStateException("Metric export failed or is unavailable"); } ``` -These methods are Datadog extensions and don't use or shut down an OpenTelemetry `SdkMeterProvider`. `shutdown()` performs a final export and stops the Datadog metrics export pipeline. A `false` result indicates that the operation failed or metrics export is unavailable. `get` can throw `TimeoutException`; its timeout bounds the caller's wait without cancelling the operation. +The provider returned from `GlobalOpenTelemetry` implements `DatadogMeterProvider`. `shutdown()` performs a final export and stops the Datadog metrics export pipeline. A result that isn't successful indicates that the operation failed, timed out, or metrics export is unavailable. {% /if %} {% /if %}