Send new per-query alert count event reports for QA telemetry (#1741)
This commit is contained in:
parent
cff3d9e3c9
commit
46a6823b81
19 changed files with 213 additions and 51 deletions
|
|
@ -6,7 +6,7 @@ import * as toolrunner from "@actions/exec/lib/toolrunner";
|
|||
import del from "del";
|
||||
import * as yaml from "js-yaml";
|
||||
|
||||
import { DatabaseCreationTimings } from "./actions-util";
|
||||
import { DatabaseCreationTimings, EventReport } from "./actions-util";
|
||||
import * as analysisPaths from "./analysis-paths";
|
||||
import { CodeQL, getCodeQL } from "./codeql";
|
||||
import * as configUtils from "./config-utils";
|
||||
|
|
@ -14,6 +14,7 @@ import { FeatureEnablement, Feature } from "./feature-flags";
|
|||
import { isScannedLanguage, Language } from "./languages";
|
||||
import { Logger } from "./logging";
|
||||
import { endTracingForCluster } from "./tracer-config";
|
||||
import { validateSarifFileSchema } from "./upload-lib";
|
||||
import * as util from "./util";
|
||||
|
||||
export class CodeQLAnalysisError extends Error {
|
||||
|
|
@ -78,6 +79,8 @@ export interface QueriesStatusReport {
|
|||
interpret_results_swift_duration_ms?: number;
|
||||
/** Name of language that errored during analysis (or undefined if no language failed). */
|
||||
analyze_failure_language?: string;
|
||||
/** Reports on discrete events associated with this status report. */
|
||||
event_reports?: EventReport[];
|
||||
}
|
||||
|
||||
async function setupPythonExtractor(
|
||||
|
|
@ -242,6 +245,9 @@ export async function runQueries(
|
|||
const packsWithVersion = config.packs[language] || [];
|
||||
|
||||
try {
|
||||
const sarifFile = path.join(sarifFolder, `${language}.sarif`);
|
||||
let startTimeInterpretResults: number;
|
||||
let endTimeInterpretResults: number;
|
||||
if (await util.useCodeScanningConfigInCli(codeql, features)) {
|
||||
// If we are using the code scanning config in the CLI,
|
||||
// much of the work needed to generate the query suites
|
||||
|
|
@ -257,16 +263,16 @@ export async function runQueries(
|
|||
new Date().getTime() - startTimeBuiltIn;
|
||||
|
||||
logger.startGroup(`Interpreting results for ${language}`);
|
||||
const startTimeInterpretResults = new Date().getTime();
|
||||
const sarifFile = path.join(sarifFolder, `${language}.sarif`);
|
||||
startTimeInterpretResults = new Date().getTime();
|
||||
const analysisSummary = await runInterpretResults(
|
||||
language,
|
||||
undefined,
|
||||
sarifFile,
|
||||
config.debugMode
|
||||
);
|
||||
endTimeInterpretResults = new Date().getTime();
|
||||
statusReport[`interpret_results_${language}_duration_ms`] =
|
||||
new Date().getTime() - startTimeInterpretResults;
|
||||
endTimeInterpretResults - startTimeInterpretResults;
|
||||
logger.endGroup();
|
||||
logger.info(analysisSummary);
|
||||
} else {
|
||||
|
|
@ -342,19 +348,37 @@ export async function runQueries(
|
|||
}
|
||||
logger.endGroup();
|
||||
logger.startGroup(`Interpreting results for ${language}`);
|
||||
const startTimeInterpretResults = new Date().getTime();
|
||||
const sarifFile = path.join(sarifFolder, `${language}.sarif`);
|
||||
startTimeInterpretResults = new Date().getTime();
|
||||
const analysisSummary = await runInterpretResults(
|
||||
language,
|
||||
querySuitePaths,
|
||||
sarifFile,
|
||||
config.debugMode
|
||||
);
|
||||
endTimeInterpretResults = new Date().getTime();
|
||||
statusReport[`interpret_results_${language}_duration_ms`] =
|
||||
new Date().getTime() - startTimeInterpretResults;
|
||||
endTimeInterpretResults - startTimeInterpretResults;
|
||||
logger.endGroup();
|
||||
logger.info(analysisSummary);
|
||||
}
|
||||
if (await features.getValue(Feature.QaTelemetryEnabled)) {
|
||||
const perQueryAlertCounts = getPerQueryAlertCounts(sarifFile, logger);
|
||||
|
||||
const perQueryAlertCountEventReport: EventReport = {
|
||||
event: "codeql database interpret-results",
|
||||
started_at: startTimeInterpretResults.toString(),
|
||||
completed_at: endTimeInterpretResults.toString(),
|
||||
exit_status: "success",
|
||||
language,
|
||||
properties: perQueryAlertCounts,
|
||||
};
|
||||
|
||||
if (statusReport["event_reports"] === undefined) {
|
||||
statusReport["event_reports"] = [];
|
||||
}
|
||||
statusReport["event_reports"].push(perQueryAlertCountEventReport);
|
||||
}
|
||||
|
||||
await runPrintLinesOfCode(language);
|
||||
} catch (e) {
|
||||
logger.info(String(e));
|
||||
|
|
@ -392,6 +416,34 @@ export async function runQueries(
|
|||
);
|
||||
}
|
||||
|
||||
/** Get an object with all queries and their counts parsed from a SARIF file path. */
|
||||
function getPerQueryAlertCounts(
|
||||
sarifPath: string,
|
||||
log: Logger
|
||||
): Record<string, number> {
|
||||
validateSarifFileSchema(sarifPath, log);
|
||||
const sarifObject = JSON.parse(
|
||||
fs.readFileSync(sarifPath, "utf8")
|
||||
) as util.SarifFile;
|
||||
// We do not need to compute fingerprints because we are not sending data based off of locations.
|
||||
|
||||
// Generate the query: alert count object
|
||||
const perQueryAlertCounts: Record<string, number> = {};
|
||||
|
||||
// All rules (queries), from all results, from all runs
|
||||
for (const sarifRun of sarifObject.runs) {
|
||||
if (sarifRun.results) {
|
||||
for (const result of sarifRun.results) {
|
||||
const query = result.rule?.id || result.ruleId;
|
||||
if (query) {
|
||||
perQueryAlertCounts[query] = (perQueryAlertCounts[query] || 0) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return perQueryAlertCounts;
|
||||
}
|
||||
|
||||
async function runPrintLinesOfCode(language: Language): Promise<string> {
|
||||
const databasePath = util.getCodeQLDatabasePath(config, language);
|
||||
return await codeql.databasePrintBaseline(databasePath);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue