From ac225734806c2f106fac014973e1f70cdeb94d37 Mon Sep 17 00:00:00 2001 From: Michal Zgliczynski Date: Mon, 16 Dec 2024 11:24:28 +0100 Subject: [PATCH 1/6] Add runtime telemetry --- .../javascript/bridge/BridgeServer.java | 7 ++- .../javascript/bridge/BridgeServerImpl.java | 11 +++-- .../javascript/nodejs/NodeCommand.java | 11 ++++- .../nodejs/NodeCommandBuilderImpl.java | 9 +++- .../javascript/nodejs/NodeVersion.java | 3 +- .../bridge/BridgeServerImplTest.java | 4 +- .../javascript/nodejs/NodeCommandTest.java | 12 ++++- .../analysis/AnalysisWithProgram.java | 3 +- .../javascript/analysis/PluginTelemetry.java | 44 +++++++++++++---- .../JavaScriptEslintBasedSensorTest.java | 5 +- .../analysis/PluginTelemetryTest.java | 49 ++++++++++++++++--- 11 files changed, 123 insertions(+), 35 deletions(-) diff --git a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java index 52b7d28720e..5133afdca1c 100644 --- a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java +++ b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java @@ -26,6 +26,7 @@ import org.sonar.api.batch.fs.TextRange; import org.sonar.api.scanner.ScannerSide; import org.sonar.plugins.javascript.bridge.protobuf.Node; +import org.sonar.plugins.javascript.nodejs.NodeCommand; import org.sonarsource.api.sonarlint.SonarLintSide; @ScannerSide @@ -68,7 +69,9 @@ void initLinter( TsConfigFile createTsConfigFile(String content) throws IOException; - TelemetryResponse getTelemetry(); + TelemetryNodeResponse getTelemetry(); + + NodeCommand command(); record JsAnalysisRequest( String filePath, @@ -278,7 +281,7 @@ public String toString() { record TsProgramRequest(String tsConfig) {} - record TelemetryResponse(List dependencies) {} + record TelemetryNodeResponse(List dependencies) {} record Dependency(String name, String version) {} } diff --git a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java index 6ea90a4fe9d..3182e319b42 100644 --- a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java +++ b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java @@ -534,15 +534,20 @@ public TsConfigFile createTsConfigFile(String content) { } @Override - public TelemetryResponse getTelemetry() { + public TelemetryNodeResponse getTelemetry() { try { var result = http.get(url("get-telemetry")); - return GSON.fromJson(result, TelemetryResponse.class); + return GSON.fromJson(result, TelemetryNodeResponse.class); } catch (IOException e) { - return new TelemetryResponse(List.of()); + return new TelemetryNodeResponse(List.of()); } } + @Override + public NodeCommand command() { + return nodeCommand; + } + private static List emptyListIfNull(@Nullable List list) { return list == null ? emptyList() : list; } diff --git a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeCommand.java b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeCommand.java index 77fe20a1fdc..48b784c14f8 100644 --- a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeCommand.java +++ b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeCommand.java @@ -48,8 +48,9 @@ public class NodeCommand { private final Map env; private Process process; private final List command; + private final String nodeExecutableOrigin; - NodeCommand( + public NodeCommand( ProcessWrapper processWrapper, String nodeExecutable, Version actualNodeVersion, @@ -58,7 +59,8 @@ public class NodeCommand { List args, Consumer outputConsumer, Consumer errorConsumer, - Map env + Map env, + String nodeExecutableOrigin ) { this.processWrapper = processWrapper; this.command = buildCommand(nodeExecutable, nodeJsArgs, scriptFilename, args); @@ -66,6 +68,7 @@ public class NodeCommand { this.outputConsumer = outputConsumer; this.errorConsumer = errorConsumer; this.env = env; + this.nodeExecutableOrigin = nodeExecutableOrigin; } /** @@ -132,4 +135,8 @@ public String toString() { public Version getActualNodeVersion() { return actualNodeVersion; } + + public String getNodeExecutableOrigin() { + return nodeExecutableOrigin; + } } diff --git a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeCommandBuilderImpl.java b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeCommandBuilderImpl.java index fbfcd315d57..2d6f14f90a4 100644 --- a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeCommandBuilderImpl.java +++ b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeCommandBuilderImpl.java @@ -64,6 +64,7 @@ public class NodeCommandBuilderImpl implements NodeCommandBuilder { private BundlePathResolver pathResolver; private Version actualNodeVersion; private Map env = Map.of(); + private String nodeExecutableOrigin = "none"; public NodeCommandBuilderImpl(ProcessWrapper processWrapper) { this.processWrapper = processWrapper; @@ -164,7 +165,8 @@ public NodeCommand build() throws NodeCommandException, IOException { args, outputConsumer, errorConsumer, - env + env, + nodeExecutableOrigin ); } @@ -219,6 +221,7 @@ static Version nodeVersion(String versionString) throws NodeCommandException { private String retrieveNodeExecutable(Configuration configuration) throws NodeCommandException, IOException { if (configuration.hasKey(NODE_EXECUTABLE_PROPERTY)) { + nodeExecutableOrigin = NODE_EXECUTABLE_PROPERTY; String nodeExecutable = configuration.get(NODE_EXECUTABLE_PROPERTY).get(); File file = new File(nodeExecutable); if (file.exists()) { @@ -246,14 +249,18 @@ private String locateNode(boolean isForceHost) throws IOException { if (embeddedNode.isAvailable() && !isForceHost) { LOG.info("Using embedded Node.js runtime."); defaultNode = embeddedNode.binary().toString(); + nodeExecutableOrigin = "embedded"; } else if (processWrapper.isMac()) { defaultNode = locateNodeOnMac(); + nodeExecutableOrigin = "host"; } else if (processWrapper.isWindows()) { defaultNode = locateNodeOnWindows(); + nodeExecutableOrigin = "host"; } if (isForceHost) { LOG.info("Forcing to use Node.js from the host."); + nodeExecutableOrigin = "force-host"; } LOG.info("Using Node.js executable: '{}'.", defaultNode); diff --git a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeVersion.java b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeVersion.java index 71398619ca4..e7ad37ea564 100644 --- a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeVersion.java +++ b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeVersion.java @@ -48,7 +48,8 @@ public static String getVersion(ProcessWrapper processWrapper, String nodeExecut Map.of( "RUN_NODE_ERROR_MSG", "Couldn't find the Node.js binary. Ensure you have Node.js installed." - ) + ), + "host" ); nodeCommand.start(); int exitValue = nodeCommand.waitFor(); diff --git a/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java b/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java index a56439ab100..1dd4407b6b8 100644 --- a/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java +++ b/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java @@ -64,7 +64,7 @@ import org.sonar.plugins.javascript.bridge.BridgeServer.CssAnalysisRequest; import org.sonar.plugins.javascript.bridge.BridgeServer.Dependency; import org.sonar.plugins.javascript.bridge.BridgeServer.JsAnalysisRequest; -import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryResponse; +import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryNodeResponse; import org.sonar.plugins.javascript.bridge.BridgeServer.TsProgram; import org.sonar.plugins.javascript.bridge.BridgeServer.TsProgramRequest; import org.sonar.plugins.javascript.bridge.protobuf.Node; @@ -760,7 +760,7 @@ void should_return_telemetry() throws Exception { bridgeServer.startServer(serverConfig, emptyList()); var telemetry = bridgeServer.getTelemetry(); assertThat(telemetry).isEqualTo( - new TelemetryResponse(List.of(new Dependency("pkg1", "1.0.0"))) + new TelemetryNodeResponse(List.of(new Dependency("pkg1", "1.0.0"))) ); } diff --git a/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/nodejs/NodeCommandTest.java b/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/nodejs/NodeCommandTest.java index 5eab923b69a..fd40d1d4627 100644 --- a/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/nodejs/NodeCommandTest.java +++ b/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/nodejs/NodeCommandTest.java @@ -189,6 +189,7 @@ void test_executable_from_configuration() throws Exception { List value = captureProcessWrapperArgument(); assertThat(value).contains(nodeExecutable.toString()); + assertThat(nodeCommand.getNodeExecutableOrigin()).isEqualTo(NODE_EXECUTABLE_PROPERTY); await() .until(() -> logTester @@ -213,6 +214,7 @@ void test_empty_configuration() throws Exception { List value = captureProcessWrapperArgument(); assertThat(value).contains("node"); + assertThat(nodeCommand.getNodeExecutableOrigin()).isEqualTo("none"); } private List captureProcessWrapperArgument() throws IOException { @@ -335,6 +337,7 @@ void test_command_on_mac() throws Exception { .pathResolver(getPathResolver()) .build(); nodeCommand.start(); + assertThat(nodeCommand.getNodeExecutableOrigin()).isEqualTo("host"); List value = captureProcessWrapperArgument(); assertThat(value).hasSize(2); assertThat(value.get(0)).endsWith("src/test/resources/package/bin/run-node"); @@ -366,7 +369,8 @@ void test_actual_node_version() throws Exception { Collections.emptyList(), noop, noop, - Map.of() + Map.of(), + "host" ); assertThat(nodeCommand.getActualNodeVersion().major()).isEqualTo(12); } @@ -390,6 +394,7 @@ void test_windows_default_node() throws Exception { "C:\\Program Files\\node.exe", "script.js" ); + assertThat(nodeCommand.getNodeExecutableOrigin()).isEqualTo("host"); } @Test @@ -420,6 +425,7 @@ void test_embedded_runtime() throws Exception { // For some reason, using mockProcessWrapper to test for the used command does not yield the expected result var expectedCommand = Paths.get(en.binary().toString()) + " " + PATH_TO_SCRIPT; assertThat(nodeCommand.toString()).isEqualTo(expectedCommand); + assertThat(nodeCommand.getNodeExecutableOrigin()).isEqualTo("embedded"); } @Test @@ -443,6 +449,7 @@ void test_embedded_runtime_with_forceHost_for_macos() throws Exception { .build(); var commandParts = nodeCommand.toString().split(" "); assertThat(commandParts[0]).endsWith("src/test/resources/package/bin/run-node"); + assertThat(nodeCommand.getNodeExecutableOrigin()).isEqualTo("force-host"); } @Test @@ -451,7 +458,7 @@ void test_skipping_nodejs_provisioning_property() throws Exception { var settings = new MapSettings(); settings.setProperty(skipNodePropvisioning, true); - builder() + var nodeCommand = builder() .configuration(settings.asConfig()) .script("script.js") .pathResolver(getPathResolver()) @@ -460,6 +467,7 @@ void test_skipping_nodejs_provisioning_property() throws Exception { assertThat(logTester.logs(Level.INFO)) .doesNotContain("Using embedded Node.js runtime") .contains("Forcing to use Node.js from the host."); + assertThat(nodeCommand.getNodeExecutableOrigin()).isEqualTo("force-host"); } @Test diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/AnalysisWithProgram.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/AnalysisWithProgram.java index b7ff2ec225a..c003ff56284 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/AnalysisWithProgram.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/AnalysisWithProgram.java @@ -111,8 +111,7 @@ void analyzeFiles(List inputFiles) throws IOException { ) ); } - var telemetry = bridgeServer.getTelemetry(); - new PluginTelemetry(context).reportTelemetry(telemetry); + new PluginTelemetry(context, bridgeServer).reportTelemetry(); } finally { if (success) { progressReport.stop(); diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java index 2bb09af2751..b9d770317d2 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java @@ -16,43 +16,67 @@ */ package org.sonar.plugins.javascript.analysis; +import java.util.HashMap; import java.util.stream.Collectors; -import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.utils.Version; +import org.sonar.plugins.javascript.bridge.BridgeServer; import org.sonar.plugins.javascript.bridge.BridgeServer.Dependency; -import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryResponse; public class PluginTelemetry { private static final Logger LOG = LoggerFactory.getLogger(PluginTelemetry.class); private static final String KEY_PREFIX = "javascript."; private static final String DEPENDENCY_PREFIX = KEY_PREFIX + "dependency."; + private static final String RUNTIME_PREFIX = KEY_PREFIX + "runtime."; + private final BridgeServer server; private final SensorContext ctx; - public PluginTelemetry(SensorContext ctx) { + public PluginTelemetry(SensorContext ctx, BridgeServer server) { this.ctx = ctx; + this.server = server; } - void reportTelemetry(@Nullable TelemetryResponse telemetry) { + void reportTelemetry() { var isTelemetrySupported = ctx .runtime() .getApiVersion() .isGreaterThanOrEqual(Version.create(10, 9)); - if (telemetry == null || !isTelemetrySupported) { + if (!isTelemetrySupported) { // addTelemetryProperty is added in 10.9: // https://github.com/SonarSource/sonar-plugin-api/releases/tag/10.9.0.2362 return; } - var keyMapToSave = telemetry - .dependencies() - .stream() - .collect( - Collectors.toMap(dependency -> DEPENDENCY_PREFIX + dependency.name(), Dependency::version) + var dependenciesResponse = server.getTelemetry(); + var keyMapToSave = new HashMap(); + if (dependenciesResponse != null) { + keyMapToSave.putAll( + dependenciesResponse + .dependencies() + .stream() + .collect( + Collectors.toMap( + dependency -> DEPENDENCY_PREFIX + dependency.name(), + Dependency::version + ) + ) ); + } + keyMapToSave.put( + RUNTIME_PREFIX + "major-version", + Integer.toString(server.command().getActualNodeVersion().major()) + ); + keyMapToSave.put( + RUNTIME_PREFIX + "version", + server.command().getActualNodeVersion().toString() + ); + keyMapToSave.put( + RUNTIME_PREFIX + "node-executable-origin", + server.command().getNodeExecutableOrigin() + ); keyMapToSave.forEach(ctx::addTelemetryProperty); LOG.debug("Telemetry saved: {}", keyMapToSave); } diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java index 8d6883ff81e..7a2fadd88d9 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java @@ -57,7 +57,6 @@ import org.sonar.api.batch.rule.CheckFactory; import org.sonar.api.batch.rule.internal.ActiveRulesBuilder; import org.sonar.api.batch.rule.internal.NewActiveRule; -import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.cache.WriteCache; import org.sonar.api.batch.sensor.highlighting.TypeOfText; import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor; @@ -82,7 +81,7 @@ import org.sonar.plugins.javascript.bridge.BridgeServer.AnalysisResponse; import org.sonar.plugins.javascript.bridge.BridgeServer.Dependency; import org.sonar.plugins.javascript.bridge.BridgeServer.JsAnalysisRequest; -import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryResponse; +import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryNodeResponse; import org.sonar.plugins.javascript.bridge.BridgeServer.TsProgram; import org.sonar.plugins.javascript.bridge.EslintRule; import org.sonar.plugins.javascript.bridge.PluginInfo; @@ -759,7 +758,7 @@ void log_debug_analyzed_filename() throws Exception { void should_add_telemetry_for_scanner_analysis() throws Exception { when(bridgeServerMock.analyzeJavaScript(any())).thenReturn(new AnalysisResponse()); when(bridgeServerMock.getTelemetry()).thenReturn( - new TelemetryResponse(List.of(new Dependency("pkg1", "1.1.0"))) + new TelemetryNodeResponse(List.of(new Dependency("pkg1", "1.1.0"))) ); var sensor = createSensor(); context.setRuntime( diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/PluginTelemetryTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/PluginTelemetryTest.java index 973cbbfd1c2..e92c7411ce2 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/PluginTelemetryTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/PluginTelemetryTest.java @@ -23,41 +23,76 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.function.Consumer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.sonar.api.SonarRuntime; import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.utils.Version; +import org.sonar.plugins.javascript.bridge.BridgeServer; import org.sonar.plugins.javascript.bridge.BridgeServer.Dependency; -import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryResponse; +import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryNodeResponse; +import org.sonar.plugins.javascript.nodejs.NodeCommand; +import org.sonar.plugins.javascript.nodejs.ProcessWrapper; class PluginTelemetryTest { private SensorContext ctx; private PluginTelemetry pluginTelemetry; - private TelemetryResponse telemetryResponse; @BeforeEach void setUp() { ctx = mock(SensorContext.class); SonarRuntime sonarRuntime = mock(SonarRuntime.class); when(ctx.runtime()).thenReturn(sonarRuntime); - pluginTelemetry = new PluginTelemetry(ctx); - telemetryResponse = new TelemetryResponse(List.of(new Dependency("pkg1", "1.0.0"))); + + BridgeServer server = mock(BridgeServer.class); + TelemetryNodeResponse telemetryNodeResponse = new TelemetryNodeResponse( + List.of(new Dependency("pkg1", "1.0.0")) + ); + when(server.getTelemetry()).thenReturn(telemetryNodeResponse); + Consumer noop = s -> {}; + when(server.command()).thenReturn( + new NodeCommand( + mock(ProcessWrapper.class), + "node", + Version.create(22, 9, 0), + Collections.emptyList(), + null, + Collections.emptyList(), + noop, + noop, + Map.of(), + "embedded" + ) + ); + + pluginTelemetry = new PluginTelemetry(ctx, server); } @Test void shouldNotReportIfApiVersionIsLessThan109() { when(ctx.runtime().getApiVersion()).thenReturn(Version.create(10, 8)); - pluginTelemetry.reportTelemetry(telemetryResponse); + pluginTelemetry.reportTelemetry(); verify(ctx, never()).addTelemetryProperty(anyString(), anyString()); } @Test - void shouldReportIfApiVersionIsGreaterThanOrEqualTo109() { + void shouldReport() { when(ctx.runtime().getApiVersion()).thenReturn(Version.create(10, 9)); - pluginTelemetry.reportTelemetry(telemetryResponse); + pluginTelemetry.reportTelemetry(); verify(ctx).addTelemetryProperty("javascript.dependency.pkg1", "1.0.0"); } + + @Test + void shouldReportRuntimeTelemetry() { + when(ctx.runtime().getApiVersion()).thenReturn(Version.create(10, 9)); + pluginTelemetry.reportTelemetry(); + verify(ctx).addTelemetryProperty("javascript.runtime.major-version", "22"); + verify(ctx).addTelemetryProperty("javascript.runtime.version", "22.9"); + verify(ctx).addTelemetryProperty("javascript.runtime.node-executable-origin", "embedded"); + } } From 5f4a453c65dd3b62a2ad6cc93f370b39f8d9eef6 Mon Sep 17 00:00:00 2001 From: Michal Zgliczynski Date: Mon, 16 Dec 2024 11:43:56 +0100 Subject: [PATCH 2/6] Fix failing tests --- .../JavaScriptEslintBasedSensorTest.java | 22 ++++++++++++++++++- .../javascript/analysis/JsTsSensorTest.java | 20 +++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java index 7a2fadd88d9..00aded51201 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java @@ -35,8 +35,11 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.function.Consumer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -87,7 +90,9 @@ import org.sonar.plugins.javascript.bridge.PluginInfo; import org.sonar.plugins.javascript.bridge.ServerAlreadyFailedException; import org.sonar.plugins.javascript.bridge.TsConfigFile; +import org.sonar.plugins.javascript.nodejs.NodeCommand; import org.sonar.plugins.javascript.nodejs.NodeCommandException; +import org.sonar.plugins.javascript.nodejs.ProcessWrapper; import org.sonar.plugins.javascript.sonarlint.TsConfigCacheImpl; class JavaScriptEslintBasedSensorTest { @@ -147,6 +152,21 @@ public void setUp() throws Exception { ); tsProgram = new TsProgram("", new ArrayList<>(), List.of()); when(bridgeServerMock.createProgram(any())).thenReturn(tsProgram); + Consumer noop = s -> {}; + when(bridgeServerMock.command()).thenReturn( + new NodeCommand( + mock(ProcessWrapper.class), + "node", + Version.create(22, 9, 0), + Collections.emptyList(), + null, + Collections.emptyList(), + noop, + noop, + Map.of(), + "embedded" + ) + ); context = SensorContextTester.create(baseDir); context.fileSystem().setWorkDir(workDir); context.setRuntime( @@ -772,7 +792,7 @@ void should_add_telemetry_for_scanner_analysis() throws Exception { createInputFile(context); sensor.execute(context); assertThat(logTester.logs(Level.DEBUG)).contains( - "Telemetry saved: {javascript.dependency.pkg1=1.1.0}" + "Telemetry saved: {javascript.runtime.node-executable-origin=embedded, javascript.runtime.major-version=22, javascript.dependency.pkg1=1.1.0, javascript.runtime.version=22.9}" ); } diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java index bb4da3c1732..3bc6e974177 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java @@ -39,8 +39,11 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -104,6 +107,8 @@ import org.sonar.plugins.javascript.bridge.protobuf.Position; import org.sonar.plugins.javascript.bridge.protobuf.Program; import org.sonar.plugins.javascript.bridge.protobuf.SourceLocation; +import org.sonar.plugins.javascript.nodejs.NodeCommand; +import org.sonar.plugins.javascript.nodejs.ProcessWrapper; import org.sonar.plugins.javascript.sonarlint.TsConfigCache; import org.sonar.plugins.javascript.sonarlint.TsConfigCacheImpl; @@ -166,6 +171,21 @@ public void setUp() throws Exception { when(bridgeServerMock.createTsConfigFile(any())).thenReturn( new TsConfigFile(tempFolder.newFile().getAbsolutePath(), emptyList(), emptyList()) ); + Consumer noop = s -> {}; + when(bridgeServerMock.command()).thenReturn( + new NodeCommand( + mock(ProcessWrapper.class), + "node", + Version.create(22, 9, 0), + Collections.emptyList(), + null, + Collections.emptyList(), + noop, + noop, + Map.of(), + "embedded" + ) + ); context = createSensorContext(baseDir); context.setPreviousCache(mock(ReadCache.class)); From 9a36b309ecaa78fe2c752179d9cf7c5e8d82af77 Mon Sep 17 00:00:00 2001 From: Michal Zgliczynski Date: Tue, 17 Dec 2024 12:03:36 +0100 Subject: [PATCH 3/6] comments --- .../javascript/bridge/BridgeServer.java | 10 ++--- .../javascript/bridge/BridgeServerImpl.java | 25 ++++++++---- .../bridge/BridgeServerImplTest.java | 8 ++-- .../javascript/analysis/PluginTelemetry.java | 40 +++++++------------ .../JavaScriptEslintBasedSensorTest.java | 22 +++------- .../javascript/analysis/JsTsSensorTest.java | 15 ------- .../analysis/PluginTelemetryTest.java | 24 +++-------- 7 files changed, 51 insertions(+), 93 deletions(-) diff --git a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java index 5133afdca1c..cc2f135e2b3 100644 --- a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java +++ b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java @@ -20,13 +20,13 @@ import java.io.IOException; import java.util.List; +import java.util.Map; import javax.annotation.Nullable; import org.sonar.api.Startable; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.TextRange; import org.sonar.api.scanner.ScannerSide; import org.sonar.plugins.javascript.bridge.protobuf.Node; -import org.sonar.plugins.javascript.nodejs.NodeCommand; import org.sonarsource.api.sonarlint.SonarLintSide; @ScannerSide @@ -69,9 +69,7 @@ void initLinter( TsConfigFile createTsConfigFile(String content) throws IOException; - TelemetryNodeResponse getTelemetry(); - - NodeCommand command(); + TelemetryData getTelemetry(); record JsAnalysisRequest( String filePath, @@ -281,7 +279,9 @@ public String toString() { record TsProgramRequest(String tsConfig) {} - record TelemetryNodeResponse(List dependencies) {} + record TelemetryEslintBridgeResponse(List dependencies) {} + + record TelemetryData(List dependencies, Map runtime) {} record Dependency(String name, String version) {} } diff --git a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java index 3182e319b42..4dbf224f6ee 100644 --- a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java +++ b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java @@ -534,20 +534,29 @@ public TsConfigFile createTsConfigFile(String content) { } @Override - public TelemetryNodeResponse getTelemetry() { + public TelemetryData getTelemetry() { + return new TelemetryData( + getTelemetryEslintBridgeResponse().dependencies(), + Map.of( + "version", + nodeCommand.getActualNodeVersion().toString(), + "major-version", + Integer.toString(nodeCommand.getActualNodeVersion().major()), + "node-executable-origin", + nodeCommand.getNodeExecutableOrigin() + ) + ); + } + + private TelemetryEslintBridgeResponse getTelemetryEslintBridgeResponse() { try { var result = http.get(url("get-telemetry")); - return GSON.fromJson(result, TelemetryNodeResponse.class); + return GSON.fromJson(result, TelemetryEslintBridgeResponse.class); } catch (IOException e) { - return new TelemetryNodeResponse(List.of()); + return new TelemetryEslintBridgeResponse(List.of()); } } - @Override - public NodeCommand command() { - return nodeCommand; - } - private static List emptyListIfNull(@Nullable List list) { return list == null ? emptyList() : list; } diff --git a/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java b/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java index 1dd4407b6b8..deea51eb0ef 100644 --- a/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java +++ b/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java @@ -64,7 +64,6 @@ import org.sonar.plugins.javascript.bridge.BridgeServer.CssAnalysisRequest; import org.sonar.plugins.javascript.bridge.BridgeServer.Dependency; import org.sonar.plugins.javascript.bridge.BridgeServer.JsAnalysisRequest; -import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryNodeResponse; import org.sonar.plugins.javascript.bridge.BridgeServer.TsProgram; import org.sonar.plugins.javascript.bridge.BridgeServer.TsProgramRequest; import org.sonar.plugins.javascript.bridge.protobuf.Node; @@ -759,9 +758,10 @@ void should_return_telemetry() throws Exception { bridgeServer = createBridgeServer(START_SERVER_SCRIPT); bridgeServer.startServer(serverConfig, emptyList()); var telemetry = bridgeServer.getTelemetry(); - assertThat(telemetry).isEqualTo( - new TelemetryNodeResponse(List.of(new Dependency("pkg1", "1.0.0"))) - ); + assertThat(telemetry.dependencies()).isEqualTo(List.of(new Dependency("pkg1", "1.0.0"))); + assertThat(telemetry.runtime()).containsEntry("node-executable-origin", "host"); + assertThat(telemetry.runtime()).containsKey("version"); + assertThat(telemetry.runtime()).containsKey("major-version"); } @Test diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java index b9d770317d2..1bc1201b73f 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java @@ -17,6 +17,7 @@ package org.sonar.plugins.javascript.analysis; import java.util.HashMap; +import java.util.Map; import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,32 +51,21 @@ void reportTelemetry() { // https://github.com/SonarSource/sonar-plugin-api/releases/tag/10.9.0.2362 return; } - var dependenciesResponse = server.getTelemetry(); - var keyMapToSave = new HashMap(); - if (dependenciesResponse != null) { - keyMapToSave.putAll( - dependenciesResponse - .dependencies() - .stream() - .collect( - Collectors.toMap( - dependency -> DEPENDENCY_PREFIX + dependency.name(), - Dependency::version - ) - ) - ); - } - keyMapToSave.put( - RUNTIME_PREFIX + "major-version", - Integer.toString(server.command().getActualNodeVersion().major()) - ); - keyMapToSave.put( - RUNTIME_PREFIX + "version", - server.command().getActualNodeVersion().toString() + var telemetry = server.getTelemetry(); + var keyMapToSave = new HashMap( + telemetry + .dependencies() + .stream() + .collect( + Collectors.toMap(dependency -> DEPENDENCY_PREFIX + dependency.name(), Dependency::version) + ) ); - keyMapToSave.put( - RUNTIME_PREFIX + "node-executable-origin", - server.command().getNodeExecutableOrigin() + keyMapToSave.putAll( + telemetry + .runtime() + .entrySet() + .stream() + .collect(Collectors.toMap(key -> RUNTIME_PREFIX + key.getKey(), value -> value.getValue())) ); keyMapToSave.forEach(ctx::addTelemetryProperty); LOG.debug("Telemetry saved: {}", keyMapToSave); diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java index 00aded51201..545fd32674a 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java @@ -84,7 +84,7 @@ import org.sonar.plugins.javascript.bridge.BridgeServer.AnalysisResponse; import org.sonar.plugins.javascript.bridge.BridgeServer.Dependency; import org.sonar.plugins.javascript.bridge.BridgeServer.JsAnalysisRequest; -import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryNodeResponse; +import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryEslintBridgeResponse; import org.sonar.plugins.javascript.bridge.BridgeServer.TsProgram; import org.sonar.plugins.javascript.bridge.EslintRule; import org.sonar.plugins.javascript.bridge.PluginInfo; @@ -152,21 +152,6 @@ public void setUp() throws Exception { ); tsProgram = new TsProgram("", new ArrayList<>(), List.of()); when(bridgeServerMock.createProgram(any())).thenReturn(tsProgram); - Consumer noop = s -> {}; - when(bridgeServerMock.command()).thenReturn( - new NodeCommand( - mock(ProcessWrapper.class), - "node", - Version.create(22, 9, 0), - Collections.emptyList(), - null, - Collections.emptyList(), - noop, - noop, - Map.of(), - "embedded" - ) - ); context = SensorContextTester.create(baseDir); context.fileSystem().setWorkDir(workDir); context.setRuntime( @@ -778,7 +763,10 @@ void log_debug_analyzed_filename() throws Exception { void should_add_telemetry_for_scanner_analysis() throws Exception { when(bridgeServerMock.analyzeJavaScript(any())).thenReturn(new AnalysisResponse()); when(bridgeServerMock.getTelemetry()).thenReturn( - new TelemetryNodeResponse(List.of(new Dependency("pkg1", "1.1.0"))) + new BridgeServer.TelemetryData( + List.of(new Dependency("pkg1", "1.1.0")), + Map.of("version", "22.9", "major-version", "22", "node-executable-origin", "embedded") + ) ); var sensor = createSensor(); context.setRuntime( diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java index 3bc6e974177..30182455ffe 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java @@ -171,21 +171,6 @@ public void setUp() throws Exception { when(bridgeServerMock.createTsConfigFile(any())).thenReturn( new TsConfigFile(tempFolder.newFile().getAbsolutePath(), emptyList(), emptyList()) ); - Consumer noop = s -> {}; - when(bridgeServerMock.command()).thenReturn( - new NodeCommand( - mock(ProcessWrapper.class), - "node", - Version.create(22, 9, 0), - Collections.emptyList(), - null, - Collections.emptyList(), - noop, - noop, - Map.of(), - "embedded" - ) - ); context = createSensorContext(baseDir); context.setPreviousCache(mock(ReadCache.class)); diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/PluginTelemetryTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/PluginTelemetryTest.java index e92c7411ce2..a1868629b44 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/PluginTelemetryTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/PluginTelemetryTest.java @@ -34,7 +34,7 @@ import org.sonar.api.utils.Version; import org.sonar.plugins.javascript.bridge.BridgeServer; import org.sonar.plugins.javascript.bridge.BridgeServer.Dependency; -import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryNodeResponse; +import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryEslintBridgeResponse; import org.sonar.plugins.javascript.nodejs.NodeCommand; import org.sonar.plugins.javascript.nodejs.ProcessWrapper; @@ -50,26 +50,12 @@ void setUp() { when(ctx.runtime()).thenReturn(sonarRuntime); BridgeServer server = mock(BridgeServer.class); - TelemetryNodeResponse telemetryNodeResponse = new TelemetryNodeResponse( - List.of(new Dependency("pkg1", "1.0.0")) - ); - when(server.getTelemetry()).thenReturn(telemetryNodeResponse); - Consumer noop = s -> {}; - when(server.command()).thenReturn( - new NodeCommand( - mock(ProcessWrapper.class), - "node", - Version.create(22, 9, 0), - Collections.emptyList(), - null, - Collections.emptyList(), - noop, - noop, - Map.of(), - "embedded" + when(server.getTelemetry()).thenReturn( + new BridgeServer.TelemetryData( + List.of(new Dependency("pkg1", "1.0.0")), + Map.of("version", "22.9", "major-version", "22", "node-executable-origin", "embedded") ) ); - pluginTelemetry = new PluginTelemetry(ctx, server); } From 2ce0fd65d686d2c8d017d3c7049d95272de2596b Mon Sep 17 00:00:00 2001 From: Michal Zgliczynski Date: Wed, 18 Dec 2024 09:40:56 +0100 Subject: [PATCH 4/6] Comments --- .../plugins/javascript/bridge/BridgeServer.java | 5 ++++- .../javascript/bridge/BridgeServerImpl.java | 8 ++------ .../javascript/bridge/BridgeServerImplTest.java | 6 +++--- .../javascript/analysis/PluginTelemetry.java | 14 ++++++++------ .../analysis/JavaScriptEslintBasedSensorTest.java | 12 ++++-------- .../javascript/analysis/PluginTelemetryTest.java | 13 ++++--------- 6 files changed, 25 insertions(+), 33 deletions(-) diff --git a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java index cc2f135e2b3..91eabca91f2 100644 --- a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java +++ b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java @@ -26,6 +26,7 @@ import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.TextRange; import org.sonar.api.scanner.ScannerSide; +import org.sonar.api.utils.Version; import org.sonar.plugins.javascript.bridge.protobuf.Node; import org.sonarsource.api.sonarlint.SonarLintSide; @@ -281,7 +282,9 @@ record TsProgramRequest(String tsConfig) {} record TelemetryEslintBridgeResponse(List dependencies) {} - record TelemetryData(List dependencies, Map runtime) {} + record TelemetryData(List dependencies, RuntimeTelemetry runtimeTelemetry) {} record Dependency(String name, String version) {} + + record RuntimeTelemetry(Version version, String nodeExecutableOrigin) {} } diff --git a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java index 4dbf224f6ee..3ef38c2622c 100644 --- a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java +++ b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java @@ -537,12 +537,8 @@ public TsConfigFile createTsConfigFile(String content) { public TelemetryData getTelemetry() { return new TelemetryData( getTelemetryEslintBridgeResponse().dependencies(), - Map.of( - "version", - nodeCommand.getActualNodeVersion().toString(), - "major-version", - Integer.toString(nodeCommand.getActualNodeVersion().major()), - "node-executable-origin", + new RuntimeTelemetry( + nodeCommand.getActualNodeVersion(), nodeCommand.getNodeExecutableOrigin() ) ); diff --git a/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java b/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java index deea51eb0ef..3a0b376a6bf 100644 --- a/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java +++ b/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java @@ -759,9 +759,9 @@ void should_return_telemetry() throws Exception { bridgeServer.startServer(serverConfig, emptyList()); var telemetry = bridgeServer.getTelemetry(); assertThat(telemetry.dependencies()).isEqualTo(List.of(new Dependency("pkg1", "1.0.0"))); - assertThat(telemetry.runtime()).containsEntry("node-executable-origin", "host"); - assertThat(telemetry.runtime()).containsKey("version"); - assertThat(telemetry.runtime()).containsKey("major-version"); + var runtimeTelemetry = telemetry.runtimeTelemetry(); + assertThat(runtimeTelemetry.version().isGreaterThanOrEqual(Version.create(22, 9))).isTrue(); + assertThat(runtimeTelemetry.nodeExecutableOrigin()).isNotEmpty(); } @Test diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java index 1bc1201b73f..6c6733638fd 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java @@ -60,12 +60,14 @@ void reportTelemetry() { Collectors.toMap(dependency -> DEPENDENCY_PREFIX + dependency.name(), Dependency::version) ) ); - keyMapToSave.putAll( - telemetry - .runtime() - .entrySet() - .stream() - .collect(Collectors.toMap(key -> RUNTIME_PREFIX + key.getKey(), value -> value.getValue())) + keyMapToSave.put( + RUNTIME_PREFIX + "node-executable-origin", + telemetry.runtimeTelemetry().nodeExecutableOrigin() + ); + keyMapToSave.put(RUNTIME_PREFIX + "version", telemetry.runtimeTelemetry().version().toString()); + keyMapToSave.put( + RUNTIME_PREFIX + "major-version", + Integer.toString(telemetry.runtimeTelemetry().version().major()) ); keyMapToSave.forEach(ctx::addTelemetryProperty); LOG.debug("Telemetry saved: {}", keyMapToSave); diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java index 545fd32674a..6c06b2a9152 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java @@ -35,11 +35,8 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.Map; -import java.util.function.Consumer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -84,15 +81,14 @@ import org.sonar.plugins.javascript.bridge.BridgeServer.AnalysisResponse; import org.sonar.plugins.javascript.bridge.BridgeServer.Dependency; import org.sonar.plugins.javascript.bridge.BridgeServer.JsAnalysisRequest; -import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryEslintBridgeResponse; +import org.sonar.plugins.javascript.bridge.BridgeServer.RuntimeTelemetry; +import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryData; import org.sonar.plugins.javascript.bridge.BridgeServer.TsProgram; import org.sonar.plugins.javascript.bridge.EslintRule; import org.sonar.plugins.javascript.bridge.PluginInfo; import org.sonar.plugins.javascript.bridge.ServerAlreadyFailedException; import org.sonar.plugins.javascript.bridge.TsConfigFile; -import org.sonar.plugins.javascript.nodejs.NodeCommand; import org.sonar.plugins.javascript.nodejs.NodeCommandException; -import org.sonar.plugins.javascript.nodejs.ProcessWrapper; import org.sonar.plugins.javascript.sonarlint.TsConfigCacheImpl; class JavaScriptEslintBasedSensorTest { @@ -763,9 +759,9 @@ void log_debug_analyzed_filename() throws Exception { void should_add_telemetry_for_scanner_analysis() throws Exception { when(bridgeServerMock.analyzeJavaScript(any())).thenReturn(new AnalysisResponse()); when(bridgeServerMock.getTelemetry()).thenReturn( - new BridgeServer.TelemetryData( + new TelemetryData( List.of(new Dependency("pkg1", "1.1.0")), - Map.of("version", "22.9", "major-version", "22", "node-executable-origin", "embedded") + new RuntimeTelemetry(Version.create(22, 9), "embedded") ) ); var sensor = createSensor(); diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/PluginTelemetryTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/PluginTelemetryTest.java index a1868629b44..eda07727a6d 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/PluginTelemetryTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/PluginTelemetryTest.java @@ -17,16 +17,12 @@ package org.sonar.plugins.javascript.analysis; import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import java.util.Collections; import java.util.List; -import java.util.Map; -import java.util.function.Consumer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.sonar.api.SonarRuntime; @@ -34,9 +30,8 @@ import org.sonar.api.utils.Version; import org.sonar.plugins.javascript.bridge.BridgeServer; import org.sonar.plugins.javascript.bridge.BridgeServer.Dependency; -import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryEslintBridgeResponse; -import org.sonar.plugins.javascript.nodejs.NodeCommand; -import org.sonar.plugins.javascript.nodejs.ProcessWrapper; +import org.sonar.plugins.javascript.bridge.BridgeServer.RuntimeTelemetry; +import org.sonar.plugins.javascript.bridge.BridgeServer.TelemetryData; class PluginTelemetryTest { @@ -51,9 +46,9 @@ void setUp() { BridgeServer server = mock(BridgeServer.class); when(server.getTelemetry()).thenReturn( - new BridgeServer.TelemetryData( + new TelemetryData( List.of(new Dependency("pkg1", "1.0.0")), - Map.of("version", "22.9", "major-version", "22", "node-executable-origin", "embedded") + new RuntimeTelemetry(Version.create(22, 9), "embedded") ) ); pluginTelemetry = new PluginTelemetry(ctx, server); From 44f3788df3661bbc15ecdb8008fc7b26bd50013f Mon Sep 17 00:00:00 2001 From: Michal Zgliczynski Date: Wed, 18 Dec 2024 09:45:17 +0100 Subject: [PATCH 5/6] cleanup --- .../org/sonar/plugins/javascript/bridge/BridgeServer.java | 1 - .../org/sonar/plugins/javascript/nodejs/NodeCommand.java | 2 +- .../sonar/plugins/javascript/analysis/PluginTelemetry.java | 3 +-- .../sonar/plugins/javascript/analysis/JsTsSensorTest.java | 5 ----- 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java index 91eabca91f2..6dae7339246 100644 --- a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java +++ b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java @@ -20,7 +20,6 @@ import java.io.IOException; import java.util.List; -import java.util.Map; import javax.annotation.Nullable; import org.sonar.api.Startable; import org.sonar.api.batch.fs.InputFile; diff --git a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeCommand.java b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeCommand.java index 48b784c14f8..4f2cc41257c 100644 --- a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeCommand.java +++ b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/nodejs/NodeCommand.java @@ -50,7 +50,7 @@ public class NodeCommand { private final List command; private final String nodeExecutableOrigin; - public NodeCommand( + NodeCommand( ProcessWrapper processWrapper, String nodeExecutable, Version actualNodeVersion, diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java index 6c6733638fd..d44dfd728ac 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/analysis/PluginTelemetry.java @@ -17,7 +17,6 @@ package org.sonar.plugins.javascript.analysis; import java.util.HashMap; -import java.util.Map; import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,7 +51,7 @@ void reportTelemetry() { return; } var telemetry = server.getTelemetry(); - var keyMapToSave = new HashMap( + var keyMapToSave = new HashMap<>( telemetry .dependencies() .stream() diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java index 30182455ffe..bb4da3c1732 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java @@ -39,11 +39,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.Map; -import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -107,8 +104,6 @@ import org.sonar.plugins.javascript.bridge.protobuf.Position; import org.sonar.plugins.javascript.bridge.protobuf.Program; import org.sonar.plugins.javascript.bridge.protobuf.SourceLocation; -import org.sonar.plugins.javascript.nodejs.NodeCommand; -import org.sonar.plugins.javascript.nodejs.ProcessWrapper; import org.sonar.plugins.javascript.sonarlint.TsConfigCache; import org.sonar.plugins.javascript.sonarlint.TsConfigCacheImpl; From 98804f23eb87a1c091c324034277404cb4021ada Mon Sep 17 00:00:00 2001 From: Michal Zgliczynski Date: Wed, 18 Dec 2024 10:00:38 +0100 Subject: [PATCH 6/6] Add mocks for .getTelemetry --- .../analysis/JavaScriptEslintBasedSensorTest.java | 3 +++ .../sonar/plugins/javascript/analysis/JsTsSensorTest.java | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java index 6c06b2a9152..cc36ef4a6f0 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JavaScriptEslintBasedSensorTest.java @@ -148,6 +148,9 @@ public void setUp() throws Exception { ); tsProgram = new TsProgram("", new ArrayList<>(), List.of()); when(bridgeServerMock.createProgram(any())).thenReturn(tsProgram); + when(bridgeServerMock.getTelemetry()).thenReturn( + new TelemetryData(List.of(), new RuntimeTelemetry(Version.create(22, 9), "host")) + ); context = SensorContextTester.create(baseDir); context.fileSystem().setWorkDir(workDir); context.setRuntime( diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java index bb4da3c1732..f55ebb58e07 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/analysis/JsTsSensorTest.java @@ -152,6 +152,12 @@ public void setUp() throws Exception { when(bridgeServerMock.isAlive()).thenReturn(true); when(bridgeServerMock.analyzeTypeScript(any())).thenReturn(new AnalysisResponse()); when(bridgeServerMock.getCommandInfo()).thenReturn("bridgeServerMock command info"); + when(bridgeServerMock.getTelemetry()).thenReturn( + new BridgeServer.TelemetryData( + List.of(), + new BridgeServer.RuntimeTelemetry(Version.create(22, 9), "host") + ) + ); when(bridgeServerMock.loadTsConfig(any())).thenAnswer(invocationOnMock -> { String tsConfigPath = (String) invocationOnMock.getArguments()[0]; FilePredicates predicates = context.fileSystem().predicates();