Skip to content

Commit 0397bb9

Browse files
ArtemHoruzhenkoseth-riedel
authored andcommitted
enhance logger
1 parent 9eab472 commit 0397bb9

File tree

2 files changed

+99
-49
lines changed

2 files changed

+99
-49
lines changed

redisinsight/api/config/logger.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@ if (LOGGER_CONFIG.stdout) {
1919
format: format.combine(
2020
sensitiveDataFormatter({ omitSensitiveData: LOGGER_CONFIG.omitSensitiveData }),
2121
format.timestamp(),
22-
nestWinstonModuleUtilities.format.nestLike(),
22+
nestWinstonModuleUtilities.format.nestLike('Redis Insight', {
23+
colors: true,
24+
prettyPrint: true,
25+
processId: true,
26+
appName: true,
27+
}),
2328
),
2429
}),
2530
);

redisinsight/api/src/common/logger/app-logger.ts

Lines changed: 93 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import { LoggerService, Injectable } from '@nestjs/common';
22
import { WinstonModule, WinstonModuleOptions } from 'nest-winston';
3+
import { isString } from 'lodash';
4+
import { ClientMetadata, SessionMetadata } from 'src/common/models';
35

46
type LogMeta = object;
57

68
type LogObject = {
79
[key: string]: unknown;
810
};
911

10-
type ErrorOrMeta = Error | LogMeta | string;
12+
type ErrorOrMeta = Error | LogMeta | string | ClientMetadata | SessionMetadata;
1113

1214
@Injectable()
1315
export class AppLogger implements LoggerService {
@@ -25,89 +27,132 @@ export class AppLogger implements LoggerService {
2527
this.logger = WinstonModule.createLogger(loggerConfig);
2628
}
2729

28-
private isException(error?: unknown) {
29-
return !!(
30-
error instanceof Error
31-
|| ((error as Error)?.stack && (error as Error)?.message)
32-
);
30+
/**
31+
* Get context from optional arguments
32+
* If the last argument is a string - it will be handled like a context
33+
* since nest passes the logger context as the last argument
34+
* Note: args array might be mutated
35+
* @param args
36+
*/
37+
static getContext(args: ErrorOrMeta[] = []): string {
38+
const lastArg = args?.[args.length - 1];
39+
40+
if (isString(lastArg)) {
41+
return args.pop() as string;
42+
}
43+
44+
return 'TODO: generic name or null?';
45+
}
46+
47+
/**
48+
* Get an error from the optional arguments
49+
* Will find first entry which is error type
50+
* Note: args array might be mutated
51+
* @param args
52+
*/
53+
static getError(args: ErrorOrMeta[] = []): void | {} {
54+
let error = null;
55+
const index = args.findIndex((arg) => (arg instanceof Error));
56+
if (index > -1) {
57+
[error] = args.splice(index, 1);
58+
}
59+
60+
if (error) {
61+
return {
62+
message: error.message,
63+
stack: error.stack,
64+
response: error.response,
65+
};
66+
}
67+
68+
return undefined;
69+
}
70+
71+
/**
72+
* Get clientMetadata and/or sessionMetadata object(s) from args
73+
* Will find first entry of ClientMetadata and get SessionMetadata, from it and return both
74+
* otherwise will find SessionMetadata and return only it
75+
* otherwise will return empty object
76+
* Note: args array might be mutated
77+
* @param args
78+
*/
79+
static getUserMetadata(args: ErrorOrMeta[] = []): {
80+
clientMetadata?: Partial<ClientMetadata>,
81+
sessionMetadata?: SessionMetadata,
82+
} {
83+
// check for client metadata in args
84+
const clientMetadataIndex = args.findIndex((arg) => (arg instanceof ClientMetadata));
85+
if (clientMetadataIndex > -1) {
86+
const [clientMetadata] = args.splice(clientMetadataIndex, 1) as ClientMetadata[];
87+
return {
88+
clientMetadata: {
89+
...clientMetadata,
90+
sessionMetadata: undefined,
91+
},
92+
sessionMetadata: clientMetadata.sessionMetadata,
93+
};
94+
}
95+
96+
// check for session metadata in args
97+
const sessionMetadataIndex = args.findIndex((arg) => (arg instanceof SessionMetadata));
98+
if (sessionMetadataIndex > -1) {
99+
const [sessionMetadata] = args.splice(sessionMetadataIndex, 1) as SessionMetadata[];
100+
return {
101+
sessionMetadata,
102+
};
103+
}
104+
105+
// by default will return empty object
106+
return {};
33107
}
34108

35109
private parseLoggerArgs(
36110
message: string | LogObject,
37-
optionalParams: ErrorOrMeta[],
38-
isErrorLevel = false,
111+
optionalParams: ErrorOrMeta[] = [],
39112
) {
40113
const messageObj: LogObject = (
41114
typeof message === 'object' ? message : { message }
42115
) as LogObject;
43-
const meta = [];
44-
let errorMessage: string;
45-
let errorStack: string;
46-
47-
// nest passes the logger context as the last argument
48-
const contextArg = optionalParams?.[optionalParams.length - 1];
49-
50-
// the global exception filter converts the error object to strings
51-
if (
52-
isErrorLevel
53-
&& typeof optionalParams[0] === 'string'
54-
&& optionalParams.length > 1
55-
) {
56-
errorStack = optionalParams.shift() as string;
57-
}
58116

59-
for (const k in optionalParams) {
60-
if (this.isException(optionalParams[k])) {
61-
errorMessage = (optionalParams[k] as Error).message;
62-
errorStack = (optionalParams[k] as Error).stack;
63-
} else if (optionalParams[k] !== contextArg) {
64-
meta.push(optionalParams[k]);
65-
}
66-
}
67-
const metaObj = meta.length > 1 ? meta : meta[0];
117+
const context = AppLogger.getContext(optionalParams);
118+
const error = AppLogger.getError(optionalParams);
119+
const userMetadata = AppLogger.getUserMetadata(optionalParams);
68120

69121
return {
70-
context: contextArg && typeof contextArg === 'string' ? contextArg : null,
71-
...metaObj,
72-
...(messageObj || {}),
73-
...(errorMessage || errorStack
74-
? {
75-
error: errorMessage,
76-
stack: [errorStack],
77-
}
78-
: {}),
122+
...messageObj,
123+
context,
124+
error,
125+
...userMetadata,
126+
data: optionalParams?.length ? optionalParams : undefined,
79127
};
80128
}
81129

82130
/**
83131
* Write a 'log' level log.
84132
*/
85133
log(message: string | LogObject, ...optionalParams: ErrorOrMeta[]) {
86-
const parsedArgs = this.parseLoggerArgs(message, optionalParams);
87-
if (!AppLogger.startupContexts.includes(parsedArgs.context)) {
88-
this.logger.log(parsedArgs);
89-
}
134+
this.logger.log(this.parseLoggerArgs(message, optionalParams));
90135
}
91136

92137
/**
93138
* Write a 'fatal' level log.
94139
*/
95140
fatal(message: string | LogObject, ...optionalParams: ErrorOrMeta[]) {
96-
this.logger.fatal(this.parseLoggerArgs(message, optionalParams, true));
141+
this.logger.fatal(this.parseLoggerArgs(message, optionalParams));
97142
}
98143

99144
/**
100145
* Write an 'error' level log.
101146
*/
102147
error(message: string | LogObject, ...optionalParams: ErrorOrMeta[]) {
103-
this.logger.error(this.parseLoggerArgs(message, optionalParams, true));
148+
this.logger.error(this.parseLoggerArgs(message, optionalParams));
104149
}
105150

106151
/**
107152
* Write a 'warn' level log.
108153
*/
109154
warn(message: string | LogObject, ...optionalParams: ErrorOrMeta[]) {
110-
this.logger.warn(this.parseLoggerArgs(message, optionalParams, true));
155+
this.logger.warn(this.parseLoggerArgs(message, optionalParams));
111156
}
112157

113158
/**

0 commit comments

Comments
 (0)