@hamak/logging 0.5.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 +252 -0
- package/dist/api/index.d.ts +12 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +14 -0
- package/dist/api/interfaces/index.d.ts +4 -0
- package/dist/api/interfaces/index.d.ts.map +1 -0
- package/dist/api/interfaces/index.js +3 -0
- package/dist/api/interfaces/logger.d.ts +105 -0
- package/dist/api/interfaces/logger.d.ts.map +1 -0
- package/dist/api/interfaces/logger.js +1 -0
- package/dist/api/interfaces/manager.d.ts +120 -0
- package/dist/api/interfaces/manager.d.ts.map +1 -0
- package/dist/api/interfaces/manager.js +1 -0
- package/dist/api/interfaces/transport.d.ts +97 -0
- package/dist/api/interfaces/transport.d.ts.map +1 -0
- package/dist/api/interfaces/transport.js +1 -0
- package/dist/api/tokens/index.d.ts +2 -0
- package/dist/api/tokens/index.d.ts.map +1 -0
- package/dist/api/tokens/index.js +1 -0
- package/dist/api/tokens/service-tokens.d.ts +51 -0
- package/dist/api/tokens/service-tokens.d.ts.map +1 -0
- package/dist/api/tokens/service-tokens.js +42 -0
- package/dist/api/types/index.d.ts +3 -0
- package/dist/api/types/index.d.ts.map +1 -0
- package/dist/api/types/index.js +2 -0
- package/dist/api/types/log-config.d.ts +72 -0
- package/dist/api/types/log-config.d.ts.map +1 -0
- package/dist/api/types/log-config.js +1 -0
- package/dist/api/types/log-entry.d.ts +64 -0
- package/dist/api/types/log-entry.d.ts.map +1 -0
- package/dist/api/types/log-entry.js +12 -0
- package/dist/impl/core/context-logger.d.ts +26 -0
- package/dist/impl/core/context-logger.d.ts.map +1 -0
- package/dist/impl/core/context-logger.js +102 -0
- package/dist/impl/core/index.d.ts +3 -0
- package/dist/impl/core/index.d.ts.map +1 -0
- package/dist/impl/core/index.js +2 -0
- package/dist/impl/core/log-manager.d.ts +41 -0
- package/dist/impl/core/log-manager.d.ts.map +1 -0
- package/dist/impl/core/log-manager.js +278 -0
- package/dist/impl/formatters/dev-formatter.d.ts +20 -0
- package/dist/impl/formatters/dev-formatter.d.ts.map +1 -0
- package/dist/impl/formatters/dev-formatter.js +145 -0
- package/dist/impl/formatters/index.d.ts +3 -0
- package/dist/impl/formatters/index.d.ts.map +1 -0
- package/dist/impl/formatters/index.js +2 -0
- package/dist/impl/formatters/json-formatter.d.ts +24 -0
- package/dist/impl/formatters/json-formatter.d.ts.map +1 -0
- package/dist/impl/formatters/json-formatter.js +70 -0
- package/dist/impl/index.d.ts +16 -0
- package/dist/impl/index.d.ts.map +1 -0
- package/dist/impl/index.js +19 -0
- package/dist/impl/plugin/index.d.ts +2 -0
- package/dist/impl/plugin/index.d.ts.map +1 -0
- package/dist/impl/plugin/index.js +1 -0
- package/dist/impl/plugin/logging-plugin-factory.d.ts +37 -0
- package/dist/impl/plugin/logging-plugin-factory.d.ts.map +1 -0
- package/dist/impl/plugin/logging-plugin-factory.js +112 -0
- package/dist/impl/transports/console-transport.d.ts +16 -0
- package/dist/impl/transports/console-transport.d.ts.map +1 -0
- package/dist/impl/transports/console-transport.js +55 -0
- package/dist/impl/transports/index.d.ts +2 -0
- package/dist/impl/transports/index.d.ts.map +1 -0
- package/dist/impl/transports/index.js +1 -0
- package/dist/impl/utils/console-interceptor.d.ts +36 -0
- package/dist/impl/utils/console-interceptor.d.ts.map +1 -0
- package/dist/impl/utils/console-interceptor.js +121 -0
- package/dist/impl/utils/event-emitter.d.ts +11 -0
- package/dist/impl/utils/event-emitter.d.ts.map +1 -0
- package/dist/impl/utils/event-emitter.js +44 -0
- package/dist/impl/utils/index.d.ts +3 -0
- package/dist/impl/utils/index.d.ts.map +1 -0
- package/dist/impl/utils/index.js +2 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/spi/formatter/formatter-provider.d.ts +67 -0
- package/dist/spi/formatter/formatter-provider.d.ts.map +1 -0
- package/dist/spi/formatter/formatter-provider.js +1 -0
- package/dist/spi/formatter/index.d.ts +2 -0
- package/dist/spi/formatter/index.d.ts.map +1 -0
- package/dist/spi/formatter/index.js +1 -0
- package/dist/spi/index.d.ts +12 -0
- package/dist/spi/index.d.ts.map +1 -0
- package/dist/spi/index.js +12 -0
- package/dist/spi/transport/index.d.ts +2 -0
- package/dist/spi/transport/index.d.ts.map +1 -0
- package/dist/spi/transport/index.js +1 -0
- package/dist/spi/transport/transport-provider.d.ts +89 -0
- package/dist/spi/transport/transport-provider.d.ts.map +1 -0
- package/dist/spi/transport/transport-provider.js +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { ContextLogger } from './context-logger';
|
|
2
|
+
import { EventEmitter } from '../utils/event-emitter';
|
|
3
|
+
/**
|
|
4
|
+
* Central log manager implementation
|
|
5
|
+
*
|
|
6
|
+
* Manages transports, creates loggers, and dispatches log entries.
|
|
7
|
+
*/
|
|
8
|
+
export class LogManager {
|
|
9
|
+
constructor(config = {}) {
|
|
10
|
+
Object.defineProperty(this, "transports", {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
writable: true,
|
|
14
|
+
value: new Map()
|
|
15
|
+
});
|
|
16
|
+
Object.defineProperty(this, "transportConfigs", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true,
|
|
20
|
+
value: new Map()
|
|
21
|
+
});
|
|
22
|
+
Object.defineProperty(this, "loggers", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
writable: true,
|
|
26
|
+
value: new Map()
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(this, "buffer", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
configurable: true,
|
|
31
|
+
writable: true,
|
|
32
|
+
value: []
|
|
33
|
+
});
|
|
34
|
+
Object.defineProperty(this, "config", {
|
|
35
|
+
enumerable: true,
|
|
36
|
+
configurable: true,
|
|
37
|
+
writable: true,
|
|
38
|
+
value: void 0
|
|
39
|
+
});
|
|
40
|
+
Object.defineProperty(this, "eventEmitter", {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
configurable: true,
|
|
43
|
+
writable: true,
|
|
44
|
+
value: new EventEmitter()
|
|
45
|
+
});
|
|
46
|
+
Object.defineProperty(this, "flushTimer", {
|
|
47
|
+
enumerable: true,
|
|
48
|
+
configurable: true,
|
|
49
|
+
writable: true,
|
|
50
|
+
value: void 0
|
|
51
|
+
});
|
|
52
|
+
this.config = {
|
|
53
|
+
globalLevel: config.globalLevel ?? 2, // LogLevel.INFO
|
|
54
|
+
bufferSize: config.bufferSize ?? 1000,
|
|
55
|
+
flushInterval: config.flushInterval ?? 5000,
|
|
56
|
+
defaultTransports: config.defaultTransports ?? [],
|
|
57
|
+
pluginLevels: config.pluginLevels ?? {},
|
|
58
|
+
moduleLevels: config.moduleLevels ?? {},
|
|
59
|
+
};
|
|
60
|
+
if (this.config.flushInterval > 0) {
|
|
61
|
+
this.startFlushTimer();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
registerTransport(transport, config) {
|
|
65
|
+
this.transports.set(transport.id, transport);
|
|
66
|
+
if (config) {
|
|
67
|
+
this.transportConfigs.set(transport.id, {
|
|
68
|
+
enabled: true,
|
|
69
|
+
...config,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
this.transportConfigs.set(transport.id, {
|
|
74
|
+
id: transport.id,
|
|
75
|
+
enabled: true,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
unregisterTransport(id) {
|
|
80
|
+
const transport = this.transports.get(id);
|
|
81
|
+
if (transport && transport.close) {
|
|
82
|
+
transport.close().catch((error) => {
|
|
83
|
+
this.handleTransportError(transport, error);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
this.transports.delete(id);
|
|
87
|
+
this.transportConfigs.delete(id);
|
|
88
|
+
}
|
|
89
|
+
getTransport(id) {
|
|
90
|
+
return this.transports.get(id);
|
|
91
|
+
}
|
|
92
|
+
listTransports() {
|
|
93
|
+
return Array.from(this.transports.values());
|
|
94
|
+
}
|
|
95
|
+
createLogger(context) {
|
|
96
|
+
const level = this.resolveLevel(context);
|
|
97
|
+
return new ContextLogger(this, context, level);
|
|
98
|
+
}
|
|
99
|
+
getLogger(context) {
|
|
100
|
+
const key = this.createCacheKey(context);
|
|
101
|
+
let logger = this.loggers.get(key);
|
|
102
|
+
if (!logger) {
|
|
103
|
+
logger = this.createLogger(context);
|
|
104
|
+
this.loggers.set(key, logger);
|
|
105
|
+
}
|
|
106
|
+
return logger;
|
|
107
|
+
}
|
|
108
|
+
setGlobalLevel(level) {
|
|
109
|
+
this.config.globalLevel = level;
|
|
110
|
+
}
|
|
111
|
+
setPluginLevel(plugin, level) {
|
|
112
|
+
this.config.pluginLevels[plugin] = level;
|
|
113
|
+
}
|
|
114
|
+
setModuleLevel(module, level) {
|
|
115
|
+
this.config.moduleLevels[module] = level;
|
|
116
|
+
}
|
|
117
|
+
async flush() {
|
|
118
|
+
const entries = this.buffer.splice(0);
|
|
119
|
+
if (entries.length === 0) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
await Promise.all(entries.map(entry => this.dispatchToTransports(entry)));
|
|
123
|
+
await Promise.all(Array.from(this.transports.values())
|
|
124
|
+
.filter(t => t.flush)
|
|
125
|
+
.map(t => {
|
|
126
|
+
try {
|
|
127
|
+
return t.flush();
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
this.handleTransportError(t, error);
|
|
131
|
+
return Promise.resolve();
|
|
132
|
+
}
|
|
133
|
+
}));
|
|
134
|
+
this.eventEmitter.emit('flush', entries.length);
|
|
135
|
+
}
|
|
136
|
+
clearBuffer() {
|
|
137
|
+
this.buffer = [];
|
|
138
|
+
}
|
|
139
|
+
on(event, handler) {
|
|
140
|
+
this.eventEmitter.on(event, handler);
|
|
141
|
+
}
|
|
142
|
+
off(event, handler) {
|
|
143
|
+
this.eventEmitter.off(event, handler);
|
|
144
|
+
}
|
|
145
|
+
dispatch(entry) {
|
|
146
|
+
this.buffer.push(entry);
|
|
147
|
+
this.eventEmitter.emit('log', entry);
|
|
148
|
+
// Immediate dispatch for high-priority logs
|
|
149
|
+
if (entry.level >= 4) { // LogLevel.ERROR
|
|
150
|
+
this.dispatchToTransports(entry).catch(error => {
|
|
151
|
+
console.error('[LogManager] Error dispatching log entry:', error);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
// Flush if buffer is full
|
|
155
|
+
if (this.buffer.length >= this.config.bufferSize) {
|
|
156
|
+
this.flush().catch(error => {
|
|
157
|
+
console.error('[LogManager] Error flushing buffer:', error);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Clean up resources
|
|
163
|
+
*/
|
|
164
|
+
async destroy() {
|
|
165
|
+
if (this.flushTimer) {
|
|
166
|
+
clearInterval(this.flushTimer);
|
|
167
|
+
this.flushTimer = undefined;
|
|
168
|
+
}
|
|
169
|
+
await this.flush();
|
|
170
|
+
await Promise.all(Array.from(this.transports.values())
|
|
171
|
+
.filter(t => t.close)
|
|
172
|
+
.map(t => t.close()));
|
|
173
|
+
this.transports.clear();
|
|
174
|
+
this.transportConfigs.clear();
|
|
175
|
+
this.loggers.clear();
|
|
176
|
+
this.eventEmitter.clear();
|
|
177
|
+
}
|
|
178
|
+
async dispatchToTransports(entry) {
|
|
179
|
+
const promises = [];
|
|
180
|
+
for (const [id, transport] of this.transports) {
|
|
181
|
+
const config = this.transportConfigs.get(id);
|
|
182
|
+
if (!this.shouldDispatch(entry, config, transport)) {
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
const result = transport.log(entry);
|
|
187
|
+
if (result instanceof Promise) {
|
|
188
|
+
promises.push(result.catch(error => {
|
|
189
|
+
this.handleTransportError(transport, error);
|
|
190
|
+
}));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
this.handleTransportError(transport, error);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
await Promise.all(promises);
|
|
198
|
+
}
|
|
199
|
+
shouldDispatch(entry, config, transport) {
|
|
200
|
+
if (config && config.enabled === false) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
if (config?.minLevel !== undefined && entry.level < config.minLevel) {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
if (config?.maxLevel !== undefined && entry.level > config.maxLevel) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
if (config?.plugins && config.plugins.length > 0) {
|
|
210
|
+
if (!entry.context.plugin || !config.plugins.includes(entry.context.plugin)) {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (config?.modules && config.modules.length > 0) {
|
|
215
|
+
if (!entry.context.module || !config.modules.includes(entry.context.module)) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (config?.tags && config.tags.length > 0) {
|
|
220
|
+
if (!entry.metadata?.tags || !config.tags.some(tag => entry.metadata.tags.includes(tag))) {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (config?.filter && !config.filter(entry)) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
if (transport?.shouldLog && !transport.shouldLog(entry)) {
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
resolveLevel(context) {
|
|
233
|
+
if (context?.plugin) {
|
|
234
|
+
const pluginLevel = this.config.pluginLevels[context.plugin];
|
|
235
|
+
if (pluginLevel !== undefined) {
|
|
236
|
+
return pluginLevel;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (context?.module) {
|
|
240
|
+
const moduleLevel = this.config.moduleLevels[context.module];
|
|
241
|
+
if (moduleLevel !== undefined) {
|
|
242
|
+
return moduleLevel;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return this.config.globalLevel;
|
|
246
|
+
}
|
|
247
|
+
createCacheKey(context) {
|
|
248
|
+
if (!context) {
|
|
249
|
+
return '__default__';
|
|
250
|
+
}
|
|
251
|
+
return JSON.stringify({
|
|
252
|
+
plugin: context.plugin,
|
|
253
|
+
module: context.module,
|
|
254
|
+
component: context.component,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
startFlushTimer() {
|
|
258
|
+
this.flushTimer = setInterval(() => {
|
|
259
|
+
this.flush().catch(error => {
|
|
260
|
+
console.error('[LogManager] Error in flush timer:', error);
|
|
261
|
+
});
|
|
262
|
+
}, this.config.flushInterval);
|
|
263
|
+
}
|
|
264
|
+
handleTransportError(transport, error) {
|
|
265
|
+
this.eventEmitter.emit('error', { transport: transport.id, error });
|
|
266
|
+
if (transport.onError) {
|
|
267
|
+
try {
|
|
268
|
+
transport.onError(error);
|
|
269
|
+
}
|
|
270
|
+
catch (handlerError) {
|
|
271
|
+
console.error('[LogManager] Error in transport error handler:', handlerError);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
console.error(`[LogManager] Transport '${transport.id}' error:`, error);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ILogFormatter, LogEntry, ConsoleTransportConfig } from '../../api/index';
|
|
2
|
+
/**
|
|
3
|
+
* Development formatter with colors and emojis
|
|
4
|
+
*
|
|
5
|
+
* Provides rich, human-readable console output for development.
|
|
6
|
+
*/
|
|
7
|
+
export declare class DevFormatter implements ILogFormatter {
|
|
8
|
+
private config;
|
|
9
|
+
constructor(config?: ConsoleTransportConfig);
|
|
10
|
+
format(entry: LogEntry): string;
|
|
11
|
+
formatBatch(entries: LogEntry[]): string;
|
|
12
|
+
private formatTimestamp;
|
|
13
|
+
private formatLevel;
|
|
14
|
+
private getLevelEmoji;
|
|
15
|
+
private getLevelLabel;
|
|
16
|
+
private colorize;
|
|
17
|
+
private formatContext;
|
|
18
|
+
private formatMetadata;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=dev-formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-formatter.d.ts","sourceRoot":"","sources":["../../../src/impl/formatters/dev-formatter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAqC,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAE1H;;;;GAIG;AACH,qBAAa,YAAa,YAAW,aAAa;IACpC,OAAO,CAAC,MAAM;gBAAN,MAAM,GAAE,sBAA2B;IASvD,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM;IA+B/B,WAAW,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM;IAIxC,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,QAAQ;IAehB,OAAO,CAAC,aAAa;IAkCrB,OAAO,CAAC,cAAc;CAiCvB"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Development formatter with colors and emojis
|
|
3
|
+
*
|
|
4
|
+
* Provides rich, human-readable console output for development.
|
|
5
|
+
*/
|
|
6
|
+
export class DevFormatter {
|
|
7
|
+
constructor(config = {}) {
|
|
8
|
+
Object.defineProperty(this, "config", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
configurable: true,
|
|
11
|
+
writable: true,
|
|
12
|
+
value: config
|
|
13
|
+
});
|
|
14
|
+
this.config = {
|
|
15
|
+
colors: config.colors ?? true,
|
|
16
|
+
emojis: config.emojis ?? true,
|
|
17
|
+
timestamps: config.timestamps ?? true,
|
|
18
|
+
showContext: config.showContext ?? true,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
format(entry) {
|
|
22
|
+
const parts = [];
|
|
23
|
+
// Timestamp
|
|
24
|
+
if (this.config.timestamps) {
|
|
25
|
+
parts.push(this.formatTimestamp(entry.timestamp));
|
|
26
|
+
}
|
|
27
|
+
// Level with emoji and color
|
|
28
|
+
parts.push(this.formatLevel(entry.level));
|
|
29
|
+
// Context (plugin/module/component)
|
|
30
|
+
if (this.config.showContext) {
|
|
31
|
+
const context = this.formatContext(entry.context);
|
|
32
|
+
if (context) {
|
|
33
|
+
parts.push(context);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Message
|
|
37
|
+
parts.push(entry.message);
|
|
38
|
+
// Metadata
|
|
39
|
+
const metadata = this.formatMetadata(entry.metadata);
|
|
40
|
+
if (metadata) {
|
|
41
|
+
parts.push(metadata);
|
|
42
|
+
}
|
|
43
|
+
return parts.join(' ');
|
|
44
|
+
}
|
|
45
|
+
formatBatch(entries) {
|
|
46
|
+
return entries.map(e => this.format(e)).join('\n');
|
|
47
|
+
}
|
|
48
|
+
formatTimestamp(timestamp) {
|
|
49
|
+
const date = new Date(timestamp);
|
|
50
|
+
const time = date.toISOString().split('T')[1].split('.')[0];
|
|
51
|
+
return this.config.colors ? `\x1b[90m${time}\x1b[0m` : time;
|
|
52
|
+
}
|
|
53
|
+
formatLevel(level) {
|
|
54
|
+
const emoji = this.config.emojis ? this.getLevelEmoji(level) : '';
|
|
55
|
+
const label = this.getLevelLabel(level);
|
|
56
|
+
const colored = this.config.colors ? this.colorize(label, level) : label;
|
|
57
|
+
return emoji ? `${emoji} ${colored}` : colored;
|
|
58
|
+
}
|
|
59
|
+
getLevelEmoji(level) {
|
|
60
|
+
switch (level) {
|
|
61
|
+
case 0: return '🔍'; // TRACE
|
|
62
|
+
case 1: return '🐛'; // DEBUG
|
|
63
|
+
case 2: return 'ℹ️ '; // INFO
|
|
64
|
+
case 3: return '⚠️ '; // WARN
|
|
65
|
+
case 4: return '❌'; // ERROR
|
|
66
|
+
case 5: return '💀'; // FATAL
|
|
67
|
+
default: return '';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
getLevelLabel(level) {
|
|
71
|
+
switch (level) {
|
|
72
|
+
case 0: return 'TRACE';
|
|
73
|
+
case 1: return 'DEBUG';
|
|
74
|
+
case 2: return 'INFO ';
|
|
75
|
+
case 3: return 'WARN ';
|
|
76
|
+
case 4: return 'ERROR';
|
|
77
|
+
case 5: return 'FATAL';
|
|
78
|
+
default: return 'UNKNW';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
colorize(text, level) {
|
|
82
|
+
const colors = {
|
|
83
|
+
0: '\x1b[90m', // TRACE - Gray
|
|
84
|
+
1: '\x1b[36m', // DEBUG - Cyan
|
|
85
|
+
2: '\x1b[32m', // INFO - Green
|
|
86
|
+
3: '\x1b[33m', // WARN - Yellow
|
|
87
|
+
4: '\x1b[31m', // ERROR - Red
|
|
88
|
+
5: '\x1b[35m', // FATAL - Magenta
|
|
89
|
+
};
|
|
90
|
+
const color = colors[level] || '\x1b[0m';
|
|
91
|
+
const reset = '\x1b[0m';
|
|
92
|
+
return `${color}${text}${reset}`;
|
|
93
|
+
}
|
|
94
|
+
formatContext(context) {
|
|
95
|
+
const parts = [];
|
|
96
|
+
if (context.plugin) {
|
|
97
|
+
parts.push(this.config.colors
|
|
98
|
+
? `\x1b[35m[${context.plugin}]\x1b[0m`
|
|
99
|
+
: `[${context.plugin}]`);
|
|
100
|
+
}
|
|
101
|
+
if (context.module) {
|
|
102
|
+
parts.push(this.config.colors
|
|
103
|
+
? `\x1b[34m{${context.module}}\x1b[0m`
|
|
104
|
+
: `{${context.module}}`);
|
|
105
|
+
}
|
|
106
|
+
if (context.component) {
|
|
107
|
+
parts.push(this.config.colors
|
|
108
|
+
? `\x1b[36m<${context.component}>\x1b[0m`
|
|
109
|
+
: `<${context.component}>`);
|
|
110
|
+
}
|
|
111
|
+
if (context.operation) {
|
|
112
|
+
parts.push(this.config.colors
|
|
113
|
+
? `\x1b[90m(${context.operation})\x1b[0m`
|
|
114
|
+
: `(${context.operation})`);
|
|
115
|
+
}
|
|
116
|
+
return parts.join(' ');
|
|
117
|
+
}
|
|
118
|
+
formatMetadata(metadata) {
|
|
119
|
+
if (!metadata || Object.keys(metadata).length === 0) {
|
|
120
|
+
return '';
|
|
121
|
+
}
|
|
122
|
+
const { error, stack, tags, duration, ...rest } = metadata;
|
|
123
|
+
const parts = [];
|
|
124
|
+
// Duration
|
|
125
|
+
if (duration !== undefined) {
|
|
126
|
+
const color = this.config.colors ? '\x1b[33m' : '';
|
|
127
|
+
const reset = this.config.colors ? '\x1b[0m' : '';
|
|
128
|
+
parts.push(`${color}⏱ ${duration}ms${reset}`);
|
|
129
|
+
}
|
|
130
|
+
// Tags
|
|
131
|
+
if (tags && tags.length > 0) {
|
|
132
|
+
const tagString = tags.map(t => `#${t}`).join(' ');
|
|
133
|
+
const color = this.config.colors ? '\x1b[90m' : '';
|
|
134
|
+
const reset = this.config.colors ? '\x1b[0m' : '';
|
|
135
|
+
parts.push(`${color}${tagString}${reset}`);
|
|
136
|
+
}
|
|
137
|
+
// Other metadata
|
|
138
|
+
if (Object.keys(rest).length > 0) {
|
|
139
|
+
const color = this.config.colors ? '\x1b[90m' : '';
|
|
140
|
+
const reset = this.config.colors ? '\x1b[0m' : '';
|
|
141
|
+
parts.push(`${color}${JSON.stringify(rest)}${reset}`);
|
|
142
|
+
}
|
|
143
|
+
return parts.length > 0 ? parts.join(' ') : '';
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/impl/formatters/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ILogFormatter, LogEntry } from '../../api/index';
|
|
2
|
+
/**
|
|
3
|
+
* JSON formatter for structured logging
|
|
4
|
+
*
|
|
5
|
+
* Outputs logs as JSON for easy parsing by log aggregation tools.
|
|
6
|
+
*/
|
|
7
|
+
export declare class JsonFormatter implements ILogFormatter {
|
|
8
|
+
private config;
|
|
9
|
+
constructor(config?: JsonFormatterConfig);
|
|
10
|
+
format(entry: LogEntry): string;
|
|
11
|
+
formatBatch(entries: LogEntry[]): string;
|
|
12
|
+
private toObject;
|
|
13
|
+
private getLevelName;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Configuration for JSON formatter
|
|
17
|
+
*/
|
|
18
|
+
export interface JsonFormatterConfig {
|
|
19
|
+
/** Pretty print JSON (with indentation) */
|
|
20
|
+
pretty?: boolean;
|
|
21
|
+
/** Include stack traces for errors */
|
|
22
|
+
includeStack?: boolean;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=json-formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-formatter.d.ts","sourceRoot":"","sources":["../../../src/impl/formatters/json-formatter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE/D;;;;GAIG;AACH,qBAAa,aAAc,YAAW,aAAa;IACrC,OAAO,CAAC,MAAM;gBAAN,MAAM,GAAE,mBAAwB;IAQpD,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM;IAO/B,WAAW,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM;IAOxC,OAAO,CAAC,QAAQ;IAiChB,OAAO,CAAC,YAAY;CAWrB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,2CAA2C;IAC3C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,sCAAsC;IACtC,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON formatter for structured logging
|
|
3
|
+
*
|
|
4
|
+
* Outputs logs as JSON for easy parsing by log aggregation tools.
|
|
5
|
+
*/
|
|
6
|
+
export class JsonFormatter {
|
|
7
|
+
constructor(config = {}) {
|
|
8
|
+
Object.defineProperty(this, "config", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
configurable: true,
|
|
11
|
+
writable: true,
|
|
12
|
+
value: config
|
|
13
|
+
});
|
|
14
|
+
this.config = {
|
|
15
|
+
pretty: config.pretty ?? false,
|
|
16
|
+
includeStack: config.includeStack ?? true,
|
|
17
|
+
...config,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
format(entry) {
|
|
21
|
+
const logObject = this.toObject(entry);
|
|
22
|
+
return this.config.pretty
|
|
23
|
+
? JSON.stringify(logObject, null, 2)
|
|
24
|
+
: JSON.stringify(logObject);
|
|
25
|
+
}
|
|
26
|
+
formatBatch(entries) {
|
|
27
|
+
const logObjects = entries.map(e => this.toObject(e));
|
|
28
|
+
return this.config.pretty
|
|
29
|
+
? JSON.stringify(logObjects, null, 2)
|
|
30
|
+
: JSON.stringify(logObjects);
|
|
31
|
+
}
|
|
32
|
+
toObject(entry) {
|
|
33
|
+
const obj = {
|
|
34
|
+
timestamp: entry.timestamp,
|
|
35
|
+
level: this.getLevelName(entry.level),
|
|
36
|
+
message: entry.message,
|
|
37
|
+
};
|
|
38
|
+
// Add context
|
|
39
|
+
if (entry.context && Object.keys(entry.context).length > 0) {
|
|
40
|
+
obj.context = entry.context;
|
|
41
|
+
}
|
|
42
|
+
// Add metadata
|
|
43
|
+
if (entry.metadata) {
|
|
44
|
+
const { error, stack, ...rest } = entry.metadata;
|
|
45
|
+
if (Object.keys(rest).length > 0) {
|
|
46
|
+
obj.metadata = rest;
|
|
47
|
+
}
|
|
48
|
+
// Handle error separately
|
|
49
|
+
if (error) {
|
|
50
|
+
obj.error = {
|
|
51
|
+
name: error.name,
|
|
52
|
+
message: error.message,
|
|
53
|
+
...(this.config.includeStack && stack ? { stack } : {}),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return obj;
|
|
58
|
+
}
|
|
59
|
+
getLevelName(level) {
|
|
60
|
+
switch (level) {
|
|
61
|
+
case 0: return 'TRACE';
|
|
62
|
+
case 1: return 'DEBUG';
|
|
63
|
+
case 2: return 'INFO';
|
|
64
|
+
case 3: return 'WARN';
|
|
65
|
+
case 4: return 'ERROR';
|
|
66
|
+
case 5: return 'FATAL';
|
|
67
|
+
default: return 'UNKNOWN';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hamak/logging (impl)
|
|
3
|
+
*
|
|
4
|
+
* Core implementation of the pluggable logging system.
|
|
5
|
+
* Provides LogManager, ContextLogger, transports, and formatters.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
export * from './core/index';
|
|
10
|
+
export * from './transports/index';
|
|
11
|
+
export * from './formatters/index';
|
|
12
|
+
export * from './plugin/index';
|
|
13
|
+
export * from './utils/index';
|
|
14
|
+
export type { ILogger, ILogTransport, ILogFormatter, ILogManager, LogLevel, LogEntry, LogContext, LogMetadata, TransportConfig, LogManagerConfig, ConsoleTransportConfig, RemoteTransportConfig, } from '../api/index';
|
|
15
|
+
export { LOG_MANAGER_TOKEN, LOGGER_TOKEN, LOG_CONFIG_TOKEN, } from '../api/index';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/impl/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,cAAc,cAAc,CAAC;AAG7B,cAAc,oBAAoB,CAAC;AAGnC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,gBAAgB,CAAC;AAG/B,cAAc,eAAe,CAAC;AAG9B,YAAY,EACV,OAAO,EACP,aAAa,EACb,aAAa,EACb,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,GACjB,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hamak/logging (impl)
|
|
3
|
+
*
|
|
4
|
+
* Core implementation of the pluggable logging system.
|
|
5
|
+
* Provides LogManager, ContextLogger, transports, and formatters.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
// Export core implementations
|
|
10
|
+
export * from './core/index';
|
|
11
|
+
// Export transports
|
|
12
|
+
export * from './transports/index';
|
|
13
|
+
// Export formatters
|
|
14
|
+
export * from './formatters/index';
|
|
15
|
+
// Export plugin factory
|
|
16
|
+
export * from './plugin/index';
|
|
17
|
+
// Export utilities
|
|
18
|
+
export * from './utils/index';
|
|
19
|
+
export { LOG_MANAGER_TOKEN, LOGGER_TOKEN, LOG_CONFIG_TOKEN, } from '../api/index';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/impl/plugin/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './logging-plugin-factory';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { PluginModule } from '@hamak/microkernel-spi';
|
|
2
|
+
import type { LogManagerConfig } from '../../api/index';
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for the logging plugin
|
|
5
|
+
*/
|
|
6
|
+
export interface LoggingPluginConfig extends LogManagerConfig {
|
|
7
|
+
/** Use development formatter (rich console output) */
|
|
8
|
+
devFormatter?: boolean;
|
|
9
|
+
/** Remote transport configuration */
|
|
10
|
+
remoteTransport?: any;
|
|
11
|
+
/**
|
|
12
|
+
* Intercept console.log/warn/error and route through logging system
|
|
13
|
+
* @default true - Enabled by default, set to false to disable
|
|
14
|
+
*/
|
|
15
|
+
interceptConsole?: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Create a logging plugin for the microkernel
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { createLoggingPlugin } from '@hamak/logging-impl';
|
|
23
|
+
*
|
|
24
|
+
* const loggingPlugin = createLoggingPlugin({
|
|
25
|
+
* globalLevel: LogLevel.DEBUG,
|
|
26
|
+
* pluginLevels: {
|
|
27
|
+
* 'my-plugin': LogLevel.TRACE
|
|
28
|
+
* }
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* const host = createHost({
|
|
32
|
+
* plugins: [loggingPlugin, myPlugin]
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function createLoggingPlugin(config?: LoggingPluginConfig): PluginModule;
|
|
37
|
+
//# sourceMappingURL=logging-plugin-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging-plugin-factory.d.ts","sourceRoot":"","sources":["../../../src/impl/plugin/logging-plugin-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAyB,MAAM,wBAAwB,CAAC;AAElF,OAAO,KAAK,EAAW,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAQjE;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;IAC3D,sDAAsD;IACtD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,qCAAqC;IACrC,eAAe,CAAC,EAAE,GAAG,CAAC;IACtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,GAAE,mBAAwB,GAAG,YAAY,CAyGlF"}
|