@xrystal/core 3.5.6 → 3.5.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 +1 -1
- package/source/loader/logger/index.js +62 -55
- package/x/dist/loader/logger/index.js +62 -55
- package/x/docker/Dockerfile +2 -0
package/package.json
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
import winston, { format } from "winston";
|
|
2
|
+
import Transport from "winston-transport";
|
|
2
3
|
import "winston-daily-rotate-file";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
6
|
import { Kafka, Partitioners, logLevel } from "kafkajs";
|
|
6
7
|
import { LoggerLayerEnum } from "../../utils";
|
|
8
|
+
class KafkaTransport extends Transport {
|
|
9
|
+
service;
|
|
10
|
+
constructor(opts, service) {
|
|
11
|
+
super(opts);
|
|
12
|
+
this.service = service;
|
|
13
|
+
}
|
|
14
|
+
log(info, callback) {
|
|
15
|
+
setImmediate(() => {
|
|
16
|
+
this.emit("logged", info);
|
|
17
|
+
});
|
|
18
|
+
this.service["logToKafka"](info).finally(() => {
|
|
19
|
+
callback();
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
7
23
|
const customLevels = {
|
|
8
24
|
critical: LoggerLayerEnum.CRITICAL,
|
|
9
25
|
error: LoggerLayerEnum.ERROR,
|
|
@@ -38,11 +54,6 @@ export default class LoggerService {
|
|
|
38
54
|
if (store) {
|
|
39
55
|
info.id = store.get("correlationId");
|
|
40
56
|
}
|
|
41
|
-
Object.keys(info).forEach(key => {
|
|
42
|
-
if (info[key] instanceof Headers) {
|
|
43
|
-
info[key] = Object.fromEntries(info[key].entries());
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
57
|
return info;
|
|
47
58
|
});
|
|
48
59
|
getConsoleFormat() {
|
|
@@ -75,68 +86,64 @@ export default class LoggerService {
|
|
|
75
86
|
this.serviceName = config?.serviceName || "service";
|
|
76
87
|
this.environment = config?.env || "dev";
|
|
77
88
|
this.kafkaTopic = config?.kafkaTopic || "logs";
|
|
78
|
-
this.winstonLoader({
|
|
79
|
-
loadPath: config?.loadPath || "./logs",
|
|
80
|
-
loggerLevel: config?.loggerLevel || "debug"
|
|
81
|
-
});
|
|
82
89
|
const rawBrokers = config?.kafkaBrokers;
|
|
83
90
|
const brokers = rawBrokers ? String(rawBrokers).split(",").map((b) => b.trim()) : [];
|
|
84
91
|
if (brokers.length > 0) {
|
|
85
92
|
const kafka = new Kafka({
|
|
86
93
|
clientId: this.serviceName,
|
|
87
94
|
brokers: brokers,
|
|
88
|
-
logLevel: logLevel.ERROR
|
|
89
|
-
retry: {
|
|
90
|
-
initialRetryTime: 1000,
|
|
91
|
-
retries: 10,
|
|
92
|
-
maxRetryTime: 30000,
|
|
93
|
-
factor: 2
|
|
94
|
-
},
|
|
95
|
+
logLevel: logLevel.ERROR
|
|
95
96
|
});
|
|
96
|
-
this.kafkaProducer = kafka.producer({
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
catch (err) {
|
|
103
|
-
this.isKafkaReady = false;
|
|
104
|
-
setTimeout(connectWithRetry, 5000);
|
|
97
|
+
this.kafkaProducer = kafka.producer({
|
|
98
|
+
createPartitioner: Partitioners.DefaultPartitioner,
|
|
99
|
+
retry: {
|
|
100
|
+
initialRetryTime: 100,
|
|
101
|
+
retries: 8
|
|
105
102
|
}
|
|
106
|
-
};
|
|
107
|
-
|
|
103
|
+
});
|
|
104
|
+
try {
|
|
105
|
+
await this.kafkaProducer.connect();
|
|
106
|
+
this.isKafkaReady = true;
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
this.isKafkaReady = false;
|
|
110
|
+
console.error("Kafka Connection Error:", err);
|
|
111
|
+
}
|
|
108
112
|
}
|
|
113
|
+
this.winstonLoader({
|
|
114
|
+
loadPath: config?.loadPath || "./logs",
|
|
115
|
+
loggerLevel: config?.loggerLevel || "debug"
|
|
116
|
+
});
|
|
109
117
|
};
|
|
110
118
|
winstonLoader = ({ loadPath, loggerLevel }) => {
|
|
111
119
|
const { combine, timestamp, json, errors } = format;
|
|
112
120
|
const jsonFileFormat = combine(this.getTracingFormat(), timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), errors({ stack: true }), json({ replacer: this.safeReplacer }));
|
|
121
|
+
const transports = [
|
|
122
|
+
new winston.transports.Console({
|
|
123
|
+
format: this.getConsoleFormat()
|
|
124
|
+
}),
|
|
125
|
+
new winston.transports.DailyRotateFile({
|
|
126
|
+
filename: path.resolve(loadPath, "error", "%DATE%_error.log"),
|
|
127
|
+
level: "error",
|
|
128
|
+
format: jsonFileFormat,
|
|
129
|
+
maxSize: "2mb",
|
|
130
|
+
maxFiles: "7d"
|
|
131
|
+
}),
|
|
132
|
+
new winston.transports.DailyRotateFile({
|
|
133
|
+
filename: path.resolve(loadPath, "critical", "%DATE%_critical.log"),
|
|
134
|
+
level: "critical",
|
|
135
|
+
format: jsonFileFormat,
|
|
136
|
+
maxSize: "2mb",
|
|
137
|
+
maxFiles: "14d"
|
|
138
|
+
})
|
|
139
|
+
];
|
|
140
|
+
if (this.kafkaProducer) {
|
|
141
|
+
transports.push(new KafkaTransport({ level: loggerLevel }, this));
|
|
142
|
+
}
|
|
113
143
|
const winstonLogger = winston.createLogger({
|
|
114
144
|
level: loggerLevel,
|
|
115
145
|
levels: customLevels,
|
|
116
|
-
transports
|
|
117
|
-
new winston.transports.Console({
|
|
118
|
-
format: this.getConsoleFormat()
|
|
119
|
-
}),
|
|
120
|
-
new winston.transports.DailyRotateFile({
|
|
121
|
-
filename: path.resolve(loadPath, "error", "%DATE%_error.log"),
|
|
122
|
-
level: "error",
|
|
123
|
-
format: jsonFileFormat,
|
|
124
|
-
maxSize: "2mb",
|
|
125
|
-
maxFiles: "7d"
|
|
126
|
-
}),
|
|
127
|
-
new winston.transports.DailyRotateFile({
|
|
128
|
-
filename: path.resolve(loadPath, "critical", "%DATE%_critical.log"),
|
|
129
|
-
level: "critical",
|
|
130
|
-
format: jsonFileFormat,
|
|
131
|
-
maxSize: "2mb",
|
|
132
|
-
maxFiles: "14d"
|
|
133
|
-
})
|
|
134
|
-
]
|
|
135
|
-
});
|
|
136
|
-
winstonLogger.on("data", (info) => {
|
|
137
|
-
if (this.isKafkaReady) {
|
|
138
|
-
this.logToKafka(info);
|
|
139
|
-
}
|
|
146
|
+
transports
|
|
140
147
|
});
|
|
141
148
|
this.winston = winstonLogger;
|
|
142
149
|
return winstonLogger;
|
|
@@ -150,19 +157,19 @@ export default class LoggerService {
|
|
|
150
157
|
topic: this.kafkaTopic,
|
|
151
158
|
messages: [{
|
|
152
159
|
value: JSON.stringify({
|
|
153
|
-
|
|
160
|
+
id: id || null,
|
|
154
161
|
service: this.serviceName,
|
|
162
|
+
env: this.environment,
|
|
155
163
|
level,
|
|
156
164
|
message,
|
|
157
165
|
...rest,
|
|
158
|
-
|
|
159
|
-
env: this.environment,
|
|
166
|
+
timestamp: new Date().toISOString()
|
|
160
167
|
}, this.safeReplacer)
|
|
161
168
|
}]
|
|
162
169
|
});
|
|
163
170
|
}
|
|
164
171
|
catch (err) {
|
|
165
|
-
|
|
172
|
+
console.error("Kafka Send Error:", err);
|
|
166
173
|
}
|
|
167
174
|
}
|
|
168
175
|
}
|
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
import winston, { format } from "winston";
|
|
2
|
+
import Transport from "winston-transport";
|
|
2
3
|
import "winston-daily-rotate-file";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
6
|
import { Kafka, Partitioners, logLevel } from "kafkajs";
|
|
6
7
|
import { LoggerLayerEnum } from "../../utils";
|
|
8
|
+
class KafkaTransport extends Transport {
|
|
9
|
+
service;
|
|
10
|
+
constructor(opts, service) {
|
|
11
|
+
super(opts);
|
|
12
|
+
this.service = service;
|
|
13
|
+
}
|
|
14
|
+
log(info, callback) {
|
|
15
|
+
setImmediate(() => {
|
|
16
|
+
this.emit("logged", info);
|
|
17
|
+
});
|
|
18
|
+
this.service["logToKafka"](info).finally(() => {
|
|
19
|
+
callback();
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
7
23
|
const customLevels = {
|
|
8
24
|
critical: LoggerLayerEnum.CRITICAL,
|
|
9
25
|
error: LoggerLayerEnum.ERROR,
|
|
@@ -38,11 +54,6 @@ export default class LoggerService {
|
|
|
38
54
|
if (store) {
|
|
39
55
|
info.id = store.get("correlationId");
|
|
40
56
|
}
|
|
41
|
-
Object.keys(info).forEach(key => {
|
|
42
|
-
if (info[key] instanceof Headers) {
|
|
43
|
-
info[key] = Object.fromEntries(info[key].entries());
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
57
|
return info;
|
|
47
58
|
});
|
|
48
59
|
getConsoleFormat() {
|
|
@@ -75,68 +86,64 @@ export default class LoggerService {
|
|
|
75
86
|
this.serviceName = config?.serviceName || "service";
|
|
76
87
|
this.environment = config?.env || "dev";
|
|
77
88
|
this.kafkaTopic = config?.kafkaTopic || "logs";
|
|
78
|
-
this.winstonLoader({
|
|
79
|
-
loadPath: config?.loadPath || "./logs",
|
|
80
|
-
loggerLevel: config?.loggerLevel || "debug"
|
|
81
|
-
});
|
|
82
89
|
const rawBrokers = config?.kafkaBrokers;
|
|
83
90
|
const brokers = rawBrokers ? String(rawBrokers).split(",").map((b) => b.trim()) : [];
|
|
84
91
|
if (brokers.length > 0) {
|
|
85
92
|
const kafka = new Kafka({
|
|
86
93
|
clientId: this.serviceName,
|
|
87
94
|
brokers: brokers,
|
|
88
|
-
logLevel: logLevel.ERROR
|
|
89
|
-
retry: {
|
|
90
|
-
initialRetryTime: 1000,
|
|
91
|
-
retries: 10,
|
|
92
|
-
maxRetryTime: 30000,
|
|
93
|
-
factor: 2
|
|
94
|
-
},
|
|
95
|
+
logLevel: logLevel.ERROR
|
|
95
96
|
});
|
|
96
|
-
this.kafkaProducer = kafka.producer({
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
catch (err) {
|
|
103
|
-
this.isKafkaReady = false;
|
|
104
|
-
setTimeout(connectWithRetry, 5000);
|
|
97
|
+
this.kafkaProducer = kafka.producer({
|
|
98
|
+
createPartitioner: Partitioners.DefaultPartitioner,
|
|
99
|
+
retry: {
|
|
100
|
+
initialRetryTime: 100,
|
|
101
|
+
retries: 8
|
|
105
102
|
}
|
|
106
|
-
};
|
|
107
|
-
|
|
103
|
+
});
|
|
104
|
+
try {
|
|
105
|
+
await this.kafkaProducer.connect();
|
|
106
|
+
this.isKafkaReady = true;
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
this.isKafkaReady = false;
|
|
110
|
+
console.error("Kafka Connection Error:", err);
|
|
111
|
+
}
|
|
108
112
|
}
|
|
113
|
+
this.winstonLoader({
|
|
114
|
+
loadPath: config?.loadPath || "./logs",
|
|
115
|
+
loggerLevel: config?.loggerLevel || "debug"
|
|
116
|
+
});
|
|
109
117
|
};
|
|
110
118
|
winstonLoader = ({ loadPath, loggerLevel }) => {
|
|
111
119
|
const { combine, timestamp, json, errors } = format;
|
|
112
120
|
const jsonFileFormat = combine(this.getTracingFormat(), timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), errors({ stack: true }), json({ replacer: this.safeReplacer }));
|
|
121
|
+
const transports = [
|
|
122
|
+
new winston.transports.Console({
|
|
123
|
+
format: this.getConsoleFormat()
|
|
124
|
+
}),
|
|
125
|
+
new winston.transports.DailyRotateFile({
|
|
126
|
+
filename: path.resolve(loadPath, "error", "%DATE%_error.log"),
|
|
127
|
+
level: "error",
|
|
128
|
+
format: jsonFileFormat,
|
|
129
|
+
maxSize: "2mb",
|
|
130
|
+
maxFiles: "7d"
|
|
131
|
+
}),
|
|
132
|
+
new winston.transports.DailyRotateFile({
|
|
133
|
+
filename: path.resolve(loadPath, "critical", "%DATE%_critical.log"),
|
|
134
|
+
level: "critical",
|
|
135
|
+
format: jsonFileFormat,
|
|
136
|
+
maxSize: "2mb",
|
|
137
|
+
maxFiles: "14d"
|
|
138
|
+
})
|
|
139
|
+
];
|
|
140
|
+
if (this.kafkaProducer) {
|
|
141
|
+
transports.push(new KafkaTransport({ level: loggerLevel }, this));
|
|
142
|
+
}
|
|
113
143
|
const winstonLogger = winston.createLogger({
|
|
114
144
|
level: loggerLevel,
|
|
115
145
|
levels: customLevels,
|
|
116
|
-
transports
|
|
117
|
-
new winston.transports.Console({
|
|
118
|
-
format: this.getConsoleFormat()
|
|
119
|
-
}),
|
|
120
|
-
new winston.transports.DailyRotateFile({
|
|
121
|
-
filename: path.resolve(loadPath, "error", "%DATE%_error.log"),
|
|
122
|
-
level: "error",
|
|
123
|
-
format: jsonFileFormat,
|
|
124
|
-
maxSize: "2mb",
|
|
125
|
-
maxFiles: "7d"
|
|
126
|
-
}),
|
|
127
|
-
new winston.transports.DailyRotateFile({
|
|
128
|
-
filename: path.resolve(loadPath, "critical", "%DATE%_critical.log"),
|
|
129
|
-
level: "critical",
|
|
130
|
-
format: jsonFileFormat,
|
|
131
|
-
maxSize: "2mb",
|
|
132
|
-
maxFiles: "14d"
|
|
133
|
-
})
|
|
134
|
-
]
|
|
135
|
-
});
|
|
136
|
-
winstonLogger.on("data", (info) => {
|
|
137
|
-
if (this.isKafkaReady) {
|
|
138
|
-
this.logToKafka(info);
|
|
139
|
-
}
|
|
146
|
+
transports
|
|
140
147
|
});
|
|
141
148
|
this.winston = winstonLogger;
|
|
142
149
|
return winstonLogger;
|
|
@@ -150,19 +157,19 @@ export default class LoggerService {
|
|
|
150
157
|
topic: this.kafkaTopic,
|
|
151
158
|
messages: [{
|
|
152
159
|
value: JSON.stringify({
|
|
153
|
-
|
|
160
|
+
id: id || null,
|
|
154
161
|
service: this.serviceName,
|
|
162
|
+
env: this.environment,
|
|
155
163
|
level,
|
|
156
164
|
message,
|
|
157
165
|
...rest,
|
|
158
|
-
|
|
159
|
-
env: this.environment,
|
|
166
|
+
timestamp: new Date().toISOString()
|
|
160
167
|
}, this.safeReplacer)
|
|
161
168
|
}]
|
|
162
169
|
});
|
|
163
170
|
}
|
|
164
171
|
catch (err) {
|
|
165
|
-
|
|
172
|
+
console.error("Kafka Send Error:", err);
|
|
166
173
|
}
|
|
167
174
|
}
|
|
168
175
|
}
|