Skip to content

Orleans observability

Orleans uses standard .NET observability APIs:

These signals are complementary. Metrics detect a change, traces locate it in a request path, and logs explain discrete events or failures. The Orleans Dashboard is useful for interactive inspection, but an external telemetry backend is the durable source for alerting, retention, and cross-service correlation.

OpenTelemetry provides a vendor-neutral pipeline for logs, metrics, and traces. Install these packages in the host which runs Orleans:

The following configuration works for a silo. Register CoreHostingExtensions.AddActivityPropagation on silos and ClientBuilderExtensions.AddActivityPropagation on Orleans clients.

builder.Logging.AddOpenTelemetry(logging =>
{
logging.IncludeFormattedMessage = true;
logging.IncludeScopes = true;
if (exportToOtlp)
{
logging.AddOtlpExporter();
}
});
builder.Services.AddOpenTelemetry()
.ConfigureResource(resource => resource
.AddService(
serviceName: "orders-silo",
serviceVersion: typeof(Program).Assembly.GetName().Version?.ToString(),
serviceInstanceId: Environment.MachineName)
.AddAttributes([
new("deployment.environment.name", builder.Environment.EnvironmentName),
]))
.WithMetrics(metrics =>
{
metrics
.AddMeter("Microsoft.Orleans")
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddRuntimeInstrumentation();
if (exportToOtlp)
{
metrics.AddOtlpExporter();
}
})
.WithTracing(tracing =>
{
tracing
.AddSource(
"Microsoft.Orleans.Application",
"Microsoft.Orleans.Runtime",
"Microsoft.Orleans.Lifecycle",
"Microsoft.Orleans.Storage")
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.SetSampler(new ParentBasedSampler(
new TraceIdRatioBasedSampler(0.1)));
if (exportToOtlp)
{
tracing.AddOtlpExporter();
}
});
builder.UseOrleans(siloBuilder =>
{
siloBuilder
.UseLocalhostClustering()
.AddActivityPropagation();
});

Set OTEL_EXPORTER_OTLP_ENDPOINT to the OpenTelemetry Protocol (OTLP) endpoint, for example http://localhost:4317. The OpenTelemetry .NET SDK honors standard OTEL_* environment variables. In a .NET Aspire application, the AppHost supplies the OTLP endpoint to referenced projects, so this configuration sends telemetry to the Aspire dashboard without an Orleans-specific exporter.

Use an OpenTelemetry Collector between applications and the final backend when you need buffering, routing, redaction, or backend-specific authentication.

AddMeter("Microsoft.Orleans") subscribes to numeric Orleans instruments. It doesn’t enable traces. Use metrics for rates, counts, queue pressure, latency distributions, and alerts.

AddSource(...) subscribes to spans. It doesn’t collect Orleans metrics. Orleans exposes these source names through ActivitySources:

SourceScope
Microsoft.Orleans.ApplicationApplication grain calls
Microsoft.Orleans.RuntimeRuntime operations
Microsoft.Orleans.LifecycleActivation, migration, and deactivation
Microsoft.Orleans.StorageGrain storage operations
Microsoft.Orleans.DurableJobsDurable job scheduling and execution
Microsoft.Orleans.*Wildcard for all Orleans activity sources

The example selects the first four sources explicitly so the collected scope is visible in code. Add durable jobs when used. A wildcard is convenient during investigation but can begin collecting new sources after an Orleans upgrade, so review its volume and data policy.

Propagate trace context through grain calls

Section titled “Propagate trace context through grain calls”

Register AddActivityPropagation() on every silo and Orleans client which participates in a trace. It installs grain-call filters which carry the current W3C trace context and baggage through Orleans messages. Without it, Orleans spans can still be exported, but an incoming HTTP span and the resulting grain-call spans won’t form one distributed trace.

Treat baggage as transmitted application data. Don’t put secrets, credentials, personal data, or unbounded user input in baggage. Prefer a small set of approved correlation fields.

Every process should set stable resource attributes:

  • service.name: the logical service, such as orders-silo.
  • service.version: the deployed application version.
  • service.instance.id: a unique process or pod identifier.
  • deployment.environment.name: the environment.

Don’t use a silo address as service.name; put changing instance identity in service.instance.id. Configure cluster, region, or tenant attributes only when their value set is bounded and permitted by your telemetry data policy.

  • Export metrics continuously at an interval appropriate for your alerting objectives.
  • Use parent-based trace sampling so a request keeps one sampling decision across HTTP, Orleans, and downstream calls.
  • Keep errors and slow requests with a tail-sampling collector when the backend supports it.
  • Increase sampling temporarily during an incident instead of running full-fidelity tracing indefinitely.
  • Keep metric dimensions bounded. Grain IDs, request IDs, user IDs, and exception messages are unsuitable metric attributes.
  • Filter noisy log categories at the provider and avoid logging full grain state or message payloads.

The example’s 10% head-sampling ratio is a starting point, not a universal production value. Select it from traffic volume, retention cost, and the probability of capturing rare failures.