Lerix 0.3.0

dotnet add package Lerix --version 0.3.0
                    
NuGet\Install-Package Lerix -Version 0.3.0
                    
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="Lerix" Version="0.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Lerix" Version="0.3.0" />
                    
Directory.Packages.props
<PackageReference Include="Lerix" />
                    
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 Lerix --version 0.3.0
                    
#r "nuget: Lerix, 0.3.0"
                    
#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 Lerix@0.3.0
                    
#: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=Lerix&version=0.3.0
                    
Install as a Cake Addin
#tool nuget:?package=Lerix&version=0.3.0
                    
Install as a Cake Tool

Lerix .NET SDK

NuGet .NET License: MIT

Server-side SDK for Lerix, the developer monitoring and engagement platform. Two lines in Program.cs and every unhandled exception in your ASP.NET Core app shows up in the Lerix dashboard with its stack trace, host, release and request context. The same package gives your backend a typed client for sending push notifications to your mobile and web users.

Full documentation lives at docs.lerix.dev.

Package Use it in
Lerix.AspNetCore ASP.NET Core apps (middleware, DI, hosted service). Depends on Lerix.
Lerix Console apps, workers, Azure Functions, or any .NET code without ASP.NET Core

Features

Feature Description
Middleware Reports every exception that escapes the pipeline, then rethrows so UseExceptionHandler still builds the response
Process-level capture AppDomain.UnhandledException and TaskScheduler.UnobservedTaskException are reported
Manual reporting CaptureException and CaptureMessage with type, severity and metadata
Request context Method, URL, route pattern, status code and X-Request-Id attached to every automatic report
Service identity Registered once as a server app, named after the entry assembly, with a persisted anonymous user so restarts do not create duplicates
Push notifications Send, schedule, update, unsend, cancel and read delivery status through the REST API
Configuration binding AddLerix(Configuration.GetSection("Lerix")) or environment variables

Installation

dotnet add package Lerix.AspNetCore

You will need a project API key and project id from Project Settings in the dashboard.

Quick start

using Lerix.AspNetCore;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddLerix(o =>
{
    o.ApiKey = builder.Configuration["LERIX_API_KEY"];
    o.ProjectId = builder.Configuration["LERIX_PROJECT_ID"];
});

var app = builder.Build();
app.UseExceptionHandler("/error");
app.UseLerix();          // after UseExceptionHandler, before routing/endpoints
app.MapControllers();
app.Run();

Or bind from appsettings.json:

{ "Lerix": { "ApiKey": "...", "ProjectId": "...", "Environment": "production" } }
builder.Services.AddLerix(builder.Configuration.GetSection("Lerix"));

ApiKey and ProjectId also fall back to LERIX_API_KEY and LERIX_PROJECT_ID.

Report something you handled yourself:

public class OrdersService(LerixClient lerix)
{
    public async Task Reconcile(string orderId)
    {
        try { await ledger.Reconcile(orderId); }
        catch (Exception error)
        {
            await lerix.CaptureException(error, new CaptureOptions
            {
                Type = BugType.LogicBug,
                Metadata = new Dictionary<string, object?> { ["orderId"] = orderId },
            });
            throw;
        }
    }
}

Options

Option Default Description
ApiKey LERIX_API_KEY Project API key
ProjectId LERIX_PROJECT_ID Project id
Url https://api.lerix.dev/v1 API base URL (LERIX_API_URL)
Environment LERIX_ENVIRONMENT, then ASPNETCORE_ENVIRONMENT Sent with every report as metadata
App from the entry assembly AppInfo { Id, Name, Version, BuildNumber }
Enabled true false makes every call a no-op
Debug false Log every request through ILogger
CaptureUnhandled true Install the process-level handlers
PersistState / StatePath true, .lerix/state.json Where the anonymous user id is kept
UserId Pin the anonymous user id
FlushTimeout 2 s How long shutdown waits for pending reports
Timeout 10 s HTTP timeout per request
ShouldCapture 5xx only (exception, httpContext, status) => bool
IgnorePaths empty Path prefixes whose exceptions are never reported

Request tracing

Off by default. Turn it on to record one span per HTTP request — route template, method, status code, duration — plus the database commands and outbound HttpClient calls it made, shown under Requests in the dashboard and inline on every error page:

builder.Services.AddLerix(o =>
{
    o.ApiKey = "...";
    o.ProjectId = "...";
    o.Tracing.Enabled = true;
});

Built on System.Diagnostics.Activity, so it needs no extra packages:

  • One server span per request, taken from ASP.NET Core's own request activity and named after the route template (GET /users/{id:int}), never the raw path. An incoming W3C traceparent header is continued by the framework; UseLerix() completes the span with route, status and client address. Only requests that pass through UseLerix() are traced.

  • Child spans from the runtime's instrumentation: HttpClient calls (which carry traceparent to the next service) and database drivers that publish activities — Npgsql, Microsoft.Data.SqlClient, MySqlConnector, and EF Core on top of them — with the SQL reduced to a template (SELECT * FROM users WHERE id = ?). o.Tracing.Instrumentations switches each off; AdditionalActivitySources adds your own. Anything else by hand:

    using (LerixTracing.StartChild("cache get", ActivityKind.Client, new Dictionary<string, object?> { ["server.address"] = "redis" }))
    {
        await cache.GetAsync(key);
    }
    
  • Sampling: 10% of successful requests are kept in full (SampleRate); a request that failed, exceeded SlowThreshold (2 s) or reported an error is always kept. The decision is made once at the root and travels in the W3C trace flags. Every request's root span is still sent, so per-route counts and percentiles cover 100% of traffic.

  • Errors carry their trace: every report made inside a request has the request's traceId/spanId; one outside any request records as before.

  • Client addresses follow the policy set in Project settings → Tracing: masked by default (last IPv4 octet zeroed / IPv6 cut to /64 before the address leaves your process), hashed or full on the Lerix side; the trusted-proxy depth and header decide how it is read from X-Forwarded-For, never trusting the whole chain.

  • Spans leave through a bounded queue on the thread pool as OTLP/HTTP JSON; a failed export is counted and dropped, never retried, never thrown. Counters: lerixClient.Tracing?.Stats().

  • With Tracing.Enabled false (the default) no activity listener is registered and nothing changes for the application.

Push notifications

builder.Services.AddLerixNotifications(o =>
{
    o.ProjectId = builder.Configuration["MOBILE_PROJECT_ID"];
    o.ApiKey = builder.Configuration["MOBILE_PROJECT_PRIVATE_KEY"];
});
var result = await push.SendAsync(new SendNotificationInput
{
    Title = "Order shipped",
    Body = "Arrives Tuesday",
    DeviceTokens = new[] { deviceId },
});
await push.UpdateAsync(result.NotificationId, "Order shipped!", "Arrives Monday");
await push.DeliveriesAsync(result.NotificationId);
await push.UnsendAsync(result.NotificationId);

// Every device of your own users (ids passed to setUser() in the client SDKs), on every platform:
var sent = await push.SendAsync(new SendNotificationInput
{
    Title = "New reply",
    Body = "Open the thread",
    ExternalUserIds = new[] { user.Id },
});
// sent.MatchedDevices, sent.UnknownUserIds

Use one target per send (ExternalUserIds can't be combined with the others): DeviceTokens, ExternalUserIds (up to 1000), or SendByTopic with Topic. UnknownUserIds lists ids with no device yet; that is not an error.

If the project requires identity verification, compute the hash the client SDK's setUser(externalId, identityHash) needs on your server, from the project's identity secret (never ship the secret in an app):

var hash = LerixIdentity.IdentityHash(configuration["LERIX_IDENTITY_SECRET"]!, user.Id); // hex HMAC-SHA256

Errors raise LerixApiException with Code, Message and Status.

Development

dotnet test
dotnet pack -c Release -o artifacts

Tests run against an in-process Kestrel mock of the Lerix API (tests/Lerix.Tests/MockLerixApi.cs).

License

MIT

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 (1)

Showing the top 1 NuGet packages that depend on Lerix:

Package Downloads
Lerix.AspNetCore

Lerix SDK for ASP.NET Core: reports unhandled exceptions with request context, traces requests (route, database and HttpClient spans), registers the service on startup and flushes on shutdown. Includes the push notifications client.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.3.0 38 10/2/2026
0.2.0 53 9/30/2026
0.1.0 111 9/11/2026