[TRANSLATE] Sentry Everywhere: Blazor, .NET MAUI and PHP Error Tracking
[TRANSLATE] One error-tracking tool for every Blazor, .NET MAUI and PHP project: performance alerts, release health, a generous free tier, and an MCP that AIs can drive.
Introduction
I maintain a lot of different things: Blazor web apps, .NET MAUI mobile apps on iOS and Android, and β currently β a legacy PHP project I inherited. Three runtimes, three deployment stories, three sets of "how do I even know it broke in production".
For years the answer was the same for all of them: Sentry. One account, one mental model, one dashboard. A crash on an iPhone, a 500 on a Razor page, and a PHP fatal all land in the same place, grouped, symbolicated, with the breadcrumbs that led up to them.
This post is why I keep reaching for it, what it actually does beyond "log the exception", how generous the free tier really is, how to install and use it on each stack, and the part that changed how I work day to day: Sentry has an MCP server that an AI assistant can connect to directly β to read issues, pull stack traces, run root-cause analysis, apply a fix, and resolve the issue, with you reviewing instead of copy-pasting.
Why one tool across every stack
The value is not any single feature β it is that I only learn it once.
- The issue grouping works the same whether the exception came from
Sentry.Maui,Sentry.AspNetCore, orsentry/sentry-laravel. - Breadcrumbs, tags, user context, environments, releases β same concepts, same UI, everywhere.
- Alerts route to the same Slack channel no matter which project fired.
- When I bump an app version (I automate this β see Stop Manually Bumping Version Numbers), the
releasetag flows into Sentry and I get regression detection and crash-free rate per release for free.
Context-switching between a mobile bug and a web bug costs almost nothing because the tool doesn't change.
What Sentry actually gives you
Error tracking that is genuinely useful
- Smart grouping β a thousand occurrences of the same bug are one issue, with a count and a sparkline, not a thousand log lines.
- Full stack traces with source context β for .NET it reads your PDBs; for mobile it symbolicates with dSYM (iOS) and ProGuard/R8 mapping files (Android); for PHP it shows the surrounding source lines.
- Breadcrumbs β the trail of navigation, HTTP calls, log lines, and DB queries that happened before the crash. This is the single most useful thing when a bug won't reproduce.
- Rich context β device model, OS, app version, memory, the current user, custom tags, and whatever structured data you attach.
- Suspect commits β with a GitHub/GitLab integration, Sentry points at the commit (and author) that most likely introduced the regression.
Fixes PROJECT-123in a commit message auto-resolves the issue when it merges/deploys.
Performance monitoring and automatic performance alerts
Sentry doesn't just catch exceptions β it traces transactions and flags slow patterns automatically. You don't write rules for these; it detects them:
- N+1 database queries and N+1 API calls
- Slow DB queries (with the actual SQL and the span timing)
- Consecutive DB queries that should be batched
- Render-blocking / uncompressed / oversized assets on the web
- File I/O on the main thread, image decoding on the main thread (mobile)
- Slow and frozen frames, app hangs / ANRs, and cold-start time on MAUI
- Web Vitals (LCP, INP, CLS) for Blazor front-ends
Each one becomes an issue with a trace attached, so you go from "the app feels slow" to "this endpoint runs the same SELECT 47 times" in two clicks.
Release health and crash-free rates
For MAUI this is the headline feature. Per release you get:
- Crash-free sessions and crash-free users percentages
- Adoption β how many users are on the new build
- Regressions β issues that were resolved and came back
- A clean "is this release safe to roll out wider?" signal
Session Replay and logs
- Session Replay β a DOM-level recording of the user's session leading up to an error (web), with network and console captured, and PII masking on by default.
- Logs β structured application logs alongside the errors and traces, searchable in the same place (newer feature, rolling out across SDKs).
- Uptime and cron monitoring β ping checks and "did my scheduled job run" checks, with alerts when they miss.
Alerts that don't become noise
Two kinds:
- Issue alerts β "a new issue appeared", "an issue regressed", "this issue crossed N events in 1 hour", "it's affecting more than N users".
- Metric alerts β error rate, p95 latency, failure rate, Apdex, crash-free rate dropping below a threshold.
Route them to Slack, email, PagerDuty, Discord, MS Teams, Jira, GitHub issues, or a webhook. Spike protection caps runaway ingestion so one broken deploy doesn't burn your whole quota (or your budget) in an hour.
The free tier is genuinely usable
The Developer plan is free and, unlike a lot of "free tiers", you can actually run a small production app on it. As of writing it includes (check the current numbers β Sentry adjusts them):
- ~5,000 errors / month
- A pool of performance spans / tracing units
- ~50 session replays / month
- 1 GB of attachments
- 1 uptime monitor and a handful of cron monitors
- Full feature access β performance, release health, alerts, integrations, and the MCP are not paywalled on the free plan; you're limited by volume, not by capability
For side projects and the smaller apps I maintain, I've never left the free tier. When you outgrow it, the paid Team plan is pay-as-you-go on volume.
Sentry is also source-available and self-hostable if you'd rather run it yourself β the same product, on your own infrastructure.
How to install and use it
The pattern is the same everywhere: create a project in Sentry, copy the DSN (the ingest URL), initialize the SDK as early as possible, and β for anything compiled or minified β upload your debug files in CI.
.NET MAUI
1. Add the package:
dotnet add package Sentry.Maui
2. Wire it up in MauiProgram.cs β UseSentry goes right after CreateBuilder:
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseSentry(options =>
{
options.Dsn = "https://examplePublicKey@o0.ingest.sentry.io/0";
options.Environment = "production";
// Performance: sample a fraction of transactions (1.0 = everything).
options.TracesSampleRate = 0.2;
// Release health: crash-free rate per version.
options.AutoSessionTracking = true;
// Privacy: opt in explicitly before sending user data.
options.SendDefaultPii = false;
// Drop or scrub events before they leave the device.
options.SetBeforeSend(e =>
e.Exception is OperationCanceledException ? null : e);
});
return builder.Build();
}
options.Release is picked up from your app version automatically, so it lines up with your store build number.
3. Capture what you care about. Unhandled exceptions and crashes are automatic. For handled ones, a small wrapper keeps your call sites clean and lets you filter noise centrally:
public static class SentryHelper
{
public static void CaptureExceptionWithUser(Exception ex, string operation)
{
// Skip transient network/timeout noise
if (ex is HttpRequestException or TimeoutException or TaskCanceledException)
return;
SentrySdk.ConfigureScope(scope =>
{
scope.SetTag("operation", operation);
scope.User = new SentryUser { Id = Settings.CurrentUserId };
});
SentrySdk.CaptureException(ex);
}
}
4. Upload symbols in CI so iOS/Android stack traces are readable. The Sentry.Maui build integration can do this automatically when you set your org, project, and an auth token as MSBuild properties / environment variables (SENTRY_ORG, SENTRY_PROJECT, SENTRY_AUTH_TOKEN) β or run sentry-cli debug-files upload in your pipeline.
Blazor
Blazor Server / any ASP.NET Core host β add Sentry.AspNetCore and one line in Program.cs:
dotnet add package Sentry.AspNetCore
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseSentry(options =>
{
options.Dsn = "https://examplePublicKey@o0.ingest.sentry.io/0";
options.Environment = builder.Environment.EnvironmentName;
options.TracesSampleRate = 0.2;
options.SendDefaultPii = false;
});
That captures unhandled exceptions, request context, and traces across your endpoints and HttpClient calls.
Blazor WebAssembly β add Sentry and initialize in Program.cs before the host runs:
SentrySdk.Init(options =>
{
options.Dsn = "https://examplePublicKey@o0.ingest.sentry.io/0";
options.TracesSampleRate = 0.2;
});
Wrap your UI in an error boundary so component exceptions are reported rather than blanking the page, and upload your source maps in CI (sentry-cli sourcemaps upload) so WASM/JS traces point at real lines.
PHP (Laravel and plain PHP)
Laravel:
composer require sentry/sentry-laravel
php artisan sentry:publish --dsn=https://examplePublicKey@o0.ingest.sentry.io/0
That command writes config/sentry.php and adds SENTRY_LARAVEL_DSN to your .env. The package hooks the exception handler, queues, and console kernel automatically. To enable tracing, set a sample rate:
// .env
SENTRY_LARAVEL_DSN=https://examplePublicKey@o0.ingest.sentry.io/0
SENTRY_TRACES_SAMPLE_RATE=0.2
Plain PHP (the maintenance project I mentioned β no framework):
composer require sentry/sentry
// As early as possible in your bootstrap
\Sentry\init([
'dsn' => 'https://examplePublicKey@o0.ingest.sentry.io/0',
'environment' => 'production',
'traces_sample_rate' => 0.2,
'send_default_pii' => false,
]);
// Sentry hooks set_exception_handler / set_error_handler for you.
// For caught exceptions you still want to know about:
try {
riskyThing();
} catch (\Throwable $e) {
\Sentry\captureException($e);
throw $e;
}
For a legacy app with no observability at all, dropping those seven lines into the bootstrap file turns "the client says it's broken" into "here is the file, line, and the last five things that happened".
Common configuration worth setting on every SDK
environmentβproduction/staging/development, so you can filter and alert per environment.releaseβ tie it to your version/commit so regressions and crash-free rates work.tracesSampleRateβ start at0.1β0.2; you rarely need every transaction.sendDefaultPii/ data scrubbing β decide deliberately what leaves the client. Sentry scrubs common secrets server-side too.beforeSendβ your central filter for known-noise exceptions.
The part that changed my workflow: the Sentry MCP
Sentry ships an official MCP server β https://mcp.sentry.dev/mcp β that an AI assistant (Claude, Cursor, Windsurf, VS Code, and others) can connect to over OAuth. Once it's connected, the assistant can talk to your Sentry account directly.
What it can do:
- List your organizations and projects
- Search issues ("unresolved crashes in the MAUI app from the last 24h", "issues assigned to me")
- Pull the full issue β stack trace, tags, context, and the breadcrumb trail
- Fetch a specific thread's stack trace and the distributed trace behind an event
- Run Seer, Sentry's root-cause analysis, and get back a concrete explanation plus a suggested code fix
- Update the issue β resolve, assign, ignore, or set "resolved in next release"
How that plays out: instead of me opening Sentry, reading a stack trace, copying frames into my editor, and guessing, I point the assistant at the issue URL. It reads the crash, the breadcrumbs, and the trace, cross-references my codebase, proposes a fix, and β once I've reviewed and merged it with Fixes PROJECT-123 in the message, or by asking it to call the MCP's resolve action β the issue closes itself. Triage-to-fix on autopilot, with me as the reviewer.
I did exactly this to hunt down a nasty production crash: iOS SQLite Crash + Android 16 KB XA0141 Fix in .NET MAUI started as one Sentry issue that an assistant pulled through the MCP, analyzed, and helped fix across three repos.
On top of the MCP, Sentry's Seer can open a pull request against your GitHub repo straight from the issue page β you review the PR instead of writing the first draft.
Connecting the MCP
- Hosted (recommended): point your AI client at
https://mcp.sentry.dev/mcpand complete the OAuth prompt in the browser. Nothing to install. - Local (stdio): run
npx @sentry/mcp-server@latestwith a Sentry user auth token (--access-token) and your host, for editors that expect a local command.
Then just ask: "What are the top unresolved issues in my Blazor project this week?" or "Analyze SILVADATA-1V and propose a fix."
Tips from running it in production
- Set
environmentfrom day one. Retrofitting alert rules per environment later is tedious. - Keep
tracesSampleRatelow and raise it only when you're actively investigating performance. - Wire the GitHub integration β suspect commits and
Fixes PROJECT-123auto-resolve are worth the two minutes. - Turn on spike protection and set a reasonable monthly cap, so a bad deploy can't exhaust the quota.
- Use a
beforeSendfilter for the exceptions you've consciously decided are noise (cancelled tasks, offline network errors) β don't let them drown the signal. - Upload debug files in CI, not manually. An unsymbolicated mobile crash is nearly useless.
- Create one issue alert for "new issue in production" routed to Slack. That single alert catches most regressions the day they ship.
Gotchas
- PII:
SendDefaultPiiand replay masking exist for a reason β review what you send, especially on the PHP/legacy side where request bodies can carry secrets. - Quota math: performance/tracing units are consumed fast at
tracesSampleRate = 1.0. Sample. - Free-tier volume, not features: if something seems missing on the free plan, it's almost always a volume limit, not a locked feature.
- Source maps / symbols drift: if traces suddenly go unreadable after a release, your CI debug-file upload step probably broke.
Conclusion
Sentry earns its place by being the same tool for every runtime I touch. One DSN per project, one SDK init, and I get grouped errors, breadcrumbs, automatic performance-issue detection, release health, and alerting β on Blazor, on .NET MAUI, and on a frameworkless PHP app that had zero observability a month ago. The free Developer plan covers all of it at small scale.
And the MCP closes the loop: an AI assistant can read the issue, understand the trace, propose the fix, and resolve it β turning production error tracking from a chore into something that mostly handles itself.
If you want to see the workflow end to end, the iOS SQLite crash writeup is a real bug that went from a single Sentry issue to a merged fix across three repositories. Questions? Get in touch.
Comentários
Ficou com uma dúvida ou encontrou um problema no código? Comente abaixo — eu leio e respondo pessoalmente.