Repository navigation
Health check api - #5952
Health check api#5952hazel-bohon wants to merge 8 commits into
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Five-second polling currently forces license discovery and persistence access for every open ServicePulse client.
Review effort: Balanced
Findings: 1
Open (1)
What changed in this PR
Adds a dedicated Platform Health API for ServicePulse, separating internal health reporting from customer custom checks.
Changes:
- Adds platform health inventory, alerts, licensing, and remote-instance metadata.
- Extends configuration discovery and remote probing.
- Adds unit, acceptance, authorization, and API approval coverage.
Reviewed against issue #5860, docs/platform-health.md, and the linked ServicePulse models/store. No private context was provided.
| File | Description |
|---|---|
src/ServiceControl/ServiceControlApiHostBuilderExtensions.cs |
Registers license information provider. |
src/ServiceControl/PlatformHealth/PlatformHealthState.cs |
Tracks internal health-check state. |
src/ServiceControl/PlatformHealth/PlatformHealthController.cs |
Exposes the health endpoint. |
src/ServiceControl/PlatformHealth/PlatformHealthApi.cs |
Builds platform health responses. |
src/ServiceControl/PlatformHealth.http |
Adds manual API requests. |
src/ServiceControl/Licensing/LicenseInfoProvider.cs |
Extracts shared license mapping. |
src/ServiceControl/Licensing/LicenseController.cs |
Uses the shared provider. |
src/ServiceControl/Infrastructure/WebApi/RemoteInstanceServiceCollectionExtensions.cs |
Preserves remote URL prefixes. |
src/ServiceControl/Infrastructure/Api/ConfigurationApi.cs |
Adds discovery metadata and robust remote probing. |
src/ServiceControl/CustomChecks/CustomChecksComponent.cs |
Registers platform health services. |
src/ServiceControl/CustomChecks/CustomCheckResultProcessor.cs |
Records internal health reports. |
src/ServiceControl.UnitTests/ScatterGather/RemoteInstanceHttpClientTests.cs |
Tests remote configuration requests. |
src/ServiceControl.UnitTests/PlatformHealth/PlatformHealthStateTests.cs |
Tests health-state behavior. |
src/ServiceControl.UnitTests/PlatformHealth/PlatformHealthApiTests.cs |
Tests response assembly and failures. |
src/ServiceControl.UnitTests/Licensing/ActiveLicenseTests.cs |
Tests extracted license mapping. |
src/ServiceControl.UnitTests/ApprovalFiles/APIApprovals.RootPathValue.approved.txt |
Approves discovery URL addition. |
src/ServiceControl.UnitTests/ApprovalFiles/APIApprovals.HttpApiRoutes.approved.txt |
Approves the new route. |
src/ServiceControl.UnitTests/API/APIApprovals.cs |
Tests primary configuration metadata. |
src/ServiceControl.MultiInstance.AcceptanceTests/Infrastructure/When_inspecting_platform_health.cs |
Exercises multi-instance health behavior. |
src/ServiceControl.Audit/Infrastructure/WebApi/RootController.cs |
Publishes audit identity metadata. |
src/ServiceControl.Audit.UnitTests/API/APIApprovals.cs |
Tests audit configuration metadata. |
src/ServiceControl.Api/IPlatformHealthApi.cs |
Defines the health API abstraction. |
src/ServiceControl.Api/Contracts/RootUrls.cs |
Advertises platform health discovery. |
src/ServiceControl.Api/Contracts/PlatformHealthView.cs |
Defines response contracts. |
src/ServiceControl.AcceptanceTests/WebApi/When_the_configuration_page_is_read.cs |
Verifies configuration metadata. |
src/ServiceControl.AcceptanceTests/Security/OpenIdConnect/When_authentication_is_enabled.cs |
Verifies endpoint authorization. |
src/ServiceControl.AcceptanceTests/Monitoring/CustomChecks/When_custom_checks_are_classified.cs |
Verifies health/custom-check separation. |
docs/README.md |
Indexes the design documentation. |
docs/platform-health.md |
Documents the API contract and rationale. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: hazel-bohon <2416062+hazel-bohon@users.noreply.github.com>
| | `transport_type`, `error_queue`, `error_log_queue`, `forward_error_messages` | Available transport configuration; a known `false` forwarding setting is preserved | | ||
| | `audit_queue`, `audit_log_queue`, `forward_audit_messages` | Available audit transport configuration | |
There was a problem hiding this comment.
Are these multiple fields listed in the same row? They read like the possible values for a field and not the field name themselves.
| client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); | ||
| // Application settings might contain remote URLs with /api. We strip that away to be a real base address. | ||
| client.BaseAddress = new Uri(remoteInstance.BaseAddress); | ||
| client.BaseAddress = new Uri(remoteInstance.BaseAddress.TrimEnd('/') + "/"); |
There was a problem hiding this comment.
It ensures that there's a "/" but not a double slash at the end of the base url.
| { | ||
| using var response = await httpClient.GetAsync("/api/configuration", cancellationToken); | ||
| using var response = await httpClient.GetAsync("api/configuration", cancellationToken); | ||
| response.EnsureSuccessStatusCode(); |
There was a problem hiding this comment.
I think this changes the behavior. Previously, a non-200 response was considered "online" but now it's "unavailable". That might affect consumers. I think both AuditThroughput/AuditQuery.cs and AuditThroughputCollectorHostedService.cs are good, but maybe I missed something else.
| return new PlatformHealthInstance | ||
| { | ||
| Id = remote.InstanceId, | ||
| Name = new Uri(remote.BaseAddress).Host, |
There was a problem hiding this comment.
This can fail if the address is invalid. Probably worth wrapping with try+catch or other validation.
| static DateTimeOffset? ParseDate(string value) => | ||
| DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out var date) ? date : null; | ||
|
|
||
| readonly ConcurrentDictionary<string, PlatformHealthInstance> lastKnownRemotes = new(StringComparer.Ordinal); |
There was a problem hiding this comment.
I think this dictionary is never cleared? I'm not sure if we ever get "way too many" of those, but wanted to mention that.
Co-authored-by: Michelle Chamberlin <michelle.chamberlin@particular.net>
… tests for instance ID handling
Co-authored-by: hazel-bohon <2416062+hazel-bohon@users.noreply.github.com>
| var patch = new PatchByQueryOperation(query, new QueryOperationOptions | ||
| { | ||
| AllowStale = true, | ||
| AllowStale = false, |
There was a problem hiding this comment.
Why does this need to be changed?
There was a problem hiding this comment.
Changes to the license api should be in a sperate PR.

Uh oh!
There was an error while loading. Please reload this page.