Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/platform/log/node/spdlogLog.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import type * as spdlog from '@vscode/spdlog';
7
import { ByteSize } from '../../files/common/files.js';
8
import { AbstractMessageLogger, ILogger, LogLevel } from '../common/log.js';
9
10
enum SpdLogLevel {
11
Trace,
12
Debug,
13
Info,
14
Warning,
15
Error,
16
Critical,
17
Off
18
}
19
20
async function createSpdLogLogger(name: string, logfilePath: string, filesize: number, filecount: number, donotUseFormatters: boolean): Promise<spdlog.Logger | null> {
21
// Do not crash if spdlog cannot be loaded
22
try {
23
const _spdlog = await import('@vscode/spdlog');
24
_spdlog.setFlushOn(SpdLogLevel.Trace);
25
const logger = await _spdlog.createAsyncRotatingLogger(name, logfilePath, filesize, filecount);
26
if (donotUseFormatters) {
27
logger.clearFormatters();
28
} else {
29
logger.setPattern('%Y-%m-%d %H:%M:%S.%e [%l] %v');
30
}
31
return logger;
32
} catch (e) {
33
console.error(e);
34
}
35
return null;
36
}
37
38
interface ILog {
39
level: LogLevel;
40
message: string;
41
}
42
43
function log(logger: spdlog.Logger, level: LogLevel, message: string): void {
44
switch (level) {
45
case LogLevel.Trace: logger.trace(message); break;
46
case LogLevel.Debug: logger.debug(message); break;
47
case LogLevel.Info: logger.info(message); break;
48
case LogLevel.Warning: logger.warn(message); break;
49
case LogLevel.Error: logger.error(message); break;
50
case LogLevel.Off: /* do nothing */ break;
51
default: throw new Error(`Invalid log level ${level}`);
52
}
53
}
54
55
function setLogLevel(logger: spdlog.Logger, level: LogLevel): void {
56
switch (level) {
57
case LogLevel.Trace: logger.setLevel(SpdLogLevel.Trace); break;
58
case LogLevel.Debug: logger.setLevel(SpdLogLevel.Debug); break;
59
case LogLevel.Info: logger.setLevel(SpdLogLevel.Info); break;
60
case LogLevel.Warning: logger.setLevel(SpdLogLevel.Warning); break;
61
case LogLevel.Error: logger.setLevel(SpdLogLevel.Error); break;
62
case LogLevel.Off: logger.setLevel(SpdLogLevel.Off); break;
63
default: throw new Error(`Invalid log level ${level}`);
64
}
65
}
66
67
export class SpdLogLogger extends AbstractMessageLogger implements ILogger {
68
69
private buffer: ILog[] = [];
70
private readonly _loggerCreationPromise: Promise<void>;
71
private _logger: spdlog.Logger | undefined;
72
73
constructor(
74
name: string,
75
filepath: string,
76
rotating: boolean,
77
donotUseFormatters: boolean,
78
level: LogLevel,
79
) {
80
super();
81
this.setLevel(level);
82
this._loggerCreationPromise = this._createSpdLogLogger(name, filepath, rotating, donotUseFormatters);
83
this._register(this.onDidChangeLogLevel(level => {
84
if (this._logger) {
85
setLogLevel(this._logger, level);
86
}
87
}));
88
}
89
90
private async _createSpdLogLogger(name: string, filepath: string, rotating: boolean, donotUseFormatters: boolean): Promise<void> {
91
const filecount = rotating ? 6 : 1;
92
const filesize = (30 / filecount) * ByteSize.MB;
93
const logger = await createSpdLogLogger(name, filepath, filesize, filecount, donotUseFormatters);
94
if (logger) {
95
this._logger = logger;
96
setLogLevel(this._logger, this.getLevel());
97
for (const { level, message } of this.buffer) {
98
log(this._logger, level, message);
99
}
100
this.buffer = [];
101
}
102
}
103
104
protected log(level: LogLevel, message: string): void {
105
if (this._logger) {
106
log(this._logger, level, message);
107
} else if (this.getLevel() <= level) {
108
this.buffer.push({ level, message });
109
}
110
}
111
112
override flush(): void {
113
if (this._logger) {
114
this.flushLogger();
115
} else {
116
this._loggerCreationPromise.then(() => this.flushLogger());
117
}
118
}
119
120
override dispose(): void {
121
if (this._logger) {
122
this.disposeLogger();
123
} else {
124
this._loggerCreationPromise.then(() => this.disposeLogger());
125
}
126
super.dispose();
127
}
128
129
private flushLogger(): void {
130
if (this._logger) {
131
this._logger.flush();
132
}
133
}
134
135
private disposeLogger(): void {
136
if (this._logger) {
137
this._logger.drop();
138
this._logger = undefined;
139
}
140
}
141
}
142
143