@xrystal/core 3.17.3 → 3.17.5

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/README.md CHANGED
@@ -1,14 +1,21 @@
1
1
  ## **DOCUMENT**
2
2
 
3
3
  # LOG Schema
4
+ JS
4
5
  '
5
- service: this.serviceName,
6
+ level
7
+ message
8
+ payload?
9
+ code?
10
+ '
11
+ KAFKA
12
+ '
13
+ service,
6
14
  level,
7
-
8
15
  message,
9
- ...rest,
10
- timestamp: new Date().toISOString(),
11
-
12
- id: id || null,
13
- env: this.environment
16
+ payload,
17
+ code,
18
+ timestamp: ISO String,
19
+ id,
20
+ env
14
21
  '
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "author": "Yusuf Yasir KAYGUSUZ",
3
3
  "name": "@xrystal/core",
4
- "version": "3.17.3",
4
+ "version": "3.17.5",
5
5
  "description": "Project core for xrystal",
6
6
  "publishConfig": {
7
7
  "access": "public",
@@ -1,12 +1,17 @@
1
1
  import winston from "winston";
2
2
  import "winston-daily-rotate-file";
3
3
  import { AsyncLocalStorage } from "node:async_hooks";
4
- import ConfigsService from "../configs";
5
- import { IService } from "../../utils";
4
+ import { LoggerLayerEnum, IService } from "../../utils";
6
5
  interface CustomLogger extends winston.Logger {
7
6
  critical: winston.LeveledLogMethod;
8
7
  http: winston.LeveledLogMethod;
9
8
  }
9
+ interface LogOptions {
10
+ level: LoggerLayerEnum;
11
+ message: any;
12
+ payload?: any;
13
+ code?: string | number;
14
+ }
10
15
  export default class LoggerService implements IService {
11
16
  #private;
12
17
  static readonly storage: AsyncLocalStorage<Map<string, string>>;
@@ -14,19 +19,19 @@ export default class LoggerService implements IService {
14
19
  private kafkaProducer;
15
20
  private kafkaTopic;
16
21
  private isKafkaReady;
17
- constructor({ configsService }: {
18
- configsService: ConfigsService;
19
- });
20
- load: (config: Record<string, any>) => Promise<void>;
21
- private safeReplacer;
22
- private getTracingFormat;
23
- private getConsoleFormat;
24
22
  winston: CustomLogger;
25
- runWithId: <T>(id: string, callback: () => T) => T;
23
+ constructor(deps: any);
24
+ load: (config: Record<string, any>) => Promise<void>;
26
25
  winstonLoader: ({ loadPath, loggerLevel }: {
27
26
  loadPath: string;
28
27
  loggerLevel: string;
29
28
  }) => CustomLogger;
29
+ private safeReplacer;
30
+ private getTracingFormat;
31
+ private getConsoleFormat;
32
+ runWithId: <T>(id: string, callback: () => T) => T;
30
33
  private logToKafka;
34
+ log(level: LoggerLayerEnum, message: any, payload?: any, code?: string | number): void;
35
+ log(options: LogOptions): void;
31
36
  }
32
37
  export {};
@@ -37,10 +37,20 @@ export default class LoggerService {
37
37
  kafkaProducer = null;
38
38
  kafkaTopic = "";
39
39
  isKafkaReady = false;
40
+ winston;
40
41
  #configsService;
41
- constructor({ configsService }) {
42
- this.#configsService = configsService;
42
+ constructor(deps) {
43
+ if (!deps || !deps.configsService) {
44
+ throw new Error("LoggerService: configsService is required");
45
+ }
46
+ this.#configsService = deps.configsService;
43
47
  winston.addColors(customColors);
48
+ this.winston = winston.createLogger({
49
+ level: this.#configsService.all.systemLoggerLayer || 'info',
50
+ levels: customLevels,
51
+ format: this.getConsoleFormat(),
52
+ transports: [new winston.transports.Console()]
53
+ });
44
54
  }
45
55
  load = async (config) => {
46
56
  this.serviceName = config?.serviceName || "service";
@@ -74,45 +84,6 @@ export default class LoggerService {
74
84
  loggerLevel: config?.loggerLevel
75
85
  });
76
86
  };
77
- safeReplacer = (key, value) => {
78
- if (value instanceof Headers)
79
- return Object.fromEntries(value.entries());
80
- if (value instanceof Error)
81
- return { message: value.message, stack: value.stack };
82
- return value;
83
- };
84
- getTracingFormat = format((info) => {
85
- const store = LoggerService.storage.getStore();
86
- if (store && store.has("correlationId")) {
87
- info.id = store.get("correlationId");
88
- }
89
- Object.keys(info).forEach(key => {
90
- if (info[key] instanceof Headers) {
91
- info[key] = Object.fromEntries(info[key].entries());
92
- }
93
- });
94
- return info;
95
- });
96
- getConsoleFormat() {
97
- return format.combine(this.getTracingFormat(), format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), format.colorize({ all: true }), format.printf((info) => {
98
- const msg = typeof info.message === "object"
99
- ? JSON.stringify(info.message, this.safeReplacer)
100
- : info.message;
101
- const idPart = info.id ? ` : id: ${info.id}` : "";
102
- return `${info.timestamp} [${this.serviceName}] ${info.level}: ${msg}${idPart}`;
103
- }));
104
- }
105
- winston = winston.createLogger({
106
- level: "debug",
107
- levels: customLevels,
108
- format: this.getConsoleFormat(),
109
- transports: [new winston.transports.Console()]
110
- });
111
- runWithId = (id, callback) => {
112
- const store = new Map();
113
- store.set("correlationId", id);
114
- return LoggerService.storage.run(store, callback);
115
- };
116
87
  winstonLoader = ({ loadPath, loggerLevel }) => {
117
88
  const { combine, timestamp, json, errors } = format;
118
89
  const tracing = this.getTracingFormat();
@@ -147,11 +118,46 @@ export default class LoggerService {
147
118
  });
148
119
  return this.winston;
149
120
  };
121
+ safeReplacer = (key, value) => {
122
+ if (value instanceof Headers)
123
+ return Object.fromEntries(value.entries());
124
+ if (value instanceof Error)
125
+ return { message: value.message, stack: value.stack };
126
+ return value;
127
+ };
128
+ getTracingFormat = format((info) => {
129
+ const store = LoggerService.storage.getStore();
130
+ if (store && store.has("correlationId")) {
131
+ info.id = store.get("correlationId");
132
+ }
133
+ Object.keys(info).forEach(key => {
134
+ if (info[key] instanceof Headers) {
135
+ info[key] = Object.fromEntries(info[key].entries());
136
+ }
137
+ });
138
+ return info;
139
+ });
140
+ getConsoleFormat() {
141
+ return format.combine(this.getTracingFormat(), format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), format.colorize({ all: true }), format.printf((info) => {
142
+ const msg = typeof info.message === "object"
143
+ ? JSON.stringify(info.message, this.safeReplacer)
144
+ : info.message;
145
+ const idPart = info.id ? ` : id: ${info.id}` : "";
146
+ const payloadPart = info.payload ? `\nPayload: ${JSON.stringify(info.payload, this.safeReplacer)}` : "";
147
+ const codePart = info.code ? ` [Code: ${info.code}]` : "";
148
+ return `${info.timestamp} [${this.serviceName}] ${info.level}${codePart}: ${msg}${idPart}${payloadPart}`;
149
+ }));
150
+ }
151
+ runWithId = (id, callback) => {
152
+ const store = new Map();
153
+ store.set("correlationId", id);
154
+ return LoggerService.storage.run(store, callback);
155
+ };
150
156
  async logToKafka(info) {
151
157
  if (!this.kafkaProducer || !this.isKafkaReady)
152
158
  return;
153
159
  try {
154
- const { id, level, message, ...rest } = info;
160
+ const { id, level, message, payload, code } = info;
155
161
  await this.kafkaProducer.send({
156
162
  topic: this.kafkaTopic,
157
163
  messages: [{
@@ -159,7 +165,8 @@ export default class LoggerService {
159
165
  service: this.serviceName,
160
166
  level,
161
167
  message,
162
- ...rest,
168
+ payload,
169
+ code,
163
170
  timestamp: new Date().toISOString(),
164
171
  id: id || null,
165
172
  env: this.#configsService.all.env
@@ -171,4 +178,11 @@ export default class LoggerService {
171
178
  this.isKafkaReady = false;
172
179
  }
173
180
  }
181
+ log(arg1, arg2, arg3, arg4) {
182
+ const isObj = typeof arg1 === 'object' && arg1 !== null && 'level' in arg1;
183
+ const { level, message, payload, code } = isObj
184
+ ? arg1
185
+ : { level: arg1, message: arg2, payload: arg3, code: arg4 };
186
+ this.winston.log(LoggerLayerEnum[level].toLowerCase(), message, { payload, code });
187
+ }
174
188
  }