diff --git a/package-lock.json b/package-lock.json index 93efd6d..89d760e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "@ctrl/ngx-emoji-mart": "^9.2.0", "@ngx-translate/core": "^15.0.0", "@ngx-translate/http-loader": "^8.0.0", + "@sentry/angular": "^8.30.0", "crypto-es": "^2.1.0", "ng2-pdf-viewer": "^10.0.0", "ngx-extended-pdf-viewer": "^19.6.6", @@ -4208,6 +4209,129 @@ "yarn": ">= 1.13.0" } }, + "node_modules/@sentry-internal/browser-utils": { + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.30.0.tgz", + "integrity": "sha512-pwX+awNWaxSOAsBLVLqc1+Hw+Fm1Nci9mbKFA6Ed5YzCG049PnBVQwugpmx2dcyyCqJpORhcIqb9jHdCkYmCiA==", + "dependencies": { + "@sentry/core": "8.30.0", + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.30.0.tgz", + "integrity": "sha512-ParFRxQY6helxkwUDmro77Wc5uSIC6rZos88jYMrYwFmoTJaNWf4lDzPyECfdSiSYyzSMZk4dorSUN85Ul7DCg==", + "dependencies": { + "@sentry/core": "8.30.0", + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.30.0.tgz", + "integrity": "sha512-/KFre+BrovPCiovgAu5N1ErJtkDVzkJA5hV3Jw011AlxRWxrmPwu6+9sV9/rn3tqYAGyq6IggYqeIOHhLh1Ihg==", + "dependencies": { + "@sentry-internal/browser-utils": "8.30.0", + "@sentry/core": "8.30.0", + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.30.0.tgz", + "integrity": "sha512-y/QqcvchhtMlVA6eOZicIfTxtZarazQZJuFW0018ynPxBTiuuWSxMCLqduulXUYsFejfD8/eKHb3BpCIFdDYjg==", + "dependencies": { + "@sentry-internal/replay": "8.30.0", + "@sentry/core": "8.30.0", + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/angular": { + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry/angular/-/angular-8.30.0.tgz", + "integrity": "sha512-JTHJJLRlR4UyizZxIA0ZkiQGSH7By/kOSJii4ePqM192+pOwKSN06HxxQGAjWTt5rkbRDNowZN8bt/KyLLMKyg==", + "dependencies": { + "@sentry/browser": "8.30.0", + "@sentry/core": "8.30.0", + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0", + "tslib": "^2.4.1" + }, + "engines": { + "node": ">=14.18" + }, + "peerDependencies": { + "@angular/common": ">= 14.x <= 18.x", + "@angular/core": ">= 14.x <= 18.x", + "@angular/router": ">= 14.x <= 18.x", + "rxjs": "^6.5.5 || ^7.x" + } + }, + "node_modules/@sentry/browser": { + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.30.0.tgz", + "integrity": "sha512-M+tKqawH9S3CqlAIcqdZcHbcsNQkEa9MrPqPCYvXco3C4LRpNizJP2XwBiGQY2yK+fOSvbaWpPtlI938/wuRZQ==", + "dependencies": { + "@sentry-internal/browser-utils": "8.30.0", + "@sentry-internal/feedback": "8.30.0", + "@sentry-internal/replay": "8.30.0", + "@sentry-internal/replay-canvas": "8.30.0", + "@sentry/core": "8.30.0", + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/core": { + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.30.0.tgz", + "integrity": "sha512-CJ/FuWLw0QEKGKXGL/nm9eaOdajEcmPekLuHAuOCxID7N07R9l9laz3vFbAkUZ97GGDv3sYrJZgywfY3Moropg==", + "dependencies": { + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/types": { + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.30.0.tgz", + "integrity": "sha512-kgWW2BCjBmVlSQRG32GonHEVyeDbys74xf9mLPvynwHTgw3+NUlNAlEdu05xnb2ow4bCTHfbkS5G1zRgyv5k4Q==", + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/utils": { + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.30.0.tgz", + "integrity": "sha512-wZxU2HWlzsnu8214Xy7S7cRIuD6h8Z5DnnkojJfX0i0NLooepZQk2824el1Q13AakLb7/S8CHSHXOMnCtoSduw==", + "dependencies": { + "@sentry/types": "8.30.0" + }, + "engines": { + "node": ">=14.18" + } + }, "node_modules/@sigstore/bundle": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.2.0.tgz", diff --git a/package.json b/package.json index c09e623..92baa4f 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@ctrl/ngx-emoji-mart": "^9.2.0", "@ngx-translate/core": "^15.0.0", "@ngx-translate/http-loader": "^8.0.0", + "@sentry/angular": "^8.30.0", "crypto-es": "^2.1.0", "ng2-pdf-viewer": "^10.0.0", "ngx-extended-pdf-viewer": "^19.6.6", diff --git a/src/app/app.config.ts b/src/app/app.config.ts index f80652a..ae91674 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -1,5 +1,10 @@ -import { ApplicationConfig, importProvidersFrom } from '@angular/core'; -import { provideRouter } from '@angular/router'; +import { + APP_INITIALIZER, + ApplicationConfig, + ErrorHandler, + importProvidersFrom, +} from '@angular/core'; +import { provideRouter, Router } from '@angular/router'; import { HttpClientModule, HttpClient } from '@angular/common/http'; import { routes } from './app.routes'; import { initializeApp, provideFirebaseApp } from '@angular/fire/app'; @@ -9,6 +14,7 @@ import { provideAnimationsAsync } from '@angular/platform-browser/animations/asy import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; import { TranslateHttpLoader } from '@ngx-translate/http-loader'; import { firebaseConfig } from '../environments/config'; +import * as Sentry from '@sentry/angular'; export function HttpLoaderFactory(httpClient: HttpClient) { return new TranslateHttpLoader(httpClient, './assets/i18n/', '.json'); @@ -34,5 +40,19 @@ export const appConfig: ApplicationConfig = { TranslateModule.forRoot(translationConfig) ), provideAnimationsAsync(), + { + provide: ErrorHandler, + useValue: Sentry.createErrorHandler(), + }, + { + provide: Sentry.TraceService, + deps: [Router], + }, + { + provide: APP_INITIALIZER, + useFactory: () => () => {}, + deps: [Sentry.TraceService], + multi: true, + }, ], }; diff --git a/src/main.ts b/src/main.ts index 35b00f3..18668b8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,26 @@ import { bootstrapApplication } from '@angular/platform-browser'; import { appConfig } from './app/app.config'; import { AppComponent } from './app/app.component'; +import * as Sentry from '@sentry/angular'; -bootstrapApplication(AppComponent, appConfig) - .catch((err) => console.error(err)); +Sentry.init({ + dsn: 'https://32b2e0319614793098e9c0b9352fcc49@o4507955559464960.ingest.de.sentry.io/4507955680968784', + integrations: [ + Sentry.browserTracingIntegration(), + Sentry.replayIntegration(), + ], + // Tracing + tracesSampleRate: 1.0, // Capture 100% of the transactions + // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled + tracePropagationTargets: [ + 'localhost', + /^https:\/\/dabubble\.andre-kempf\.com/, + ], + // Session Replay + replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production. + replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur. +}); + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err) +);