ErrorDock.Core 0.1.0-rc.1

This is a prerelease version of ErrorDock.Core.
dotnet add package ErrorDock.Core --version 0.1.0-rc.1
                    
NuGet\Install-Package ErrorDock.Core -Version 0.1.0-rc.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ErrorDock.Core" Version="0.1.0-rc.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ErrorDock.Core" Version="0.1.0-rc.1" />
                    
Directory.Packages.props
<PackageReference Include="ErrorDock.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ErrorDock.Core --version 0.1.0-rc.1
                    
#r "nuget: ErrorDock.Core, 0.1.0-rc.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ErrorDock.Core@0.1.0-rc.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ErrorDock.Core&version=0.1.0-rc.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=ErrorDock.Core&version=0.1.0-rc.1&prerelease
                    
Install as a Cake Tool

ErrorDock.Core

The framework-neutral core of the ErrorDock SDK for .NET. Capture, feature tracking, queueing, batching and durable delivery, sent to ErrorDock.

dotnet add package ErrorDock.Core

Targets netstandard2.0 and net8.0, so it runs on .NET Framework 4.7.2 and on .NET 8, 9 and 10 alike.

Which package do you want?

Your application Install
ASP.NET Core ErrorDock.AspNetCore
Worker service, or a console app on the generic host ErrorDock.Extensions.Logging
WinForms ErrorDock.WinForms
WPF ErrorDock.Wpf
Anything else — a plain console app, a plug-in, Avalonia, MAUI this package

Each of those depends on this one and adds the wiring for its framework. You only install ErrorDock.Core directly when there is no such package for what you are building.

Getting started

using ErrorDock;

ErrorDockSdk.Init(options =>
{
    options.ApiKey = "ed_app_…";
    options.Endpoint = "https://api.errordock.com";
    options.Release = typeof(Program).Assembly.GetName().Version?.ToString();
});

AppDomain.CurrentDomain.UnhandledException += (_, e) =>
{
    ErrorDockSdk.Client.CaptureException(e.ExceptionObject as Exception, level: LogEventLevel.Fatal);
    ErrorDockSdk.Shutdown();
};

Init starts the flush loop, the configuration poller and the offline queue. Shutdown sends what it can and keeps what it cannot. ErrorDockSdk.Client is safe to call before Init and after Shutdown — it is never null and never throws.

Use an application key (ed_app_) in anything you ship to somebody else's machine. A server key (ed_live_) is a secret, and a secret inside an installer is a secret your customers hold.

Reporting

ErrorDockSdk.Client.CaptureException(ex, "Order could not be paid");
ErrorDockSdk.Client.CaptureMessage("Nightly run failed to reach the bank", LogEventLevel.Warning);

// A timed execution with an outcome — the denominator of the feature error rate.
var receipt = ErrorDockSdk.Client.RunFeature("checkout", () => _payments.Charge(order));

CaptureMessage obeys MinimumLogLevel — Warning by default — exactly as the ILogger bridge does, so a message at Information is dropped unless you lower the threshold. Exceptions are never subject to it.

using (ErrorDockScope.SetUser(user.Id))
using (ErrorDockScope.SetTag("tenant", tenant.Slug))
{
    // Everything reported in here carries the user and the tag.
}

// The same two on the client, for code that holds an IErrorDockClient rather than a static.
using (client.SetUser(user.Id))
using (client.SetTag("tenant", tenant.Slug))
{
}

User identifiers are not sent unless SendUserIdentifier is turned on. Without it the server sees a hash, which is enough to count affected people and not enough to name them.

client.AddBreadcrumb("Coupon applied", category: "cart");
client.AddBreadcrumb("GET /prices → 503", category: "http", data: new Dictionary<string, string>
{
    ["provider"] = "primary",
});

The last fifty (MaxBreadcrumbs) ride along with the next error and with nothing else. One trail for the process, not one per request: on a server the fifty most recent things that happened anywhere are the ones that explain a crash.

The last look before it leaves

options.BeforeSend = e =>
{
    if (e.Message?.Contains("card number", StringComparison.OrdinalIgnoreCase) == true)
    {
        return null;             // drop it
    }

    e.Tags?.Remove("debug");     // or change it
    return e;
};

BeforeSend runs after the SDK has filled in everything it can — environment, release, the scope, the session, the breadcrumbs — and before the project's remote configuration, so it sees the event as it would be sent and cannot get one past a rule set in the dashboard. A hook that throws drops the event and is reported through OnInternalError.

Every event carries sdk.name and sdk.version tags, and every request a User-Agent: errordock-dotnet/<version> header, so a bug in one SDK release is findable. Batches are gzipped on the way out (CompressRequests, on by default); the server sniffs the magic bytes, so nothing else changes.

The offline queue

A batch that cannot be delivered — no network, a 5xx, a quota that will reset, a process being killed — is written to disk and replayed on a later run, with its original id and timestamp intact so the server recognises it rather than storing it twice.

options.OfflineQueueEnabled = true;                      // the default
options.StoragePath = @"C:\ProgramData\MyApp\errordock";
options.MaxOfflineQueueBytes = 5 * 1024 * 1024;
options.OfflineQueueHorizon = TimeSpan.FromHours(24);

The default location is under the user's local application data. Set StoragePath explicitly in a Windows Service or a container, where the account's profile directory is not somewhere anybody would look — or is thrown away with the container.

Events older than OfflineQueueHorizon are dropped rather than sent. The server replaces any timestamp more than 24 hours old with the time it arrived, so a crash replayed three days late would be filed under today's date and today's release. Dropping it is the honest outcome; sending it is a quiet lie about when it happened. Nothing is encrypted at rest: the queue holds what was about to be sent anyway, and a key stored beside the file it protects is decoration.

Feature flags

if (ErrorDockSdk.FeatureFlags.IsEnabled("new-checkout", userId, defaultValue: false))
{
    // New implementation
}

Evaluation is local. The call reads one immutable in-memory snapshot: no network, no disk, no lock. It returns in roughly a quarter of a microsecond and it cannot throw.

The snapshot is refreshed in the background every thirty seconds with a conditional request, and every validated version is written to disk. So an application that restarts while ErrorDock is unreachable loads its last-known-good configuration before it serves its first request, and one that has never reached ErrorDock at all falls back to the default you passed in.

options.FeatureFlags.Enabled = true;                             // the default
options.FeatureFlags.RefreshInterval = TimeSpan.FromSeconds(30); // the default
options.FeatureFlags.PersistentCache.Enabled = true;             // the default
options.FeatureFlags.PersistentCache.Path = @"C:\ProgramData\MyApp\errordock\flags";

Ask why, when the answer surprises you:

var result = ErrorDockSdk.FeatureFlags.Evaluate("new-checkout", context, defaultValue: false);

result.Reason;                      // percentage_rollout, explicit_target_off, flag_disabled, …
result.ConfigurationAge;            // how old the configuration behind it is
result.IsUsingCachedConfiguration;  // restored from disk, not fetched in this process

A change cannot reach an application that cannot reach ErrorDock. A disconnected SDK keeps its last-known-good configuration until connectivity returns — including through a kill switch. That is the trade: your application's availability comes before your configuration's freshness.

Under dependency injection, inject IErrorDockFeatureFlags rather than using the static. For testing your own branches, ErrorDockFeatureFlags.FromSnapshot(...) hands back the real evaluator over a snapshot you write, so there is no mock to keep in step.

What it guarantees

  • It never throws. Every entry point swallows its own failures; a monitoring SDK that breaks a customer's application is worse than no SDK at all. OnInternalError is there if you want to see what it swallowed.
  • It never blocks. Events go on a bounded queue and are sent in batches by a background sender. A full queue drops the oldest event rather than waiting.
  • It gives up on purpose. A circuit breaker opens after repeated failures, so an ErrorDock outage costs you nothing but the telemetry from it.
  • It brings almost no dependencies. None at all on net8.0. On netstandard2.0 it takes System.Text.Json, Microsoft.Bcl.TimeProvider and System.Diagnostics.DiagnosticSource, because .NET Framework has none of the three.
  • It follows the dashboard. With RemoteConfiguration on, toggling data collection in your project settings changes what this SDK sends within five minutes and without a deploy.
  • It never makes ErrorDock a dependency of your application. Feature flags evaluate from memory, start from disk, and fall back to the default you passed in. Nothing this SDK does can stop your application starting or serving a request.

Licence

MIT. The ErrorDock service itself is proprietary; this SDK is not.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on ErrorDock.Core:

Package Downloads
ErrorDock.Extensions.Logging

ErrorDock for applications built on the .NET generic host: worker services, console applications and Windows Services. Adds AddErrorDock() and an ILogger provider. For ASP.NET Core use ErrorDock.AspNetCore, which builds on this.

ErrorDock.WinForms

ErrorDock for Windows Forms: unhandled UI-thread exceptions, crashes, sessions and feature usage, with a queue that survives a machine with no network.

ErrorDock.Wpf

ErrorDock for WPF: unhandled dispatcher exceptions, crashes, sessions and feature usage, with a queue that survives a machine with no network.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0-rc.1 202 9/9/2026