zario 0.2.11 → 0.3.1
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 +10 -1
- package/dist/cjs/core/CustomLogLevel.js +2 -0
- package/dist/cjs/core/Formatter.js +75 -0
- package/dist/cjs/core/LogLevel.js +2 -0
- package/dist/cjs/core/Logger.js +234 -0
- package/dist/cjs/index.js +19 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/transports/ConsoleTransport.js +39 -0
- package/dist/cjs/transports/FileTransport.js +260 -0
- package/dist/cjs/transports/HttpTransport.js +150 -0
- package/dist/cjs/transports/Transport.js +2 -0
- package/dist/cjs/transports/index.js +20 -0
- package/dist/cjs/utils/ColorUtil.js +42 -0
- package/dist/cjs/utils/TimeUtil.js +26 -0
- package/dist/cjs/utils/Timerutil.js +22 -0
- package/dist/{core → esm/core}/CustomLogLevel.d.ts +1 -1
- package/dist/esm/core/CustomLogLevel.js +1 -0
- package/dist/{core → esm/core}/Formatter.d.ts +1 -1
- package/dist/esm/core/Formatter.js +71 -0
- package/dist/esm/core/LogLevel.js +1 -0
- package/dist/{core → esm/core}/Logger.d.ts +4 -5
- package/dist/esm/core/Logger.js +230 -0
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.js +13 -0
- package/dist/{transports → esm/transports}/ConsoleTransport.d.ts +3 -3
- package/dist/esm/transports/ConsoleTransport.js +35 -0
- package/dist/{transports → esm/transports}/FileTransport.d.ts +7 -5
- package/dist/esm/transports/FileTransport.js +223 -0
- package/dist/{transports → esm/transports}/HttpTransport.d.ts +3 -3
- package/dist/esm/transports/HttpTransport.js +113 -0
- package/dist/{transports → esm/transports}/Transport.d.ts +2 -2
- package/dist/esm/transports/Transport.js +1 -0
- package/dist/esm/transports/index.d.ts +4 -0
- package/dist/esm/transports/index.js +4 -0
- package/dist/esm/utils/ColorUtil.js +38 -0
- package/dist/esm/utils/TimeUtil.js +22 -0
- package/dist/esm/utils/Timerutil.js +18 -0
- package/package.json +19 -8
- package/dist/index.d.ts +0 -8
- package/dist/index.js +0 -3
- package/dist/index.mjs +0 -3
- package/dist/transports/index.d.ts +0 -28
- /package/dist/{core → esm/core}/LogLevel.d.ts +0 -0
- /package/dist/{utils → esm/utils}/ColorUtil.d.ts +0 -0
- /package/dist/{utils → esm/utils}/TimeUtil.d.ts +0 -0
- /package/dist/{utils → esm/utils}/Timerutil.d.ts +0 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.FileTransport = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const zlib = __importStar(require("zlib"));
|
|
40
|
+
const util_1 = require("util");
|
|
41
|
+
const compressGzip = (0, util_1.promisify)(zlib.gzip);
|
|
42
|
+
const compressDeflate = (0, util_1.promisify)(zlib.deflate);
|
|
43
|
+
class FileTransport {
|
|
44
|
+
constructor(options) {
|
|
45
|
+
// batching funct
|
|
46
|
+
this.batchQueue = [];
|
|
47
|
+
this.batchTimer = null;
|
|
48
|
+
const { path: filePath, maxSize = 10 * 1024 * 1024, maxFiles = 5, compression = "none", batchInterval = 0, // no batching
|
|
49
|
+
compressOldFiles = true, } = options;
|
|
50
|
+
this.filePath = filePath;
|
|
51
|
+
this.maxSize = maxSize;
|
|
52
|
+
this.maxFiles = maxFiles;
|
|
53
|
+
this.compression = compression;
|
|
54
|
+
this.batchInterval = batchInterval;
|
|
55
|
+
this.compressOldFiles = compressOldFiles;
|
|
56
|
+
const dir = path.dirname(this.filePath);
|
|
57
|
+
if (!fs.existsSync(dir)) {
|
|
58
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
59
|
+
}
|
|
60
|
+
if (!fs.existsSync(this.filePath)) {
|
|
61
|
+
fs.writeFileSync(this.filePath, "", "utf8");
|
|
62
|
+
}
|
|
63
|
+
// Start batching if an interval is set
|
|
64
|
+
if (batchInterval > 0) {
|
|
65
|
+
this.startBatching();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
write(data, formatter) {
|
|
69
|
+
const output = formatter.format(data);
|
|
70
|
+
const formattedOutput = output + "\n";
|
|
71
|
+
if (this.batchInterval > 0) {
|
|
72
|
+
// Queue entry if batching is enabled
|
|
73
|
+
this.batchQueue.push({
|
|
74
|
+
data: formattedOutput,
|
|
75
|
+
timestamp: new Date(),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// Write immediately when batching is disabled
|
|
80
|
+
fs.appendFileSync(this.filePath, formattedOutput);
|
|
81
|
+
if (this.shouldRotate()) {
|
|
82
|
+
this.rotateFiles();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async writeAsync(data, formatter) {
|
|
87
|
+
const formattedOutput = formatter.format(data) + "\n";
|
|
88
|
+
if (this.batchInterval > 0) {
|
|
89
|
+
this.batchQueue.push({
|
|
90
|
+
data: formattedOutput,
|
|
91
|
+
timestamp: new Date(),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
try {
|
|
96
|
+
await fs.promises.appendFile(this.filePath, formattedOutput);
|
|
97
|
+
if (this.shouldRotate()) {
|
|
98
|
+
await this.rotateFilesAsync();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
shouldRotate() {
|
|
107
|
+
if (!fs.existsSync(this.filePath))
|
|
108
|
+
return false;
|
|
109
|
+
try {
|
|
110
|
+
return fs.statSync(this.filePath).size >= this.maxSize;
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
rotateFiles() {
|
|
117
|
+
try {
|
|
118
|
+
if (!fs.existsSync(this.filePath))
|
|
119
|
+
return;
|
|
120
|
+
const currentContent = fs.readFileSync(this.filePath, "utf8");
|
|
121
|
+
this.performRotation(currentContent, fs.writeFileSync);
|
|
122
|
+
this.cleanupOldFiles();
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
console.error("Error during file rotation:", error);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async rotateFilesAsync() {
|
|
129
|
+
try {
|
|
130
|
+
if (!fs.existsSync(this.filePath))
|
|
131
|
+
return;
|
|
132
|
+
const currentContent = await fs.promises.readFile(this.filePath, "utf8");
|
|
133
|
+
await this.performRotationAsync(currentContent);
|
|
134
|
+
await this.cleanupOldFilesAsync();
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
console.error("Error during async file rotation:", error);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
performRotation(content, writeFn) {
|
|
141
|
+
let rotatedFilePath = this.getRotatedFilePath();
|
|
142
|
+
if (this.compression !== "none" && this.compressOldFiles) {
|
|
143
|
+
rotatedFilePath += `.${this.compression === "gzip" ? "gz" : "zz"}`;
|
|
144
|
+
const compressed = this.compression === "gzip" ? zlib.gzipSync(content) : zlib.deflateSync(content);
|
|
145
|
+
writeFn(rotatedFilePath, compressed);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
writeFn(rotatedFilePath, content, "utf8");
|
|
149
|
+
}
|
|
150
|
+
writeFn(this.filePath, "", "utf8");
|
|
151
|
+
}
|
|
152
|
+
async performRotationAsync(content) {
|
|
153
|
+
let rotatedFilePath = this.getRotatedFilePath();
|
|
154
|
+
if (this.compression !== "none" && this.compressOldFiles) {
|
|
155
|
+
rotatedFilePath += `.${this.compression === "gzip" ? "gz" : "zz"}`;
|
|
156
|
+
const compressed = this.compression === "gzip" ? await compressGzip(content) : await compressDeflate(content);
|
|
157
|
+
await fs.promises.writeFile(rotatedFilePath, compressed);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
await fs.promises.writeFile(rotatedFilePath, content, "utf8");
|
|
161
|
+
}
|
|
162
|
+
await fs.promises.writeFile(this.filePath, "", "utf8");
|
|
163
|
+
}
|
|
164
|
+
getRotatedFilePath() {
|
|
165
|
+
const dir = path.dirname(this.filePath);
|
|
166
|
+
return path.join(dir, `${path.basename(this.filePath)}.${Date.now()}`);
|
|
167
|
+
}
|
|
168
|
+
filterRotatedFiles(files, baseName) {
|
|
169
|
+
return files
|
|
170
|
+
.filter(f => f !== baseName && f.startsWith(baseName + "."))
|
|
171
|
+
.sort((a, b) => {
|
|
172
|
+
const getTs = (s) => parseInt(s.slice(baseName.length + 1).split(".")[0] ?? "0");
|
|
173
|
+
return getTs(b) - getTs(a);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
cleanupOldFiles() {
|
|
177
|
+
const dir = path.dirname(this.filePath);
|
|
178
|
+
const baseName = path.basename(this.filePath);
|
|
179
|
+
try {
|
|
180
|
+
const files = fs.readdirSync(dir);
|
|
181
|
+
const rotated = this.filterRotatedFiles(files, baseName);
|
|
182
|
+
for (let i = this.maxFiles; i < rotated.length; i++) {
|
|
183
|
+
const file = rotated[i];
|
|
184
|
+
if (file) {
|
|
185
|
+
try {
|
|
186
|
+
fs.unlinkSync(path.join(dir, file));
|
|
187
|
+
}
|
|
188
|
+
catch { }
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch { }
|
|
193
|
+
}
|
|
194
|
+
async cleanupOldFilesAsync() {
|
|
195
|
+
const dir = path.dirname(this.filePath);
|
|
196
|
+
const baseName = path.basename(this.filePath);
|
|
197
|
+
try {
|
|
198
|
+
const files = await fs.promises.readdir(dir);
|
|
199
|
+
const rotated = this.filterRotatedFiles(files, baseName);
|
|
200
|
+
await Promise.all(rotated.slice(this.maxFiles).map(f => fs.promises.unlink(path.join(dir, f)).catch(() => { })));
|
|
201
|
+
}
|
|
202
|
+
catch { }
|
|
203
|
+
}
|
|
204
|
+
startBatching() {
|
|
205
|
+
if (this.batchInterval > 0) {
|
|
206
|
+
this.batchTimer = setInterval(() => {
|
|
207
|
+
this.processBatch().catch((error) => {
|
|
208
|
+
console.error("Error in batch processing timer:", error);
|
|
209
|
+
});
|
|
210
|
+
}, this.batchInterval);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
async processBatch() {
|
|
214
|
+
if (this.batchQueue.length === 0) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
// Atomically capture and clear queue
|
|
218
|
+
const currentBatch = this.batchQueue;
|
|
219
|
+
this.batchQueue = [];
|
|
220
|
+
// Combine queued entries into one batch
|
|
221
|
+
const batchContent = currentBatch.map((entry) => entry.data).join("");
|
|
222
|
+
try {
|
|
223
|
+
await new Promise((resolve, reject) => {
|
|
224
|
+
fs.appendFile(this.filePath, batchContent, (err) => {
|
|
225
|
+
if (err) {
|
|
226
|
+
reject(err);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
resolve();
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
// Rotate if needed after writing
|
|
233
|
+
if (this.shouldRotate()) {
|
|
234
|
+
await this.rotateFilesAsync();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
console.error("Error processing log batch:", error);
|
|
239
|
+
// On error, restore entries for retry (prepend to preserve order)
|
|
240
|
+
this.batchQueue = [...currentBatch, ...this.batchQueue];
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// Clean up resources when the transport is disposed
|
|
244
|
+
async destroy() {
|
|
245
|
+
if (this.batchTimer) {
|
|
246
|
+
clearInterval(this.batchTimer);
|
|
247
|
+
this.batchTimer = null;
|
|
248
|
+
}
|
|
249
|
+
// Flush remaining queued entries
|
|
250
|
+
if (this.batchQueue.length > 0) {
|
|
251
|
+
try {
|
|
252
|
+
await this.processBatch();
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
console.error("Error processing final batch:", error);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
exports.FileTransport = FileTransport;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.HttpTransport = void 0;
|
|
37
|
+
const http = __importStar(require("http"));
|
|
38
|
+
const https = __importStar(require("https"));
|
|
39
|
+
const url = __importStar(require("url"));
|
|
40
|
+
class HttpTransport {
|
|
41
|
+
constructor(options) {
|
|
42
|
+
const { url, method = 'POST', headers = {}, timeout = 5000, retries = 3 // defaults
|
|
43
|
+
} = options;
|
|
44
|
+
if (!url) {
|
|
45
|
+
throw new Error('HttpTransport requires a URL option');
|
|
46
|
+
}
|
|
47
|
+
this.url = url;
|
|
48
|
+
this.method = method.toUpperCase();
|
|
49
|
+
this.headers = { ...headers };
|
|
50
|
+
this.timeout = timeout;
|
|
51
|
+
this.retries = retries;
|
|
52
|
+
// Set default Content-Type if not provided
|
|
53
|
+
if (!this.headers['Content-Type'] && !this.headers['content-type']) {
|
|
54
|
+
this.headers['Content-Type'] = 'application/json';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
write(data, formatter) {
|
|
58
|
+
// Format the data as JSON for HTTP transport
|
|
59
|
+
const logObject = this.parseFormattedData(data);
|
|
60
|
+
const body = JSON.stringify(logObject);
|
|
61
|
+
setImmediate(() => {
|
|
62
|
+
this.sendHttpRequestWithRetry(body, 0)
|
|
63
|
+
.catch((error) => {
|
|
64
|
+
console.error('HttpTransport error (sync mode):', error.message);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
async writeAsync(data, formatter) {
|
|
69
|
+
// json formating for HttpTransport
|
|
70
|
+
const logObject = this.parseFormattedData(data);
|
|
71
|
+
const body = JSON.stringify(logObject);
|
|
72
|
+
await this.sendHttpRequestWithRetry(body, this.retries);
|
|
73
|
+
}
|
|
74
|
+
parseFormattedData(originalData) {
|
|
75
|
+
// structured log overide original params
|
|
76
|
+
return {
|
|
77
|
+
level: originalData.level,
|
|
78
|
+
message: originalData.message,
|
|
79
|
+
timestamp: originalData.timestamp.toISOString(),
|
|
80
|
+
...(originalData.prefix && { prefix: originalData.prefix }),
|
|
81
|
+
...(originalData.metadata && { metadata: originalData.metadata })
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async sendHttpRequestWithRetry(body, maxRetries) {
|
|
85
|
+
let lastError = null;
|
|
86
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
87
|
+
try {
|
|
88
|
+
await this.sendHttpRequest(body);
|
|
89
|
+
return; // success then exit
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
lastError = error;
|
|
93
|
+
// stop if last attempt
|
|
94
|
+
if (attempt === maxRetries) {
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
// timer wait before continue
|
|
98
|
+
await this.delay(Math.pow(2, attempt) * 1000);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (lastError) {
|
|
102
|
+
throw lastError;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
sendHttpRequest(body) {
|
|
106
|
+
return new Promise((resolve, reject) => {
|
|
107
|
+
const parsedUrl = new url.URL(this.url);
|
|
108
|
+
const isHttps = parsedUrl.protocol === 'https:';
|
|
109
|
+
const client = isHttps ? https : http;
|
|
110
|
+
const requestOptions = {
|
|
111
|
+
hostname: parsedUrl.hostname,
|
|
112
|
+
port: parsedUrl.port,
|
|
113
|
+
path: parsedUrl.pathname + parsedUrl.search,
|
|
114
|
+
method: this.method,
|
|
115
|
+
headers: {
|
|
116
|
+
...this.headers,
|
|
117
|
+
'Content-Length': Buffer.byteLength(body, 'utf8'),
|
|
118
|
+
},
|
|
119
|
+
timeout: this.timeout,
|
|
120
|
+
};
|
|
121
|
+
const req = client.request(requestOptions, (res) => {
|
|
122
|
+
let responseData = '';
|
|
123
|
+
res.on('data', (chunk) => {
|
|
124
|
+
responseData += chunk;
|
|
125
|
+
});
|
|
126
|
+
res.on('end', () => {
|
|
127
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
128
|
+
resolve();
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
reject(new Error(`HTTP request failed with status ${res.statusCode}: ${responseData}`));
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
req.on('error', (error) => {
|
|
136
|
+
reject(error);
|
|
137
|
+
});
|
|
138
|
+
req.on('timeout', () => {
|
|
139
|
+
req.destroy();
|
|
140
|
+
reject(new Error('Request timeout'));
|
|
141
|
+
});
|
|
142
|
+
req.write(body);
|
|
143
|
+
req.end();
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
delay(ms) {
|
|
147
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
exports.HttpTransport = HttpTransport;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./Transport.js"), exports);
|
|
18
|
+
__exportStar(require("./ConsoleTransport.js"), exports);
|
|
19
|
+
__exportStar(require("./FileTransport.js"), exports);
|
|
20
|
+
__exportStar(require("./HttpTransport.js"), exports);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ColorUtil = void 0;
|
|
4
|
+
class ColorUtil {
|
|
5
|
+
static colorize(text, color) {
|
|
6
|
+
const supportsColor = process.env.FORCE_COLOR !== "0" &&
|
|
7
|
+
(process.stdout.isTTY || process.env.FORCE_COLOR === "1");
|
|
8
|
+
if (!supportsColor) {
|
|
9
|
+
return text;
|
|
10
|
+
}
|
|
11
|
+
const colorCode = ColorUtil.ANSI_COLORS[color] || ColorUtil.ANSI_COLORS.reset;
|
|
12
|
+
return `${colorCode}${text}${ColorUtil.ANSI_COLORS.reset}`;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.ColorUtil = ColorUtil;
|
|
16
|
+
// ANSI color codes
|
|
17
|
+
ColorUtil.ANSI_COLORS = {
|
|
18
|
+
// Standard colors
|
|
19
|
+
black: "\x1b[30m",
|
|
20
|
+
red: "\x1b[31m",
|
|
21
|
+
green: "\x1b[32m",
|
|
22
|
+
yellow: "\x1b[33m",
|
|
23
|
+
blue: "\x1b[34m",
|
|
24
|
+
magenta: "\x1b[35m",
|
|
25
|
+
cyan: "\x1b[36m",
|
|
26
|
+
white: "\x1b[37m",
|
|
27
|
+
// Bright colors
|
|
28
|
+
brightRed: "\x1b[91m",
|
|
29
|
+
brightGreen: "\x1b[92m",
|
|
30
|
+
brightYellow: "\x1b[93m",
|
|
31
|
+
brightBlue: "\x1b[94m",
|
|
32
|
+
brightMagenta: "\x1b[95m",
|
|
33
|
+
brightCyan: "\x1b[96m",
|
|
34
|
+
brightWhite: "\x1b[97m",
|
|
35
|
+
// Default log level colors
|
|
36
|
+
info: "\x1b[32m",
|
|
37
|
+
warn: "\x1b[33m",
|
|
38
|
+
error: "\x1b[31m",
|
|
39
|
+
debug: "\x1b[36m",
|
|
40
|
+
boring: "\x1b[37m",
|
|
41
|
+
reset: "\x1b[0m",
|
|
42
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TimeUtil = void 0;
|
|
4
|
+
class TimeUtil {
|
|
5
|
+
// util class for date formating
|
|
6
|
+
static format(date, format) {
|
|
7
|
+
if (format === "ISO")
|
|
8
|
+
return date.toISOString();
|
|
9
|
+
if (format === "UTC")
|
|
10
|
+
return date.toUTCString();
|
|
11
|
+
if (format === "LOCAL")
|
|
12
|
+
return date.toLocaleString();
|
|
13
|
+
const pad = (n, width = 2) => n.toString().padStart(width, "0");
|
|
14
|
+
const tokens = {
|
|
15
|
+
YYYY: pad(date.getFullYear(), 4),
|
|
16
|
+
MM: pad(date.getMonth() + 1),
|
|
17
|
+
DD: pad(date.getDate()),
|
|
18
|
+
HH: pad(date.getHours()),
|
|
19
|
+
mm: pad(date.getMinutes()),
|
|
20
|
+
ss: pad(date.getSeconds()),
|
|
21
|
+
SSS: pad(date.getMilliseconds(), 3),
|
|
22
|
+
};
|
|
23
|
+
return format.replace(/YYYY|MM|DD|HH|mm|ss|SSS/g, (match) => tokens[match] || match);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.TimeUtil = TimeUtil;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Timer = void 0;
|
|
4
|
+
class Timer {
|
|
5
|
+
constructor(name, logFn) {
|
|
6
|
+
this.hasEnded = false;
|
|
7
|
+
this.name = name;
|
|
8
|
+
this.logFn = logFn;
|
|
9
|
+
this.startTime = Date.now();
|
|
10
|
+
}
|
|
11
|
+
end() {
|
|
12
|
+
// If already ended, do nothing (idempotent)
|
|
13
|
+
if (this.hasEnded) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const endTime = Date.now();
|
|
17
|
+
const duration = endTime - this.startTime;
|
|
18
|
+
this.logFn(`${this.name} took ${duration}ms`);
|
|
19
|
+
this.hasEnded = true;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.Timer = Timer;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { TimeUtil } from "../utils/TimeUtil.js";
|
|
2
|
+
import { ColorUtil } from "../utils/ColorUtil.js";
|
|
3
|
+
export class Formatter {
|
|
4
|
+
constructor(options = {}) {
|
|
5
|
+
const { colorize = true, json = false, timestampFormat = "YYYY-MM-DD HH:mm:ss", timestamp = false, customColors = {}, } = options;
|
|
6
|
+
this.colorize = colorize;
|
|
7
|
+
this.json = json;
|
|
8
|
+
this.timestampFormat = timestampFormat;
|
|
9
|
+
this.timestamp = timestamp;
|
|
10
|
+
this.customColors = customColors;
|
|
11
|
+
}
|
|
12
|
+
format(data) {
|
|
13
|
+
if (this.json) {
|
|
14
|
+
return this.formatAsJson(data);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
return this.formatAsText(data);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
formatAsJson(data) {
|
|
21
|
+
const formattedData = {
|
|
22
|
+
...data.metadata, // Spread first so core fields can override
|
|
23
|
+
level: data.level,
|
|
24
|
+
message: data.message,
|
|
25
|
+
};
|
|
26
|
+
if (this.timestamp) {
|
|
27
|
+
formattedData.timestamp = data.timestamp.toISOString();
|
|
28
|
+
}
|
|
29
|
+
if (data.prefix) {
|
|
30
|
+
formattedData.prefix = data.prefix;
|
|
31
|
+
}
|
|
32
|
+
return JSON.stringify(formattedData);
|
|
33
|
+
}
|
|
34
|
+
formatAsText(data) {
|
|
35
|
+
let output = "";
|
|
36
|
+
if (this.timestamp) {
|
|
37
|
+
output += `[${TimeUtil.format(data.timestamp, this.timestampFormat)}] `;
|
|
38
|
+
}
|
|
39
|
+
if (data.prefix) {
|
|
40
|
+
output += `${data.prefix} `;
|
|
41
|
+
}
|
|
42
|
+
let level = data.level.toUpperCase();
|
|
43
|
+
if (this.colorize) {
|
|
44
|
+
const color = this.customColors[data.level] || data.level;
|
|
45
|
+
level = ColorUtil.colorize(level, color);
|
|
46
|
+
}
|
|
47
|
+
output += `[${level}] ${data.message}`;
|
|
48
|
+
if (data.metadata) {
|
|
49
|
+
output += ` ${JSON.stringify(data.metadata)}`;
|
|
50
|
+
}
|
|
51
|
+
return output;
|
|
52
|
+
}
|
|
53
|
+
setJson(json) {
|
|
54
|
+
this.json = json;
|
|
55
|
+
}
|
|
56
|
+
isColorized() {
|
|
57
|
+
return this.colorize;
|
|
58
|
+
}
|
|
59
|
+
isJson() {
|
|
60
|
+
return this.json;
|
|
61
|
+
}
|
|
62
|
+
getTimestampFormat() {
|
|
63
|
+
return this.timestampFormat;
|
|
64
|
+
}
|
|
65
|
+
hasTimestamp() {
|
|
66
|
+
return this.timestamp;
|
|
67
|
+
}
|
|
68
|
+
getCustomColors() {
|
|
69
|
+
return { ...this.customColors };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { LogLevel } from "./LogLevel";
|
|
2
|
-
import { Transport } from "../transports";
|
|
3
|
-
import { TransportConfig } from "../types";
|
|
1
|
+
import { LogLevel } from "./LogLevel.js";
|
|
2
|
+
import { Transport } from "../transports/Transport.js";
|
|
3
|
+
import { TransportConfig } from "../types/index.js";
|
|
4
4
|
export interface LoggerOptions {
|
|
5
5
|
level?: LogLevel;
|
|
6
6
|
colorize?: boolean;
|
|
@@ -28,6 +28,7 @@ export declare class Logger {
|
|
|
28
28
|
private asyncMode;
|
|
29
29
|
private customLevels;
|
|
30
30
|
private static _global;
|
|
31
|
+
static defaultTransportsFactory: ((isProd: boolean) => TransportConfig[]) | null;
|
|
31
32
|
private static readonly LEVEL_PRIORITIES;
|
|
32
33
|
prefix: string;
|
|
33
34
|
timestamp: boolean;
|
|
@@ -40,12 +41,10 @@ export declare class Logger {
|
|
|
40
41
|
private getDefaultTransports;
|
|
41
42
|
private getDefaultAsyncMode;
|
|
42
43
|
private initTransports;
|
|
43
|
-
private isLegacyTransportOptions;
|
|
44
44
|
private isTransport;
|
|
45
45
|
private shouldLog;
|
|
46
46
|
private getLevelPriority;
|
|
47
47
|
private log;
|
|
48
|
-
private logAsyncDirect;
|
|
49
48
|
debug(message: string, metadata?: Record<string, any>): void;
|
|
50
49
|
info(message: string, metadata?: Record<string, any>): void;
|
|
51
50
|
warn(message: string, metadata?: Record<string, any>): void;
|