Observability
Trace content actions and monitor Bifrost with Heimdall's built-in ActivitySource and System.Diagnostics.Metrics instruments.
The Server package emits diagnostics without requiring an exporter. Your application chooses OpenTelemetry, sampling, retention, and alerting.
1. Register the Source and Meter
Use the public constants so configuration, dashboards, and tests do not repeat framework string literals.
using Heimdall.Server;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
.AddSource(HeimdallDiagnostics.ActivitySourceName))
.WithMetrics(metrics => metrics
.AddMeter(HeimdallDiagnostics.MeterName));2. Activities
Content actions include the resolved action ID, status, outcome, exception type, or cancellation reason as appropriate. Bifrost exposes connection and publish activities.
heimdall.content_action
heimdall.bifrost.connection
heimdall.bifrost.publish
// Public constants:
HeimdallDiagnostics.ContentActionActivityName
HeimdallDiagnostics.BifrostConnectionActivityName
HeimdallDiagnostics.BifrostPublishActivityName3. Content-Action Metrics
The action pipeline records volume, latency, sizes, failures, and cancellation independently so expected replacement cancellation does not look like an application exception.
heimdall.server.content_action.requests
heimdall.server.content_action.duration
heimdall.server.content_action.request.body.size
heimdall.server.content_action.response.body.size
heimdall.server.content_action.exceptions
heimdall.server.content_action.cancellations4. Bifrost Metrics
Connection and subscriber gauges show current load. Message counters distinguish publication, delivery, expiry, and drops so slow subscribers or undersized buffers are visible.
heimdall.server.bifrost.connections.active
heimdall.server.bifrost.subscribers.active
heimdall.server.bifrost.messages.published
heimdall.server.bifrost.messages.delivered
heimdall.server.bifrost.messages.expired
heimdall.server.bifrost.messages.dropped5. Tags and Cardinality
Stable dimensions include action ID, outcome, status, error type, cancellation reason, Bifrost event name, and drop reason. Action IDs and event names should come from bounded application-defined sets.
Intentionally excluded:
- action payloads
- user identities
- Bifrost topic names
- selectors and request URLs
Do not add sensitive or unbounded values back as tags.6. Read Outcomes Correctly
Timeout, replacement, external cancellation, and errors are different operational signals. A Bifrost no-subscribers outcome can be normal for best-effort live UI. Aggregate active counts across instances in the telemetry backend when the service is scaled out.
Suggested dashboards:
- action rate, p50/p95/p99 duration, and error ratio
- cancellations by reason
- request/response size distributions
- active Bifrost connections and subscribers
- published vs delivered vs expired/dropped messages7. HasSubscribers Is Not Telemetry
Bifrost.HasSubscribers(topic) is an instantaneous local-instance hint for skipping optional expensive work. It is not a delivery guarantee, a distributed presence query, or a substitute for metrics.
if (bifrost.HasSubscribers("orders"))
{
var html = await RenderExpensiveOrderUpdate(ct);
await bifrost.PublishAsync("orders", html,
TimeSpan.FromSeconds(5), ct);
}