.NET SDK
Monitor scheduled jobs from your .NET code with the official SteadyCron SDK. Wrap a job with TrackAsync and get alerted on missed, failed, and stuck runs — the monitor is declared as code in YAML or Terraform.
SteadyCron.Monitoring is the official .NET code-monitoring SDK. Wrap a scheduled job
with TrackAsync and SteadyCron will know when it started, succeeded, or
failed — and alert you when it doesn’t run on time or starts but never
finishes.
The SDK never creates monitors. You declare the heartbeat monitor as code — in a
YAML manifest or with the
Terraform provider — and reference it from your application by its
stable key. The cron schedule, the alert rules, and the instrumentation all live in
the same repository.
Install
dotnet add package SteadyCron.Monitoring
Quick start
ASP.NET Core / Generic Host
Register the monitor with dependency injection:
// Program.cs
builder.Services.AddSteadyCron(o =>
{
o.ApiKey = builder.Configuration["SteadyCron:ApiKey"]; // read-only key
o.Environment = builder.Environment.EnvironmentName; // optional
});
// BackupWorker.cs
public class BackupWorker(ISteadyCronMonitor monitor) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken ct)
{
await monitor.TrackAsync("nightly-db-backup", async ct =>
{
await RunBackupAsync(ct);
}, ct);
}
}
The string "nightly-db-backup" is the same key you set on the
steadycron_heartbeat_monitor resource (Terraform) or the heartbeat job id (YAML
manifest). That is the only contract between your schedule-as-code and your application.
Console / standalone (no DI)
var monitor = SteadyCronMonitor.Create(new SteadyCronOptions
{
ApiKey = Environment.GetEnvironmentVariable("STEADYCRON_API_KEY"),
});
await monitor.TrackAsync("nightly-db-backup", ct => RunBackupAsync(ct));
Authentication
The SDK uses a read-only API key to resolve a monitor key to its ping token at startup. Create one under Settings → API keys → New key → Scope: Read-only.
Provide it via any of:
- Environment variable:
STEADYCRON_API_KEY=sc_ro_... SteadyCronOptions.ApiKeydirectly"SteadyCron:ApiKey"inappsettings.json
Configuration
| Property | Default | Env var fallback |
|---|---|---|
ApiKey | null | STEADYCRON_API_KEY |
ApiUrl | https://api.steadycron.com | STEADYCRON_API_URL |
PingUrl | https://ping.steadycron.com | STEADYCRON_PING_URL |
Environment | null | STEADYCRON_ENVIRONMENT |
CaptureErrors | false | — |
PingTimeout | 5 seconds | — |
ResolveCacheTtl | 1 hour | — |
How it works
- On first use, the SDK calls
GET /api/monitors/resolve?key=<your-key>with the read-only API key to retrieve the ping token. The token is cached for one hour (configurable viaResolveCacheTtl). - All pings are fire-and-forget: a bounded timeout (~5 s) is applied; transport errors are logged and swallowed, never propagated.
- Resolution errors —
404(unknown key),409(ambiguous key), or wrong kind — raise immediately. They indicate misconfiguration. - On an exception inside
TrackAsync, afailping is sent and the original exception is rethrown unchanged.
Direct / token mode
If you cannot use API-key resolution (for example, in an air-gapped environment), set the ping token directly and skip the resolve call:
o.Monitors["nightly-db-backup"] = "hRkmWz8oZtlMFzvTAUdnRE";
The token is visible in the dashboard under Job detail → Code monitoring → Reveal ping token.
Reliability contract
- Ping failures are never propagated. A transport error, timeout, or non-2xx response from a ping is logged at Warning/Debug and discarded.
- Resolution errors always propagate. A
404or409from the resolve endpoint raises on first use; fix the key or remove the decorator. - Original exceptions pass through unchanged.
TrackAsyncdoes not wrap exceptions — thefailping is sent before rethrowing. - No ping blocks the job. Pings run inline but are bounded by
PingTimeout(default 5 s). A slow ping delays but never hangs the job.
Related
- Heartbeat monitoring — how missed, failed, and stuck runs are detected
- Python SDK — the same code-monitoring workflow for Python
- Terraform provider — declare the monitor and its
keyas HCL - YAML & CLI — declare the monitor in a manifest instead
- Ping snippets — ping from any language or shell without the SDK