Configure telemetry for an integration
Wire an integration host up to OpenTelemetry with the Intropy.Telemetry package, so every run exports its traces, metrics, and logs over OTLP.
Before you begin
Section titled “Before you begin”- Read The Intropy model and The Intropy Framework — the framework emits pipeline and step spans on its own; this guide is about getting them out of the process
- Have an integration project that builds and runs on .NET 10.0 or later
- Have Docker available — the Verify section runs a local telemetry backend in a container
1. Install the package that matches your host
Section titled “1. Install the package that matches your host”Two NuGet packages expose the same configuration surface; pick by how the Component is hosted.
Components that run to completion or drain a queue next to a Dapr sidecar — scaffolded extractors and transactional integrations are the typical cases.
dotnet add package Intropy.Telemetry.ConsoleAppFor Components that serve HTTP — scaffolded loaders, which receive deliveries on a Dapr subscription endpoint, use this one.
dotnet add package Intropy.Telemetry.AspNetCore2. Register OpenTelemetry at startup
Section titled “2. Register OpenTelemetry at startup”A single AddOpenTelemetry call replaces the usual page of provider boilerplate. ServiceName and Environment are required. The service name becomes the service.name resource attribute on every signal — give each integration its own, and keep it stable, because it’s what you’ll filter by in every backend.
using Intropy.Telemetry.ConsoleApp;
var services = new ServiceCollection();
services.AddOpenTelemetry(config =>{ config.ServiceName = "customer-golden-record"; config.ServiceNamespace = "fluxia"; // your organization config.Environment = "Production";});
var serviceProvider = services.BuildServiceProvider();using var telemetryScope = new OpenTelemetryScope(serviceProvider);The OpenTelemetryScope owns the provider lifetime: keep it alive for the whole run, and let its disposal flush any remaining telemetry before the host exits.
using Intropy.Telemetry.AspNetCore;
builder.Services.AddOpenTelemetry(config =>{ config.ServiceName = "customer-api"; config.ServiceNamespace = "fluxia"; // your organization config.Environment = builder.Environment.EnvironmentName;});Requests to /healthz are excluded from tracing by default; set config.FilterHttpRequest if your probe path differs.
That one call configures all three signals:
- Traces — subscribes activity sources matching
Intropy.*(which covers the framework’sIntropy.Framework.Core,.Blocks,.Adapters, and.Hostingsources) plus yourServiceName, and instruments outbound HTTP, SQL Client, and gRPC calls. The framework’sPipeline.<name>,Step.<StepName>, andFinalizer.<FinalizerName>spans are collected with no further registration. - Metrics — HTTP client metrics, plus ASP.NET Core request metrics on that host type.
- Logs — structured
ILoggeroutput exported alongside the traces, correlated with the active span.
3. Point the exporter at a collector
Section titled “3. Point the exporter at a collector”All three signals export over OTLP, configured through the standard OpenTelemetry environment variables:
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317Locally, that’s wherever the collector you test against listens — the Verify section below runs one. In a deployed environment the endpoint is environment configuration, not code — set it per environment alongside the rest of the Component’s deployment config (see the intropy.run observability docs for where the reference stack receives OTLP).
Verify
Section titled “Verify”To check the signals locally, run Grafana’s otel-lgtm image — an OTLP collector in front of the same backends the reference environment runs: Tempo for traces, Prometheus for metrics, Loki for logs, and Grafana on top.
docker run --rm -ti -p 3000:3000 -p 4317:4317 -p 4318:4318 grafana/otel-lgtmPorts 4317 and 4318 receive OTLP over gRPC and HTTP; 3000 serves the Grafana UI (default credentials admin / admin).
With the container running and OTEL_EXPORTER_OTLP_ENDPOINT pointed at it, run the integration once with a message flowing through it, then open Grafana at http://localhost:3000 and use Explore with the Tempo data source:
- A trace appears under your
ServiceName, with aPipeline.<name>root andStep.<StepName>children - Log lines from the run carry the trace’s
trace_id - Outbound HTTP or SQL calls made by your steps show up as child spans
If nothing arrives at all, the endpoint is wrong or unreachable — check OTEL_EXPORTER_OTLP_ENDPOINT from inside the host’s environment, not just your shell. If signals arrive under the wrong service name, two hosts share a ServiceName — go back to Step 2.