@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,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Console interceptor that routes console methods through the logging system
|
|
3
|
+
*
|
|
4
|
+
* By default, this is enabled. Set `interceptConsole: false` in LoggingPluginConfig to disable.
|
|
5
|
+
*/
|
|
6
|
+
export class ConsoleInterceptor {
|
|
7
|
+
constructor(logManager) {
|
|
8
|
+
this.logManager = logManager;
|
|
9
|
+
this.isIntercepting = false;
|
|
10
|
+
// Store original console methods
|
|
11
|
+
this.originalConsole = {
|
|
12
|
+
log: console.log.bind(console),
|
|
13
|
+
debug: console.debug.bind(console),
|
|
14
|
+
info: console.info.bind(console),
|
|
15
|
+
warn: console.warn.bind(console),
|
|
16
|
+
error: console.error.bind(console),
|
|
17
|
+
trace: console.trace.bind(console),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Start intercepting console methods
|
|
22
|
+
*/
|
|
23
|
+
intercept() {
|
|
24
|
+
if (this.isIntercepting) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const logger = this.logManager.createLogger({
|
|
28
|
+
plugin: 'console-interceptor',
|
|
29
|
+
module: 'global'
|
|
30
|
+
});
|
|
31
|
+
// Intercept console.log
|
|
32
|
+
console.log = (...args) => {
|
|
33
|
+
logger.info(this.formatMessage(args));
|
|
34
|
+
};
|
|
35
|
+
// Intercept console.debug
|
|
36
|
+
console.debug = (...args) => {
|
|
37
|
+
logger.debug(this.formatMessage(args));
|
|
38
|
+
};
|
|
39
|
+
// Intercept console.info
|
|
40
|
+
console.info = (...args) => {
|
|
41
|
+
logger.info(this.formatMessage(args));
|
|
42
|
+
};
|
|
43
|
+
// Intercept console.warn
|
|
44
|
+
console.warn = (...args) => {
|
|
45
|
+
logger.warn(this.formatMessage(args));
|
|
46
|
+
};
|
|
47
|
+
// Intercept console.error
|
|
48
|
+
console.error = (...args) => {
|
|
49
|
+
const message = this.formatMessage(args);
|
|
50
|
+
const error = args.find(arg => arg instanceof Error);
|
|
51
|
+
logger.error(message, error);
|
|
52
|
+
};
|
|
53
|
+
// Intercept console.trace
|
|
54
|
+
console.trace = (...args) => {
|
|
55
|
+
const message = this.formatMessage(args);
|
|
56
|
+
logger.debug(message, {
|
|
57
|
+
stack: new Error().stack,
|
|
58
|
+
tags: ['trace']
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
this.isIntercepting = true;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Stop intercepting and restore original console methods
|
|
65
|
+
*/
|
|
66
|
+
restore() {
|
|
67
|
+
if (!this.isIntercepting) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
console.log = this.originalConsole.log;
|
|
71
|
+
console.debug = this.originalConsole.debug;
|
|
72
|
+
console.info = this.originalConsole.info;
|
|
73
|
+
console.warn = this.originalConsole.warn;
|
|
74
|
+
console.error = this.originalConsole.error;
|
|
75
|
+
console.trace = this.originalConsole.trace;
|
|
76
|
+
this.isIntercepting = false;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get original console for direct access
|
|
80
|
+
*/
|
|
81
|
+
getOriginalConsole() {
|
|
82
|
+
return this.originalConsole;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Format console arguments into a single message
|
|
86
|
+
*/
|
|
87
|
+
formatMessage(args) {
|
|
88
|
+
return args
|
|
89
|
+
.map(arg => {
|
|
90
|
+
if (typeof arg === 'string') {
|
|
91
|
+
return arg;
|
|
92
|
+
}
|
|
93
|
+
if (arg instanceof Error) {
|
|
94
|
+
return `${arg.name}: ${arg.message}`;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
return JSON.stringify(arg);
|
|
98
|
+
}
|
|
99
|
+
catch (_a) {
|
|
100
|
+
return String(arg);
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
.join(' ');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple event emitter for internal use
|
|
3
|
+
*/
|
|
4
|
+
export class EventEmitter {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.listeners = new Map();
|
|
7
|
+
}
|
|
8
|
+
on(event, handler) {
|
|
9
|
+
if (!this.listeners.has(event)) {
|
|
10
|
+
this.listeners.set(event, new Set());
|
|
11
|
+
}
|
|
12
|
+
this.listeners.get(event).add(handler);
|
|
13
|
+
}
|
|
14
|
+
off(event, handler) {
|
|
15
|
+
const handlers = this.listeners.get(event);
|
|
16
|
+
if (handlers) {
|
|
17
|
+
handlers.delete(handler);
|
|
18
|
+
if (handlers.size === 0) {
|
|
19
|
+
this.listeners.delete(event);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
emit(event, ...args) {
|
|
24
|
+
const handlers = this.listeners.get(event);
|
|
25
|
+
if (handlers) {
|
|
26
|
+
handlers.forEach(handler => {
|
|
27
|
+
try {
|
|
28
|
+
handler(...args);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
console.error(`[EventEmitter] Error in handler for '${event}':`, error);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
clear() {
|
|
37
|
+
this.listeners.clear();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ILogFormatter, LogEntry, ConsoleTransportConfig } from '@hamak/logging-api';
|
|
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/formatters/dev-formatter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAqC,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAE7H;;;;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,140 @@
|
|
|
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
|
+
this.config = config;
|
|
9
|
+
this.config = {
|
|
10
|
+
colors: config.colors ?? true,
|
|
11
|
+
emojis: config.emojis ?? true,
|
|
12
|
+
timestamps: config.timestamps ?? true,
|
|
13
|
+
showContext: config.showContext ?? true,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
format(entry) {
|
|
17
|
+
const parts = [];
|
|
18
|
+
// Timestamp
|
|
19
|
+
if (this.config.timestamps) {
|
|
20
|
+
parts.push(this.formatTimestamp(entry.timestamp));
|
|
21
|
+
}
|
|
22
|
+
// Level with emoji and color
|
|
23
|
+
parts.push(this.formatLevel(entry.level));
|
|
24
|
+
// Context (plugin/module/component)
|
|
25
|
+
if (this.config.showContext) {
|
|
26
|
+
const context = this.formatContext(entry.context);
|
|
27
|
+
if (context) {
|
|
28
|
+
parts.push(context);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Message
|
|
32
|
+
parts.push(entry.message);
|
|
33
|
+
// Metadata
|
|
34
|
+
const metadata = this.formatMetadata(entry.metadata);
|
|
35
|
+
if (metadata) {
|
|
36
|
+
parts.push(metadata);
|
|
37
|
+
}
|
|
38
|
+
return parts.join(' ');
|
|
39
|
+
}
|
|
40
|
+
formatBatch(entries) {
|
|
41
|
+
return entries.map(e => this.format(e)).join('\n');
|
|
42
|
+
}
|
|
43
|
+
formatTimestamp(timestamp) {
|
|
44
|
+
const date = new Date(timestamp);
|
|
45
|
+
const time = date.toISOString().split('T')[1].split('.')[0];
|
|
46
|
+
return this.config.colors ? `\x1b[90m${time}\x1b[0m` : time;
|
|
47
|
+
}
|
|
48
|
+
formatLevel(level) {
|
|
49
|
+
const emoji = this.config.emojis ? this.getLevelEmoji(level) : '';
|
|
50
|
+
const label = this.getLevelLabel(level);
|
|
51
|
+
const colored = this.config.colors ? this.colorize(label, level) : label;
|
|
52
|
+
return emoji ? `${emoji} ${colored}` : colored;
|
|
53
|
+
}
|
|
54
|
+
getLevelEmoji(level) {
|
|
55
|
+
switch (level) {
|
|
56
|
+
case 0: return '🔍'; // TRACE
|
|
57
|
+
case 1: return '🐛'; // DEBUG
|
|
58
|
+
case 2: return 'ℹ️ '; // INFO
|
|
59
|
+
case 3: return '⚠️ '; // WARN
|
|
60
|
+
case 4: return '❌'; // ERROR
|
|
61
|
+
case 5: return '💀'; // FATAL
|
|
62
|
+
default: return '';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
getLevelLabel(level) {
|
|
66
|
+
switch (level) {
|
|
67
|
+
case 0: return 'TRACE';
|
|
68
|
+
case 1: return 'DEBUG';
|
|
69
|
+
case 2: return 'INFO ';
|
|
70
|
+
case 3: return 'WARN ';
|
|
71
|
+
case 4: return 'ERROR';
|
|
72
|
+
case 5: return 'FATAL';
|
|
73
|
+
default: return 'UNKNW';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
colorize(text, level) {
|
|
77
|
+
const colors = {
|
|
78
|
+
0: '\x1b[90m', // TRACE - Gray
|
|
79
|
+
1: '\x1b[36m', // DEBUG - Cyan
|
|
80
|
+
2: '\x1b[32m', // INFO - Green
|
|
81
|
+
3: '\x1b[33m', // WARN - Yellow
|
|
82
|
+
4: '\x1b[31m', // ERROR - Red
|
|
83
|
+
5: '\x1b[35m', // FATAL - Magenta
|
|
84
|
+
};
|
|
85
|
+
const color = colors[level] || '\x1b[0m';
|
|
86
|
+
const reset = '\x1b[0m';
|
|
87
|
+
return `${color}${text}${reset}`;
|
|
88
|
+
}
|
|
89
|
+
formatContext(context) {
|
|
90
|
+
const parts = [];
|
|
91
|
+
if (context.plugin) {
|
|
92
|
+
parts.push(this.config.colors
|
|
93
|
+
? `\x1b[35m[${context.plugin}]\x1b[0m`
|
|
94
|
+
: `[${context.plugin}]`);
|
|
95
|
+
}
|
|
96
|
+
if (context.module) {
|
|
97
|
+
parts.push(this.config.colors
|
|
98
|
+
? `\x1b[34m{${context.module}}\x1b[0m`
|
|
99
|
+
: `{${context.module}}`);
|
|
100
|
+
}
|
|
101
|
+
if (context.component) {
|
|
102
|
+
parts.push(this.config.colors
|
|
103
|
+
? `\x1b[36m<${context.component}>\x1b[0m`
|
|
104
|
+
: `<${context.component}>`);
|
|
105
|
+
}
|
|
106
|
+
if (context.operation) {
|
|
107
|
+
parts.push(this.config.colors
|
|
108
|
+
? `\x1b[90m(${context.operation})\x1b[0m`
|
|
109
|
+
: `(${context.operation})`);
|
|
110
|
+
}
|
|
111
|
+
return parts.join(' ');
|
|
112
|
+
}
|
|
113
|
+
formatMetadata(metadata) {
|
|
114
|
+
if (!metadata || Object.keys(metadata).length === 0) {
|
|
115
|
+
return '';
|
|
116
|
+
}
|
|
117
|
+
const { error, stack, tags, duration, ...rest } = metadata;
|
|
118
|
+
const parts = [];
|
|
119
|
+
// Duration
|
|
120
|
+
if (duration !== undefined) {
|
|
121
|
+
const color = this.config.colors ? '\x1b[33m' : '';
|
|
122
|
+
const reset = this.config.colors ? '\x1b[0m' : '';
|
|
123
|
+
parts.push(`${color}⏱ ${duration}ms${reset}`);
|
|
124
|
+
}
|
|
125
|
+
// Tags
|
|
126
|
+
if (tags && tags.length > 0) {
|
|
127
|
+
const tagString = tags.map(t => `#${t}`).join(' ');
|
|
128
|
+
const color = this.config.colors ? '\x1b[90m' : '';
|
|
129
|
+
const reset = this.config.colors ? '\x1b[0m' : '';
|
|
130
|
+
parts.push(`${color}${tagString}${reset}`);
|
|
131
|
+
}
|
|
132
|
+
// Other metadata
|
|
133
|
+
if (Object.keys(rest).length > 0) {
|
|
134
|
+
const color = this.config.colors ? '\x1b[90m' : '';
|
|
135
|
+
const reset = this.config.colors ? '\x1b[0m' : '';
|
|
136
|
+
parts.push(`${color}${JSON.stringify(rest)}${reset}`);
|
|
137
|
+
}
|
|
138
|
+
return parts.length > 0 ? parts.join(' ') : '';
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/formatters/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ILogFormatter, LogEntry } from '@hamak/logging-api';
|
|
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/formatters/json-formatter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAElE;;;;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,65 @@
|
|
|
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
|
+
this.config = config;
|
|
9
|
+
this.config = {
|
|
10
|
+
pretty: config.pretty ?? false,
|
|
11
|
+
includeStack: config.includeStack ?? true,
|
|
12
|
+
...config,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
format(entry) {
|
|
16
|
+
const logObject = this.toObject(entry);
|
|
17
|
+
return this.config.pretty
|
|
18
|
+
? JSON.stringify(logObject, null, 2)
|
|
19
|
+
: JSON.stringify(logObject);
|
|
20
|
+
}
|
|
21
|
+
formatBatch(entries) {
|
|
22
|
+
const logObjects = entries.map(e => this.toObject(e));
|
|
23
|
+
return this.config.pretty
|
|
24
|
+
? JSON.stringify(logObjects, null, 2)
|
|
25
|
+
: JSON.stringify(logObjects);
|
|
26
|
+
}
|
|
27
|
+
toObject(entry) {
|
|
28
|
+
const obj = {
|
|
29
|
+
timestamp: entry.timestamp,
|
|
30
|
+
level: this.getLevelName(entry.level),
|
|
31
|
+
message: entry.message,
|
|
32
|
+
};
|
|
33
|
+
// Add context
|
|
34
|
+
if (entry.context && Object.keys(entry.context).length > 0) {
|
|
35
|
+
obj.context = entry.context;
|
|
36
|
+
}
|
|
37
|
+
// Add metadata
|
|
38
|
+
if (entry.metadata) {
|
|
39
|
+
const { error, stack, ...rest } = entry.metadata;
|
|
40
|
+
if (Object.keys(rest).length > 0) {
|
|
41
|
+
obj.metadata = rest;
|
|
42
|
+
}
|
|
43
|
+
// Handle error separately
|
|
44
|
+
if (error) {
|
|
45
|
+
obj.error = {
|
|
46
|
+
name: error.name,
|
|
47
|
+
message: error.message,
|
|
48
|
+
...(this.config.includeStack && stack ? { stack } : {}),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return obj;
|
|
53
|
+
}
|
|
54
|
+
getLevelName(level) {
|
|
55
|
+
switch (level) {
|
|
56
|
+
case 0: return 'TRACE';
|
|
57
|
+
case 1: return 'DEBUG';
|
|
58
|
+
case 2: return 'INFO';
|
|
59
|
+
case 3: return 'WARN';
|
|
60
|
+
case 4: return 'ERROR';
|
|
61
|
+
case 5: return 'FATAL';
|
|
62
|
+
default: return 'UNKNOWN';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -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.js';
|
|
10
|
+
export * from './transports/index.js';
|
|
11
|
+
export * from './formatters/index.js';
|
|
12
|
+
export * from './plugin/index.js';
|
|
13
|
+
export * from './utils/index.js';
|
|
14
|
+
export type { ILogger, ILogTransport, ILogFormatter, ILogManager, LogLevel, LogEntry, LogContext, LogMetadata, TransportConfig, LogManagerConfig, ConsoleTransportConfig, RemoteTransportConfig, } from '@hamak/logging-api';
|
|
15
|
+
export { LOG_MANAGER_TOKEN, LOGGER_TOKEN, LOG_CONFIG_TOKEN, } from '@hamak/logging-api';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,cAAc,iBAAiB,CAAC;AAGhC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,kBAAkB,CAAC;AAGjC,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,oBAAoB,CAAC;AAE5B,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,GACjB,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -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.js';
|
|
11
|
+
// Export transports
|
|
12
|
+
export * from './transports/index.js';
|
|
13
|
+
// Export formatters
|
|
14
|
+
export * from './formatters/index.js';
|
|
15
|
+
// Export plugin factory
|
|
16
|
+
export * from './plugin/index.js';
|
|
17
|
+
// Export utilities
|
|
18
|
+
export * from './utils/index.js';
|
|
19
|
+
export { LOG_MANAGER_TOKEN, LOGGER_TOKEN, LOG_CONFIG_TOKEN, } from '@hamak/logging-api';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './logging-plugin-factory.js';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { PluginModule } from '@hamak/microkernel-spi';
|
|
2
|
+
import type { LogManagerConfig } from '@hamak/logging-api';
|
|
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/plugin/logging-plugin-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAyB,MAAM,wBAAwB,CAAC;AAElF,OAAO,KAAK,EAAW,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAQpE;;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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { LOG_MANAGER_TOKEN, LOGGER_TOKEN, LOG_CONFIG_TOKEN } from '@hamak/logging-api';
|
|
2
|
+
import { LogManager } from '../core/log-manager.js';
|
|
3
|
+
import { ConsoleTransport } from '../transports/console-transport.js';
|
|
4
|
+
import { DevFormatter } from '../formatters/dev-formatter.js';
|
|
5
|
+
import { JsonFormatter } from '../formatters/json-formatter.js';
|
|
6
|
+
import { ConsoleInterceptor } from '../utils/console-interceptor.js';
|
|
7
|
+
/**
|
|
8
|
+
* Create a logging plugin for the microkernel
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { createLoggingPlugin } from '@hamak/logging-impl';
|
|
13
|
+
*
|
|
14
|
+
* const loggingPlugin = createLoggingPlugin({
|
|
15
|
+
* globalLevel: LogLevel.DEBUG,
|
|
16
|
+
* pluginLevels: {
|
|
17
|
+
* 'my-plugin': LogLevel.TRACE
|
|
18
|
+
* }
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* const host = createHost({
|
|
22
|
+
* plugins: [loggingPlugin, myPlugin]
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function createLoggingPlugin(config = {}) {
|
|
27
|
+
let logManager;
|
|
28
|
+
let rootLogger;
|
|
29
|
+
let consoleInterceptor;
|
|
30
|
+
// Determine environment
|
|
31
|
+
const isDevelopment = typeof process !== 'undefined'
|
|
32
|
+
? process.env.NODE_ENV === 'development'
|
|
33
|
+
: true;
|
|
34
|
+
const defaultConfig = {
|
|
35
|
+
globalLevel: isDevelopment ? 1 : 2, // DEBUG in dev, INFO in prod
|
|
36
|
+
bufferSize: 1000,
|
|
37
|
+
flushInterval: 5000,
|
|
38
|
+
devFormatter: isDevelopment,
|
|
39
|
+
interceptConsole: true, // Enabled by default
|
|
40
|
+
pluginLevels: {},
|
|
41
|
+
moduleLevels: {},
|
|
42
|
+
...config,
|
|
43
|
+
};
|
|
44
|
+
return {
|
|
45
|
+
async initialize(ctx) {
|
|
46
|
+
// Create log manager
|
|
47
|
+
logManager = new LogManager(defaultConfig);
|
|
48
|
+
rootLogger = logManager.createLogger({ plugin: 'logging', module: 'plugin' });
|
|
49
|
+
// Register console transport
|
|
50
|
+
const formatter = defaultConfig.devFormatter
|
|
51
|
+
? new DevFormatter({
|
|
52
|
+
colors: true,
|
|
53
|
+
emojis: true,
|
|
54
|
+
timestamps: true,
|
|
55
|
+
showContext: true,
|
|
56
|
+
})
|
|
57
|
+
: new JsonFormatter({ pretty: isDevelopment });
|
|
58
|
+
logManager.registerTransport(new ConsoleTransport(formatter), {
|
|
59
|
+
id: 'console',
|
|
60
|
+
enabled: true,
|
|
61
|
+
minLevel: defaultConfig.globalLevel,
|
|
62
|
+
});
|
|
63
|
+
// Register services via DI
|
|
64
|
+
ctx.provide({ provide: LOG_MANAGER_TOKEN, useValue: logManager });
|
|
65
|
+
ctx.provide({ provide: LOG_CONFIG_TOKEN, useValue: defaultConfig });
|
|
66
|
+
// Provide logger factory
|
|
67
|
+
ctx.provide({
|
|
68
|
+
provide: LOGGER_TOKEN,
|
|
69
|
+
useFactory: (pluginName) => {
|
|
70
|
+
return logManager.createLogger({ plugin: pluginName });
|
|
71
|
+
},
|
|
72
|
+
deps: [],
|
|
73
|
+
});
|
|
74
|
+
rootLogger.info('Logging plugin initialized', {
|
|
75
|
+
globalLevel: defaultConfig.globalLevel,
|
|
76
|
+
formatter: defaultConfig.devFormatter ? 'dev' : 'json',
|
|
77
|
+
tags: ['initialization'],
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
async activate(ctx) {
|
|
81
|
+
// Bridge microkernel events to logging
|
|
82
|
+
ctx.hooks.on('plugin:error', ({ plugin, error }) => {
|
|
83
|
+
const logger = logManager.createLogger({ plugin });
|
|
84
|
+
logger.error('Plugin error', error);
|
|
85
|
+
});
|
|
86
|
+
ctx.hooks.on('host:activated', () => {
|
|
87
|
+
rootLogger.info('Microkernel host activated', { tags: ['lifecycle'] });
|
|
88
|
+
});
|
|
89
|
+
// Intercept console methods if enabled
|
|
90
|
+
if (defaultConfig.interceptConsole) {
|
|
91
|
+
consoleInterceptor = new ConsoleInterceptor(logManager);
|
|
92
|
+
consoleInterceptor.intercept();
|
|
93
|
+
rootLogger.debug('Console interception enabled', { tags: ['console'] });
|
|
94
|
+
}
|
|
95
|
+
// Emit logging ready event
|
|
96
|
+
ctx.hooks.emit('logging:ready', { logManager });
|
|
97
|
+
rootLogger.info('Logging plugin activated', {
|
|
98
|
+
tags: ['lifecycle'],
|
|
99
|
+
interceptConsole: defaultConfig.interceptConsole,
|
|
100
|
+
});
|
|
101
|
+
},
|
|
102
|
+
async deactivate() {
|
|
103
|
+
rootLogger.info('Logging plugin deactivating', { tags: ['lifecycle'] });
|
|
104
|
+
// Restore original console methods
|
|
105
|
+
if (consoleInterceptor) {
|
|
106
|
+
consoleInterceptor.restore();
|
|
107
|
+
rootLogger.debug('Console interception disabled', { tags: ['console'] });
|
|
108
|
+
}
|
|
109
|
+
await logManager.destroy();
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ILogTransport, ILogFormatter, LogEntry } from '@hamak/logging-api';
|
|
2
|
+
/**
|
|
3
|
+
* Console transport
|
|
4
|
+
*
|
|
5
|
+
* Outputs logs to the browser console or Node.js console.
|
|
6
|
+
* Supports formatting via pluggable formatters.
|
|
7
|
+
*/
|
|
8
|
+
export declare class ConsoleTransport implements ILogTransport {
|
|
9
|
+
private formatter;
|
|
10
|
+
readonly id = "console";
|
|
11
|
+
readonly name = "Console Transport";
|
|
12
|
+
constructor(formatter: ILogFormatter);
|
|
13
|
+
log(entry: LogEntry): void;
|
|
14
|
+
onError(error: Error): void;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=console-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console-transport.d.ts","sourceRoot":"","sources":["../../src/transports/console-transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEjF;;;;;GAKG;AACH,qBAAa,gBAAiB,YAAW,aAAa;IAIxC,OAAO,CAAC,SAAS;IAH7B,QAAQ,CAAC,EAAE,aAAa;IACxB,QAAQ,CAAC,IAAI,uBAAuB;gBAEhB,SAAS,EAAE,aAAa;IAE5C,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IA8B1B,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;CAG5B"}
|