@yadsh/dsh-plugin-log 0.1.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 +44 -0
- package/lib/dsh-home.d.ts +12 -0
- package/lib/dsh-home.d.ts.map +1 -0
- package/lib/dsh-home.js +17 -0
- package/lib/dsh-home.js.map +1 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +6 -0
- package/lib/index.js.map +1 -0
- package/lib/plugin-logger.d.ts +123 -0
- package/lib/plugin-logger.d.ts.map +1 -0
- package/lib/plugin-logger.js +625 -0
- package/lib/plugin-logger.js.map +1 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-plugins 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
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @yadsh/dsh-plugin-log
|
|
2
|
+
|
|
3
|
+
Structured JSON or readable-text file logging for server-side DeepSeek Harness
|
|
4
|
+
plugins, with daily rotation, retention, console mirroring, and runtime
|
|
5
|
+
discovery.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import {
|
|
9
|
+
getPluginLogger,
|
|
10
|
+
getRegisteredPluginLoggers,
|
|
11
|
+
setPluginLogFormat,
|
|
12
|
+
setPluginLogLevel,
|
|
13
|
+
subscribePluginLoggerRegistry,
|
|
14
|
+
} from "@yadsh/dsh-plugin-log";
|
|
15
|
+
|
|
16
|
+
const log = getPluginLogger({ pluginId: "dsh-example" });
|
|
17
|
+
log.info("example.ready");
|
|
18
|
+
|
|
19
|
+
const unsubscribe = subscribePluginLoggerRegistry((loggers) => {
|
|
20
|
+
console.info("active logger consumers", loggers);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
setPluginLogLevel("dsh-example", "debug");
|
|
24
|
+
setPluginLogFormat("text");
|
|
25
|
+
unsubscribe();
|
|
26
|
+
await log.close();
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The registry is process-wide and tracks active logger instances automatically.
|
|
30
|
+
`@yadsh/dsh-plugin-log-ui` uses it to provide live defaults, per-plugin level
|
|
31
|
+
overrides, and a `json`/`text` selector in DSH settings.
|
|
32
|
+
See the repository's
|
|
33
|
+
[`docs/PLUGIN_LOGGING.md`](https://github.com/xarleyn/dsh-plugins/blob/main/docs/PLUGIN_LOGGING.md)
|
|
34
|
+
for the complete behavior and API contract.
|
|
35
|
+
|
|
36
|
+
## Development
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pnpm --filter @yadsh/dsh-plugin-log check
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
|
|
44
|
+
MIT
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DSH home resolution for plugin runtime helpers.
|
|
3
|
+
*
|
|
4
|
+
* Kept free of DSH runtime dependencies so the logger can be used by any
|
|
5
|
+
* server-side package.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the DSH home directory: `$DSH_HOME` when set to a non-blank value,
|
|
9
|
+
* otherwise `~/.dsh` (the same convention as `dsh-draft-sessions` storage).
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveDshHome(env?: NodeJS.ProcessEnv): string;
|
|
12
|
+
//# sourceMappingURL=dsh-home.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dsh-home.d.ts","sourceRoot":"","sources":["../src/dsh-home.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAG3E"}
|
package/lib/dsh-home.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DSH home resolution for plugin runtime helpers.
|
|
3
|
+
*
|
|
4
|
+
* Kept free of DSH runtime dependencies so the logger can be used by any
|
|
5
|
+
* server-side package.
|
|
6
|
+
*/
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
import { join, resolve } from "node:path";
|
|
9
|
+
/**
|
|
10
|
+
* Resolve the DSH home directory: `$DSH_HOME` when set to a non-blank value,
|
|
11
|
+
* otherwise `~/.dsh` (the same convention as `dsh-draft-sessions` storage).
|
|
12
|
+
*/
|
|
13
|
+
export function resolveDshHome(env = process.env) {
|
|
14
|
+
const configured = env.DSH_HOME?.trim();
|
|
15
|
+
return configured ? resolve(configured) : join(homedir(), ".dsh");
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=dsh-home.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dsh-home.js","sourceRoot":"","sources":["../src/dsh-home.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAAyB,OAAO,CAAC,GAAG;IACjE,MAAM,UAAU,GAAG,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;IACxC,OAAO,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC;AACpE,CAAC"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
|
package/lib/index.js
ADDED
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared file logger for server-side DSH plugins. The wrapper:
|
|
3
|
+
*
|
|
4
|
+
* - wraps `pino` for severity levels and JSON/text serialization;
|
|
5
|
+
* - writes daily files `<dir>/<YYYY-MM-DD>.log`, by default under
|
|
6
|
+
* `<$DSH_HOME>/logs/<pluginId>`;
|
|
7
|
+
* - mirrors selected records to an injectable console sink (default level
|
|
8
|
+
* `warn`) so operators still see problems live;
|
|
9
|
+
* - never throws at runtime: file-system failures degrade to console-only
|
|
10
|
+
* logging (fail-open), and closed loggers silently drop records;
|
|
11
|
+
* - disables file output when `DSH_LOG_DISABLED=1`, and under `NODE_ENV=test`
|
|
12
|
+
* unless `dir` is set explicitly (unit tests never touch a real home).
|
|
13
|
+
*
|
|
14
|
+
* Record shape (one JSON object per line): pino's `level` (numeric),
|
|
15
|
+
* `time` (epoch ms) and `msg` (= the event code), plus `plugin` and the
|
|
16
|
+
* caller's fields; `child(module)` adds `module`. Reserved pino keys
|
|
17
|
+
* (`level`, `time`, `msg`, `plugin`, `module`) must not be used as field
|
|
18
|
+
* names.
|
|
19
|
+
*/
|
|
20
|
+
/** Ordered severity levels; `silent` disables the logger entirely. */
|
|
21
|
+
export declare const PLUGIN_LOG_LEVELS: readonly ["trace", "debug", "info", "warn", "error", "fatal", "silent"];
|
|
22
|
+
export type PluginLogLevel = (typeof PLUGIN_LOG_LEVELS)[number];
|
|
23
|
+
/** File serialization formats. JSON is NDJSON; text is one readable line. */
|
|
24
|
+
export declare const PLUGIN_LOG_FORMATS: readonly ["json", "text"];
|
|
25
|
+
export type PluginLogFormat = (typeof PLUGIN_LOG_FORMATS)[number];
|
|
26
|
+
/** Every level except `silent` (which also disables the console mirror). */
|
|
27
|
+
export type ConsoleLevel = Exclude<PluginLogLevel, "silent">;
|
|
28
|
+
/**
|
|
29
|
+
* Receives console-mirrored records. Must not throw; the wrapper guards every
|
|
30
|
+
* call regardless.
|
|
31
|
+
*/
|
|
32
|
+
export type PluginConsoleSink = (level: ConsoleLevel, message: string) => void;
|
|
33
|
+
/** Default console mirror threshold. */
|
|
34
|
+
export declare const DEFAULT_CONSOLE_LEVEL: PluginLogLevel;
|
|
35
|
+
/** Daily log files kept per plugin by default (0 = keep forever). */
|
|
36
|
+
export declare const DEFAULT_LOG_RETENTION_DAYS = 14;
|
|
37
|
+
/** Type guard for level strings (config parsing, env overrides). */
|
|
38
|
+
export declare function isPluginLogLevel(value: unknown): value is PluginLogLevel;
|
|
39
|
+
/** Type guard for file serialization format strings. */
|
|
40
|
+
export declare function isPluginLogFormat(value: unknown): value is PluginLogFormat;
|
|
41
|
+
/** Logger configuration; every field except `pluginId` is optional. */
|
|
42
|
+
export interface PluginLoggerOptions {
|
|
43
|
+
/**
|
|
44
|
+
* Plugin id: directory name, `plugin` record field and env-prefix source
|
|
45
|
+
* (`DSH_LOG_LEVEL_<ID>`). Must match `[A-Za-z0-9][A-Za-z0-9._-]*`.
|
|
46
|
+
*/
|
|
47
|
+
readonly pluginId: string;
|
|
48
|
+
/** Severity threshold. Default: `DSH_LOG_LEVEL_<ID>` / `DSH_LOG_LEVEL` env, else `info`. */
|
|
49
|
+
readonly level?: PluginLogLevel;
|
|
50
|
+
/** File serialization format. Default: `json`. */
|
|
51
|
+
readonly format?: PluginLogFormat;
|
|
52
|
+
/** Absolute log directory. Default: `<$DSH_HOME>/logs/<pluginId>`. */
|
|
53
|
+
readonly dir?: string;
|
|
54
|
+
/** Overrides the DSH home used to build the default `dir` (tests). */
|
|
55
|
+
readonly dshHome?: string;
|
|
56
|
+
/** Console mirror threshold; `silent` disables mirroring. Default: `warn`. */
|
|
57
|
+
readonly console?: PluginLogLevel;
|
|
58
|
+
/** Mirror target. Default: the global `console`. */
|
|
59
|
+
readonly consoleSink?: PluginConsoleSink;
|
|
60
|
+
/** Daily files older than this are deleted on rollover. Default: 14; 0 disables. */
|
|
61
|
+
readonly retentionDays?: number;
|
|
62
|
+
/** Master switch for file output. Default: auto (see the module docs). */
|
|
63
|
+
readonly file?: boolean;
|
|
64
|
+
/** Record fields to redact (pino `redact` paths), e.g. `["apiKey"]`. */
|
|
65
|
+
readonly redact?: readonly string[];
|
|
66
|
+
/** Clock for file naming, rollover and retention (tests). */
|
|
67
|
+
readonly now?: () => number;
|
|
68
|
+
}
|
|
69
|
+
/** Stable logging surface shared by server-side plugins. */
|
|
70
|
+
export interface PluginLogger {
|
|
71
|
+
trace(event: string, fields?: Record<string, unknown>): void;
|
|
72
|
+
debug(event: string, fields?: Record<string, unknown>): void;
|
|
73
|
+
info(event: string, fields?: Record<string, unknown>): void;
|
|
74
|
+
warn(event: string, fields?: Record<string, unknown>): void;
|
|
75
|
+
error(event: string, fields?: Record<string, unknown>): void;
|
|
76
|
+
fatal(event: string, fields?: Record<string, unknown>): void;
|
|
77
|
+
/** Bound sub-logger that adds a `module` field to every record. */
|
|
78
|
+
child(module: string): PluginLogger;
|
|
79
|
+
/** Current severity threshold. */
|
|
80
|
+
get level(): PluginLogLevel;
|
|
81
|
+
/** Change the severity threshold at runtime. */
|
|
82
|
+
setLevel(level: PluginLogLevel): void;
|
|
83
|
+
/** Current file serialization format. */
|
|
84
|
+
get format(): PluginLogFormat;
|
|
85
|
+
/** Change the file serialization format at runtime. */
|
|
86
|
+
setFormat(format: PluginLogFormat): void;
|
|
87
|
+
/** Best-effort synchronous flush of buffered file output. */
|
|
88
|
+
flush(): void;
|
|
89
|
+
/** Flush and close the destination; idempotent; later writes are dropped. */
|
|
90
|
+
close(): Promise<void>;
|
|
91
|
+
}
|
|
92
|
+
/** Runtime metadata exposed to logging-settings and diagnostics consumers. */
|
|
93
|
+
export interface RegisteredPluginLogger {
|
|
94
|
+
/** Process-local identity of this root logger instance. */
|
|
95
|
+
readonly registrationId: number;
|
|
96
|
+
readonly pluginId: string;
|
|
97
|
+
readonly dir: string;
|
|
98
|
+
readonly level: PluginLogLevel;
|
|
99
|
+
readonly format: PluginLogFormat;
|
|
100
|
+
}
|
|
101
|
+
/** Receives a complete snapshot whenever the process-wide registry changes. */
|
|
102
|
+
export type PluginLoggerRegistryListener = (loggers: readonly RegisteredPluginLogger[]) => void;
|
|
103
|
+
/** Snapshot of every active root logger, sorted for deterministic UI output. */
|
|
104
|
+
export declare function getRegisteredPluginLoggers(): readonly RegisteredPluginLogger[];
|
|
105
|
+
/**
|
|
106
|
+
* Subscribe to registry snapshots. The listener is called immediately and
|
|
107
|
+
* after registration, close, or a level change. Returns an idempotent cleanup.
|
|
108
|
+
*/
|
|
109
|
+
export declare function subscribePluginLoggerRegistry(listener: PluginLoggerRegistryListener): () => void;
|
|
110
|
+
/** Change the level of every active logger owned by `pluginId`. */
|
|
111
|
+
export declare function setPluginLogLevel(pluginId: string, level: PluginLogLevel): number;
|
|
112
|
+
/** Change the format of every active plugin logger. */
|
|
113
|
+
export declare function setPluginLogFormat(format: PluginLogFormat): number;
|
|
114
|
+
/** Create a standalone logger instance (no caching). */
|
|
115
|
+
export declare function createPluginLogger(options: PluginLoggerOptions): PluginLogger;
|
|
116
|
+
/**
|
|
117
|
+
* Create or return the cached logger for `pluginId` + resolved `dir`. A later
|
|
118
|
+
* call with an explicit `level` updates the cached instance's threshold, so
|
|
119
|
+
* plugin config reloads take effect. `close()` evicts the cache entry; the
|
|
120
|
+
* next call creates a fresh instance.
|
|
121
|
+
*/
|
|
122
|
+
export declare function getPluginLogger(options: PluginLoggerOptions): PluginLogger;
|
|
123
|
+
//# sourceMappingURL=plugin-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-logger.d.ts","sourceRoot":"","sources":["../src/plugin-logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared file logger for server-side DSH plugins. The wrapper:
|
|
3
|
+
*
|
|
4
|
+
* - wraps `pino` for severity levels and JSON/text serialization;
|
|
5
|
+
* - writes daily files `<dir>/<YYYY-MM-DD>.log`, by default under
|
|
6
|
+
* `<$DSH_HOME>/logs/<pluginId>`;
|
|
7
|
+
* - mirrors selected records to an injectable console sink (default level
|
|
8
|
+
* `warn`) so operators still see problems live;
|
|
9
|
+
* - never throws at runtime: file-system failures degrade to console-only
|
|
10
|
+
* logging (fail-open), and closed loggers silently drop records;
|
|
11
|
+
* - disables file output when `DSH_LOG_DISABLED=1`, and under `NODE_ENV=test`
|
|
12
|
+
* unless `dir` is set explicitly (unit tests never touch a real home).
|
|
13
|
+
*
|
|
14
|
+
* Record shape (one JSON object per line): pino's `level` (numeric),
|
|
15
|
+
* `time` (epoch ms) and `msg` (= the event code), plus `plugin` and the
|
|
16
|
+
* caller's fields; `child(module)` adds `module`. Reserved pino keys
|
|
17
|
+
* (`level`, `time`, `msg`, `plugin`, `module`) must not be used as field
|
|
18
|
+
* names.
|
|
19
|
+
*/
|
|
20
|
+
import { mkdirSync } from "node:fs";
|
|
21
|
+
import { readdir, unlink } from "node:fs/promises";
|
|
22
|
+
import { join } from "node:path";
|
|
23
|
+
import { Writable } from "node:stream";
|
|
24
|
+
import pino from "pino";
|
|
25
|
+
import { resolveDshHome } from "./dsh-home.js";
|
|
26
|
+
/** Ordered severity levels; `silent` disables the logger entirely. */
|
|
27
|
+
export const PLUGIN_LOG_LEVELS = [
|
|
28
|
+
"trace",
|
|
29
|
+
"debug",
|
|
30
|
+
"info",
|
|
31
|
+
"warn",
|
|
32
|
+
"error",
|
|
33
|
+
"fatal",
|
|
34
|
+
"silent",
|
|
35
|
+
];
|
|
36
|
+
/** File serialization formats. JSON is NDJSON; text is one readable line. */
|
|
37
|
+
export const PLUGIN_LOG_FORMATS = ["json", "text"];
|
|
38
|
+
/** Default console mirror threshold. */
|
|
39
|
+
export const DEFAULT_CONSOLE_LEVEL = "warn";
|
|
40
|
+
/** Daily log files kept per plugin by default (0 = keep forever). */
|
|
41
|
+
export const DEFAULT_LOG_RETENTION_DAYS = 14;
|
|
42
|
+
const LEVEL_WEIGHT = {
|
|
43
|
+
trace: 10,
|
|
44
|
+
debug: 20,
|
|
45
|
+
info: 30,
|
|
46
|
+
warn: 40,
|
|
47
|
+
error: 50,
|
|
48
|
+
fatal: 60,
|
|
49
|
+
};
|
|
50
|
+
const DAY_MS = 86_400_000;
|
|
51
|
+
const LOG_FILE_PATTERN = /^(\d{4}-\d{2}-\d{2})\.log$/;
|
|
52
|
+
function weightOf(level) {
|
|
53
|
+
return level === "silent" ? Number.POSITIVE_INFINITY : LEVEL_WEIGHT[level];
|
|
54
|
+
}
|
|
55
|
+
/** Type guard for level strings (config parsing, env overrides). */
|
|
56
|
+
export function isPluginLogLevel(value) {
|
|
57
|
+
return typeof value === "string" && PLUGIN_LOG_LEVELS.includes(value);
|
|
58
|
+
}
|
|
59
|
+
/** Type guard for file serialization format strings. */
|
|
60
|
+
export function isPluginLogFormat(value) {
|
|
61
|
+
return typeof value === "string" && PLUGIN_LOG_FORMATS.includes(value);
|
|
62
|
+
}
|
|
63
|
+
const REGISTRY_SYMBOL = Symbol.for("@yadsh/dsh-plugin-log/registry/v1");
|
|
64
|
+
function registryState() {
|
|
65
|
+
const globalObject = globalThis;
|
|
66
|
+
const existing = globalObject[REGISTRY_SYMBOL];
|
|
67
|
+
if (existing?.version === 1)
|
|
68
|
+
return existing;
|
|
69
|
+
const created = {
|
|
70
|
+
version: 1,
|
|
71
|
+
nextRegistrationId: 1,
|
|
72
|
+
cache: new Map(),
|
|
73
|
+
active: new Map(),
|
|
74
|
+
listeners: new Set(),
|
|
75
|
+
};
|
|
76
|
+
globalObject[REGISTRY_SYMBOL] = created;
|
|
77
|
+
return created;
|
|
78
|
+
}
|
|
79
|
+
/** Snapshot of every active root logger, sorted for deterministic UI output. */
|
|
80
|
+
export function getRegisteredPluginLoggers() {
|
|
81
|
+
const snapshots = [];
|
|
82
|
+
for (const [registrationId, core] of registryState().active) {
|
|
83
|
+
if (core.isClosed())
|
|
84
|
+
continue;
|
|
85
|
+
snapshots.push(Object.freeze({
|
|
86
|
+
registrationId,
|
|
87
|
+
pluginId: core.pluginId,
|
|
88
|
+
dir: core.dir,
|
|
89
|
+
level: core.level,
|
|
90
|
+
format: core.format,
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
return Object.freeze(snapshots.sort((left, right) => left.pluginId.localeCompare(right.pluginId) ||
|
|
94
|
+
left.dir.localeCompare(right.dir) ||
|
|
95
|
+
left.registrationId - right.registrationId));
|
|
96
|
+
}
|
|
97
|
+
function notifyRegistryListeners() {
|
|
98
|
+
const state = registryState();
|
|
99
|
+
const snapshot = getRegisteredPluginLoggers();
|
|
100
|
+
for (const listener of state.listeners) {
|
|
101
|
+
try {
|
|
102
|
+
listener(snapshot);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// Registry observers must never affect logging or plugin execution.
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Subscribe to registry snapshots. The listener is called immediately and
|
|
111
|
+
* after registration, close, or a level change. Returns an idempotent cleanup.
|
|
112
|
+
*/
|
|
113
|
+
export function subscribePluginLoggerRegistry(listener) {
|
|
114
|
+
const listeners = registryState().listeners;
|
|
115
|
+
listeners.add(listener);
|
|
116
|
+
try {
|
|
117
|
+
listener(getRegisteredPluginLoggers());
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// Keep the registry fail-open just like the logger itself.
|
|
121
|
+
}
|
|
122
|
+
return () => {
|
|
123
|
+
listeners.delete(listener);
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/** Change the level of every active logger owned by `pluginId`. */
|
|
127
|
+
export function setPluginLogLevel(pluginId, level) {
|
|
128
|
+
if (!isPluginLogLevel(level)) {
|
|
129
|
+
throw new TypeError(`unknown plugin log level: ${JSON.stringify(level)}`);
|
|
130
|
+
}
|
|
131
|
+
let updated = 0;
|
|
132
|
+
for (const core of registryState().active.values()) {
|
|
133
|
+
if (!core.isClosed() && core.pluginId === pluginId) {
|
|
134
|
+
core.setLevel(level);
|
|
135
|
+
updated += 1;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return updated;
|
|
139
|
+
}
|
|
140
|
+
/** Change the format of every active plugin logger. */
|
|
141
|
+
export function setPluginLogFormat(format) {
|
|
142
|
+
if (!isPluginLogFormat(format)) {
|
|
143
|
+
throw new TypeError(`unknown plugin log format: ${JSON.stringify(format)}`);
|
|
144
|
+
}
|
|
145
|
+
let updated = 0;
|
|
146
|
+
for (const core of registryState().active.values()) {
|
|
147
|
+
if (!core.isClosed()) {
|
|
148
|
+
core.setFormat(format);
|
|
149
|
+
updated += 1;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return updated;
|
|
153
|
+
}
|
|
154
|
+
function formatConsole(event, fields) {
|
|
155
|
+
if (fields === undefined)
|
|
156
|
+
return event;
|
|
157
|
+
const parts = Object.entries(fields).map(([key, value]) => {
|
|
158
|
+
const rendered = typeof value === "string" ? value : JSON.stringify(value);
|
|
159
|
+
return `${key}=${rendered}`;
|
|
160
|
+
});
|
|
161
|
+
return parts.length === 0 ? event : `${event} ${parts.join(" ")}`;
|
|
162
|
+
}
|
|
163
|
+
/** Local-calendar date stamp used in file names (sorts lexically). */
|
|
164
|
+
function dayStamp(ms) {
|
|
165
|
+
const date = new Date(ms);
|
|
166
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
167
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
168
|
+
return `${date.getFullYear()}-${month}-${day}`;
|
|
169
|
+
}
|
|
170
|
+
function envLevelOverride(pluginId) {
|
|
171
|
+
const env = process.env;
|
|
172
|
+
const specific = env[`DSH_LOG_LEVEL_${pluginId.replaceAll("-", "_").toUpperCase()}`];
|
|
173
|
+
if (isPluginLogLevel(specific))
|
|
174
|
+
return specific;
|
|
175
|
+
return isPluginLogLevel(env.DSH_LOG_LEVEL) ? env.DSH_LOG_LEVEL : undefined;
|
|
176
|
+
}
|
|
177
|
+
function envFileDisabled(explicitDir) {
|
|
178
|
+
const flag = process.env.DSH_LOG_DISABLED ?? process.env.DSH_PLUGIN_LOG_DISABLED;
|
|
179
|
+
if (flag === "1" || flag === "true")
|
|
180
|
+
return true;
|
|
181
|
+
// Unit tests must never write into a real DSH home unless a dir is explicit.
|
|
182
|
+
return process.env.NODE_ENV === "test" && !explicitDir;
|
|
183
|
+
}
|
|
184
|
+
async function sweepOldLogFiles(dir, retentionDays, nowMs) {
|
|
185
|
+
if (retentionDays <= 0)
|
|
186
|
+
return;
|
|
187
|
+
const cutoff = nowMs - retentionDays * DAY_MS;
|
|
188
|
+
const entries = await readdir(dir).catch(() => []);
|
|
189
|
+
for (const entry of entries) {
|
|
190
|
+
const match = LOG_FILE_PATTERN.exec(entry);
|
|
191
|
+
if (match === null || match[1] === undefined)
|
|
192
|
+
continue;
|
|
193
|
+
const stampMs = Date.parse(`${match[1]}T00:00:00`);
|
|
194
|
+
if (!Number.isFinite(stampMs) || stampMs >= cutoff)
|
|
195
|
+
continue;
|
|
196
|
+
await unlink(join(dir, entry)).catch(() => undefined);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const LEVEL_LABEL = new Map(Object.entries(LEVEL_WEIGHT).map(([level, weight]) => [weight, level.toUpperCase()]));
|
|
200
|
+
function textValue(value) {
|
|
201
|
+
if (typeof value === "string")
|
|
202
|
+
return JSON.stringify(value);
|
|
203
|
+
const rendered = JSON.stringify(value);
|
|
204
|
+
return rendered === undefined ? String(value) : rendered;
|
|
205
|
+
}
|
|
206
|
+
function renderTextRecord(line) {
|
|
207
|
+
try {
|
|
208
|
+
const record = JSON.parse(line);
|
|
209
|
+
const time = typeof record["time"] === "number"
|
|
210
|
+
? new Date(record["time"]).toISOString()
|
|
211
|
+
: String(record["time"] ?? "-");
|
|
212
|
+
const numericLevel = typeof record["level"] === "number" ? record["level"] : Number.NaN;
|
|
213
|
+
const level = (LEVEL_LABEL.get(numericLevel) ?? String(record["level"] ?? "LOG")).padEnd(5);
|
|
214
|
+
const plugin = String(record["plugin"] ?? "unknown");
|
|
215
|
+
const module = typeof record["module"] === "string" ? `/${record["module"]}` : "";
|
|
216
|
+
const event = String(record["msg"] ?? "");
|
|
217
|
+
const reserved = new Set(["level", "time", "plugin", "module", "msg"]);
|
|
218
|
+
const fields = Object.entries(record)
|
|
219
|
+
.filter(([key]) => !reserved.has(key))
|
|
220
|
+
.map(([key, value]) => `${key}=${textValue(value)}`);
|
|
221
|
+
return `${time} ${level} [${plugin}${module}] ${event}${fields.length === 0 ? "" : ` ${fields.join(" ")}`}\n`;
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
return `${line}\n`;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/** Converts pino NDJSON chunks to readable lines before the file destination. */
|
|
228
|
+
class TextDestination extends Writable {
|
|
229
|
+
target;
|
|
230
|
+
buffered = "";
|
|
231
|
+
constructor(target) {
|
|
232
|
+
super();
|
|
233
|
+
this.target = target;
|
|
234
|
+
}
|
|
235
|
+
_write(chunk, _encoding, callback) {
|
|
236
|
+
try {
|
|
237
|
+
this.buffered += chunk.toString();
|
|
238
|
+
this.writeCompleteLines();
|
|
239
|
+
callback();
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
callback(error instanceof Error ? error : new Error(String(error)));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
_final(callback) {
|
|
246
|
+
try {
|
|
247
|
+
if (this.buffered.length > 0) {
|
|
248
|
+
this.target.write(renderTextRecord(this.buffered));
|
|
249
|
+
this.buffered = "";
|
|
250
|
+
}
|
|
251
|
+
if (this.target.destroyed === true) {
|
|
252
|
+
callback();
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
if (this.target.once !== undefined) {
|
|
256
|
+
this.target.once("close", callback);
|
|
257
|
+
this.target.end?.();
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
this.target.end?.();
|
|
261
|
+
callback();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
callback(error instanceof Error ? error : new Error(String(error)));
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
flushSync() {
|
|
269
|
+
this.writeCompleteLines();
|
|
270
|
+
this.target.flushSync?.();
|
|
271
|
+
}
|
|
272
|
+
writeCompleteLines() {
|
|
273
|
+
let newline = this.buffered.indexOf("\n");
|
|
274
|
+
while (newline >= 0) {
|
|
275
|
+
const line = this.buffered.slice(0, newline);
|
|
276
|
+
this.buffered = this.buffered.slice(newline + 1);
|
|
277
|
+
if (line.length > 0)
|
|
278
|
+
this.target.write(renderTextRecord(line));
|
|
279
|
+
newline = this.buffered.indexOf("\n");
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
let sharedDevNull;
|
|
284
|
+
function devNull() {
|
|
285
|
+
sharedDevNull ??= new Writable({
|
|
286
|
+
write(_chunk, _encoding, callback) {
|
|
287
|
+
callback();
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
return sharedDevNull;
|
|
291
|
+
}
|
|
292
|
+
function closeQuietly(destination) {
|
|
293
|
+
try {
|
|
294
|
+
destination.end?.();
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
// Fail-open: closing must never surface.
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* SonicBoom's `end()` takes no callback — completion is signaled by the
|
|
302
|
+
* `close` event. A bounded guard keeps a wedged stream from hanging plugin
|
|
303
|
+
* disposal forever.
|
|
304
|
+
*/
|
|
305
|
+
function closeDestination(destination) {
|
|
306
|
+
return new Promise((resolve) => {
|
|
307
|
+
if (destination.destroyed === true) {
|
|
308
|
+
resolve();
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
let settled = false;
|
|
312
|
+
const done = () => {
|
|
313
|
+
if (settled)
|
|
314
|
+
return;
|
|
315
|
+
settled = true;
|
|
316
|
+
clearTimeout(guard);
|
|
317
|
+
resolve();
|
|
318
|
+
};
|
|
319
|
+
const guard = setTimeout(done, 1000);
|
|
320
|
+
guard.unref();
|
|
321
|
+
try {
|
|
322
|
+
destination.once?.("close", done);
|
|
323
|
+
destination.end?.();
|
|
324
|
+
}
|
|
325
|
+
catch {
|
|
326
|
+
done();
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
function errorMessage(error) {
|
|
331
|
+
return error instanceof Error ? error.message : String(error);
|
|
332
|
+
}
|
|
333
|
+
const defaultSink = (level, message) => {
|
|
334
|
+
if (level === "warn")
|
|
335
|
+
console.warn(message);
|
|
336
|
+
else if (level === "error" || level === "fatal")
|
|
337
|
+
console.error(message);
|
|
338
|
+
else if (level === "trace" || level === "debug")
|
|
339
|
+
console.log(message);
|
|
340
|
+
else
|
|
341
|
+
console.info(message);
|
|
342
|
+
};
|
|
343
|
+
/** Mutable state shared by a root logger and all of its `child()` views. */
|
|
344
|
+
class LoggerCore {
|
|
345
|
+
pluginId;
|
|
346
|
+
dir;
|
|
347
|
+
registrationId;
|
|
348
|
+
levelName;
|
|
349
|
+
formatName;
|
|
350
|
+
consoleLevel;
|
|
351
|
+
sink;
|
|
352
|
+
retentionDays;
|
|
353
|
+
redact;
|
|
354
|
+
clock;
|
|
355
|
+
fileEnabled;
|
|
356
|
+
closed = false;
|
|
357
|
+
destination;
|
|
358
|
+
destinationDay = "";
|
|
359
|
+
root;
|
|
360
|
+
children = new Map();
|
|
361
|
+
retention;
|
|
362
|
+
constructor(options) {
|
|
363
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(options.pluginId)) {
|
|
364
|
+
throw new TypeError(`pluginId must match [A-Za-z0-9][A-Za-z0-9._-]*, got ${JSON.stringify(options.pluginId)}`);
|
|
365
|
+
}
|
|
366
|
+
this.pluginId = options.pluginId;
|
|
367
|
+
const home = options.dshHome ?? resolveDshHome();
|
|
368
|
+
this.dir = options.dir ?? join(home, "logs", options.pluginId);
|
|
369
|
+
this.levelName = options.level ?? envLevelOverride(options.pluginId) ?? "info";
|
|
370
|
+
this.formatName = options.format ?? "json";
|
|
371
|
+
this.consoleLevel = options.console ?? DEFAULT_CONSOLE_LEVEL;
|
|
372
|
+
this.sink = options.consoleSink ?? defaultSink;
|
|
373
|
+
this.retentionDays = Math.max(0, Math.floor(options.retentionDays ?? DEFAULT_LOG_RETENTION_DAYS));
|
|
374
|
+
this.redact = options.redact ?? [];
|
|
375
|
+
this.clock = options.now ?? Date.now;
|
|
376
|
+
this.fileEnabled = (options.file ?? true) && !envFileDisabled(options.dir !== undefined);
|
|
377
|
+
}
|
|
378
|
+
isClosed() {
|
|
379
|
+
return this.closed;
|
|
380
|
+
}
|
|
381
|
+
activate() {
|
|
382
|
+
if (this.closed || this.registrationId !== undefined)
|
|
383
|
+
return;
|
|
384
|
+
const state = registryState();
|
|
385
|
+
this.registrationId = state.nextRegistrationId;
|
|
386
|
+
state.nextRegistrationId += 1;
|
|
387
|
+
state.active.set(this.registrationId, this);
|
|
388
|
+
notifyRegistryListeners();
|
|
389
|
+
}
|
|
390
|
+
key() {
|
|
391
|
+
return `${this.pluginId}\u0000${this.dir}`;
|
|
392
|
+
}
|
|
393
|
+
get level() {
|
|
394
|
+
return this.levelName;
|
|
395
|
+
}
|
|
396
|
+
setLevel(level) {
|
|
397
|
+
if (!isPluginLogLevel(level)) {
|
|
398
|
+
throw new TypeError(`unknown plugin log level: ${JSON.stringify(level)}`);
|
|
399
|
+
}
|
|
400
|
+
if (level === this.levelName)
|
|
401
|
+
return;
|
|
402
|
+
this.levelName = level;
|
|
403
|
+
// Rebuild the destination on the next write so the new threshold takes
|
|
404
|
+
// effect without touching the file handle while silent.
|
|
405
|
+
this.destinationDay = "";
|
|
406
|
+
if (this.registrationId !== undefined)
|
|
407
|
+
notifyRegistryListeners();
|
|
408
|
+
}
|
|
409
|
+
get format() {
|
|
410
|
+
return this.formatName;
|
|
411
|
+
}
|
|
412
|
+
setFormat(format) {
|
|
413
|
+
if (!isPluginLogFormat(format)) {
|
|
414
|
+
throw new TypeError(`unknown plugin log format: ${JSON.stringify(format)}`);
|
|
415
|
+
}
|
|
416
|
+
if (format === this.formatName)
|
|
417
|
+
return;
|
|
418
|
+
this.formatName = format;
|
|
419
|
+
this.destinationDay = "";
|
|
420
|
+
if (this.registrationId !== undefined)
|
|
421
|
+
notifyRegistryListeners();
|
|
422
|
+
}
|
|
423
|
+
write(moduleField, level, event, fields) {
|
|
424
|
+
if (this.closed || this.levelName === "silent")
|
|
425
|
+
return;
|
|
426
|
+
if (weightOf(level) < weightOf(this.levelName)) {
|
|
427
|
+
this.mirror(moduleField, level, event, fields);
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
this.open();
|
|
431
|
+
const target = this.targetFor(moduleField);
|
|
432
|
+
if (target !== undefined) {
|
|
433
|
+
try {
|
|
434
|
+
target[level](fields ?? {}, event);
|
|
435
|
+
}
|
|
436
|
+
catch {
|
|
437
|
+
// Fail-open: serialization problems must never break the plugin.
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
this.mirror(moduleField, level, event, fields);
|
|
441
|
+
}
|
|
442
|
+
flush() {
|
|
443
|
+
try {
|
|
444
|
+
this.destination?.flushSync?.();
|
|
445
|
+
}
|
|
446
|
+
catch {
|
|
447
|
+
// Fail-open.
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
async close() {
|
|
451
|
+
if (this.closed)
|
|
452
|
+
return;
|
|
453
|
+
this.closed = true;
|
|
454
|
+
const state = registryState();
|
|
455
|
+
const cached = state.cache.get(this.key());
|
|
456
|
+
if (cached?.core === this)
|
|
457
|
+
state.cache.delete(this.key());
|
|
458
|
+
if (this.registrationId !== undefined) {
|
|
459
|
+
state.active.delete(this.registrationId);
|
|
460
|
+
this.registrationId = undefined;
|
|
461
|
+
notifyRegistryListeners();
|
|
462
|
+
}
|
|
463
|
+
const destination = this.destination;
|
|
464
|
+
this.destination = undefined;
|
|
465
|
+
this.root = undefined;
|
|
466
|
+
this.children.clear();
|
|
467
|
+
this.destinationDay = "";
|
|
468
|
+
await this.retention;
|
|
469
|
+
if (destination !== undefined)
|
|
470
|
+
await closeDestination(destination);
|
|
471
|
+
}
|
|
472
|
+
/** Open (or roll over to) the destination file for the current day. */
|
|
473
|
+
open() {
|
|
474
|
+
const stamp = dayStamp(this.clock());
|
|
475
|
+
if (this.root !== undefined && stamp === this.destinationDay)
|
|
476
|
+
return;
|
|
477
|
+
this.rollover(stamp);
|
|
478
|
+
}
|
|
479
|
+
rollover(stamp) {
|
|
480
|
+
this.destinationDay = stamp;
|
|
481
|
+
let next;
|
|
482
|
+
if (this.fileEnabled) {
|
|
483
|
+
try {
|
|
484
|
+
mkdirSync(this.dir, { recursive: true });
|
|
485
|
+
const fileDestination = pino.destination({
|
|
486
|
+
dest: join(this.dir, `${stamp}.log`),
|
|
487
|
+
append: true,
|
|
488
|
+
mkdir: true,
|
|
489
|
+
sync: false,
|
|
490
|
+
minLength: 0,
|
|
491
|
+
});
|
|
492
|
+
next = this.formatName === "text"
|
|
493
|
+
? new TextDestination(fileDestination)
|
|
494
|
+
: fileDestination;
|
|
495
|
+
}
|
|
496
|
+
catch (error) {
|
|
497
|
+
// Fail-open: an unusable log directory degrades to console-only.
|
|
498
|
+
this.fileEnabled = false;
|
|
499
|
+
next = undefined;
|
|
500
|
+
this.mirror(undefined, "warn", "logging.file_disabled", { reason: errorMessage(error) });
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
const previous = this.destination;
|
|
504
|
+
this.destination = next;
|
|
505
|
+
this.children.clear();
|
|
506
|
+
this.root = pino({
|
|
507
|
+
level: this.levelName,
|
|
508
|
+
base: { plugin: this.pluginId },
|
|
509
|
+
...(this.redact.length > 0 ? { redact: [...this.redact] } : {}),
|
|
510
|
+
}, next ?? devNull());
|
|
511
|
+
if (previous !== undefined && previous !== next)
|
|
512
|
+
closeQuietly(previous);
|
|
513
|
+
if (this.fileEnabled)
|
|
514
|
+
this.scheduleRetentionSweep();
|
|
515
|
+
}
|
|
516
|
+
targetFor(moduleField) {
|
|
517
|
+
const root = this.root;
|
|
518
|
+
if (root === undefined)
|
|
519
|
+
return undefined;
|
|
520
|
+
if (moduleField === undefined)
|
|
521
|
+
return root;
|
|
522
|
+
const cached = this.children.get(moduleField);
|
|
523
|
+
if (cached !== undefined)
|
|
524
|
+
return cached;
|
|
525
|
+
const created = root.child({ module: moduleField });
|
|
526
|
+
this.children.set(moduleField, created);
|
|
527
|
+
return created;
|
|
528
|
+
}
|
|
529
|
+
mirror(moduleField, level, event, fields) {
|
|
530
|
+
if (this.consoleLevel === "silent")
|
|
531
|
+
return;
|
|
532
|
+
if (weightOf(level) < weightOf(this.consoleLevel))
|
|
533
|
+
return;
|
|
534
|
+
const scope = moduleField === undefined ? "" : `/${moduleField}`;
|
|
535
|
+
try {
|
|
536
|
+
this.sink(level, `[${this.pluginId}${scope}] ${formatConsole(event, fields)}`);
|
|
537
|
+
}
|
|
538
|
+
catch {
|
|
539
|
+
// Fail-open.
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
scheduleRetentionSweep() {
|
|
543
|
+
if (this.retentionDays <= 0 || this.retention !== undefined)
|
|
544
|
+
return;
|
|
545
|
+
this.retention = sweepOldLogFiles(this.dir, this.retentionDays, this.clock()).then(() => undefined, () => undefined);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
class PluginLoggerImpl {
|
|
549
|
+
core;
|
|
550
|
+
moduleField;
|
|
551
|
+
constructor(core, moduleField) {
|
|
552
|
+
this.core = core;
|
|
553
|
+
this.moduleField = moduleField;
|
|
554
|
+
}
|
|
555
|
+
trace(event, fields) {
|
|
556
|
+
this.core.write(this.moduleField, "trace", event, fields);
|
|
557
|
+
}
|
|
558
|
+
debug(event, fields) {
|
|
559
|
+
this.core.write(this.moduleField, "debug", event, fields);
|
|
560
|
+
}
|
|
561
|
+
info(event, fields) {
|
|
562
|
+
this.core.write(this.moduleField, "info", event, fields);
|
|
563
|
+
}
|
|
564
|
+
warn(event, fields) {
|
|
565
|
+
this.core.write(this.moduleField, "warn", event, fields);
|
|
566
|
+
}
|
|
567
|
+
error(event, fields) {
|
|
568
|
+
this.core.write(this.moduleField, "error", event, fields);
|
|
569
|
+
}
|
|
570
|
+
fatal(event, fields) {
|
|
571
|
+
this.core.write(this.moduleField, "fatal", event, fields);
|
|
572
|
+
}
|
|
573
|
+
child(module) {
|
|
574
|
+
return new PluginLoggerImpl(this.core, module);
|
|
575
|
+
}
|
|
576
|
+
get level() {
|
|
577
|
+
return this.core.level;
|
|
578
|
+
}
|
|
579
|
+
setLevel(level) {
|
|
580
|
+
this.core.setLevel(level);
|
|
581
|
+
}
|
|
582
|
+
get format() {
|
|
583
|
+
return this.core.format;
|
|
584
|
+
}
|
|
585
|
+
setFormat(format) {
|
|
586
|
+
this.core.setFormat(format);
|
|
587
|
+
}
|
|
588
|
+
flush() {
|
|
589
|
+
this.core.flush();
|
|
590
|
+
}
|
|
591
|
+
close() {
|
|
592
|
+
return this.core.close();
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
/** Create a standalone logger instance (no caching). */
|
|
596
|
+
export function createPluginLogger(options) {
|
|
597
|
+
const core = new LoggerCore(options);
|
|
598
|
+
const root = new PluginLoggerImpl(core);
|
|
599
|
+
core.activate();
|
|
600
|
+
return root;
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Create or return the cached logger for `pluginId` + resolved `dir`. A later
|
|
604
|
+
* call with an explicit `level` updates the cached instance's threshold, so
|
|
605
|
+
* plugin config reloads take effect. `close()` evicts the cache entry; the
|
|
606
|
+
* next call creates a fresh instance.
|
|
607
|
+
*/
|
|
608
|
+
export function getPluginLogger(options) {
|
|
609
|
+
const candidate = new LoggerCore(options);
|
|
610
|
+
const key = candidate.key();
|
|
611
|
+
const state = registryState();
|
|
612
|
+
const existing = state.cache.get(key);
|
|
613
|
+
if (existing === undefined || existing.core.isClosed()) {
|
|
614
|
+
const entry = { core: candidate, root: new PluginLoggerImpl(candidate) };
|
|
615
|
+
state.cache.set(key, entry);
|
|
616
|
+
candidate.activate();
|
|
617
|
+
return entry.root;
|
|
618
|
+
}
|
|
619
|
+
if (options.level !== undefined)
|
|
620
|
+
existing.core.setLevel(options.level);
|
|
621
|
+
if (options.format !== undefined)
|
|
622
|
+
existing.core.setFormat(options.format);
|
|
623
|
+
return existing.root;
|
|
624
|
+
}
|
|
625
|
+
//# sourceMappingURL=plugin-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-logger.js","sourceRoot":"","sources":["../src/plugin-logger.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yadsh/dsh-plugin-log",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Shared structured file logging and runtime logger discovery for DSH plugins",
|
|
5
|
+
"homepage": "https://github.com/xarleyn/dsh-plugins/tree/main/packages/plugin-log#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/xarleyn/dsh-plugins/issues"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/xarleyn/dsh-plugins.git",
|
|
12
|
+
"directory": "packages/plugin-log"
|
|
13
|
+
},
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "./lib/index.js",
|
|
17
|
+
"types": "./lib/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./lib/index.d.ts",
|
|
21
|
+
"default": "./lib/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./package.json": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"lib",
|
|
27
|
+
"README.md",
|
|
28
|
+
"LICENSE"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc",
|
|
32
|
+
"lint": "eslint src tests",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"typecheck": "tsc --noEmit",
|
|
35
|
+
"prepack": "pnpm run build",
|
|
36
|
+
"check": "pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run build"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"pino": "^10.3.1"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "catalog:tooling",
|
|
43
|
+
"@yadsh/dsh-config": "workspace:^",
|
|
44
|
+
"eslint": "catalog:tooling",
|
|
45
|
+
"typescript": "catalog:tooling",
|
|
46
|
+
"vitest": "catalog:tooling"
|
|
47
|
+
},
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public",
|
|
50
|
+
"registry": "https://registry.npmjs.org/"
|
|
51
|
+
},
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=20"
|
|
54
|
+
}
|
|
55
|
+
}
|