Specify custom directory for storing query server logs

This commit is contained in:
shati-patel
2021-05-14 18:03:33 +01:00
committed by Shati Patel
parent f550cbe98f
commit 7e27f20e0e
5 changed files with 55 additions and 13 deletions

View File

@@ -179,6 +179,14 @@
"default": 20,
"description": "Max number of simultaneous queries to run using the 'CodeQL: Run Queries' command."
},
"codeQL.runningQueries.customLogDirectory": {
"type": [
"string",
null
],
"default": null,
"description": "Path to a directory where the CodeQL extension should store query server logs. If empty, the extension stores logs in a temporary workspace folder and deletes the contents after each run."
},
"codeQL.resultsDisplay.pageSize": {
"type": "integer",
"default": 200,

View File

@@ -87,9 +87,10 @@ export const NUMBER_OF_TEST_THREADS_SETTING = new Setting('numberOfThreads', RUN
export const MAX_QUERIES = new Setting('maxQueries', RUNNING_QUERIES_SETTING);
export const AUTOSAVE_SETTING = new Setting('autoSave', RUNNING_QUERIES_SETTING);
export const PAGE_SIZE = new Setting('pageSize', RESULTS_DISPLAY_SETTING);
const CUSTOM_LOG_DIRECTORY_SETTING = new Setting('customLogDirectory', RUNNING_QUERIES_SETTING);
/** When these settings change, the running query server should be restarted. */
const QUERY_SERVER_RESTARTING_SETTINGS = [NUMBER_OF_THREADS_SETTING, SAVE_CACHE_SETTING, CACHE_SIZE_SETTING, MEMORY_SETTING, DEBUG_SETTING];
const QUERY_SERVER_RESTARTING_SETTINGS = [NUMBER_OF_THREADS_SETTING, SAVE_CACHE_SETTING, CACHE_SIZE_SETTING, MEMORY_SETTING, DEBUG_SETTING, CUSTOM_LOG_DIRECTORY_SETTING];
export interface QueryServerConfig {
codeQlPath: string;
@@ -99,6 +100,7 @@ export interface QueryServerConfig {
cacheSize: number;
queryMemoryMb?: number;
timeoutSecs: number;
customLogDirectory?: string;
onDidChangeConfiguration?: Event<void>;
}
@@ -197,6 +199,10 @@ export class QueryServerConfigListener extends ConfigListener implements QuerySe
return this._codeQlPath;
}
public get customLogDirectory(): string | undefined {
return CUSTOM_LOG_DIRECTORY_SETTING.getValue<string>() || undefined;
}
public get numThreads(): number {
return NUMBER_OF_THREADS_SETTING.getValue<number>();
}

View File

@@ -380,6 +380,7 @@ async function activateWithInstalledDistribution(
cliServer,
{
logger: queryServerLogger,
contextStoragePath: getContextStoragePath(ctx),
},
(task) =>
Window.withProgress(
@@ -768,9 +769,8 @@ function getContextStoragePath(ctx: ExtensionContext) {
function initializeLogging(ctx: ExtensionContext): void {
const storagePath = getContextStoragePath(ctx);
logger.init(storagePath);
queryServerLogger.init(storagePath);
ideServerLogger.init(storagePath);
logger.setLogStoragePath(storagePath, false);
ideServerLogger.setLogStoragePath(storagePath, false);
ctx.subscriptions.push(logger);
ctx.subscriptions.push(queryServerLogger);
ctx.subscriptions.push(ideServerLogger);

View File

@@ -40,18 +40,24 @@ export class OutputChannelLogger extends DisposableObject implements Logger {
public readonly outputChannel: OutputChannel;
private readonly additionalLocations = new Map<string, AdditionalLogLocation>();
private additionalLogLocationPath: string | undefined;
isCustomLogDirectory: boolean;
constructor(private title: string) {
super();
this.outputChannel = Window.createOutputChannel(title);
this.push(this.outputChannel);
this.isCustomLogDirectory = false;
}
init(storagePath: string): void {
setLogStoragePath(storagePath: string, isCustomLogDirectory: boolean): void {
this.additionalLogLocationPath = path.join(storagePath, this.title);
// clear out any old state from previous runs
fs.remove(this.additionalLogLocationPath);
this.isCustomLogDirectory = isCustomLogDirectory;
if (!this.isCustomLogDirectory) {
// clear out any old state from previous runs
fs.remove(this.additionalLogLocationPath);
}
}
/**
@@ -80,7 +86,7 @@ export class OutputChannelLogger extends DisposableObject implements Logger {
this.outputChannel.appendLine(separator);
this.outputChannel.appendLine(msg);
this.outputChannel.appendLine(separator);
additional = new AdditionalLogLocation(logPath);
additional = new AdditionalLogLocation(logPath, !this.isCustomLogDirectory);
this.additionalLocations.set(logPath, additional);
this.track(additional);
}
@@ -112,7 +118,7 @@ export class OutputChannelLogger extends DisposableObject implements Logger {
}
class AdditionalLogLocation extends Disposable {
constructor(private location: string) {
constructor(private location: string, private shouldDeleteLogs: boolean) {
super(() => { /**/ });
}
@@ -128,7 +134,9 @@ class AdditionalLogLocation extends Disposable {
}
async dispose(): Promise<void> {
await fs.remove(this.location);
if (this.shouldDeleteLogs) {
await fs.remove(this.location);
}
}
}

View File

@@ -5,13 +5,16 @@ import { Disposable, CancellationToken, commands } from 'vscode';
import { createMessageConnection, MessageConnection, RequestType } from 'vscode-jsonrpc';
import * as cli from './cli';
import { QueryServerConfig } from './config';
import { Logger, ProgressReporter } from './logging';
import { Logger, ProgressReporter, queryServerLogger } from './logging';
import { completeQuery, EvaluationResult, progress, ProgressMessage, WithProgressId } from './pure/messages';
import * as messages from './pure/messages';
import { ProgressCallback, ProgressTask } from './commandRunner';
import * as fs from 'fs-extra';
import * as helpers from './helpers';
type ServerOpts = {
logger: Logger;
contextStoragePath: string;
}
/** A running query server process and its associated message connection. */
@@ -86,8 +89,24 @@ export class QueryServerClient extends DisposableObject {
this.evaluationResultCallbacks = {};
}
initLogger() {
let storagePath = this.opts.contextStoragePath;
let isCustomLogDirectory = false;
if (this.config.customLogDirectory) {
if (fs.existsSync(this.config.customLogDirectory) && fs.statSync(this.config.customLogDirectory).isDirectory()) {
storagePath = this.config.customLogDirectory;
isCustomLogDirectory = true;
} else if (this.config.customLogDirectory) {
helpers.showAndLogErrorMessage(`${this.config.customLogDirectory} is not a valid directory. Logs will be stored in a temporary workspace directory instead.`);
}
}
queryServerLogger.setLogStoragePath(storagePath, isCustomLogDirectory);
}
get logger(): Logger {
return this.opts.logger;
return queryServerLogger;
}
/** Stops the query server by disposing of the current server process. */
@@ -151,6 +170,7 @@ export class QueryServerClient extends DisposableObject {
args.push('-J=-agentlib:jdwp=transport=dt_socket,address=localhost:9010,server=y,suspend=n,quiet=y');
}
this.initLogger();
const child = cli.spawnServer(
this.config.codeQlPath,
'CodeQL query server',
@@ -185,7 +205,7 @@ export class QueryServerClient extends DisposableObject {
callback(res);
}
});
this.serverProcess = new ServerProcess(child, connection, this.opts.logger);
this.serverProcess = new ServerProcess(child, connection, this.logger);
// Ensure the server process is disposed together with this client.
this.track(this.serverProcess);
connection.listen();