@adatechnology/logger 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adatechnology/logger",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/src/index.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  export { LoggerModule } from "./logger.module";
2
- export { LOGGER_PROVIDER } from "./logger.token";
2
+ export { LOGGER_PROVIDER, HTTP_LOGGING_INTERCEPTOR } from "./logger.token";
3
3
  export type {
4
4
  LoggerProviderInterface,
5
5
  LogPayload,
6
6
  LoggerLevel,
7
7
  } from "./logger.interface";
8
8
  export { RequestContextMiddleware } from "./middleware/request-context.middleware";
9
+ export { HttpLoggingInterceptor } from "./interceptors/http-logging.interceptor";
10
+ export { HTTP_LOGGING_INTERCEPTOR_CONTEXT } from "./interceptors/http-logging.interceptor.constant";
9
11
  export { getContext, runWithContext } from "./context/async-context.service";
10
12
  export type { LoggerConfig } from "./logger.config";
11
13
  export { DEFAULT_LOGGER_CONFIG } from "./logger.config";
@@ -0,0 +1,5 @@
1
+ export const HTTP_LOGGING_INTERCEPTOR_CONTEXT = {
2
+ INTERCEPT: "HttpLoggingInterceptor.intercept",
3
+ ON_RESPONSE: "HttpLoggingInterceptor.onResponse",
4
+ ON_ERROR: "HttpLoggingInterceptor.onError",
5
+ } as const;
@@ -0,0 +1,84 @@
1
+ import { CallHandler, ExecutionContext, Inject, Injectable, NestInterceptor } from "@nestjs/common";
2
+ import { Observable } from "rxjs";
3
+ import { tap } from "rxjs/operators";
4
+ import { LOGGER_PROVIDER } from "../logger.token";
5
+ import type { LoggerProviderInterface } from "../logger.interface";
6
+ import { HTTP_LOGGING_INTERCEPTOR_CONTEXT } from "./http-logging.interceptor.constant";
7
+
8
+ @Injectable()
9
+ export class HttpLoggingInterceptor implements NestInterceptor {
10
+ constructor(
11
+ @Inject(LOGGER_PROVIDER)
12
+ private readonly logger: LoggerProviderInterface,
13
+ ) {}
14
+
15
+ intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {
16
+ const http = context.switchToHttp();
17
+ const request = http.getRequest<Record<string, any>>();
18
+ const response = http.getResponse<Record<string, any>>();
19
+ const start = Date.now();
20
+
21
+ const { method, url, headers, body, query, params } = request;
22
+
23
+ this.logger.info({
24
+ message: "HTTP Request",
25
+ context: HTTP_LOGGING_INTERCEPTOR_CONTEXT.INTERCEPT,
26
+ meta: {
27
+ request: {
28
+ method,
29
+ path: url,
30
+ headers,
31
+ query: query && Object.keys(query).length ? query : undefined,
32
+ params: params && Object.keys(params).length ? params : undefined,
33
+ body: body && Object.keys(body).length ? body : undefined,
34
+ },
35
+ },
36
+ });
37
+
38
+ return next.handle().pipe(
39
+ tap({
40
+ next: (responseBody) => {
41
+ const durationMs = Date.now() - start;
42
+ const statusCode =
43
+ response?.statusCode ??
44
+ response?.raw?.statusCode ??
45
+ 200;
46
+
47
+ this.logger.info({
48
+ message: "HTTP Response",
49
+ context: HTTP_LOGGING_INTERCEPTOR_CONTEXT.ON_RESPONSE,
50
+ meta: {
51
+ request: {
52
+ method,
53
+ path: url,
54
+ },
55
+ response: {
56
+ statusCode,
57
+ durationMs,
58
+ body: responseBody ?? undefined,
59
+ },
60
+ },
61
+ });
62
+ },
63
+ error: (error: unknown) => {
64
+ const durationMs = Date.now() - start;
65
+
66
+ this.logger.error({
67
+ message: "HTTP Response Error",
68
+ context: HTTP_LOGGING_INTERCEPTOR_CONTEXT.ON_ERROR,
69
+ meta: {
70
+ request: {
71
+ method,
72
+ path: url,
73
+ },
74
+ response: {
75
+ durationMs,
76
+ error: error instanceof Error ? error.message : String(error),
77
+ },
78
+ },
79
+ });
80
+ },
81
+ }),
82
+ );
83
+ }
84
+ }
@@ -1,27 +1,33 @@
1
1
  import { DynamicModule, Module, Scope, Provider, Global } from "@nestjs/common";
2
2
  import { LoggerProvider } from "./logger.provider";
3
- import { LOGGER_PROVIDER } from "./logger.token";
3
+ import { LOGGER_PROVIDER, HTTP_LOGGING_INTERCEPTOR } from "./logger.token";
4
4
  import { WinstonImplementationModule } from "./implementations/winston/winston.logger.module";
5
+ import { HttpLoggingInterceptor } from "./interceptors/http-logging.interceptor";
5
6
  import type { LoggerConfig } from "./logger.config";
6
7
 
8
+ const httpLoggingInterceptorProvider: Provider = {
9
+ provide: HTTP_LOGGING_INTERCEPTOR,
10
+ useClass: HttpLoggingInterceptor,
11
+ };
12
+
7
13
  @Global()
8
14
  @Module({})
9
15
  export class LoggerModule {
10
16
  static forRoot(config?: LoggerConfig): DynamicModule {
11
17
  const implModule = WinstonImplementationModule.forRoot(config);
12
- const provider: Provider = {
18
+ const loggerProvider: Provider = {
13
19
  provide: LOGGER_PROVIDER,
14
20
  useClass: LoggerProvider,
15
21
  };
16
22
  if (config && config.requestScoped) {
17
- provider.scope = Scope.REQUEST;
23
+ loggerProvider.scope = Scope.REQUEST;
18
24
  }
19
25
 
20
26
  return {
21
27
  module: LoggerModule,
22
28
  imports: [implModule],
23
- providers: [provider],
24
- exports: [LOGGER_PROVIDER],
29
+ providers: [loggerProvider, httpLoggingInterceptorProvider],
30
+ exports: [LOGGER_PROVIDER, HTTP_LOGGING_INTERCEPTOR],
25
31
  };
26
32
  }
27
33
 
@@ -41,8 +47,9 @@ export class LoggerModule {
41
47
  provide: LOGGER_PROVIDER,
42
48
  useClass: LoggerProvider,
43
49
  },
50
+ httpLoggingInterceptorProvider,
44
51
  ],
45
- exports: [LOGGER_PROVIDER],
52
+ exports: [LOGGER_PROVIDER, HTTP_LOGGING_INTERCEPTOR],
46
53
  };
47
54
  }
48
55
  }
@@ -1 +1,2 @@
1
1
  export const LOGGER_PROVIDER = "LOGGER_PROVIDER";
2
+ export const HTTP_LOGGING_INTERCEPTOR = "HTTP_LOGGING_INTERCEPTOR";