20.12. Error Tracking
Table of Contents
Why Error Tracking Matters
When you run a backend in development, you see errors directly in your terminal or logs. In production, you usually cannot watch logs all day, and errors may happen rarely or only for certain users.
Error tracking solves this by:
- Automatically collecting errors from your application.
- Grouping similar errors together.
- Showing how often they happen and to which users.
- Keeping stack traces so you can understand where and why a crash occurred.
- Alerting you quickly when something breaks.
Without error tracking, many bugs stay hidden until users complain. With it, you can find and fix problems much faster.
Important: Error tracking is not a replacement for logging.
Use logging to understand system behavior and business events.
Use error tracking to detect and analyze failures.
Errors vs Exceptions vs Failures
In backend applications, several related terms are common:
- Exception: A runtime event in code, such as
ZeroDivisionError,KeyError, or a customUserNotFoundError. - Error: Informal word for something going wrong. In code, it is often represented as an exception.
- Failure: A visible effect of an error, such as a
500 Internal Server Errorreturned to the client.
Not every exception is a failure:
- A handled exception might be turned into a clean
400 Bad Requestresponse. - A logged warning might not affect the user at all.
Error tracking usually focuses on unhandled exceptions or handled exceptions that you decide to report, such as:
- Database connection failures.
- Unexpected edge cases in business logic.
- Third-party service outages.
- Programming bugs, such as
AttributeErrordue toNone.
What Error Tracking Tools Do
An error tracking system generally provides:
Automatic Error Capture
Libraries for your language and framework:
- Catch uncaught exceptions.
- Capture stack traces.
- Attach context, such as HTTP request info, user identifiers, headers, or environment.
For example, in a Python web app, an error tracker might catch:
def get_user_age(user):
return 2024 - user.birth_year # raises AttributeError if user is None
If user is None, the error tracker records:
- Exception type:
AttributeError - Message:
'NoneType' object has no attribute 'birth_year' - Stack trace: file name, line number, call chain
- Request info: path
/users/age, query params, etc.
Grouping and De-duplication
If the same error happens 1,000 times, you do not want 1,000 separate issues. Error trackers group errors by a fingerprint, often based on:
- Exception type.
- File and line where it originated.
- Stack trace.
The dashboard might show:
| Error group | Events | Users | Last seen |
|---|---|---|---|
| AttributeError in user_service.py:42 | 1,203 | 534 | 5 minutes ago |
| TimeoutError calling payment provider | 129 | 82 | 2 minutes ago |
| KeyError "cart_id" in cart_controller.py | 64 | 60 | 13 minutes ago |
Context and Breadcrumbs
Error trackers add context:
- Current user id or email.
- Request path, method, headers, and body (with sensitive data removed).
- Environment: production, staging, local.
- App version or commit hash.
They may also add breadcrumbs, which are recent events leading up to the error, such as:
- "User clicked Add To Cart"
- "POST /api/cart/add"
- "Call to Redis GET cart:1234"
This helps you reproduce the problem.
Alerts and Notifications
Error trackers can send alerts when:
- A new type of error appears.
- Error frequency suddenly spikes.
- An error that was marked as resolved reappears.
Common alert channels:
- Email.
- Slack or Microsoft Teams.
- PagerDuty or other on-call tools.
- Webhooks to custom systems.
Popular Error Tracking Tools
There are many error tracking tools. Here are some common ones in backend development:
| Tool | Type | Main features |
|---|---|---|
| Sentry | Hosted / self | Rich UI, SDKs for many languages, performance data |
| Rollbar | Hosted | Real-time grouping, deployments tracking |
| Honeybadger | Hosted | Error tracking plus uptime & check-ins |
| Bugsnag | Hosted | Error stability scores, rich dashboards |
| Open-source | Self-hosted | Examples: Sentry (self-hosted), GlitchTip |
You do not need to choose a specific tool for this course, but the concepts are very similar across products.
How Error Tracking Integrates with Your Backend
Error tracking usually integrates at two main levels:
- Framework-level integration
A middleware or plugin that wraps your web framework and captures unhandled exceptions. - Manual reporting in code
Explicit calls to report important handled exceptions or custom events.
Framework-Level Example (Conceptual)
Imagine a typical Python web framework with middleware support. An error tracking middleware might look like this:
def error_tracking_middleware(app, tracker):
async def wrapper(request):
try:
return await app(request)
except Exception as exc:
tracker.capture_exception(exc, request=request)
# Re-raise so your normal error handlers still run
raise
return wrapperOnce this wrapper is installed:
- Any uncaught exception will be automatically sent to your tracking tool.
- You do not need to wrap every endpoint in try/except manually.
A FastAPI, Django, or Flask integration does something similar, but the code is hidden inside the tool’s SDK.
Manual Reporting Example
Sometimes you intentionally catch exceptions but still want to know about them:
def charge_card(user_id, amount):
try:
return payment_provider.charge(user_id, amount)
except PaymentTimeoutError as exc:
error_tracker.capture_exception(exc, extra={"user_id": user_id, "amount": amount})
# Fallback behavior that user might see as "please try again later"
raise ServiceUnavailableError("Payment service unavailable")This pattern is important for:
- Third-party API failures.
- Non-fatal errors that you recover from but still want to monitor.
- Suspicious conditions that might indicate a bug or attack.
Error Tracking vs Traditional Logging
Both error tracking and logging are important. They serve different but complementary purposes.
Comparison
| Aspect | Logging | Error tracking |
|---|---|---|
| Focus | All events, behavior, debug info | Failures and exceptions |
| Volume | Potentially very high | Much lower, filtered to errors |
| Typical storage | Log files, ELK stack, cloud logging | Specialized dashboard |
| Query style | Search by text, fields, time window | Browse error groups, issues, stack traces |
| Alerts | Often on log patterns or metrics | On new or frequent error groups |
| User context | Optional | Usually built-in (user, request, environment) |
You might log something like:
logger.error("Payment provider timeout for user %s", user_id)While also sending it to error tracking:
error_tracker.capture_exception(exc, extra={"user_id": user_id})Use logs for detailed behavior and debugging. Use error tracking for high-level overview of failures.
Configuring Error Tracking for Different Environments
Backends usually run in multiple environments:
localordevelopmentstagingortestproduction
You do not want to treat all environments equally.
Typical Configuration
| Environment | Should capture errors? | Should send alerts? | Notes |
|---|---|---|---|
| Development | Optional | No | You see errors locally anyway |
| Staging | Yes | Maybe | Useful for release testing |
| Production | Yes | Yes | Critical to detect real issues |
In code, you might check an environment variable:
import os
ENV = os.getenv("APP_ENV", "development")
if ENV == "production":
error_tracker.init(dsn=os.getenv("ERROR_TRACKING_DSN"), send_pii=False)
else:
# In dev, maybe log to console instead or use a different project
error_tracker.init(dsn=None) # disabledThis makes sure you do not mix development errors with real production errors in the dashboard.
Error Grouping and Prioritization
As your system grows, you will have many different errors. You need to decide what to fix first.
Grouping Errors
Error tracking tools usually group by:
- Exception type, such as
ValueError. - Location, such as
user_service.py:42. - Stack trace.
You might see groups like:
KeyErrorincart_service.get_cartTimeoutErrorinpayment_gateway.chargeIntegrityErroronorderstable insert
Prioritizing What to Fix
Common ways to prioritize:
- Frequency: How often does the error happen?
- User impact: How many users are affected?
- Business criticality: Does it prevent payments, signups, or logins?
- Recency: Is it still happening, or was it a one-time event?
A simple prioritization scheme:
| Priority | Description | Example |
|---|---|---|
| P0 | System unusable for many users | All API requests return 500 |
| P1 | Critical feature broken for some users | Checkout fails for some payment methods |
| P2 | Non-critical feature broken | Profile picture upload failing |
| P3 | Cosmetic or minor errors | Rare admin-page errors, typo exceptions |
Error tracking dashboards often support:
- Marking an issue as resolved.
- Marking as ignored (for known non-critical cases).
- Assigning an issue to a developer.
Example Workflow: From Error to Fix
Here is a typical lifecycle of an error with an error tracking tool:
- Error occurs in production.
A user requestsPOST /orders, and the backend raisesIntegrityErrordue to a missing foreign key. - Tool captures the error.
The exception is caught by the framework integration and sent to the tracking service with full context. - Error appears in dashboard.
You see a new issue: - Type:
IntegrityError - Message:
insert or update on table "orders" violates foreign key constraint "orders_user_id_fkey" - Affected users: 27
- First seen: 10 minutes ago
- Last seen: 1 minute ago
- Alert is sent.
A Slack notification posts in#backend-alertswith a link to the issue. - Developer investigates the stack trace.
The stack shows the error originates inorder_service.create_order.
They inspect the code and realize user ids are not checked properly after a recent refactor. - Developer reproduces locally.
Using the request details from the error report, they reproduce the problem with a test or manually. - Fix is implemented and deployed.
The developer adds proper validation and tests, then deploys a new version. - Error tracking detects that the issue is gone.
After deployment, the issue stops appearing.
The developer marks it as resolved in the error tracking dashboard. - Regression monitoring.
If the same error happens again in a new version, it will automatically be reopened.
Privacy and Security Considerations
Error tracking deals with sensitive information. You must be careful not to leak:
- Passwords.
- Authentication tokens or API keys.
- Credit card details.
- Personal data that is not needed for debugging.
Redacting Sensitive Data
Error tracking tools usually support:
- Removing certain headers, such as
AuthorizationorCookie. - Masking known field names, such as
password,token, orcard_number. - Limiting the size of captured request bodies.
Conceptually, you might configure:
error_tracker.init(
dsn="...",
scrub_fields=["password", "token", "authorization", "credit_card"]
)Then, if a request body contains:
{
"email": "user@example.com",
"password": "supersecret"
}The error tracker might only store:
{
"email": "user@example.com",
"password": "[Filtered]"
}Rule: Never send secrets (passwords, private keys, full credit card numbers) to any third-party service, including error tracking tools.
Minimizing Personal Data
Often you only need:
- An internal user id.
- Whether the user is logged in.
- Maybe an email address, if allowed by your privacy policy.
You do not need:
- Full address.
- Date of birth.
- Other sensitive profile data.
Design your error tracking integration to attach only the minimum personal data needed to debug issues.
Using Error Tracking with Metrics and Monitoring
Error tracking fits into a larger monitoring and observability setup.
You will often combine:
- Metrics (from monitoring systems)
Things like error rate, request latency, CPU usage. - Logs (from logging systems)
Detailed event-by-event traces. - Error tracking
High-level catalog of failures with stack traces.
Example relationships:
- A metrics dashboard shows a spike in HTTP 500 error rate.
You click through to error tracking to see which exceptions are causing those 500s. - An error tracking issue shows a new type of error.
You search logs for that error id or correlation id to see surrounding events and queries.
In production-ready systems, all three work together.
Integrating Error Tracking Into Your Development Process
To get the most out of error tracking, it should become part of everyday development, not just a tool you check during emergencies.
During Development
- Configure different projects or DSNs for development, staging, and production.
- Test local error capture so you know how issues will look.
- Add manual reporting in critical areas, such as payments or external API calls.
During Code Review
Reviewers can ask:
- Is this exception handled?
- Should we report this error to our tracking tool?
- Are we sending any sensitive data in the error context?
For example, instead of:
except Exception:
passUse:
except Exception as exc:
error_tracker.capture_exception(exc)
raiseOr handle specific exception types.
During On-Call and Incident Response
When something breaks in production:
- Check metrics (uptime, error rate).
- Open the error tracking dashboard to see:
- New errors.
- Spikes in existing errors.
- Use stack traces and context to identify the root cause.
- After the fix, mark the error as resolved and monitor for regressions.
This becomes a repeatable process that helps stabilize your backend over time.
Summary
- Error tracking automatically collects and organizes exceptions from your backend.
- It provides stack traces, context, grouping, and alerts for failures.
- It complements logging and metrics and is especially useful in production.
- Integrations exist for most languages and frameworks, often through middleware.
- You can also manually report handled exceptions that matter.
- Configure environments carefully and protect privacy by redacting sensitive data.
- Make error tracking part of your daily development, code review, and incident response workflows.
Using a good error tracking setup will help you discover bugs earlier, fix them faster, and maintain a more reliable backend system.
Views: 18
KAHIBARO