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)
- 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)
- 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

View File

@@ -667,15 +667,18 @@ export class CodeQLCliServer implements Disposable {
/**
* 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 outputPath The path to write a human-readable summary of it to.
*/
async generateLogSummary(
inputPath: string,
outputPath: string,
endSummaryPath: string,
): Promise<string> {
const subcommandArgs = [
'--format=text',
`--end-summary=${endSummaryPath}`,
inputPath,
outputPath
];
@@ -1279,8 +1282,14 @@ export class CliVersionConstraint {
/**
* 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) {
/**/

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 {
/**

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 + '?');
}
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(
singleItem: QueryHistoryInfo,
multiSelect: QueryHistoryInfo[]
@@ -810,13 +815,10 @@ export class QueryHistoryManager extends DisposableObject {
return;
}
if (finalSingleItem.evalLogLocation) {
if (!fs.existsSync(finalSingleItem.evalLogSummaryLocation)) {
await this.qs.cliServer.generateLogSummary(finalSingleItem.evalLogLocation, finalSingleItem.evalLogSummaryLocation);
}
await this.tryOpenExternalFile(finalSingleItem.evalLogSummaryLocation);
if (finalSingleItem.evalLogSummaryLocation) {
await this.tryOpenExternalFile(finalSingleItem.evalLogSummaryLocation);
} else {
this.warnNoEvalLog();
this.warnNoEvalLogSummary();
}
}

View File

@@ -217,6 +217,7 @@ export class LocalQueryInfo {
public failureReason: string | undefined;
public completedQuery: CompletedQueryInfo | undefined;
public evalLogLocation: string | undefined;
public evalLogSummaryLocation: string | 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 {
return !!this.completedQuery;
}

View File

@@ -259,6 +259,14 @@ export function findQueryLogFile(resultPath: string): string {
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');
}
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);
}
get structLogPath() {
return qsClient.findQueryStructLogFile(this.querySaveDir);
get evalLogPath() {
return qsClient.findQueryEvalLogFile(this.querySaveDir);
}
get evalLogSummaryPath() {
return qsClient.findQueryEvalLogSummaryFile(this.querySaveDir);
}
get evalLogEndSummaryPath() {
return qsClient.findQueryEvalLogEndSummaryFile(this.querySaveDir);
}
get resultsPaths() {
@@ -164,8 +172,9 @@ export class QueryEvaluationInfo {
if (queryInfo && await qs.cliServer.cliConstraints.supportsPerQueryEvalLog()) {
await qs.sendRequest(messages.startLog, {
db: dataset,
logPath: this.structLogPath,
logPath: this.evalLogPath,
});
}
const params: messages.EvaluateQueriesParams = {
db: dataset,
@@ -186,9 +195,22 @@ export class QueryEvaluationInfo {
if (queryInfo && await qs.cliServer.cliConstraints.supportsPerQueryEvalLog()) {
await qs.sendRequest(messages.endLog, {
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 || {
@@ -303,6 +325,13 @@ export class QueryEvaluationInfo {
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
* does not have interpreted results and the CSV file does not already exist.