@cto.af/log 1.3.7 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +55 -0
- package/lib/index.js +147 -0
- package/package.json +11 -8
- package/lib/index.d.mts +0 -59
- package/lib/index.mjs +0 -1
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import pino from 'pino';
|
|
2
|
+
export interface CtoLogOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Increase (or decrease if negative) log verbosity by this much.
|
|
5
|
+
* -3: fatal, -2: error, -1: warn, 0: info, 1: debug, 2: trace.
|
|
6
|
+
* Useful for -qqqvvvv option processing. Default: 0.
|
|
7
|
+
*/
|
|
8
|
+
logLevel?: number;
|
|
9
|
+
/** If a string, create this log file and write to it. */
|
|
10
|
+
logFile?: string | null;
|
|
11
|
+
/** If true, do not log to stdout. */
|
|
12
|
+
mute?: boolean;
|
|
13
|
+
/** If logFile is set, write synchronously if true (for testing). */
|
|
14
|
+
sync?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Ignore this set of comma-separated fields when pretty printing logs
|
|
17
|
+
* to stdout. Default: 'pid,hostname,name,host,port'.
|
|
18
|
+
*/
|
|
19
|
+
prettyIgnore?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Log instance, created by the first layer to call createLog. Alternative
|
|
22
|
+
* to getLog for times when multiple loggers are needed.
|
|
23
|
+
*/
|
|
24
|
+
log?: Logger | null;
|
|
25
|
+
}
|
|
26
|
+
export declare const DEFAULT_LOG_OPTIONS: Required<CtoLogOptions>;
|
|
27
|
+
export declare const LOG_OPTIONS_NAMES: Set<keyof CtoLogOptions | keyof pino.LoggerOptions<never, false>>;
|
|
28
|
+
export type LogOptions = CtoLogOptions & pino.LoggerOptions<never, false>;
|
|
29
|
+
export type Logger = pino.Logger;
|
|
30
|
+
/**
|
|
31
|
+
* Create a new log instance. Mostly useful for testing.
|
|
32
|
+
*
|
|
33
|
+
* @param opts Logging options.
|
|
34
|
+
* @param bindings Extra fields to put into every log item.
|
|
35
|
+
* @returns Logging object.
|
|
36
|
+
*/
|
|
37
|
+
export declare function createLog(opts?: LogOptions, bindings?: pino.Bindings): Logger;
|
|
38
|
+
/**
|
|
39
|
+
* Get a singleton logging object. Opts and bindings are used the first time,
|
|
40
|
+
* and ignored thereafter. Ideally the highest-level layer will call this
|
|
41
|
+
* first before any lower layer.
|
|
42
|
+
*
|
|
43
|
+
* @param opts Logging options.
|
|
44
|
+
* @param bindings Extra fields to put into every log item.
|
|
45
|
+
* @returns Singleton logging object.
|
|
46
|
+
*/
|
|
47
|
+
export declare function getLog(opts?: LogOptions, bindings?: pino.Bindings): Logger;
|
|
48
|
+
/**
|
|
49
|
+
* Get a child logger with the given bindings.
|
|
50
|
+
*
|
|
51
|
+
* @param opts Log options.
|
|
52
|
+
* @param bindings Name/value pairs to add to each log line.
|
|
53
|
+
* @returns Initialized logger instance.
|
|
54
|
+
*/
|
|
55
|
+
export declare function childLogger(opts?: LogOptions, bindings?: pino.Bindings): Logger;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { assertDisjoint, nameSet, select } from '@cto.af/utils';
|
|
2
|
+
import pino from 'pino';
|
|
3
|
+
import pretty from 'pino-pretty';
|
|
4
|
+
export const DEFAULT_LOG_OPTIONS = {
|
|
5
|
+
log: null,
|
|
6
|
+
logFile: null,
|
|
7
|
+
logLevel: 0,
|
|
8
|
+
mute: false,
|
|
9
|
+
prettyIgnore: 'pid,hostname,name,host,port,ns',
|
|
10
|
+
sync: false,
|
|
11
|
+
};
|
|
12
|
+
const CTO_LOG_OPTIONS_NAMES = nameSet(DEFAULT_LOG_OPTIONS);
|
|
13
|
+
const PINO_OPTIONS_NAMES = new Set([
|
|
14
|
+
'base',
|
|
15
|
+
'browser',
|
|
16
|
+
'crlf',
|
|
17
|
+
'customLevels',
|
|
18
|
+
'depthLimit',
|
|
19
|
+
'edgeLimit',
|
|
20
|
+
'enabled',
|
|
21
|
+
'errorKey',
|
|
22
|
+
'formatters',
|
|
23
|
+
'hooks',
|
|
24
|
+
'level',
|
|
25
|
+
'levelComparison',
|
|
26
|
+
'levelVal',
|
|
27
|
+
'messageKey',
|
|
28
|
+
'mixin',
|
|
29
|
+
'mixinMergeStrategy',
|
|
30
|
+
'msgPrefix',
|
|
31
|
+
'name',
|
|
32
|
+
'nestedKey',
|
|
33
|
+
'onChild',
|
|
34
|
+
'redact',
|
|
35
|
+
'safe',
|
|
36
|
+
'serializers',
|
|
37
|
+
'timestamp',
|
|
38
|
+
'transport',
|
|
39
|
+
'useOnlyCustomLevels',
|
|
40
|
+
]);
|
|
41
|
+
assertDisjoint(CTO_LOG_OPTIONS_NAMES, PINO_OPTIONS_NAMES);
|
|
42
|
+
export const LOG_OPTIONS_NAMES = new Set([...CTO_LOG_OPTIONS_NAMES, ...PINO_OPTIONS_NAMES]);
|
|
43
|
+
/**
|
|
44
|
+
* "Write" to dev/null.
|
|
45
|
+
*/
|
|
46
|
+
class WriteSink {
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/class-methods-use-this
|
|
48
|
+
write(_msg) {
|
|
49
|
+
// No-op.
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create a new log instance. Mostly useful for testing.
|
|
54
|
+
*
|
|
55
|
+
* @param opts Logging options.
|
|
56
|
+
* @param bindings Extra fields to put into every log item.
|
|
57
|
+
* @returns Logging object.
|
|
58
|
+
*/
|
|
59
|
+
export function createLog(opts = {}, bindings) {
|
|
60
|
+
const [logOpts, pinoOpts] = select(opts, DEFAULT_LOG_OPTIONS);
|
|
61
|
+
if (logOpts.log) {
|
|
62
|
+
return logOpts.log;
|
|
63
|
+
}
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
65
|
+
const envLevel = globalThis['process']?.env?.CTOAF_LOG_LEVEL;
|
|
66
|
+
if (typeof envLevel === 'string') {
|
|
67
|
+
const lev = parseInt(envLevel, 10);
|
|
68
|
+
if (!isNaN(lev)) {
|
|
69
|
+
logOpts.logLevel = lev;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
let levelNum = Math.round(3 - logOpts.logLevel);
|
|
73
|
+
if (levelNum < 1) {
|
|
74
|
+
levelNum = 1;
|
|
75
|
+
}
|
|
76
|
+
else if (levelNum > 6) {
|
|
77
|
+
levelNum = 6;
|
|
78
|
+
}
|
|
79
|
+
pinoOpts.level = pino.levels.labels[levelNum * 10];
|
|
80
|
+
let ret = undefined;
|
|
81
|
+
if (logOpts.mute && !logOpts.logFile) {
|
|
82
|
+
// Shh.
|
|
83
|
+
ret = pino(pinoOpts, new WriteSink());
|
|
84
|
+
}
|
|
85
|
+
else if (logOpts.logFile) {
|
|
86
|
+
const dest = pino.destination({
|
|
87
|
+
dest: logOpts.logFile,
|
|
88
|
+
sync: logOpts.sync,
|
|
89
|
+
append: true,
|
|
90
|
+
mkdir: true,
|
|
91
|
+
});
|
|
92
|
+
if (logOpts.mute) {
|
|
93
|
+
ret = pino(pinoOpts, dest);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
ret = pino(pinoOpts, pino.multistream([{
|
|
97
|
+
level: pinoOpts.level,
|
|
98
|
+
stream: dest,
|
|
99
|
+
}, {
|
|
100
|
+
level: pinoOpts.level,
|
|
101
|
+
stream: pretty({
|
|
102
|
+
ignore: logOpts.prettyIgnore,
|
|
103
|
+
}),
|
|
104
|
+
}]));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
ret = pino(pinoOpts, pretty({
|
|
109
|
+
ignore: logOpts.prettyIgnore,
|
|
110
|
+
}));
|
|
111
|
+
}
|
|
112
|
+
if (bindings) {
|
|
113
|
+
ret.setBindings(bindings);
|
|
114
|
+
}
|
|
115
|
+
opts.log = ret;
|
|
116
|
+
return ret;
|
|
117
|
+
}
|
|
118
|
+
let instance = undefined;
|
|
119
|
+
/**
|
|
120
|
+
* Get a singleton logging object. Opts and bindings are used the first time,
|
|
121
|
+
* and ignored thereafter. Ideally the highest-level layer will call this
|
|
122
|
+
* first before any lower layer.
|
|
123
|
+
*
|
|
124
|
+
* @param opts Logging options.
|
|
125
|
+
* @param bindings Extra fields to put into every log item.
|
|
126
|
+
* @returns Singleton logging object.
|
|
127
|
+
*/
|
|
128
|
+
export function getLog(opts, bindings = {}) {
|
|
129
|
+
if (opts?.log) {
|
|
130
|
+
return opts.log;
|
|
131
|
+
}
|
|
132
|
+
if (!instance) {
|
|
133
|
+
instance = createLog(opts, bindings);
|
|
134
|
+
}
|
|
135
|
+
return instance;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get a child logger with the given bindings.
|
|
139
|
+
*
|
|
140
|
+
* @param opts Log options.
|
|
141
|
+
* @param bindings Name/value pairs to add to each log line.
|
|
142
|
+
* @returns Initialized logger instance.
|
|
143
|
+
*/
|
|
144
|
+
export function childLogger(opts = {}, bindings = {}) {
|
|
145
|
+
const log = getLog(opts);
|
|
146
|
+
return log.child(bindings);
|
|
147
|
+
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cto.af/log",
|
|
3
|
-
"version": "
|
|
4
|
-
"decription": "",
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"decription": "A thin wrapper around Pino to help isolate its changes from other projects",
|
|
5
5
|
"main": "lib/index.mjs",
|
|
6
6
|
"files": [
|
|
7
7
|
"lib/*"
|
|
8
8
|
],
|
|
9
9
|
"type": "module",
|
|
10
|
-
"keywords": [
|
|
10
|
+
"keywords": [
|
|
11
|
+
"logging",
|
|
12
|
+
"pino"
|
|
13
|
+
],
|
|
11
14
|
"author": "Joe Hildebrand <joe-github@cursive.net>",
|
|
12
15
|
"license": "MIT",
|
|
13
16
|
"repository": {
|
|
@@ -19,12 +22,12 @@
|
|
|
19
22
|
"url": "https://github.com/cto-af/log/issues"
|
|
20
23
|
},
|
|
21
24
|
"dependencies": {
|
|
22
|
-
"@cto.af/utils": "~
|
|
23
|
-
"pino": "~10.
|
|
24
|
-
"pino-pretty": "~13.
|
|
25
|
+
"@cto.af/utils": "~2.0.1",
|
|
26
|
+
"pino": "~10.4.0",
|
|
27
|
+
"pino-pretty": "~13.2.0"
|
|
25
28
|
},
|
|
26
|
-
"packageManager": "pnpm@
|
|
29
|
+
"packageManager": "pnpm@12.9.1",
|
|
27
30
|
"engines": {
|
|
28
|
-
"node": ">=
|
|
31
|
+
"node": ">=22"
|
|
29
32
|
}
|
|
30
33
|
}
|
package/lib/index.d.mts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import pino from "pino";
|
|
2
|
-
|
|
3
|
-
//#region src/index.d.ts
|
|
4
|
-
interface CtoLogOptions {
|
|
5
|
-
/**
|
|
6
|
-
* Increase (or decrease if negative) log verbosity by this much.
|
|
7
|
-
* -3: fatal, -2: error, -1: warn, 0: info, 1: debug, 2: trace.
|
|
8
|
-
* Useful for -qqqvvvv option processing. Default: 0.
|
|
9
|
-
*/
|
|
10
|
-
logLevel?: number;
|
|
11
|
-
/** If a string, create this log file and write to it. */
|
|
12
|
-
logFile?: string | null;
|
|
13
|
-
/** If true, do not log to stdout. */
|
|
14
|
-
mute?: boolean;
|
|
15
|
-
/** If logFile is set, write synchronously if true (for testing). */
|
|
16
|
-
sync?: boolean;
|
|
17
|
-
/**
|
|
18
|
-
* Ignore this set of comma-separated fields when pretty printing logs
|
|
19
|
-
* to stdout. Default: 'pid,hostname,name,host,port'.
|
|
20
|
-
*/
|
|
21
|
-
prettyIgnore?: string;
|
|
22
|
-
/**
|
|
23
|
-
* Log instance, created by the first layer to call createLog. Alternative
|
|
24
|
-
* to getLog for times when multiple loggers are needed.
|
|
25
|
-
*/
|
|
26
|
-
log?: Logger | null;
|
|
27
|
-
}
|
|
28
|
-
declare const DEFAULT_LOG_OPTIONS: Required<CtoLogOptions>;
|
|
29
|
-
declare const LOG_OPTIONS_NAMES: Set<keyof CtoLogOptions | keyof pino.LoggerOptions<never, false>>;
|
|
30
|
-
type LogOptions = CtoLogOptions & pino.LoggerOptions<never, false>;
|
|
31
|
-
type Logger = pino.Logger;
|
|
32
|
-
/**
|
|
33
|
-
* Create a new log instance. Mostly useful for testing.
|
|
34
|
-
*
|
|
35
|
-
* @param opts Logging options.
|
|
36
|
-
* @param bindings Extra fields to put into every log item.
|
|
37
|
-
* @returns Logging object.
|
|
38
|
-
*/
|
|
39
|
-
declare function createLog(opts?: LogOptions, bindings?: pino.Bindings): Logger;
|
|
40
|
-
/**
|
|
41
|
-
* Get a singleton logging object. Opts and bindings are used the first time,
|
|
42
|
-
* and ignored thereafter. Ideally the highest-level layer will call this
|
|
43
|
-
* first before any lower layer.
|
|
44
|
-
*
|
|
45
|
-
* @param opts Logging options.
|
|
46
|
-
* @param bindings Extra fields to put into every log item.
|
|
47
|
-
* @returns Singleton logging object.
|
|
48
|
-
*/
|
|
49
|
-
declare function getLog(opts?: LogOptions, bindings?: pino.Bindings): Logger;
|
|
50
|
-
/**
|
|
51
|
-
* Get a child logger with the given bindings.
|
|
52
|
-
*
|
|
53
|
-
* @param opts Log options.
|
|
54
|
-
* @param bindings Name/value pairs to add to each log line.
|
|
55
|
-
* @returns Initialized logger instance.
|
|
56
|
-
*/
|
|
57
|
-
declare function childLogger(opts?: LogOptions, bindings?: pino.Bindings): Logger;
|
|
58
|
-
//#endregion
|
|
59
|
-
export { CtoLogOptions, DEFAULT_LOG_OPTIONS, LOG_OPTIONS_NAMES, LogOptions, Logger, childLogger, createLog, getLog };
|
package/lib/index.mjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{assertDisjoint as e,nameSet as t,select as n}from"@cto.af/utils";import r from"pino";import i from"pino-pretty";const a={log:null,logFile:null,logLevel:0,mute:!1,prettyIgnore:`pid,hostname,name,host,port,ns`,sync:!1},o=t(a),s=new Set(`base.browser.crlf.customLevels.depthLimit.edgeLimit.enabled.errorKey.formatters.hooks.level.levelComparison.levelVal.messageKey.mixin.mixinMergeStrategy.msgPrefix.name.nestedKey.onChild.redact.safe.serializers.timestamp.transport.useOnlyCustomLevels`.split(`.`));e(o,s);const c=new Set([...o,...s]);var l=class{write(e){}};function u(e={},t){let[o,s]=n(e,a);if(o.log)return o.log;let c=globalThis.process?.env?.CTOAF_LOG_LEVEL;if(typeof c==`string`){let e=parseInt(c,10);isNaN(e)||(o.logLevel=e)}let u=Math.round(3-o.logLevel);u<1?u=1:u>6&&(u=6),s.level=r.levels.labels[u*10];let d;if(o.mute&&!o.logFile)d=r(s,new l);else if(o.logFile){let e=r.destination({dest:o.logFile,sync:o.sync,append:!0,mkdir:!0});d=o.mute?r(s,e):r(s,r.multistream([{level:s.level,stream:e},{level:s.level,stream:i({ignore:o.prettyIgnore})}]))}else d=r(s,i({ignore:o.prettyIgnore}));return t&&d.setBindings(t),e.log=d,d}let d;function f(e,t={}){return e?.log?e.log:(d||=u(e,t),d)}function p(e={},t={}){return f(e).child(t)}export{a as DEFAULT_LOG_OPTIONS,c as LOG_OPTIONS_NAMES,p as childLogger,u as createLog,f as getLog};
|