diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/LiveMetricsModel.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/LiveMetricsModel.java index 52541a054..d33b80544 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/LiveMetricsModel.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/LiveMetricsModel.java @@ -2,6 +2,6 @@ package org.springframework.ide.vscode.boot.java.livehover.v2; public interface LiveMetricsModel { - RequestMappingMetrics getRequestMappingMetrics(LiveRequestMapping rm); + RequestMappingMetrics getRequestMappingMetrics(String[] strings, String[] array); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessLiveDataExtractorOverJMX.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessLiveDataExtractorOverJMX.java index 580f88d84..752b875b5 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessLiveDataExtractorOverJMX.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessLiveDataExtractorOverJMX.java @@ -126,15 +126,15 @@ public class SpringProcessLiveDataExtractorOverJMX { return new LiveMetricsModel() { @Override - public RequestMappingMetrics getRequestMappingMetrics(LiveRequestMapping rm) { + public RequestMappingMetrics getRequestMappingMetrics(String[] paths, String[] requestMethods) { try { List tags = new ArrayList<>(); - if (rm.getSplitPath().length == 0) { + if (paths.length == 0) { return null; } - tags.add("uri:" + rm.getSplitPath()[0]); - if (!rm.getRequestMethods().isEmpty()) { - tags.add("method:" + String.join(",", rm.getRequestMethods())); + tags.add("uri:" + String.join(",", paths)); + if (requestMethods.length > 0) { + tags.add("method:" + String.join(",", requestMethods)); } Object[] params = new Object[] {"http.server.requests", tags}; diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java index ec3089465..ca037e831 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -69,8 +70,7 @@ public class RequestMappingHoverProvider implements HoverProvider { List> val = getRequestMappingMethodFromRunningApp(annotation, processLiveData); if (!val.isEmpty()) { Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength()); - List urls = getUrls(val); - return assembleCodeLenses(hoverRange, urls); + return assembleCodeLenses(hoverRange, val); } } } @@ -133,21 +133,30 @@ public class RequestMappingHoverProvider implements HoverProvider { // return builder.build(); // } - private Collection assembleCodeLenses(Range range, List urls) { + private Collection assembleCodeLenses(Range range, List> data) { Collection lenses = new ArrayList<>(); - - if (urls != null) { - int limit = urls.size() <= CODE_LENS_LIMIT ? urls.size() : CODE_LENS_LIMIT; - for (int i = 0; i < limit; i++) { - CodeLens codeLens = createCodeLensForRequestMapping(range, urls.get(i)); - lenses.add(codeLens); - } - if (urls.size() > CODE_LENS_LIMIT) { - CodeLens codeLens = createCodeLensForRemaining(range, urls.size() - CODE_LENS_LIMIT); - lenses.add(codeLens); + + int remaining = 0; + + for (Tuple2 dataEntry : data) { + for (String url : getUrls(dataEntry)) { + if (lenses.size() <= CODE_LENS_LIMIT) { + Set requestMethods = dataEntry.getT1().getRequestMethods(); + RequestMappingMetrics metrics = dataEntry.getT2().getLiveMterics().getRequestMappingMetrics(new String[] { url }, requestMethods.toArray(new String[requestMethods.size()])); + CodeLens codeLens = createCodeLensForRequestMapping(range, url, metrics); + lenses.add(codeLens); + } else { + remaining++; + } } } + + if (remaining > 0) { + CodeLens codeLens = createCodeLensForRemaining(range, remaining); + lenses.add(codeLens); + } + return lenses; } @@ -223,29 +232,26 @@ public class RequestMappingHoverProvider implements HoverProvider { return false; } - private List getUrls(List> mappingMethods) throws Exception { + private List getUrls(Tuple2 mappingMethod) { List urls = new ArrayList<>(); - for (int i = 0; i < mappingMethods.size(); i++) { - Tuple2 mappingMethod = mappingMethods.get(i); - SpringProcessLiveData liveData = mappingMethod.getT2(); - String contextPath = liveData.getContextPath(); + SpringProcessLiveData liveData = mappingMethod.getT2(); + String contextPath = liveData.getContextPath(); - String urlScheme = liveData.getUrlScheme(); - String port = liveData.getPort(); - String host = liveData.getHost(); + String urlScheme = liveData.getUrlScheme(); + String port = liveData.getPort(); + String host = liveData.getHost(); - String[] paths = mappingMethod.getT1().getSplitPath(); - if (paths==null || paths.length==0) { - //Technically, this means the path 'predicate' is unconstrained, meaning any path matches. - //So this is not quite the same as the case where path=""... but... - //It is better for us to show one link where any path is allowed, versus showing no links where any link is allowed. - //So we'll pretend this is the same as path="" as that gives a working link. - paths = new String[] {""}; - } - for (String path : paths) { - String url = UrlUtil.createUrl(urlScheme, host, port, path, contextPath); - urls.add(url); - } + String[] paths = mappingMethod.getT1().getSplitPath(); + if (paths==null || paths.length==0) { + //Technically, this means the path 'predicate' is unconstrained, meaning any path matches. + //So this is not quite the same as the case where path=""... but... + //It is better for us to show one link where any path is allowed, versus showing no links where any link is allowed. + //So we'll pretend this is the same as path="" as that gives a working link. + paths = new String[] {""}; + } + for (String path : paths) { + String url = UrlUtil.createUrl(urlScheme, host, port, path, contextPath); + urls.add(url); } return urls; } @@ -279,7 +285,8 @@ public class RequestMappingHoverProvider implements HoverProvider { Renderable urlRenderables = Renderables.concat(renderableUrls); - RequestMappingMetrics metrics = liveData.getLiveMterics().getRequestMappingMetrics(requestMapping); + Set requestMethods = requestMapping.getRequestMethods(); + RequestMappingMetrics metrics = liveData.getLiveMterics().getRequestMappingMetrics(requestMapping.getSplitPath(), requestMethods.toArray(new String[requestMethods.size()])); if (metrics != null) { Renderable metricsRenderable = Renderables.concat( Renderables.bold("Count: " + metrics.getCallsCount() + " | Total Time: " + metrics.getTotalTime() + " | Max Time: " + metrics.getMaxTime()), @@ -307,14 +314,32 @@ public class RequestMappingHoverProvider implements HoverProvider { return new Hover(ImmutableList.of(Either.forLeft(contentVal.toString()))); } - private CodeLens createCodeLensForRequestMapping(Range range, String content) { + private CodeLens createCodeLensForRequestMapping(Range range, String content, RequestMappingMetrics metrics) { CodeLens codeLens = new CodeLens(); codeLens.setRange(range); Command cmd = new Command(); if (StringUtil.hasText(content)) { + codeLens.setData(content); - cmd.setTitle(content); + + StringBuilder codeLenseContent = new StringBuilder(content); + if (metrics != null) { + char timeUnitShort = metrics.getTimeUnit().name().charAt(0); + codeLenseContent.append('('); + codeLenseContent.append("Count="); + codeLenseContent.append(metrics.getCallsCount()); + codeLenseContent.append(' '); + codeLenseContent.append("Total="); + codeLenseContent.append(metrics.getTotalTime()); + codeLenseContent.append(timeUnitShort); + codeLenseContent.append(' '); + codeLenseContent.append("Max="); + codeLenseContent.append(metrics.getMaxTime()); + codeLenseContent.append(timeUnitShort); + codeLenseContent.append(')'); + } + cmd.setTitle(codeLenseContent.toString()); cmd.setCommand("sts.open.url"); cmd.setArguments(ImmutableList.of(content)); diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingLiveHoverTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingLiveHoverTest.java index 61528f459..e84b8ee77 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingLiveHoverTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingLiveHoverTest.java @@ -22,7 +22,6 @@ import org.springframework.context.annotation.Import; import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest; import org.springframework.ide.vscode.boot.bootiful.HoverTestConf; import org.springframework.ide.vscode.boot.java.livehover.v2.LiveMetricsModel; -import org.springframework.ide.vscode.boot.java.livehover.v2.LiveRequestMapping; import org.springframework.ide.vscode.boot.java.livehover.v2.RequestMappingMetrics; import org.springframework.ide.vscode.boot.java.livehover.v2.SpringProcessLiveData; import org.springframework.ide.vscode.boot.java.livehover.v2.SpringProcessLiveDataProvider; @@ -199,7 +198,7 @@ public class RequestMappingLiveHoverTest { .liveMetrics(new LiveMetricsModel() { @Override - public RequestMappingMetrics getRequestMappingMetrics(LiveRequestMapping rm) { + public RequestMappingMetrics getRequestMappingMetrics(String[] paths, String[] requestMethods) { return new RequestMappingMetrics() { @Override