Skip to content

Checkend/checkend-dotnet

Repository files navigation

Checkend .NET SDK

Test

.NET SDK for Checkend error monitoring. Async by default with ASP.NET Core integration.

Works with both the hosted service and self-hosted Checkend server.

Features

  • Async by default - Non-blocking error sending via Channel
  • ASP.NET Core Middleware - Easy integration with web apps
  • Automatic context - Request, user, and custom context tracking
  • Sensitive data filtering - Automatic scrubbing of passwords, tokens, etc.
  • Testing utilities - Capture errors in tests without sending

Requirements

  • .NET 8.0+
  • No external dependencies

Installation

NuGet

dotnet add package Checkend

Package Manager

Install-Package Checkend

Quick Start

using Checkend;

// Configure the SDK
CheckendClient.Configure(builder => builder
    .ApiKey("your-api-key")
    .Endpoint("https://your-checkend-server.com")
);

// Report an error
try
{
    DoSomething();
}
catch (Exception ex)
{
    CheckendClient.Notify(ex);
}

Configuration

CheckendClient.Configure(builder => builder
    .ApiKey("your-api-key")                       // Required
    .Endpoint("https://your-checkend-server.com") // Required
    .Environment("production")            // Optional: Auto-detected
    .Enabled(true)                        // Optional: Enable/disable
    .AsyncSend(true)                      // Optional: Async sending (default: true)
    .MaxQueueSize(1000)                   // Optional: Max queue size
    .Timeout(15000)                       // Optional: HTTP timeout in ms
    .AddFilterKey("custom_secret")        // Optional: Additional keys to filter
    .AddIgnoredException<MyException>()   // Optional: Exceptions to ignore
    .Debug(false)                         // Optional: Enable debug logging
);

Environment Variables

CHECKEND_API_KEY=your-api-key
CHECKEND_ENDPOINT=https://your-server.com
CHECKEND_ENVIRONMENT=production
CHECKEND_DEBUG=true

Manual Error Reporting

// Basic error reporting
try
{
    RiskyOperation();
}
catch (Exception ex)
{
    CheckendClient.Notify(ex);
}

// With additional context
try
{
    ProcessOrder(orderId);
}
catch (Exception ex)
{
    CheckendClient.Notify(ex, new NoticeOptions
    {
        Context = new Dictionary<string, object?> { ["order_id"] = orderId },
        User = new Dictionary<string, object?> { ["id"] = userId, ["email"] = userEmail },
        Tags = new List<string> { "orders", "critical" },
        Fingerprint = "order-processing-error"
    });
}

// Synchronous sending (blocks until sent)
var response = await CheckendClient.NotifySyncAsync(ex);
if (response.IsSuccess)
{
    Console.WriteLine("Notice sent successfully");
}

Context & User Tracking

// Set context for all errors in this async context
CheckendClient.SetContext(new Dictionary<string, object?>
{
    ["order_id"] = 12345,
    ["feature_flag"] = "new-checkout"
});

// Set user information
CheckendClient.SetUser(new Dictionary<string, object?>
{
    ["id"] = user.Id,
    ["email"] = user.Email,
    ["name"] = user.Name
});

// Set request information
CheckendClient.SetRequest(new Dictionary<string, object?>
{
    ["url"] = HttpContext.Request.Path,
    ["method"] = HttpContext.Request.Method
});

// Clear all context (call at end of request)
CheckendClient.Clear();

ASP.NET Core Integration

Using Middleware

// Program.cs
var builder = WebApplication.CreateBuilder(args);

// Add Checkend using configuration
builder.Services.AddCheckend(builder.Configuration);
// Or configure directly
builder.Services.AddCheckend(config => config
    .ApiKey("your-api-key")
    .Endpoint("https://your-checkend-server.com")
    .Environment("production")
);

var app = builder.Build();

// Use Checkend middleware for automatic error reporting
app.UseCheckend();

app.Run();

appsettings.json

{
  "Checkend": {
    "ApiKey": "your-api-key",
    "Endpoint": "https://your-checkend-server.com",
    "Environment": "production",
    "Enabled": true,
    "Debug": false
  }
}

Global Exception Handler

app.UseExceptionHandler(errorApp =>
{
    errorApp.Run(async context =>
    {
        var exceptionFeature = context.Features.Get<IExceptionHandlerFeature>();
        if (exceptionFeature?.Error != null)
        {
            CheckendClient.Notify(exceptionFeature.Error);
        }

        context.Response.StatusCode = 500;
        await context.Response.WriteAsync("Internal Server Error");
    });
});

Testing

Use the Testing class to capture errors without sending them:

using Checkend;
using Xunit;

public class MyTests : IDisposable
{
    public MyTests()
    {
        Testing.Setup();
        CheckendClient.Configure(builder => builder
            .ApiKey("test-key")
            .Endpoint("https://your-checkend-server.com")
            .Enabled(true)
        );
    }

    public void Dispose()
    {
        Testing.Teardown();
        CheckendClient.ResetAsync().GetAwaiter().GetResult();
    }

    [Fact]
    public void TestErrorReporting()
    {
        try
        {
            throw new InvalidOperationException("Test error");
        }
        catch (Exception ex)
        {
            CheckendClient.Notify(ex);
        }

        Assert.True(Testing.HasNotices());
        Assert.Equal(1, Testing.NoticeCount());

        var notice = Testing.LastNotice();
        Assert.Equal("System.InvalidOperationException", notice?.ErrorClass);
    }
}

Filtering Sensitive Data

By default, these keys are filtered: password, secret, token, api_key, authorization, credit_card, cvv, ssn, etc.

Add custom keys:

CheckendClient.Configure(builder => builder
    .ApiKey("your-api-key")
    .AddFilterKey("custom_secret")
    .AddFilterKey("internal_token")
);

Filtered values appear as [FILTERED] in the dashboard.

Ignoring Exceptions

CheckendClient.Configure(builder => builder
    .ApiKey("your-api-key")
    .AddIgnoredException<ResourceNotFoundException>()
    .AddIgnoredException("OperationCanceledException")
    .AddIgnoredException(new Regex(".*NotFound.*"))
);

Before Notify Callbacks

CheckendClient.Configure(builder => builder
    .ApiKey("your-api-key")
    .AddBeforeNotify(notice =>
    {
        // Add extra context
        notice.Context["server"] = Environment.MachineName;
        return notice;
    })
    .AddBeforeNotify(notice =>
    {
        // Skip certain errors
        if (notice.Message.Contains("ignore-me"))
        {
            return false;
        }
        return true;
    })
);

Graceful Shutdown

The SDK automatically flushes pending notices. For manual control:

// Wait for pending notices to send
await CheckendClient.FlushAsync();

// Stop the worker
await CheckendClient.StopAsync();

Development

# Build
dotnet build

# Run tests
dotnet test

# Pack
dotnet pack

Publishing to NuGet

Via GitHub Actions UI (Recommended)

  1. Go to ActionsPublish to NuGetRun workflow
  2. Enter the version number (e.g., 0.2.0)
  3. Click Run workflow

The workflow will automatically:

  • Update the version in the csproj
  • Build and run tests
  • Commit the version change
  • Create a git tag and GitHub release
  • Publish to NuGet

Via GitHub Release

  1. Update the version in src/Checkend/Checkend.csproj
  2. Commit and push the version change
  3. Create a new GitHub release with a tag (e.g., v0.1.0)
  4. The publish workflow will automatically build, test, and push to NuGet

Manual Publishing

dotnet pack src/Checkend/Checkend.csproj -c Release
dotnet nuget push src/Checkend/bin/Release/Checkend.*.nupkg \
  --api-key YOUR_API_KEY \
  --source https://api.nuget.org/v3/index.json

License

MIT License - see LICENSE for details.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •