microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
2c19da7f131d11b4265a94fe25139194a565116e

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/extension/log/OutputChannelLogger.ts

161lines · 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
14
15const channels: { [channelName: string]: OutputChannelLogger } = {};
16
17export class OutputChannelLogger implements ILogger {
18 public static MAIN_CHANNEL_NAME: string = "React Native";
19 private readonly channelLogFilePath: string | undefined;
20 private channelLogFileStream: fs.WriteStream;
21 private outputChannel: vscode.OutputChannel;
22 private logTimestamps: boolean;
23 private static forbiddenFileNameSymbols: RegExp = /\W/gi;
24
25 public static disposeChannel(channelName: string): void {
26 if (channels[channelName]) {
27 channels[channelName].getOutputChannel().dispose();
28 if (channels[channelName].channelLogFileStream) {
29 channels[channelName].channelLogFileStream.end();
30 }
31 delete channels[channelName];
32 }
33 }
34
35 public static getMainChannel(): OutputChannelLogger {
36 return this.getChannel(this.MAIN_CHANNEL_NAME, true);
37 }
38
39 public static getChannel(channelName: string, lazy?: boolean, preserveFocus?: boolean, logTimestamps?: boolean): OutputChannelLogger {
40 if (!channels[channelName]) {
41 channels[channelName] = new OutputChannelLogger(channelName, lazy, preserveFocus, logTimestamps);
42 }
43 return channels[channelName];
44 }
45
46 constructor(public readonly channelName: string, lazy: boolean = false, private preserveFocus: boolean = false, logTimestamps: boolean = false) {
47 this.logTimestamps = logTimestamps;
48 const channelLogFolder = getLoggingDirectory();
49 if (channelLogFolder) {
50 const filename = channelName.replace(OutputChannelLogger.forbiddenFileNameSymbols, "");
51 this.channelLogFilePath = path.join(channelLogFolder, `${filename}.txt`);
52 this.channelLogFileStream = fs.createWriteStream(this.channelLogFilePath);
53 this.channelLogFileStream.on("error", err => {
54 this.error(`Error writing to log file at path: ${this.channelLogFilePath}. Error: ${err.toString()}\n`);
55 });
56 }
57 if (!lazy) {
58 this.channel = vscode.window.createOutputChannel(this.channelName);
59 this.channel.show(this.preserveFocus);
60 }
61 }
62
63 public log(message: string, level: LogLevel): void {
64 if (LogHelper.LOG_LEVEL === LogLevel.None) {
65 return;
66 }
67
68 if (level >= LogHelper.LOG_LEVEL) {
69 message = OutputChannelLogger.getFormattedMessage(message, LogLevel[level], this.logTimestamps);
70 this.channel.appendLine(message);
71 if (this.channelLogFileStream) {
72 this.channelLogFileStream.write(message);
73 }
74 }
75 }
76
77 public logWithCustomTag(tag: string, message: string, level: LogLevel): void {
78 if (LogHelper.LOG_LEVEL === LogLevel.None) {
79 return;
80 }
81
82 if (level === LogLevel.Custom) {
83 message = OutputChannelLogger.getFormattedMessage(message, tag, this.logTimestamps);
84 this.channel.appendLine(message);
85 if (this.channelLogFileStream) {
86 this.channelLogFileStream.write(message);
87 }
88 }
89 }
90
91 public info(message: string): void {
92 this.log(message, LogLevel.Info);
93 }
94
95 public warning(message: string | Error, logStack = false): void {
96 this.log(message.toString(), LogLevel.Warning);
97 }
98
99 public error(errorMessage: string, error?: Error, logStack: boolean = true): void {
100 const message = OutputChannelLogger.getFormattedMessage(errorMessage, LogLevel[LogLevel.Error], this.logTimestamps);
101 this.channel.appendLine(message);
102 if (this.channelLogFileStream) {
103 this.channelLogFileStream.write(message);
104 }
105
106 // Print the error stack if necessary
107 if (logStack && error && (<Error>error).stack) {
108 this.channel.appendLine(`Stack: ${(<Error>error).stack}`);
109 if (this.channelLogFileStream) {
110 this.channelLogFileStream.write(`Stack: ${(<Error>error).stack}`);
111 }
112 }
113 }
114
115 public debug(message: string): void {
116 this.log(message, LogLevel.Debug);
117 }
118
119 public logStream(data: Buffer | string) {
120 this.channel.append(data.toString());
121 if (this.channelLogFileStream) {
122 this.channelLogFileStream.write(data);
123 }
124 }
125
126 public setFocusOnLogChannel(): void {
127 this.channel.show(false);
128 }
129
130 protected static getFormattedMessage(message: string, tag: string, prependTimestamp: boolean = false): string {
131 let formattedMessage = `[${tag}] ${message}\n`;
132
133 if (prependTimestamp) {
134 formattedMessage = `[${getFormattedDatetimeString(new Date())}] ${formattedMessage}`;
135 }
136
137 return formattedMessage;
138 }
139
140 public getOutputChannel(): vscode.OutputChannel {
141 return this.channel;
142 }
143
144 public clear(): void {
145 this.channel.clear();
146 }
147
148 private get channel(): vscode.OutputChannel {
149 if (this.outputChannel) {
150 return this.outputChannel;
151 } else {
152 this.outputChannel = vscode.window.createOutputChannel(this.channelName);
153 this.outputChannel.show(this.preserveFocus);
154 return this.outputChannel;
155 }
156 }
157
158 private set channel(channel: vscode.OutputChannel) {
159 this.outputChannel = channel;
160 }
161}
162