Summary
The three non-broker-transport CritterWatch samples — WebService.Http, Fleet.PostgresqlQueues, Fleet.SqlServerQueues — build clean but their Aspire batteries fail at runtime the same way: the CritterWatch console comes up (GET /api/critterwatch/about → 200) but no monitored service ever registers (GET /api/critterwatch/services stays empty — Registered: [(none)], test times out waiting).
This is deferred from the initial round pending a focused investigation. Tracking re-add here.
Confirmed pattern (the useful finding)
| Transport |
Sample |
Services register? |
| RabbitMQ |
Fleet.RabbitMq |
✅ yes (verified green) |
| Azure Service Bus (emulator) |
Fleet.AzureServiceBus |
✅ yes (verified green) |
| Wolverine HTTP transport |
WebService.Http |
❌ no |
| PostgreSQL DB queue |
Fleet.PostgresqlQueues |
❌ no |
| SQL Server DB queue |
Fleet.SqlServerQueues |
❌ no |
Registration works on broker transports, fails on every non-broker transport tested. (Amazon SQS — also a broker — is separately blocked on an Aspire/LocalStack startup issue, #5; it did not get far enough to test registration.)
What we ruled out / learned
- Not the per-endpoint serializer. The broker consoles call
.UseCritterWatchSerializer() on the listen endpoint; the DB-queue/HTTP consoles can't — UseCritterWatchSerializer is not defined on PostgresqlListenerConfiguration/SqlServerListenerConfiguration (compile error). These transports are meant to get the CritterWatch wire-format via AddCritterWatch's serializer policy, not a per-endpoint call. So the bare ListenToPostgresqlQueue("critterwatch") is the intended shape.
- The DB-queue samples correctly share one transport schema for the control queue (per the multi-host schema note) and each keeps its own event-store schema. The console (CritterWatch package) registers its Wolverine store in a
{schema}_wolverine schema — whether the control queue the console listens on lands in the same schema the services publish to is one thing to verify at runtime.
Candidate root causes to investigate (runtime)
- Does AddCritterWatch's serializer policy actually apply to a DB-queue / HTTP control listener (vs. only broker listeners)? If the console can't decode the brotli-framed registration envelopes, they'd be silently dropped.
- Is the console actually consuming the control queue on these transports (leader/listener actually started; queue table in the schema the services write to)?
- HTTP specifically: the console set the CritterWatch serializer as its default serializer and maps
MapWolverineHttpTransportEndpoints(); confirm the inline-invoke receive path resolves it and the service's per-URI named HttpClient actually posts.
Likely a CritterWatch-side multi-host control-channel behavior on non-broker transports rather than sample wiring — but confirm before filing a CritterWatch issue. Inspect under DistributedApplicationTestingBuilder with the critterwatch + service resource logs dumped, and look at the actual queue tables.
Status of the code
All three solutions are present under critterwatch/ and build clean; only runtime service-registration is broken. The exact control-channel wiring for each is in the code + the critterwatch/plans/ files. Re-add = fix registration + green battery, not a rebuild.
Acceptance
WebService.Http, Fleet.PostgresqlQueues, Fleet.SqlServerQueues each verified with a green Aspire battery (/about 200 + all fleet services registered).
Summary
The three non-broker-transport CritterWatch samples —
WebService.Http,Fleet.PostgresqlQueues,Fleet.SqlServerQueues— build clean but their Aspire batteries fail at runtime the same way: the CritterWatch console comes up (GET /api/critterwatch/about→ 200) but no monitored service ever registers (GET /api/critterwatch/servicesstays empty —Registered: [(none)], test times out waiting).This is deferred from the initial round pending a focused investigation. Tracking re-add here.
Confirmed pattern (the useful finding)
Registration works on broker transports, fails on every non-broker transport tested. (Amazon SQS — also a broker — is separately blocked on an Aspire/LocalStack startup issue, #5; it did not get far enough to test registration.)
What we ruled out / learned
.UseCritterWatchSerializer()on the listen endpoint; the DB-queue/HTTP consoles can't —UseCritterWatchSerializeris not defined onPostgresqlListenerConfiguration/SqlServerListenerConfiguration(compile error). These transports are meant to get the CritterWatch wire-format via AddCritterWatch's serializer policy, not a per-endpoint call. So the bareListenToPostgresqlQueue("critterwatch")is the intended shape.{schema}_wolverineschema — whether the control queue the console listens on lands in the same schema the services publish to is one thing to verify at runtime.Candidate root causes to investigate (runtime)
MapWolverineHttpTransportEndpoints(); confirm the inline-invoke receive path resolves it and the service's per-URI named HttpClient actually posts.Likely a CritterWatch-side multi-host control-channel behavior on non-broker transports rather than sample wiring — but confirm before filing a CritterWatch issue. Inspect under
DistributedApplicationTestingBuilderwith thecritterwatch+ service resource logs dumped, and look at the actual queue tables.Status of the code
All three solutions are present under
critterwatch/and build clean; only runtime service-registration is broken. The exact control-channel wiring for each is in the code + thecritterwatch/plans/files. Re-add = fix registration + green battery, not a rebuild.Acceptance
WebService.Http,Fleet.PostgresqlQueues,Fleet.SqlServerQueueseach verified with a green Aspire battery (/about200 + all fleet services registered).