CGS.Monitor 1.1.0

CGS.Monitor for .NET

Reports errors from an ASP.NET Core application to CGS Monitor. Supports .NET 6 and later.

Install

From the CGS NuGet feed (see nuget-server/README.md to deploy it, and publish.ps1 to publish a release):

dotnet nuget add source https://<feed-host>/v3/index.json --name cgs
dotnet add package CGS.Monitor

Without the feed, build it and add the folder as a local source:

dotnet pack src/CGS.Monitor -c Release -o artifacts
dotnet nuget add source <absolute-path-to>/artifacts --name cgs-local
dotnet add package CGS.Monitor

Use an absolute path: a relative one is resolved against the NuGet config file it is saved in, and would break every restore on the machine. The source is registered by name, so dotnet add package needs no --source.

Use

using CGS.Monitor;

builder.Services.AddCgsMonitor(builder.Configuration);   // reads the "CgsMonitor" section
// or: builder.Services.AddCgsMonitor(o => { o.Key = ...; o.Endpoint = ...; });

var app = builder.Build();
app.UseCgsMonitor();   // first is recommended; capture works before or after UseExceptionHandler

Capture by hand with ICgsMonitor:

monitor.CaptureException(ex, new CaptureOptions { Tags = new Dictionary<string, string> { ["plan"] = "pro" } });
monitor.CaptureMessage("Nightly import finished", "info");

Configuration

Keep the key out of source control: use user secrets or environment variables (CgsMonitor__Key, CgsMonitor__Endpoint).

Setting Default Meaning
Key none Secret API key of the environment. Without it nothing is sent.
Endpoint none Base address of the service, for example https://monitor.example.com.
Release entry assembly version Release shown with each event.
Enabled true false turns every call into a no-op.
QueueCapacity 256 Events waiting to be sent. When full, new events are dropped.
BatchSize 20 Most events in one request.
MaxRetries 3 Retries of a failed send after the first try.
RequestTimeout 5 s Time limit of one request.
ShutdownTimeout 2 s How long shutdown waits to send what is queued.
IncludeSourceContext true Send the 5 lines before and after the failing line of your code's frames.

What is sent

For an unhandled exception: the exception type, message and stack frames, its InnerException chain (up to 5, each with its type, message and frames), the HTTP method, the route pattern when the request matched one (never the raw path, which may hold ids or tokens, and never the query string), the response status code, the host environment name, and the release.

Each frame has the method, the assembly, and, when the .pdb is next to the DLL, the file, line and column. Publish the .pdb with the app (the default for dotnet publish), or embed it with <DebugType>embedded</DebugType> in the project: without it frames still name the method, but not the file or the line. For your own code's frames (at most 5 per exception), the 5 lines before and after the failing line go too, read from the source file the .pdb names. That is the build machine's path, so they appear where the source is on disk (a developer's machine, a server that builds in place); elsewhere frames go without them. Source lines are scrubbed like any other text. Turn them off with IncludeSourceContext = false.

Never sent: request or response headers, cookies, query strings, or bodies. Context you add by hand is scrubbed first: keys that look like secrets (password, token, api key, cookie, authorization, session and similar) are redacted, and card numbers in text are masked.

Context takes simple values (text, numbers, booleans, dates, GUIDs, enums), lists, and dictionaries. Any other object arrives as its type name, for example [type: Order]: the client never calls code of yours while reading it. Pass parsed values, not live objects. Reading Request.Form itself can block on a stalled body, in your code before the SDK runs, so read it yourself with a cancellation token and pass the values you want.

An exception's own Message is read as it is, because reporting it is the point: an override of Message that throws loses only the message, but one that blocks would block the call, as it would block any logger in your app first.

Failure behavior

The client never changes what your application does. Sending happens in the background, so a slow, hanging or unreachable service does not slow requests. A full queue drops new events. No call throws. A missing or wrong key logs a warning and the app runs on; a rejected key (401) pauses sending for 5 minutes. Shutdown waits at most ShutdownTimeout and drops what remains. An unhandled exception is reported and then rethrown, so your error handling and status code are unchanged. A request cancelled by the client is not reported.

Sample

samples/CGS.Monitor.Sample has GET /health, GET /boom (throws) and POST /report.

cd samples/CGS.Monitor.Sample
dotnet user-secrets init
dotnet user-secrets set CgsMonitor:Key <your key>
dotnet user-secrets set CgsMonitor:Endpoint https://monitor.example.com
dotnet run

The sample ships Properties/launchSettings.json, which runs it as Development on http://localhost:5187, because user secrets load only in Development. Without that profile (for example when published), set the key with the CgsMonitor__Key environment variable instead.

No packages depend on CGS.Monitor.

.NET 6.0

  • No dependencies.

Version Downloads Last updated
1.1.0 2 11/14/2026