@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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "author": "Yusuf Yasir KAYGUSUZ",
3
3
  "name": "@xrystal/core",
4
- "version": "3.5.6",
4
+ "version": "3.5.8",
5
5
  "description": "Project core for xrystal",
6
6
  "publishConfig": {
7
7
  "access": "public",
@@ -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({ createPartitioner: Partitioners.LegacyPartitioner });
97
- const connectWithRetry = async () => {
98
- try {
99
- await this.kafkaProducer?.connect();
100
- this.isKafkaReady = true;
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
- connectWithRetry();
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
- timestamp: new Date().toISOString(),
160
+ id: id || null,
154
161
  service: this.serviceName,
162
+ env: this.environment,
155
163
  level,
156
164
  message,
157
165
  ...rest,
158
- id: id || null,
159
- env: this.environment,
166
+ timestamp: new Date().toISOString()
160
167
  }, this.safeReplacer)
161
168
  }]
162
169
  });
163
170
  }
164
171
  catch (err) {
165
- this.isKafkaReady = false;
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({ createPartitioner: Partitioners.LegacyPartitioner });
97
- const connectWithRetry = async () => {
98
- try {
99
- await this.kafkaProducer?.connect();
100
- this.isKafkaReady = true;
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
- connectWithRetry();
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
- timestamp: new Date().toISOString(),
160
+ id: id || null,
154
161
  service: this.serviceName,
162
+ env: this.environment,
155
163
  level,
156
164
  message,
157
165
  ...rest,
158
- id: id || null,
159
- env: this.environment,
166
+ timestamp: new Date().toISOString()
160
167
  }, this.safeReplacer)
161
168
  }]
162
169
  });
163
170
  }
164
171
  catch (err) {
165
- this.isKafkaReady = false;
172
+ console.error("Kafka Send Error:", err);
166
173
  }
167
174
  }
168
175
  }
@@ -21,4 +21,6 @@ COPY --from=builder /app/x ./x
21
21
  COPY --from=builder /app/package.json ./package.json
22
22
  COPY --from=builder /app/bun.lockb* ./
23
23
 
24
+ RUN rm -rf ./x/dist
25
+
24
26
  RUN bun install --production