diff --git a/gradle.properties b/gradle.properties index 8c99a14ed..caa2ee15c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ kotlin.code.style=official pluginGroup = spp.jetbrains pluginName = Source++ -projectVersion=0.4.6 +projectVersion=0.4.7 pluginSinceBuild = 202.4357 # Plugin Verifier integration -> https://github.com/JetBrains/gradle-intellij-plugin#plugin-verifier-dsl # See https://jb.gg/intellij-platform-builds-list for available build versions diff --git a/monitor/src/main/graphql/.graphqlconfig b/monitor/src/main/graphql/.graphqlconfig index b20520af1..0c53e3656 100644 --- a/monitor/src/main/graphql/.graphqlconfig +++ b/monitor/src/main/graphql/.graphqlconfig @@ -12,4 +12,4 @@ } } } -} \ No newline at end of file +} diff --git a/monitor/src/main/kotlin/spp/jetbrains/monitor/skywalking/SkywalkingClient.kt b/monitor/src/main/kotlin/spp/jetbrains/monitor/skywalking/SkywalkingClient.kt index 7e9e5c871..869f873d1 100644 --- a/monitor/src/main/kotlin/spp/jetbrains/monitor/skywalking/SkywalkingClient.kt +++ b/monitor/src/main/kotlin/spp/jetbrains/monitor/skywalking/SkywalkingClient.kt @@ -127,7 +127,6 @@ class SkywalkingClient( serviceId = Optional.presentIfNotNull(request.serviceId), serviceInstanceId = Optional.presentIfNotNull(request.serviceInstanceId), endpointId = Optional.presentIfNotNull(request.endpointId), - endpointName = Optional.presentIfNotNull(request.endpointName), queryDuration = Optional.Present(request.zonedDuration.toDuration(this)), queryOrder = request.orderType.toQueryOrder(), traceState = request.orderType.toTraceState(), diff --git a/monitor/src/main/kotlin/spp/jetbrains/monitor/skywalking/SkywalkingMonitor.kt b/monitor/src/main/kotlin/spp/jetbrains/monitor/skywalking/SkywalkingMonitor.kt index 8faa7fb98..5767daf7f 100644 --- a/monitor/src/main/kotlin/spp/jetbrains/monitor/skywalking/SkywalkingMonitor.kt +++ b/monitor/src/main/kotlin/spp/jetbrains/monitor/skywalking/SkywalkingMonitor.kt @@ -64,13 +64,6 @@ class SkywalkingMonitor( private suspend fun setup() { log.debug("Apache SkyWalking server: $serverUrl") val httpBuilder = OkHttpClient().newBuilder() - .addInterceptor { chain -> - chain.proceed( - chain.request().newBuilder() - .addHeader("spp-skywalking-reroute", "true") - .build() - ) - } .hostnameVerifier { _, _ -> true } if (!jwtToken.isNullOrEmpty()) { httpBuilder.addInterceptor { chain -> diff --git a/monitor/src/main/kotlin/spp/jetbrains/monitor/skywalking/service/SWLiveViewService.kt b/monitor/src/main/kotlin/spp/jetbrains/monitor/skywalking/service/SWLiveViewService.kt index 45d73aa72..f153767f0 100644 --- a/monitor/src/main/kotlin/spp/jetbrains/monitor/skywalking/service/SWLiveViewService.kt +++ b/monitor/src/main/kotlin/spp/jetbrains/monitor/skywalking/service/SWLiveViewService.kt @@ -75,10 +75,9 @@ class SWLiveViewService : CoroutineVerticle(), LiveViewService { subscriptionMap.forEach { (_, subscription) -> launch(vertx.dispatcher()) { when (subscription.subscription.liveViewConfig.viewName) { - "ACTIVITY" -> sendActivitySubscriptionUpdate(subscription) "LOGS" -> pullLatestLogs(subscription) "TRACES" -> sendTracesSubscriptionUpdate(subscription) - else -> TODO("not implemented") + else -> sendEndpointMetricSubscriptionUpdate(subscription) } } } @@ -92,7 +91,7 @@ class SWLiveViewService : CoroutineVerticle(), LiveViewService { private suspend fun sendTracesSubscriptionUpdate(swSubscription: SWLiveViewSubscription) { val subscription = swSubscription.subscription - val endpointId = subscription.artifactQualifiedName.operationName!! //todo: PortalEventListener sets temp + val endpointId = subscription.entityIds.first() val traceResult = EndpointTracesBridge.getTraces( GetEndpointTraces( artifactQualifiedName = subscription.artifactQualifiedName, @@ -167,15 +166,14 @@ class SWLiveViewService : CoroutineVerticle(), LiveViewService { } } - private suspend fun sendActivitySubscriptionUpdate(swSubscription: SWLiveViewSubscription) { + private suspend fun sendEndpointMetricSubscriptionUpdate(swSubscription: SWLiveViewSubscription) { val subscription = swSubscription.subscription - val endpointId = subscription.artifactQualifiedName.operationName!! //todo: PortalEventListener & ActivityQuickStatsIndicator sets temp val lastMetricsByTimeBucket = swSubscription.lastMetricsByTimeBucket val endTime = ZonedDateTime.now().plusMinutes(1).truncatedTo(ChronoUnit.MINUTES) //exclusive val startTime = endTime.minusMinutes(3) val metricsRequest = GetEndpointMetrics( subscription.liveViewConfig.viewMetrics, - endpointId, //subscription.entityIds.first(), + subscription.entityIds.first(), ZonedDuration(startTime, endTime, SkywalkingClient.DurationStep.MINUTE) ) @@ -216,8 +214,7 @@ class SWLiveViewService : CoroutineVerticle(), LiveViewService { value: Any ): JsonObject { return JsonObject() - .put("entityId", subscription.artifactQualifiedName.operationName) //todo: PortalEventListener sets temp - .put("entityName", subscription.entityIds.first()) + .put("entityId", subscription.entityIds.first()) .put("serviceId", "todo") .put("value", value) .put("total", value) diff --git a/plugin/src/main/java/spp/jetbrains/sourcemarker/ControlBar.java b/plugin/src/main/java/spp/jetbrains/sourcemarker/ControlBar.java index d9293b89e..d26325acd 100644 --- a/plugin/src/main/java/spp/jetbrains/sourcemarker/ControlBar.java +++ b/plugin/src/main/java/spp/jetbrains/sourcemarker/ControlBar.java @@ -201,7 +201,7 @@ private void initComponents() { textField1 = new AutocompleteField( message("location") + ": " + location + "#" + inlayMark.getLineNumber(), availableCommands, lookup, inlayMark.getArtifactQualifiedName(), true, true, SELECT_COLOR_RED); - textField1.setCellRenderer(new ControlBarCellRenderer(textField1)); + textField1.setCellRenderer(new ControlBarCellRenderer(textField1, (ExpressionSourceMark) inlayMark)); label2 = new JLabel(); //======== this ======== diff --git a/plugin/src/main/java/spp/jetbrains/sourcemarker/settings/PluginConfigurationPanel.java b/plugin/src/main/java/spp/jetbrains/sourcemarker/settings/PluginConfigurationPanel.java index bc23cf872..56c8a8209 100644 --- a/plugin/src/main/java/spp/jetbrains/sourcemarker/settings/PluginConfigurationPanel.java +++ b/plugin/src/main/java/spp/jetbrains/sourcemarker/settings/PluginConfigurationPanel.java @@ -93,7 +93,9 @@ public JComponent getContentPane() { } boolean isModified() { - if (!Arrays.equals(rootSourcePackageTextField.getText().split(","), config.getRootSourcePackages().toArray())) { + if (config.getOverride()) return false; + + if (!Arrays.equals(Arrays.stream(rootSourcePackageTextField.getText().split(",")).filter(s -> !s.isEmpty()).toArray(), config.getRootSourcePackages().toArray())) { return true; } if (!Objects.equals(autoResolveEndpointNamesCheckBox.isSelected(), config.getAutoResolveEndpointNames())) { @@ -102,7 +104,7 @@ boolean isModified() { if (!Objects.equals(debugConsoleCheckBox.isSelected(), config.getPluginConsoleEnabled())) { return true; } - if (!Objects.equals(serviceHostTextField.getText(), config.getServiceHost())) { + if (!Objects.equals(serviceHostTextField.getText(), config.getServiceHost() != null ? config.getServiceHost() : "")) { return true; } if (!Objects.equals(accessTokenTextField.getText(), config.getAccessToken() != null ? config.getAccessToken() : "")) { diff --git a/plugin/src/main/java/spp/jetbrains/sourcemarker/status/BreakpointStatusBar.java b/plugin/src/main/java/spp/jetbrains/sourcemarker/status/BreakpointStatusBar.java index 66d423857..56e108d66 100644 --- a/plugin/src/main/java/spp/jetbrains/sourcemarker/status/BreakpointStatusBar.java +++ b/plugin/src/main/java/spp/jetbrains/sourcemarker/status/BreakpointStatusBar.java @@ -57,12 +57,12 @@ import static spp.jetbrains.sourcemarker.PluginBundle.message; import static spp.jetbrains.sourcemarker.PluginUI.*; import static spp.jetbrains.sourcemarker.status.util.ViewUtils.addRecursiveMouseListener; -import static spp.protocol.marshall.ProtocolMarshaller.deserializeLiveInstrumentRemoved; import static spp.protocol.SourceServices.Instance.INSTANCE; import static spp.protocol.instrument.event.LiveInstrumentEventType.BREAKPOINT_HIT; import static spp.protocol.instrument.event.LiveInstrumentEventType.BREAKPOINT_REMOVED; +import static spp.protocol.marshall.ProtocolMarshaller.deserializeLiveInstrumentRemoved; -public class BreakpointStatusBar extends JPanel implements StatusBar, InstrumentEventListener, VisibleAreaListener { +public class BreakpointStatusBar extends JPanel implements StatusBar, InstrumentEventListener, VisibleAreaListener { private final InlayMark inlayMark; private final LiveSourceLocation sourceLocation; @@ -146,7 +146,7 @@ public void setWrapperPanel(JPanel wrapperPanel) { @Override public void visibleAreaChanged(VisibleAreaEvent e) { breakpointConditionField.hideAutocompletePopup(); - if(popup != null) { + if (popup != null) { popup.dispose(); popup = null; } diff --git a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/SourceMarkerPlugin.kt b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/SourceMarkerPlugin.kt index c6c5dc289..2ba7a346d 100644 --- a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/SourceMarkerPlugin.kt +++ b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/SourceMarkerPlugin.kt @@ -36,6 +36,7 @@ import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent import com.intellij.openapi.vfs.newvfs.events.VFileEvent import eu.geekplace.javapinning.JavaPinning import eu.geekplace.javapinning.pin.Pin +import io.vertx.core.MultiMap import io.vertx.core.Vertx import io.vertx.core.VertxOptions import io.vertx.core.http.HttpClientOptions @@ -44,7 +45,6 @@ import io.vertx.core.json.DecodeException import io.vertx.core.json.Json import io.vertx.core.json.JsonObject import io.vertx.core.net.TrustOptions -import io.vertx.ext.auth.impl.jose.JWT import io.vertx.kotlin.coroutines.await import io.vertx.kotlin.coroutines.dispatcher import io.vertx.servicediscovery.ServiceDiscovery @@ -88,6 +88,7 @@ import spp.protocol.service.LiveService import spp.protocol.service.LiveViewService import java.awt.Dimension import java.io.File +import javax.net.ssl.SSLHandshakeException /** * Sets up the SourceMarker plugin by configuring and initializing the various plugin modules. @@ -304,7 +305,7 @@ object SourceMarkerPlugin { if (persistedConfig == null && fileConfig != null) { fileConfig } else { - SourceMarkerConfig(override = true) + persistedConfig ?: SourceMarkerConfig() } } return config @@ -413,7 +414,7 @@ object SourceMarkerPlugin { private suspend fun initServices(project: Project, config: SourceMarkerConfig) { if (!config.serviceHost.isNullOrBlank()) { - val servicePort = config.getServicePortNormalized()!! + val servicePort = config.getServicePortNormalized() val certificatePins = mutableListOf() certificatePins.addAll(config.certificatePins) val httpClientOptions = if (certificatePins.isNotEmpty()) { @@ -437,8 +438,9 @@ object SourceMarkerPlugin { val tokenUri = "/api/new-token?access_token=" + config.accessToken val req = vertx.createHttpClient(httpClientOptions).request( RequestOptions() + .setHeaders(MultiMap.caseInsensitiveMultiMap().add("spp-platform-request", "true")) .setSsl(config.isSsl()) - .setHost(config.serviceHostNormalized!!) + .setHost(config.serviceHostNormalized) .setPort(servicePort) .setURI(tokenUri) ).await() @@ -456,38 +458,73 @@ object SourceMarkerPlugin { } } else { //try default local access - val defaultAccessToken = "change-me" - val tokenUri = "/api/new-token?access_token=$defaultAccessToken" - val req = vertx.createHttpClient(HttpClientOptions().setSsl(true).setVerifyHost(false).setTrustAll(true)) - .request( - RequestOptions() - .setHost("localhost") - .setPort(SourceMarkerConfig.DEFAULT_SERVICE_PORT) - .setURI(tokenUri) - ).await() - req.end().await() - val resp = req.response().await() - if (resp.statusCode() in 200..299) { - val body = resp.body().await().toString() - config.serviceToken = body + try { + tryDefaultAccess(true, config, project) + } catch (e: SSLHandshakeException) { + tryDefaultAccess(false, config, project) + } catch (e: Exception) { + log.warn("Unable to find local live platform", e) + } + } + } + + private suspend fun tryDefaultAccess(ssl: Boolean, config: SourceMarkerConfig, project: Project) { + val defaultAccessToken = "change-me" + val tokenUri = "/api/new-token?access_token=$defaultAccessToken" + val req = vertx.createHttpClient(HttpClientOptions().setSsl(ssl).setVerifyHost(false).setTrustAll(true)) + .request( + RequestOptions() + .setHeaders(MultiMap.caseInsensitiveMultiMap().add("spp-platform-request", "true")) + .setHost("localhost") + .setPort(SourceMarkerConfig.DEFAULT_SERVICE_PORT) + .setURI(tokenUri) + ).await() + req.end().await() + + val resp = req.response().await() + if (resp.statusCode() in 200..299) { + val body = resp.body().await().toString() + config.serviceToken = body + if (ssl) { config.serviceHost = "https://localhost:" + SourceMarkerConfig.DEFAULT_SERVICE_PORT - config.accessToken = defaultAccessToken - config.verifyHost = false + } else { + config.serviceHost = "http://localhost:" + SourceMarkerConfig.DEFAULT_SERVICE_PORT + } + config.accessToken = defaultAccessToken + config.verifyHost = false - val projectSettings = PropertiesComponent.getInstance(project) - projectSettings.setValue("sourcemarker_plugin_config", Json.encode(config)) + val projectSettings = PropertiesComponent.getInstance(project) + projectSettings.setValue("sourcemarker_plugin_config", Json.encode(config)) - discoverAvailableServices(config, project) + discoverAvailableServices(config, project) - //auto-established notification - Notifications.Bus.notify( - Notification( - message("plugin_name"), "Connection auto-established", - "You have successfully auto-connected. ${message("plugin_name")} is now fully activated.", - NotificationType.INFORMATION - ) + //auto-established notification + Notifications.Bus.notify( + Notification( + message("plugin_name"), "Connection auto-established", + "You have successfully auto-connected to Live Platform. ${message("plugin_name")} is now fully activated.", + NotificationType.INFORMATION ) + ) + } else if (resp.statusCode() == 405) { + //found skywalking OAP server + if (ssl) { + config.serviceHost = "https://localhost:" + SourceMarkerConfig.DEFAULT_SERVICE_PORT + } else { + config.serviceHost = "http://localhost:" + SourceMarkerConfig.DEFAULT_SERVICE_PORT + config.verifyHost = false } + val projectSettings = PropertiesComponent.getInstance(project) + projectSettings.setValue("sourcemarker_plugin_config", Json.encode(config)) + + //auto-established notification + Notifications.Bus.notify( + Notification( + message("plugin_name"), "Connection auto-established", + "You have successfully auto-connected to Apache SkyWalking. ${message("plugin_name")} is now fully activated.", + NotificationType.INFORMATION + ) + ) } } diff --git a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/command/ControlBarController.kt b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/command/ControlBarController.kt index a7eff4dae..7230801be 100644 --- a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/command/ControlBarController.kt +++ b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/command/ControlBarController.kt @@ -29,7 +29,6 @@ import spp.jetbrains.marker.source.SourceFileMarker import spp.jetbrains.marker.source.mark.api.MethodSourceMark import spp.jetbrains.marker.source.mark.api.SourceMark import spp.jetbrains.marker.source.mark.api.component.swing.SwingSourceMarkComponentProvider -import spp.jetbrains.marker.source.mark.api.event.SourceMarkEvent import spp.jetbrains.marker.source.mark.api.event.SourceMarkEventCode.* import spp.jetbrains.marker.source.mark.inlay.ExpressionInlayMark import spp.jetbrains.marker.source.mark.inlay.InlayMark @@ -236,8 +235,8 @@ object ControlBarController { private fun handleViewPortalCommand(editor: Editor, command: LiveControlCommand) { val sourceMark = SourceMarkSearch.getClosestSourceMark(previousControlBar!!.sourceFileMarker, editor) if (sourceMark != null) { - sourceMark.triggerEvent(SourceMarkEvent(sourceMark, UPDATE_PORTAL_CONFIG, command)) { - sourceMark.triggerEvent(SourceMarkEvent(sourceMark, PORTAL_OPENING)) + sourceMark.triggerEvent(UPDATE_PORTAL_CONFIG, listOf(command)) { + sourceMark.triggerEvent(PORTAL_OPENING, listOf(PORTAL_OPENING)) } } else { log.warn("No source mark found for command: {}", command) diff --git a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/portal/PortalController.kt b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/portal/PortalController.kt index 1c76c8ed0..83e16ed6f 100644 --- a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/portal/PortalController.kt +++ b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/portal/PortalController.kt @@ -20,6 +20,7 @@ package spp.jetbrains.sourcemarker.portal import com.fasterxml.jackson.databind.module.SimpleModule import com.intellij.ide.ui.laf.IntelliJLaf import com.intellij.openapi.application.ApplicationManager +import io.vertx.core.json.JsonObject import io.vertx.core.json.jackson.DatabindCodec import io.vertx.kotlin.coroutines.CoroutineVerticle import io.vertx.kotlin.coroutines.await @@ -31,6 +32,7 @@ import spp.jetbrains.marker.source.mark.api.event.SourceMarkEventCode import spp.jetbrains.marker.source.mark.guide.GuideMark import spp.jetbrains.portal.SourcePortal import spp.jetbrains.portal.backend.PortalServer +import spp.jetbrains.portal.protocol.ProtocolAddress.Global.RenderPage import spp.jetbrains.portal.protocol.portal.PageType import spp.jetbrains.sourcemarker.command.LiveControlCommand import spp.jetbrains.sourcemarker.command.LiveControlCommand.* @@ -71,27 +73,36 @@ class PortalController(private val markerConfig: SourceMarkerConfig) : Coroutine val genUrl = "http://localhost:${portalServer.serverPort}?portalUuid=${portal.portalUuid}" it.sourceMark.addEventListener { if (it.eventCode == SourceMarkEventCode.UPDATE_PORTAL_CONFIG) { - when (val command = it.params.first() as LiveControlCommand) { - VIEW_OVERVIEW -> portal.configuration.config["currentPage"] = PageType.OVERVIEW - VIEW_ACTIVITY -> portal.configuration.config["currentPage"] = PageType.ACTIVITY - VIEW_TRACES -> portal.configuration.config["currentPage"] = PageType.TRACES - VIEW_LOGS -> portal.configuration.config["currentPage"] = PageType.LOGS + val newPage = when (val command = it.params.first() as LiveControlCommand) { + VIEW_OVERVIEW -> PageType.OVERVIEW + VIEW_ACTIVITY -> PageType.ACTIVITY + VIEW_TRACES -> PageType.TRACES + VIEW_LOGS -> PageType.LOGS else -> throw UnsupportedOperationException("Command input: $command") } - val jcefComponent = it.sourceMark.sourceMarkComponent as SourceMarkJcefComponent - jcefComponent.configuration.currentUrl = "#" + if (newPage != portal.configuration.config["currentPage"]) { + log.info("Setting portal page to $newPage") + portal.configuration.config["currentPage"] = newPage + } } else if (it.eventCode == SourceMarkEventCode.PORTAL_OPENING) { + SourcePortal.getPortals().filter { it.portalUuid != portal.portalUuid }.forEach { + it.configuration.config["active"] = false + } + portal.configuration.config["active"] = true + val jcefComponent = it.sourceMark.sourceMarkComponent as SourceMarkJcefComponent portal.configuration.darkMode = UIManager.getLookAndFeel() !is IntelliJLaf - if (jcefComponent.configuration.currentUrl != genUrl) { + if (jcefComponent.configuration.currentUrl == "about:blank") { jcefComponent.configuration.initialUrl = genUrl jcefComponent.configuration.currentUrl = genUrl jcefComponent.getBrowser().cefBrowser.executeJavaScript( "window.location.href = '$genUrl';", genUrl, 0 ) } + portal.configuration.config["portal_uuid"] = portal.portalUuid + vertx.eventBus().publish(RenderPage, JsonObject.mapFrom(portal.configuration)) ApplicationManager.getApplication().invokeLater(it.sourceMark::displayPopup) } } diff --git a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/portal/PortalEventListener.kt b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/portal/PortalEventListener.kt index 4215b8469..c05a1aa22 100644 --- a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/portal/PortalEventListener.kt +++ b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/portal/PortalEventListener.kt @@ -47,6 +47,7 @@ import spp.jetbrains.monitor.skywalking.SkywalkingClient import spp.jetbrains.monitor.skywalking.average import spp.jetbrains.monitor.skywalking.bridge.EndpointMetricsBridge import spp.jetbrains.monitor.skywalking.bridge.EndpointTracesBridge +import spp.jetbrains.monitor.skywalking.bridge.GeneralBridge import spp.jetbrains.monitor.skywalking.bridge.LogsBridge import spp.jetbrains.monitor.skywalking.bridge.LogsBridge.GetEndpointLogs import spp.jetbrains.monitor.skywalking.model.GetEndpointMetrics @@ -74,13 +75,14 @@ import spp.jetbrains.portal.protocol.ProtocolAddress.Global.RefreshPortal import spp.jetbrains.portal.protocol.ProtocolAddress.Global.RefreshTraces import spp.jetbrains.portal.protocol.ProtocolAddress.Global.SetCurrentPage import spp.jetbrains.portal.protocol.ProtocolAddress.Global.TraceSpanUpdated -import spp.jetbrains.portal.protocol.ProtocolAddress.Portal.UpdateEndpoints +import spp.jetbrains.portal.protocol.ProtocolAddress.Global.UpdateEndpoints import spp.jetbrains.portal.protocol.artifact.endpoint.EndpointResult import spp.jetbrains.portal.protocol.artifact.endpoint.EndpointType import spp.jetbrains.portal.protocol.artifact.metrics.ArtifactSummarizedMetrics import spp.jetbrains.portal.protocol.artifact.metrics.ArtifactSummarizedResult import spp.jetbrains.portal.protocol.portal.PageType import spp.jetbrains.sourcemarker.PluginBundle +import spp.jetbrains.sourcemarker.SourceMarkerPlugin import spp.jetbrains.sourcemarker.mark.SourceMarkKeys import spp.jetbrains.sourcemarker.mark.SourceMarkKeys.ENDPOINT_DETECTOR import spp.jetbrains.sourcemarker.mark.SourceMarkSearch @@ -140,7 +142,7 @@ class PortalEventListener( if (lastDisplayedInternalPortal != null) { lastDisplayedInternalPortal!!.configuration.darkMode = (it.newValue !is IntelliJLaf) val sourceMark = SourceMarker.getSourceMark( - lastDisplayedInternalPortal!!.viewingArtifact, SourceMark.Type.GUTTER + lastDisplayedInternalPortal!!.viewingArtifact, SourceMark.Type.GUIDE ) if (sourceMark != null) { val jcefComponent = sourceMark.sourceMarkComponent as SourceMarkJcefComponent @@ -193,7 +195,7 @@ class PortalEventListener( if (lastDisplayedInternalPortal == null) { configureDisplayedPortal(portal) } else { - val sourceMark = SourceMarker.getSourceMark(portal.viewingArtifact, SourceMark.Type.GUTTER) + val sourceMark = SourceMarker.getSourceMark(portal.viewingArtifact, SourceMark.Type.GUIDE) val jcefComponent = sourceMark!!.sourceMarkComponent as SourceMarkJcefComponent val port = vertx.sharedData().getLocalMap("portal")["http.port"]!! val host = "http://localhost:$port" @@ -298,7 +300,7 @@ class PortalEventListener( //update subscriptions launch(vertx.dispatcher()) { val sourceMark = SourceMarker.getSourceMark( - portal.viewingArtifact, SourceMark.Type.GUTTER + portal.viewingArtifact, SourceMark.Type.GUIDE ) ?: return@launch val endpointName = sourceMark.getUserData( ENDPOINT_DETECTOR @@ -307,13 +309,19 @@ class PortalEventListener( ENDPOINT_DETECTOR )?.getOrFindEndpointId(sourceMark) ?: return@launch + val swVersion = GeneralBridge.getVersion(SourceMarkerPlugin.vertx) + val fetchMetricTypes = if (swVersion.startsWith("9")) { + listOf("endpoint_cpm", "endpoint_resp_time", "endpoint_sla") + } else { + listOf("endpoint_cpm", "endpoint_avg", "endpoint_sla") + } Instance.liveView!!.addLiveViewSubscription( LiveViewSubscription( null, listOf(endpointName), - portal.viewingArtifact.copy(operationName = endpointId), //todo: only SWLiveViewService uses + portal.viewingArtifact, LiveSourceLocation(portal.viewingArtifact.identifier, 0), //todo: fix - LiveViewConfig("ACTIVITY", listOf("endpoint_cpm", "endpoint_avg", "endpoint_sla")) + LiveViewConfig("ACTIVITY", fetchMetricTypes) ) ).onComplete { if (it.succeeded()) { @@ -346,7 +354,7 @@ class PortalEventListener( //update subscriptions launch(vertx.dispatcher()) { val sourceMark = SourceMarker.getSourceMark( - portal.viewingArtifact, SourceMark.Type.GUTTER + portal.viewingArtifact, SourceMark.Type.GUIDE ) ?: return@launch val endpointName = sourceMark.getUserData( ENDPOINT_DETECTOR @@ -359,7 +367,7 @@ class PortalEventListener( LiveViewSubscription( null, listOf(endpointName), - portal.viewingArtifact.copy(operationName = endpointId), //todo: only SWLiveViewService uses + portal.viewingArtifact, LiveSourceLocation(portal.viewingArtifact.identifier, 0), //todo: fix LiveViewConfig("TRACES", listOf("endpoint_traces")) ) @@ -394,7 +402,7 @@ class PortalEventListener( //update subscriptions launch(vertx.dispatcher()) { val sourceMark = SourceMarker.getSourceMark( - portal.viewingArtifact, SourceMark.Type.GUTTER + portal.viewingArtifact, SourceMark.Type.GUIDE ) ?: return@launch val logPatterns = if (sourceMark is ClassSourceMark) { sourceMark.sourceFileMarker.getSourceMarks().filterIsInstance() @@ -482,7 +490,7 @@ class PortalEventListener( } private suspend fun pullLatestTraces(portal: SourcePortal) { - val sourceMark = SourceMarker.getSourceMark(portal.viewingArtifact, SourceMark.Type.GUTTER) + val sourceMark = SourceMarker.getSourceMark(portal.viewingArtifact, SourceMark.Type.GUIDE) if (sourceMark != null && sourceMark is MethodSourceMark) { val endpointId = sourceMark.getUserData(ENDPOINT_DETECTOR)!!.getOrFindEndpointId(sourceMark) if (endpointId != null) { @@ -539,7 +547,7 @@ class PortalEventListener( private suspend fun pullLatestLogs(portal: SourcePortal) { if (log.isTraceEnabled) log.trace("Refreshing logs. Portal: {}", portal.portalUuid) - val sourceMark = SourceMarker.getSourceMark(portal.viewingArtifact, SourceMark.Type.GUTTER) + val sourceMark = SourceMarker.getSourceMark(portal.viewingArtifact, SourceMark.Type.GUIDE) val logsResult = LogsBridge.queryLogs( GetEndpointLogs( endpointId = if (sourceMark is MethodSourceMark) { @@ -583,7 +591,12 @@ class PortalEventListener( it.getUserData(ENDPOINT_DETECTOR)!!.getOrFindEndpointId(it) != null } - val fetchMetricTypes = listOf("endpoint_cpm", "endpoint_avg", "endpoint_sla") + val swVersion = GeneralBridge.getVersion(SourceMarkerPlugin.vertx) + val fetchMetricTypes = if (swVersion.startsWith("9")) { + listOf("endpoint_cpm", "endpoint_resp_time", "endpoint_sla") + } else { + listOf("endpoint_cpm", "endpoint_avg", "endpoint_sla") + } val requestDuration = ZonedDuration( ZonedDateTime.now().minusMinutes(portal.overviewView.timeFrame.minutes.toLong()), ZonedDateTime.now(), @@ -616,7 +629,7 @@ class PortalEventListener( } vertx.eventBus().send( - UpdateEndpoints(portal.portalUuid), + UpdateEndpoints, JsonObject( Json.encode( EndpointResult( @@ -632,7 +645,7 @@ class PortalEventListener( } private suspend fun pullLatestActivity(portal: SourcePortal) { - val sourceMark = SourceMarker.getSourceMark(portal.viewingArtifact, SourceMark.Type.GUTTER) + val sourceMark = SourceMarker.getSourceMark(portal.viewingArtifact, SourceMark.Type.GUIDE) if (sourceMark != null && sourceMark is MethodSourceMark) { val endpointId = sourceMark.getUserData(ENDPOINT_DETECTOR)!!.getOrFindEndpointId(sourceMark) if (endpointId != null) { @@ -642,10 +655,16 @@ class PortalEventListener( } private suspend fun pullLatestActivity(portal: SourcePortal, endpointId: String) { + val swVersion = GeneralBridge.getVersion(SourceMarkerPlugin.vertx) + val fetchMetricTypes = if (swVersion.startsWith("9")) { + listOf("endpoint_cpm", "endpoint_resp_time", "endpoint_sla") + } else { + listOf("endpoint_cpm", "endpoint_avg", "endpoint_sla") + } val endTime = ZonedDateTime.now().plusMinutes(1).truncatedTo(ChronoUnit.MINUTES) val startTime = endTime.minusMinutes(portal.activityView.timeFrame.minutes.toLong()) val metricsRequest = GetEndpointMetrics( - listOf("endpoint_cpm", "endpoint_avg", "endpoint_sla"), + fetchMetricTypes, endpointId, ZonedDuration(startTime, endTime, SkywalkingClient.DurationStep.MINUTE) ) @@ -663,7 +682,7 @@ class PortalEventListener( } private fun openPortal(portal: SourcePortal) { - val sourceMark = SourceMarker.getSourceMark(portal.viewingArtifact, SourceMark.Type.GUTTER) + val sourceMark = SourceMarker.getSourceMark(portal.viewingArtifact, SourceMark.Type.GUIDE) if (sourceMark != null) { configureDisplayedPortal(portal) ApplicationManager.getApplication().invokeLater(sourceMark::displayPopup) @@ -671,7 +690,7 @@ class PortalEventListener( } private fun configureDisplayedPortal(portal: SourcePortal) { - val sourceMark = SourceMarker.getSourceMark(portal.viewingArtifact, SourceMark.Type.GUTTER) + val sourceMark = SourceMarker.getSourceMark(portal.viewingArtifact, SourceMark.Type.GUIDE) if (sourceMark != null) { val jcefComponent = sourceMark.sourceMarkComponent as SourceMarkJcefComponent if (portal != lastDisplayedInternalPortal) { @@ -836,7 +855,7 @@ class PortalEventListener( } private fun closePortal(portal: SourcePortal) { - val sourceMark = SourceMarker.getSourceMark(portal.viewingArtifact, SourceMark.Type.GUTTER) + val sourceMark = SourceMarker.getSourceMark(portal.viewingArtifact, SourceMark.Type.GUIDE) if (sourceMark != null) { ApplicationManager.getApplication().invokeLater(sourceMark::closePopup) } diff --git a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/service/LiveViewManager.kt b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/service/LiveViewManager.kt index 9a77d9c7d..f00672cc3 100644 --- a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/service/LiveViewManager.kt +++ b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/service/LiveViewManager.kt @@ -55,6 +55,8 @@ class LiveViewManager(private val pluginConfig: SourceMarkerConfig) : CoroutineV //todo: remove in favor of sending events to individual subscribers SourceMarkSearch.findBySubscriptionId(event.subscriptionId) ?.getUserData(SourceMarkKeys.VIEW_EVENT_LISTENERS)?.forEach { it.accept(event) } + + vertx.eventBus().publish(toLiveViewSubscriberAddress(event.subscriptionId), it.body()) } FrameHelper.sendFrame( diff --git a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/service/discover/TCPServiceDiscoveryBackend.kt b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/service/discover/TCPServiceDiscoveryBackend.kt index 4f5de840a..d084d3304 100644 --- a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/service/discover/TCPServiceDiscoveryBackend.kt +++ b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/service/discover/TCPServiceDiscoveryBackend.kt @@ -74,7 +74,7 @@ class TCPServiceDiscoveryBackend : ServiceDiscoveryBackend { config.getJsonObject("sourcemarker_plugin_config").toString(), SourceMarkerConfig::class.java ) - val serviceHost = pluginConfig.serviceHostNormalized!! + val serviceHost = pluginConfig.serviceHostNormalized val certificatePins = mutableListOf() certificatePins.addAll(pluginConfig.certificatePins) diff --git a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/settings/SourceMarkerConfig.kt b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/settings/SourceMarkerConfig.kt index 222e9443e..1177bafac 100644 --- a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/settings/SourceMarkerConfig.kt +++ b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/settings/SourceMarkerConfig.kt @@ -38,14 +38,14 @@ data class SourceMarkerConfig( val override: Boolean = false ) { companion object { - const val DEFAULT_SERVICE_PORT = 5445 + const val DEFAULT_SERVICE_PORT = 12800 const val DEFAULT_TCP_SERVICE_PORT = 5455 } } -val SourceMarkerConfig.serviceHostNormalized: String? +val SourceMarkerConfig.serviceHostNormalized: String get() { - if (serviceHost == null) return null + if (serviceHost == null) return "localhost" var serviceHost = serviceHost!! .substringAfter("https://").substringAfter("http://") if (serviceHost.contains(":")) { @@ -55,8 +55,8 @@ val SourceMarkerConfig.serviceHostNormalized: String? return serviceHost } -fun SourceMarkerConfig.getServicePortNormalized(): Int? { - if (serviceHost == null) return null +fun SourceMarkerConfig.getServicePortNormalized(): Int { + if (serviceHost == null) return SourceMarkerConfig.DEFAULT_SERVICE_PORT val hostStr = serviceHost!!.substringAfter("https://").substringAfter("http://") if (hostStr.contains(":")) { return hostStr.split(":")[1].toInt() diff --git a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/settings/SourceMarkerConfigurable.kt b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/settings/SourceMarkerConfigurable.kt index 8540c4710..8891fd395 100644 --- a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/settings/SourceMarkerConfigurable.kt +++ b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/settings/SourceMarkerConfigurable.kt @@ -36,12 +36,9 @@ import javax.swing.JComponent class SourceMarkerConfigurable : Configurable { private var form: PluginConfigurationPanel? = null - override fun getDisplayName(): String = message("plugin_name") - override fun isModified(): Boolean { - val projectSettings = PropertiesComponent.getInstance(ProjectManager.getInstance().openProjects[0]) - return !projectSettings.isValueSet("sourcemarker_plugin_config") || form!!.isModified - } + override fun getDisplayName(): String = message("plugin_name") + override fun isModified(): Boolean = form!!.isModified override fun apply() { val updatedConfig = form!!.pluginConfig diff --git a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/status/util/ControlBarCellRenderer.kt b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/status/util/ControlBarCellRenderer.kt index 233d143cd..2adf98b43 100644 --- a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/status/util/ControlBarCellRenderer.kt +++ b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/status/util/ControlBarCellRenderer.kt @@ -17,6 +17,8 @@ */ package spp.jetbrains.sourcemarker.status.util +import spp.jetbrains.marker.source.mark.api.ExpressionSourceMark +import spp.jetbrains.marker.source.mark.api.event.SourceMarkEventCode.UPDATE_PORTAL_CONFIG import spp.jetbrains.sourcemarker.PluginUI.BGND_FOCUS_COLOR import spp.jetbrains.sourcemarker.command.LiveControlCommand import spp.jetbrains.sourcemarker.element.LiveControlBarRow @@ -31,7 +33,9 @@ import javax.swing.JList * @since 0.3.0 * @author [Brandon Fergerson](mailto:bfergerson@apache.org) */ -class ControlBarCellRenderer(private val autocompleteField: AutocompleteField) : DefaultListCellRenderer() { +class ControlBarCellRenderer( + private val autocompleteField: AutocompleteField, val sourceMark: ExpressionSourceMark +) : DefaultListCellRenderer() { init { isOpaque = false } @@ -60,6 +64,9 @@ class ControlBarCellRenderer(private val autocompleteField: AutocompleteField) : if (isSelected) { row.background = BGND_FOCUS_COLOR row.setCommandIcon(entry.selectedIcon) + if (entry.name.startsWith("VIEW_")) { + sourceMark.getParentSourceMark()!!.triggerEvent(UPDATE_PORTAL_CONFIG, listOf(entry)) + } } return row } diff --git a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/view/ActivityQuickStatsIndicator.kt b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/view/ActivityQuickStatsIndicator.kt index 1b9f37e1d..6c8e4de34 100644 --- a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/view/ActivityQuickStatsIndicator.kt +++ b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/view/ActivityQuickStatsIndicator.kt @@ -142,9 +142,7 @@ class ActivityQuickStatsIndicator(val config: SourceMarkerConfig) : SourceMarkEv LiveViewSubscription( null, listOf(sourceMark.getUserData(EndpointDetector.ENDPOINT_NAME)!!), - sourceMark.artifactQualifiedName.copy( - operationName = sourceMark.getUserData(EndpointDetector.ENDPOINT_ID)!! //todo: only SWLiveViewService uses - ), + sourceMark.artifactQualifiedName, LiveSourceLocation(sourceMark.artifactQualifiedName.identifier, 0), //todo: don't need LiveViewConfig("ACTIVITY", listenMetrics, -1) ) diff --git a/test/e2e/docker-compose.yml b/test/e2e/docker-compose.yml index 0d0bc7085..6680f6c09 100644 --- a/test/e2e/docker-compose.yml +++ b/test/e2e/docker-compose.yml @@ -5,9 +5,9 @@ services: container_name: spp-platform hostname: spp-platform ports: - - "5445:5445" - "5450:5450" - "5455:5455" + - "12800:12800" environment: - SPP_LOGGING_LEVEL=trace - SPP_OAP_HOST=skywalking-oap @@ -61,4 +61,4 @@ services: # links: # - skywalking-oap # environment: -# - SW_OAP_ADDRESS=skywalking-oap:12800 \ No newline at end of file +# - SW_OAP_ADDRESS=skywalking-oap:12800 diff --git a/test/e2e/example-web-app b/test/e2e/example-web-app index ad89a5549..ef048628d 160000 --- a/test/e2e/example-web-app +++ b/test/e2e/example-web-app @@ -1 +1 @@ -Subproject commit ad89a55493e655a3a00c22c7d284409923312051 +Subproject commit ef048628d53c681b5b5d6faa80786f659c699736