Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ServiceComposer/ServiceComposer.AspNetCore/llms.txt

Use this file to discover all available pages before exploring further.

ServiceComposer emits distributed traces using System.Diagnostics.ActivitySource, the built-in .NET tracing API. Because ActivitySource ships with the runtime, no extra NuGet packages are required in your handler libraries — traces are emitted automatically once the host application wires up the OpenTelemetry SDK. Two independent activity sources are provided, one per feature, so you can opt into only what you use.

Activity sources

FeatureActivity source name
ViewModel CompositionServiceComposer.AspNetCore.ViewModelComposition
Scatter/GatherServiceComposer.AspNetCore.ScatterGather
The constants live in CompositionTelemetry:
public static class CompositionTelemetry
{
    public const string ViewModelCompositionSourceName = "ServiceComposer.AspNetCore.ViewModelComposition";
    public const string ScatterGatherSourceName = "ServiceComposer.AspNetCore.ScatterGather";
    // ...
}

Setup

Add the OpenTelemetry.Extensions.Hosting NuGet package to your host project, then register the desired source(s) in the OpenTelemetry tracing pipeline.
builder.Services.AddOpenTelemetry()
    .WithTracing(b => b
        .AddSource("ServiceComposer.AspNetCore.ViewModelComposition"));
The wildcard form ServiceComposer.AspNetCore.* is the most future-proof option. Any new activity sources that ServiceComposer adds in later releases will be captured automatically.

What gets traced

ViewModel Composition spans

Each ICompositionRequestsHandler execution produces a child span of the ASP.NET Core HTTP server span.

composition.handler span

Operation name: composition.handler
Display name: Fully qualified handler type name
TagValue
composition.handler.typeFully qualified handler type name
composition.handler.namespaceHandler namespace

composition.event span

Operation name: composition.event
Display name: Fully qualified event type name
Emitted when a handler raises an event via context.RaiseEvent<TEvent>(). Appears as a child of the raising handler’s span.
TagValue
composition.event.typeFully qualified event type name
composition.event.namespaceEvent namespace
The span names and tag keys as defined in CompositionTelemetry:
public static class Spans
{
    public const string Handler = "composition.handler";
    public const string Event = "composition.event";
    public const string Gatherer = "scatter-gather.gatherer";
}

public static class Tags
{
    public const string HandlerType = "composition.handler.type";
    public const string HandlerNamespace = "composition.handler.namespace";
    public const string EventType = "composition.event.type";
    public const string EventNamespace = "composition.event.namespace";
    public const string GathererKey = "scatter_gather.gatherer.key";
}

Scatter/Gather spans

Each IGatherer execution produces a child span of the ASP.NET Core HTTP server span.
FieldValue
Operation namescatter-gather.gatherer
Display nameGatherer key
scatter_gather.gatherer.keyThe gatherer key

Error spans

When any handler, event handler, or gatherer throws an unhandled exception, ServiceComposer sets ActivityStatusCode.Error on the span and adds the following tags, plus an exception event following the OpenTelemetry exception semantic conventions:
TagValue
otel.status_code"error"
otel.status_descriptionException message

Complete example

The following shows a typical Program.cs that registers both ServiceComposer and the OpenTelemetry tracing pipeline with an OTLP exporter:
using OpenTelemetry;
using OpenTelemetry.Trace;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddViewModelComposition();
builder.Services.AddControllers();
builder.Services.AddRouting();

builder.Services.AddOpenTelemetry()
    .WithTracing(b => b
        .AddSource("ServiceComposer.AspNetCore.*")
        .AddAspNetCoreInstrumentation()
        .AddOtlpExporter());

var app = builder.Build();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
    endpoints.MapCompositionHandlers();
    endpoints.MapControllers();
});

app.Run();
The AddAspNetCoreInstrumentation() call is optional but recommended — it creates the root HTTP server span that composition and gatherer spans attach to as children, giving you the full request trace tree.

Build docs developers (and LLMs) love