Print end-of-query summary logs to Query Server Console (#1264)

* Log new end summary file to query server console

* Change supported CLI version to 2.9.0
This commit is contained in:
Angela P Wen
2022-03-31 09:26:13 -07:00
committed by GitHub
parent 2f7908773a
commit cc1bf74370
7 changed files with 64 additions and 22 deletions

View File

@@ -6,6 +6,7 @@
- Avoid synchronizing the `codeQL.cli.executablePath` setting. [#1252](https://github.com/github/vscode-codeql/pull/1252) - Avoid synchronizing the `codeQL.cli.executablePath` setting. [#1252](https://github.com/github/vscode-codeql/pull/1252)
- Open the directory in the finder/explorer (instead of just highlighting it) when running the "Open query directory" command from the query history view. [#1235](https://github.com/github/vscode-codeql/pull/1235) - Open the directory in the finder/explorer (instead of just highlighting it) when running the "Open query directory" command from the query history view. [#1235](https://github.com/github/vscode-codeql/pull/1235)
- Ensure query label in the query history view changes are persisted across restarts. [#1235](https://github.com/github/vscode-codeql/pull/1235) - Ensure query label in the query history view changes are persisted across restarts. [#1235](https://github.com/github/vscode-codeql/pull/1235)
- Prints end-of-query evaluator log summaries to the Query Server Console. [#1264](https://github.com/github/vscode-codeql/pull/1264)
## 1.6.1 - 17 March 2022 ## 1.6.1 - 17 March 2022

View File

@@ -667,15 +667,18 @@ export class CodeQLCliServer implements Disposable {
/** /**
* Generate a summary of an evaluation log. * Generate a summary of an evaluation log.
* @param endSummaryPath The path to write only the end of query part of the human-readable summary to.
* @param inputPath The path of an evaluation event log. * @param inputPath The path of an evaluation event log.
* @param outputPath The path to write a human-readable summary of it to. * @param outputPath The path to write a human-readable summary of it to.
*/ */
async generateLogSummary( async generateLogSummary(
inputPath: string, inputPath: string,
outputPath: string, outputPath: string,
endSummaryPath: string,
): Promise<string> { ): Promise<string> {
const subcommandArgs = [ const subcommandArgs = [
'--format=text', '--format=text',
`--end-summary=${endSummaryPath}`,
inputPath, inputPath,
outputPath outputPath
]; ];
@@ -1279,8 +1282,14 @@ export class CliVersionConstraint {
/** /**
* CLI version that supports rotating structured logs to produce one per query. * CLI version that supports rotating structured logs to produce one per query.
*
* Note that 2.8.4 supports generating the evaluation logs and summaries,
* but 2.9.0 includes a new option to produce the end-of-query summary logs to
* the query server console. For simplicity we gate all features behind 2.9.0,
* but if a user is tied to the 2.8 release, we can enable evaluator logs
* and summaries for them.
*/ */
public static CLI_VERSION_WITH_PER_QUERY_EVAL_LOG = new SemVer('2.8.4'); public static CLI_VERSION_WITH_PER_QUERY_EVAL_LOG = new SemVer('2.9.0');
constructor(private readonly cli: CodeQLCliServer) { constructor(private readonly cli: CodeQLCliServer) {
/**/ /**/

View File

@@ -722,7 +722,7 @@ export interface StartLogResult {
} }
/** /**
* The result of terminating a structured. * The result of terminating a structured log.
*/ */
export interface EndLogResult { export interface EndLogResult {
/** /**

View File

@@ -781,6 +781,11 @@ export class QueryHistoryManager extends DisposableObject {
void showAndLogWarningMessage('No evaluator log is available for this run. Perhaps it failed before evaluation, or you are running with a version of CodeQL before ' + CliVersionConstraint.CLI_VERSION_WITH_PER_QUERY_EVAL_LOG + '?'); void showAndLogWarningMessage('No evaluator log is available for this run. Perhaps it failed before evaluation, or you are running with a version of CodeQL before ' + CliVersionConstraint.CLI_VERSION_WITH_PER_QUERY_EVAL_LOG + '?');
} }
private warnNoEvalLogSummary() {
void showAndLogWarningMessage(`No evaluator log summary is available for this run. Perhaps it failed before evaluation, or you are running with a version of CodeQL before ${CliVersionConstraint.CLI_VERSION_WITH_PER_QUERY_EVAL_LOG}?`);
}
async handleShowEvalLog( async handleShowEvalLog(
singleItem: QueryHistoryInfo, singleItem: QueryHistoryInfo,
multiSelect: QueryHistoryInfo[] multiSelect: QueryHistoryInfo[]
@@ -810,13 +815,10 @@ export class QueryHistoryManager extends DisposableObject {
return; return;
} }
if (finalSingleItem.evalLogLocation) { if (finalSingleItem.evalLogSummaryLocation) {
if (!fs.existsSync(finalSingleItem.evalLogSummaryLocation)) { await this.tryOpenExternalFile(finalSingleItem.evalLogSummaryLocation);
await this.qs.cliServer.generateLogSummary(finalSingleItem.evalLogLocation, finalSingleItem.evalLogSummaryLocation);
}
await this.tryOpenExternalFile(finalSingleItem.evalLogSummaryLocation);
} else { } else {
this.warnNoEvalLog(); this.warnNoEvalLogSummary();
} }
} }

View File

@@ -217,6 +217,7 @@ export class LocalQueryInfo {
public failureReason: string | undefined; public failureReason: string | undefined;
public completedQuery: CompletedQueryInfo | undefined; public completedQuery: CompletedQueryInfo | undefined;
public evalLogLocation: string | undefined; public evalLogLocation: string | undefined;
public evalLogSummaryLocation: string | undefined;
private config: QueryHistoryConfig | undefined; private config: QueryHistoryConfig | undefined;
/** /**
@@ -312,14 +313,6 @@ export class LocalQueryInfo {
} }
} }
/**
* Return the location of a query's evaluator log summary. This file may not exist yet,
* in which case it can be created by invoking `codeql generate log-summary`.
*/
get evalLogSummaryLocation(): string {
return this.evalLogLocation + '.summary';
}
get completed(): boolean { get completed(): boolean {
return !!this.completedQuery; return !!this.completedQuery;
} }

View File

@@ -259,6 +259,14 @@ export function findQueryLogFile(resultPath: string): string {
return path.join(resultPath, 'query.log'); return path.join(resultPath, 'query.log');
} }
export function findQueryStructLogFile(resultPath: string): string { export function findQueryEvalLogFile(resultPath: string): string {
return path.join(resultPath, 'evaluator-log.jsonl'); return path.join(resultPath, 'evaluator-log.jsonl');
} }
export function findQueryEvalLogSummaryFile(resultPath: string): string {
return path.join(resultPath, 'evaluator-log.summary');
}
export function findQueryEvalLogEndSummaryFile(resultPath: string): string {
return path.join(resultPath, 'evaluator-log-end.summary');
}

View File

@@ -95,8 +95,16 @@ export class QueryEvaluationInfo {
return qsClient.findQueryLogFile(this.querySaveDir); return qsClient.findQueryLogFile(this.querySaveDir);
} }
get structLogPath() { get evalLogPath() {
return qsClient.findQueryStructLogFile(this.querySaveDir); return qsClient.findQueryEvalLogFile(this.querySaveDir);
}
get evalLogSummaryPath() {
return qsClient.findQueryEvalLogSummaryFile(this.querySaveDir);
}
get evalLogEndSummaryPath() {
return qsClient.findQueryEvalLogEndSummaryFile(this.querySaveDir);
} }
get resultsPaths() { get resultsPaths() {
@@ -164,8 +172,9 @@ export class QueryEvaluationInfo {
if (queryInfo && await qs.cliServer.cliConstraints.supportsPerQueryEvalLog()) { if (queryInfo && await qs.cliServer.cliConstraints.supportsPerQueryEvalLog()) {
await qs.sendRequest(messages.startLog, { await qs.sendRequest(messages.startLog, {
db: dataset, db: dataset,
logPath: this.structLogPath, logPath: this.evalLogPath,
}); });
} }
const params: messages.EvaluateQueriesParams = { const params: messages.EvaluateQueriesParams = {
db: dataset, db: dataset,
@@ -186,9 +195,22 @@ export class QueryEvaluationInfo {
if (queryInfo && await qs.cliServer.cliConstraints.supportsPerQueryEvalLog()) { if (queryInfo && await qs.cliServer.cliConstraints.supportsPerQueryEvalLog()) {
await qs.sendRequest(messages.endLog, { await qs.sendRequest(messages.endLog, {
db: dataset, db: dataset,
logPath: this.structLogPath, logPath: this.evalLogPath,
}); });
queryInfo.evalLogLocation = this.structLogPath; if (await this.hasEvalLog()) {
queryInfo.evalLogLocation = this.evalLogPath;
await qs.cliServer.generateLogSummary(this.evalLogPath, this.evalLogSummaryPath, this.evalLogEndSummaryPath);
queryInfo.evalLogSummaryLocation = this.evalLogSummaryPath;
fs.readFile(this.evalLogEndSummaryPath, (err, buffer) => {
if (err) {
throw new Error(`Could not read structured evaluator log end of summary file at ${this.evalLogEndSummaryPath}.`);
}
void qs.logger.log(' --- Evaluator Log Summary --- ');
void qs.logger.log(buffer.toString());
});
} else {
void showAndLogWarningMessage(`Failed to write structured evaluator log to ${this.evalLogPath}.`);
}
} }
} }
return result || { return result || {
@@ -303,6 +325,13 @@ export class QueryEvaluationInfo {
return this.dilPath; return this.dilPath;
} }
/**
* Holds if this query already has a completed structured evaluator log
*/
async hasEvalLog(): Promise<boolean> {
return fs.pathExists(this.evalLogPath);
}
/** /**
* Creates the CSV file containing the results of this query. This will only be called if the query * Creates the CSV file containing the results of this query. This will only be called if the query
* does not have interpreted results and the CSV file does not already exist. * does not have interpreted results and the CSV file does not already exist.