Skip to content

Commit 8c6fd12

Browse files
committed
add observability: EventBus logging, HTTP logging interceptor & structured GlobalErrorHandler
1 parent 552863b commit 8c6fd12

5 files changed

Lines changed: 65 additions & 19 deletions

File tree

projects/core/src/lib/interceptors/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22

33
export * from "./bearer-token.interceptor";
44
export * from "./camelcase.interceptor";
5+
export * from "./logging.interceptor";
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/** @format */
2+
3+
import { Injectable } from "@angular/core";
4+
import {
5+
HttpErrorResponse,
6+
HttpEvent,
7+
HttpHandler,
8+
HttpInterceptor,
9+
HttpRequest,
10+
HttpResponse,
11+
} from "@angular/common/http";
12+
import { Observable, tap } from "rxjs";
13+
import { LoggerService } from "../services";
14+
15+
@Injectable()
16+
export class LoggingInterceptor implements HttpInterceptor {
17+
constructor(private readonly logger: LoggerService) {}
18+
19+
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
20+
const started = Date.now();
21+
22+
return next.handle(request).pipe(
23+
tap({
24+
next: event => {
25+
if (event instanceof HttpResponse) {
26+
const elapsed = Date.now() - started;
27+
this.logger.debug(
28+
`[HTTP] ${request.method} ${request.urlWithParams} ${event.status} ${elapsed}ms`
29+
);
30+
}
31+
},
32+
error: (error: HttpErrorResponse) => {
33+
const elapsed = Date.now() - started;
34+
this.logger.error(
35+
`[HTTP] ${request.method} ${request.urlWithParams} ${error.status} ${elapsed}ms`,
36+
error.message
37+
);
38+
},
39+
})
40+
);
41+
}
42+
}

projects/core/src/lib/services/error/global-error-handler.service.ts

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/** @format */
22

3-
import { ErrorHandler, Injectable, NgZone } from "@angular/core";
3+
import { ErrorHandler, inject, Injectable, NgZone } from "@angular/core";
44
import { ErrorService } from "./error.service";
5+
import { LoggerService } from "../logger/logger.service";
56

67
/**
78
* Глобальный обработчик ошибок приложения
@@ -31,29 +32,17 @@ import { ErrorService } from "./error.service";
3132
*/
3233
@Injectable()
3334
export class GlobalErrorHandlerService implements ErrorHandler {
35+
private readonly logger = inject(LoggerService);
36+
3437
constructor(private readonly errorService: ErrorService, private readonly zone: NgZone) {}
3538

36-
/**
37-
* Обрабатывает глобальные ошибки приложения
38-
* @param err - ошибка или Promise rejection
39-
*/
4039
handleError(err: any): void {
41-
// Извлекаем фактическую ошибку из Promise rejection или используем как есть
4240
const error = err.rejection ? err.rejection : err;
4341

44-
// Закомментированный код для обработки HTTP ошибок:
45-
// if(error instanceof HttpErrorResponse) {
46-
// switch(error.status) {
47-
// case 404: {
48-
// this.zone.run(() => this.errorService.throwNotFount())
49-
// break;
50-
// }
51-
// }
52-
// }
53-
54-
// Логируем ошибки типа Error в консоль
5542
if (error instanceof Error) {
56-
console.error(error);
43+
this.logger.error(`[GlobalError] ${error.name}: ${error.message}`, error.stack);
44+
} else {
45+
this.logger.error("[GlobalError] Unknown error", error);
5746
}
5847
}
5948
}

projects/social_platform/src/app/app.config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
API_URL,
1515
BearerTokenInterceptor,
1616
CamelcaseInterceptor,
17+
LoggingInterceptor,
1718
PRODUCTION,
1819
SKILLS_API_URL,
1920
} from "@corelib";
@@ -62,6 +63,11 @@ export const APP_CONFIG: ApplicationConfig = {
6263
useClass: BearerTokenInterceptor,
6364
multi: true,
6465
},
66+
{
67+
provide: HTTP_INTERCEPTORS,
68+
useClass: LoggingInterceptor,
69+
multi: true,
70+
},
6571
{
6672
provide: API_URL,
6773
useValue: environment.apiUrl,

projects/social_platform/src/app/domain/shared/event-bus.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
/** @format */
22

3-
import { Injectable } from "@angular/core";
3+
import { inject, Injectable } from "@angular/core";
44
import { filter, map, Observable, Subject } from "rxjs";
55
import { DomainEvent } from "./domain-event";
6+
import { LoggerService } from "@corelib";
67

78
@Injectable({ providedIn: "root" })
89
export class EventBus {
910
private readonly events$ = new Subject<DomainEvent>();
11+
private readonly logger = inject(LoggerService);
12+
13+
constructor() {
14+
this.events$.subscribe(event => {
15+
this.logger.debug(`[EventBus] ${event.type}`, event.payload);
16+
});
17+
}
1018

1119
emit<T extends DomainEvent>(event: T): void {
1220
this.events$.next(event);

0 commit comments

Comments
 (0)