diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 660b36cc6..aa9501910 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -29,7 +29,6 @@ jobs: SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} with: sourcemaps: ./dist/control-center/browser - environment: ${{ startsWith(github.ref_name, 'epic/') && 'staging' || 'production' }} set_commits: skip - name: Remove source maps run: find dist/control-center/browser -type f -name '*.map' -delete diff --git a/.gitignore b/.gitignore index 50edd2db7..e1bb39e32 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,7 @@ Thumbs.db # Config appConfig*.json -authConfig*.json \ No newline at end of file +authConfig*.json + +# Env +.env diff --git a/package.json b/package.json index 59e10d99b..72527def3 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "scripts": { "ng": "ng", - "start": "ng serve", + "start": ". ./.env && ng serve --define \"SENTRY_DSN='${SENTRY_DSN}'\"", "prod": "ng serve --configuration=production", "build": "ng build", "watch": "ng build --watch --configuration development", diff --git a/public/assets/_appConfig.json b/public/assets/_appConfig.json index 795953363..cedb0da85 100644 --- a/public/assets/_appConfig.json +++ b/public/assets/_appConfig.json @@ -18,5 +18,6 @@ "category": 2, "termset": 2 } - } + }, + "tier": "production" } diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 37968da61..a96a144ed 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -2,7 +2,15 @@ import Keycloak from 'keycloak-js'; import { debounceTime, map, of, shareReplay, switchMap, tap } from 'rxjs'; import { CommonModule } from '@angular/common'; -import { ChangeDetectionStrategy, Component, DestroyRef, inject, signal } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + DestroyRef, + OnInit, + inject, + isDevMode, + signal, +} from '@angular/core'; import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; @@ -11,6 +19,7 @@ import { MatSidenavModule } from '@angular/material/sidenav'; import { MatToolbarModule } from '@angular/material/toolbar'; import { MatTooltipModule } from '@angular/material/tooltip'; import { Router, RouterOutlet } from '@angular/router'; +import * as Sentry from '@sentry/angular'; import { AppModeService, @@ -27,7 +36,7 @@ import { ThriftRepositoryService } from '~/api/services'; import { SidenavInfoModule, SidenavInfoService } from '~/components/sidenav-info'; import { getLimitedDomainObjectDetails } from '~/components/thrift-api-crud'; import { DomainObjectCardComponent } from '~/components/thrift-api-crud/domain'; -import { KeycloakUserService, Service } from '~/services'; +import { ConfigService, KeycloakUserService, Service } from '~/services'; import { LOGGING } from '~/utils'; import { APP_ROUTES } from './app-routes'; @@ -221,9 +230,10 @@ const createNavLinks = (): Link[] => [ MatTooltipModule, ], }) -export class AppComponent { +export class AppComponent implements OnInit { private keycloakService = inject(Keycloak); private keycloakUserService = inject(KeycloakUserService); + private configService = inject(ConfigService); private repositoryService = inject(ThriftRepositoryService); private router = inject(Router); private dr = inject(DestroyRef); @@ -270,6 +280,19 @@ export class AppComponent { this.registerConsoleUtils(); } + ngOnInit() { + if (SENTRY_DSN) { + this.configService.config.getFirstValue().subscribe((config) => { + if (config?.tier) { + Sentry.setTag('tier', config.tier); + } + }); + this.keycloakUserService.user.getFirstValue().subscribe((user) => { + Sentry.setUser({ id: user.id, username: user.username, email: user.email }); + }); + } + } + logout() { this.keycloakService.logout(); } diff --git a/src/app/app.config.ts b/src/app/app.config.ts index 198117db1..a69e0e1fb 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -7,6 +7,7 @@ import { provideHttpClient, withInterceptorsFromDi, withXhr } from '@angular/com import localeRu from '@angular/common/locales/ru'; import { ApplicationConfig, + ErrorHandler, LOCALE_ID, inject, isDevMode, @@ -18,6 +19,7 @@ import { MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core'; import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field'; import { MatIconRegistry } from '@angular/material/icon'; import { provideRouter, withRouterConfig } from '@angular/router'; +import * as Sentry from '@sentry/angular'; import { ERROR_PARSER, LogError, QUERY_PARAMS_SERIALIZERS } from '@vality/matez'; @@ -43,6 +45,10 @@ registerLocaleData(localeRu); export const appConfig: ApplicationConfig = { providers: [ + { + provide: ErrorHandler, + useValue: Sentry.createErrorHandler(), + }, provideBrowserGlobalErrorListeners(), provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes, withRouterConfig({ paramsInheritanceStrategy: 'always' })), diff --git a/src/main.ts b/src/main.ts index e7a9e0e01..1d64dcc63 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,3 +1,4 @@ +import { isDevMode } from '@angular/core'; import { bootstrapApplication } from '@angular/platform-browser'; import * as Sentry from '@sentry/angular'; @@ -7,7 +8,15 @@ import { appConfig } from './app/app.config'; if (SENTRY_DSN) { Sentry.init({ dsn: SENTRY_DSN, - integrations: [Sentry.browserTracingIntegration(), Sentry.replayIntegration()], + environment: isDevMode() ? 'development' : 'production', + integrations: [ + Sentry.browserTracingIntegration(), + Sentry.replayIntegration({ + maskAllText: true, + maskAllInputs: true, + blockAllMedia: true, + }), + ], tracesSampleRate: 1, replaysSessionSampleRate: 1, replaysOnErrorSampleRate: 1, diff --git a/src/services/config/types/app-config.ts b/src/services/config/types/app-config.ts index 34e5a7971..a88551791 100644 --- a/src/services/config/types/app-config.ts +++ b/src/services/config/types/app-config.ts @@ -30,4 +30,5 @@ export interface AppConfig { }; checkout: Endpoint; default: Record; + tier?: 'production' | 'staging'; }