microsoft/vscode-react-native

Public

mirrored fromhttps://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
1.5.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/extension/log/OutputChannelLogger.ts

191lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4/**
5 * Formatter for the Output channel.
6 */
7
8import * as vscode from "vscode";
9import { ILogger, LogLevel, LogHelper, getLoggingDirectory } from "./LogHelper";
10import * as fs from "fs";
11import * as path from "path";
12import { getFormattedDatetimeString } from "../../common/utils";
13
14const channels: { [channelName: string]: OutputChannelLogger } = {};
15
16export class OutputChannelLogger implements ILogger {
17 public static MAIN_CHANNEL_NAME: string = "React Native";
18 private readonly channelLogFilePath: string | undefined;
19 private channelLogFileStream: fs.WriteStream;
20 private outputChannel: vscode.OutputChannel;
21 private logTimestamps: boolean;
22 private static forbiddenFileNameSymbols: RegExp = /\W/gi;
23
24 public static disposeChannel(channelName: string): void {
25 if (channels[channelName]) {
26 channels[channelName].getOutputChannel().dispose();
27 if (channels[channelName].channelLogFileStream) {
28 channels[channelName].channelLogFileStream.end();
29 }
30 delete channels[channelName];
31 }
32 }
33
34 public static getMainChannel(): OutputChannelLogger {
35 return this.getChannel(this.MAIN_CHANNEL_NAME, true);
36 }
37
38 public static getChannel(
39 channelName: string,
40 lazy?: boolean,
41 preserveFocus?: boolean,
42 logTimestamps?: boolean,
43 ): OutputChannelLogger {
44 if (!channels[channelName]) {
45 channels[channelName] = new OutputChannelLogger(
46 channelName,
47 lazy,
48 preserveFocus,
49 logTimestamps,
50 );
51 }
52 return channels[channelName];
53 }
54
55 constructor(
56 public readonly channelName: string,
57 lazy: boolean = false,
58 private preserveFocus: boolean = false,
59 logTimestamps: boolean = false,
60 ) {
61 this.logTimestamps = logTimestamps;
62 const channelLogFolder = getLoggingDirectory();
63 if (channelLogFolder) {
64 const filename = channelName.replace(OutputChannelLogger.forbiddenFileNameSymbols, "");
65 this.channelLogFilePath = path.join(channelLogFolder, `${filename}.txt`);
66 this.channelLogFileStream = fs.createWriteStream(this.channelLogFilePath);
67 this.channelLogFileStream.on("error", err => {
68 this.error(
69 `Error writing to log file at path: ${
70 this.channelLogFilePath
71 }. Error: ${err.toString()}\n`,
72 );
73 });
74 }
75 if (!lazy) {
76 this.channel = vscode.window.createOutputChannel(this.channelName);
77 this.channel.show(this.preserveFocus);
78 }
79 }
80
81 public log(message: string, level: LogLevel): void {
82 if (LogHelper.LOG_LEVEL === LogLevel.None) {
83 return;
84 }
85
86 if (level >= LogHelper.LOG_LEVEL) {
87 message = OutputChannelLogger.getFormattedMessage(
88 message,
89 LogLevel[level],
90 this.logTimestamps,
91 );
92 this.channel.appendLine(message);
93 if (this.channelLogFileStream) {
94 this.channelLogFileStream.write(message);
95 }
96 }
97 }
98
99 public logWithCustomTag(tag: string, message: string, level: LogLevel): void {
100 if (LogHelper.LOG_LEVEL === LogLevel.None) {
101 return;
102 }
103
104 if (level === LogLevel.Custom) {
105 message = OutputChannelLogger.getFormattedMessage(message, tag, this.logTimestamps);
106 this.channel.appendLine(message);
107 if (this.channelLogFileStream) {
108 this.channelLogFileStream.write(message);
109 }
110 }
111 }
112
113 public info(message: string): void {
114 this.log(message, LogLevel.Info);
115 }
116
117 public warning(message: string | Error): void {
118 this.log(message.toString(), LogLevel.Warning);
119 }
120
121 public error(errorMessage: string, error?: Error, logStack: boolean = true): void {
122 const message = OutputChannelLogger.getFormattedMessage(
123 errorMessage,
124 LogLevel[LogLevel.Error],
125 this.logTimestamps,
126 );
127 this.channel.appendLine(message);
128 if (this.channelLogFileStream) {
129 this.channelLogFileStream.write(message);
130 }
131
132 // Print the error stack if necessary
133 if (logStack && error && (<Error>error).stack) {
134 this.channel.appendLine(`Stack: ${(<Error>error).stack}`);
135 if (this.channelLogFileStream) {
136 this.channelLogFileStream.write(`Stack: ${(<Error>error).stack}`);
137 }
138 }
139 }
140
141 public debug(message: string): void {
142 this.log(message, LogLevel.Debug);
143 }
144
145 public logStream(data: Buffer | string): void {
146 this.channel.append(data.toString());
147 if (this.channelLogFileStream) {
148 this.channelLogFileStream.write(data);
149 }
150 }
151
152 public setFocusOnLogChannel(): void {
153 this.channel.show(false);
154 }
155
156 protected static getFormattedMessage(
157 message: string,
158 tag: string,
159 prependTimestamp: boolean = false,
160 ): string {
161 let formattedMessage = `[${tag}] ${message}\n`;
162
163 if (prependTimestamp) {
164 formattedMessage = `[${getFormattedDatetimeString(new Date())}] ${formattedMessage}`;
165 }
166
167 return formattedMessage;
168 }
169
170 public getOutputChannel(): vscode.OutputChannel {
171 return this.channel;
172 }
173
174 public clear(): void {
175 this.channel.clear();
176 }
177
178 private get channel(): vscode.OutputChannel {
179 if (this.outputChannel) {
180 return this.outputChannel;
181 } else {
182 this.outputChannel = vscode.window.createOutputChannel(this.channelName);
183 this.outputChannel.show(this.preserveFocus);
184 return this.outputChannel;
185 }
186 }
187
188 private set channel(channel: vscode.OutputChannel) {
189 this.outputChannel = channel;
190 }
191}