diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index 2b0a86c77b9..5e3fb24e885 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -57,6 +57,7 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2 ### :books: Documentation +* docs(configuration): add declarative config example (`experimental/examples/declarative-config/`) [#6807](https://github.com/open-telemetry/opentelemetry-js/issues/6807) @MikeGoldsmith * docs(configuration): link the configuration README to the cross-SDK declarative config language support status doc [#6809](https://github.com/open-telemetry/opentelemetry-js/issues/6809) @MikeGoldsmith ### :house: Internal diff --git a/experimental/examples/README.md b/experimental/examples/README.md index f582ec6f760..92bbe7296b1 100644 --- a/experimental/examples/README.md +++ b/experimental/examples/README.md @@ -6,9 +6,10 @@ This directory contains examples of how to run real applications with OpenTeleme These examples are using work in progress metrics packages. -| Name | Description | Complexity Level | -| ------------------------- | -------------------------------------------------------------------------------- | ---------------- | -| [prometheus](prometheus/) | Basic Metric use with Prometheus (`@opentelemetry/exporter-prometheus`) Exporter | Beginner | +| Name | Description | Complexity Level | +| ----------------------------------------- | ----------------------------------------------------------------------------------------------- | ---------------- | +| [declarative-config](declarative-config/) | End-to-end traces/metrics/logs over OTLP HTTP, configured from a YAML file via `startNodeSDK()` | Beginner | +| [prometheus](prometheus/) | Basic Metric use with Prometheus (`@opentelemetry/exporter-prometheus`) Exporter | Beginner | ## Contributing diff --git a/experimental/examples/declarative-config/README.md b/experimental/examples/declarative-config/README.md new file mode 100644 index 00000000000..abee94bf020 --- /dev/null +++ b/experimental/examples/declarative-config/README.md @@ -0,0 +1,48 @@ +# Declarative Configuration Example + +End-to-end example of configuring the Node SDK from a YAML file via +`OTEL_CONFIG_FILE` and `startNodeSDK()`. No programmatic provider construction: +the YAML drives traces, metrics, logs, resource attributes, propagators, and +the sampler. + +## What this demonstrates + +- A single `otel-config.yaml` covering traces, metrics, and logs over OTLP HTTP. +- Environment variable substitution (`${OTEL_EXPORTER_OTLP_ENDPOINT:-...}`, + `${EXAMPLE_API_KEY:-}`) so secrets and per-environment values stay out of the + YAML. +- A `parent_based` sampler config. + +See [`../../packages/configuration/README.md`](../../packages/configuration/README.md) +for the full list of supported fields and current limitations. + +## Run it + +The example exports to any OTLP HTTP endpoint. The simplest path is the bundled +collector that prints what it receives. + +```sh +# 1. Start a collector locally (OTLP HTTP receiver on :4318, debug exporter) +docker compose up -d + +# 2. Install deps + start the example +npm install +npm start +``` + +You should see span, metric, and log entries in the collector's container logs: + +```sh +docker compose logs -f otel-collector +``` + +To export to your own backend instead, set `OTEL_EXPORTER_OTLP_ENDPOINT` and +(optionally) `EXAMPLE_API_KEY`: + +```sh +OTEL_EXPORTER_OTLP_ENDPOINT=https://vendor.endpoint \ +EXAMPLE_API_KEY=$VENDOR_API_KEY \ +npm start +``` + +Tear down the collector with `docker compose down`. diff --git a/experimental/examples/declarative-config/docker-compose.yaml b/experimental/examples/declarative-config/docker-compose.yaml new file mode 100644 index 00000000000..dbd4874f259 --- /dev/null +++ b/experimental/examples/declarative-config/docker-compose.yaml @@ -0,0 +1,9 @@ +services: + otel-collector: + image: otel/opentelemetry-collector-contrib:latest + command: ["--config=/etc/otel-collector-config.yaml"] + volumes: + - "./otel-collector-config.yaml:/etc/otel-collector-config.yaml" + ports: + - "4318:4318" # OTLP HTTP + restart: unless-stopped diff --git a/experimental/examples/declarative-config/index.ts b/experimental/examples/declarative-config/index.ts new file mode 100644 index 00000000000..d85cfdcf708 --- /dev/null +++ b/experimental/examples/declarative-config/index.ts @@ -0,0 +1,41 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { trace, metrics } from '@opentelemetry/api'; +import { logs, SeverityNumber } from '@opentelemetry/api-logs'; +import { startNodeSDK } from '@opentelemetry/sdk-node'; + +// `startNodeSDK()` reads OTEL_CONFIG_FILE (set in package.json's start script) +// and wires up trace, metric, and log pipelines from the YAML. No programmatic +// provider construction needed. +const sdk = startNodeSDK(); + +const tracer = trace.getTracer('example'); +const meter = metrics.getMeter('example'); +const logger = logs.getLogger('example'); + +const counter = meter.createCounter('example.requests', { + description: 'Demo counter incremented per request', +}); + +async function main(): Promise { + await tracer.startActiveSpan('example.request', async span => { + span.setAttribute('example.kind', 'demo'); + counter.add(1, { route: '/hello' }); + logger.emit({ + severityNumber: SeverityNumber.INFO, + body: 'Handled example request', + attributes: { route: '/hello' }, + }); + span.end(); + }); + + await sdk.shutdown(); +} + +main().catch(err => { + console.error(err); + process.exit(1); +}); diff --git a/experimental/examples/declarative-config/otel-collector-config.yaml b/experimental/examples/declarative-config/otel-collector-config.yaml new file mode 100644 index 00000000000..f45bba5dd6c --- /dev/null +++ b/experimental/examples/declarative-config/otel-collector-config.yaml @@ -0,0 +1,21 @@ +receivers: + otlp: + protocols: + http: + endpoint: 0.0.0.0:4318 + +exporters: + debug: + verbosity: detailed + +service: + pipelines: + traces: + receivers: [otlp] + exporters: [debug] + metrics: + receivers: [otlp] + exporters: [debug] + logs: + receivers: [otlp] + exporters: [debug] diff --git a/experimental/examples/declarative-config/otel-config.yaml b/experimental/examples/declarative-config/otel-config.yaml new file mode 100644 index 00000000000..b9778edb45a --- /dev/null +++ b/experimental/examples/declarative-config/otel-config.yaml @@ -0,0 +1,58 @@ +file_format: "1.1" + +disabled: ${OTEL_SDK_DISABLED:-false} +log_level: info + +resource: + attributes: + - name: service.name + value: declarative-config-example + - name: service.version + value: "0.1.0" + - name: deployment.environment.name + value: ${DEPLOYMENT_ENV:-development} + +# Configure the W3C propagators explicitly. tracecontext and baggage match the +# spec default, but the propagator block must be present for any to be applied. +propagator: + composite: + - tracecontext: + - baggage: + +tracer_provider: + processors: + - batch: + exporter: + otlp_http: + endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4318}/v1/traces + # Headers support env var substitution so secrets don't live in the YAML. + headers: + - name: x-example-api-key + value: ${EXAMPLE_API_KEY:-} + compression: gzip + timeout: 10000 + sampler: + parent_based: + root: + trace_id_ratio_based: + ratio: 1.0 + +meter_provider: + readers: + - periodic: + interval: 10000 + timeout: 5000 + exporter: + otlp_http: + endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4318}/v1/metrics + compression: gzip + timeout: 10000 + +logger_provider: + processors: + - batch: + exporter: + otlp_http: + endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4318}/v1/logs + compression: gzip + timeout: 10000 diff --git a/experimental/examples/declarative-config/package.json b/experimental/examples/declarative-config/package.json new file mode 100644 index 00000000000..19581751551 --- /dev/null +++ b/experimental/examples/declarative-config/package.json @@ -0,0 +1,23 @@ +{ + "name": "declarative-config-example", + "version": "0.220.0", + "private": true, + "description": "Example of configuring the Node SDK from a YAML file via OTEL_CONFIG_FILE + startNodeSDK()", + "main": "index.ts", + "scripts": { + "start": "OTEL_CONFIG_FILE=./otel-config.yaml ts-node index.ts", + "align-api-deps": "node ../../../scripts/align-api-deps.js" + }, + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.7.0", + "@opentelemetry/api-logs": "0.220.0", + "@opentelemetry/configuration": "0.220.0", + "@opentelemetry/sdk-node": "0.220.0" + }, + "devDependencies": { + "@types/node": "18.19.130", + "ts-node": "^10.9.1" + } +} diff --git a/experimental/examples/declarative-config/tsconfig.json b/experimental/examples/declarative-config/tsconfig.json new file mode 100644 index 00000000000..af86374efe7 --- /dev/null +++ b/experimental/examples/declarative-config/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "build", + "rootDir": "." + }, + "include": ["./index.ts"], + "references": [ + { + "path": "../../../api" + }, + { + "path": "../../../experimental/packages/api-logs" + }, + { + "path": "../../../experimental/packages/configuration" + }, + { + "path": "../../../experimental/packages/opentelemetry-sdk-node" + } + ] +} diff --git a/package-lock.json b/package-lock.json index 96d2a3df2be..a57c06a503d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1161,6 +1161,21 @@ "node": "^18.19.0 || >=20.6.0" } }, + "experimental/examples/declarative-config": { + "name": "declarative-config-example", + "version": "0.220.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.7.0", + "@opentelemetry/api-logs": "0.220.0", + "@opentelemetry/configuration": "0.220.0", + "@opentelemetry/sdk-node": "0.220.0" + }, + "devDependencies": { + "@types/node": "18.19.130", + "ts-node": "^10.9.1" + } + }, "experimental/examples/logs": { "name": "logs-example", "version": "0.211.0", @@ -10926,6 +10941,10 @@ "node": ">=0.10.0" } }, + "node_modules/declarative-config-example": { + "resolved": "experimental/examples/declarative-config", + "link": true + }, "node_modules/decode-named-character-reference": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz",