Sentry .NET SDK
Opinionated wizard that scans your .NET project and guides you through complete Sentry setup: error monitoring, distributed tracing, profiling, structured logging, and cron monitoring across all major .NET frameworks.
Invoke This Skill When
- User asks to "add Sentry to .NET", "set up Sentry in C#", or "install Sentry for ASP.NET Core"
- User wants error monitoring, tracing, profiling, logging, or crons for a .NET app
- User mentions , , , or
- User wants to capture unhandled exceptions in WPF, WinForms, MAUI, or Azure Functions
- User asks about , , , or symbol upload
Note: SDK version and APIs below reflect
NuGet packages ≥6.1.0.
Always verify against
docs.sentry.io/platforms/dotnet/ before implementing.
Phase 1: Detect
Run these commands to understand the project before making any recommendations:
bash
# Detect framework type — find all .csproj files
find . -name "*.csproj" | head -20
# Detect framework targets
grep -r "TargetFramework\|Project Sdk" --include="*.csproj" .
# Check for existing Sentry packages
grep -r "Sentry" --include="*.csproj" . | grep "PackageReference"
# Check startup files
ls Program.cs src/Program.cs App.xaml.cs MauiProgram.cs 2>/dev/null
# Check for appsettings
ls appsettings.json src/appsettings.json 2>/dev/null
# Check for logging libraries
grep -r "Serilog\|NLog\|log4net" --include="*.csproj" .
# Check for companion frontend
ls ../frontend ../client ../web 2>/dev/null
cat ../package.json 2>/dev/null | grep -E '"next"|"react"|"vue"' | head -3
What to determine:
| Question | Impact |
|---|
| Framework type? | Determines correct package and init pattern |
| .NET version? | .NET 8+ recommended; .NET Framework 4.6.2+ supported |
| Sentry already installed? | Skip install, go to feature config |
| Logging library (Serilog, NLog)? | Recommend matching Sentry sink/target |
| Async/hosted app (ASP.NET Core)? | on ; no needed |
| Desktop app (WPF, WinForms, WinUI)? | Must set IsGlobalModeEnabled = true
|
| Serverless (Azure Functions, Lambda)? | Must set FlushOnCompletedRequest = true
|
| Frontend directory found? | Trigger Phase 4 cross-link |
Framework → Package mapping:
| Detected | Package to install |
|---|
Sdk="Microsoft.NET.Sdk.Web"
(ASP.NET Core) | |
| with base | (WPF) |
| in | (WinForms) |
| |
| Sentry.AspNetCore.Blazor.WebAssembly
|
| Sentry.Extensions.Logging
+ |
| / | |
| Generic host / Worker Service | Sentry.Extensions.Logging
|
Phase 2: Recommend
Present a concrete recommendation based on what you found. Lead with a proposal — don't ask open-ended questions.
Recommended (core coverage):
- ✅ Error Monitoring — always; captures unhandled exceptions, structured captures, scope enrichment
- ✅ Tracing — always for ASP.NET Core and hosted apps; auto-instruments HTTP requests and EF Core queries
- ✅ Logging — recommended for all apps; routes ILogger / Serilog / NLog entries to Sentry as breadcrumbs and events
Optional (enhanced observability):
- ⚡ Profiling — CPU profiling; recommend for performance-critical services running on .NET 6+
- ⚡ Crons — detect missed/failed scheduled jobs; recommend when Hangfire, Quartz.NET, or scheduled endpoints detected
Recommendation logic:
| Feature | Recommend when... |
|---|
| Error Monitoring | Always — non-negotiable baseline |
| Tracing | Always for ASP.NET Core — request traces, EF Core spans, HttpClient spans are high-value |
| Logging | App uses , Serilog, NLog, or log4net |
| Profiling | Performance-critical service on .NET 6+ |
| Crons | App uses Hangfire, Quartz.NET, or scheduled Azure Functions |
Propose: "I recommend setting up Error Monitoring + Tracing + Logging. Want me to also add Profiling or Crons?"
Phase 3: Guide
Option 1: Wizard (Recommended)
bash
npx @sentry/wizard@latest -i dotnet
The wizard logs you into Sentry, selects your org and project, configures your DSN, and sets up MSBuild symbol upload for readable stack traces in production.
Skip to Verification after running the wizard.
Option 2: Manual Setup
Install the right package
bash
# ASP.NET Core
dotnet add package Sentry.AspNetCore -v 6.1.0
# WPF or WinForms or Console
dotnet add package Sentry -v 6.1.0
# .NET MAUI
dotnet add package Sentry.Maui -v 6.1.0
# Blazor WebAssembly
dotnet add package Sentry.AspNetCore.Blazor.WebAssembly -v 6.1.0
# Azure Functions (Isolated Worker)
dotnet add package Sentry.Extensions.Logging -v 6.1.0
dotnet add package Sentry.OpenTelemetry -v 6.1.0
# Classic ASP.NET (System.Web / .NET Framework)
dotnet add package Sentry.AspNet -v 6.1.0
ASP.NET Core —
csharp
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseSentry(options =>
{
options.Dsn = Environment.GetEnvironmentVariable("SENTRY_DSN")
?? "___YOUR_DSN___";
options.Debug = true; // disable in production
options.SendDefaultPii = true; // captures user IP, name, email
options.MaxRequestBodySize = RequestSize.Always;
options.MinimumBreadcrumbLevel = LogLevel.Debug;
options.MinimumEventLevel = LogLevel.Warning;
options.TracesSampleRate = 1.0; // tune to 0.1–0.2 in production
options.SetBeforeSend((@event, hint) =>
{
@event.ServerName = null; // scrub hostname from events
return @event;
});
});
var app = builder.Build();
app.Run();
(alternative configuration):
json
{
"Sentry": {
"Dsn": "___YOUR_DSN___",
"SendDefaultPii": true,
"MaxRequestBodySize": "Always",
"MinimumBreadcrumbLevel": "Debug",
"MinimumEventLevel": "Warning",
"AttachStacktrace": true,
"Debug": true,
"TracesSampleRate": 1.0,
"Environment": "production",
"Release": "my-app@1.0.0"
}
}
Environment variables (double underscore as separator):
bash
export Sentry__Dsn="https://examplePublicKey@o0.ingest.sentry.io/0"
export Sentry__TracesSampleRate="0.1"
export Sentry__Environment="staging"
WPF —
⚠️
Critical: Initialize in the
constructor, NOT in
. The constructor fires earlier, catching more failure modes.
csharp
using System.Windows;
using Sentry;
public partial class App : Application
{
public App()
{
SentrySdk.Init(options =>
{
options.Dsn = "___YOUR_DSN___";
options.Debug = true;
options.SendDefaultPii = true;
options.TracesSampleRate = 1.0;
options.IsGlobalModeEnabled = true; // required for all desktop apps
});
// Capture WPF UI-thread exceptions before WPF's crash dialog appears
DispatcherUnhandledException += App_DispatcherUnhandledException;
}
private void App_DispatcherUnhandledException(
object sender,
System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
SentrySdk.CaptureException(e.Exception);
// Set e.Handled = true to prevent crash dialog and keep app running
}
}
WinForms —
csharp
using System;
using System.Windows.Forms;
using Sentry;
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Required: allows Sentry to see unhandled WinForms exceptions
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
using (SentrySdk.Init(new SentryOptions
{
Dsn = "___YOUR_DSN___",
Debug = true,
TracesSampleRate = 1.0,
IsGlobalModeEnabled = true, // required for desktop apps
}))
{
Application.Run(new MainForm());
} // Disposing flushes all pending events
}
}
.NET MAUI —
csharp
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseSentry(options =>
{
options.Dsn = "___YOUR_DSN___";
options.Debug = true;
options.SendDefaultPii = true;
options.TracesSampleRate = 1.0;
// MAUI-specific: opt-in breadcrumbs (off by default — PII risk)
options.IncludeTextInBreadcrumbs = false;
options.IncludeTitleInBreadcrumbs = false;
options.IncludeBackgroundingStateInBreadcrumbs = false;
});
return builder.Build();
}
}
Blazor WebAssembly —
csharp
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.UseSentry(options =>
{
options.Dsn = "___YOUR_DSN___";
options.Debug = true;
options.SendDefaultPii = true;
options.TracesSampleRate = 0.1;
});
// Hook logging pipeline without re-initializing the SDK
builder.Logging.AddSentry(o => o.InitializeSdk = false);
await builder.Build().RunAsync();
Azure Functions (Isolated Worker) —
csharp
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using OpenTelemetry.Trace;
using Sentry.OpenTelemetry;
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureServices(services =>
{
services.AddOpenTelemetry().WithTracing(builder =>
{
builder
.AddSentry() // route OTel spans to Sentry
.AddHttpClientInstrumentation(); // capture outgoing HTTP
});
})
.ConfigureLogging(logging =>
{
logging.AddSentry(options =>
{
options.Dsn = "___YOUR_DSN___";
options.Debug = true;
options.TracesSampleRate = 1.0;
options.UseOpenTelemetry(); // let OTel drive tracing
options.DisableSentryHttpMessageHandler = true; // prevent duplicate HTTP spans
});
})
.Build();
await host.RunAsync();
AWS Lambda —
csharp
public class LambdaEntryPoint : APIGatewayProxyFunction
{
protected override void Init(IWebHostBuilder builder)
{
builder
.UseSentry(options =>
{
options.Dsn = "___YOUR_DSN___";
options.TracesSampleRate = 1.0;
options.FlushOnCompletedRequest = true; // REQUIRED for Lambda
})
.UseStartup<Startup>();
}
}
Classic ASP.NET —
csharp
public class MvcApplication : HttpApplication
{
private IDisposable _sentry;
protected void Application_Start()
{
_sentry = SentrySdk.Init(options =>
{
options.Dsn = "___YOUR_DSN___";
options.TracesSampleRate = 1.0;
options.AddEntityFramework(); // EF6 query breadcrumbs
options.AddAspNet(); // Classic ASP.NET integration
});
}
protected void Application_Error() => Server.CaptureLastError();
protected void Application_BeginRequest() => Context.StartSentryTransaction();
protected void Application_EndRequest() => Context.FinishSentryTransaction();
protected void Application_End() => _sentry?.Dispose();
}
Symbol Upload (Readable Stack Traces)
Without debug symbols, stack traces show only method names — no file names or line numbers. Upload PDB files to unlock full source context.
Step 1: Create a Sentry auth token
Go to
sentry.io/settings/auth-tokens/ and create a token with
and
scopes.
Step 2: Add MSBuild properties to or :
xml
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<SentryOrg>___ORG_SLUG___</SentryOrg>
<SentryProject>___PROJECT_SLUG___</SentryProject>
<SentryUploadSymbols>true</SentryUploadSymbols>
<SentryUploadSources>true</SentryUploadSources>
<SentryCreateRelease>true</SentryCreateRelease>
<SentrySetCommits>true</SentrySetCommits>
</PropertyGroup>
yaml
# GitHub Actions
- name: Build & upload symbols
run: dotnet build -c Release
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
For Each Agreed Feature
Load the corresponding reference file and follow its steps:
| Feature | Reference file | Load when... |
|---|
| Error Monitoring | references/error-monitoring.md
| Always — , scopes, enrichment, filtering |
| Tracing | | Server apps, distributed tracing, EF Core spans, custom instrumentation |
| Profiling | | Performance-critical apps on .NET 6+ |
| Logging | | , Serilog, NLog, log4net integration |
| Crons | | Hangfire, Quartz.NET, or scheduled function monitoring |
For each feature: read the reference file, follow its steps exactly, and verify before moving on.
Verification
After wizard or manual setup, add a test throw and remove it after verifying:
csharp
// ASP.NET Core: add a temporary endpoint
app.MapGet("/sentry-test", () =>
{
throw new Exception("Sentry test error — delete me");
});
// Or capture explicitly anywhere
SentrySdk.CaptureException(new Exception("Sentry test error — delete me"));
Then check your
Sentry Issues dashboard — the error should appear within ~30 seconds.
Verification checklist:
| Check | How |
|---|
| Exceptions captured | Throw a test exception, verify in Sentry Issues |
| Stack traces readable | Check that file names and line numbers appear |
| Tracing active | Check Performance tab for transactions |
| Logging wired | Log an error via , check it appears as Sentry breadcrumb |
| Symbol upload working | Stack trace shows Controllers/HomeController.cs:42
not |
Config Reference
Core
| Option | Type | Default | Env Var | Notes |
|---|
| | — | | Required. SDK disabled if unset. |
| | | — | SDK diagnostic output. Disable in production. |
| | | — | , , , , |
| | auto | | Auto-detected from assembly version + git SHA |
| | | | when debugger attached |
| | — | — | Build variant. Max 64 chars. |
| | | — | Error event sampling rate 0.0–1.0 |
| | | — | Transaction sampling. Must be to enable. |
| Func<SamplingContext, double>
| — | — | Per-transaction dynamic sampler; overrides |
| | | — | Fraction of traced transactions to profile. Requires . |
| | | — | Include user IP, name, email |
| | | — | Attach stack trace to all messages |
| | | — | Max breadcrumbs stored per event |
| | * | — | *Auto- for MAUI, Blazor WASM. Must be for WPF, WinForms, Console. |
| | * | — | *Auto- for MAUI. Enable for Release Health. |
| | | — | Auto-capture HTTP client errors |
| | — | — | Offline event caching directory |
| | — | — | Max wait for event flush on shutdown |
| | — | — | Proxy URL for Sentry requests |
EnableBackpressureHandling
| | | — | Auto-reduce sample rates on delivery failures |
ASP.NET Core Extended Options ()
| Option | Type | Default | Notes |
|---|
| | | , (~4 KB), (~10 KB), |
| | | Min log level for breadcrumbs |
| | | Min log level to send as Sentry event |
| | | Detect / threadpool starvation |
| | | Required for Lambda / serverless |
| | | Capture System.Diagnostics.Activity
values |
MAUI Extended Options ()
| Option | Type | Default | Notes |
|---|
| | | Text from , , elements. ⚠️ PII risk. |
IncludeTitleInBreadcrumbs
| | | Titles from , elements. ⚠️ PII risk. |
IncludeBackgroundingStateInBreadcrumbs
| | | event state. ⚠️ PII risk. |
Environment Variables
| Variable | Purpose |
|---|
| Project DSN |
| App version (e.g. ) |
| Deployment environment name |
| MSBuild / symbol upload auth token |
ASP.NET Core: use double underscore
as hierarchy separator:
bash
export Sentry__Dsn="https://..."
export Sentry__TracesSampleRate="0.1"
MSBuild Symbol Upload Properties
| Property | Type | Default | Description |
|---|
| | — | Sentry organization slug |
| | — | Sentry project slug |
| | | Upload PDB files for line numbers in stack traces |
| | | Upload source files for source context |
| | | Auto-create a Sentry release during build |
| | | Associate git commits with the release |
| | — | Self-hosted Sentry URL |
Phase 4: Cross-Link
After completing .NET setup, check for companion frontend projects:
bash
# Check for frontend in adjacent directories
ls ../frontend ../client ../web ../app 2>/dev/null
# Check for JavaScript framework indicators
cat ../package.json 2>/dev/null | grep -E '"next"|"react"|"vue"|"nuxt"' | head -3
If a frontend is found, suggest the matching SDK skill:
Connecting frontend and backend with the same Sentry project enables distributed tracing — a single trace view spanning browser, .NET server, and any downstream APIs.
Troubleshooting
| Issue | Cause | Solution |
|---|
| Events not appearing | DSN misconfigured | Set and check console output for SDK diagnostic messages |
| Stack traces show no file/line | PDB files not uploaded | Add to ; set in CI |
| WPF/WinForms exceptions missing | not set | Set options.IsGlobalModeEnabled = true
in |
| Lambda/serverless events lost | Container freezes before flush | Set options.FlushOnCompletedRequest = true
|
| WPF UI-thread exceptions missing | DispatcherUnhandledException
not wired | Register App.DispatcherUnhandledException
in constructor (not ) |
| Duplicate HTTP spans in Azure Functions | Both Sentry and OTel instrument HTTP | Set options.DisableSentryHttpMessageHandler = true
|
| has no effect | Rate is (default) | Set to enable tracing |
| values ignored | Config key format wrong | Use flat key or env var (double underscore) |
| drops all events | Hook returns unconditionally | Verify your filter logic; return only for events you want to drop |
| MAUI native crashes not captured | Wrong package | Confirm is installed (not just ) |