@nx-ddd/logging 19.50.0 → 19.80.0
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/fesm2022/nx-ddd-logging-base.mjs +0 -51
- package/fesm2022/nx-ddd-logging-base.mjs.map +1 -1
- package/fesm2022/nx-ddd-logging-console.mjs +35 -13
- package/fesm2022/nx-ddd-logging-console.mjs.map +1 -1
- package/fesm2022/nx-ddd-logging-factory.mjs +31 -0
- package/fesm2022/nx-ddd-logging-factory.mjs.map +1 -0
- package/fesm2022/nx-ddd-logging-file.mjs +20 -25
- package/fesm2022/nx-ddd-logging-file.mjs.map +1 -1
- package/fesm2022/nx-ddd-logging-format.mjs +59 -0
- package/fesm2022/nx-ddd-logging-format.mjs.map +1 -0
- package/fesm2022/nx-ddd-logging-http.mjs +109 -0
- package/fesm2022/nx-ddd-logging-http.mjs.map +1 -0
- package/fesm2022/nx-ddd-logging-tee.mjs +1 -22
- package/fesm2022/nx-ddd-logging-tee.mjs.map +1 -1
- package/fesm2022/nx-ddd-logging.mjs +18 -65
- package/fesm2022/nx-ddd-logging.mjs.map +1 -1
- package/package.json +13 -1
- package/types/nx-ddd-logging-base.d.ts +1 -92
- package/types/nx-ddd-logging-base.d.ts.map +1 -1
- package/types/nx-ddd-logging-console.d.ts +7 -8
- package/types/nx-ddd-logging-console.d.ts.map +1 -1
- package/types/nx-ddd-logging-factory.d.ts +15 -0
- package/types/nx-ddd-logging-factory.d.ts.map +1 -0
- package/types/nx-ddd-logging-file.d.ts +5 -12
- package/types/nx-ddd-logging-file.d.ts.map +1 -1
- package/types/nx-ddd-logging-format.d.ts +23 -0
- package/types/nx-ddd-logging-format.d.ts.map +1 -0
- package/types/nx-ddd-logging-http.d.ts +51 -0
- package/types/nx-ddd-logging-http.d.ts.map +1 -0
- package/types/nx-ddd-logging-tee.d.ts +0 -17
- package/types/nx-ddd-logging-tee.d.ts.map +1 -1
- package/types/nx-ddd-logging.d.ts +8 -95
- package/types/nx-ddd-logging.d.ts.map +1 -1
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { InjectionToken, Injectable } from '@angular/core';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* LoggingService interfaces
|
|
6
|
-
*
|
|
7
|
-
* Provides structured logging with different log levels and file output
|
|
8
|
-
*/
|
|
9
4
|
var LogLevel;
|
|
10
5
|
(function (LogLevel) {
|
|
11
6
|
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
|
|
@@ -15,12 +10,8 @@ var LogLevel;
|
|
|
15
10
|
LogLevel[LogLevel["FATAL"] = 4] = "FATAL";
|
|
16
11
|
})(LogLevel || (LogLevel = {}));
|
|
17
12
|
|
|
18
|
-
/**
|
|
19
|
-
* Base Logger class for multi-provider logging system
|
|
20
|
-
*/
|
|
21
13
|
const LOGGER = new InjectionToken('Logger');
|
|
22
14
|
class BaseLogger {
|
|
23
|
-
// Convenience methods
|
|
24
15
|
debug(message, context) {
|
|
25
16
|
this.log(LogLevel.DEBUG, message, context);
|
|
26
17
|
}
|
|
@@ -50,36 +41,11 @@ function provideLogger(useFactory) {
|
|
|
50
41
|
};
|
|
51
42
|
}
|
|
52
43
|
|
|
53
|
-
/**
|
|
54
|
-
* LogFilter - Simple function-based log filtering
|
|
55
|
-
*/
|
|
56
44
|
const LOG_FILTER = new InjectionToken('LogFilter');
|
|
57
45
|
|
|
58
|
-
/**
|
|
59
|
-
* Provider functions for log filtering
|
|
60
|
-
*/
|
|
61
|
-
/**
|
|
62
|
-
* Provide a log filter function
|
|
63
|
-
*
|
|
64
|
-
* @example
|
|
65
|
-
* // Filter by log level
|
|
66
|
-
* provideLogFilter((level) => level >= LogLevel.WARN)
|
|
67
|
-
*
|
|
68
|
-
* @example
|
|
69
|
-
* // Filter by component
|
|
70
|
-
* provideLogFilter((level, context) => context?.component?.startsWith('My'))
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* // Allow all logs
|
|
74
|
-
* provideLogFilter(() => true)
|
|
75
|
-
*/
|
|
76
46
|
function provideLogFilter(filter) {
|
|
77
47
|
return { provide: LOG_FILTER, useValue: filter };
|
|
78
48
|
}
|
|
79
|
-
/**
|
|
80
|
-
* Provide a log filter with explicit configuration
|
|
81
|
-
* @param config - Filter configuration (minLevel defaults to WARN)
|
|
82
|
-
*/
|
|
83
49
|
function provideLogFilterWithConfig(config) {
|
|
84
50
|
const minLevel = config?.minLevel ?? LogLevel.WARN;
|
|
85
51
|
const componentRegex = config?.componentPattern ? new RegExp(config.componentPattern) : null;
|
|
@@ -92,23 +58,6 @@ function provideLogFilterWithConfig(config) {
|
|
|
92
58
|
return true;
|
|
93
59
|
});
|
|
94
60
|
}
|
|
95
|
-
/**
|
|
96
|
-
* @deprecated Use provideLogFilterWithConfig() instead.
|
|
97
|
-
* This function directly accesses process.env which violates the rule
|
|
98
|
-
* that packages should not access environment variables directly.
|
|
99
|
-
*
|
|
100
|
-
* Migration example:
|
|
101
|
-
* ```typescript
|
|
102
|
-
* // Before (in packages)
|
|
103
|
-
* provideLogFilterFromEnv()
|
|
104
|
-
*
|
|
105
|
-
* // After (in application layer)
|
|
106
|
-
* provideLogFilterWithConfig({
|
|
107
|
-
* minLevel: process.env['LOG_LEVEL'] ? LogLevel[process.env['LOG_LEVEL'].toUpperCase()] : undefined,
|
|
108
|
-
* componentPattern: process.env['LOG_COMPONENTS']
|
|
109
|
-
* })
|
|
110
|
-
* ```
|
|
111
|
-
*/
|
|
112
61
|
function provideLogFilterFromEnv() {
|
|
113
62
|
console.warn('[DEPRECATED] provideLogFilterFromEnv() is deprecated. Use provideLogFilterWithConfig() instead.');
|
|
114
63
|
return provideLogFilterWithConfig();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nx-ddd-logging-base.mjs","sources":["../../../../../packages/@nx-ddd/logging/src/lib/base/interfaces.ts","../../../../../packages/@nx-ddd/logging/src/lib/base/base.logger.ts","../../../../../packages/@nx-ddd/logging/src/lib/base/log-filter.ts","../../../../../packages/@nx-ddd/logging/src/lib/base/providers.ts","../../../../../packages/@nx-ddd/logging/src/lib/base/nx-ddd-logging-base.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"nx-ddd-logging-base.mjs","sources":["../../../../../packages/@nx-ddd/logging/src/lib/base/interfaces.ts","../../../../../packages/@nx-ddd/logging/src/lib/base/base.logger.ts","../../../../../packages/@nx-ddd/logging/src/lib/base/log-filter.ts","../../../../../packages/@nx-ddd/logging/src/lib/base/providers.ts","../../../../../packages/@nx-ddd/logging/src/lib/base/nx-ddd-logging-base.ts"],"sourcesContent":["\n\nexport enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3,\n FATAL = 4,\n}\n\nexport interface LogContext {\n component?: string;\n package?: string;\n sessionId?: string;\n clientId?: string;\n [key: string]: any;\n}\n\nexport interface ILoggingService {\n \n debug(message: string, context?: LogContext): void;\n\n \n info(message: string, context?: LogContext): void;\n\n \n warn(message: string, context?: LogContext): void;\n\n \n error(message: string, error?: Error, context?: LogContext): void;\n\n \n fatal(message: string, error?: Error, context?: LogContext): void;\n\n \n setLogLevel(level: LogLevel): void;\n\n \n setComponent(component: string): void;\n\n \n close(): void;\n}\n","\n\nimport { Injectable, InjectionToken, Provider } from '@angular/core';\nimport { LogLevel, LogContext } from './interfaces';\n\nexport const LOGGER = new InjectionToken<BaseLogger>('Logger');\n\n@Injectable()\nexport abstract class BaseLogger {\n \n abstract log(\n level: LogLevel,\n message: string,\n context?: LogContext,\n error?: Error\n ): void;\n\n \n abstract close(): void;\n\n \n debug(message: string, context?: LogContext): void {\n this.log(LogLevel.DEBUG, message, context);\n }\n\n info(message: string, context?: LogContext): void {\n this.log(LogLevel.INFO, message, context);\n }\n\n warn(message: string, context?: LogContext): void {\n this.log(LogLevel.WARN, message, context);\n }\n\n error(message: string, error?: Error, context?: LogContext): void {\n this.log(LogLevel.ERROR, message, context, error);\n }\n\n fatal(message: string, error?: Error, context?: LogContext): void {\n this.log(LogLevel.FATAL, message, context, error);\n }\n}\n\nexport function provideLogger(useFactory: () => BaseLogger): Provider {\n return {\n provide: LOGGER,\n multi: true,\n useFactory,\n };\n}\n","\n\nimport { InjectionToken } from '@angular/core';\nimport { LogLevel, LogContext } from './interfaces';\n\n\nexport type LogFilterFn = (level: LogLevel, context?: LogContext) => boolean;\n\nexport const LOG_FILTER = new InjectionToken<LogFilterFn>('LogFilter');\n","\n\nimport { Provider } from '@angular/core';\nimport { LogLevel } from './interfaces';\nimport { LOG_FILTER, LogFilterFn } from './log-filter';\n\n\nexport function provideLogFilter(filter: LogFilterFn): Provider {\n return { provide: LOG_FILTER, useValue: filter };\n}\n\n\nexport interface LogFilterConfig {\n minLevel?: LogLevel;\n componentPattern?: string;\n}\n\n\nexport function provideLogFilterWithConfig(config?: LogFilterConfig): Provider {\n const minLevel = config?.minLevel ?? LogLevel.WARN;\n const componentRegex = config?.componentPattern ? new RegExp(config.componentPattern) : null;\n\n return provideLogFilter((level, context) => {\n if (level < minLevel) return false;\n if (componentRegex && context?.component && !componentRegex.test(context.component)) {\n return false;\n }\n return true;\n });\n}\n\n\nexport function provideLogFilterFromEnv(): Provider {\n console.warn('[DEPRECATED] provideLogFilterFromEnv() is deprecated. Use provideLogFilterWithConfig() instead.');\n return provideLogFilterWithConfig();\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,33 +1,55 @@
|
|
|
1
1
|
import { BaseLogger, LogLevel, LOGGER } from '@nx-ddd/logging/base';
|
|
2
|
+
import { buildLogRecord, formatText } from '@nx-ddd/logging/format';
|
|
2
3
|
|
|
3
|
-
/**
|
|
4
|
-
* ConsoleLogger implementation for multi-provider logging
|
|
5
|
-
*/
|
|
6
4
|
class ConsoleLogger extends BaseLogger {
|
|
7
5
|
minLevel;
|
|
6
|
+
useStderr;
|
|
7
|
+
format;
|
|
8
|
+
color;
|
|
8
9
|
constructor(options) {
|
|
9
10
|
super();
|
|
10
11
|
this.minLevel = options?.minLevel ?? LogLevel.WARN;
|
|
12
|
+
this.useStderr = options?.useStderr ?? false;
|
|
13
|
+
this.format = options?.format ?? 'legacy';
|
|
14
|
+
this.color = options?.color;
|
|
11
15
|
}
|
|
12
16
|
log(level, message, context, error) {
|
|
13
|
-
// Filter by log level - only output logs at or above minLevel
|
|
14
17
|
if (level < this.minLevel)
|
|
15
18
|
return;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
if (this.format === 'pretty') {
|
|
20
|
+
const record = buildLogRecord(level, message, context, error);
|
|
21
|
+
const line = formatText(record, { color: this.color ?? this.detectTty() });
|
|
22
|
+
if (this.useStderr) {
|
|
23
|
+
console.error(line);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
console.log(line);
|
|
27
|
+
}
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const { component, package: _pkg, ...restCtx } = context ?? {};
|
|
31
|
+
const source = component != null ? `[${component}] ` : '';
|
|
32
|
+
const args = [`[${LogLevel[level]}] ${source}${message}`];
|
|
33
|
+
if (Object.keys(restCtx).length > 0)
|
|
34
|
+
args.push(restCtx);
|
|
19
35
|
if (error != null)
|
|
20
36
|
args.push(error);
|
|
21
|
-
|
|
37
|
+
if (this.useStderr) {
|
|
38
|
+
console.error(...args);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
console.log(...args);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
detectTty() {
|
|
45
|
+
const proc = globalThis.process;
|
|
46
|
+
const stream = this.useStderr ? proc?.stderr : proc?.stdout;
|
|
47
|
+
return Boolean(stream?.isTTY);
|
|
22
48
|
}
|
|
23
49
|
close() {
|
|
24
|
-
|
|
50
|
+
void 0;
|
|
25
51
|
}
|
|
26
52
|
}
|
|
27
|
-
/**
|
|
28
|
-
* Provide ConsoleLogger with optional configuration
|
|
29
|
-
* @param options - Logger options (minLevel defaults to WARN if not specified)
|
|
30
|
-
*/
|
|
31
53
|
function provideConsoleLogger(options) {
|
|
32
54
|
return {
|
|
33
55
|
provide: LOGGER,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nx-ddd-logging-console.mjs","sources":["../../../../../packages/@nx-ddd/logging/src/lib/console/console.logger.ts","../../../../../packages/@nx-ddd/logging/src/lib/console/nx-ddd-logging-console.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"nx-ddd-logging-console.mjs","sources":["../../../../../packages/@nx-ddd/logging/src/lib/console/console.logger.ts","../../../../../packages/@nx-ddd/logging/src/lib/console/nx-ddd-logging-console.ts"],"sourcesContent":["\n\nimport { Provider } from '@angular/core';\nimport { BaseLogger, LogLevel, LogContext, LOGGER } from '@nx-ddd/logging/base';\nimport { buildLogRecord, formatText } from '@nx-ddd/logging/format';\n\nexport interface ConsoleLoggerOptions {\n minLevel?: LogLevel;\n componentFilter?: string; \n \n useStderr?: boolean;\n format?: 'legacy' | 'pretty';\n color?: boolean;\n}\n\nexport class ConsoleLogger extends BaseLogger {\n private readonly minLevel: LogLevel;\n private readonly useStderr: boolean;\n private readonly format: 'legacy' | 'pretty';\n private readonly color?: boolean;\n\n constructor(options?: ConsoleLoggerOptions) {\n super();\n this.minLevel = options?.minLevel ?? LogLevel.WARN;\n this.useStderr = options?.useStderr ?? false;\n this.format = options?.format ?? 'legacy';\n this.color = options?.color;\n }\n\n log(level: LogLevel, message: string, context?: LogContext, error?: Error): void {\n \n if (level < this.minLevel) return;\n\n if (this.format === 'pretty') {\n const record = buildLogRecord(level, message, context, error);\n const line = formatText(record, { color: this.color ?? this.detectTty() });\n if (this.useStderr) {\n console.error(line);\n } else {\n console.log(line);\n }\n return;\n }\n\n const { component, package: _pkg, ...restCtx } = context ?? {};\n const source = component != null ? `[${component}] ` : '';\n const args: any[] = [`[${LogLevel[level]}] ${source}${message}`];\n if (Object.keys(restCtx).length > 0) args.push(restCtx);\n if (error != null) args.push(error);\n if (this.useStderr) {\n console.error(...args);\n } else {\n console.log(...args);\n }\n }\n\n private detectTty(): boolean {\n const proc = (globalThis as { process?: { stderr?: { isTTY?: boolean }; stdout?: { isTTY?: boolean } } }).process;\n const stream = this.useStderr ? proc?.stderr : proc?.stdout;\n return Boolean(stream?.isTTY);\n }\n\n close(): void {\n void 0;\n }\n}\n\n\nexport function provideConsoleLogger(options?: ConsoleLoggerOptions): Provider {\n return {\n provide: LOGGER,\n multi: true,\n useFactory: () => new ConsoleLogger(options)\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAeM,MAAO,aAAc,SAAQ,UAAU,CAAA;AAC1B,IAAA,QAAQ;AACR,IAAA,SAAS;AACT,IAAA,MAAM;AACN,IAAA,KAAK;AAEtB,IAAA,WAAA,CAAY,OAA8B,EAAA;AACxC,QAAA,KAAK,EAAE;QACP,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,QAAQ,CAAC,IAAI;QAClD,IAAI,CAAC,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,KAAK;QAC5C,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,QAAQ;AACzC,QAAA,IAAI,CAAC,KAAK,GAAG,OAAO,EAAE,KAAK;IAC7B;AAEA,IAAA,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,OAAoB,EAAE,KAAa,EAAA;AAEvE,QAAA,IAAI,KAAK,GAAG,IAAI,CAAC,QAAQ;YAAE;AAE3B,QAAA,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE;AAC5B,YAAA,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC;AAC7D,YAAA,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;AAC1E,YAAA,IAAI,IAAI,CAAC,SAAS,EAAE;AAClB,gBAAA,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;YACrB;iBAAO;AACL,gBAAA,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YACnB;YACA;QACF;AAEA,QAAA,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,GAAG,OAAO,IAAI,EAAE;AAC9D,QAAA,MAAM,MAAM,GAAG,SAAS,IAAI,IAAI,GAAG,CAAA,CAAA,EAAI,SAAS,CAAA,EAAA,CAAI,GAAG,EAAE;AACzD,QAAA,MAAM,IAAI,GAAU,CAAC,CAAA,CAAA,EAAI,QAAQ,CAAC,KAAK,CAAC,CAAA,EAAA,EAAK,MAAM,CAAA,EAAG,OAAO,CAAA,CAAE,CAAC;QAChE,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC;AAAE,YAAA,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;QACvD,IAAI,KAAK,IAAI,IAAI;AAAE,YAAA,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;AACnC,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;AAClB,YAAA,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;QACxB;aAAO;AACL,YAAA,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;QACtB;IACF;IAEQ,SAAS,GAAA;AACf,QAAA,MAAM,IAAI,GAAI,UAA2F,CAAC,OAAO;AACjH,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM;AAC3D,QAAA,OAAO,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC;IAC/B;IAEA,KAAK,GAAA;AACH,QAAA,KAAK,CAAC;IACR;AACD;AAGK,SAAU,oBAAoB,CAAC,OAA8B,EAAA;IACjE,OAAO;AACL,QAAA,OAAO,EAAE,MAAM;AACf,QAAA,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,MAAM,IAAI,aAAa,CAAC,OAAO;KAC5C;AACH;;AC1EA;;AAEG;;;;"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { InjectionToken, inject } from '@angular/core';
|
|
2
|
+
import { getLogger, LoggingService } from '@nx-ddd/logging';
|
|
3
|
+
|
|
4
|
+
const LOG_SCOPE = new InjectionToken('LogScope');
|
|
5
|
+
function provideLogScope(segment) {
|
|
6
|
+
return {
|
|
7
|
+
provide: LOG_SCOPE,
|
|
8
|
+
useFactory: () => {
|
|
9
|
+
const parent = inject(LOG_SCOPE, { optional: true, skipSelf: true });
|
|
10
|
+
return parent != null ? `${parent}.${segment}` : segment;
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function loggerFactory(pkg) {
|
|
16
|
+
return {
|
|
17
|
+
injectLogger: (component) => {
|
|
18
|
+
const scope = inject(LOG_SCOPE, { optional: true });
|
|
19
|
+
const name = scope != null ? `${scope}.${component}` : component;
|
|
20
|
+
return inject(LoggingService).getLogger(name, { package: pkg });
|
|
21
|
+
},
|
|
22
|
+
getLogger: (component) => getLogger(component, { package: pkg }),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Generated bundle index. Do not edit.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
export { LOG_SCOPE, loggerFactory, provideLogScope };
|
|
31
|
+
//# sourceMappingURL=nx-ddd-logging-factory.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nx-ddd-logging-factory.mjs","sources":["../../../../../packages/@nx-ddd/logging/src/lib/factory/log-scope.ts","../../../../../packages/@nx-ddd/logging/src/lib/factory/logger-factory.ts","../../../../../packages/@nx-ddd/logging/src/lib/factory/nx-ddd-logging-factory.ts"],"sourcesContent":["import { inject, InjectionToken, Provider } from '@angular/core';\n\nexport const LOG_SCOPE = new InjectionToken<string>('LogScope');\n\nexport function provideLogScope(segment: string): Provider {\n return {\n provide: LOG_SCOPE,\n useFactory: () => {\n const parent = inject(LOG_SCOPE, { optional: true, skipSelf: true });\n return parent != null ? `${parent}.${segment}` : segment;\n },\n };\n}\n","import { inject } from '@angular/core';\nimport { getLogger as getGlobalLogger, Logger, LoggingService } from '@nx-ddd/logging';\nimport { LOG_SCOPE } from './log-scope';\n\nexport interface PackageLoggers {\n injectLogger(component: string): Logger;\n getLogger(component: string): Logger;\n}\n\nexport function loggerFactory(pkg: string): PackageLoggers {\n return {\n injectLogger: (component: string): Logger => {\n const scope = inject(LOG_SCOPE, { optional: true });\n const name = scope != null ? `${scope}.${component}` : component;\n return inject(LoggingService).getLogger(name, { package: pkg });\n },\n getLogger: (component: string): Logger => getGlobalLogger(component, { package: pkg }),\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["getGlobalLogger"],"mappings":";;;MAEa,SAAS,GAAG,IAAI,cAAc,CAAS,UAAU;AAExD,SAAU,eAAe,CAAC,OAAe,EAAA;IAC7C,OAAO;AACL,QAAA,OAAO,EAAE,SAAS;QAClB,UAAU,EAAE,MAAK;AACf,YAAA,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACpE,YAAA,OAAO,MAAM,IAAI,IAAI,GAAG,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,OAAO,CAAA,CAAE,GAAG,OAAO;QAC1D,CAAC;KACF;AACH;;ACHM,SAAU,aAAa,CAAC,GAAW,EAAA;IACvC,OAAO;AACL,QAAA,YAAY,EAAE,CAAC,SAAiB,KAAY;AAC1C,YAAA,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACnD,YAAA,MAAM,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,CAAA,EAAG,KAAK,IAAI,SAAS,CAAA,CAAE,GAAG,SAAS;AAChE,YAAA,OAAO,MAAM,CAAC,cAAc,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QACjE,CAAC;AACD,QAAA,SAAS,EAAE,CAAC,SAAiB,KAAaA,SAAe,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;KACvF;AACH;;AClBA;;AAEG;;;;"}
|
|
@@ -2,28 +2,26 @@ import * as fs from 'fs';
|
|
|
2
2
|
import * as os from 'os';
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import { BaseLogger, LogLevel, LOGGER } from '@nx-ddd/logging/base';
|
|
5
|
+
import { formatJson, buildLogRecord } from '@nx-ddd/logging/format';
|
|
5
6
|
|
|
6
|
-
/**
|
|
7
|
-
* FileLogger implementation for multi-provider logging
|
|
8
|
-
*/
|
|
9
7
|
class FileLogger extends BaseLogger {
|
|
10
8
|
writeStream = null;
|
|
11
9
|
minLevel;
|
|
12
10
|
componentFilter;
|
|
13
11
|
startTime;
|
|
12
|
+
format;
|
|
14
13
|
constructor(options) {
|
|
15
14
|
super();
|
|
16
|
-
this.minLevel = options?.minLevel ?? LogLevel.DEBUG;
|
|
15
|
+
this.minLevel = options?.minLevel ?? LogLevel.DEBUG;
|
|
17
16
|
this.componentFilter = options?.componentFilter
|
|
18
17
|
? new RegExp(options.componentFilter)
|
|
19
18
|
: undefined;
|
|
19
|
+
this.format = options?.format ?? 'text';
|
|
20
20
|
this.startTime = Date.now();
|
|
21
|
-
// Determine log file path
|
|
22
21
|
const logDir = options?.logDir || join(os.homedir(), '.machina', 'logs');
|
|
23
|
-
const date = new Date().toISOString().split('T')[0];
|
|
22
|
+
const date = new Date().toISOString().split('T')[0];
|
|
24
23
|
const component = options?.component || 'app';
|
|
25
24
|
const logFile = options?.filePath || join(logDir, `${component}-${date}.log`);
|
|
26
|
-
// Create log directory
|
|
27
25
|
try {
|
|
28
26
|
const dir = options?.filePath ? join(logFile, '..') : logDir;
|
|
29
27
|
fs.mkdirSync(dir, { recursive: true });
|
|
@@ -31,7 +29,6 @@ class FileLogger extends BaseLogger {
|
|
|
31
29
|
catch (error) {
|
|
32
30
|
console.error(`[FileLogger] Failed to create log directory: ${error}`);
|
|
33
31
|
}
|
|
34
|
-
// Open log file
|
|
35
32
|
try {
|
|
36
33
|
this.writeStream = fs.createWriteStream(logFile, { flags: 'a' });
|
|
37
34
|
}
|
|
@@ -40,25 +37,27 @@ class FileLogger extends BaseLogger {
|
|
|
40
37
|
}
|
|
41
38
|
}
|
|
42
39
|
log(level, message, context, error) {
|
|
43
|
-
// Level filtering
|
|
44
40
|
if (level < this.minLevel)
|
|
45
41
|
return;
|
|
46
|
-
// Component filtering
|
|
47
42
|
if (this.componentFilter && context?.component) {
|
|
48
43
|
if (!this.componentFilter.test(context.component))
|
|
49
44
|
return;
|
|
50
45
|
}
|
|
51
46
|
if (!this.writeStream)
|
|
52
47
|
return;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
48
|
+
let logMessage;
|
|
49
|
+
if (this.format === 'json') {
|
|
50
|
+
logMessage = formatJson(buildLogRecord(level, message, context, error)) + '\n';
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
const timestamp = new Date().toISOString();
|
|
54
|
+
const elapsed = ((Date.now() - this.startTime) / 1000).toFixed(2);
|
|
55
|
+
const levelStr = LogLevel[level];
|
|
56
|
+
const component = context?.component || 'unknown';
|
|
57
|
+
const contextStr = context ? JSON.stringify(context) : '';
|
|
58
|
+
const errorStr = error ? `\n Error: ${error.message}\n Stack: ${error.stack}` : '';
|
|
59
|
+
logMessage = `[${timestamp}] [+${elapsed}s] [${levelStr}] [${component}] ${message}${contextStr ? ' ' + contextStr : ''}${errorStr}\n`;
|
|
60
|
+
}
|
|
62
61
|
this.writeStream.write(logMessage);
|
|
63
62
|
}
|
|
64
63
|
close() {
|
|
@@ -68,17 +67,12 @@ class FileLogger extends BaseLogger {
|
|
|
68
67
|
}
|
|
69
68
|
}
|
|
70
69
|
}
|
|
71
|
-
/**
|
|
72
|
-
* Provide FileLogger with optional configuration
|
|
73
|
-
* @param options - Logger options (minLevel defaults to DEBUG if not specified)
|
|
74
|
-
*/
|
|
75
70
|
function provideFileLogger(options) {
|
|
76
71
|
return {
|
|
77
72
|
provide: LOGGER,
|
|
78
73
|
multi: true,
|
|
79
74
|
useFactory: () => {
|
|
80
75
|
const minLevel = options?.minLevel ?? LogLevel.DEBUG;
|
|
81
|
-
// Determine file path
|
|
82
76
|
let filePath;
|
|
83
77
|
if (options?.filePath) {
|
|
84
78
|
filePath = options.filePath;
|
|
@@ -92,7 +86,8 @@ function provideFileLogger(options) {
|
|
|
92
86
|
return new FileLogger({
|
|
93
87
|
filePath,
|
|
94
88
|
minLevel,
|
|
95
|
-
componentFilter: options?.componentFilter
|
|
89
|
+
componentFilter: options?.componentFilter,
|
|
90
|
+
format: options?.format
|
|
96
91
|
});
|
|
97
92
|
}
|
|
98
93
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nx-ddd-logging-file.mjs","sources":["../../../../../packages/@nx-ddd/logging/src/lib/file/file-logger.ts","../../../../../packages/@nx-ddd/logging/src/lib/file/nx-ddd-logging-file.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"nx-ddd-logging-file.mjs","sources":["../../../../../packages/@nx-ddd/logging/src/lib/file/file-logger.ts","../../../../../packages/@nx-ddd/logging/src/lib/file/nx-ddd-logging-file.ts"],"sourcesContent":["\n\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport { join } from 'path';\nimport type { WriteStream } from 'fs';\nimport { BaseLogger, LOGGER, LogLevel, LogContext } from '@nx-ddd/logging/base';\nimport { buildLogRecord, formatJson } from '@nx-ddd/logging/format';\nimport { Provider } from '@angular/core';\n\nexport type FileLogFormat = 'text' | 'json';\n\nexport interface FileLoggerOptions {\n filePath?: string;\n logDir?: string;\n component?: string; \n minLevel?: LogLevel;\n componentFilter?: string;\n format?: FileLogFormat;\n}\n\nexport class FileLogger extends BaseLogger {\n private writeStream: WriteStream | null = null;\n private minLevel: LogLevel;\n private componentFilter?: RegExp;\n private startTime: number;\n private format: FileLogFormat;\n\n constructor(options?: FileLoggerOptions) {\n super();\n this.minLevel = options?.minLevel ?? LogLevel.DEBUG; \n this.componentFilter = options?.componentFilter\n ? new RegExp(options.componentFilter)\n : undefined;\n this.format = options?.format ?? 'text';\n this.startTime = Date.now();\n\n \n const logDir = options?.logDir || join(os.homedir(), '.machina', 'logs');\n const date = new Date().toISOString().split('T')[0]; \n const component = options?.component || 'app';\n const logFile = options?.filePath || join(logDir, `${component}-${date}.log`);\n\n \n try {\n const dir = options?.filePath ? join(logFile, '..') : logDir;\n fs.mkdirSync(dir, { recursive: true });\n } catch (error) {\n console.error(`[FileLogger] Failed to create log directory: ${error}`);\n }\n\n \n try {\n this.writeStream = fs.createWriteStream(logFile, { flags: 'a' });\n } catch (error) {\n console.error(`[FileLogger] Failed to open log file: ${error}`);\n }\n }\n\n log(level: LogLevel, message: string, context?: LogContext, error?: Error): void {\n \n if (level < this.minLevel) return;\n\n \n if (this.componentFilter && context?.component) {\n if (!this.componentFilter.test(context.component)) return;\n }\n\n if (!this.writeStream) return;\n\n let logMessage: string;\n if (this.format === 'json') {\n logMessage = formatJson(buildLogRecord(level, message, context, error)) + '\\n';\n } else {\n const timestamp = new Date().toISOString();\n const elapsed = ((Date.now() - this.startTime) / 1000).toFixed(2);\n const levelStr = LogLevel[level];\n const component = context?.component || 'unknown';\n const contextStr = context ? JSON.stringify(context) : '';\n const errorStr = error ? `\\n Error: ${error.message}\\n Stack: ${error.stack}` : '';\n logMessage = `[${timestamp}] [+${elapsed}s] [${levelStr}] [${component}] ${message}${contextStr ? ' ' + contextStr : ''}${errorStr}\\n`;\n }\n\n \n this.writeStream.write(logMessage);\n }\n\n close(): void {\n if (this.writeStream) {\n this.writeStream.end();\n this.writeStream = null;\n }\n }\n}\n\n\nexport interface FileLoggerProviderOptions {\n component?: string;\n logDir?: string;\n filePath?: string;\n minLevel?: LogLevel;\n componentFilter?: string;\n format?: FileLogFormat;\n}\n\n\nexport function provideFileLogger(options?: FileLoggerProviderOptions): Provider {\n return {\n provide: LOGGER,\n multi: true,\n useFactory: () => {\n const minLevel = options?.minLevel ?? LogLevel.DEBUG;\n\n \n let filePath: string;\n if (options?.filePath) {\n filePath = options.filePath;\n } else {\n const logDir = options?.logDir || join(os.homedir(), '.machina', 'logs');\n const date = new Date().toISOString().split('T')[0];\n const component = options?.component || 'app';\n filePath = join(logDir, `${component}-${date}.log`);\n }\n\n return new FileLogger({\n filePath,\n minLevel,\n componentFilter: options?.componentFilter,\n format: options?.format\n });\n }\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { LogLevel } from '@nx-ddd/logging/base';
|
|
2
|
+
|
|
3
|
+
function buildLogRecord(level, message, context, error, ts = new Date().toISOString()) {
|
|
4
|
+
const { component, package: pkg, ...restCtx } = context ?? {};
|
|
5
|
+
const record = {
|
|
6
|
+
ts,
|
|
7
|
+
lvl: LogLevel[level],
|
|
8
|
+
component: component ?? 'unknown',
|
|
9
|
+
msg: message,
|
|
10
|
+
};
|
|
11
|
+
if (pkg != null) {
|
|
12
|
+
record.package = pkg;
|
|
13
|
+
}
|
|
14
|
+
if (Object.keys(restCtx).length > 0) {
|
|
15
|
+
record.ctx = restCtx;
|
|
16
|
+
}
|
|
17
|
+
if (error != null) {
|
|
18
|
+
record.err = { message: error.message, stack: error.stack };
|
|
19
|
+
}
|
|
20
|
+
return record;
|
|
21
|
+
}
|
|
22
|
+
const LEVEL_COLOR = {
|
|
23
|
+
DEBUG: '\x1b[90m',
|
|
24
|
+
INFO: '\x1b[36m',
|
|
25
|
+
WARN: '\x1b[33m',
|
|
26
|
+
ERROR: '\x1b[31m',
|
|
27
|
+
FATAL: '\x1b[35m',
|
|
28
|
+
};
|
|
29
|
+
const RESET = '\x1b[0m';
|
|
30
|
+
function formatText(record, opts) {
|
|
31
|
+
const color = opts?.color ?? false;
|
|
32
|
+
const levelStr = color
|
|
33
|
+
? `${LEVEL_COLOR[record.lvl] ?? ''}${record.lvl}${RESET}`
|
|
34
|
+
: record.lvl;
|
|
35
|
+
const source = record.package != null
|
|
36
|
+
? `[${record.package}][${record.component}]`
|
|
37
|
+
: `[${record.component}]`;
|
|
38
|
+
let line = `[${record.ts}][${levelStr}]${source} ${record.msg}`;
|
|
39
|
+
if (record.ctx != null) {
|
|
40
|
+
line += ` ${JSON.stringify(record.ctx)}`;
|
|
41
|
+
}
|
|
42
|
+
if (record.err != null) {
|
|
43
|
+
line += `\n Error: ${record.err.message}`;
|
|
44
|
+
if (record.err.stack != null) {
|
|
45
|
+
line += `\n Stack: ${record.err.stack}`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return line;
|
|
49
|
+
}
|
|
50
|
+
function formatJson(record) {
|
|
51
|
+
return JSON.stringify(record);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Generated bundle index. Do not edit.
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
export { buildLogRecord, formatJson, formatText };
|
|
59
|
+
//# sourceMappingURL=nx-ddd-logging-format.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nx-ddd-logging-format.mjs","sources":["../../../../../packages/@nx-ddd/logging/src/lib/format/log-record.ts","../../../../../packages/@nx-ddd/logging/src/lib/format/nx-ddd-logging-format.ts"],"sourcesContent":["import { LogLevel, LogContext } from '@nx-ddd/logging/base';\n\nexport interface LogRecord {\n ts: string;\n lvl: string;\n component: string;\n package?: string;\n msg: string;\n ctx?: Record<string, unknown>;\n err?: { message: string; stack?: string };\n}\n\nexport function buildLogRecord(\n level: LogLevel,\n message: string,\n context?: LogContext,\n error?: Error,\n ts: string = new Date().toISOString(),\n): LogRecord {\n const { component, package: pkg, ...restCtx } = context ?? {};\n const record: LogRecord = {\n ts,\n lvl: LogLevel[level],\n component: (component as string | undefined) ?? 'unknown',\n msg: message,\n };\n if (pkg != null) {\n record.package = pkg as string;\n }\n if (Object.keys(restCtx).length > 0) {\n record.ctx = restCtx as Record<string, unknown>;\n }\n if (error != null) {\n record.err = { message: error.message, stack: error.stack };\n }\n return record;\n}\n\nconst LEVEL_COLOR: Record<string, string> = {\n DEBUG: '\\x1b[90m',\n INFO: '\\x1b[36m',\n WARN: '\\x1b[33m',\n ERROR: '\\x1b[31m',\n FATAL: '\\x1b[35m',\n};\nconst RESET = '\\x1b[0m';\n\nexport function formatText(record: LogRecord, opts?: { color?: boolean }): string {\n const color = opts?.color ?? false;\n const levelStr = color\n ? `${LEVEL_COLOR[record.lvl] ?? ''}${record.lvl}${RESET}`\n : record.lvl;\n const source = record.package != null\n ? `[${record.package}][${record.component}]`\n : `[${record.component}]`;\n let line = `[${record.ts}][${levelStr}]${source} ${record.msg}`;\n if (record.ctx != null) {\n line += ` ${JSON.stringify(record.ctx)}`;\n }\n if (record.err != null) {\n line += `\\n Error: ${record.err.message}`;\n if (record.err.stack != null) {\n line += `\\n Stack: ${record.err.stack}`;\n }\n }\n return line;\n}\n\nexport function formatJson(record: LogRecord): string {\n return JSON.stringify(record);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;SAYgB,cAAc,CAC5B,KAAe,EACf,OAAe,EACf,OAAoB,EACpB,KAAa,EACb,EAAA,GAAa,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAA;AAErC,IAAA,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,OAAO,IAAI,EAAE;AAC7D,IAAA,MAAM,MAAM,GAAc;QACxB,EAAE;AACF,QAAA,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC;QACpB,SAAS,EAAG,SAAgC,IAAI,SAAS;AACzD,QAAA,GAAG,EAAE,OAAO;KACb;AACD,IAAA,IAAI,GAAG,IAAI,IAAI,EAAE;AACf,QAAA,MAAM,CAAC,OAAO,GAAG,GAAa;IAChC;IACA,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;AACnC,QAAA,MAAM,CAAC,GAAG,GAAG,OAAkC;IACjD;AACA,IAAA,IAAI,KAAK,IAAI,IAAI,EAAE;AACjB,QAAA,MAAM,CAAC,GAAG,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;IAC7D;AACA,IAAA,OAAO,MAAM;AACf;AAEA,MAAM,WAAW,GAA2B;AAC1C,IAAA,KAAK,EAAE,UAAU;AACjB,IAAA,IAAI,EAAE,UAAU;AAChB,IAAA,IAAI,EAAE,UAAU;AAChB,IAAA,KAAK,EAAE,UAAU;AACjB,IAAA,KAAK,EAAE,UAAU;CAClB;AACD,MAAM,KAAK,GAAG,SAAS;AAEjB,SAAU,UAAU,CAAC,MAAiB,EAAE,IAA0B,EAAA;AACtE,IAAA,MAAM,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI,KAAK;IAClC,MAAM,QAAQ,GAAG;AACf,UAAE,CAAA,EAAG,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,GAAG,CAAA,EAAG,KAAK,CAAA;AACvD,UAAE,MAAM,CAAC,GAAG;AACd,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,IAAI;UAC7B,IAAI,MAAM,CAAC,OAAO,CAAA,EAAA,EAAK,MAAM,CAAC,SAAS,CAAA,CAAA;AACzC,UAAE,CAAA,CAAA,EAAI,MAAM,CAAC,SAAS,GAAG;AAC3B,IAAA,IAAI,IAAI,GAAG,CAAA,CAAA,EAAI,MAAM,CAAC,EAAE,CAAA,EAAA,EAAK,QAAQ,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA,EAAI,MAAM,CAAC,GAAG,EAAE;AAC/D,IAAA,IAAI,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE;QACtB,IAAI,IAAI,CAAA,CAAA,EAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA,CAAE;IAC1C;AACA,IAAA,IAAI,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE;QACtB,IAAI,IAAI,cAAc,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE;QAC1C,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,EAAE;YAC5B,IAAI,IAAI,cAAc,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE;QAC1C;IACF;AACA,IAAA,OAAO,IAAI;AACb;AAEM,SAAU,UAAU,CAAC,MAAiB,EAAA;AAC1C,IAAA,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;AAC/B;;ACtEA;;AAEG;;;;"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { BaseLogger, LogLevel, LOGGER } from '@nx-ddd/logging/base';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_HTTP_FLUSH_INTERVAL_MS = 1_000;
|
|
4
|
+
const DEFAULT_HTTP_MAX_BATCH = 200;
|
|
5
|
+
const DEFAULT_HTTP_MAX_BUFFER = 5_000;
|
|
6
|
+
class HttpLogger extends BaseLogger {
|
|
7
|
+
resolveEndpoint;
|
|
8
|
+
peerId;
|
|
9
|
+
minLevel;
|
|
10
|
+
maxBatch;
|
|
11
|
+
maxBuffer;
|
|
12
|
+
fetchFn;
|
|
13
|
+
buffer = [];
|
|
14
|
+
timer;
|
|
15
|
+
inflight = false;
|
|
16
|
+
closed = false;
|
|
17
|
+
seq = 0;
|
|
18
|
+
warnedOnce = false;
|
|
19
|
+
constructor(options) {
|
|
20
|
+
super();
|
|
21
|
+
this.resolveEndpoint = options.resolveEndpoint;
|
|
22
|
+
this.peerId = options.peerId ?? 'local';
|
|
23
|
+
this.minLevel = options.minLevel ?? LogLevel.DEBUG;
|
|
24
|
+
this.maxBatch = options.maxBatch ?? DEFAULT_HTTP_MAX_BATCH;
|
|
25
|
+
this.maxBuffer = options.maxBuffer ?? DEFAULT_HTTP_MAX_BUFFER;
|
|
26
|
+
this.fetchFn = options.fetchFn ?? fetch;
|
|
27
|
+
this.timer = setInterval(() => void this.flush(), options.flushIntervalMs ?? DEFAULT_HTTP_FLUSH_INTERVAL_MS);
|
|
28
|
+
this.timer.unref?.();
|
|
29
|
+
}
|
|
30
|
+
log(level, message, context, error) {
|
|
31
|
+
if (this.closed || level < this.minLevel)
|
|
32
|
+
return;
|
|
33
|
+
this.buffer.push(this.toRecord(level, message, context, error));
|
|
34
|
+
if (this.buffer.length > this.maxBuffer)
|
|
35
|
+
this.buffer.splice(0, this.buffer.length - this.maxBuffer);
|
|
36
|
+
}
|
|
37
|
+
close() {
|
|
38
|
+
if (this.timer != null) {
|
|
39
|
+
clearInterval(this.timer);
|
|
40
|
+
this.timer = null;
|
|
41
|
+
}
|
|
42
|
+
void this.flush();
|
|
43
|
+
this.closed = true;
|
|
44
|
+
}
|
|
45
|
+
toRecord(level, message, context, error) {
|
|
46
|
+
const { component, ...restCtx } = context ?? {};
|
|
47
|
+
const timestamp = Date.now();
|
|
48
|
+
const id = `${String(timestamp).padStart(14, '0')}-${process.pid.toString(36)}-${(this.seq++).toString(36).padStart(6, '0')}`;
|
|
49
|
+
const derived = component ?? /^\[([^[\]\s]+)\]/.exec(message)?.[1] ?? 'unknown';
|
|
50
|
+
return {
|
|
51
|
+
id,
|
|
52
|
+
timestamp,
|
|
53
|
+
peer_id: typeof this.peerId === 'function' ? this.peerId() : this.peerId,
|
|
54
|
+
process_id: process.pid,
|
|
55
|
+
level: LogLevel[level],
|
|
56
|
+
component: derived,
|
|
57
|
+
message,
|
|
58
|
+
context: Object.keys(restCtx).length > 0 ? JSON.stringify(restCtx) : null,
|
|
59
|
+
error: error != null ? `${error.message}${error.stack != null ? `\n${error.stack}` : ''}` : null,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async flush() {
|
|
63
|
+
if (this.inflight || this.buffer.length === 0)
|
|
64
|
+
return;
|
|
65
|
+
const endpoint = this.safeResolveEndpoint();
|
|
66
|
+
if (endpoint == null)
|
|
67
|
+
return;
|
|
68
|
+
const batch = this.buffer.splice(0, this.maxBatch);
|
|
69
|
+
this.inflight = true;
|
|
70
|
+
try {
|
|
71
|
+
await this.fetchFn(`${endpoint}/log`, {
|
|
72
|
+
method: 'POST',
|
|
73
|
+
headers: { 'Content-Type': 'application/json' },
|
|
74
|
+
body: JSON.stringify(batch),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (!this.warnedOnce) {
|
|
79
|
+
this.warnedOnce = true;
|
|
80
|
+
console.error(`[http-logger] ship failed (best-effort, batch dropped): ${error}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
this.inflight = false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
safeResolveEndpoint() {
|
|
88
|
+
try {
|
|
89
|
+
return this.resolveEndpoint();
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function provideHttpLogger(options) {
|
|
97
|
+
return {
|
|
98
|
+
provide: LOGGER,
|
|
99
|
+
multi: true,
|
|
100
|
+
useFactory: () => new HttpLogger(options),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Generated bundle index. Do not edit.
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
export { DEFAULT_HTTP_FLUSH_INTERVAL_MS, DEFAULT_HTTP_MAX_BATCH, DEFAULT_HTTP_MAX_BUFFER, HttpLogger, provideHttpLogger };
|
|
109
|
+
//# sourceMappingURL=nx-ddd-logging-http.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nx-ddd-logging-http.mjs","sources":["../../../../../packages/@nx-ddd/logging/src/lib/http/http.logger.ts","../../../../../packages/@nx-ddd/logging/src/lib/http/nx-ddd-logging-http.ts"],"sourcesContent":["import { Provider } from '@angular/core';\nimport { BaseLogger, LogLevel, LogContext, LOGGER } from '@nx-ddd/logging/base';\n\nexport interface HttpLogRecord {\n id: string;\n timestamp: number;\n peer_id: string;\n process_id: number;\n level: string;\n component: string;\n message: string;\n context: string | null;\n error: string | null;\n}\n\nexport interface HttpLoggerOptions {\n resolveEndpoint: () => string | null;\n peerId?: string | (() => string);\n minLevel?: LogLevel;\n flushIntervalMs?: number;\n maxBatch?: number;\n maxBuffer?: number;\n fetchFn?: typeof fetch;\n}\n\nexport const DEFAULT_HTTP_FLUSH_INTERVAL_MS = 1_000;\nexport const DEFAULT_HTTP_MAX_BATCH = 200;\nexport const DEFAULT_HTTP_MAX_BUFFER = 5_000;\n\nexport class HttpLogger extends BaseLogger {\n private readonly resolveEndpoint: () => string | null;\n private readonly peerId: string | (() => string);\n private readonly minLevel: LogLevel;\n private readonly maxBatch: number;\n private readonly maxBuffer: number;\n private readonly fetchFn: typeof fetch;\n private readonly buffer: HttpLogRecord[] = [];\n private timer: ReturnType<typeof setInterval> | null;\n private inflight = false;\n private closed = false;\n private seq = 0;\n private warnedOnce = false;\n\n constructor(options: HttpLoggerOptions) {\n super();\n this.resolveEndpoint = options.resolveEndpoint;\n this.peerId = options.peerId ?? 'local';\n this.minLevel = options.minLevel ?? LogLevel.DEBUG;\n this.maxBatch = options.maxBatch ?? DEFAULT_HTTP_MAX_BATCH;\n this.maxBuffer = options.maxBuffer ?? DEFAULT_HTTP_MAX_BUFFER;\n this.fetchFn = options.fetchFn ?? fetch;\n this.timer = setInterval(() => void this.flush(), options.flushIntervalMs ?? DEFAULT_HTTP_FLUSH_INTERVAL_MS);\n (this.timer as unknown as { unref?: () => void }).unref?.();\n }\n\n log(level: LogLevel, message: string, context?: LogContext, error?: Error): void {\n if (this.closed || level < this.minLevel) return;\n this.buffer.push(this.toRecord(level, message, context, error));\n if (this.buffer.length > this.maxBuffer) this.buffer.splice(0, this.buffer.length - this.maxBuffer);\n }\n\n close(): void {\n if (this.timer != null) {\n clearInterval(this.timer);\n this.timer = null;\n }\n void this.flush();\n this.closed = true;\n }\n\n private toRecord(level: LogLevel, message: string, context?: LogContext, error?: Error): HttpLogRecord {\n const { component, ...restCtx } = context ?? {};\n const timestamp = Date.now();\n const id = `${String(timestamp).padStart(14, '0')}-${process.pid.toString(36)}-${(this.seq++).toString(36).padStart(6, '0')}`;\n const derived = (component as string | undefined) ?? /^\\[([^[\\]\\s]+)\\]/.exec(message)?.[1] ?? 'unknown';\n return {\n id,\n timestamp,\n peer_id: typeof this.peerId === 'function' ? this.peerId() : this.peerId,\n process_id: process.pid,\n level: LogLevel[level],\n component: derived,\n message,\n context: Object.keys(restCtx).length > 0 ? JSON.stringify(restCtx) : null,\n error: error != null ? `${error.message}${error.stack != null ? `\\n${error.stack}` : ''}` : null,\n };\n }\n\n private async flush(): Promise<void> {\n if (this.inflight || this.buffer.length === 0) return;\n const endpoint = this.safeResolveEndpoint();\n if (endpoint == null) return;\n const batch = this.buffer.splice(0, this.maxBatch);\n this.inflight = true;\n try {\n await this.fetchFn(`${endpoint}/log`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(batch),\n });\n } catch (error) {\n if (!this.warnedOnce) {\n this.warnedOnce = true;\n console.error(`[http-logger] ship failed (best-effort, batch dropped): ${error}`);\n }\n } finally {\n this.inflight = false;\n }\n }\n\n private safeResolveEndpoint(): string | null {\n try {\n return this.resolveEndpoint();\n } catch {\n return null;\n }\n }\n}\n\nexport function provideHttpLogger(options: HttpLoggerOptions): Provider {\n return {\n provide: LOGGER,\n multi: true,\n useFactory: () => new HttpLogger(options),\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|