Added implementation for connector over http

This commit is contained in:
V Udayani
2022-10-26 13:55:36 +05:30
committed by aboyko
parent 103e225f7b
commit d70425d71e
9 changed files with 294 additions and 48 deletions

View File

@@ -31,8 +31,6 @@ public interface ActuatorConnection {
String getMetrics(String metric, Map<String, String> tags) throws IOException;
Map<?, ?> getStartup() throws IOException;
// String getGcPausesMetrics() throws IOException;
// String getMemoryMetrics(String metricName) throws IOException;
String getLiveMetrics(String metricName, String tags) throws IOException;
}

View File

@@ -76,6 +76,16 @@ public class HttpActuatorConnection implements ActuatorConnection {
public String getBeans() throws IOException {
return restTemplate.getForObject("/beans", String.class);
}
@Override
public String getLiveMetrics(String metricName, String tags) throws IOException {
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromPath("/metrics/"+metricName);
if (tags != null) {
uriBuilder.queryParam("tag", tags);
}
String url = uriBuilder.encode().toUriString();
return restTemplate.getForObject(url, String.class);
}
@Override
public String getMetrics(String metric, Map<String, String> tags) throws IOException {

View File

@@ -147,22 +147,24 @@ public class SpringProcessCommandHandler {
}
private CompletableFuture<Object> refresh(ExecuteCommandParams params) {
String processKey = getProcessKey(params);
String endpoint = getArgumentByKey(params, "endpoint");
if (processKey != null) {
connectorService.refreshProcess(processKey, endpoint, "", null);
SpringProcessParams springProcessParams = new SpringProcessParams();
springProcessParams.setProcessKey(getProcessKey(params));
springProcessParams.setEndpoint(getArgumentByKey(params, "endpoint"));
if (springProcessParams.getProcessKey() != null) {
connectorService.refreshProcess(springProcessParams);
}
return CompletableFuture.completedFuture(null);
}
private CompletableFuture<Object> refreshMetrics(ExecuteCommandParams params) {
String processKey = getProcessKey(params);
String endpoint = getArgumentByKey(params, "endpoint");
String metricName = getArgumentByKey(params, "metricName");
String tags = getArgumentByKey(params, "tags");
if (processKey != null) {
connectorService.refreshProcess(processKey, endpoint, metricName, tags);
SpringProcessParams springProcessParams = new SpringProcessParams();
springProcessParams.setProcessKey(getProcessKey(params));
springProcessParams.setEndpoint(getArgumentByKey(params, "endpoint"));
springProcessParams.setMetricName(getArgumentByKey(params, "metricName"));
springProcessParams.setTags(getArgumentByKey(params, "tags")); // Convert tags to a map
if (springProcessParams.getProcessKey() != null) {
connectorService.refreshProcess(springProcessParams);
}
return CompletableFuture.completedFuture(null);

View File

@@ -106,13 +106,45 @@ public class SpringProcessConnectorOverHttp implements SpringProcessConnector {
@Override
public SpringProcessGcPausesMetricsLiveData refreshGcPausesMetrics(SpringProcessLiveData current, String metricName, String tags)
throws Exception {
return null;
if (actuatorConnection != null) {
SpringProcessGcPausesMetricsLiveData liveData = new SpringProcessLiveDataExtractorOverHttp().retrieveLiveGcPausesMetricsData(getProcessType(), actuatorConnection, processID, processName, current, metricName, tags);
if (this.processID == null) {
this.processID = liveData.getProcessID();
}
if (this.processName == null) {
this.processName = liveData.getProcessName();
}
if (liveData != null && liveData.getGcPausesMetrics() != null && liveData.getGcPausesMetrics().length > 0) {
return liveData;
}
}
throw new Exception("no live gc pauses metric data received, lets try again");
}
@Override
public SpringProcessMemoryMetricsLiveData refreshMemoryMetrics(SpringProcessLiveData current, String metricName, String tags)
throws Exception {
return null;
if (actuatorConnection != null) {
SpringProcessMemoryMetricsLiveData liveData = new SpringProcessLiveDataExtractorOverHttp().retrieveLiveMemoryMetricsData(getProcessType(), actuatorConnection, processID, processName, current, metricName, tags);
if (this.processID == null) {
this.processID = liveData.getProcessID();
}
if (this.processName == null) {
this.processName = liveData.getProcessName();
}
if (liveData != null && liveData.getMemoryMetrics() != null && liveData.getMemoryMetrics().length > 0) {
return liveData;
}
}
throw new Exception("no live memory metrics data received, lets try again");
}

View File

@@ -99,17 +99,17 @@ public class SpringProcessConnectorService {
}
}
public void refreshProcess(String processKey, String endpoint, String metricName, String tags) {
log.info("refresh process: " + processKey);
public void refreshProcess(SpringProcessParams springProcessParams) {
log.info("refresh process: " + springProcessParams.getProcessKey());
SpringProcessConnector connector = this.connectors.get(processKey);
SpringProcessConnector connector = this.connectors.get(springProcessParams.getProcessKey());
if (connector != null) {
final ProgressTask progressTask = getProgressTask(
"spring-process-connector-service-refresh-data-" + processKey);
"spring-process-connector-service-refresh-data-" + springProcessParams.getProcessKey());
progressTask.progressBegin("Refresh", null);
scheduleRefresh(progressTask, processKey, connector, 0, TimeUnit.SECONDS, 0, endpoint, metricName, tags);
scheduleRefresh(progressTask, springProcessParams, connector, 0, TimeUnit.SECONDS, 0);
}
}
@@ -170,9 +170,9 @@ public class SpringProcessConnectorService {
connector.connect();
progressTask.progressDone();
refreshProcess(processKey, "", "", "");
refreshProcess(processKey, "metrics", "memory", "area:heap");
refreshProcess(processKey, "metrics", "gcPauses", "");
refreshProcess(new SpringProcessParams(processKey, "", "", ""));
refreshProcess(new SpringProcessParams(processKey, "metrics", "memory", "area:heap"));
refreshProcess(new SpringProcessParams(processKey, "metrics", "gcPauses", ""));
}
catch (Exception e) {
log.info("problem occured during process connect", e);
@@ -220,8 +220,11 @@ public class SpringProcessConnectorService {
}, delay, unit);
}
private void scheduleRefresh(ProgressTask progressTask, String processKey, SpringProcessConnector connector, long delay, TimeUnit unit, int retryNo, String endpoint, String metricName, String tags) {
String progressMessage = "Refreshing data from Spring process: " + processKey + " - retry no: " + retryNo;
private void scheduleRefresh(ProgressTask progressTask, SpringProcessParams springProcessParams, SpringProcessConnector connector, long delay, TimeUnit unit, int retryNo) {
String processKey = springProcessParams.getProcessKey();
String endpoint = springProcessParams.getEndpoint();
String metricName = springProcessParams.getMetricName();
String progressMessage = "Refreshing data from Spring process: " + processKey + " - retry no: " + retryNo;
log.info(progressMessage);
@@ -230,7 +233,7 @@ public class SpringProcessConnectorService {
try {
progressTask.progressEvent(progressMessage);
if(endpoint.equals("metrics") && metricName.equals("memory")) {
SpringProcessMemoryMetricsLiveData newMetricsLiveData = connector.refreshMemoryMetrics(this.liveDataProvider.getCurrent(processKey), metricName, tags);
SpringProcessMemoryMetricsLiveData newMetricsLiveData = connector.refreshMemoryMetrics(this.liveDataProvider.getCurrent(processKey), metricName, springProcessParams.getTags());
if (newMetricsLiveData != null) {
if (!this.liveDataProvider.addMemoryMetrics(processKey, newMetricsLiveData)) {
@@ -241,7 +244,7 @@ public class SpringProcessConnectorService {
}
} else if(endpoint.equals("metrics") && metricName.equals("gcPauses")) {
SpringProcessGcPausesMetricsLiveData newMetricsLiveData = connector.refreshGcPausesMetrics(this.liveDataProvider.getCurrent(processKey), metricName, tags);
SpringProcessGcPausesMetricsLiveData newMetricsLiveData = connector.refreshGcPausesMetrics(this.liveDataProvider.getCurrent(processKey), metricName, springProcessParams.getTags());
if (newMetricsLiveData != null) {
if (!this.liveDataProvider.addGcPausesMetrics(processKey, newMetricsLiveData)) {
@@ -269,8 +272,8 @@ public class SpringProcessConnectorService {
log.info("problem occured during process live data refresh", e);
if (retryNo < maxRetryCount && isKnownProcessKey(processKey)) {
scheduleRefresh(progressTask, processKey, connector, retryDelayInSeconds, TimeUnit.SECONDS,
retryNo + 1, endpoint, metricName, tags);
scheduleRefresh(progressTask, springProcessParams, connector, retryDelayInSeconds, TimeUnit.SECONDS,
retryNo + 1);
}
else {
progressTask.progressDone();

View File

@@ -12,6 +12,7 @@ package org.springframework.ide.vscode.boot.java.livehover.v2;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -23,6 +24,7 @@ import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -76,17 +78,11 @@ public class SpringProcessLiveDataExtractorOverHttp {
LiveBeansModel beans = getBeans(connection);
LiveMetricsModel metrics = getMetrics(connection);
StartupMetricsModel startup = getStartupMetrics(connection, currentData == null ? null : currentData.getStartupMetrics());
// LiveMemoryMetricsModel[] memoryMetrics = getMemoryMetrics(connection);
// LiveMemoryMetricsModel gcPausesMetrics = getGcPausesMetrics(connection);
if (contextPath == null) {
contextPath = getContextPath(environment);
}
// if (port == null) {
// port = getPort(connection, environment);
// }
return new SpringProcessLiveData(
processType,
processName,
@@ -103,8 +99,6 @@ public class SpringProcessLiveDataExtractorOverHttp {
metrics,
startup
);
// memoryMetrics,
// gcPausesMetrics);
}
catch (Exception e) {
log.error("error reading live data from: " + processID + " - " + processName, e);
@@ -113,6 +107,119 @@ public class SpringProcessLiveDataExtractorOverHttp {
return null;
}
/**
* @param processType
* @param processID if null, will be determined searching existing mbeans for that information (for remote processes via platform beans runtime name)
* @param processName if null, will be determined searching existing mbeans for that information (for remote processes inferring the java command from the system properties)
* @param currentData currently stored live data
* @param metricName
* @param tags
*/
public SpringProcessMemoryMetricsLiveData retrieveLiveMemoryMetricsData(ProcessType processType, ActuatorConnection connection, String processID, String processName,
SpringProcessLiveData currentData, String metricName, String tags) {
List<String> memoryMetrics = Arrays.asList("jvm.memory.committed", "jvm.memory.max");
List<LiveMemoryMetricsModel> memoryMetricsList = new ArrayList<>();
try {
if (processID == null) {
processID = connection.getProcessID();
}
if (processName == null) {
Properties systemProperties = connection.getSystemProperties();
if (systemProperties != null) {
String javaCommand = getJavaCommand(systemProperties);
processName = getProcessName(javaCommand);
}
}
LiveMemoryMetricsModel jvmMemUsedMetrics = getLiveMetrics(connection, "jvm.memory.used", tags);
if(jvmMemUsedMetrics != null) {
memoryMetricsList.add(jvmMemUsedMetrics);
Arrays.sort(jvmMemUsedMetrics.getAvailableTags()[0].getValues());
String[] memoryZones = jvmMemUsedMetrics.getAvailableTags()[0].getValues();
for(String zone : memoryZones) {
String tag = tags+",id:"+zone;
LiveMemoryMetricsModel metrics = getLiveMetrics(connection, "jvm.memory.used", tag );
if(metrics != null) {
memoryMetricsList.add(metrics);
}
}
for(String metric : memoryMetrics) {
LiveMemoryMetricsModel metrics = getLiveMetrics(connection, metric, tags );
if(metrics != null) {
memoryMetricsList.add(metrics);
}
}
}
LiveMemoryMetricsModel[] res = (LiveMemoryMetricsModel[]) memoryMetricsList.toArray(new LiveMemoryMetricsModel[memoryMetricsList.size()]);
return new SpringProcessMemoryMetricsLiveData(
processType,
processName,
processID,
res
);
}
catch (Exception e) {
log.error("error reading live metrics data from: " + processID + " - " + processName, e);
}
return null;
}
/**
* @param processType
* @param processID if null, will be determined searching existing mbeans for that information (for remote processes via platform beans runtime name)
* @param processName if null, will be determined searching existing mbeans for that information (for remote processes inferring the java command from the system properties)
* @param currentData currently stored live data
* @param metricName
* @param tags
*/
public SpringProcessGcPausesMetricsLiveData retrieveLiveGcPausesMetricsData(ProcessType processType, ActuatorConnection connection, String processID, String processName,
SpringProcessLiveData currentData, String metricName, String tags) {
List<LiveMemoryMetricsModel> memoryMetricsList = new ArrayList<>();
try {
if (processID == null) {
processID = connection.getProcessID();
}
if (processName == null) {
Properties systemProperties = connection.getSystemProperties();
if (systemProperties != null) {
String javaCommand = getJavaCommand(systemProperties);
processName = getProcessName(javaCommand);
}
}
LiveMemoryMetricsModel metrics = getLiveMetrics(connection, metricName, tags);
if(metrics != null) {
memoryMetricsList.add(metrics);
}
LiveMemoryMetricsModel[] res = (LiveMemoryMetricsModel[]) memoryMetricsList.toArray(new LiveMemoryMetricsModel[memoryMetricsList.size()]);
return new SpringProcessGcPausesMetricsLiveData(
processType,
processName,
processID,
res
);
}
catch (Exception e) {
log.error("error reading live metrics data from: " + processID + " - " + processName, e);
}
return null;
}
private LiveMetricsModel getMetrics(ActuatorConnection connection) {
return new LiveMetricsModel() {
@@ -275,5 +382,23 @@ public class SpringProcessLiveDataExtractorOverHttp {
public String getContextPath(String environment) throws Exception {
return environment != null ? LiveContextPathUtil.getContextPath("2.x", environment) : null;
}
public LiveMemoryMetricsModel getLiveMetrics(ActuatorConnection connection, String metricName, String tags) {
try {
String jvmMemUsedMetrics = connection.getLiveMetrics(metricName, tags);
if (jvmMemUsedMetrics instanceof String) {
return gson.fromJson((String)jvmMemUsedMetrics, LiveMemoryMetricsModel.class);
} else if(jvmMemUsedMetrics != null){
ObjectMapper mapper = new ObjectMapper();
return mapper.convertValue(jvmMemUsedMetrics, LiveMemoryMetricsModel.class);
}
} catch (IOException e) {
// ignore
} catch (Exception e) {
log.error("Error parsing beans", e);
}
return null;
}
}

View File

@@ -135,7 +135,8 @@ public class SpringProcessLiveDataExtractorOverJMX {
* @param processID if null, will be determined searching existing mbeans for that information (for remote processes via platform beans runtime name)
* @param processName if null, will be determined searching existing mbeans for that information (for remote processes inferring the java command from the system properties)
* @param currentData currently stored live data
* @param metricName
* @param metricName
* @param tags
*/
public SpringProcessMemoryMetricsLiveData retrieveLiveMemoryMetricsData(ProcessType processType, JMXConnector jmxConnector, String processID, String processName,
SpringProcessLiveData currentData, String metricName, String tags) {
@@ -161,8 +162,9 @@ public class SpringProcessLiveDataExtractorOverJMX {
LiveMemoryMetricsModel jvmMemUsedMetrics = getLiveMetrics(connection, domain, "jvm.memory.used", tags);
if(jvmMemUsedMetrics != null ) {
memoryMetricsList.add(jvmMemUsedMetrics);
Arrays.sort(jvmMemUsedMetrics.getAvailableTags()[0].getValues());
String[] memoryZones = jvmMemUsedMetrics.getAvailableTags()[0].getValues();
Arrays.sort(memoryZones);
for(String zone : memoryZones) {
String tag = tags+",id:"+zone;
LiveMemoryMetricsModel metrics = getLiveMetrics(connection, domain, "jvm.memory.used", tag );
@@ -200,6 +202,7 @@ public class SpringProcessLiveDataExtractorOverJMX {
* @param processName if null, will be determined searching existing mbeans for that information (for remote processes inferring the java command from the system properties)
* @param currentData currently stored live data
* @param metricName
* @param tags
*/
public SpringProcessGcPausesMetricsLiveData retrieveLiveGcPausesMetricsData(ProcessType processType, JMXConnector jmxConnector, String processID, String processName,
SpringProcessLiveData currentData, String metricName, String tags) {

View File

@@ -61,7 +61,7 @@ public class SpringProcessLiveDataProvider {
public boolean addMemoryMetrics(String processKey, SpringProcessMemoryMetricsLiveData liveData) {
SpringProcessMemoryMetricsLiveData oldData = this.memoryMetricsLiveData.putIfAbsent(processKey, liveData);
if (oldData == null) {
getClient().liveProcessMemoryMetricsDataUpdated(createProcessSummaryForMetrics(processKey, liveData.getProcessType().jsonName(),liveData.getProcessName(),liveData.getProcessID()));
getClient().liveProcessMemoryMetricsDataUpdated(createMemoryMetricsSummary(processKey, liveData));
}
return oldData == null;
}
@@ -69,7 +69,7 @@ public class SpringProcessLiveDataProvider {
public boolean addGcPausesMetrics(String processKey, SpringProcessGcPausesMetricsLiveData liveData) {
SpringProcessGcPausesMetricsLiveData oldData = this.gcPausesMetricsLiveData.putIfAbsent(processKey, liveData);
if (oldData == null) {
getClient().liveProcessGcPausesMetricsDataUpdated(createProcessSummaryForMetrics(processKey, liveData.getProcessType().jsonName(),liveData.getProcessName(),liveData.getProcessID()));
getClient().liveProcessGcPausesMetricsDataUpdated(createGcPausesMetricsSummary(processKey, liveData));
}
return oldData == null;
}
@@ -96,12 +96,12 @@ public class SpringProcessLiveDataProvider {
public void updateMemoryMetrics(String processKey, SpringProcessMemoryMetricsLiveData liveData) {
this.memoryMetricsLiveData.put(processKey, liveData);
getClient().liveProcessMemoryMetricsDataUpdated(createProcessSummaryForMetrics(processKey, liveData.getProcessType().jsonName(),liveData.getProcessName(),liveData.getProcessID()));
getClient().liveProcessMemoryMetricsDataUpdated(createMemoryMetricsSummary(processKey, liveData));
}
public void updateGcPausesMetrics(String processKey, SpringProcessGcPausesMetricsLiveData liveData) {
this.gcPausesMetricsLiveData.put(processKey, liveData);
getClient().liveProcessGcPausesMetricsDataUpdated(createProcessSummaryForMetrics(processKey, liveData.getProcessType().jsonName(),liveData.getProcessName(),liveData.getProcessID()));
getClient().liveProcessGcPausesMetricsDataUpdated(createGcPausesMetricsSummary(processKey, liveData));
}
public void addLiveDataChangeListener(SpringProcessLiveDataChangeListener listener) {
@@ -141,14 +141,22 @@ public class SpringProcessLiveDataProvider {
return p;
}
public static LiveProcessSummary createProcessSummaryForMetrics(String processKey, String processType, String processName,
String processID) {
public static LiveProcessSummary createMemoryMetricsSummary(String processKey, SpringProcessMemoryMetricsLiveData liveData) {
LiveProcessSummary p = new LiveProcessSummary();
p.setType(processType);
p.setType(liveData.getProcessType().jsonName());
p.setProcessKey(processKey);
p.setProcessName(processName);
p.setPid(processID);
p.setProcessName(liveData.getProcessName());
p.setPid(liveData.getProcessID());
return p;
}
public static LiveProcessSummary createGcPausesMetricsSummary(String processKey, SpringProcessGcPausesMetricsLiveData liveData) {
LiveProcessSummary p = new LiveProcessSummary();
p.setType(liveData.getProcessType().jsonName());
p.setProcessKey(processKey);
p.setProcessName(liveData.getProcessName());
p.setPid(liveData.getProcessID());
return p;
}
}

View File

@@ -0,0 +1,65 @@
/*******************************************************************************
* Copyright (c) 2019, 2020 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.livehover.v2;
/**
* @author V Udayani
*/
public class SpringProcessParams {
private String processKey;
private String endpoint;
private String metricName;
private String tags;
public SpringProcessParams() {
}
public SpringProcessParams(String processKey, String endpoint, String metricName, String tags) {
this.processKey = processKey;
this.endpoint = endpoint;
this.metricName = metricName;
this.tags = tags;
}
public String getProcessKey() {
return processKey;
}
public void setProcessKey(String processKey) {
this.processKey = processKey;
}
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public String getMetricName() {
return metricName;
}
public void setMetricName(String metricName) {
this.metricName = metricName;
}
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
}