@wireio/shared 1.0.2 → 1.0.3
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/package.json +5 -1
- package/src/guards/applyTypeGuardExtras.ts +0 -9
- package/src/guards/array.ts +0 -5
- package/src/guards/assert.ts +0 -83
- package/src/guards/class.ts +0 -56
- package/src/guards/guard-tools.ts +0 -78
- package/src/guards/index.ts +0 -7
- package/src/guards/primitive.ts +0 -77
- package/src/guards/types.ts +0 -15
- package/src/helpers/Deferred.ts +0 -149
- package/src/helpers/index.ts +0 -1
- package/src/index.ts +0 -3
- package/src/logging/Appender.ts +0 -5
- package/src/logging/Formatter.ts +0 -8
- package/src/logging/InternalLogger.ts +0 -6
- package/src/logging/Level.ts +0 -19
- package/src/logging/LogRecord.ts +0 -17
- package/src/logging/Logger.ts +0 -222
- package/src/logging/LoggingManager.ts +0 -306
- package/src/logging/appenders/ConsoleAppender.ts +0 -110
- package/src/logging/appenders/DebugAppender.ts +0 -254
- package/src/logging/appenders/FileAppender.ts +0 -281
- package/src/logging/appenders/aws-firehose/AWSFirehoseAppender.ts +0 -176
- package/src/logging/appenders/aws-firehose/AWSFirehoseCredentialManager.ts +0 -132
- package/src/logging/appenders/index.ts +0 -3
- package/src/logging/context/LogContext.ts +0 -74
- package/src/logging/context/LogContextContainer.ts +0 -28
- package/src/logging/context/LogContextProvider.ts +0 -43
- package/src/logging/context/index.ts +0 -3
- package/src/logging/context/providers/node/NodeContextProvider.ts +0 -45
- package/src/logging/context/providers/node/index.ts +0 -3
- package/src/logging/examples/example-debug-appender.ts +0 -19
- package/src/logging/examples/example-file-appender.ts +0 -19
- package/src/logging/getLogger.ts +0 -9
- package/src/logging/index-node.ts +0 -2
- package/src/logging/index.ts +0 -11
- package/src/logging/util.ts +0 -6
- package/tsconfig.json +0 -9
- package/tsconfig.tsbuildinfo +0 -1
package/src/logging/Logger.ts
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
import { assert, getValue, isString, isDefined, isFunction, isNumber } from "../guards/index.js"
|
|
2
|
-
import { Option } from "prelude-ts"
|
|
3
|
-
import { pick } from "lodash"
|
|
4
|
-
import { LevelKind, LevelThresholds } from "./Level.js"
|
|
5
|
-
import type { LoggingManager } from "./LoggingManager.js"
|
|
6
|
-
import type { LogRecord } from "./LogRecord.js"
|
|
7
|
-
import { isLogLevelKind } from "./util.js"
|
|
8
|
-
|
|
9
|
-
export interface LoggerOptions {
|
|
10
|
-
categoryInterpolator: CategoryInterpolator
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export type CategoryInterpolator = (
|
|
14
|
-
inCategory: string,
|
|
15
|
-
options?: LoggerOptions
|
|
16
|
-
) => string
|
|
17
|
-
|
|
18
|
-
export const filenameCategoryInterpolator: CategoryInterpolator = (
|
|
19
|
-
filename: string
|
|
20
|
-
) => {
|
|
21
|
-
const allParts = filename.replaceAll("\\","/").split("/")
|
|
22
|
-
const rootIndex = Math.max(
|
|
23
|
-
...["src", "lib"].map((name) => allParts.indexOf(name))
|
|
24
|
-
)
|
|
25
|
-
const parts =
|
|
26
|
-
rootIndex === -1 ? [allParts.pop()] : allParts.slice(rootIndex + 1)
|
|
27
|
-
const category = Option.of(parts.join(":"))
|
|
28
|
-
.flatMap((cat) =>
|
|
29
|
-
Option.of(cat.lastIndexOf(".")).map((index) =>
|
|
30
|
-
index === -1 ? cat : cat.slice(0, index)
|
|
31
|
-
)
|
|
32
|
-
)
|
|
33
|
-
.getOrElse("unknown")
|
|
34
|
-
return category
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export const defaultLoggerOptions: LoggerOptions = {
|
|
38
|
-
categoryInterpolator: filenameCategoryInterpolator
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function toLogRecord(
|
|
42
|
-
logger: Logger,
|
|
43
|
-
levelOrRecord: LevelKind | LogRecord,
|
|
44
|
-
args: any[]
|
|
45
|
-
) {
|
|
46
|
-
const errRecord = Option.ofNullable(
|
|
47
|
-
args.find((arg) => (isString(arg?.message) && !!arg.stack) || arg instanceof Error)
|
|
48
|
-
).match({
|
|
49
|
-
Some: (err) => ({
|
|
50
|
-
errorMessage: getValue(() => err.message),
|
|
51
|
-
errorStack: getValue(() => err.stack)
|
|
52
|
-
}),
|
|
53
|
-
None: () => ({})
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
const recordBase = isString(levelOrRecord)
|
|
57
|
-
? ({
|
|
58
|
-
...pick(logger, ["category"]),
|
|
59
|
-
timestamp: Date.now(),
|
|
60
|
-
message: args[0],
|
|
61
|
-
level: levelOrRecord,
|
|
62
|
-
args: args.slice(1)
|
|
63
|
-
} as LogRecord)
|
|
64
|
-
: levelOrRecord
|
|
65
|
-
return {
|
|
66
|
-
...recordBase,
|
|
67
|
-
...errRecord,
|
|
68
|
-
timestamp: isNumber(recordBase.timestamp) && recordBase.timestamp > 0 ? recordBase.timestamp : Date.now(),
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export interface LoggerState {
|
|
73
|
-
overrideLevel?: LevelKind
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export class Logger {
|
|
77
|
-
readonly state: LoggerState = {
|
|
78
|
-
overrideLevel: null
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
get overrideLevel(): LevelKind {
|
|
82
|
-
return Option.ofNullable(this.state.overrideLevel)
|
|
83
|
-
.filter(isLogLevelKind) //Predicate.of<LevelKind>(isString).and(isLogLevelKind))
|
|
84
|
-
.getOrNull()
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
get overrideThreshold() {
|
|
88
|
-
return Option.ofNullable(this.overrideLevel)
|
|
89
|
-
.map((level) => LevelThresholds[level])
|
|
90
|
-
.getOrNull()
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
setOverrideLevel(inOverrideLevel: LevelKind) {
|
|
94
|
-
const overrideLevel = (
|
|
95
|
-
!inOverrideLevel ? null : inOverrideLevel.toLocaleLowerCase()
|
|
96
|
-
) as LevelKind
|
|
97
|
-
|
|
98
|
-
assert(
|
|
99
|
-
!isDefined(overrideLevel) || isLogLevelKind(overrideLevel),
|
|
100
|
-
`Invalid override level, must be a log level, all lower case`
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
Object.assign(this.state, {
|
|
104
|
-
overrideLevel
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
return this
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Base logging function
|
|
112
|
-
*
|
|
113
|
-
* @param record
|
|
114
|
-
*/
|
|
115
|
-
log(record: LogRecord):void
|
|
116
|
-
log(level: LevelKind, message: string, ...args: any[]):void
|
|
117
|
-
log(levelOrRecord: LevelKind | LogRecord, ...args: any[]) {
|
|
118
|
-
const record = toLogRecord(this, levelOrRecord, args)
|
|
119
|
-
this.manager.fire(record)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Factory for the log
|
|
124
|
-
* level functions
|
|
125
|
-
*
|
|
126
|
-
* @param {LevelKind} level
|
|
127
|
-
* @returns {(message: string, ...args: any[]) => void}
|
|
128
|
-
* @private
|
|
129
|
-
*/
|
|
130
|
-
private createLevelLogger(level: LevelKind): (message: string, ...args: any[]) => void {
|
|
131
|
-
const isEnabled = this.createLevelEnabled(level)
|
|
132
|
-
return (message: string, ...args: any[]) => {
|
|
133
|
-
if (isEnabled()) {
|
|
134
|
-
this.log(level, message, ...args)
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Factory for is<Level>Enabled
|
|
141
|
-
*
|
|
142
|
-
* @param {LevelKind} level
|
|
143
|
-
* @returns {() => boolean}
|
|
144
|
-
* @private
|
|
145
|
-
*/
|
|
146
|
-
private createLevelEnabled(level: LevelKind): () => boolean {
|
|
147
|
-
return () => {
|
|
148
|
-
const { rootThreshold } = this.manager
|
|
149
|
-
|
|
150
|
-
const globalOverrideThreshold = this.manager.determineThresholdOverride(this.category)
|
|
151
|
-
const categoryThresholds = [
|
|
152
|
-
globalOverrideThreshold,
|
|
153
|
-
rootThreshold,
|
|
154
|
-
this.overrideThreshold
|
|
155
|
-
].filter(isNumber)
|
|
156
|
-
|
|
157
|
-
const categoryThreshold = Math.min(...categoryThresholds)
|
|
158
|
-
|
|
159
|
-
const recordThreshold = LevelThresholds[level]
|
|
160
|
-
|
|
161
|
-
return recordThreshold >= categoryThreshold
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
readonly trace = this.createLevelLogger("trace")
|
|
166
|
-
readonly debug = this.createLevelLogger("debug")
|
|
167
|
-
readonly info = this.createLevelLogger("info")
|
|
168
|
-
readonly warn = this.createLevelLogger("warn")
|
|
169
|
-
readonly error = this.createLevelLogger("error")
|
|
170
|
-
readonly fatal = this.createLevelLogger("fatal")
|
|
171
|
-
|
|
172
|
-
readonly isTraceEnabled = this.createLevelEnabled("trace")
|
|
173
|
-
readonly isDebugEnabled = this.createLevelEnabled("debug")
|
|
174
|
-
readonly isInfoEnabled = this.createLevelEnabled("info")
|
|
175
|
-
readonly isWarnEnabled = this.createLevelEnabled("warn")
|
|
176
|
-
readonly isErrorEnabled = this.createLevelEnabled("error")
|
|
177
|
-
readonly isFatalEnabled = this.createLevelEnabled("fatal")
|
|
178
|
-
|
|
179
|
-
assert(test: boolean | (() => boolean), message: string, ...args: any[]) {
|
|
180
|
-
const isTruthy = isFunction(test) ? test() : test
|
|
181
|
-
if (isTruthy) {
|
|
182
|
-
return
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
this.error(message, ...args)
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
assertFatal(test: boolean | (() => boolean), message: string, exitCode: number = 1) {
|
|
189
|
-
const isTruthy = isFunction(test) ? test() : test
|
|
190
|
-
if (isTruthy) {
|
|
191
|
-
return
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
this.fatal("FATAL ASSERTION: ", message)
|
|
195
|
-
if (typeof process !== "undefined") {
|
|
196
|
-
process.exit(exitCode)
|
|
197
|
-
} else {
|
|
198
|
-
console.error("FATAL ASSERTION: `process` is not defined, probably in a web browser")
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
constructor(
|
|
203
|
-
readonly manager: LoggingManager,
|
|
204
|
-
readonly category: string,
|
|
205
|
-
readonly options: LoggerOptions
|
|
206
|
-
) {}
|
|
207
|
-
|
|
208
|
-
static hydrateOptions(options: Partial<LoggerOptions> = {}): LoggerOptions {
|
|
209
|
-
return {
|
|
210
|
-
...defaultLoggerOptions,
|
|
211
|
-
...options
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
static interoplateCategory(category: string, options: LoggerOptions) {
|
|
216
|
-
options = {
|
|
217
|
-
...defaultLoggerOptions,
|
|
218
|
-
...options
|
|
219
|
-
}
|
|
220
|
-
return options.categoryInterpolator(category, options)
|
|
221
|
-
}
|
|
222
|
-
}
|
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
import { isNumber, isObject, isString } from "../guards/index.js"
|
|
2
|
-
import { Option } from "prelude-ts"
|
|
3
|
-
import { flatten, isEmpty, min, negate } from "lodash"
|
|
4
|
-
import type { Appender } from "./Appender.js"
|
|
5
|
-
import { ConsoleAppender } from "./appenders/ConsoleAppender.js"
|
|
6
|
-
import { Level, LevelKind, LevelThresholds } from "./Level.js"
|
|
7
|
-
import { Logger, LoggerOptions } from "./Logger.js"
|
|
8
|
-
import type { LogRecord } from "./LogRecord.js"
|
|
9
|
-
import { LogContext, LogContextContainer } from "./context/index.js"
|
|
10
|
-
import { flow, get, nth } from "lodash/fp.js"
|
|
11
|
-
|
|
12
|
-
export type CategoryMatch = RegExp | string
|
|
13
|
-
|
|
14
|
-
export type ThresholdOverride = [match: CategoryMatch, level: LevelKind]
|
|
15
|
-
|
|
16
|
-
export interface LoggingManagerState<Record extends LogRecord> {
|
|
17
|
-
rootLevel: LevelKind
|
|
18
|
-
appenders: Array<Appender<Record>>
|
|
19
|
-
thresholdOverrides: Array<ThresholdOverride>
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type LoggingManagerOptions<Record extends LogRecord> = Partial<
|
|
23
|
-
LoggingManagerState<Record>
|
|
24
|
-
>
|
|
25
|
-
|
|
26
|
-
function parseThresholdOverridePatterns(
|
|
27
|
-
value: string,
|
|
28
|
-
level: LevelKind = "debug"
|
|
29
|
-
): ThresholdOverride[] {
|
|
30
|
-
return value
|
|
31
|
-
.split(",")
|
|
32
|
-
.map((s) => [new RegExp(s), level] as ThresholdOverride)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export const kEnvThresholdOverrides = Option.ofNullable(typeof process !== "undefined" && process.env.DEBUG_PATTERNS)
|
|
36
|
-
.filter(negate(isEmpty))
|
|
37
|
-
.map(parseThresholdOverridePatterns)
|
|
38
|
-
.getOrElse([])
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Logging manager
|
|
42
|
-
*/
|
|
43
|
-
export class LoggingManager<Record extends LogRecord = any> {
|
|
44
|
-
private readonly loggers = new Map<string, Logger>()
|
|
45
|
-
|
|
46
|
-
private readonly state: LoggingManagerState<Record> = {
|
|
47
|
-
appenders: [],
|
|
48
|
-
rootLevel: Level.info,
|
|
49
|
-
thresholdOverrides: kEnvThresholdOverrides
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
get rootLevel() {
|
|
53
|
-
return this.state.rootLevel
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
set rootLevel(newRootLevel: LevelKind) {
|
|
57
|
-
this.state.rootLevel = newRootLevel
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
get rootThreshold() {
|
|
61
|
-
return LevelThresholds[this.rootLevel]
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Get the current handler
|
|
66
|
-
*
|
|
67
|
-
* @returns {Appender<Record>}
|
|
68
|
-
*/
|
|
69
|
-
get appenders(): Array<Appender<Record>> {
|
|
70
|
-
return Option.ofNullable(this.state.appenders)
|
|
71
|
-
.filter((appenders) => appenders.length > 0)
|
|
72
|
-
.getOrCall(() => {
|
|
73
|
-
this.state.appenders.push(new ConsoleAppender())
|
|
74
|
-
return this.state.appenders
|
|
75
|
-
})
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Global threshold overrides
|
|
80
|
-
*/
|
|
81
|
-
get thresholdOverrides() {
|
|
82
|
-
return this.state.thresholdOverrides
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Update the overrides
|
|
87
|
-
*
|
|
88
|
-
* @param newOverrides
|
|
89
|
-
*/
|
|
90
|
-
set thresholdOverrides(newOverrides:ThresholdOverride[]) {
|
|
91
|
-
this.state.thresholdOverrides = newOverrides
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Set global appenders
|
|
96
|
-
*
|
|
97
|
-
* @param {Array<Appender<Record>>} newAppenders
|
|
98
|
-
*/
|
|
99
|
-
setAppenders(...newAppenders: Array<Appender<Record> | Appender<Record>[]>) {
|
|
100
|
-
// WE MUTATE DO TO THE LIKELIHOOD OF SOMEONE HOLDING A REF TO THE ARRAY,
|
|
101
|
-
// CONVERT TO OBSERVABLE AT SOME POINT
|
|
102
|
-
const persistentAppenders = this.state.appenders
|
|
103
|
-
persistentAppenders.length = 0
|
|
104
|
-
persistentAppenders.push(...flatten(newAppenders))
|
|
105
|
-
|
|
106
|
-
return this
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Add one or more appenders to existing appender set
|
|
111
|
-
*
|
|
112
|
-
* @param {Appender<Record> | Appender<Record>[]} newAppenders
|
|
113
|
-
* @returns {this<Record>}
|
|
114
|
-
*/
|
|
115
|
-
addAppenders(...newAppenders: Array<Appender<Record> | Appender<Record>[]>): this {
|
|
116
|
-
this.state.appenders.push(...flatten(newAppenders))
|
|
117
|
-
return this
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Clear threshold overrides
|
|
122
|
-
*
|
|
123
|
-
* @returns {this<Record>}
|
|
124
|
-
*/
|
|
125
|
-
clearThresholdOverrides(): this {
|
|
126
|
-
this.state.thresholdOverrides.length = 0
|
|
127
|
-
return this
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
setThresholdOverrides(...overrides: Array<ThresholdOverride>) {
|
|
131
|
-
this.state.thresholdOverrides.length = 0
|
|
132
|
-
this.state.thresholdOverrides.push(...overrides)
|
|
133
|
-
return this
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
addThresholdOverrides(...overrides: Array<ThresholdOverride>) {
|
|
137
|
-
this.state.thresholdOverrides.push(...overrides)
|
|
138
|
-
return this
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Get applicable current contexts
|
|
143
|
-
*
|
|
144
|
-
* @param {string} category
|
|
145
|
-
* @returns {LogContext[]}
|
|
146
|
-
*/
|
|
147
|
-
getApplicableCurrentContexts(category: string): LogContext[] {
|
|
148
|
-
return LogContextContainer.currentContext().filter(
|
|
149
|
-
({ pattern }) => !pattern || pattern.test(category)
|
|
150
|
-
)
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Check for any matching threshold overrides
|
|
155
|
-
*
|
|
156
|
-
* @param category
|
|
157
|
-
*/
|
|
158
|
-
determineThresholdOverride(category: string): number {
|
|
159
|
-
const contexts = this.getApplicableCurrentContexts(category),
|
|
160
|
-
|
|
161
|
-
// FIND CONFIGURED OVERRIDE LEVEL
|
|
162
|
-
overrideThreshold = Option.ofNullable(
|
|
163
|
-
this.thresholdOverrides.find(([match]) =>
|
|
164
|
-
isString(match) ? match === category : (match as RegExp).test(category)
|
|
165
|
-
)
|
|
166
|
-
)
|
|
167
|
-
.map(nth(1))
|
|
168
|
-
.map((level) => LevelThresholds[level as Level])
|
|
169
|
-
.getOrNull(),
|
|
170
|
-
// FIND `LogContext` OVERRIDE LEVEL
|
|
171
|
-
contextThresholds = contexts
|
|
172
|
-
.filter(flow(get("thresholdLevel"), isString))
|
|
173
|
-
.map(({ thresholdLevel }) => LevelThresholds[thresholdLevel]),
|
|
174
|
-
// IF ANY OVERRIDES, GET THE MOST VERBOSE LEVEL
|
|
175
|
-
override = Option.ofNullable(
|
|
176
|
-
[...contextThresholds, overrideThreshold].filter(isNumber)
|
|
177
|
-
)
|
|
178
|
-
.filter(negate(isEmpty))
|
|
179
|
-
.map(min)
|
|
180
|
-
.getOrNull()
|
|
181
|
-
|
|
182
|
-
return override as number
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Set the root logging level
|
|
187
|
-
*
|
|
188
|
-
* @param {LevelKind} newLevel
|
|
189
|
-
* @returns {this<Record>}
|
|
190
|
-
*/
|
|
191
|
-
setRootLevel(newLevel: LevelKind): this {
|
|
192
|
-
this.state.rootLevel = newLevel
|
|
193
|
-
return this
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Fire a log event, eventually
|
|
198
|
-
* invert this by making `Logger` an
|
|
199
|
-
* `EventEmitter3` and having the `LoggingManager`
|
|
200
|
-
* subscribe to `record` event
|
|
201
|
-
*
|
|
202
|
-
* @param {LogRecord<Record>} record
|
|
203
|
-
* @internal
|
|
204
|
-
*/
|
|
205
|
-
fire(record: LogRecord<Record>) {
|
|
206
|
-
const { category } = record,
|
|
207
|
-
contexts = this.getApplicableCurrentContexts(category),
|
|
208
|
-
contextAppenders = contexts.flatMap(get("appenders")),
|
|
209
|
-
appenders = [...this.appenders, ...contextAppenders]
|
|
210
|
-
|
|
211
|
-
appenders.forEach((appender) => appender.append(record as Record))
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Get a logger from cache, if the category
|
|
216
|
-
* does not have an existing logger, then create one.
|
|
217
|
-
*
|
|
218
|
-
* @param {string} categoryOrFilename
|
|
219
|
-
* @param {Partial<LoggerOptions>} inOptions
|
|
220
|
-
* @returns {Logger}
|
|
221
|
-
*/
|
|
222
|
-
getLogger(
|
|
223
|
-
categoryOrFilename: string,
|
|
224
|
-
inOptions: Partial<LoggerOptions> = {}
|
|
225
|
-
): Logger {
|
|
226
|
-
const options = Logger.hydrateOptions(inOptions)
|
|
227
|
-
const category = Logger.interoplateCategory(categoryOrFilename, options)
|
|
228
|
-
|
|
229
|
-
return Option.ofNullable(category)
|
|
230
|
-
.map((category) => this.loggers.get(category))
|
|
231
|
-
.getOrCall(() => {
|
|
232
|
-
const logger = new Logger(this, category, options)
|
|
233
|
-
this.loggers.set(category, logger)
|
|
234
|
-
return logger
|
|
235
|
-
})
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Configure the logging manager,
|
|
240
|
-
* this function is additive, so simply calling
|
|
241
|
-
* `configure` with a single option `rootLevel`,
|
|
242
|
-
* will not affect other options like `appenders` *
|
|
243
|
-
*
|
|
244
|
-
* @param {LoggingManagerOptions<any>} options
|
|
245
|
-
* @returns {this<Record>}
|
|
246
|
-
*/
|
|
247
|
-
configure(options: LoggingManagerOptions<any>): this {
|
|
248
|
-
if (Level[options?.rootLevel]) {
|
|
249
|
-
this.setRootLevel(options.rootLevel)
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
if (options?.appenders) {
|
|
253
|
-
this.setAppenders(options.appenders)
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (options?.thresholdOverrides) {
|
|
257
|
-
this.addThresholdOverrides(...options.thresholdOverrides)
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
return this
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
private constructor() {
|
|
264
|
-
this.configure({})
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Singleton instance
|
|
269
|
-
*
|
|
270
|
-
* @type {LoggingManager}
|
|
271
|
-
* @private
|
|
272
|
-
*/
|
|
273
|
-
private static manager: LoggingManager
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Get logging manager and optionally provided
|
|
277
|
-
* configuration options
|
|
278
|
-
*
|
|
279
|
-
* @param {LoggingManagerOptions<Record>} options
|
|
280
|
-
* @returns {LoggingManager<Record>}
|
|
281
|
-
*/
|
|
282
|
-
static get<Record extends LogRecord = any>(
|
|
283
|
-
options: LoggingManagerOptions<Record> = null
|
|
284
|
-
): LoggingManager<Record> {
|
|
285
|
-
if (!this.manager) {
|
|
286
|
-
this.manager = new LoggingManager<Record>()
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if (options) {
|
|
290
|
-
this.manager.configure(options)
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
return this.manager
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
export function getLoggingManager(): LoggingManager {
|
|
298
|
-
return LoggingManager.get()
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
if (Option.try_(() => process.env.NODE_ENV === "development").getOrElse(false)) {
|
|
302
|
-
[typeof window !== "undefined" && window, typeof global !== "undefined" && global].filter(isObject)
|
|
303
|
-
.map(target => Object.assign(target, {
|
|
304
|
-
loggingManager: getLoggingManager()
|
|
305
|
-
}))
|
|
306
|
-
}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import type { LogRecord } from "../LogRecord"
|
|
2
|
-
import type { Appender } from "../Appender"
|
|
3
|
-
import { Option } from "prelude-ts"
|
|
4
|
-
import type { LevelKind } from "../Level"
|
|
5
|
-
import type { Formatter } from "../Formatter"
|
|
6
|
-
|
|
7
|
-
const consoleLogBindings = new Map<LevelKind, (...args: any[]) => any>()
|
|
8
|
-
|
|
9
|
-
function getBoundConsoleFn(level: LevelKind) {
|
|
10
|
-
return (console[level] ?? console.log).bind(console)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Get a cached console bound log function
|
|
15
|
-
*
|
|
16
|
-
* @param {LevelKind} level
|
|
17
|
-
* @returns {(...args: any[]) => any}
|
|
18
|
-
*/
|
|
19
|
-
export function getConsoleLogBinding(level: LevelKind) {
|
|
20
|
-
if (!consoleLogBindings.has(level)) {
|
|
21
|
-
consoleLogBindings.set(level, getBoundConsoleFn(level))
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return consoleLogBindings.get(level)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* ConsoleAppender Configuration
|
|
29
|
-
*/
|
|
30
|
-
export interface ConsoleAppenderConfig<Record extends LogRecord = any> {
|
|
31
|
-
cacheEnabled: boolean
|
|
32
|
-
prettyPrint: boolean
|
|
33
|
-
formatter?: Formatter<string | Array<any>>
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Partial of config, used for shortening instead of Partial<...>
|
|
38
|
-
*/
|
|
39
|
-
export type ConsoleAppenderOptions<Record extends LogRecord> = Partial<
|
|
40
|
-
ConsoleAppenderConfig<Record>
|
|
41
|
-
>
|
|
42
|
-
|
|
43
|
-
export const consoleFormatter: Formatter<Array<any>> = ({
|
|
44
|
-
level,
|
|
45
|
-
message,
|
|
46
|
-
data,
|
|
47
|
-
args,
|
|
48
|
-
category,
|
|
49
|
-
timestamp
|
|
50
|
-
}) => [
|
|
51
|
-
`[${category}] (${level}) ${message}`,
|
|
52
|
-
...(Array.isArray(args) ? args : [args])
|
|
53
|
-
]
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Default console config
|
|
57
|
-
* @type {ConsoleAppenderConfig}
|
|
58
|
-
*/
|
|
59
|
-
export const kDefaultConsoleAppenderConfig: ConsoleAppenderConfig = {
|
|
60
|
-
cacheEnabled: true,
|
|
61
|
-
prettyPrint: true,
|
|
62
|
-
formatter: consoleFormatter
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Console appender, the simple default appender used
|
|
67
|
-
* everywhere OOB
|
|
68
|
-
*/
|
|
69
|
-
export class ConsoleAppender<Record extends LogRecord>
|
|
70
|
-
implements Appender<Record>
|
|
71
|
-
{
|
|
72
|
-
readonly config: ConsoleAppenderConfig
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Handle log records, transform, push to ES
|
|
76
|
-
*
|
|
77
|
-
* @param record
|
|
78
|
-
*/
|
|
79
|
-
append(record: Record): void {
|
|
80
|
-
const { level, message, data, args, category, timestamp } = record
|
|
81
|
-
const { formatter = consoleFormatter } = this.config
|
|
82
|
-
Option.ofNullable(formatter(record)).map((result) => {
|
|
83
|
-
const args = Array.isArray(result) ? result : [result]
|
|
84
|
-
this.write(level, ...args)
|
|
85
|
-
})
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Write args to console
|
|
90
|
-
*
|
|
91
|
-
* @param level
|
|
92
|
-
* @param args
|
|
93
|
-
*/
|
|
94
|
-
protected write(level: LevelKind, ...args: any[]) {
|
|
95
|
-
Option.ofNullable(console[level])
|
|
96
|
-
.orCall(() => Option.ofNullable(console.log))
|
|
97
|
-
.map((fn: Function) => fn.apply(console, args))
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
*
|
|
102
|
-
* @param {Partial<ConsoleAppenderOptions<Record>>} options
|
|
103
|
-
*/
|
|
104
|
-
constructor(options: Partial<ConsoleAppenderOptions<Record>> = {}) {
|
|
105
|
-
this.config = {
|
|
106
|
-
...kDefaultConsoleAppenderConfig,
|
|
107
|
-
...options
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|