@@ -9,42 +9,66 @@ import { Observable, throwError } from 'rxjs';
99import { tap , catchError } from 'rxjs/operators' ;
1010import type { FastifyRequest } from 'fastify' ;
1111import { WinstonModule , utilities } from 'nest-winston' ;
12- import { format , transports } from 'winston' ;
12+ import { format , transport , transports } from 'winston' ;
13+ import Loki from 'winston-loki' ;
14+ import type { NestFastifyApplication } from '@nestjs/platform-fastify' ;
15+ import { ConfigService } from '@nestjs/config' ;
1316
14- export function setupLogger ( service : string ) {
15- const isProduction = process . env . NODE_ENV === 'production' ;
17+ export function setupLogger ( app : NestFastifyApplication , service : string ) {
18+ const cfg = app . get ( ConfigService ) ;
1619
17- return WinstonModule . createLogger ( {
18- level : isProduction ? 'info' : 'debug' ,
19- transports : [
20- new transports . Console ( {
21- format : format . combine (
22- format . timestamp ( { format : 'YYYY-MM-DD HH:mm:ss' } ) ,
23- format . ms ( ) ,
24- format . errors ( { stack : true } ) ,
25- format . metadata ( { fillExcept : [ 'message' , 'level' , 'timestamp' , 'context' ] } ) ,
26- format ( ( info ) => {
27- const mask = ( obj : any ) => {
28- const sensitive = [ 'password' , 'token' , 'secret' , 'authorization' ] ;
29- for ( const key in obj ) {
30- if ( sensitive . includes ( key . toLowerCase ( ) ) ) obj [ key ] = '***' ;
31- else if ( typeof obj [ key ] === 'object' ) mask ( obj [ key ] ) ;
32- }
33- } ;
34- if ( info . metadata ) mask ( info . metadata ) ;
35- return info ;
36- } ) ( ) ,
37-
38- isProduction
39- ? format . json ( )
40- : utilities . format . nestLike ( service , {
41- colors : true ,
42- prettyPrint : false ,
43- } ) ,
44- ) ,
20+ const isProduction = cfg . get ( 'NODE_ENV' ) === 'production' ;
21+ const loki = cfg . get ( 'LOKI_HOST' ) ;
22+
23+ const transportsList : transport [ ] = [
24+ new transports . Console ( {
25+ format : format . combine (
26+ format . timestamp ( { format : 'YYYY-MM-DD HH:mm:ss' } ) ,
27+ format . ms ( ) ,
28+ format . errors ( { stack : true } ) ,
29+ format . metadata ( { fillExcept : [ 'message' , 'level' , 'timestamp' , 'context' ] } ) ,
30+ format ( ( info ) => {
31+ const mask = ( obj : any ) => {
32+ const sensitive = [ 'password' , 'token' , 'secret' , 'authorization' ] ;
33+ for ( const key in obj ) {
34+ if ( sensitive . includes ( key . toLowerCase ( ) ) ) obj [ key ] = '***' ;
35+ else if ( typeof obj [ key ] === 'object' ) mask ( obj [ key ] ) ;
36+ }
37+ } ;
38+ if ( info . metadata ) mask ( info . metadata ) ;
39+ return info ;
40+ } ) ( ) ,
41+
42+ isProduction
43+ ? format . json ( )
44+ : utilities . format . nestLike ( service , {
45+ colors : true ,
46+ prettyPrint : false ,
47+ } ) ,
48+ ) ,
49+ } ) ,
50+ ] ;
51+
52+ if ( loki ) {
53+ transportsList . push (
54+ new Loki ( {
55+ host : loki ,
56+ labels : { app : service } ,
57+ json : true ,
58+ format : format . json ( ) ,
59+ replaceTimestamp : true ,
60+ onConnectionError : ( err ) => console . error ( 'Loki connection error:' , err ) ,
4561 } ) ,
46- ] ,
62+ ) ;
63+ }
64+
65+ const logger = WinstonModule . createLogger ( {
66+ level : isProduction ? 'info' : 'debug' ,
67+ transports : transportsList ,
4768 } ) ;
69+
70+ app . useLogger ( logger ) ;
71+ app . useGlobalInterceptors ( new LoggingInterceptor ( ) ) ;
4872}
4973
5074@Injectable ( )
0 commit comments