How to use Sentry with Angular
Implementing robust error tracking is essential for maintaining high-quality web applications and ensuring a seamless user experience.
With over 25 years of experience in software development and as the creator of CoreUI, I have integrated Sentry into hundreds of enterprise-grade Angular projects to achieve 99.9% crash-free sessions.
The most efficient and modern way to use Sentry with Angular is by utilizing the @sentry/angular SDK combined with Angular’s native ErrorHandler and standalone API providers.
This approach allows you to capture every unhandled exception, monitor performance bottlenecks, and gain deep insights into production issues without manual overhead.
Use the @sentry/angular package and provide the Sentry.ErrorHandler in your application configuration to automatically track all runtime errors.
import { ErrorHandler } from '@angular/core'
import * as Sentry from '@sentry/angular'
export const sentryProviders = [
{
provide: ErrorHandler,
useValue: Sentry.createErrorHandler({
showDialog: true
})
},
{
provide: Sentry.TraceService,
deps: [Sentry.Router]
}
]
This configuration replaces the default Angular error handler with Sentry’s specialized version, which intercepts exceptions and sends them to your dashboard. It ensures that every error occurring in your components, services, or pipes is recorded with full stack traces and contextual metadata.
1. Installation and Basic Setup
The first step is to install the Sentry browser SDK specifically designed for Angular applications. This package includes the necessary decorators, services, and error handlers required for deep integration.
Before you begin, ensure you have a project ready. .
npm install --save @sentry/angular
Once the package is installed, you need to initialize Sentry as early as possible in your application lifecycle, typically in the main.ts file.
import { bootstrapApplication } from '@angular/platform-browser'
import { appConfig } from './app/app.config'
import { AppComponent } from './app/app.component'
import * as Sentry from '@sentry/angular'
Sentry.init({
dsn: 'https://[email protected]/your-project-id',
integrations: [
Sentry.browserTracingIntegration(),
Sentry.replayIntegration()
],
tracesSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0
})
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err))
This setup enables not only error tracking but also performance tracing and session replays, which are invaluable for debugging complex frontend states.
2. Configuring Standalone Providers
Modern Angular applications (v15+) prefer standalone components and configuration objects over traditional NgModules. To integrate Sentry properly, you should add its providers to your app.config.ts.
By providing the ErrorHandler globally, you ensure that no error goes unnoticed, regardless of where it happens in the component tree.
import { ApplicationConfig } from '@angular/core'
import { provideRouter } from '@angular/router'
import * as Sentry from '@sentry/angular'
import { routes } from './app.routes'
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
// Sentry v8+ recommended pattern — better tree-shaking than createErrorHandler
Sentry.provideErrorHandler({ showDialog: false }),
{
provide: Sentry.TraceService,
deps: [Sentry.Router]
}
]
}
Sentry.provideErrorHandler() is the recommended pattern in @sentry/angular v8+ for standalone applications — it provides better tree-shaking than the older createErrorHandler() object literal approach. This clean separation keeps your entry point focused while Sentry silently monitors application health in the background.
3. Implementing Global Error Handling
Angular’s ErrorHandler is a class that provides a hook for centralized exception handling. Sentry extends this to provide detailed breadcrumbs, which show the steps leading up to the error.
When an error occurs, Sentry captures the browser version, operating system, and the exact line of code in your TypeScript source (via source maps).
import { Injectable, ErrorHandler } from '@angular/core'
import * as Sentry from '@sentry/angular'
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
handleError(error: any): void {
const eventId = Sentry.captureException(error.originalError || error)
// Log to console for local development
console.error('Captured by Sentry:', error)
// Optionally trigger a user-facing notification using CoreUI Alert
// https://coreui.io/angular/docs/components/alert
}
}
You can then provide this custom class instead of the default Sentry one if you need to add custom logic, such as filtering specific HTTP errors or showing custom UI elements.
4. Performance Monitoring with Routing
One of the most powerful features of Sentry is its ability to track page transitions and navigation performance. In Angular, this is achieved by integrating with the Router.
When a user navigates from one route to another, Sentry records the time it takes for components to initialize and for data to be fetched.
import { Component, OnInit } from '@angular/core'
import { TraceService } from '@sentry/angular'
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
standalone: true
})
export class AppComponent implements OnInit {
constructor(private trace: TraceService) {}
ngOnInit() {
// This empty call ensures the TraceService is instantiated
// and starts listening to router events immediately.
}
}
By injecting TraceService in your root component, you enable automatic performance spans for every route change. This is a pattern we consistently use in the Angular Dashboard Template to ensure high performance.
5. Capturing Manual Exceptions
While automatic tracking handles unhandled errors, you often want to manually log specific business logic failures or API errors that are caught in try-catch blocks.
Manual capture allows you to add custom tags or extra context to the error report, making it easier to filter in the Sentry dashboard.
import { Component } from '@angular/core'
import * as Sentry from '@sentry/angular'
@Component({
selector: 'app-payment',
template: '<button (click)="processPayment()">Pay</button>',
standalone: true
})
export class PaymentComponent {
processPayment() {
try {
// Simulate payment logic
throw new Error('Payment gateway timeout')
} catch (error) {
Sentry.captureException(error, {
tags: { section: 'checkout' },
extra: { userId: 'user_123' }
})
}
}
}
Adding context like userId or section helps your team prioritize fixes based on the impact on specific user segments or critical features.
6. Integrating with CoreUI Alerts
When an error is captured, it is often best practice to inform the user that something went wrong without breaking the entire layout. Using CoreUI Alerts provides a professional way to display these messages.
You can create a notification service that listens for errors and triggers an alert component.
import { Injectable } from '@angular/core'
import { Subject } from 'rxjs'
@Injectable({ providedIn: 'root' })
export class NotificationService {
private errorSource = new Subject<string>()
errors$ = this.errorSource.asObservable()
notifyError(message: string) {
this.errorSource.next(message)
}
}
In your component template, you can use the CoreUI Alert to show the error:
<c-alert color="danger" *ngIf="errorMessage$ | async as msg" dismissible>
{{ msg }}
</c-alert>
This creates a polished user experience where errors are handled gracefully in the UI while being tracked silently in the background.
Best Practice Note:
Always use environment-specific DSNs and configurations. You should disable Sentry in development mode to avoid polluting your dashboard with local errors. We recommend using isDevMode() from @angular/core to conditionally initialize Sentry.
In CoreUI templates, we also suggest setting the environment tag in Sentry.init to distinguish between staging and production data. This ensures that your performance metrics and error counts are accurate and actionable for the right environment.



