-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #18697 from hvitved/rust/telemetry
Rust: Implement database quality telemetry query
- Loading branch information
Showing
6 changed files
with
185 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/** | ||
* Provides database quality statistics that are reported by | ||
* `rust/telemetry/extractor-information` | ||
* and perhaps warned about by `rust/diagnostics/database-quality`. | ||
*/ | ||
|
||
import rust | ||
import codeql.util.ReportStats | ||
|
||
module CallTargetStats implements StatsSig { | ||
int getNumberOfOk() { result = count(CallExprBase c | exists(c.getStaticTarget())) } | ||
|
||
private predicate isLambdaCall(CallExpr call) { | ||
exists(Expr receiver | receiver = call.getFunction() | | ||
// All calls to complex expressions and local variable accesses are lambda calls | ||
receiver instanceof PathExpr implies receiver = any(Variable v).getAnAccess() | ||
) | ||
} | ||
|
||
additional predicate isNotOkCall(CallExprBase c) { | ||
not exists(c.getStaticTarget()) and | ||
not isLambdaCall(c) | ||
} | ||
|
||
int getNumberOfNotOk() { result = count(CallExprBase c | isNotOkCall(c)) } | ||
|
||
string getOkText() { result = "calls with call target" } | ||
|
||
string getNotOkText() { result = "calls with missing call target" } | ||
} | ||
|
||
module MacroCallTargetStats implements StatsSig { | ||
int getNumberOfOk() { result = count(MacroCall c | c.hasExpanded()) } | ||
|
||
additional predicate isNotOkCall(MacroCall c) { not c.hasExpanded() } | ||
|
||
int getNumberOfNotOk() { result = count(MacroCall c | isNotOkCall(c)) } | ||
|
||
string getOkText() { result = "macro calls with call target" } | ||
|
||
string getNotOkText() { result = "macro calls with missing call target" } | ||
} | ||
|
||
module CallTargetStatsReport = ReportStats<CallTargetStats>; | ||
|
||
module MacroCallTargetStatsReport = ReportStats<MacroCallTargetStats>; |
41 changes: 41 additions & 0 deletions
41
rust/ql/src/queries/telemetry/DatabaseQualityDiagnostics.ql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/** | ||
* @name Low Rust analysis quality | ||
* @description Low Rust analysis quality | ||
* @kind diagnostic | ||
* @id rust/diagnostic/database-quality | ||
*/ | ||
|
||
import rust | ||
import DatabaseQuality | ||
import codeql.util.Unit | ||
|
||
class DbQualityDiagnostic extends Unit { | ||
DbQualityDiagnostic() { | ||
exists(float percentageGood | | ||
CallTargetStatsReport::percentageOfOk(_, percentageGood) | ||
or | ||
MacroCallTargetStatsReport::percentageOfOk(_, percentageGood) | ||
| | ||
percentageGood < 95 | ||
) | ||
} | ||
|
||
string toString() { | ||
result = | ||
"Scanning Rust code completed successfully, but the scan encountered issues. " + | ||
"This may be caused by problems identifying dependencies or use of generated source code, among other reasons -- " | ||
+ | ||
"see other CodeQL diagnostics reported on the CodeQL status page for more details of possible causes. " | ||
+ "Addressing these warnings is advisable to avoid false-positive or missing results." | ||
} | ||
} | ||
|
||
query predicate diagnosticAttributes(DbQualityDiagnostic e, string key, string value) { | ||
exists(e) and // Quieten warning about unconstrained 'e' | ||
key = ["visibilityCliSummaryTable", "visibilityTelemetry", "visibilityStatusPage"] and | ||
value = "true" | ||
} | ||
|
||
from DbQualityDiagnostic d | ||
select d, d.toString(), 1 | ||
/* 1 = Warning severity */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/** | ||
* @name Rust extraction information | ||
* @description Information about the extraction for a Rust database | ||
* @kind metric | ||
* @tags summary telemetry | ||
* @id rust/telemetry/extraction-information | ||
*/ | ||
|
||
import rust | ||
import DatabaseQuality | ||
import codeql.rust.Diagnostics | ||
|
||
predicate fileCount(string key, int value) { | ||
key = "Number of files" and | ||
value = strictcount(File f) | ||
} | ||
|
||
predicate fileCountByExtension(string key, int value) { | ||
exists(string extension | | ||
key = "Number of files with extension " + extension and | ||
value = strictcount(File f | f.getExtension() = extension) | ||
) | ||
} | ||
|
||
predicate numberOfLinesOfCode(string key, int value) { | ||
key = "Number of lines of code" and | ||
value = strictsum(File f | any() | f.getNumberOfLinesOfCode()) | ||
} | ||
|
||
predicate numberOfLinesOfCodeByExtension(string key, int value) { | ||
exists(string extension | | ||
key = "Number of lines of code with extension " + extension and | ||
value = strictsum(File f | f.getExtension() = extension | f.getNumberOfLinesOfCode()) | ||
) | ||
} | ||
|
||
predicate extractorDiagnostics(string key, int value) { | ||
exists(int severity | | ||
key = "Number of diagnostics with severity " + severity.toString() and | ||
value = strictcount(Diagnostic d | d.getSeverity() = severity) | ||
) | ||
} | ||
|
||
from string key, float value | ||
where | ||
( | ||
fileCount(key, value) or | ||
fileCountByExtension(key, value) or | ||
numberOfLinesOfCode(key, value) or | ||
numberOfLinesOfCodeByExtension(key, value) or | ||
extractorDiagnostics(key, value) or | ||
CallTargetStatsReport::numberOfOk(key, value) or | ||
CallTargetStatsReport::numberOfNotOk(key, value) or | ||
CallTargetStatsReport::percentageOfOk(key, value) or | ||
MacroCallTargetStatsReport::numberOfOk(key, value) or | ||
MacroCallTargetStatsReport::numberOfNotOk(key, value) or | ||
MacroCallTargetStatsReport::percentageOfOk(key, value) | ||
) and | ||
/* Infinity */ | ||
value != 1.0 / 0.0 and | ||
/* -Infinity */ | ||
value != -1.0 / 0.0 and | ||
/* NaN */ | ||
value != 0.0 / 0.0 | ||
select key, value |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/** | ||
* Provides the `ReportStats` module for reporting database quality statistics. | ||
*/ | ||
module; | ||
|
||
signature module StatsSig { | ||
int getNumberOfOk(); | ||
|
||
int getNumberOfNotOk(); | ||
|
||
string getOkText(); | ||
|
||
string getNotOkText(); | ||
} | ||
|
||
module ReportStats<StatsSig Stats> { | ||
predicate numberOfOk(string key, int value) { | ||
value = Stats::getNumberOfOk() and | ||
key = "Number of " + Stats::getOkText() | ||
} | ||
|
||
predicate numberOfNotOk(string key, int value) { | ||
value = Stats::getNumberOfNotOk() and | ||
key = "Number of " + Stats::getNotOkText() | ||
} | ||
|
||
predicate percentageOfOk(string key, float value) { | ||
value = Stats::getNumberOfOk() * 100.0 / (Stats::getNumberOfOk() + Stats::getNumberOfNotOk()) and | ||
key = "Percentage of " + Stats::getOkText() | ||
} | ||
} |