@hamak/logging-impl 0.4.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/dist/core/context-logger.d.ts +26 -0
- package/dist/core/context-logger.d.ts.map +1 -0
- package/dist/core/context-logger.js +82 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +2 -0
- package/dist/core/log-manager.d.ts +41 -0
- package/dist/core/log-manager.d.ts.map +1 -0
- package/dist/core/log-manager.js +241 -0
- package/dist/es2015/core/context-logger.js +74 -0
- package/dist/es2015/core/index.js +2 -0
- package/dist/es2015/core/log-manager.js +255 -0
- package/dist/es2015/formatters/dev-formatter.js +152 -0
- package/dist/es2015/formatters/index.js +2 -0
- package/dist/es2015/formatters/json-formatter.js +69 -0
- package/dist/es2015/index.js +19 -0
- package/dist/es2015/plugin/index.js +1 -0
- package/dist/es2015/plugin/logging-plugin-factory.js +118 -0
- package/dist/es2015/transports/console-transport.js +41 -0
- package/dist/es2015/transports/index.js +1 -0
- package/dist/es2015/utils/console-interceptor.js +105 -0
- package/dist/es2015/utils/event-emitter.js +39 -0
- package/dist/es2015/utils/index.js +2 -0
- package/dist/formatters/dev-formatter.d.ts +20 -0
- package/dist/formatters/dev-formatter.d.ts.map +1 -0
- package/dist/formatters/dev-formatter.js +140 -0
- package/dist/formatters/index.d.ts +3 -0
- package/dist/formatters/index.d.ts.map +1 -0
- package/dist/formatters/index.js +2 -0
- package/dist/formatters/json-formatter.d.ts +24 -0
- package/dist/formatters/json-formatter.d.ts.map +1 -0
- package/dist/formatters/json-formatter.js +65 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/plugin/index.d.ts +2 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/index.js +1 -0
- package/dist/plugin/logging-plugin-factory.d.ts +37 -0
- package/dist/plugin/logging-plugin-factory.d.ts.map +1 -0
- package/dist/plugin/logging-plugin-factory.js +112 -0
- package/dist/transports/console-transport.d.ts +16 -0
- package/dist/transports/console-transport.d.ts.map +1 -0
- package/dist/transports/console-transport.js +40 -0
- package/dist/transports/index.d.ts +2 -0
- package/dist/transports/index.d.ts.map +1 -0
- package/dist/transports/index.js +1 -0
- package/dist/utils/console-interceptor.d.ts +36 -0
- package/dist/utils/console-interceptor.d.ts.map +1 -0
- package/dist/utils/console-interceptor.js +105 -0
- package/dist/utils/event-emitter.d.ts +11 -0
- package/dist/utils/event-emitter.d.ts.map +1 -0
- package/dist/utils/event-emitter.js +39 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2 -0
- package/package.json +54 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ILogger, ILogManager, LogLevel, LogContext, LogMetadata } from '@hamak/logging-api';
|
|
2
|
+
/**
|
|
3
|
+
* Logger implementation with context awareness
|
|
4
|
+
*
|
|
5
|
+
* Tracks plugin/module/component hierarchy and supports child loggers.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ContextLogger implements ILogger {
|
|
8
|
+
private manager;
|
|
9
|
+
private context;
|
|
10
|
+
private minLevel;
|
|
11
|
+
private timers;
|
|
12
|
+
constructor(manager: ILogManager, context: LogContext | undefined, minLevel: LogLevel);
|
|
13
|
+
trace(message: string, meta?: LogMetadata): void;
|
|
14
|
+
debug(message: string, meta?: LogMetadata): void;
|
|
15
|
+
info(message: string, meta?: LogMetadata): void;
|
|
16
|
+
warn(message: string, meta?: LogMetadata): void;
|
|
17
|
+
error(message: string, error?: Error, meta?: LogMetadata): void;
|
|
18
|
+
fatal(message: string, error?: Error, meta?: LogMetadata): void;
|
|
19
|
+
private log;
|
|
20
|
+
child(context: LogContext): ILogger;
|
|
21
|
+
scoped(context: LogContext, fn: (logger: ILogger) => void): void;
|
|
22
|
+
isLevelEnabled(level: LogLevel): boolean;
|
|
23
|
+
time(label: string): void;
|
|
24
|
+
timeEnd(label: string): void;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=context-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-logger.d.ts","sourceRoot":"","sources":["../../src/core/context-logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAElG;;;;GAIG;AACH,qBAAa,aAAc,YAAW,OAAO;IAIzC,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ;IALlB,OAAO,CAAC,MAAM,CAA6B;gBAGjC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,UAAU,YAAK,EACxB,QAAQ,EAAE,QAAQ;IAG5B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI;IAKhD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI;IAKhD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI;IAK/C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI;IAK/C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI;IAS/D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI;IAS/D,OAAO,CAAC,GAAG;IAYX,KAAK,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO;IAQnC,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAKhE,cAAc,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IAIxC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIzB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAQ7B"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger implementation with context awareness
|
|
3
|
+
*
|
|
4
|
+
* Tracks plugin/module/component hierarchy and supports child loggers.
|
|
5
|
+
*/
|
|
6
|
+
export class ContextLogger {
|
|
7
|
+
constructor(manager, context = {}, minLevel) {
|
|
8
|
+
this.manager = manager;
|
|
9
|
+
this.context = context;
|
|
10
|
+
this.minLevel = minLevel;
|
|
11
|
+
this.timers = new Map();
|
|
12
|
+
}
|
|
13
|
+
trace(message, meta) {
|
|
14
|
+
if (!this.isLevelEnabled(0))
|
|
15
|
+
return; // LogLevel.TRACE = 0
|
|
16
|
+
this.log(0, message, meta);
|
|
17
|
+
}
|
|
18
|
+
debug(message, meta) {
|
|
19
|
+
if (!this.isLevelEnabled(1))
|
|
20
|
+
return; // LogLevel.DEBUG = 1
|
|
21
|
+
this.log(1, message, meta);
|
|
22
|
+
}
|
|
23
|
+
info(message, meta) {
|
|
24
|
+
if (!this.isLevelEnabled(2))
|
|
25
|
+
return; // LogLevel.INFO = 2
|
|
26
|
+
this.log(2, message, meta);
|
|
27
|
+
}
|
|
28
|
+
warn(message, meta) {
|
|
29
|
+
if (!this.isLevelEnabled(3))
|
|
30
|
+
return; // LogLevel.WARN = 3
|
|
31
|
+
this.log(3, message, meta);
|
|
32
|
+
}
|
|
33
|
+
error(message, error, meta) {
|
|
34
|
+
if (!this.isLevelEnabled(4))
|
|
35
|
+
return; // LogLevel.ERROR = 4
|
|
36
|
+
this.log(4, message, {
|
|
37
|
+
...meta,
|
|
38
|
+
error,
|
|
39
|
+
stack: error?.stack,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
fatal(message, error, meta) {
|
|
43
|
+
if (!this.isLevelEnabled(5))
|
|
44
|
+
return; // LogLevel.FATAL = 5
|
|
45
|
+
this.log(5, message, {
|
|
46
|
+
...meta,
|
|
47
|
+
error,
|
|
48
|
+
stack: error?.stack,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
log(level, message, metadata) {
|
|
52
|
+
const entry = {
|
|
53
|
+
timestamp: Date.now(),
|
|
54
|
+
level,
|
|
55
|
+
message,
|
|
56
|
+
context: { ...this.context },
|
|
57
|
+
metadata,
|
|
58
|
+
};
|
|
59
|
+
this.manager.dispatch(entry);
|
|
60
|
+
}
|
|
61
|
+
child(context) {
|
|
62
|
+
return new ContextLogger(this.manager, { ...this.context, ...context }, this.minLevel);
|
|
63
|
+
}
|
|
64
|
+
scoped(context, fn) {
|
|
65
|
+
const scopedLogger = this.child(context);
|
|
66
|
+
fn(scopedLogger);
|
|
67
|
+
}
|
|
68
|
+
isLevelEnabled(level) {
|
|
69
|
+
return level >= this.minLevel;
|
|
70
|
+
}
|
|
71
|
+
time(label) {
|
|
72
|
+
this.timers.set(label, Date.now());
|
|
73
|
+
}
|
|
74
|
+
timeEnd(label) {
|
|
75
|
+
const start = this.timers.get(label);
|
|
76
|
+
if (start !== undefined) {
|
|
77
|
+
const duration = Date.now() - start;
|
|
78
|
+
this.debug(`${label}`, { duration, tags: ['performance'] });
|
|
79
|
+
this.timers.delete(label);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ILogManager, ILogger, ILogTransport, LogLevel, LogContext, LogEntry, LogManagerConfig, TransportConfig } from '@hamak/logging-api';
|
|
2
|
+
/**
|
|
3
|
+
* Central log manager implementation
|
|
4
|
+
*
|
|
5
|
+
* Manages transports, creates loggers, and dispatches log entries.
|
|
6
|
+
*/
|
|
7
|
+
export declare class LogManager implements ILogManager {
|
|
8
|
+
private transports;
|
|
9
|
+
private transportConfigs;
|
|
10
|
+
private loggers;
|
|
11
|
+
private buffer;
|
|
12
|
+
private config;
|
|
13
|
+
private eventEmitter;
|
|
14
|
+
private flushTimer?;
|
|
15
|
+
constructor(config?: LogManagerConfig);
|
|
16
|
+
registerTransport(transport: ILogTransport, config?: TransportConfig): void;
|
|
17
|
+
unregisterTransport(id: string): void;
|
|
18
|
+
getTransport(id: string): ILogTransport | undefined;
|
|
19
|
+
listTransports(): ILogTransport[];
|
|
20
|
+
createLogger(context?: LogContext): ILogger;
|
|
21
|
+
getLogger(context?: LogContext): ILogger;
|
|
22
|
+
setGlobalLevel(level: LogLevel): void;
|
|
23
|
+
setPluginLevel(plugin: string, level: LogLevel): void;
|
|
24
|
+
setModuleLevel(module: string, level: LogLevel): void;
|
|
25
|
+
flush(): Promise<void>;
|
|
26
|
+
clearBuffer(): void;
|
|
27
|
+
on(event: 'log' | 'error' | 'flush', handler: (...args: any[]) => void): void;
|
|
28
|
+
off(event: string, handler: (...args: any[]) => void): void;
|
|
29
|
+
dispatch(entry: LogEntry): void;
|
|
30
|
+
/**
|
|
31
|
+
* Clean up resources
|
|
32
|
+
*/
|
|
33
|
+
destroy(): Promise<void>;
|
|
34
|
+
private dispatchToTransports;
|
|
35
|
+
private shouldDispatch;
|
|
36
|
+
private resolveLevel;
|
|
37
|
+
private createCacheKey;
|
|
38
|
+
private startFlushTimer;
|
|
39
|
+
private handleTransportError;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=log-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-manager.d.ts","sourceRoot":"","sources":["../../src/core/log-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,OAAO,EACP,aAAa,EACb,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,gBAAgB,EAChB,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAI5B;;;;GAIG;AACH,qBAAa,UAAW,YAAW,WAAW;IAC5C,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,gBAAgB,CAAsC;IAC9D,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,UAAU,CAAC,CAAiC;gBAExC,MAAM,GAAE,gBAAqB;IAezC,iBAAiB,CAAC,SAAS,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI;IAe3E,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAWrC,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAInD,cAAc,IAAI,aAAa,EAAE;IAIjC,YAAY,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO;IAK3C,SAAS,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO;IAUxC,cAAc,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAIrC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI;IAIrD,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA2B5B,WAAW,IAAI,IAAI;IAInB,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,IAAI;IAI7E,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,IAAI;IAI3D,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAoB/B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAoBhB,oBAAoB;IAyBlC,OAAO,CAAC,cAAc;IA8CtB,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,oBAAoB;CAa7B"}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { ContextLogger } from './context-logger.js';
|
|
2
|
+
import { EventEmitter } from '../utils/event-emitter.js';
|
|
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
|
+
this.transports = new Map();
|
|
11
|
+
this.transportConfigs = new Map();
|
|
12
|
+
this.loggers = new Map();
|
|
13
|
+
this.buffer = [];
|
|
14
|
+
this.eventEmitter = new EventEmitter();
|
|
15
|
+
this.config = {
|
|
16
|
+
globalLevel: config.globalLevel ?? 2, // LogLevel.INFO
|
|
17
|
+
bufferSize: config.bufferSize ?? 1000,
|
|
18
|
+
flushInterval: config.flushInterval ?? 5000,
|
|
19
|
+
defaultTransports: config.defaultTransports ?? [],
|
|
20
|
+
pluginLevels: config.pluginLevels ?? {},
|
|
21
|
+
moduleLevels: config.moduleLevels ?? {},
|
|
22
|
+
};
|
|
23
|
+
if (this.config.flushInterval > 0) {
|
|
24
|
+
this.startFlushTimer();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
registerTransport(transport, config) {
|
|
28
|
+
this.transports.set(transport.id, transport);
|
|
29
|
+
if (config) {
|
|
30
|
+
this.transportConfigs.set(transport.id, {
|
|
31
|
+
enabled: true,
|
|
32
|
+
...config,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
this.transportConfigs.set(transport.id, {
|
|
37
|
+
id: transport.id,
|
|
38
|
+
enabled: true,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
unregisterTransport(id) {
|
|
43
|
+
const transport = this.transports.get(id);
|
|
44
|
+
if (transport && transport.close) {
|
|
45
|
+
transport.close().catch((error) => {
|
|
46
|
+
this.handleTransportError(transport, error);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
this.transports.delete(id);
|
|
50
|
+
this.transportConfigs.delete(id);
|
|
51
|
+
}
|
|
52
|
+
getTransport(id) {
|
|
53
|
+
return this.transports.get(id);
|
|
54
|
+
}
|
|
55
|
+
listTransports() {
|
|
56
|
+
return Array.from(this.transports.values());
|
|
57
|
+
}
|
|
58
|
+
createLogger(context) {
|
|
59
|
+
const level = this.resolveLevel(context);
|
|
60
|
+
return new ContextLogger(this, context, level);
|
|
61
|
+
}
|
|
62
|
+
getLogger(context) {
|
|
63
|
+
const key = this.createCacheKey(context);
|
|
64
|
+
let logger = this.loggers.get(key);
|
|
65
|
+
if (!logger) {
|
|
66
|
+
logger = this.createLogger(context);
|
|
67
|
+
this.loggers.set(key, logger);
|
|
68
|
+
}
|
|
69
|
+
return logger;
|
|
70
|
+
}
|
|
71
|
+
setGlobalLevel(level) {
|
|
72
|
+
this.config.globalLevel = level;
|
|
73
|
+
}
|
|
74
|
+
setPluginLevel(plugin, level) {
|
|
75
|
+
this.config.pluginLevels[plugin] = level;
|
|
76
|
+
}
|
|
77
|
+
setModuleLevel(module, level) {
|
|
78
|
+
this.config.moduleLevels[module] = level;
|
|
79
|
+
}
|
|
80
|
+
async flush() {
|
|
81
|
+
const entries = this.buffer.splice(0);
|
|
82
|
+
if (entries.length === 0) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
await Promise.all(entries.map(entry => this.dispatchToTransports(entry)));
|
|
86
|
+
await Promise.all(Array.from(this.transports.values())
|
|
87
|
+
.filter(t => t.flush)
|
|
88
|
+
.map(t => {
|
|
89
|
+
try {
|
|
90
|
+
return t.flush();
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
this.handleTransportError(t, error);
|
|
94
|
+
return Promise.resolve();
|
|
95
|
+
}
|
|
96
|
+
}));
|
|
97
|
+
this.eventEmitter.emit('flush', entries.length);
|
|
98
|
+
}
|
|
99
|
+
clearBuffer() {
|
|
100
|
+
this.buffer = [];
|
|
101
|
+
}
|
|
102
|
+
on(event, handler) {
|
|
103
|
+
this.eventEmitter.on(event, handler);
|
|
104
|
+
}
|
|
105
|
+
off(event, handler) {
|
|
106
|
+
this.eventEmitter.off(event, handler);
|
|
107
|
+
}
|
|
108
|
+
dispatch(entry) {
|
|
109
|
+
this.buffer.push(entry);
|
|
110
|
+
this.eventEmitter.emit('log', entry);
|
|
111
|
+
// Immediate dispatch for high-priority logs
|
|
112
|
+
if (entry.level >= 4) { // LogLevel.ERROR
|
|
113
|
+
this.dispatchToTransports(entry).catch(error => {
|
|
114
|
+
console.error('[LogManager] Error dispatching log entry:', error);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
// Flush if buffer is full
|
|
118
|
+
if (this.buffer.length >= this.config.bufferSize) {
|
|
119
|
+
this.flush().catch(error => {
|
|
120
|
+
console.error('[LogManager] Error flushing buffer:', error);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Clean up resources
|
|
126
|
+
*/
|
|
127
|
+
async destroy() {
|
|
128
|
+
if (this.flushTimer) {
|
|
129
|
+
clearInterval(this.flushTimer);
|
|
130
|
+
this.flushTimer = undefined;
|
|
131
|
+
}
|
|
132
|
+
await this.flush();
|
|
133
|
+
await Promise.all(Array.from(this.transports.values())
|
|
134
|
+
.filter(t => t.close)
|
|
135
|
+
.map(t => t.close()));
|
|
136
|
+
this.transports.clear();
|
|
137
|
+
this.transportConfigs.clear();
|
|
138
|
+
this.loggers.clear();
|
|
139
|
+
this.eventEmitter.clear();
|
|
140
|
+
}
|
|
141
|
+
async dispatchToTransports(entry) {
|
|
142
|
+
const promises = [];
|
|
143
|
+
for (const [id, transport] of this.transports) {
|
|
144
|
+
const config = this.transportConfigs.get(id);
|
|
145
|
+
if (!this.shouldDispatch(entry, config, transport)) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
const result = transport.log(entry);
|
|
150
|
+
if (result instanceof Promise) {
|
|
151
|
+
promises.push(result.catch(error => {
|
|
152
|
+
this.handleTransportError(transport, error);
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
this.handleTransportError(transport, error);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
await Promise.all(promises);
|
|
161
|
+
}
|
|
162
|
+
shouldDispatch(entry, config, transport) {
|
|
163
|
+
if (config && config.enabled === false) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
if (config?.minLevel !== undefined && entry.level < config.minLevel) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
if (config?.maxLevel !== undefined && entry.level > config.maxLevel) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
if (config?.plugins && config.plugins.length > 0) {
|
|
173
|
+
if (!entry.context.plugin || !config.plugins.includes(entry.context.plugin)) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (config?.modules && config.modules.length > 0) {
|
|
178
|
+
if (!entry.context.module || !config.modules.includes(entry.context.module)) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (config?.tags && config.tags.length > 0) {
|
|
183
|
+
if (!entry.metadata?.tags || !config.tags.some(tag => entry.metadata.tags.includes(tag))) {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (config?.filter && !config.filter(entry)) {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
if (transport?.shouldLog && !transport.shouldLog(entry)) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
resolveLevel(context) {
|
|
196
|
+
if (context?.plugin) {
|
|
197
|
+
const pluginLevel = this.config.pluginLevels[context.plugin];
|
|
198
|
+
if (pluginLevel !== undefined) {
|
|
199
|
+
return pluginLevel;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (context?.module) {
|
|
203
|
+
const moduleLevel = this.config.moduleLevels[context.module];
|
|
204
|
+
if (moduleLevel !== undefined) {
|
|
205
|
+
return moduleLevel;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return this.config.globalLevel;
|
|
209
|
+
}
|
|
210
|
+
createCacheKey(context) {
|
|
211
|
+
if (!context) {
|
|
212
|
+
return '__default__';
|
|
213
|
+
}
|
|
214
|
+
return JSON.stringify({
|
|
215
|
+
plugin: context.plugin,
|
|
216
|
+
module: context.module,
|
|
217
|
+
component: context.component,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
startFlushTimer() {
|
|
221
|
+
this.flushTimer = setInterval(() => {
|
|
222
|
+
this.flush().catch(error => {
|
|
223
|
+
console.error('[LogManager] Error in flush timer:', error);
|
|
224
|
+
});
|
|
225
|
+
}, this.config.flushInterval);
|
|
226
|
+
}
|
|
227
|
+
handleTransportError(transport, error) {
|
|
228
|
+
this.eventEmitter.emit('error', { transport: transport.id, error });
|
|
229
|
+
if (transport.onError) {
|
|
230
|
+
try {
|
|
231
|
+
transport.onError(error);
|
|
232
|
+
}
|
|
233
|
+
catch (handlerError) {
|
|
234
|
+
console.error('[LogManager] Error in transport error handler:', handlerError);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
console.error(`[LogManager] Transport '${transport.id}' error:`, error);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger implementation with context awareness
|
|
3
|
+
*
|
|
4
|
+
* Tracks plugin/module/component hierarchy and supports child loggers.
|
|
5
|
+
*/
|
|
6
|
+
export class ContextLogger {
|
|
7
|
+
constructor(manager, context = {}, minLevel) {
|
|
8
|
+
this.manager = manager;
|
|
9
|
+
this.context = context;
|
|
10
|
+
this.minLevel = minLevel;
|
|
11
|
+
this.timers = new Map();
|
|
12
|
+
}
|
|
13
|
+
trace(message, meta) {
|
|
14
|
+
if (!this.isLevelEnabled(0))
|
|
15
|
+
return; // LogLevel.TRACE = 0
|
|
16
|
+
this.log(0, message, meta);
|
|
17
|
+
}
|
|
18
|
+
debug(message, meta) {
|
|
19
|
+
if (!this.isLevelEnabled(1))
|
|
20
|
+
return; // LogLevel.DEBUG = 1
|
|
21
|
+
this.log(1, message, meta);
|
|
22
|
+
}
|
|
23
|
+
info(message, meta) {
|
|
24
|
+
if (!this.isLevelEnabled(2))
|
|
25
|
+
return; // LogLevel.INFO = 2
|
|
26
|
+
this.log(2, message, meta);
|
|
27
|
+
}
|
|
28
|
+
warn(message, meta) {
|
|
29
|
+
if (!this.isLevelEnabled(3))
|
|
30
|
+
return; // LogLevel.WARN = 3
|
|
31
|
+
this.log(3, message, meta);
|
|
32
|
+
}
|
|
33
|
+
error(message, error, meta) {
|
|
34
|
+
if (!this.isLevelEnabled(4))
|
|
35
|
+
return; // LogLevel.ERROR = 4
|
|
36
|
+
this.log(4, message, Object.assign(Object.assign({}, meta), { error, stack: error === null || error === void 0 ? void 0 : error.stack }));
|
|
37
|
+
}
|
|
38
|
+
fatal(message, error, meta) {
|
|
39
|
+
if (!this.isLevelEnabled(5))
|
|
40
|
+
return; // LogLevel.FATAL = 5
|
|
41
|
+
this.log(5, message, Object.assign(Object.assign({}, meta), { error, stack: error === null || error === void 0 ? void 0 : error.stack }));
|
|
42
|
+
}
|
|
43
|
+
log(level, message, metadata) {
|
|
44
|
+
const entry = {
|
|
45
|
+
timestamp: Date.now(),
|
|
46
|
+
level,
|
|
47
|
+
message,
|
|
48
|
+
context: Object.assign({}, this.context),
|
|
49
|
+
metadata,
|
|
50
|
+
};
|
|
51
|
+
this.manager.dispatch(entry);
|
|
52
|
+
}
|
|
53
|
+
child(context) {
|
|
54
|
+
return new ContextLogger(this.manager, Object.assign(Object.assign({}, this.context), context), this.minLevel);
|
|
55
|
+
}
|
|
56
|
+
scoped(context, fn) {
|
|
57
|
+
const scopedLogger = this.child(context);
|
|
58
|
+
fn(scopedLogger);
|
|
59
|
+
}
|
|
60
|
+
isLevelEnabled(level) {
|
|
61
|
+
return level >= this.minLevel;
|
|
62
|
+
}
|
|
63
|
+
time(label) {
|
|
64
|
+
this.timers.set(label, Date.now());
|
|
65
|
+
}
|
|
66
|
+
timeEnd(label) {
|
|
67
|
+
const start = this.timers.get(label);
|
|
68
|
+
if (start !== undefined) {
|
|
69
|
+
const duration = Date.now() - start;
|
|
70
|
+
this.debug(`${label}`, { duration, tags: ['performance'] });
|
|
71
|
+
this.timers.delete(label);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|