Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1a68845

Browse filesBrowse files
authored
Merge pull request #17892 from github/calumgrant/telemetry
C++: Initial telemetry queries
2 parents 349518b + 91b1cb8 commit 1a68845
Copy full SHA for 1a68845

26 files changed

+471
-0
lines changed
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* @name Compiler errors
3+
* @description A count of all compiler errors, grouped by error text.
4+
* @kind metric
5+
* @tags summary telemetry
6+
* @id cpp/telemetry/compiler-errors
7+
*/
8+
9+
import Metrics
10+
11+
from CppMetrics::ErrorCount m
12+
where RankMetric<CppMetrics::ErrorCount>::getRank(m) <= 50
13+
select m.toString(), m.getValue()
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* @name Database quality
3+
* @description Metrics that indicate the quality of the database.
4+
* @kind metric
5+
* @tags summary telemetry
6+
* @id cpp/telemetry/database-quality
7+
*/
8+
9+
import Metrics
10+
11+
from QualityMetric m
12+
select m.toString(), m.getValue()

‎cpp/ql/src/Telemetry/Diagnostics.qll

Copy file name to clipboard
+29Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import cpp
2+
3+
/**
4+
* A syntax error.
5+
*/
6+
class SyntaxError extends CompilerError {
7+
SyntaxError() {
8+
this.getTag().matches("exp_%") or
9+
this.getTag() =
10+
[
11+
"bad_data_member_initialization", "bad_pure_specifier", "bad_return", "bad_uuid_string",
12+
"literal_without_initializer", "missing_class_definition", "missing_exception_declaration",
13+
"nonstd_const_member_decl_not_allowed", "operator_name_not_allowed",
14+
"wide_string_invalid_in_asm"
15+
]
16+
}
17+
}
18+
19+
/**
20+
* A cannot open file error.
21+
* Typically this is due to a missing include.
22+
*/
23+
class CannotOpenFileError extends CompilerError {
24+
CannotOpenFileError() { this.hasTag(["cannot_open_file", "cannot_open_file_reason"]) }
25+
26+
string getIncludedFile() {
27+
result = this.getMessage().regexpCapture("cannot open source file '([^']+)'", 1)
28+
}
29+
}
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* @name Extraction metrics
3+
* @description Raw metrics relating to extraction.
4+
* @kind metric
5+
* @tags summary telemetry
6+
* @id cpp/telemetry/extraction-metrics
7+
*/
8+
9+
import Metrics
10+
11+
from ExtractionMetric m
12+
select m.toString(), m.getValue()

‎cpp/ql/src/Telemetry/Metrics.qll

Copy file name to clipboard
+269Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
import cpp
2+
import Diagnostics
3+
4+
/**
5+
* A metric is a string with a value.
6+
*/
7+
abstract class Metric extends string {
8+
bindingset[this]
9+
Metric() { any() }
10+
}
11+
12+
/**
13+
* A metric that we want to report in cpp/telemetry/extraction-metrics
14+
*/
15+
abstract class ExtractionMetric extends Metric {
16+
bindingset[this]
17+
ExtractionMetric() { any() }
18+
19+
/** Gets the value of this metric. */
20+
abstract int getValue();
21+
}
22+
23+
/**
24+
* A metric that provides a baseline for a SuccessMetric.
25+
*/
26+
abstract class BaseMetric extends ExtractionMetric {
27+
bindingset[this]
28+
BaseMetric() { any() }
29+
}
30+
31+
/**
32+
* A metric that is relative to another metric,
33+
* so can be used to calculate percentages.
34+
*
35+
* For clarity, metrics should express success,
36+
* so higher values means better.
37+
*/
38+
abstract class SuccessMetric extends ExtractionMetric {
39+
bindingset[this]
40+
SuccessMetric() { any() }
41+
42+
/** Gets the metric this is relative to. */
43+
abstract BaseMetric getBaseline();
44+
}
45+
46+
/**
47+
* A metric used to report database quality.
48+
*/
49+
class QualityMetric extends Metric {
50+
BaseMetric baseMetric;
51+
SuccessMetric relativeMetric;
52+
53+
QualityMetric() {
54+
baseMetric = relativeMetric.getBaseline() and this = "Percentage of " + relativeMetric
55+
}
56+
57+
float getValue() {
58+
baseMetric.getValue() > 0 and
59+
result = 100.0 * relativeMetric.getValue() / baseMetric.getValue()
60+
}
61+
}
62+
63+
signature class RankedMetric extends Metric {
64+
int getValue();
65+
}
66+
67+
module RankMetric<RankedMetric M> {
68+
int getRank(M s) { s = rank[result](M m | | m order by m.getValue() desc) }
69+
}
70+
71+
/** Various metrics we want to report. */
72+
module CppMetrics {
73+
class Compilations extends BaseMetric {
74+
Compilations() { this = "compilations" }
75+
76+
override int getValue() { result = count(Compilation c) }
77+
}
78+
79+
class SourceAndHeaderFiles extends BaseMetric {
80+
SourceAndHeaderFiles() { this = "source/header files" }
81+
82+
override int getValue() { result = count(File f | f.fromSource()) }
83+
}
84+
85+
class SourceAndHeaderFilesWithoutErrors extends SuccessMetric {
86+
SourceAndHeaderFilesWithoutErrors() { this = "source/header files without errors" }
87+
88+
override int getValue() {
89+
result = count(File f | f.fromSource() and not exists(CompilerError e | f = e.getFile()))
90+
}
91+
92+
override SourceAndHeaderFiles getBaseline() { any() }
93+
}
94+
95+
class CompilationsWithoutErrors extends SuccessMetric {
96+
CompilationsWithoutErrors() { this = "compilations without errors" }
97+
98+
override int getValue() {
99+
result = count(Compilation c | not exists(Diagnostic d | d.getFile() = c.getAFileCompiled()))
100+
}
101+
102+
override Compilations getBaseline() { any() }
103+
}
104+
105+
class Expressions extends BaseMetric {
106+
Expressions() { this = "expressions" }
107+
108+
override int getValue() { result = count(Expr e) }
109+
}
110+
111+
class SucceededExpressions extends SuccessMetric {
112+
SucceededExpressions() { this = "non-error expressions" }
113+
114+
override int getValue() { result = count(Expr e) - count(ErrorExpr e) }
115+
116+
override Expressions getBaseline() { any() }
117+
}
118+
119+
class TypedExpressions extends SuccessMetric {
120+
TypedExpressions() { this = "expressions with a known type" }
121+
122+
override int getValue() { result = count(Expr e | not e.getType() instanceof ErroneousType) }
123+
124+
override Expressions getBaseline() { any() }
125+
}
126+
127+
class Calls extends BaseMetric {
128+
Calls() { this = "calls" }
129+
130+
override int getValue() { result = count(Call c) }
131+
}
132+
133+
class CallsWithExplicitTarget extends SuccessMetric {
134+
CallsWithExplicitTarget() { this = "calls with an explicit target" }
135+
136+
override int getValue() {
137+
result = count(Call c | not c.getTarget().getADeclarationEntry().isImplicit())
138+
}
139+
140+
override Calls getBaseline() { any() }
141+
}
142+
143+
class Variables extends BaseMetric {
144+
Variables() { this = "variables" }
145+
146+
override int getValue() { result = count(Variable v) }
147+
}
148+
149+
class VariablesKnownType extends SuccessMetric {
150+
VariablesKnownType() { this = "variables with a known type" }
151+
152+
override int getValue() {
153+
result = count(Variable v | not v.getType() instanceof ErroneousType)
154+
}
155+
156+
override Variables getBaseline() { any() }
157+
}
158+
159+
class LinesOfText extends BaseMetric {
160+
LinesOfText() { this = "lines of text" }
161+
162+
override int getValue() { result = sum(File f | | f.getMetrics().getNumberOfLines()) }
163+
}
164+
165+
class LinesOfCode extends BaseMetric {
166+
LinesOfCode() { this = "lines of code" }
167+
168+
override int getValue() { result = sum(File f | | f.getMetrics().getNumberOfLinesOfCode()) }
169+
}
170+
171+
private predicate errorLine(File file, int line) {
172+
exists(Locatable l, Location loc |
173+
loc = l.getLocation() and
174+
loc.getFile() = file and
175+
line in [loc.getStartLine() .. loc.getEndLine()]
176+
|
177+
l instanceof Diagnostic
178+
or
179+
l instanceof ErrorExpr
180+
)
181+
}
182+
183+
class SucceededLines extends SuccessMetric {
184+
SucceededLines() { this = "lines of code without errors" }
185+
186+
override int getValue() {
187+
result =
188+
sum(File f | | f.getMetrics().getNumberOfLinesOfCode()) -
189+
count(File f, int line | errorLine(f, line))
190+
}
191+
192+
override LinesOfCode getBaseline() { any() }
193+
}
194+
195+
class Functions extends BaseMetric {
196+
Functions() { this = "functions" }
197+
198+
override int getValue() { result = count(Function f) }
199+
}
200+
201+
class SucceededFunctions extends SuccessMetric {
202+
SucceededFunctions() { this = "functions without errors" }
203+
204+
override int getValue() { result = count(Function f | not f.hasErrors()) }
205+
206+
override Functions getBaseline() { any() }
207+
}
208+
209+
class Includes extends BaseMetric {
210+
Includes() { this = "#include directives" }
211+
212+
override int getValue() { result = count(Include i) + count(CannotOpenFileError e) }
213+
}
214+
215+
class SucceededIncludes extends SuccessMetric {
216+
SucceededIncludes() { this = "successfully resolved #include directives" }
217+
218+
override int getValue() { result = count(Include i) }
219+
220+
override Includes getBaseline() { any() }
221+
}
222+
223+
class SucceededIncludeCount extends Metric {
224+
string includeText;
225+
226+
SucceededIncludeCount() {
227+
exists(Include i |
228+
i.getIncludeText() = includeText and
229+
exists(i.getFile().getRelativePath()) // Only report includes from the repo
230+
) and
231+
this = "Successfully included " + includeText
232+
}
233+
234+
int getValue() { result = count(Include i | i.getIncludeText() = includeText) }
235+
236+
string getIncludeText() { result = includeText }
237+
}
238+
239+
class MissingIncludeCount extends Metric {
240+
string includeText;
241+
242+
MissingIncludeCount() {
243+
exists(CannotOpenFileError e | e.getIncludedFile() = includeText) and
244+
this = "Failed to include '" + includeText + "'"
245+
}
246+
247+
int getValue() { result = count(CannotOpenFileError e | e.getIncludedFile() = includeText) }
248+
249+
string getIncludeText() { result = includeText }
250+
}
251+
252+
class CompilerErrors extends ExtractionMetric {
253+
CompilerErrors() { this = "compiler errors" }
254+
255+
override int getValue() { result = count(CompilerError e) }
256+
}
257+
258+
class ErrorCount extends Metric {
259+
ErrorCount() { exists(CompilerError e | e.getMessage() = this) }
260+
261+
int getValue() { result = count(CompilerError e | e.getMessage() = this) }
262+
}
263+
264+
class SyntaxErrorCount extends ExtractionMetric {
265+
SyntaxErrorCount() { this = "syntax errors" }
266+
267+
override int getValue() { result = count(SyntaxError e) }
268+
}
269+
}
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* @name Failed to include header file
3+
* @description A count of all failed includes, grouped by filename.
4+
* @kind metric
5+
* @tags summary telemetry
6+
* @id cpp/telemetry/failed-includes
7+
*/
8+
9+
import Metrics
10+
11+
from CppMetrics::MissingIncludeCount e
12+
where RankMetric<CppMetrics::MissingIncludeCount>::getRank(e) <= 50
13+
select e.getIncludeText(), e.getValue()
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* @name Successfully included header files
3+
* @description A count of all succeeded includes, grouped by filename.
4+
* @kind metric
5+
* @tags summary telemetry
6+
* @id cpp/telemetry/succeeded-includes
7+
*/
8+
9+
import Metrics
10+
11+
from CppMetrics::SucceededIncludeCount m
12+
where RankMetric<CppMetrics::SucceededIncludeCount>::getRank(m) <= 50
13+
select m.getIncludeText(), m.getValue()
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
| 'this' may only be used inside a nonstatic member function | 1 |
2+
| There was an error during this compilation | 1 |
3+
| expected a ')' | 1 |
4+
| expected a ';' | 1 |
5+
| expected an expression | 1 |
6+
| identifier 'no_such_function' is undefined | 1 |
7+
| identifier 'nsf2' is undefined | 1 |
8+
| identifier 'so_is_this' is undefined | 1 |
9+
| identifier 'uint32_t' is undefined | 1 |
10+
| too few arguments in function call | 1 |
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Telemetry/CompilerErrors.ql
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
| Percentage of calls with an explicit target | 50.0 |
2+
| Percentage of compilations without errors | 50.0 |
3+
| Percentage of expressions with a known type | 30.0 |
4+
| Percentage of functions without errors | 75.0 |
5+
| Percentage of lines of code without errors | 63.1578947368421 |
6+
| Percentage of non-error expressions | 30.0 |
7+
| Percentage of source/header files without errors | 66.66666666666667 |
8+
| Percentage of successfully resolved #include directives | 100.0 |
9+
| Percentage of variables with a known type | 90.0 |
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Telemetry/DatabaseQuality.ql

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.