-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathlog.ts
122 lines (104 loc) · 3.04 KB
/
log.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import { Console } from "console"
import { stdoutStyle, stderrStyle } from "./termstyle"
import { memoize } from "./memoize"
import { prog } from "./cli"
import { captureStackTrace } from "./error"
import { Log as LogAPI } from "../estrella"
declare const DEBUG :boolean
export interface Env {
log :typeof log
}
export enum LogLevel {
Silent = -1,// log nothing
Error = 0, // only log errors
Warn, // log errors and warnings
Info, // log errors, warnings and info
Debug, // log everything
}
let log_console = console
let log_colorMode :boolean|undefined = undefined
export const log = new class Log implements LogAPI {
readonly SILENT = LogLevel.Silent // = -1
readonly ERROR = LogLevel.Error // = 0
readonly WARN = LogLevel.Warn // = 1
readonly INFO = LogLevel.Info // = 2
readonly DEBUG = LogLevel.Debug // = 3
level = LogLevel.Info
error(...v :any[]) :void {
if (log.level >= LogLevel.Error) {
evalFunctionInArgs(v)
log_console.error(stderrStyle.red(`${prog}:`), ...v)
}
}
warn(...v :any[]) :void {
if (log.level >= LogLevel.Warn) {
evalFunctionInArgs(v)
log_console.error(stderrStyle.magenta(`${prog}:`), ...v)
}
}
info(...v :any[]) :void {
if (log.level >= LogLevel.Info) {
evalFunctionInArgs(v)
log_console.log(...v)
}
}
// DEPRECATED in Estrella 1.2.2
readonly infoOnce = this.info
readonly debug = log_debug
get colorMode() :boolean|undefined {
return log_colorMode
}
set colorMode(colorMode :boolean|undefined) {
if (log_colorMode === colorMode) {
return
}
log_colorMode = colorMode
if (colorMode === undefined) { // auto
log_console = console
} else {
log_console = new Console({
stdout: process.stdout,
stderr: process.stderr,
colorMode
})
}
}
}
export default log
function evalFunctionInArgs(args :any[]) {
// evaluate first function argument
if (typeof args[0] == "function") {
args[0] = args[0]()
}
}
function log_debug(...v :any[]) {
if (log.level >= LogLevel.Debug) {
let meta = ""
if (DEBUG) {
// stack traces are only useful in debug builds (not mangled)
const stack = captureStackTrace(log_debug)
const frames = stack.split("\n", 5)
const f = frames[1] // stack frame
let m = f && /at (\w+)/.exec(f)
if (m) {
meta = " " + m[1]
} else if (!m && frames[2]) {
if (m = frames[2] && /at (\w+)/.exec(frames[2])) {
meta = ` ${m[1]} → ${stdoutStyle.italic("f")}`
}
}
}
evalFunctionInArgs(v)
if (v.length == 0 || (v.length == 1 && (v[0] === "" || v[0] === undefined))) {
// Nothing to be logged.
// This is sometimes useful when logging something complex conditionally, for example:
// log.debug(() => {
// if (expensiveComputation()) {
// return "redirecting foobar to fuzlol"
// }
// })
return
}
log_console.log(stdoutStyle.bold(stdoutStyle.blue(`[DEBUG${meta}]`)), ...v)
}
}