X.Spectator is a lightweight and extensible monitoring and health evaluation framework for .NET applications.
It provides a clean, event-driven model for observing system health, diagnostics, and performance — built around the concept of Probes, Spectators, and State Evaluators.
Designed for developers who need a flexible, composable monitoring layer that integrates seamlessly with modern .NET health checks and diagnostics.
- Native Integration — fully aligned with .NET's built-in
HealthStatusmodel. - Probes & Spectators — modular design for collecting, evaluating, and reacting to system metrics.
- Event-Driven Monitoring — trigger state changes and health checks dynamically.
- Flexible Extensions — implement custom probes, evaluators, and journal strategies.
- Asynchronous Support — works both in synchronous and background modes.
Represents a single measurable system indicator (e.g., CPU usage, API latency, cache size).
Each probe implements the IProbe interface and returns a ProbeResult containing:
- Probe name
- Execution timestamp
HealthCheckResultvalue (with status, description, exception, and diagnostic data)
public interface IProbe
{
string Name { get; }
Task<ProbeResult> Check();
}An ISpectator instance aggregates multiple probes, polls them periodically, and raises events:
- StateChanged — when system health transitions
- HealthChecked — after each probe cycle
public interface ISpectator<TState>
{
event EventHandler<StateEventArgs<TState>> StateChanged;
event EventHandler<HealthCheckEventArgs> HealthChecked;
void AddProbe(IProbe probe);
void CheckHealth();
}Built-in implementations include:
SpectatorBase<TState>— synchronous monitoring base classAutomatedSpectator<TState>— asynchronous, background monitoring (implementsIHostedService)
Implements custom logic for aggregating probe results into a system-wide state.
public interface IStateEvaluator<TState>
{
TState Evaluate(TState currentState, DateTime stateChangedLastTime, IReadOnlyCollection<JournalRecord> journal);
}A time-series record of probe snapshots used for retrospective analysis and state evaluation.
public record JournalRecord
{
public DateTime Time { get; init; }
public IReadOnlyCollection<ProbeResult> Values { get; init; }
}Install via NuGet:
dotnet add package X.SpectatorOr update your project file:
<PackageReference Include="X.Spectator" Version="2.2.4" />NuGet Package: https://www.nuget.org/packages/X.Spectator/
// Create a state evaluator
var stateEvaluator = new MyHealthStatusEvaluator();
// Create an automated spectator
var spectator = new AutomatedSpectator<HealthStatus>(
checkHealthPeriod: TimeSpan.FromSeconds(10),
retentionPeriod: TimeSpan.FromMinutes(5),
stateEvaluator: stateEvaluator,
initialState: HealthStatus.Healthy
)
{
Name = "AppSpectator"
};
// Add probes
spectator.AddProbe(new MemoryUsageProbe());
// Subscribe to events
spectator.StateChanged += (s, e) =>
{
Console.WriteLine($"State changed to: {e.State}");
};
// Start monitoring (implements IHostedService)
await spectator.StartAsync(CancellationToken.None);- Replaced custom enums with native .NET
HealthStatus ProbeResultnow wrapsHealthCheckResultfor full integration with .NET health checks- Improved asynchronous monitoring model with
IHostedServicesupport - Enhanced XML documentation and unit tests
- Support for .NET 8.0 and .NET 9.0
Full changelog: https://github.com/a-gubskiy/X.Spectator/releases
Contributions are welcome!
If you want to improve or extend X.Spectator, please follow the standard GitHub flow:
- Fork the repository
- Create a branch (
feature/YourFeature) - Commit and push your changes
- Open a Pull Request
- 📖 Article: X.Spectator 2.0 on Medium
- 📦 NuGet Package
- 💻 GitHub Repository
X.Spectator continues to evolve alongside .NET — bridging classic monitoring patterns with modern health diagnostics for high-reliability applications.