Merge pull request #720 from DustinCampbell/omnisharp-logging

Improve OmniSharp server logging
This commit is contained in:
Dustin Campbell 2016-08-26 11:00:59 -07:00 коммит произвёл GitHub
Родитель 2d4b7ae003 bac456cbbb
Коммит bfa72b95e3
5 изменённых файлов: 114 добавлений и 25 удалений

Просмотреть файл

@ -17,6 +17,7 @@ const debugInstall = require('./out/coreclr-debug/install.js');
const fs_extra = require('fs-extra-promise'); const fs_extra = require('fs-extra-promise');
const omnisharp = require('./out/omnisharp/omnisharp'); const omnisharp = require('./out/omnisharp/omnisharp');
const download = require('./out/omnisharp/download'); const download = require('./out/omnisharp/download');
const logger = require('./out/omnisharp/logger');
const platform = require('./out/platform'); const platform = require('./out/platform');
const child_process = require('child_process'); const child_process = require('child_process');
@ -35,8 +36,11 @@ gulp.task('clean', ['omnisharp:clean', 'debugger:clean', 'package:clean'], () =
/// Omnisharp Tasks /// Omnisharp Tasks
function installOmnisharp(omnisharps) { function installOmnisharp(omnisharps) {
const logger = (message) => { console.log(message); }; const promises = omnisharps.map((omni, index) => {
const promises = omnisharps.map((omni) => download.go(omni.flavor, omni.platform, logger)); const log = new logger.Logger(message => process.stdout.write(message), index.toString());
return download.go(omni.flavor, omni.platform, log);
});
return Promise.all(promises); return Promise.all(promises);
} }

Просмотреть файл

@ -19,6 +19,7 @@ import {parse} from 'url';
import {Flavor, getInstallDirectory} from './omnisharp'; import {Flavor, getInstallDirectory} from './omnisharp';
import {Platform} from '../platform'; import {Platform} from '../platform';
import {getProxyAgent} from '../proxy'; import {getProxyAgent} from '../proxy';
import {Logger} from './logger';
const decompress = require('decompress'); const decompress = require('decompress');
@ -108,20 +109,17 @@ function download(urlString: string, proxy?: string, strictSSL?: boolean): Promi
}); });
} }
export function go(flavor: Flavor, platform: Platform, log?: (message: string) => void, proxy?: string, strictSSL?: boolean) { export function go(flavor: Flavor, platform: Platform, logger: Logger, proxy?: string, strictSSL?: boolean) {
return new Promise<boolean>((resolve, reject) => { return new Promise<boolean>((resolve, reject) => {
log = log || (_ => { });
log(`Flavor: ${flavor}, Platform: ${platform}`);
const fileName = getDownloadFileName(flavor, platform); const fileName = getDownloadFileName(flavor, platform);
const installDirectory = getInstallDirectory(flavor); const installDirectory = getInstallDirectory(flavor);
log(`[INFO] Installing OmniSharp to ${installDirectory}`); logger.appendLine(`Installing OmniSharp to ${installDirectory}`);
logger.increaseIndent();
const urlString = `${BaseDownloadUrl}/${fileName}`; const urlString = `${BaseDownloadUrl}/${fileName}`;
log(`[INFO] Attempting to download ${urlString}`); logger.appendLine(`Attempting to download ${fileName}`);
return download(urlString, proxy, strictSSL) return download(urlString, proxy, strictSSL)
.then(inStream => { .then(inStream => {
@ -130,7 +128,7 @@ export function go(flavor: Flavor, platform: Platform, log?: (message: string) =
return reject(err); return reject(err);
} }
log(`[INFO] Downloading to ${tmpPath}...`); logger.appendLine(`Downloading to ${tmpPath}...`);
const outStream = fs.createWriteStream(null, { fd: fd }); const outStream = fs.createWriteStream(null, { fd: fd });
@ -140,16 +138,16 @@ export function go(flavor: Flavor, platform: Platform, log?: (message: string) =
outStream.once('finish', () => { outStream.once('finish', () => {
// At this point, the asset has finished downloading. // At this point, the asset has finished downloading.
log(`[INFO] Download complete!`); logger.appendLine(`Download complete!`);
log(`[INFO] Decompressing...`); logger.appendLine(`Decompressing...`);
return decompress(tmpPath, installDirectory) return decompress(tmpPath, installDirectory)
.then(files => { .then(files => {
log(`[INFO] Done! ${files.length} files unpacked.`); logger.appendLine(`Done! ${files.length} files unpacked.\n`);
return resolve(true); return resolve(true);
}) })
.catch(err => { .catch(err => {
log(`[ERROR] ${err}`); logger.appendLine(`[ERROR] ${err}`);
return reject(err); return reject(err);
}); });
}); });
@ -159,7 +157,10 @@ export function go(flavor: Flavor, platform: Platform, log?: (message: string) =
}) })
.catch(err => .catch(err =>
{ {
log(`[ERROR] ${err}`); logger.appendLine(`[ERROR] ${err}`);
}); });
}).then(res => {
logger.decreaseIndent();
return res;
}); });
} }

Просмотреть файл

@ -149,6 +149,7 @@ export interface LaunchDetails {
export interface LaunchResult { export interface LaunchResult {
process: ChildProcess; process: ChildProcess;
command: string; command: string;
usingMono: boolean;
} }
export function launchOmniSharp(details: LaunchDetails): Promise<LaunchResult> { export function launchOmniSharp(details: LaunchDetails): Promise<LaunchResult> {
@ -205,7 +206,8 @@ function launchWindows(details: LaunchDetails): Promise<LaunchResult> {
return resolve({ return resolve({
process, process,
command: details.serverPath command: details.serverPath,
usingMono: false
}); });
}); });
} }
@ -231,7 +233,8 @@ function launchNixCoreCLR(details: LaunchDetails): Promise<LaunchResult> {
return resolve({ return resolve({
process, process,
command: details.serverPath command: details.serverPath,
usingMono: false
}); });
}); });
} }
@ -249,7 +252,8 @@ function launchNixMono(details: LaunchDetails): Promise<LaunchResult> {
return resolve({ return resolve({
process, process,
command: details.serverPath command: details.serverPath,
usingMono: true
}); });
}); });
}); });

58
src/omnisharp/logger.ts Normal file
Просмотреть файл

@ -0,0 +1,58 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
export class Logger {
private _writer: (message: string) => void;
private _prefix: string;
private _indentLevel: number = 0;
private _indentSize: number = 4;
private _atLineStart: boolean = false;
constructor(writer: (message: string) => void, prefix?: string) {
this._writer = writer;
this._prefix = prefix;
}
private _appendCore(message: string): void {
if (this._atLineStart) {
if (this._indentLevel > 0) {
const indent = " ".repeat(this._indentLevel * this._indentSize);
this._writer(indent);
}
if (this._prefix) {
this._writer(`[${this._prefix}] `);
}
this._atLineStart = false;
}
this._writer(message);
}
public increaseIndent(): void {
this._indentLevel += 1;
}
public decreaseIndent(): void {
if (this._indentLevel > 0) {
this._indentLevel -= 1;
}
}
public append(message?: string): void {
message = message || "";
this._appendCore(message);
}
public appendLine(message?: string): void {
message = message || "";
this._appendCore(message + '\n');
this._atLineStart = true;
}
}

Просмотреть файл

@ -13,6 +13,7 @@ import {launchOmniSharp} from './launcher';
import * as protocol from './protocol'; import * as protocol from './protocol';
import * as omnisharp from './omnisharp'; import * as omnisharp from './omnisharp';
import * as download from './download'; import * as download from './download';
import {Logger} from './logger';
import {DelayTracker} from './delayTracker'; import {DelayTracker} from './delayTracker';
import {LaunchTarget, findLaunchTargets, getDefaultFlavor} from './launcher'; import {LaunchTarget, findLaunchTargets, getDefaultFlavor} from './launcher';
import {Platform, getCurrentPlatform} from '../platform'; import {Platform, getCurrentPlatform} from '../platform';
@ -76,6 +77,7 @@ export abstract class OmnisharpServer {
private _queue: Request[] = []; private _queue: Request[] = [];
private _isProcessingQueue = false; private _isProcessingQueue = false;
private _channel: vscode.OutputChannel; private _channel: vscode.OutputChannel;
protected _logger: Logger;
private _isDebugEnable: boolean = false; private _isDebugEnable: boolean = false;
@ -84,8 +86,10 @@ export abstract class OmnisharpServer {
constructor(reporter: TelemetryReporter) { constructor(reporter: TelemetryReporter) {
this._extraArgs = []; this._extraArgs = [];
this._channel = vscode.window.createOutputChannel('OmniSharp Log');
this._reporter = reporter; this._reporter = reporter;
this._channel = vscode.window.createOutputChannel('OmniSharp Log');
this._logger = new Logger(message => this._channel.append(message));
} }
public isRunning(): boolean { public isRunning(): boolean {
@ -276,15 +280,33 @@ export abstract class OmnisharpServer {
args = args.concat(this._extraArgs); args = args.concat(this._extraArgs);
this._fireEvent(Events.StdOut, `[INFO] Starting OmniSharp at '${solutionPath}'...\n`); this._logger.appendLine(`Starting OmniSharp server at ${new Date().toLocaleString()}`);
this._logger.increaseIndent();
this._logger.appendLine(`Target: ${solutionPath}`);
this._logger.decreaseIndent();
this._logger.appendLine();
this._fireEvent(Events.BeforeServerStart, solutionPath); this._fireEvent(Events.BeforeServerStart, solutionPath);
return launchOmniSharp({serverPath, flavor, cwd, args}).then(value => { return launchOmniSharp({serverPath, flavor, cwd, args}).then(value => {
if (value.usingMono) {
this._logger.appendLine(`OmniSharp server started wth Mono`);
}
else {
this._logger.appendLine(`OmniSharp server started`);
}
this._logger.increaseIndent();
this._logger.appendLine(`Path: ${value.command}`);
this._logger.appendLine(`PID: ${value.process.pid}`);
this._logger.decreaseIndent();
this._logger.appendLine();
this._serverProcess = value.process; this._serverProcess = value.process;
this._delayTrackers = {}; this._delayTrackers = {};
this._fireEvent(Events.StdOut, `[INFO] Started OmniSharp from '${value.command}' with process id ${value.process.pid}...\n`);
this._setState(ServerState.Started); this._setState(ServerState.Started);
this._fireEvent(Events.ServerStart, solutionPath); this._fireEvent(Events.ServerStart, solutionPath);
return this._doConnect(); return this._doConnect();
}).then(() => { }).then(() => {
return vscode.commands.getCommands() return vscode.commands.getCommands()
@ -440,11 +462,11 @@ export abstract class OmnisharpServer {
const config = vscode.workspace.getConfiguration(); const config = vscode.workspace.getConfiguration();
const proxy = config.get<string>('http.proxy'); const proxy = config.get<string>('http.proxy');
const strictSSL = config.get('http.proxyStrictSSL', true); const strictSSL = config.get('http.proxyStrictSSL', true);
const logger = (message: string) => { this._channel.appendLine(message); }; const logger = (message: string) => { this._logger.appendLine(message); };
this._fireEvent(Events.BeforeServerInstall, this); this._fireEvent(Events.BeforeServerInstall, this);
return download.go(flavor, platform, logger, proxy, strictSSL).then(_ => { return download.go(flavor, platform, this._logger, proxy, strictSSL).then(_ => {
return omnisharp.findServerPath(installDirectory); return omnisharp.findServerPath(installDirectory);
}); });
}); });
@ -622,7 +644,7 @@ export class StdioOmnisharpServer extends OmnisharpServer {
const onLineReceived = (line: string) => { const onLineReceived = (line: string) => {
if (line[0] !== '{') { if (line[0] !== '{') {
this._fireEvent(Events.StdOut, `${line}\n`); this._logger.appendLine(line);
return; return;
} }
@ -681,7 +703,7 @@ export class StdioOmnisharpServer extends OmnisharpServer {
if (packet.Event === 'log') { if (packet.Event === 'log') {
// handle log events // handle log events
const entry = <{ LogLevel: string; Name: string; Message: string; }>packet.Body; const entry = <{ LogLevel: string; Name: string; Message: string; }>packet.Body;
this._fireEvent(Events.StdOut, `[${entry.LogLevel}:${entry.Name}] ${entry.Message}\n`); this._logger.appendLine(`[${entry.LogLevel}:${entry.Name}] ${entry.Message}`);
return; return;
} else { } else {
// fwd all other events // fwd all other events