sentry-dotnet-sdk

Full Sentry SDK setup for .NET. Use when asked to "add Sentry to .NET", "install Sentry for C#", or configure error monitoring, tracing, profiling, logging, or…

INSTALLATION
npx skills add https://github.com/getsentry/sentry-for-ai --skill sentry-dotnet-sdk
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$2b

Phase 1: Detect

Run these commands to understand the project before making any recommendations:

# 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)?

UseSentry() on WebHost; no IsGlobalModeEnabled 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)

Sentry.AspNetCore

App.xaml.cs with Application base

Sentry (WPF)

[STAThread] in Program.cs

Sentry (WinForms)

MauiProgram.cs

Sentry.Maui

WebAssemblyHostBuilder

Sentry.AspNetCore.Blazor.WebAssembly

FunctionsStartup

Sentry.Extensions.Logging + Sentry.OpenTelemetry

HttpApplication / Global.asax

Sentry.AspNet

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+
  • Metrics — counters, gauges, distributions linked to traces; recommend for apps that need custom business metrics
  • 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 ILogger<T>, Serilog, NLog, or log4net

Profiling

Performance-critical service on .NET 6+

Metrics

App needs custom business metrics (request counts, queue depths, response times)

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)

You need to run this yourself — the wizard opens a browser for login and requires interactive input that the agent can't handle. Copy-paste into your terminal:

npx @sentry/wizard@latest -i dotnet

It handles login, org/project selection, DSN configuration, and MSBuild symbol upload setup for readable stack traces in production.

Once it finishes, come back and skip to [Verification](#verification).

If the user skips the wizard, proceed with Option 2 (Manual Setup) below.

Option 2: Manual Setup

#### Install the right package

# 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 — Program.cs

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

**appsettings.json (alternative configuration):**

{

  "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):

export Sentry__Dsn="https://examplePublicKey@o0.ingest.sentry.io/0"

export Sentry__TracesSampleRate="0.1"

export Sentry__Environment="staging"

#### WPF — App.xaml.cs

⚠️ Critical: Initialize in the constructor, NOT in OnStartup(). The constructor fires earlier, catching more failure modes.

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 — Program.cs

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 — MauiProgram.cs

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 — Program.cs

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) — Program.cs

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 — LambdaEntryPoint.cs

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 — Global.asax.cs

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 project:releases and org:read scopes.

**Step 2: Add MSBuild properties to .csproj or Directory.Build.props:**

<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>

**Step 3: Set SENTRY_AUTH_TOKEN in CI:**

# GitHub Actions

- name: Build &#x26; 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 — CaptureException, scopes, enrichment, filtering

Tracing

references/tracing.md

Server apps, distributed tracing, EF Core spans, custom instrumentation

Profiling

references/profiling.md

Performance-critical apps on .NET 6+

Logging

references/logging.md

ILogger<T>, Serilog, NLog, log4net integration

Metrics

references/metrics.md

Custom counters, gauges, distributions; EmitCounter, EmitGauge, EmitDistribution

Crons

references/crons.md

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:

// 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 ILogger, check it appears as Sentry breadcrumb

Symbol upload working

Stack trace shows Controllers/HomeController.cs:42 not <unknown>

Config Reference

Core SentryOptions

Option

Type

Default

Env Var

Notes

Dsn

string

SENTRY_DSN

Required. SDK disabled if unset.

Debug

bool

false

SDK diagnostic output. Disable in production.

DiagnosticLevel

SentryLevel

Debug

Debug, Info, Warning, Error, Fatal

Release

string

auto

SENTRY_RELEASE

Auto-detected from assembly version + git SHA

Environment

string

"production"

SENTRY_ENVIRONMENT

"debug" when debugger attached

Dist

string

Build variant. Max 64 chars.

SampleRate

float

1.0

Error event sampling rate 0.0–1.0

TracesSampleRate

double

0.0

Transaction sampling. Must be > 0 to enable.

TracesSampler

Func<SamplingContext, double>

Per-transaction dynamic sampler; overrides TracesSampleRate

ProfilesSampleRate

double

0.0

Fraction of traced transactions to profile. Requires Sentry.Profiling.

SendDefaultPii

bool

false

Include user IP, name, email

AttachStacktrace

bool

true

Attach stack trace to all messages

MaxBreadcrumbs

int

100

Max breadcrumbs stored per event

IsGlobalModeEnabled

bool

false*

*Auto-true for MAUI, Blazor WASM. Must be true for WPF, WinForms, Console.

AutoSessionTracking

bool

false*

*Auto-true for MAUI. Enable for Release Health.

CaptureFailedRequests

bool

true

Auto-capture HTTP client errors

CacheDirectoryPath

string

Offline event caching directory

ShutdownTimeout

TimeSpan

Max wait for event flush on shutdown

HttpProxy

string

Proxy URL for Sentry requests

EnableBackpressureHandling

bool

true

Auto-reduce sample rates on delivery failures

TraceIgnoreStatusCodes

IList<HttpStatusCodeRange>

[]

Drop transactions whose HTTP response status matches any range; e.g., [404] or [(500, 599)]

ASP.NET Core Extended Options ( SentryAspNetCoreOptions )

Option

Type

Default

Notes

MaxRequestBodySize

RequestSize

None

None, Small (~4 KB), Medium (~10 KB), Always

MinimumBreadcrumbLevel

LogLevel

Information

Min log level for breadcrumbs

MinimumEventLevel

LogLevel

Error

Min log level to send as Sentry event

CaptureBlockingCalls

bool

false

Detect .Wait() / .Result threadpool starvation

FlushOnCompletedRequest

bool

false

Required for Lambda / serverless

IncludeActivityData

bool

false

Capture System.Diagnostics.Activity values

MAUI Extended Options ( SentryMauiOptions )

Option

Type

Default

Notes

IncludeTextInBreadcrumbs

bool

false

Text from Button, Label, Entry elements. ⚠️ PII risk.

IncludeTitleInBreadcrumbs

bool

false

Titles from Window, Page elements. ⚠️ PII risk.

IncludeBackgroundingStateInBreadcrumbs

bool

false

Window.Backgrounding event state. ⚠️ PII risk.

Environment Variables

Variable

Purpose

SENTRY_DSN

Project DSN

SENTRY_RELEASE

App version (e.g. my-app@1.2.3)

SENTRY_ENVIRONMENT

Deployment environment name

SENTRY_AUTH_TOKEN

MSBuild / sentry-cli symbol upload auth token

ASP.NET Core: use double underscore __ as hierarchy separator:

export Sentry__Dsn="https://..."

export Sentry__TracesSampleRate="0.1"

MSBuild Symbol Upload Properties

Property

Type

Default

Description

SentryOrg

string

Sentry organization slug

SentryProject

string

Sentry project slug

SentryUploadSymbols

bool

false

Upload PDB files for line numbers in stack traces

SentryUploadSources

bool

false

Upload source files for source context

SentryCreateRelease

bool

false

Auto-create a Sentry release during build

SentrySetCommits

bool

false

Associate git commits with the release

SentryUrl

string

Self-hosted Sentry URL

Phase 4: Cross-Link

After completing .NET setup, check for companion frontend projects:

# 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:

Frontend detected

Suggest skill

Next.js ("next" in package.json)

sentry-nextjs-sdk

React SPA ("react" without "next")

@sentry/react — see docs.sentry.io/platforms/javascript/guides/react/

Vue.js

@sentry/vue — see docs.sentry.io/platforms/javascript/guides/vue/

Nuxt

@sentry/nuxt — see docs.sentry.io/platforms/javascript/guides/nuxt/

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 Debug = true and check console output for SDK diagnostic messages

Stack traces show no file/line

PDB files not uploaded

Add SentryUploadSymbols=true to .csproj; set SENTRY_AUTH_TOKEN in CI

WPF/WinForms exceptions missing

IsGlobalModeEnabled not set

Set options.IsGlobalModeEnabled = true in SentrySdk.Init()

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 OnStartup)

Duplicate HTTP spans in Azure Functions

Both Sentry and OTel instrument HTTP

Set options.DisableSentryHttpMessageHandler = true

TracesSampleRate has no effect

Rate is 0.0 (default)

Set TracesSampleRate > 0 to enable tracing

appsettings.json values ignored

Config key format wrong

Use flat key "Sentry:Dsn" or env var Sentry__Dsn (double underscore)

BeforeSend drops all events

Hook returns null unconditionally

Verify your filter logic; return null only for events you want to drop

MAUI native crashes not captured

Wrong package

Confirm Sentry.Maui is installed (not just Sentry)

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card