# [[Declarative Configuration for OTel SDKs]] ![[Declarative Configuration for OTel.svg]] [[Declarative]] configuration for [[OpenTelemetry]] is a new approach to [[Instrumentation]] that uses a [[YAML]]/[[JSON]] file or [[Environment variables]] to define things like: - how you initialize the OTel [[SDK]] - instrumentation libraries to use - exporters and propagators - resource attributes and anything else that might otherwise be set in the code for the purposes of *configuring* the instrumentation/implementation. ## Example ### Without declarative config Without using declarative config, here's what a typical OTel implementation might look like in [[Java]]: ```java import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.SdkTracerProvider; import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; public class App { public static void main(String[] args) { // 👇 Imperative setup: creating all components manually // 1. Define service name and resource attributes Resource resource = Resource.getDefault() .merge(Resource.builder() .put("service.name", "payment-service") .put("service.environment", "production") .build()); // 2. Create the exporter OtlpGrpcSpanExporter exporter = OtlpGrpcSpanExporter.builder() .setEndpoint("https://otel-collector:4317") .addHeader("x-api-key", System.getenv("OTEL_API_KEY")) .build(); // 3. Configure the processor BatchSpanProcessor processor = BatchSpanProcessor.builder(exporter) .setScheduleDelay(java.time.Duration.ofMillis(5000)) .build(); // 4. Build the tracer provider SdkTracerProvider tracerProvider = SdkTracerProvider.builder() .setResource(resource) .addSpanProcessor(processor) .build(); // 5. Initialize the global OpenTelemetry instance OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() .setTracerProvider(tracerProvider) .buildAndRegisterGlobal(); // 👇 Your instrumentation (manual or auto) uses this tracer Tracer tracer = openTelemetry.getTracer("io.example.payment"); tracer.spanBuilder("checkout").startSpan().end(); } } ``` Note that the code includes both instrumentation and configuration. In fact, most of that is configuration. Only the `Tracer tracer = openTelemetry.getTracer(...)` part is actual instrumentation. ### With declarative configuration Declarative configuration can replace everything but the actual instrumentation lines. You'd have the following in something like `otel-config.yaml`: ```yaml resource: service.name: payment-service service.environment: production traces: sampler: type: parentbased_traceidratio argument: 0.5 processor: type: batch schedule_delay: 5000 exporter: type: otlp protocol: grpc endpoint: https://otel-collector:4317 headers: x-api-key: ${OTEL_API_KEY} ``` and then just have this in your code for the instrumentation: ```java import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; public class App { public static void main(String[] args) { // 👇 Declarative setup: automatically loads from environment / YAML OpenTelemetry openTelemetry = AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk(); // Only need to obtain and use a tracer now Tracer tracer = openTelemetry.getTracer("io.example.payment"); tracer.spanBuilder("checkout").startSpan().end(); } } ``` OR, instead of instrumenting the code manually, [[OTel Autoconfigure]] can be used to accomplish the same thing: ``` java -Dotel.config.file=otel-config.yaml \ -javaagent:opentelemetry-javaagent.jar \ -jar app.jar ``` ## Availability per language Declarative configuration in SDKs is new and only available for the following languages: | Language | Status of Support | | -------- | ----------------- | | [[Java]] | Experimental | | [[PHP]] | Experimental | %% # Excalidraw Data ## Text Elements ## Drawing ```json { "type": "excalidraw", "version": 2, "source": "https://github.com/zsviczian/obsidian-excalidraw-plugin/releases/tag/2.1.4", "elements": [ { "id": "4y8R7iOA", "type": "text", "x": 118.49495565891266, "y": -333.44393157958984, "width": 3.8599853515625, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", "fillStyle": "solid", "strokeWidth": 2, "strokeStyle": "solid", "roughness": 1, "opacity": 100, "groupIds": [], "frameId": null, "roundness": null, "seed": 967149026, "version": 2, "versionNonce": 939059582, "isDeleted": true, "boundElements": null, "updated": 1713723615080, "link": null, "locked": false, "text": "", "rawText": "", "fontSize": 20, "fontFamily": 4, "textAlign": "left", "verticalAlign": "top", "containerId": null, "originalText": "", "lineHeight": 1.2 } ], "appState": { "theme": "dark", "viewBackgroundColor": "#ffffff", "currentItemStrokeColor": "#1e1e1e", "currentItemBackgroundColor": "transparent", "currentItemFillStyle": "solid", "currentItemStrokeWidth": 2, "currentItemStrokeStyle": "solid", "currentItemRoughness": 1, "currentItemOpacity": 100, "currentItemFontFamily": 4, "currentItemFontSize": 20, "currentItemTextAlign": "left", "currentItemStartArrowhead": null, "currentItemEndArrowhead": "arrow", "scrollX": 583.2388916015625, "scrollY": 573.6323852539062, "zoom": { "value": 1 }, "currentItemRoundness": "round", "gridSize": null, "gridColor": { "Bold": "#C9C9C9FF", "Regular": "#EDEDEDFF" }, "currentStrokeOptions": null, "previousGridSize": null, "frameRendering": { "enabled": true, "clip": true, "name": true, "outline": true } }, "files": {} } ``` %%