diff --git a/src/vs/code/electron-browser/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcessMain.ts index 934007fcceb..1f42e93f975 100644 --- a/src/vs/code/electron-browser/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcessMain.ts @@ -35,7 +35,7 @@ import { WindowsChannelClient } from 'vs/platform/windows/common/windowsIpc'; import { ipcRenderer } from 'electron'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { createSharedProcessContributions } from 'vs/code/electron-browser/contrib/contributions'; -import { SpdLogService } from 'vs/platform/log/node/spdlogService'; +import { createLogService } from 'vs/platform/log/node/spdlogService'; import { ILogService, registerGlobalLogService } from 'vs/platform/log/common/log'; export interface ISharedProcessConfiguration { @@ -79,7 +79,7 @@ function main(server: Server, initData: ISharedProcessInitData, configuration: I const services = new ServiceCollection(); const environmentService = new EnvironmentService(initData.args, process.execPath); - const logService = new SpdLogService('sharedprocess', environmentService); + const logService = createLogService('sharedprocess', environmentService); process.once('exit', () => logService.dispose()); registerGlobalLogService(logService); diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index e305aba5ff9..8299843bf7d 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -9,8 +9,9 @@ import { app, dialog } from 'electron'; import { assign } from 'vs/base/common/objects'; import * as platform from 'vs/base/common/platform'; import product from 'vs/platform/node/product'; +import * as path from 'path'; import { parseMainProcessArgv } from 'vs/platform/environment/node/argv'; -import { mkdirp } from 'vs/base/node/pfs'; +import { mkdirp, readdir, rimraf } from 'vs/base/node/pfs'; import { validatePaths } from 'vs/code/node/paths'; import { LifecycleService, ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net'; @@ -41,14 +42,14 @@ import { WorkspacesMainService } from 'vs/platform/workspaces/electron-main/work import { IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces'; import { localize } from 'vs/nls'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; -import { SpdLogService } from 'vs/platform/log/node/spdlogService'; +import { createLogService } from 'vs/platform/log/node/spdlogService'; import { printDiagnostics } from 'vs/code/electron-main/diagnostics'; function createServices(args: ParsedArgs): IInstantiationService { const services = new ServiceCollection(); const environmentService = new EnvironmentService(args, process.execPath); - const spdlogService = new SpdLogService('main', environmentService); + const spdlogService = createLogService('main', environmentService); const consoleLogService = new ConsoleLogMainService(environmentService); const logService = new MultiplexLogService([consoleLogService, spdlogService]); @@ -56,7 +57,7 @@ function createServices(args: ParsedArgs): IInstantiationService { process.once('exit', () => logService.dispose()); // Eventually cleanup - setTimeout(() => spdlogService.cleanup().then(null, err => console.error(err)), 10000); + setTimeout(() => cleanupOlderLogs(environmentService).then(null, err => console.error(err)), 10000); services.set(IEnvironmentService, environmentService); services.set(ILogService, logService); @@ -72,6 +73,20 @@ function createServices(args: ParsedArgs): IInstantiationService { return new InstantiationService(services, true); } +/** + * Cleans up older logs, while keeping the 10 most recent ones. +*/ +async function cleanupOlderLogs(environmentService: EnvironmentService): TPromise { + const currentLog = path.basename(environmentService.logsPath); + const logsRoot = path.dirname(environmentService.logsPath); + const children = await readdir(logsRoot); + const allSessions = children.filter(name => /^\d{8}T\d{6}$/.test(name)); + const oldSessions = allSessions.sort().filter((d, i) => d !== currentLog); + const toDelete = oldSessions.slice(0, Math.max(0, oldSessions.length - 9)); + + await TPromise.join(toDelete.map(name => rimraf(path.join(logsRoot, name)))); +} + function createPaths(environmentService: IEnvironmentService): TPromise { const paths = [ environmentService.appSettingsHome, diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index 93f32694539..21b4cf65866 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -35,7 +35,7 @@ import { ChoiceCliService } from 'vs/platform/message/node/messageCli'; import { getBaseLabel } from 'vs/base/common/labels'; import { IStateService } from 'vs/platform/state/common/state'; import { StateService } from 'vs/platform/state/node/stateService'; -import { SpdLogService } from 'vs/platform/log/node/spdlogService'; +import { createLogService } from 'vs/platform/log/node/spdlogService'; import { registerGlobalLogService, ILogService } from 'vs/platform/log/common/log'; const notFound = (id: string) => localize('notFound', "Extension '{0}' not found.", id); @@ -179,7 +179,8 @@ export function main(argv: ParsedArgs): TPromise { const services = new ServiceCollection(); const environmentService = new EnvironmentService(argv, process.execPath); - const logService = new SpdLogService('cli', environmentService); + const logService = createLogService('cli', environmentService); + process.once('exit', () => logService.dispose()); registerGlobalLogService(logService); logService.info('main', argv); diff --git a/src/vs/platform/log/node/spdlogService.ts b/src/vs/platform/log/node/spdlogService.ts index 61d670adc4c..a4d0ac85ccc 100644 --- a/src/vs/platform/log/node/spdlogService.ts +++ b/src/vs/platform/log/node/spdlogService.ts @@ -6,44 +6,33 @@ 'use strict'; import * as path from 'path'; -import { ILogService, LogLevel } from 'vs/platform/log/common/log'; +import { ILogService, LogLevel, NoopLogService } from 'vs/platform/log/common/log'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { RotatingLogger, setAsyncMode } from 'spdlog'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { TPromise } from 'vs/base/common/winjs.base'; -import { readdir, rimraf } from 'vs/base/node/pfs'; -export class SpdLogService implements ILogService { +export function createLogService(processName: string, environmentService: IEnvironmentService): ILogService { + try { + setAsyncMode(8192, 2000); + const logfilePath = path.join(environmentService.logsPath, `${processName}.log`); + const logger = new RotatingLogger(processName, logfilePath, 1024 * 1024 * 5, 6); + return new SpdLogService(logger, environmentService.logLevel); + } catch (e) { + console.error(e); + } + return new NoopLogService(); +} + +class SpdLogService implements ILogService { _serviceBrand: any; - private level: LogLevel = LogLevel.Error; - private logger: RotatingLogger; private disposables: IDisposable[] = []; constructor( - processName: string, - @IEnvironmentService private environmentService: IEnvironmentService + private readonly logger: RotatingLogger, + private level: LogLevel = LogLevel.Error ) { - setAsyncMode(8192, 2000); - - const logfilePath = path.join(environmentService.logsPath, `${processName}.log`); - this.logger = new RotatingLogger(processName, logfilePath, 1024 * 1024 * 5, 6); - this.setLevel(environmentService.logLevel); - } - - /** - * Cleans up older logs, while keeping the 10 most recent ones. - */ - async cleanup(): TPromise { - const currentLog = path.basename(this.environmentService.logsPath); - const logsRoot = path.dirname(this.environmentService.logsPath); - const children = await readdir(logsRoot); - const allSessions = children.filter(name => /^\d{8}T\d{6}$/.test(name)); - const oldSessions = allSessions.sort().filter((d, i) => d !== currentLog); - const toDelete = oldSessions.slice(0, Math.max(0, oldSessions.length - 9)); - - await TPromise.join(toDelete.map(name => rimraf(path.join(logsRoot, name)))); } setLevel(logLevel: LogLevel): void { diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts index 0504f085b57..f68435c5753 100644 --- a/src/vs/workbench/electron-browser/main.ts +++ b/src/vs/workbench/electron-browser/main.ts @@ -39,7 +39,7 @@ import { URLChannelClient } from 'vs/platform/url/common/urlIpc'; import { IURLService } from 'vs/platform/url/common/url'; import { WorkspacesChannelClient } from 'vs/platform/workspaces/common/workspacesIpc'; import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; -import { SpdLogService } from 'vs/platform/log/node/spdlogService'; +import { createLogService } from 'vs/platform/log/node/spdlogService'; import fs = require('fs'); import { registerGlobalLogService } from 'vs/platform/log/common/log'; @@ -74,7 +74,7 @@ function openWorkbench(configuration: IWindowConfiguration): TPromise { const mainServices = createMainProcessServices(mainProcessClient); const environmentService = new EnvironmentService(configuration, configuration.execPath); - const logService = new SpdLogService(`renderer${currentWindowId}`, environmentService); + const logService = createLogService(`renderer${currentWindowId}`, environmentService); registerGlobalLogService(logService); logService.info('openWorkbench', JSON.stringify(configuration)); diff --git a/src/vs/workbench/node/extensionHostMain.ts b/src/vs/workbench/node/extensionHostMain.ts index c6f8750a74c..9902580455f 100644 --- a/src/vs/workbench/node/extensionHostMain.ts +++ b/src/vs/workbench/node/extensionHostMain.ts @@ -23,7 +23,7 @@ import * as watchdog from 'native-watchdog'; import * as glob from 'vs/base/common/glob'; import { ExtensionActivatedByEvent } from 'vs/workbench/api/node/extHostExtensionActivator'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; -import { SpdLogService } from 'vs/platform/log/node/spdlogService'; +import { createLogService } from 'vs/platform/log/node/spdlogService'; import { registerGlobalLogService } from 'vs/platform/log/common/log'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; @@ -90,7 +90,7 @@ export class ExtensionHostMain { const threadService = new ExtHostThreadService(rpcProtocol); const extHostWorkspace = new ExtHostWorkspace(threadService, initData.workspace); const environmentService = new EnvironmentService(initData.args, initData.execPath); - const logService = new SpdLogService(`exthost${initData.windowId}`, environmentService); + const logService = createLogService(`exthost${initData.windowId}`, environmentService); registerGlobalLogService(logService); this.disposables.push(logService);