MyServiceBusDocs

Optional addon · Experimental

Understand distributed applications through messaging.

C# and Java services export precise bus metadata and bounded activity batches to a central monitoring service. The standalone Blazor dashboard presents them as participants in one distributed application, so application developers can understand behavior before drilling into endpoints, topology, and transport detail.

MVP boundary

The end-to-end stack is ready for local development and controlled evaluation. Optional PostgreSQL storage now provides restart durability, but authentication, long-range history views, broker metrics, administration, alerting, and automated scaling advice remain future work.

Applications first, infrastructure when needed

The dashboard is for developing and operating a distributed application made from services or sub-applications, not only for debugging MyServiceBus itself. Its main objects are those application participants, not bus instances. The landing page is a concise answer to “does this distributed application look healthy?” It shows participant and replica availability, messages handled per second, recent failures, monitoring completeness, a compact live throughput graph, and current concerns. Detailed engineering data stays one click away instead of competing for the first viewport.

The monitoring service preserves exact terms such as bus identity, endpoint, observation, and topology. The dashboard progressively discloses those concepts from the distributed application to one participant: system overview → service behavior → messaging paths → topology and transport context. Future broker inspection and operational commands remain separate capabilities with their own credentials and safety boundaries.

This dashboard is an opinionated example of what can be built from the monitoring APIs. A future engineering-specific UI could organize the same precise data around buses, endpoints, topology, and broker objects without turning this application-developer view into an infrastructure console.

  • Application overview shows replicas, receive endpoints, current rate, latency, failures, busiest receiving paths, and secondary connection context.
  • Application metrics expands one application's live throughput and ranks receive endpoints by observed activity.
  • Application flow limits the D3 map to one application and its directly observed neighbors.
  • Receive endpoints explains where messages arrive and shows availability, consumers, message types, addresses, throughput, retries, and failures.
  • Throughput expands the overview sparkline into a streamed five-minute graph and per-application breakdown.
  • Message flow uses an interactive D3 map to show observed application paths, with line weight and labels communicating throughput.
  • Failures and Outbox keep diagnostic and delivery detail in focused operational views.
  • A compact rolling Failures badge indicates recent activity, clears after recovery, and caps at 99+; it is not an unread or acknowledged alert.

The same information hierarchy supports learning and operations: concepts use plain labels such as “messages handled,” while exact rates, endpoint addresses, retry counts, latency, and transport details remain available. Light, dark, and system themes persist across navigation. On phones, cards collapse, maps and graphs fit the viewport, navigation scrolls, and wide tables stay contained inside their panels.

Graphs and maps are distinct reusable components, with compact overview and full drill-down forms. Future capabilities such as sagas can add their own focused views without turning the landing page into a catalog of every metric.

Scheduled work, Recurring jobs, and Tracked jobs are separate application-focused views. Scheduled work shows one-time message intent and due state; recurring jobs show definitions, cadence, revision, and next occurrence; tracked jobs show execution progress, timing, outcomes, and expandable attempts. Providers export bounded operational metadata, while message bodies, serialized callbacks, arbitrary headers, and failure messages remain outside monitoring. Cancellation and retry belong to a later privileged control plane.

Customization boundary

Overview widgets already have stable identities for a future versioned JSON layout. The preview intentionally ships one curated default and does not expose dashboard customization yet.

How it fits together

  1. General-purpose, read-only bus hooks observe lifecycle and message operations.
  2. The optional exporter copies observations into a bounded local queue.
  3. A background worker batches metadata, activity, and heartbeats over HTTP.
  4. The monitoring service owns the distributed read model and optional PostgreSQL history.
  5. The dashboard queries HTTP snapshots and refreshes from WebSocket invalidations.

Monitoring is never part of message delivery. If the service is unavailable, messaging continues and the bounded exporter may report dropped observations after connectivity returns.

Enable an exporter

C#
Loading code…
C#
Loading code…

What the MVP shows

  • Applications with automatically grouped replicas and optional resource labels
  • Application-specific Overview, Metrics, and Flow drill-downs
  • Receive-endpoint availability, replicas, consumers, messages, addresses, transports, and windowed activity
  • Live throughput graphs, windowed rates, load share, and p95 consume latency
  • Retries, failures, completeness, and observed cross-application flow
  • Expandable failure metadata without capturing message bodies or arbitrary headers
  • Recent observations and optional W3C trace correlation identifiers
  • Outbox dispatcher backlog, oldest-undispatched age, throughput, failures, lost leases, and cycle latency
  • One-time schedules, recurring definitions, and tracked C# or Java job executions in separate application-oriented views
  • HTTP queries plus WebSocket change invalidations
  • Transparent storage durability, freshness, retained-window coverage, and monitoring gaps

Build another dashboard or exporter

The supplied dashboard is only one consumer of the monitoring service. The service publishes its current OpenAPI 3.1 contract at /openapi/v1.json. It describes the versioned /api/monitoring/v1 HTTP ingest and query operations, JSON schemas, filters, and response codes, with separate tags for exporters and dashboards. A team can generate a client from the exact collector version it deploys instead of depending on the Blazor application or a .NET interface. A five-second cached /summary projection gives dashboard shells rolling failures, affected applications, outbox and tracked-job state, and explicit completeness and freshness without fetching every detailed view.

Live updates use the separately documented WebSocket endpoint /api/monitoring/v1/stream. Each UTF-8 JSON message contains an invalidation type such as observations_changed or jobs_changed and an occurredAtUtc timestamp. It is a bounded hint stream, not a durable event log: clients fetch initial state over HTTP, re-query after relevant hints, and fetch again after reconnecting. Polling is a supported fallback.

The OpenAPI and WebSocket contracts are preview integration surfaces, not control-plane APIs. They expose monitoring state but do not authorize queue purges, job cancellation, retries, or broker mutation. Raw failures and dashboard badges also do not provide alert acknowledgement; a future alerting service will own cross-source policy, recovery, acknowledgement, and notifications. The collector still has no built-in authentication, so alternative dashboards and exporters must remain inside a trusted deployment boundary.

Replicas and flexible grouping

Processes with the same application name are replicas of one participating service or sub-application, while each instance remains available for comparison. Optional bounded labels add a display level above that model: for example, group=commerce, environment=production, or role=worker. Labels organize the view; they do not replace identity.

Scaling-oriented, not prescriptive

The prototype lets an operator compare per-replica consume rate, load share, p95 duration, retries, and failures. It deliberately does not recommend a replica count. Queue depth and host saturation require transport-specific or external telemetry integrations and remain separate from the portable model.

Outbox dispatcher operations

C# and Java delivery services treat embedded and standalone dispatchers as first-class runtime components. Per service partition and worker, the dashboard's Outbox view shows current backlog, oldest-undispatched age, dispatch throughput, failures, lost leases, cycle latency, and online state. This makes an undersized dispatcher fleet visible as a bottleneck and separates time waiting in an outbox from broker backlog and consumer processing time.

The collector receives bounded cycle observations from each service; it does not connect to application databases or mutate persisted records. Message bodies, arbitrary headers, record identities, connection details, and SQL remain outside the monitoring protocol. Inbox duplicate outcomes, cleanup progress, and alerting remain future work. Optional PostgreSQL monitoring history is owned by the collector and stores monitoring records, not application outbox tables.

Optional PostgreSQL history

In-memory storage remains the zero-configuration development default. The .NET monitoring service can instead use its Entity Framework Core PostgreSQL provider:

JSON
Loading code…

The provider applies its migration at startup, deduplicates retried observation batches, restores the active 15-minute observation window, and restores the latest scheduled-work, recurring-definition, and tracked-job snapshots after restart. Seven-day retention bounds stored observation batches for future history queries; latest-state snapshots are not time series, and the current dashboard does not imply that the full retained period is queryable yet.

Follow one operation across services

MyServiceBus already creates OpenTelemetry producer and consumer spans in C# and Java and propagates W3C trace context through messages. A trace can connect the request entering one service to the message it sends, the worker that consumes it, and any downstream message produced by that consumer.

Text
Loading code…

This complements the aggregate monitoring view: the dashboard describes current topology, throughput, latency, retries, failures, and observed flow, while an OpenTelemetry backend explains the path and timing of one operation. In the included Aspire stack, the Aspire dashboard telemetry trace view shows the inbound request and the message producer and consumer spans together as one end-to-end path, provided each participating service exports its telemetry. The monitoring service does not collect or persist those spans today. Observations retain trace and span identifiers so a future dashboard provider can link to the existing tracing backend without recreating it.

Try the complete stack

Run the Aspire AppHost from the repository root:

Shell
Loading code…

Open the monitoring-dashboard resource, then call the sample applications' /publish, /send, /request/fault, or POST /jobs routes. The C# and Java samples self-register, create one recurring tracked occurrence at startup, and support delaySeconds, failFirstAttempt, and failAlways job-query options. The C# outbox sample contributes a durable PostgreSQL-backed recurring execution.

Deploy the components separately

The exporter is a client package. The collector and Blazor dashboard are separate applications, published as versioned Linux container images for AMD64 and ARM64:

Text
Loading code…

Both listen on port 8080. Configure the dashboard's Dashboard:MonitoringServiceAddress setting, or Dashboard__MonitoringServiceAddress environment variable, with the collector base address. PostgreSQL adds durable collection, but the preview still has no authentication; keep it inside a controlled network.

NextTest messaging behavior in isolation
Testing →