Lerix 0.3.0
dotnet add package Lerix --version 0.3.0
NuGet\Install-Package Lerix -Version 0.3.0
<PackageReference Include="Lerix" Version="0.3.0" />
<PackageVersion Include="Lerix" Version="0.3.0" />
<PackageReference Include="Lerix" />
paket add Lerix --version 0.3.0
#r "nuget: Lerix, 0.3.0"
#:package Lerix@0.3.0
#addin nuget:?package=Lerix&version=0.3.0
#tool nuget:?package=Lerix&version=0.3.0
Lerix .NET SDK
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 W3Ctraceparentheader is continued by the framework;UseLerix()completes the span with route, status and client address. Only requests that pass throughUseLerix()are traced.Child spans from the runtime's instrumentation:
HttpClientcalls (which carrytraceparentto 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.Instrumentationsswitches each off;AdditionalActivitySourcesadds 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, exceededSlowThreshold(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:
maskedby default (last IPv4 octet zeroed / IPv6 cut to /64 before the address leaves your process),hashedorfullon the Lerix side; the trusted-proxy depth and header decide how it is read fromX-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.Enabledfalse (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 | Versions 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. |
-
.NETStandard 2.0
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.2)
- System.Diagnostics.DiagnosticSource (>= 8.0.1)
- System.Net.Http (>= 4.3.4)
- System.Text.Json (>= 8.0.5)
-
net8.0
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.2)
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.