forked from SmartDropLabs/smartdrop-backend
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlogger.js
More file actions
103 lines (91 loc) · 3.43 KB
/
Copy pathlogger.js
File metadata and controls
103 lines (91 loc) · 3.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
const winston = require('winston');
const DailyRotateFile = require('winston-daily-rotate-file');
const { name: serviceName, version } = require('../package.json');
const { requestContext } = require('./middleware/requestId');
const { redactFormat } = require('./services/logRedaction');
// ==================== LOG LEVEL ====================
const getLogLevel = () => {
if (process.env.LOG_LEVEL) {
return process.env.LOG_LEVEL;
}
const env = process.env.NODE_ENV || 'development';
if (env === 'production') return 'info';
if (env === 'test') return 'warn';
return 'debug';
};
// ==================== FORMAT DECISION ====================
const env = process.env.NODE_ENV || 'development';
const logFormat = process.env.LOG_FORMAT || (env === 'production' ? 'json' : 'pretty');
const useJsonFormat = logFormat === 'json';
// ==================== REQUEST CONTEXT ====================
const requestIdFormat = winston.format((info) => {
const requestId = requestContext.getStore()?.requestId ?? 'system';
info.requestId = requestId;
// snake_case alias so structured log output matches the request_id field
// name used on delivery records and in API responses (issue #250).
// `requestId` is kept for existing dashboards and queries.
if (info.request_id === undefined) info.request_id = requestId;
return info;
});
const errorTrackerFormat = winston.format((info) => {
if (info.level === 'error') {
const errorObj = info.error instanceof Error ? info.error : (info.stack ? info : new Error(info.message || 'Logged Error'));
const { level, message, timestamp, ...extra } = info;
require('./services/errorTracker').captureException(errorObj, extra);
}
return info;
});
// ==================== BASE FORMATS ====================
const baseFormats = [
winston.format.timestamp({ format: () => new Date().toISOString() }),
winston.format.errors({ stack: true }),
requestIdFormat(),
redactFormat(),
errorTrackerFormat(),
];
// ==================== JSON FORMAT ====================
const jsonFormat = winston.format.combine(
...baseFormats,
winston.format.json()
);
// ==================== PRETTY FORMAT ====================
const prettyFormat = winston.format.combine(
...baseFormats,
winston.format.colorize(),
winston.format.printf(({ timestamp, level, message, stack, ...meta }) => {
// request_id is a snake_case alias of requestId (issue #250); printing
// both would duplicate the same value in every pretty-formatted line.
const { service, version: ver, request_id: _requestIdAlias, ...rest } = meta;
const metaStr = Object.keys(rest).length
? ` ${JSON.stringify(rest)}`
: '';
return `${timestamp} [${level}] [${service}@${ver}] ${message}${metaStr}${stack ? `\n${stack}` : ''}`;
})
);
// ==================== TRANSPORTS ====================
const transports = [
new winston.transports.Console({
format: useJsonFormat ? jsonFormat : prettyFormat
})
];
// Optional file logging
if (process.env.LOG_FILE_PATH) {
transports.push(
new DailyRotateFile({
filename: `${process.env.LOG_FILE_PATH}/application-%DATE%.log`,
datePattern: 'YYYY-MM-DD',
zippedArchive: true,
maxSize: '20m',
maxFiles: '14d',
format: jsonFormat
})
);
}
// ==================== LOGGER ====================
const logger = winston.createLogger({
level: getLogLevel(),
defaultMeta: { service: serviceName, version },
transports,
exitOnError: false
});
module.exports = logger;