Skip to content

Commit fc085d2

Browse files
authored
SONARPY-2457 Collect data for the Python version (#2252)
1 parent a22456e commit fc085d2

File tree

5 files changed

+58
-3
lines changed

5 files changed

+58
-3
lines changed

sonar-python-plugin/src/main/java/org/sonar/plugins/python/IPynbSensor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ private List<PythonInputFile> parseNotebooks(List<PythonInputFile> pythonFiles,
103103

104104
for (PythonInputFile inputFile : pythonFiles) {
105105
try {
106-
sensorTelemetryStorage.updateMetric(TelemetryMetricKey.NOTEBOOK_PRESENT_KEY, "1");
106+
sensorTelemetryStorage.updateMetric(TelemetryMetricKey.NOTEBOOK_PRESENT_KEY, true);
107107
var result = IpynbNotebookParser.parseNotebook(inputFile);
108108
result.ifPresent(generatedIPythonFiles::add);
109109
} catch (Exception e) {
@@ -114,7 +114,7 @@ private List<PythonInputFile> parseNotebooks(List<PythonInputFile> pythonFiles,
114114
}
115115
}
116116

117-
sensorTelemetryStorage.updateMetric(TelemetryMetricKey.NOTEBOOK_EXCEPTION_KEY, String.valueOf(numberOfExceptions));
117+
sensorTelemetryStorage.updateMetric(TelemetryMetricKey.NOTEBOOK_EXCEPTION_KEY, numberOfExceptions);
118118
return generatedIPythonFiles;
119119
}
120120

sonar-python-plugin/src/main/java/org/sonar/plugins/python/PythonSensor.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ public final class PythonSensor implements Sensor {
6868
static final String UNSET_VERSION_WARNING = "Your code is analyzed as compatible with all Python 3 versions by default." +
6969
" You can get a more precise analysis by setting the exact Python version in your configuration via the parameter \"sonar.python.version\"";
7070

71+
private final SensorTelemetryStorage sensorTelemetryStorage;
72+
7173
/**
7274
* Constructor to be used by pico if neither PythonCustomRuleRepository nor PythonIndexer are to be found and injected.
7375
*/
@@ -100,6 +102,7 @@ public PythonSensor(FileLinesContextFactory fileLinesContextFactory, CheckFactor
100102
this.indexer = indexer;
101103
this.sonarLintCache = sonarLintCache;
102104
this.analysisWarnings = analysisWarnings;
105+
this.sensorTelemetryStorage = new SensorTelemetryStorage();
103106
}
104107

105108
@Override
@@ -121,15 +124,27 @@ public void execute(SensorContext context) {
121124
if (pythonVersionParameter.length != 0){
122125
ProjectPythonVersion.setCurrentVersions(PythonVersionUtils.fromStringArray(pythonVersionParameter));
123126
}
127+
updatePythonVersionTelemetry(context, pythonVersionParameter);
124128
CacheContext cacheContext = CacheContextImpl.of(context);
125129
PythonIndexer pythonIndexer = this.indexer != null ? this.indexer : new SonarQubePythonIndexer(pythonFiles, cacheContext, context);
126130
pythonIndexer.setSonarLintCache(sonarLintCache);
127131
TypeShed.setProjectLevelSymbolTable(pythonIndexer.projectLevelSymbolTable());
128132
PythonScanner scanner = new PythonScanner(context, checks, fileLinesContextFactory, noSonarFilter, PythonParser.create(), pythonIndexer);
129133
scanner.execute(pythonFiles, context);
134+
sensorTelemetryStorage.send(context);
130135
durationReport.stop();
131136
}
132137

138+
private void updatePythonVersionTelemetry(SensorContext context, String[] pythonVersionParameter) {
139+
if (context.runtime().getProduct() == SonarProduct.SONARLINT) {
140+
return;
141+
}
142+
sensorTelemetryStorage.updateMetric(TelemetryMetricKey.PYTHON_VERSION_SET_KEY, pythonVersionParameter.length != 0);
143+
if (pythonVersionParameter.length != 0) {
144+
sensorTelemetryStorage.updateMetric(TelemetryMetricKey.PYTHON_VERSION_KEY, String.join(",", pythonVersionParameter));
145+
}
146+
}
147+
133148
private static List<PythonInputFile> getInputFiles(SensorContext context) {
134149
FilePredicates p = context.fileSystem().predicates();
135150
Iterable<InputFile> it = context.fileSystem().inputFiles(p.and(p.hasLanguage(Python.KEY)));

sonar-python-plugin/src/main/java/org/sonar/plugins/python/SensorTelemetryStorage.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,12 @@ public void updateMetric(TelemetryMetricKey key, int value) {
5555
data.put(key, String.valueOf(value));
5656
}
5757

58+
public void updateMetric(TelemetryMetricKey key, boolean value) {
59+
data.put(key, boolToString(value));
60+
}
61+
62+
private static String boolToString(boolean value) {
63+
return value ? "1" : "0";
64+
}
65+
5866
}

sonar-python-plugin/src/main/java/org/sonar/plugins/python/TelemetryMetricKey.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ public enum TelemetryMetricKey {
2020
NOTEBOOK_PRESENT_KEY("python.notebook.present"),
2121
NOTEBOOK_TOTAL_KEY("python.notebook.total"),
2222
NOTEBOOK_RECOGNITION_ERROR_KEY("python.notebook.recognition_error"),
23-
NOTEBOOK_EXCEPTION_KEY("python.notebook.exceptions");
23+
NOTEBOOK_EXCEPTION_KEY("python.notebook.exceptions"),
24+
PYTHON_VERSION_SET_KEY("python.version.set"),
25+
PYTHON_VERSION_KEY("python.version");
2426

2527
private final String key;
2628

sonar-python-plugin/src/test/java/org/sonar/plugins/python/PythonSensorTest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,6 +1408,36 @@ void test_scanner_isNotebook() {
14081408
assertThat(PythonScanner.isNotebook(notebookPythonFile)).isTrue();
14091409
}
14101410

1411+
@Test
1412+
void send_telemetry_with_version() {
1413+
activeRules = new ActiveRulesBuilder()
1414+
.addRule(new NewActiveRule.Builder()
1415+
.setRuleKey(RuleKey.of(CheckList.REPOSITORY_KEY, "S930"))
1416+
.build())
1417+
.build();
1418+
1419+
context.setSettings(new MapSettings().setProperty("sonar.python.version", "3.10,3.13"));
1420+
var contextSpy = spy(context);
1421+
PythonSensor sensor = sensor();
1422+
sensor.execute(contextSpy);
1423+
verify(contextSpy, times(1)).addTelemetryProperty(TelemetryMetricKey.PYTHON_VERSION_KEY.key(), "3.10,3.13");
1424+
verify(contextSpy, times(1)).addTelemetryProperty(TelemetryMetricKey.PYTHON_VERSION_SET_KEY.key(), "1");
1425+
}
1426+
1427+
@Test
1428+
void send_telemetry_no_version() {
1429+
activeRules = new ActiveRulesBuilder()
1430+
.addRule(new NewActiveRule.Builder()
1431+
.setRuleKey(RuleKey.of(CheckList.REPOSITORY_KEY, "S930"))
1432+
.build())
1433+
.build();
1434+
1435+
PythonSensor sensor = sensor();
1436+
var contextSpy = spy(context);
1437+
sensor.execute(contextSpy);
1438+
verify(contextSpy, times(1)).addTelemetryProperty(TelemetryMetricKey.PYTHON_VERSION_SET_KEY.key(), "0");
1439+
}
1440+
14111441
private com.sonar.sslr.api.Token passToken(URI uri) {
14121442
return com.sonar.sslr.api.Token.builder()
14131443
.setType(PythonKeyword.PASS)

0 commit comments

Comments
 (0)