Skip to content

Outbound Events

Outbound events are messages your monitored service publishes back to the CritterWatch console. They flow over your existing Wolverine transport from the service to the console's critterwatch queue.

This page is for integrators who want to consume the same telemetry from their own infrastructure (a separate analytics pipeline, a custom dashboard, an audit system, etc.). For day-to-day operation, you don't need any of this — the console handles it for you.

How telemetry is shaped

Most outbound traffic is wrapped in a single ServiceUpdates batch published once per second. A few message types are published on demand in response to specific console queries (handler source code, HTTP chain source code, pending-migration probe results, tenant list refresh).

The batch carries everything CritterWatch needs to render a service's pages in one round-trip — endpoint snapshot, subscription catalog, persistence counts, shard states, agent health, and any change events that occurred since the previous batch.

What's in ServiceUpdates

csharp
public record ServiceUpdates(
    string ServiceName,
    string Label,
    string WolverineVersion,
    EndpointState[] Endpoints,
    MessagingSubscription[] Subscriptions,
    WolverineChange[] Changes,
    AgentHealthReport[] AgentHealth,
    PersistenceCounts PersistenceCounts,
    ShardStateSnapshot[] ShardStates
);

The Changes array carries the discrete state-change events that occurred since the previous batch. The other arrays are full snapshots — current endpoints, current subscriptions, current health.

Change-event categories

The WolverineChange discriminator covers:

CategoryTriggerDrives
NodeAdded / NodeRemovedProcess node joined or left the clusterCluster tab → Nodes view
LeadershipChangedNew leader electedCluster tab → Leader pill
AgentStarted / AgentStoppedAgent assignment changesCluster tab → Agents view
EndpointAdded / EndpointStoppedListener or sender lifecycleEndpoints tab
CircuitBreakerTripped / CircuitBreakerResetEndpoint resilience eventEndpoints tab + alert
BackPressureTriggered / BackPressureLiftedFlow-control eventEndpoints tab + alert
ExceptionTriggeredHandler exceptionTimeline + DLQ rate metrics

On-demand response messages

These are published in response to a specific console query rather than on the regular cadence:

ResponseTriggered byCarries
HandlerSourceCodeResponseRequestHandlerSourceCodeGenerated handler source code for a message type
HttpChainSourceCodeReportedRequestHttpChainSourceCodeGenerated source code for an HTTP chain
PendingMigrationsReportedResponseRequestPendingMigrationsCheckPending EF Core migration list for a DbContext
TenantListResponseRequestTenantListCurrent tenant list for multi-tenant services
AgentHealthReportRequestAgentHealthReport (or scheduled)Agent health snapshot
RestartProjectionResultRestartProjection / RebuildProjectionSuccess/failure of the operation
ScheduledMessageEditedEditScheduledMessageConfirmation of edit + new execution time
StaleNodesEjectedEjectNodeConfirmation of ejected node ids
SubscriptionOrProjectionRestartedAuto-restart on stallWhy and when

Capability advertisement (on startup)

The first ServiceUpdates batch after startup carries the full capability set:

  • MessagingSubscription[] — every message type with its handler binding and routing role (Handler / Publisher).
  • EndpointState[] — every listener and sender with full configuration.
  • MessageStoreDiscovered — every Wolverine durability store with its database URI and store type (Postgresql / SqlServer / InMemory).
  • Event-store metadata (Marten / Polecat).
  • Tenancy mode + current tenant list.
  • Wolverine version string.

This snapshot is re-issued whenever the Wolverine runtime is reinitialized. It replaces the prior shape wholesale — no merge logic.

Causation discovery

When the runtime observes that handling message A resulted in publishing message B, the service publishes a MessageCausationDiscovered event. The console aggregates these to draw the causation graph on the Message Topology page.

Causation is reported per discovered pair, not on every occurrence — once a causation is known, repeated observations don't re-publish.

Message shape on the wire

Telemetry uses Wolverine's standard JSON envelope on the transport. When consumed via SignalR (e.g., by the browser), messages use the CloudEvents wrapper:

json
{
  "type": "service_updated",
  "data": {
    "serviceName": "trip-service",
    ...
  }
}

The type discriminator is snake_case derived from the C# type name. Properties inside data are camelCase. Enums serialize as string names.

Consuming telemetry from your own infrastructure

If you want to subscribe to the same telemetry stream from a separate process (analytics, custom audit, etc.):

  1. Listen on the critterwatch RabbitMQ queue alongside the console — or have your service fan out to a second queue using Wolverine's transport routing.
  2. Reference Wolverine.CritterWatch and deserialize the message types directly.
  3. Treat ServiceUpdates as a complete snapshot — don't try to reconstruct state from the Changes array alone, because some change events depend on having seen the prior snapshot.

For analytics pipelines, the high-volume surface is ServiceUpdates (one per second per service). The bursty / on-demand surface is the response messages and the alert lifecycle events emitted by the console (which are republished over SignalR for the browser; you can subscribe to that hub if your consumer is a server-side SignalR client).

Released under the MIT License.