Skip to content
How-to

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.

  • 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.

Terminal window
dotnet add package Intropy.Telemetry.ConsoleApp

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.

That one call configures all three signals:

  • Traces — subscribes activity sources matching Intropy.* (which covers the framework’s Intropy.Framework.Core, .Blocks, .Adapters, and .Hosting sources) plus your ServiceName, and instruments outbound HTTP, SQL Client, and gRPC calls. The framework’s Pipeline.<name>, Step.<StepName>, and Finalizer.<FinalizerName> spans are collected with no further registration.
  • Metrics — HTTP client metrics, plus ASP.NET Core request metrics on that host type.
  • Logs — structured ILogger output exported alongside the traces, correlated with the active span.

All three signals export over OTLP, configured through the standard OpenTelemetry environment variables:

Terminal window
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317

Locally, 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).

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.

Terminal window
docker run --rm -ti -p 3000:3000 -p 4317:4317 -p 4318:4318 grafana/otel-lgtm

Ports 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 a Pipeline.<name> root and Step.<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.