Skip to content

Commit 27e0eab

Browse files
Merge PR: Use Winston logger and refine some logs
2 parents b373d7d + e6907af commit 27e0eab

File tree

8 files changed

+327
-35
lines changed

8 files changed

+327
-35
lines changed

package-lock.json

Lines changed: 253 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"passport": "^0.7.0",
5454
"passport-jwt": "^4.0.1",
5555
"passport-local": "^1.0.0",
56+
"winston": "^3.17.0",
5657
"zod": "^3.24.3"
5758
},
5859
"devDependencies": {

src/lib/config.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import logger from './logger';
2-
3-
if (!process.env.SECRET) logger.error('Missing Env Var: SECRET');
4-
if (!process.env.ADMIN_SECRET) logger.error('Missing Env Var: ADMIN_SECRET');
1+
if (!process.env.NODE_ENV) console.warn('Miss Env Var: NODE_ENV');
2+
if (!process.env.SECRET) console.error('Missing Env Var: SECRET');
3+
if (!process.env.ADMIN_SECRET) console.error('Missing Env Var: ADMIN_SECRET');
54

65
export const SALT = (Number(process.env.SALT) || process.env.SALT) ?? 10;
76
export const SECRET = process.env.SECRET ?? 'secret';
87
export const ADMIN_SECRET = process.env.ADMIN_SECRET ?? 'admin_secret';
98
export const TOKEN_EXP_PERIOD = process.env.TOKEN_EXP_PERIOD ?? '3d';
9+
export const NODE_ENV = process.env.NODE_ENV;
10+
export const CI = Boolean(process.env.CI);
1011

11-
export default { SALT, SECRET, ADMIN_SECRET, TOKEN_EXP_PERIOD };
12+
export default { SALT, SECRET, ADMIN_SECRET, TOKEN_EXP_PERIOD, NODE_ENV, CI };

src/lib/db.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ const globalForPrisma = global as GlobalWithPrisma;
66

77
export let prismaClient: PrismaClient;
88

9-
logger.info();
109
logger.info(`using prisma client in ${process.env.NODE_ENV} mode`);
1110

1211
if (globalForPrisma.prisma) {
@@ -29,6 +28,4 @@ if (process.env.NODE_ENV !== 'production') {
2928
globalForPrisma.prisma = prismaClient;
3029
}
3130

32-
logger.info();
33-
3431
export default prismaClient;

src/lib/logger.ts

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,60 @@
1-
export default {
2-
log(...args: unknown[]) {
3-
console.log(...args);
4-
},
1+
import { CI, NODE_ENV } from './config';
2+
import winston from 'winston';
3+
import util from 'node:util';
54

6-
info(...args: unknown[]) {
7-
console.info(...args);
8-
},
9-
10-
warn(...args: unknown[]) {
11-
console.warn(...args);
12-
},
5+
const stripSymbols = (anyObj: unknown): unknown => {
6+
return typeof anyObj === 'object' &&
7+
anyObj !== null &&
8+
Object.keys(anyObj).length &&
9+
!Array.isArray(anyObj)
10+
? Object.fromEntries(Object.entries(anyObj))
11+
: anyObj;
12+
};
1313

14-
error(...args: unknown[]) {
15-
if (args.every((a) => a instanceof Error)) {
16-
console.error(...args.map((a) => a.toString()));
17-
} else {
18-
console.error(...args);
19-
}
20-
},
14+
const inspectObj = (anyObj: unknown): string => {
15+
if (typeof anyObj === 'string') return anyObj;
16+
const obj = stripSymbols(anyObj);
17+
return util.inspect(obj, { depth: null, colors: true, compact: CI });
2118
};
19+
20+
const winstonLevelColorsExt = Object.fromEntries(
21+
Object.entries(winston.config.npm.colors).map(([level, color]) => [
22+
level.toUpperCase(),
23+
color,
24+
])
25+
);
26+
27+
winston.addColors(winstonLevelColorsExt);
28+
29+
export const logger = winston.createLogger({
30+
format: winston.format.combine(
31+
winston.format((info) => {
32+
info.level = info.level.toUpperCase();
33+
return info;
34+
})(),
35+
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
36+
winston.format.colorize({ level: true }),
37+
winston.format.printf(({ timestamp, level, message, ...meta }) => {
38+
return `[${timestamp}] ${level}: ${inspectObj(message)}${
39+
Object.keys(meta).length ? '\n' + inspectObj(meta) : ''
40+
}`;
41+
})
42+
),
43+
transports: [new winston.transports.Console()],
44+
silent: NODE_ENV === 'test',
45+
level: 'info',
46+
});
47+
48+
if (!CI) {
49+
logger.add(
50+
new winston.transports.File({
51+
tailable: true,
52+
filename: 'logs/app.log',
53+
format: winston.format.json(),
54+
maxsize: 1024 * 1024 * 5, // 5MB
55+
maxFiles: 3,
56+
})
57+
);
58+
}
59+
60+
export default logger;

src/middlewares/request-logger.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { NextFunction, Request, Response } from 'express';
22
import logger from '../lib/logger';
33

4-
export const logReq = (req: Request, res: Response, next: NextFunction) => {
5-
logger.log('<---');
6-
logger.info(`${req.method}: ${req.originalUrl}`);
7-
if (req.body) logger.info(req.body);
8-
logger.log('--->');
4+
export const requestLogger = (
5+
req: Request,
6+
res: Response,
7+
next: NextFunction
8+
) => {
9+
const body = req.body as unknown;
10+
logger.info(`${req.method}: ${req.originalUrl}`, { body });
911
next();
1012
};
1113

12-
export default logReq;
14+
export default requestLogger;

src/server.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import logger from './lib/logger';
12
import app from './app';
23

34
const PORT = Number(process.env.PORT) || 3001;
45

5-
app.listen(PORT, () => console.log(`Listening on port ${PORT}`));
6+
app.listen(PORT, () => logger.info(`The server is running on prot ${PORT}...`));

src/tests/api/v1/auth.int.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ describe('Authentication endpoint', () => {
8080
it('should sign in and response with JWT and user insensitive-info', async () => {
8181
const res = await api.post(SIGNIN_URL).send(signInData);
8282
const resBody = res.body as SignInResponse;
83-
console.log(resBody);
8483
const resUser = resBody.user as User;
8584
const resJwtPayload = jwt.decode(
8685
resBody.token.replace(/^Bearer /, '')

0 commit comments

Comments
 (0)