@zudojs/logger 0.1.0 → 1.0.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/LICENSE +21 -0
- package/README.md +87 -8
- package/dist/loggerCore/core/loggerCore.context.d.ts +9 -2
- package/dist/loggerCore/core/loggerCore.context.js +12 -6
- package/dist/loggerCore/core/loggerCore.core.d.ts +7 -0
- package/dist/loggerCore/core/loggerCore.core.js +19 -0
- package/dist/loggerCore/helpers/loggerCore.helper.d.ts +7 -2
- package/dist/loggerCore/helpers/loggerCore.helper.js +10 -9
- package/dist/loggerCore/helpers/loggerCoreMethods/index.d.ts +1 -1
- package/dist/loggerCore/helpers/loggerCoreMethods/index.js +1 -1
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.child.js +3 -1
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.dispatch.d.ts +11 -0
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.dispatch.js +121 -11
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.entry.js +9 -2
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.level.js +9 -2
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.lifecycle.js +8 -0
- package/dist/loggerEntry/loggerEntry.core.js +0 -1
- package/dist/loggerEntry/loggerEntryHelpers/index.d.ts +2 -0
- package/dist/loggerEntry/loggerEntryHelpers/index.js +1 -0
- package/dist/loggerEntry/loggerEntryHelpers/loggerEntryHelpers.sanitize.d.ts +69 -0
- package/dist/loggerEntry/loggerEntryHelpers/loggerEntryHelpers.sanitize.js +107 -0
- package/dist/loggerEntry/loggerEntryHelpers/loggerEntryHelpers.serialize.d.ts +5 -1
- package/dist/loggerEntry/loggerEntryHelpers/loggerEntryHelpers.serialize.js +9 -5
- package/dist/loggerEntry/loggerEntryHelpers/loggerEntryHelpers.valueSerialize.js +9 -1
- package/dist/loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.context.js +9 -3
- package/dist/loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.js +3 -2
- package/dist/loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.json.js +19 -3
- package/dist/loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.metadata.js +14 -6
- package/dist/loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.text.js +31 -4
- package/dist/loggerOptions/loggerOptions.type.d.ts +12 -1
- package/dist/loggerOptions/loggerOptions.type.js +4 -1
- package/dist/loggerTransport/loggerTransportHelpers/loggerTransportHelpers.js +4 -3
- package/package.json +19 -12
- package/dist/.tsbuildinfo +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/loggerContext/index.d.ts.map +0 -1
- package/dist/loggerContext/index.js.map +0 -1
- package/dist/loggerContext/loggerContext.core.d.ts.map +0 -1
- package/dist/loggerContext/loggerContext.core.js.map +0 -1
- package/dist/loggerContext/loggerContext.type.d.ts.map +0 -1
- package/dist/loggerContext/loggerContext.type.js.map +0 -1
- package/dist/loggerContext/loggerContextCreate.d.ts.map +0 -1
- package/dist/loggerContext/loggerContextCreate.js.map +0 -1
- package/dist/loggerContext/loggerContextSerialize.d.ts.map +0 -1
- package/dist/loggerContext/loggerContextSerialize.js.map +0 -1
- package/dist/loggerContext/loggerContextStorage.d.ts.map +0 -1
- package/dist/loggerContext/loggerContextStorage.js.map +0 -1
- package/dist/loggerCore/core/index.d.ts.map +0 -1
- package/dist/loggerCore/core/index.js.map +0 -1
- package/dist/loggerCore/core/loggerCore.context.d.ts.map +0 -1
- package/dist/loggerCore/core/loggerCore.context.js.map +0 -1
- package/dist/loggerCore/core/loggerCore.core.d.ts.map +0 -1
- package/dist/loggerCore/core/loggerCore.core.js.map +0 -1
- package/dist/loggerCore/core/loggerCore.type.d.ts.map +0 -1
- package/dist/loggerCore/core/loggerCore.type.js.map +0 -1
- package/dist/loggerCore/helpers/index.d.ts.map +0 -1
- package/dist/loggerCore/helpers/index.js.map +0 -1
- package/dist/loggerCore/helpers/loggerCore.helper.d.ts.map +0 -1
- package/dist/loggerCore/helpers/loggerCore.helper.js.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreHelpers.d.ts.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreHelpers.js.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods/index.d.ts.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods/index.js.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.child.d.ts.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.child.js.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.dispatch.d.ts.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.dispatch.js.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.entry.d.ts.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.entry.js.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.level.d.ts.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.level.js.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.lifecycle.d.ts.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods/loggerCoreMethods.lifecycle.js.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods.logLevels.d.ts.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods.logLevels.js.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods.loggerProps.d.ts.map +0 -1
- package/dist/loggerCore/helpers/loggerCoreMethods.loggerProps.js.map +0 -1
- package/dist/loggerCore/index.d.ts.map +0 -1
- package/dist/loggerCore/index.js.map +0 -1
- package/dist/loggerEntry/index.d.ts.map +0 -1
- package/dist/loggerEntry/index.js.map +0 -1
- package/dist/loggerEntry/loggerEntry.core.d.ts.map +0 -1
- package/dist/loggerEntry/loggerEntry.core.js.map +0 -1
- package/dist/loggerEntry/loggerEntry.type.d.ts.map +0 -1
- package/dist/loggerEntry/loggerEntry.type.js.map +0 -1
- package/dist/loggerEntry/loggerEntryCreate.d.ts.map +0 -1
- package/dist/loggerEntry/loggerEntryCreate.js.map +0 -1
- package/dist/loggerEntry/loggerEntryHelpers/index.d.ts.map +0 -1
- package/dist/loggerEntry/loggerEntryHelpers/index.js.map +0 -1
- package/dist/loggerEntry/loggerEntryHelpers/loggerEntryHelpers.interfaces.d.ts.map +0 -1
- package/dist/loggerEntry/loggerEntryHelpers/loggerEntryHelpers.interfaces.js.map +0 -1
- package/dist/loggerEntry/loggerEntryHelpers/loggerEntryHelpers.serialize.d.ts.map +0 -1
- package/dist/loggerEntry/loggerEntryHelpers/loggerEntryHelpers.serialize.js.map +0 -1
- package/dist/loggerEntry/loggerEntryHelpers/loggerEntryHelpers.types.d.ts.map +0 -1
- package/dist/loggerEntry/loggerEntryHelpers/loggerEntryHelpers.types.js.map +0 -1
- package/dist/loggerEntry/loggerEntryHelpers/loggerEntryHelpers.valueSerialize.d.ts.map +0 -1
- package/dist/loggerEntry/loggerEntryHelpers/loggerEntryHelpers.valueSerialize.js.map +0 -1
- package/dist/loggerEntry/loggerEntrySerialize.d.ts.map +0 -1
- package/dist/loggerEntry/loggerEntrySerialize.js.map +0 -1
- package/dist/loggerErrors/index.d.ts.map +0 -1
- package/dist/loggerErrors/index.js.map +0 -1
- package/dist/loggerErrors/loggerError.base.d.ts.map +0 -1
- package/dist/loggerErrors/loggerError.base.js.map +0 -1
- package/dist/loggerErrors/loggerError.helpers.d.ts.map +0 -1
- package/dist/loggerErrors/loggerError.helpers.js.map +0 -1
- package/dist/loggerFactory/index.d.ts.map +0 -1
- package/dist/loggerFactory/index.js.map +0 -1
- package/dist/loggerFactory/loggerFactory.core.d.ts.map +0 -1
- package/dist/loggerFactory/loggerFactory.core.js.map +0 -1
- package/dist/loggerFormatter/index.d.ts.map +0 -1
- package/dist/loggerFormatter/index.js.map +0 -1
- package/dist/loggerFormatter/loggerFormatter.core.d.ts.map +0 -1
- package/dist/loggerFormatter/loggerFormatter.core.js.map +0 -1
- package/dist/loggerFormatter/loggerFormatter.type.d.ts.map +0 -1
- package/dist/loggerFormatter/loggerFormatter.type.js.map +0 -1
- package/dist/loggerFormatter/loggerFormatterFormatters/index.d.ts.map +0 -1
- package/dist/loggerFormatter/loggerFormatterFormatters/index.js.map +0 -1
- package/dist/loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.context.d.ts.map +0 -1
- package/dist/loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.context.js.map +0 -1
- package/dist/loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.d.ts.map +0 -1
- package/dist/loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.js.map +0 -1
- package/dist/loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.json.d.ts.map +0 -1
- package/dist/loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.json.js.map +0 -1
- package/dist/loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.metadata.d.ts.map +0 -1
- package/dist/loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.metadata.js.map +0 -1
- package/dist/loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.text.d.ts.map +0 -1
- package/dist/loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.text.js.map +0 -1
- package/dist/loggerFormatter/loggerFormatterGuard.d.ts.map +0 -1
- package/dist/loggerFormatter/loggerFormatterGuard.js.map +0 -1
- package/dist/loggerLevel/index.d.ts.map +0 -1
- package/dist/loggerLevel/index.js.map +0 -1
- package/dist/loggerLevel/loggerLevel.type.d.ts.map +0 -1
- package/dist/loggerLevel/loggerLevel.type.js.map +0 -1
- package/dist/loggerManager/index.d.ts.map +0 -1
- package/dist/loggerManager/index.js.map +0 -1
- package/dist/loggerManager/loggerManager.core.d.ts.map +0 -1
- package/dist/loggerManager/loggerManager.core.js.map +0 -1
- package/dist/loggerOptions/index.d.ts.map +0 -1
- package/dist/loggerOptions/index.js.map +0 -1
- package/dist/loggerOptions/loggerOptions.type.d.ts.map +0 -1
- package/dist/loggerOptions/loggerOptions.type.js.map +0 -1
- package/dist/loggerTransport/index.d.ts.map +0 -1
- package/dist/loggerTransport/index.js.map +0 -1
- package/dist/loggerTransport/loggerTransport.core.d.ts.map +0 -1
- package/dist/loggerTransport/loggerTransport.core.js.map +0 -1
- package/dist/loggerTransport/loggerTransport.registry.d.ts.map +0 -1
- package/dist/loggerTransport/loggerTransport.registry.js.map +0 -1
- package/dist/loggerTransport/loggerTransport.type.d.ts.map +0 -1
- package/dist/loggerTransport/loggerTransport.type.js.map +0 -1
- package/dist/loggerTransport/loggerTransportComposite/index.d.ts.map +0 -1
- package/dist/loggerTransport/loggerTransportComposite/index.js.map +0 -1
- package/dist/loggerTransport/loggerTransportComposite/loggerTransportComposite.buffered.d.ts.map +0 -1
- package/dist/loggerTransport/loggerTransportComposite/loggerTransportComposite.buffered.js.map +0 -1
- package/dist/loggerTransport/loggerTransportComposite/loggerTransportComposite.d.ts.map +0 -1
- package/dist/loggerTransport/loggerTransportComposite/loggerTransportComposite.js.map +0 -1
- package/dist/loggerTransport/loggerTransportConsole/index.d.ts.map +0 -1
- package/dist/loggerTransport/loggerTransportConsole/index.js.map +0 -1
- package/dist/loggerTransport/loggerTransportConsole/loggerTransportConsole.core.d.ts.map +0 -1
- package/dist/loggerTransport/loggerTransportConsole/loggerTransportConsole.core.js.map +0 -1
- package/dist/loggerTransport/loggerTransportGuard.d.ts.map +0 -1
- package/dist/loggerTransport/loggerTransportGuard.js.map +0 -1
- package/dist/loggerTransport/loggerTransportHelpers/index.d.ts.map +0 -1
- package/dist/loggerTransport/loggerTransportHelpers/index.js.map +0 -1
- package/dist/loggerTransport/loggerTransportHelpers/loggerTransportHelpers.d.ts.map +0 -1
- package/dist/loggerTransport/loggerTransportHelpers/loggerTransportHelpers.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zudojs Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# @zudojs/logger
|
|
2
2
|
|
|
3
|
-
Structured logging with transports, log levels,
|
|
3
|
+
Structured logging with transports, formatters, log levels, secret
|
|
4
|
+
redaction, and context propagation for Zudojs applications.
|
|
4
5
|
|
|
5
6
|
## Installation
|
|
6
7
|
|
|
@@ -17,16 +18,94 @@ const logger = createLogger({ name: "api" });
|
|
|
17
18
|
|
|
18
19
|
logger.info("Server started", { port: 3000, env: "production" });
|
|
19
20
|
logger.error("Connection failed", { error: err.message });
|
|
21
|
+
|
|
22
|
+
await logger.flush(); // drain in-flight writes before exit
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Levels
|
|
26
|
+
|
|
27
|
+
`fatal` (0), `error` (1), `warn` (2), `info` (3), `debug` (4), `trace`
|
|
28
|
+
(5). A logger emits every message at or below its configured level;
|
|
29
|
+
`level` defaults to `info`.
|
|
30
|
+
|
|
31
|
+
## Transports
|
|
32
|
+
|
|
33
|
+
A transport is either a `{ name, enabled, write, flush?, close? }`
|
|
34
|
+
object or a `(entry, context) => void | Promise<void>` function. When no
|
|
35
|
+
transport is configured the logger writes to the console.
|
|
36
|
+
|
|
37
|
+
Built in: `createConsoleLoggerTransport`, and the composites
|
|
38
|
+
`createMultiLoggerTransport`, `createConditionalLoggerTransport` and
|
|
39
|
+
`createBufferedLoggerTransport`. File and HTTP transports are not
|
|
40
|
+
included — implement the `LoggerTransport` interface for those.
|
|
41
|
+
|
|
42
|
+
`transportTimeout` (default 10s) bounds every transport write, so a
|
|
43
|
+
transport that stops responding cannot hang `flush()` or `close()`.
|
|
44
|
+
|
|
45
|
+
## Flushing
|
|
46
|
+
|
|
47
|
+
Dispatch completes synchronously when every transport is synchronous.
|
|
48
|
+
With an asynchronous transport — or with `asynchronous: true`, which
|
|
49
|
+
always defers so the caller stays off the transport's critical path —
|
|
50
|
+
writes are in flight until drained. `flush()` and `close()` drain them,
|
|
51
|
+
so nothing is lost at exit.
|
|
52
|
+
|
|
53
|
+
## Secret redaction
|
|
54
|
+
|
|
55
|
+
Redaction is **on by default**. Metadata and context fields whose NAME
|
|
56
|
+
looks like a secret — password, secret, token, api key, private key,
|
|
57
|
+
credential, authorization, cookie — are replaced with `"[REDACTED]"`
|
|
58
|
+
before the entry reaches any formatter or transport. Nested objects,
|
|
59
|
+
arrays and getters are all covered.
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
logger.info("login", { user: "alice", password: "hunter2" });
|
|
63
|
+
// metadata: { user: "alice", password: "[REDACTED]" }
|
|
64
|
+
|
|
65
|
+
createLogger({ redact: { keys: ["ssn"], replacement: "***" } });
|
|
66
|
+
createLogger({ redact: { enabled: false } }); // opt out
|
|
20
67
|
```
|
|
21
68
|
|
|
22
|
-
##
|
|
69
|
+
## Log injection
|
|
70
|
+
|
|
71
|
+
Text-shaped formatters escape control characters in the message, the
|
|
72
|
+
logger name, metadata keys and values, context values and source
|
|
73
|
+
locations. A newline or ANSI escape inside attacker-supplied text
|
|
74
|
+
becomes `\n` / `` rather than forging an extra log record or
|
|
75
|
+
driving the operator's terminal. The JSON formatter relies on
|
|
76
|
+
`JSON.stringify`, which escapes the same characters.
|
|
77
|
+
|
|
78
|
+
Metadata is normalized before serialization, so circular references
|
|
79
|
+
(`"[Circular]"`), BigInt values and functions never make a formatter
|
|
80
|
+
throw and silently drop the record.
|
|
81
|
+
|
|
82
|
+
## Context
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { createLoggerContext, withLoggerContext } from "@zudojs/logger";
|
|
86
|
+
|
|
87
|
+
const scoped = logger.withContext(
|
|
88
|
+
createLoggerContext({ requestId: "req-1", metadata: { tenant: "acme" } }),
|
|
89
|
+
);
|
|
90
|
+
scoped.info("handled"); // metadata carries requestId and tenant
|
|
91
|
+
|
|
92
|
+
withLoggerContext(logger, createLoggerContext({ traceId }), (scoped) => {
|
|
93
|
+
scoped.info("inside the trace");
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Child loggers inherit name, level, formatter, transports, metadata and
|
|
98
|
+
redaction settings: `logger.child({ name: "api.db" })`.
|
|
99
|
+
|
|
100
|
+
## Formatters
|
|
101
|
+
|
|
102
|
+
`createTextLoggerFormatter`, `createJsonLoggerFormatter`,
|
|
103
|
+
`createCompactLoggerFormatter`, `createDevelopmentLoggerFormatter`,
|
|
104
|
+
`createProductionLoggerFormatter`, `createStructuredLoggerFormatter`.
|
|
23
105
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
- Child loggers with inherited context
|
|
28
|
-
- Correlation ID propagation
|
|
29
|
-
- Sensitive data redaction
|
|
106
|
+
Pass `{ colors: true }` in the formatter context to colourize the level
|
|
107
|
+
tag of text output. Colour codes are emitted only around the fixed level
|
|
108
|
+
name, never around user-supplied text.
|
|
30
109
|
|
|
31
110
|
## Use Cases
|
|
32
111
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { LoggerLevel } from "../../loggerLevel/loggerLevel.type.js";
|
|
5
5
|
import type { LogMetadata } from "../../loggerEntry/loggerEntry.type.js";
|
|
6
|
-
import type { LoggerContext } from "../../loggerContext/loggerContext.core.js";
|
|
6
|
+
import type { LoggerContext, LoggerContextStorage } from "../../loggerContext/loggerContext.core.js";
|
|
7
7
|
import type { ChildLoggerOptions, LogOptions } from "../../loggerOptions/loggerOptions.type.js";
|
|
8
8
|
import type { Logger } from "./loggerCore.type.js";
|
|
9
9
|
/**
|
|
@@ -12,7 +12,14 @@ import type { Logger } from "./loggerCore.type.js";
|
|
|
12
12
|
export declare class ContextLogger implements Logger {
|
|
13
13
|
private readonly logger;
|
|
14
14
|
private readonly context;
|
|
15
|
-
|
|
15
|
+
private readonly storage;
|
|
16
|
+
/**
|
|
17
|
+
* @param storage The context storage the WRAPPED logger reads from.
|
|
18
|
+
* This used to be created fresh inside `run()`, so the scoped
|
|
19
|
+
* context was written into a throwaway stack and never reached the
|
|
20
|
+
* entry — withContext() silently produced context-free logs.
|
|
21
|
+
*/
|
|
22
|
+
constructor(logger: Logger, context: LoggerContext, storage: LoggerContextStorage);
|
|
16
23
|
get name(): string;
|
|
17
24
|
get level(): LoggerLevel;
|
|
18
25
|
get enabled(): boolean;
|
|
@@ -2,16 +2,23 @@
|
|
|
2
2
|
* ContextLogger wrapper implementation.
|
|
3
3
|
*/
|
|
4
4
|
import { createLoggerContext } from "../../loggerContext/loggerContext.core.js";
|
|
5
|
-
import { createLoggerContextStorage } from "../../loggerContext/loggerContextStorage.js";
|
|
6
5
|
/**
|
|
7
6
|
* Logger wrapper that provides scoped context.
|
|
8
7
|
*/
|
|
9
8
|
export class ContextLogger {
|
|
10
9
|
logger;
|
|
11
10
|
context;
|
|
12
|
-
|
|
11
|
+
storage;
|
|
12
|
+
/**
|
|
13
|
+
* @param storage The context storage the WRAPPED logger reads from.
|
|
14
|
+
* This used to be created fresh inside `run()`, so the scoped
|
|
15
|
+
* context was written into a throwaway stack and never reached the
|
|
16
|
+
* entry — withContext() silently produced context-free logs.
|
|
17
|
+
*/
|
|
18
|
+
constructor(logger, context, storage) {
|
|
13
19
|
this.logger = logger;
|
|
14
20
|
this.context = context;
|
|
21
|
+
this.storage = storage;
|
|
15
22
|
}
|
|
16
23
|
get name() {
|
|
17
24
|
return this.logger.name;
|
|
@@ -44,14 +51,14 @@ export class ContextLogger {
|
|
|
44
51
|
this.run(() => this.logger.log(level, message, options));
|
|
45
52
|
}
|
|
46
53
|
child(options) {
|
|
47
|
-
return new ContextLogger(this.logger.child(options), this.context);
|
|
54
|
+
return new ContextLogger(this.logger.child(options), this.context, this.storage);
|
|
48
55
|
}
|
|
49
56
|
withContext(context) {
|
|
50
57
|
return new ContextLogger(this.logger, createLoggerContext({
|
|
51
58
|
parent: this.context,
|
|
52
59
|
...context.identifiers,
|
|
53
60
|
metadata: context.metadata,
|
|
54
|
-
}));
|
|
61
|
+
}), this.storage);
|
|
55
62
|
}
|
|
56
63
|
setLevel(level) {
|
|
57
64
|
this.logger.setLevel(level);
|
|
@@ -69,8 +76,7 @@ export class ContextLogger {
|
|
|
69
76
|
return this.logger.close();
|
|
70
77
|
}
|
|
71
78
|
run(callback) {
|
|
72
|
-
|
|
73
|
-
storage.run(this.context, callback);
|
|
79
|
+
this.storage.run(this.context, callback);
|
|
74
80
|
}
|
|
75
81
|
}
|
|
76
82
|
//# sourceMappingURL=loggerCore.context.js.map
|
|
@@ -19,6 +19,10 @@ export interface ZudojsLoggerContext {
|
|
|
19
19
|
markDisposed(): void;
|
|
20
20
|
updateConfiguration(config: LoggerConfiguration): void;
|
|
21
21
|
createChildLogger(options: LoggerOptions): Logger;
|
|
22
|
+
/** Registers an in-flight dispatch so it can be awaited later. */
|
|
23
|
+
trackDispatch(dispatch: Promise<void>): void;
|
|
24
|
+
/** Resolves once every registered dispatch has settled. */
|
|
25
|
+
drainDispatches(): Promise<void>;
|
|
22
26
|
}
|
|
23
27
|
/**
|
|
24
28
|
* Logger implementation.
|
|
@@ -27,6 +31,7 @@ export declare class ZudojsLogger implements Logger, ZudojsLoggerContext {
|
|
|
27
31
|
private _configuration;
|
|
28
32
|
private readonly _contextStorage;
|
|
29
33
|
private _disposed;
|
|
34
|
+
private readonly _pending;
|
|
30
35
|
constructor(options?: LoggerOptions, contextStorage?: LoggerContextStorage);
|
|
31
36
|
get configuration(): LoggerConfiguration;
|
|
32
37
|
get contextStorage(): LoggerContextStorage;
|
|
@@ -54,6 +59,8 @@ export declare class ZudojsLogger implements Logger, ZudojsLoggerContext {
|
|
|
54
59
|
markDisposed(): void;
|
|
55
60
|
updateConfiguration(config: LoggerConfiguration): void;
|
|
56
61
|
createChildLogger(options: LoggerOptions): Logger;
|
|
62
|
+
trackDispatch(dispatch: Promise<void>): void;
|
|
63
|
+
drainDispatches(): Promise<void>;
|
|
57
64
|
}
|
|
58
65
|
/**
|
|
59
66
|
* Creates a Zudojs logger.
|
|
@@ -14,6 +14,7 @@ export class ZudojsLogger {
|
|
|
14
14
|
_configuration;
|
|
15
15
|
_contextStorage;
|
|
16
16
|
_disposed = false;
|
|
17
|
+
_pending = new Set();
|
|
17
18
|
constructor(options = {}, contextStorage) {
|
|
18
19
|
this._configuration = resolveLoggerOptions(options);
|
|
19
20
|
this._contextStorage = contextStorage ?? createLoggerContextStorage();
|
|
@@ -97,6 +98,24 @@ export class ZudojsLogger {
|
|
|
97
98
|
createChildLogger(options) {
|
|
98
99
|
return new ZudojsLogger(options, this._contextStorage);
|
|
99
100
|
}
|
|
101
|
+
trackDispatch(dispatch) {
|
|
102
|
+
// dispatchEntry routes its own failures through handleError, so a
|
|
103
|
+
// rejection here is unexpected; swallow it to keep an unawaited log
|
|
104
|
+
// call from crashing the process, and keep the entry drainable.
|
|
105
|
+
const tracked = dispatch
|
|
106
|
+
.catch(() => { })
|
|
107
|
+
.finally(() => {
|
|
108
|
+
this._pending.delete(tracked);
|
|
109
|
+
});
|
|
110
|
+
this._pending.add(tracked);
|
|
111
|
+
}
|
|
112
|
+
async drainDispatches() {
|
|
113
|
+
// A dispatch can start further dispatches (a transport that logs),
|
|
114
|
+
// so drain until the set is genuinely empty.
|
|
115
|
+
while (this._pending.size > 0) {
|
|
116
|
+
await Promise.all([...this._pending]);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
100
119
|
}
|
|
101
120
|
/**
|
|
102
121
|
* Creates a Zudojs logger.
|
|
@@ -14,9 +14,14 @@ export declare function createChildLogger(parent: Logger, options?: ChildLoggerO
|
|
|
14
14
|
*/
|
|
15
15
|
export declare function logError(logger: Logger, error: Error, message?: string, metadata?: LogMetadata): void;
|
|
16
16
|
/**
|
|
17
|
-
* Creates a logger
|
|
17
|
+
* Creates a context-scoped logger and runs a callback with it.
|
|
18
|
+
*
|
|
19
|
+
* The scoped logger is passed to the callback. Both branches of the
|
|
20
|
+
* previous implementation were identical and simply discarded the
|
|
21
|
+
* scoped logger, so the context never applied to anything the callback
|
|
22
|
+
* logged.
|
|
18
23
|
*/
|
|
19
|
-
export declare function withLoggerContext<T>(logger: Logger, context: LoggerContext, callback: () => T): T;
|
|
24
|
+
export declare function withLoggerContext<T>(logger: Logger, context: LoggerContext, callback: (scoped: Logger) => T): T;
|
|
20
25
|
/**
|
|
21
26
|
* Creates a default application logger.
|
|
22
27
|
*/
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Logger helper functions.
|
|
3
3
|
*/
|
|
4
|
+
import { LoggerLevel } from "../../loggerLevel/loggerLevel.type.js";
|
|
4
5
|
import { createTextLoggerFormatter } from "../../loggerFormatter/loggerFormatterFormatters/loggerFormatterFormatters.text.js";
|
|
5
6
|
import { createConsoleLoggerTransport } from "../../loggerTransport/loggerTransport.registry.js";
|
|
6
|
-
import { ContextLogger } from "../core/loggerCore.context.js";
|
|
7
7
|
import { createLogger } from "../core/loggerCore.core.js";
|
|
8
8
|
/**
|
|
9
9
|
* Creates a child logger.
|
|
@@ -18,20 +18,21 @@ export function logError(logger, error, message, metadata) {
|
|
|
18
18
|
if (!logger.enabled) {
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
|
-
logger.log(
|
|
21
|
+
logger.log(LoggerLevel.ERROR, message ?? error.message, {
|
|
22
22
|
metadata,
|
|
23
23
|
error,
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
|
-
* Creates a logger
|
|
27
|
+
* Creates a context-scoped logger and runs a callback with it.
|
|
28
|
+
*
|
|
29
|
+
* The scoped logger is passed to the callback. Both branches of the
|
|
30
|
+
* previous implementation were identical and simply discarded the
|
|
31
|
+
* scoped logger, so the context never applied to anything the callback
|
|
32
|
+
* logged.
|
|
28
33
|
*/
|
|
29
34
|
export function withLoggerContext(logger, context, callback) {
|
|
30
|
-
|
|
31
|
-
if (scoped instanceof ContextLogger) {
|
|
32
|
-
return callback();
|
|
33
|
-
}
|
|
34
|
-
return callback();
|
|
35
|
+
return callback(logger.withContext(context));
|
|
35
36
|
}
|
|
36
37
|
/**
|
|
37
38
|
* Creates a default application logger.
|
|
@@ -39,7 +40,7 @@ export function withLoggerContext(logger, context, callback) {
|
|
|
39
40
|
export function createDefaultLogger(name = "zudojs") {
|
|
40
41
|
return createLogger({
|
|
41
42
|
name,
|
|
42
|
-
level:
|
|
43
|
+
level: LoggerLevel.INFO,
|
|
43
44
|
formatter: createTextLoggerFormatter(),
|
|
44
45
|
transports: [createConsoleLoggerTransport()],
|
|
45
46
|
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Logger class helper methods.
|
|
5
5
|
*/
|
|
6
6
|
export { createEntry } from "./loggerCoreMethods.entry.js";
|
|
7
|
-
export { dispatchEntry } from "./loggerCoreMethods.dispatch.js";
|
|
7
|
+
export { dispatchEntry, dispatchEntrySync, } from "./loggerCoreMethods.dispatch.js";
|
|
8
8
|
export { logAtLevel } from "./loggerCoreMethods.level.js";
|
|
9
9
|
export { childLogger, withContextLogger } from "./loggerCoreMethods.child.js";
|
|
10
10
|
export { setLoggerLevel, enableLogger, disableLogger, flushLogger, closeLogger, } from "./loggerCoreMethods.lifecycle.js";
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Logger class helper methods.
|
|
5
5
|
*/
|
|
6
6
|
export { createEntry } from "./loggerCoreMethods.entry.js";
|
|
7
|
-
export { dispatchEntry } from "./loggerCoreMethods.dispatch.js";
|
|
7
|
+
export { dispatchEntry, dispatchEntrySync, } from "./loggerCoreMethods.dispatch.js";
|
|
8
8
|
export { logAtLevel } from "./loggerCoreMethods.level.js";
|
|
9
9
|
export { childLogger, withContextLogger } from "./loggerCoreMethods.child.js";
|
|
10
10
|
export { setLoggerLevel, enableLogger, disableLogger, flushLogger, closeLogger, } from "./loggerCoreMethods.lifecycle.js";
|
|
@@ -17,6 +17,8 @@ export function childLogger(ctx, options = {}) {
|
|
|
17
17
|
export function withContextLogger(ctx, context) {
|
|
18
18
|
ctx.assertActive();
|
|
19
19
|
const child = childLogger(ctx);
|
|
20
|
-
|
|
20
|
+
// The child shares the parent's context storage, so the wrapper must
|
|
21
|
+
// scope THAT storage for the context to reach created entries.
|
|
22
|
+
return new ContextLogger(child, context, ctx.contextStorage);
|
|
21
23
|
}
|
|
22
24
|
//# sourceMappingURL=loggerCoreMethods.child.js.map
|
|
@@ -7,4 +7,15 @@ import type { LoggerConfiguration } from "../../../loggerOptions/loggerOptions.t
|
|
|
7
7
|
* Dispatches an entry to the configured transports.
|
|
8
8
|
*/
|
|
9
9
|
export declare function dispatchEntry(configuration: LoggerConfiguration, entry: LoggerEntry, handleError: (error: Error) => void): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Dispatches an entry, completing synchronously where it can.
|
|
12
|
+
*
|
|
13
|
+
* Returns `undefined` when every configured transport finished
|
|
14
|
+
* synchronously (nothing to await), otherwise a promise covering the
|
|
15
|
+
* asynchronous remainder. `asynchronous: true` skips the fast path
|
|
16
|
+
* entirely and always defers, keeping the caller off the transport's
|
|
17
|
+
* critical path — the option was previously stored and never read, so
|
|
18
|
+
* both settings behaved identically.
|
|
19
|
+
*/
|
|
20
|
+
export declare function dispatchEntrySync(configuration: LoggerConfiguration, entry: LoggerEntry, handleError: (error: Error) => void): void | Promise<void>;
|
|
10
21
|
//# sourceMappingURL=loggerCoreMethods.dispatch.d.ts.map
|
|
@@ -18,6 +18,41 @@ function defaultFormat(configuration, entry) {
|
|
|
18
18
|
environment: configuration.environment,
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Bounds a transport write with the configured transport timeout.
|
|
23
|
+
*
|
|
24
|
+
* `transportTimeout` was accepted, validated and stored but never read,
|
|
25
|
+
* so a transport whose write() never settled blocked flush() and
|
|
26
|
+
* close() forever. A non-positive timeout disables the bound.
|
|
27
|
+
*/
|
|
28
|
+
async function withTransportTimeout(timeoutMs, transportName, operation) {
|
|
29
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
30
|
+
await operation;
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
let timer;
|
|
34
|
+
const expiry = new Promise((_resolve, reject) => {
|
|
35
|
+
timer = setTimeout(() => {
|
|
36
|
+
reject(new LoggerTransportError(`Transport "${transportName}" did not complete within ${timeoutMs}ms.`));
|
|
37
|
+
}, timeoutMs);
|
|
38
|
+
// This timer bounds a write; it is not work in its own right. Left
|
|
39
|
+
// referenced it keeps the event loop alive, so a process that has
|
|
40
|
+
// finished but logged through an async transport hangs until the
|
|
41
|
+
// timeout elapses. Every other timer in the framework is unref'd
|
|
42
|
+
// for the same reason.
|
|
43
|
+
timer.unref?.();
|
|
44
|
+
});
|
|
45
|
+
try {
|
|
46
|
+
await Promise.race([operation, expiry]);
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
if (timer !== undefined) {
|
|
50
|
+
clearTimeout(timer);
|
|
51
|
+
}
|
|
52
|
+
// The abandoned write must never surface as an unhandled rejection.
|
|
53
|
+
void operation.catch(() => { });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
21
56
|
/**
|
|
22
57
|
* Writes to a transport.
|
|
23
58
|
*/
|
|
@@ -33,22 +68,45 @@ async function writeTransport(configuration, transport, entry, formatted) {
|
|
|
33
68
|
}
|
|
34
69
|
await writeLoggerTransport(transport.transport, entry, transportContext);
|
|
35
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Formats an entry with the configured formatter.
|
|
73
|
+
*/
|
|
74
|
+
function formatEntry(configuration, entry) {
|
|
75
|
+
const formatter = configuration.formatter;
|
|
76
|
+
if (typeof formatter === "string") {
|
|
77
|
+
return defaultFormat(configuration, entry);
|
|
78
|
+
}
|
|
79
|
+
return formatLoggerEntry(formatter, entry, {
|
|
80
|
+
loggerName: configuration.name,
|
|
81
|
+
environment: configuration.environment,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Writes an entry through one transport WITHOUT forcing a microtask.
|
|
86
|
+
*
|
|
87
|
+
* `writeLoggerTransport` is `async`, so awaiting it always defers by at
|
|
88
|
+
* least one microtask even for a fully synchronous transport. Calling
|
|
89
|
+
* the transport directly lets a synchronous console/array transport
|
|
90
|
+
* complete inline, which is what `asynchronous: false` promises.
|
|
91
|
+
*/
|
|
92
|
+
function writeTransportMaybeSync(configuration, transport, entry, formatted) {
|
|
93
|
+
const transportContext = {
|
|
94
|
+
loggerName: configuration.name,
|
|
95
|
+
environment: configuration.environment,
|
|
96
|
+
};
|
|
97
|
+
const payload = typeof formatted === "string" ? { ...entry, message: formatted } : entry;
|
|
98
|
+
const target = transport.transport;
|
|
99
|
+
return typeof target === "function"
|
|
100
|
+
? target(payload, transportContext)
|
|
101
|
+
: target.write(payload, transportContext);
|
|
102
|
+
}
|
|
36
103
|
/**
|
|
37
104
|
* Dispatches an entry to the configured transports.
|
|
38
105
|
*/
|
|
39
106
|
export async function dispatchEntry(configuration, entry, handleError) {
|
|
40
|
-
const formatter = configuration.formatter;
|
|
41
107
|
let formatted;
|
|
42
108
|
try {
|
|
43
|
-
|
|
44
|
-
formatted = defaultFormat(configuration, entry);
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
formatted = formatLoggerEntry(formatter, entry, {
|
|
48
|
-
loggerName: configuration.name,
|
|
49
|
-
environment: configuration.environment,
|
|
50
|
-
});
|
|
51
|
-
}
|
|
109
|
+
formatted = formatEntry(configuration, entry);
|
|
52
110
|
}
|
|
53
111
|
catch (error) {
|
|
54
112
|
const formatterError = new LoggerFormatterError(`Failed to format log entry: ${toLoggerError(error).message}`, { cause: error });
|
|
@@ -64,7 +122,7 @@ export async function dispatchEntry(configuration, entry, handleError) {
|
|
|
64
122
|
if (!registered.enabled) {
|
|
65
123
|
continue;
|
|
66
124
|
}
|
|
67
|
-
await writeTransport(configuration, registered, entry, formatted);
|
|
125
|
+
await withTransportTimeout(configuration.transportTimeout, registered.name, writeTransport(configuration, registered, entry, formatted));
|
|
68
126
|
}
|
|
69
127
|
catch (error) {
|
|
70
128
|
const transportError = new LoggerTransportError(`Failed to write log entry: ${toLoggerError(error).message}`, { cause: error });
|
|
@@ -72,4 +130,56 @@ export async function dispatchEntry(configuration, entry, handleError) {
|
|
|
72
130
|
}
|
|
73
131
|
}
|
|
74
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Dispatches an entry, completing synchronously where it can.
|
|
135
|
+
*
|
|
136
|
+
* Returns `undefined` when every configured transport finished
|
|
137
|
+
* synchronously (nothing to await), otherwise a promise covering the
|
|
138
|
+
* asynchronous remainder. `asynchronous: true` skips the fast path
|
|
139
|
+
* entirely and always defers, keeping the caller off the transport's
|
|
140
|
+
* critical path — the option was previously stored and never read, so
|
|
141
|
+
* both settings behaved identically.
|
|
142
|
+
*/
|
|
143
|
+
export function dispatchEntrySync(configuration, entry, handleError) {
|
|
144
|
+
if (configuration.asynchronous) {
|
|
145
|
+
// `dispatchEntry` runs synchronously up to its first await, so a
|
|
146
|
+
// synchronous transport would still execute inline. Hop a
|
|
147
|
+
// microtask first so `asynchronous: true` genuinely keeps the
|
|
148
|
+
// caller off the transport's critical path.
|
|
149
|
+
return Promise.resolve().then(() => dispatchEntry(configuration, entry, handleError));
|
|
150
|
+
}
|
|
151
|
+
let formatted;
|
|
152
|
+
try {
|
|
153
|
+
formatted = formatEntry(configuration, entry);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
handleError(new LoggerFormatterError(`Failed to format log entry: ${toLoggerError(error).message}`, { cause: error }));
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const pending = [];
|
|
160
|
+
for (const transport of configuration.transports) {
|
|
161
|
+
try {
|
|
162
|
+
if (!isLoggerTransport(transport)) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const registered = createLoggerTransport(transport);
|
|
166
|
+
if (!registered.enabled) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
const result = writeTransportMaybeSync(configuration, registered, entry, formatted);
|
|
170
|
+
if (result instanceof Promise) {
|
|
171
|
+
pending.push(withTransportTimeout(configuration.transportTimeout, registered.name, result).catch((error) => {
|
|
172
|
+
handleError(new LoggerTransportError(`Failed to write log entry: ${toLoggerError(error).message}`, { cause: error }));
|
|
173
|
+
}));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
handleError(new LoggerTransportError(`Failed to write log entry: ${toLoggerError(error).message}`, { cause: error }));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (pending.length === 0) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
return Promise.all(pending).then(() => undefined);
|
|
184
|
+
}
|
|
75
185
|
//# sourceMappingURL=loggerCoreMethods.dispatch.js.map
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Logger entry creation for dispatch.
|
|
3
3
|
*/
|
|
4
4
|
import { createLoggerEntry } from "../../../loggerEntry/loggerEntry.core.js";
|
|
5
|
+
import { createSecretMatcher, redactLogValue, LOGGER_REDACTION_TOKEN, } from "../../../loggerEntry/loggerEntryHelpers/loggerEntryHelpers.sanitize.js";
|
|
5
6
|
import { contextToLogMetadata, createLoggerContext, } from "../../../loggerContext/loggerContext.core.js";
|
|
6
7
|
/**
|
|
7
8
|
* Creates a normalized log entry.
|
|
@@ -13,11 +14,17 @@ export function createEntry(configuration, contextStorage, level, message, optio
|
|
|
13
14
|
const contextMetadata = activeContext
|
|
14
15
|
? contextToLogMetadata(activeContext)
|
|
15
16
|
: {};
|
|
16
|
-
const
|
|
17
|
+
const rawMetadata = {
|
|
17
18
|
...configuration.metadata,
|
|
18
19
|
...contextMetadata,
|
|
19
20
|
...(options.metadata ?? {}),
|
|
20
21
|
};
|
|
22
|
+
// Redaction is applied HERE, before the entry is frozen, so every
|
|
23
|
+
// formatter and every transport sees the already-masked value and no
|
|
24
|
+
// path can bypass it — including nested objects, arrays and getters.
|
|
25
|
+
const isSecret = createSecretMatcher(configuration.redact);
|
|
26
|
+
const replacement = configuration.redact.replacement ?? LOGGER_REDACTION_TOKEN;
|
|
27
|
+
const metadata = redactLogValue(rawMetadata, isSecret, replacement);
|
|
21
28
|
const context = options.context
|
|
22
29
|
? createLoggerContext({
|
|
23
30
|
parent: activeContext,
|
|
@@ -30,7 +37,7 @@ export function createEntry(configuration, contextStorage, level, message, optio
|
|
|
30
37
|
metadata,
|
|
31
38
|
context: context
|
|
32
39
|
? {
|
|
33
|
-
metadata: context.metadata,
|
|
40
|
+
metadata: redactLogValue(context.metadata, isSecret, replacement),
|
|
34
41
|
}
|
|
35
42
|
: undefined,
|
|
36
43
|
source: options.source,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { LoggerLevel, shouldLog, } from "../../../loggerLevel/loggerLevel.type.js";
|
|
5
5
|
import { LoggerConfigurationError } from "../../../loggerErrors/loggerError.base.js";
|
|
6
6
|
import { createEntry } from "./loggerCoreMethods.entry.js";
|
|
7
|
-
import {
|
|
7
|
+
import { dispatchEntrySync } from "./loggerCoreMethods.dispatch.js";
|
|
8
8
|
/**
|
|
9
9
|
* Level logging methods extracted from ZudojsLogger.
|
|
10
10
|
*/
|
|
@@ -18,6 +18,13 @@ export function logAtLevel(ctx, level, message, options = {}) {
|
|
|
18
18
|
throw new LoggerConfigurationError("Logger message must be a string.");
|
|
19
19
|
}
|
|
20
20
|
const entry = createEntry(ctx.configuration, ctx.contextStorage, level, message, options);
|
|
21
|
-
|
|
21
|
+
// Dispatch is asynchronous. It used to be fired and forgotten, so
|
|
22
|
+
// flush() and close() could return while entries were still in
|
|
23
|
+
// flight — messages were lost on process exit. Registering the
|
|
24
|
+
// promise lets the lifecycle methods drain it.
|
|
25
|
+
const dispatch = dispatchEntrySync(ctx.configuration, entry, (error) => ctx.handleInfrastructureError(error));
|
|
26
|
+
if (dispatch) {
|
|
27
|
+
ctx.trackDispatch(dispatch);
|
|
28
|
+
}
|
|
22
29
|
}
|
|
23
30
|
//# sourceMappingURL=loggerCoreMethods.level.js.map
|
|
@@ -48,6 +48,10 @@ export function disableLogger(ctx) {
|
|
|
48
48
|
*/
|
|
49
49
|
export async function flushLogger(ctx) {
|
|
50
50
|
ctx.assertActive();
|
|
51
|
+
// In-flight dispatches must land in the transports before those
|
|
52
|
+
// transports are asked to flush, otherwise flush() is a no-op for
|
|
53
|
+
// everything logged in the same tick.
|
|
54
|
+
await ctx.drainDispatches();
|
|
51
55
|
for (const transport of ctx.configuration.transports) {
|
|
52
56
|
if (!isLoggerTransport(transport)) {
|
|
53
57
|
continue;
|
|
@@ -68,11 +72,15 @@ export async function closeLogger(ctx) {
|
|
|
68
72
|
if (ctx.isDisposed()) {
|
|
69
73
|
return;
|
|
70
74
|
}
|
|
75
|
+
await ctx.drainDispatches();
|
|
71
76
|
for (const transport of ctx.configuration.transports) {
|
|
72
77
|
if (!isLoggerTransport(transport)) {
|
|
73
78
|
continue;
|
|
74
79
|
}
|
|
75
80
|
const registered = createLoggerTransport(transport);
|
|
81
|
+
if (registered.flush) {
|
|
82
|
+
await registered.flush();
|
|
83
|
+
}
|
|
76
84
|
if (registered.close) {
|
|
77
85
|
await registered.close();
|
|
78
86
|
}
|
|
@@ -6,4 +6,6 @@
|
|
|
6
6
|
export type { LogValue, LogMetadata, LoggerSource, LoggerEntryContext, } from "./loggerEntryHelpers.types.js";
|
|
7
7
|
export type { LoggerEntry, LoggerEntryInput, } from "./loggerEntryHelpers.interfaces.js";
|
|
8
8
|
export { serializeLoggerEntry, serializeLoggerError, serializeLoggerValue, loggerLevelNameFallback, } from "./loggerEntryHelpers.serialize.js";
|
|
9
|
+
export { LOGGER_REDACTION_TOKEN, DEFAULT_LOGGER_SECRET_PATTERN, escapeLogText, hasLogControlCharacters, createSecretMatcher, redactLogValue, } from "./loggerEntryHelpers.sanitize.js";
|
|
10
|
+
export type { LoggerRedactionOptions } from "./loggerEntryHelpers.sanitize.js";
|
|
9
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -4,4 +4,5 @@
|
|
|
4
4
|
* Logger entry helper types and utilities.
|
|
5
5
|
*/
|
|
6
6
|
export { serializeLoggerEntry, serializeLoggerError, serializeLoggerValue, loggerLevelNameFallback, } from "./loggerEntryHelpers.serialize.js";
|
|
7
|
+
export { LOGGER_REDACTION_TOKEN, DEFAULT_LOGGER_SECRET_PATTERN, escapeLogText, hasLogControlCharacters, createSecretMatcher, redactLogValue, } from "./loggerEntryHelpers.sanitize.js";
|
|
7
8
|
//# sourceMappingURL=index.js.map
|