@unchainedshop/logger 5.0.0-alpha.7 โ 5.0.0-alpha.9
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 +4 -1
- package/benchmarks/README.md +0 -11
- package/benchmarks/benchmark.ts +0 -273
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unchainedshop/logger",
|
|
3
3
|
"description": "High-performance logging package for the Unchained Engine",
|
|
4
|
-
"version": "5.0.0-alpha.
|
|
4
|
+
"version": "5.0.0-alpha.9",
|
|
5
|
+
"files": [
|
|
6
|
+
"lib"
|
|
7
|
+
],
|
|
5
8
|
"main": "lib/logger-index.js",
|
|
6
9
|
"types": "lib/logger-index.d.ts",
|
|
7
10
|
"type": "module",
|
package/benchmarks/README.md
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# Logger Performance Benchmarks
|
|
2
|
-
|
|
3
|
-
Run from this package with `npm run benchmark`, or from the repository root:
|
|
4
|
-
|
|
5
|
-
```bash
|
|
6
|
-
npm run benchmark --workspace @unchainedshop/logger
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
The benchmark measures logger creation, human-readable and JSON logging, complex object formatting, enabled/disabled debug logging, and DEBUG pattern matching. It prints operations per second and elapsed times for the current runtime.
|
|
10
|
-
|
|
11
|
-
Console output is suppressed during measurements, so results measure logger processing rather than terminal or log-collector throughput. Record the Node.js version and hardware when comparing runs.
|
package/benchmarks/benchmark.ts
DELETED
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
import { performance } from 'node:perf_hooks';
|
|
2
|
-
import { createLogger, resetLoggerInitialization } from '../src/createLogger.ts';
|
|
3
|
-
|
|
4
|
-
interface BenchmarkResult {
|
|
5
|
-
name: string;
|
|
6
|
-
totalTime: number;
|
|
7
|
-
operations: number;
|
|
8
|
-
opsPerSecond: number;
|
|
9
|
-
avgTimeMs: number;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
class LoggerBenchmark {
|
|
13
|
-
private originalConsole = {
|
|
14
|
-
log: console.log,
|
|
15
|
-
info: console.info,
|
|
16
|
-
warn: console.warn,
|
|
17
|
-
error: console.error,
|
|
18
|
-
debug: console.debug,
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
private suppressConsole() {
|
|
22
|
-
const noop = () => {
|
|
23
|
-
/* intentionally empty */
|
|
24
|
-
};
|
|
25
|
-
console.log = noop;
|
|
26
|
-
console.info = noop;
|
|
27
|
-
console.warn = noop;
|
|
28
|
-
console.error = noop;
|
|
29
|
-
console.debug = noop;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
private restoreConsole() {
|
|
33
|
-
Object.assign(console, this.originalConsole);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
private benchmark(name: string, iterations: number, fn: () => void): BenchmarkResult {
|
|
37
|
-
// Warm-up phase
|
|
38
|
-
for (let i = 0; i < Math.min(100, iterations / 10); i++) {
|
|
39
|
-
fn();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Actual benchmark
|
|
43
|
-
const start = performance.now();
|
|
44
|
-
for (let i = 0; i < iterations; i++) {
|
|
45
|
-
fn();
|
|
46
|
-
}
|
|
47
|
-
const totalTime = performance.now() - start;
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
name,
|
|
51
|
-
totalTime,
|
|
52
|
-
operations: iterations,
|
|
53
|
-
opsPerSecond: (iterations / totalTime) * 1000,
|
|
54
|
-
avgTimeMs: totalTime / iterations,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async run() {
|
|
59
|
-
this.restoreConsole();
|
|
60
|
-
console.log('๐ Logger Performance Benchmark\n');
|
|
61
|
-
console.log('Running benchmarks...\n');
|
|
62
|
-
|
|
63
|
-
const results: BenchmarkResult[] = [];
|
|
64
|
-
|
|
65
|
-
// Test 1: Logger creation performance
|
|
66
|
-
this.suppressConsole();
|
|
67
|
-
resetLoggerInitialization();
|
|
68
|
-
delete process.env.UNCHAINED_LOG_FORMAT;
|
|
69
|
-
delete process.env.DEBUG;
|
|
70
|
-
delete process.env.LOG_LEVEL;
|
|
71
|
-
|
|
72
|
-
results.push(
|
|
73
|
-
this.benchmark('Logger creation (default format)', 1000, () => {
|
|
74
|
-
createLogger(`module-${Math.random()}`);
|
|
75
|
-
}),
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
// Test 2: Logger creation with JSON format
|
|
79
|
-
resetLoggerInitialization();
|
|
80
|
-
process.env.UNCHAINED_LOG_FORMAT = 'json';
|
|
81
|
-
|
|
82
|
-
results.push(
|
|
83
|
-
this.benchmark('Logger creation (JSON format)', 1000, () => {
|
|
84
|
-
createLogger(`module-json-${Math.random()}`);
|
|
85
|
-
}),
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
// Test 3: Logging performance - default format
|
|
89
|
-
resetLoggerInitialization();
|
|
90
|
-
delete process.env.UNCHAINED_LOG_FORMAT;
|
|
91
|
-
const defaultLogger = createLogger('benchmark');
|
|
92
|
-
|
|
93
|
-
results.push(
|
|
94
|
-
this.benchmark('Log info (default format)', 100000, () => {
|
|
95
|
-
defaultLogger.info('Test message');
|
|
96
|
-
}),
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
// Test 4: Logging performance - JSON format
|
|
100
|
-
resetLoggerInitialization();
|
|
101
|
-
process.env.UNCHAINED_LOG_FORMAT = 'json';
|
|
102
|
-
const jsonLogger = createLogger('benchmark-json');
|
|
103
|
-
|
|
104
|
-
results.push(
|
|
105
|
-
this.benchmark('Log info (JSON format)', 100000, () => {
|
|
106
|
-
jsonLogger.info('Test message', { id: 123 });
|
|
107
|
-
}),
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
// Test 5: Complex object logging
|
|
111
|
-
const complexObject = {
|
|
112
|
-
user: { id: 'user123', name: 'John Doe', roles: ['admin', 'user'] },
|
|
113
|
-
action: 'purchase',
|
|
114
|
-
items: [
|
|
115
|
-
{ id: 'item1', name: 'Product A', price: 99.99, quantity: 2 },
|
|
116
|
-
{ id: 'item2', name: 'Product B', price: 49.99, quantity: 1 },
|
|
117
|
-
],
|
|
118
|
-
metadata: {
|
|
119
|
-
timestamp: new Date().toISOString(),
|
|
120
|
-
source: 'web',
|
|
121
|
-
version: '1.0.0',
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
results.push(
|
|
126
|
-
this.benchmark('Log complex object (JSON)', 10000, () => {
|
|
127
|
-
jsonLogger.info('Complex operation', complexObject);
|
|
128
|
-
}),
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
// Test 6: Debug logging when enabled
|
|
132
|
-
resetLoggerInitialization();
|
|
133
|
-
delete process.env.UNCHAINED_LOG_FORMAT;
|
|
134
|
-
process.env.DEBUG = 'benchmark-debug';
|
|
135
|
-
const debugEnabledLogger = createLogger('benchmark-debug');
|
|
136
|
-
|
|
137
|
-
results.push(
|
|
138
|
-
this.benchmark('Debug log (enabled)', 100000, () => {
|
|
139
|
-
debugEnabledLogger.debug('Debug message');
|
|
140
|
-
}),
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
// Test 7: Debug logging when disabled
|
|
144
|
-
resetLoggerInitialization();
|
|
145
|
-
process.env.DEBUG = 'other-module';
|
|
146
|
-
const debugDisabledLogger = createLogger('benchmark-no-debug');
|
|
147
|
-
|
|
148
|
-
results.push(
|
|
149
|
-
this.benchmark('Debug log (disabled)', 100000, () => {
|
|
150
|
-
debugDisabledLogger.debug('Debug message');
|
|
151
|
-
}),
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
// Test 8: Pattern matching performance
|
|
155
|
-
resetLoggerInitialization();
|
|
156
|
-
process.env.DEBUG = 'app:*,!app:excluded,special-*,test:module:*';
|
|
157
|
-
const testModules = [
|
|
158
|
-
'app:users',
|
|
159
|
-
'app:excluded',
|
|
160
|
-
'special-feature',
|
|
161
|
-
'test:module:sub',
|
|
162
|
-
'other:module',
|
|
163
|
-
];
|
|
164
|
-
|
|
165
|
-
results.push(
|
|
166
|
-
this.benchmark('Pattern matching (createLogger)', 5000, () => {
|
|
167
|
-
const module = testModules[Math.floor(Math.random() * testModules.length)];
|
|
168
|
-
createLogger(module);
|
|
169
|
-
}),
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
this.restoreConsole();
|
|
173
|
-
this.printResults(results);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
private printResults(results: BenchmarkResult[]) {
|
|
177
|
-
console.log('\n๐ Benchmark Results:\n');
|
|
178
|
-
|
|
179
|
-
// Header
|
|
180
|
-
const cols = {
|
|
181
|
-
name: 'Test Name',
|
|
182
|
-
ops: 'Ops/sec',
|
|
183
|
-
avgTime: 'Avg Time',
|
|
184
|
-
total: 'Total Time',
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
const widths = {
|
|
188
|
-
name: Math.max(cols.name.length, ...results.map((r) => r.name.length)),
|
|
189
|
-
ops: 12,
|
|
190
|
-
avgTime: 12,
|
|
191
|
-
total: 12,
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
// Print header
|
|
195
|
-
console.log(
|
|
196
|
-
`${cols.name.padEnd(widths.name)} | ${cols.ops.padStart(widths.ops)} | ${cols.avgTime.padStart(
|
|
197
|
-
widths.avgTime,
|
|
198
|
-
)} | ${cols.total.padStart(widths.total)}`,
|
|
199
|
-
);
|
|
200
|
-
console.log(
|
|
201
|
-
`${'-'.repeat(widths.name)}-|-${'-'.repeat(widths.ops)}-|-${'-'.repeat(widths.avgTime)}-|-${'-'.repeat(widths.total)}`,
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
// Print results
|
|
205
|
-
for (const result of results) {
|
|
206
|
-
const opsPerSec = this.formatNumber(result.opsPerSecond);
|
|
207
|
-
const avgTime = this.formatTime(result.avgTimeMs);
|
|
208
|
-
const totalTime = `${result.totalTime.toFixed(2)} ms`;
|
|
209
|
-
|
|
210
|
-
console.log(
|
|
211
|
-
`${result.name.padEnd(widths.name)} | ${opsPerSec.padStart(widths.ops)} | ${avgTime.padStart(
|
|
212
|
-
widths.avgTime,
|
|
213
|
-
)} | ${totalTime.padStart(widths.total)}`,
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Performance insights
|
|
218
|
-
console.log('\n๐ก Performance Insights:\n');
|
|
219
|
-
|
|
220
|
-
// Compare format performance
|
|
221
|
-
const defaultLog = results.find((r) => r.name === 'Log info (default format)');
|
|
222
|
-
const jsonLog = results.find((r) => r.name === 'Log info (JSON format)');
|
|
223
|
-
if (defaultLog && jsonLog) {
|
|
224
|
-
const diff = ((jsonLog.avgTimeMs - defaultLog.avgTimeMs) / defaultLog.avgTimeMs) * 100;
|
|
225
|
-
console.log(
|
|
226
|
-
`โข JSON format logging is ${Math.abs(diff).toFixed(1)}% ${diff > 0 ? 'slower' : 'faster'} than default format`,
|
|
227
|
-
);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// Compare debug enabled vs disabled
|
|
231
|
-
const debugEnabled = results.find((r) => r.name === 'Debug log (enabled)');
|
|
232
|
-
const debugDisabled = results.find((r) => r.name === 'Debug log (disabled)');
|
|
233
|
-
if (debugEnabled && debugDisabled) {
|
|
234
|
-
const speedup = debugEnabled.avgTimeMs / debugDisabled.avgTimeMs;
|
|
235
|
-
console.log(
|
|
236
|
-
`โข Debug logging when disabled is ${speedup.toFixed(1)}x faster (skips log processing entirely)`,
|
|
237
|
-
);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// Find fastest and slowest
|
|
241
|
-
const sorted = [...results].sort((a, b) => b.opsPerSecond - a.opsPerSecond);
|
|
242
|
-
console.log(
|
|
243
|
-
`โข Fastest operation: ${sorted[0].name} (${this.formatNumber(sorted[0].opsPerSecond)} ops/s)`,
|
|
244
|
-
);
|
|
245
|
-
console.log(
|
|
246
|
-
`โข Slowest operation: ${sorted[sorted.length - 1].name} (${this.formatNumber(
|
|
247
|
-
sorted[sorted.length - 1].opsPerSecond,
|
|
248
|
-
)} ops/s)`,
|
|
249
|
-
);
|
|
250
|
-
|
|
251
|
-
// Memory note
|
|
252
|
-
console.log(
|
|
253
|
-
`\n๐ Note: These benchmarks measure execution speed. Memory usage and garbage collection`,
|
|
254
|
-
);
|
|
255
|
-
console.log(` impact are not measured but may be important factors in production environments.`);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
private formatNumber(num: number): string {
|
|
259
|
-
if (num >= 1000000) return `${(num / 1000000).toFixed(2)}M`;
|
|
260
|
-
if (num >= 1000) return `${(num / 1000).toFixed(2)}K`;
|
|
261
|
-
return num.toFixed(0);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
private formatTime(ms: number): string {
|
|
265
|
-
if (ms < 0.001) return `${(ms * 1000).toFixed(2)} ยตs`;
|
|
266
|
-
if (ms < 1) return `${ms.toFixed(3)} ms`;
|
|
267
|
-
return `${ms.toFixed(2)} ms`;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// Run benchmark
|
|
272
|
-
const benchmark = new LoggerBenchmark();
|
|
273
|
-
benchmark.run().catch(console.error);
|