Skip to content

CritterWatch.Services Overview

CritterWatch.Services (NuGet package: CritterWatch) is the server-side library that runs the monitoring console. It contains the Wolverine message handlers, Marten event sourcing projections, SignalR hub, HTTP API, and the embedded Vue SPA.

Package Contents

Hosting Extensions

  • AddCritterWatch(...) — registers all CritterWatch services into the DI container
  • UseCritterWatch(...) — maps HTTP endpoints, SignalR hub, and SPA middleware

Marten Event Store

CritterWatch uses Marten to store all service state as events. The event store schema is created automatically in the critterwatch Marten schema:

  • Event streams — one per monitored service, keyed by service name
  • ProjectionsServiceSummaryProjection materializes a ServiceSummary snapshot document
  • Timeline projectionTimelineProjection produces an ordered feed of all events
  • Alert snapshotsAlertRecord documents track alert state

Message Handlers

All ServiceUpdates packets from monitored services are handled by Wolverine message handlers that append domain events to Marten:

ServiceUpdates → WolverineChange events → ServiceSummary projection
AgentHealthReport → AgentHealthState document → AlertRaised/Elevated/Resolved
MessageStoreDiscovered → MessageStoreDiscoveredEvent → ServiceSummary

SignalR Relay

A RelayToWebSocketMessageHandler pattern relays all changes from the Wolverine handler pipeline to connected browser clients via SignalR. This creates a real-time feed:

ServiceUpdates received → Marten updated → SignalR message sent → Browser updates

HTTP API

All read queries and command dispatches are exposed as Wolverine.HTTP endpoints under /api/critterwatch/*.

Embedded Vue SPA

The compiled Vue 3 application is embedded as assembly resources when built with -p:EmbedFrontend=true. The UseCritterWatch() middleware serves static files and provides a client-side routing fallback.

Backend Architecture

Thread Safety and Ordering

All ServiceUpdates messages from a given service are processed sequentially (the queue is configured with .Sequential()). This preserves event ordering within a service's stream.

Messages from different services are processed concurrently — each service's queue is independent.

Released under the MIT License.