Display indicator data in KEY, VALUE format (#12273)
* metrics default. * check style * test fail * metrics default update * qos * test * default metrics reporter * native image * If no specific metrics type is configured and there is no Prometheus dependency in the dependencies. * prometheus set * MeterRegistry dependency check * errorcode check fail * CHECKSTYLE * 1.null check 2.method replace * default metricsreport register * format response --------- Co-authored-by: Albumen Kevin <jhq0812@gmail.com> Co-authored-by: songxiaosheng <songxiaosheng@elastic.link>
This commit is contained in:
parent
50798b99c7
commit
1697a331c3
|
|
@ -19,6 +19,7 @@ package org.apache.dubbo.common.constants;
|
|||
public interface MetricsConstants {
|
||||
|
||||
String PROTOCOL_PROMETHEUS = "prometheus";
|
||||
String PROTOCOL_DEFAULT = "default";
|
||||
|
||||
String TAG_IP = "ip";
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
|
|||
import org.apache.dubbo.metrics.config.event.ConfigCenterEvent;
|
||||
import org.apache.dubbo.metrics.event.MetricsEventBus;
|
||||
import org.apache.dubbo.metrics.registry.event.RegistryEvent;
|
||||
import org.apache.dubbo.metrics.report.DefaultMetricsReporterFactory;
|
||||
import org.apache.dubbo.metrics.report.MetricsReporter;
|
||||
import org.apache.dubbo.metrics.report.MetricsReporterFactory;
|
||||
import org.apache.dubbo.metrics.service.MetricsServiceExporter;
|
||||
|
|
@ -92,11 +93,13 @@ import static java.lang.String.format;
|
|||
import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_SPLIT_PATTERN;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_METRICS_COLLECTOR_EXCEPTION;
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_FAILED_EXECUTE_DESTROY;
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_FAILED_INIT_CONFIG_CENTER;
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_FAILED_START_MODEL;
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_REFRESH_INSTANCE_ERROR;
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_REGISTER_INSTANCE_ERROR;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.PROTOCOL_DEFAULT;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.PROTOCOL_PROMETHEUS;
|
||||
import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
|
||||
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
|
||||
|
|
@ -369,25 +372,45 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
|
|||
}
|
||||
|
||||
private void initMetricsReporter() {
|
||||
if (!isSupportMetrics()) {
|
||||
return;
|
||||
}
|
||||
DefaultMetricsCollector collector =
|
||||
applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class);
|
||||
Optional<MetricsConfig> configOptional = configManager.getMetrics();
|
||||
|
||||
// TODO compatible with old usage of metrics, remove protocol check after new metrics is ready for use.
|
||||
if (!isSupportPrometheus()) {
|
||||
return;
|
||||
}
|
||||
//If no specific metrics type is configured and there is no Prometheus dependency in the dependencies.
|
||||
MetricsConfig metricsConfig = configOptional.orElse(new MetricsConfig(applicationModel));
|
||||
if (StringUtils.isBlank(metricsConfig.getProtocol())) {
|
||||
metricsConfig.setProtocol(PROTOCOL_PROMETHEUS);
|
||||
metricsConfig.setProtocol(isSupportPrometheus() ? PROTOCOL_PROMETHEUS : PROTOCOL_DEFAULT);
|
||||
}
|
||||
collector.setCollectEnabled(true);
|
||||
collector.collectApplication();
|
||||
collector.setThreadpoolCollectEnabled(Optional.ofNullable(metricsConfig.getEnableThreadpool()).orElse(true));
|
||||
MetricsReporterFactory metricsReporterFactory = getExtensionLoader(MetricsReporterFactory.class).getAdaptiveExtension();
|
||||
MetricsReporter metricsReporter = metricsReporterFactory.createMetricsReporter(metricsConfig.toUrl());
|
||||
MetricsReporter metricsReporter = null;
|
||||
try {
|
||||
metricsReporter = metricsReporterFactory.createMetricsReporter(metricsConfig.toUrl());
|
||||
} catch (IllegalStateException e) {
|
||||
if (e.getMessage().startsWith("No such extension org.apache.dubbo.metrics.report.MetricsReporterFactory")) {
|
||||
logger.warn(COMMON_METRICS_COLLECTOR_EXCEPTION, "", "", e.getMessage());
|
||||
return;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
metricsReporter.init();
|
||||
applicationModel.getBeanFactory().registerBean(metricsReporter);
|
||||
//If the protocol is not the default protocol, the default protocol is also initialized.
|
||||
if (!PROTOCOL_DEFAULT.equals(metricsConfig.getProtocol())) {
|
||||
DefaultMetricsReporterFactory defaultMetricsReporterFactory = new DefaultMetricsReporterFactory(applicationModel);
|
||||
MetricsReporter defaultMetricsReporter = defaultMetricsReporterFactory.createMetricsReporter(metricsConfig.toUrl());
|
||||
defaultMetricsReporter.init();
|
||||
applicationModel.getBeanFactory().registerBean(defaultMetricsReporter);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSupportMetrics() {
|
||||
return isClassPresent("io.micrometer.core.instrument.MeterRegistry");
|
||||
}
|
||||
|
||||
public static boolean isSupportPrometheus() {
|
||||
|
|
|
|||
|
|
@ -31,4 +31,8 @@ public interface MetricsReporter {
|
|||
void refreshData();
|
||||
|
||||
String getResponse();
|
||||
|
||||
default String getResponseWithName(String metricsName) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dubbo.metrics.report;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.Gauge;
|
||||
import io.micrometer.core.instrument.Tag;
|
||||
import io.micrometer.core.instrument.Timer;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class DefaultMetricsReporter extends AbstractMetricsReporter {
|
||||
|
||||
SimpleMeterRegistry meterRegistry = new SimpleMeterRegistry();
|
||||
|
||||
protected DefaultMetricsReporter(URL url, ApplicationModel applicationModel) {
|
||||
super(url, applicationModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResponse() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResponseWithName(String metricsName) {
|
||||
Map<String, List<Tag>> metricsTags = new HashMap<>();
|
||||
Map<String, Object> metricsValue = new HashMap<>();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
meterRegistry.getMeters().stream().filter(meter -> {
|
||||
if (meter == null || meter.getId() == null || meter.getId().getName() == null) {
|
||||
return false;
|
||||
}
|
||||
if (metricsName != null) {
|
||||
return meter.getId().getName().contains(metricsName);
|
||||
}
|
||||
return true;
|
||||
}).forEach(meter -> {
|
||||
Object value = null;
|
||||
if (meter instanceof Counter) {
|
||||
Counter counter = (Counter) meter;
|
||||
value = counter.count();
|
||||
}
|
||||
if (meter instanceof Gauge) {
|
||||
Gauge gauge = (Gauge) meter;
|
||||
value = gauge.value();
|
||||
}
|
||||
if (meter instanceof Timer) {
|
||||
Timer timer = (Timer) meter;
|
||||
value = timer.totalTime(TimeUnit.MILLISECONDS);
|
||||
}
|
||||
metricsTags.put(meter.getId().getName(), meter.getId().getTags());
|
||||
metricsValue.put(meter.getId().getName(), value);
|
||||
});
|
||||
metricsValue.forEach((key, value) -> {
|
||||
sb.append(key).append("{");
|
||||
List<Tag> tags = metricsTags.get(key);
|
||||
if (tags != null && tags.size() > 0) {
|
||||
tags.forEach(tag -> {
|
||||
sb.append(tag.getKey()).append("=").append(tag.getValue()).append(",");
|
||||
});
|
||||
}
|
||||
sb.append("} ").append(value).append(System.lineSeparator());
|
||||
});
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doInit() {
|
||||
addMeterRegistry(meterRegistry);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doDestroy() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dubbo.metrics.report;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
public class DefaultMetricsReporterFactory extends AbstractMetricsReporterFactory {
|
||||
private final ApplicationModel applicationModel;
|
||||
|
||||
public DefaultMetricsReporterFactory(ApplicationModel applicationModel) {
|
||||
super(applicationModel);
|
||||
this.applicationModel = applicationModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetricsReporter createMetricsReporter(URL url) {
|
||||
return new DefaultMetricsReporter(url, applicationModel);
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +1,3 @@
|
|||
default-collector=org.apache.dubbo.metrics.collector.DefaultMetricsCollector
|
||||
aggregateMetricsCollector=org.apache.dubbo.metrics.collector.AggregateMetricsCollector
|
||||
histogramMetricsCollector=org.apache.dubbo.metrics.collector.HistogramMetricsCollector
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
default=org.apache.dubbo.metrics.report.DefaultMetricsReporterFactory
|
||||
|
|
@ -109,7 +109,7 @@ public class PrometheusMetricsReporterCmd implements BaseCommand {
|
|||
private String getResponseByApplication(ApplicationModel applicationModel) {
|
||||
|
||||
String response = "MetricsReporter not init";
|
||||
MetricsReporter metricsReporter = applicationModel.getBeanFactory().getBean(MetricsReporter.class);
|
||||
MetricsReporter metricsReporter = applicationModel.getBeanFactory().getBean(PrometheusMetricsReporter.class);
|
||||
if (metricsReporter != null) {
|
||||
long begin = System.currentTimeMillis();
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
|
|
|||
|
|
@ -75,5 +75,10 @@
|
|||
<artifactId>dubbo-qos-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-default</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dubbo.qos.command.impl;
|
||||
|
||||
import org.apache.dubbo.common.utils.JsonUtils;
|
||||
import org.apache.dubbo.metrics.report.DefaultMetricsReporter;
|
||||
import org.apache.dubbo.metrics.report.MetricsReporter;
|
||||
import org.apache.dubbo.qos.api.BaseCommand;
|
||||
import org.apache.dubbo.qos.api.Cmd;
|
||||
import org.apache.dubbo.qos.api.CommandContext;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||
|
||||
import java.io.CharArrayReader;
|
||||
import java.io.IOException;
|
||||
import java.io.LineNumberReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Cmd(name = "metrics_default", summary = "display metrics information")
|
||||
public class DefaultMetricsReporterCmd implements BaseCommand {
|
||||
|
||||
public FrameworkModel frameworkModel;
|
||||
|
||||
public DefaultMetricsReporterCmd(FrameworkModel frameworkModel) {
|
||||
this.frameworkModel = frameworkModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(CommandContext commandContext, String[] args) {
|
||||
List<ApplicationModel> models = frameworkModel.getApplicationModels();
|
||||
String result = "There is no application with data";
|
||||
if (notSpecifyApplication(args)) {
|
||||
result = useFirst(models, result, null);
|
||||
} else if (args.length == 1) {
|
||||
result = specifyApplication(args[0], models, null);
|
||||
} else if (args.length == 2) {
|
||||
result = specifyApplication(args[0], models, args[1]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean notSpecifyApplication(String[] args) {
|
||||
return args == null || args.length == 0;
|
||||
}
|
||||
|
||||
private String useFirst(List<ApplicationModel> models, String result, String metricsName) {
|
||||
for (ApplicationModel model : models) {
|
||||
String current = getResponseByApplication(model, metricsName);
|
||||
if (current != null && getLineNumber(current) > 0) {
|
||||
result = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String specifyApplication(String appName, List<ApplicationModel> models, String metricsName) {
|
||||
if ("application_all".equals(appName)) {
|
||||
return allApplication(models);
|
||||
} else {
|
||||
return specifySingleApplication(appName, models, metricsName);
|
||||
}
|
||||
}
|
||||
|
||||
private String specifySingleApplication(String appName, List<ApplicationModel> models, String metricsName) {
|
||||
Optional<ApplicationModel> modelOptional = models.stream()
|
||||
.filter(applicationModel -> appName.equals(applicationModel.getApplicationName())).findFirst();
|
||||
if (modelOptional.isPresent()) {
|
||||
return getResponseByApplication(modelOptional.get(), metricsName);
|
||||
} else {
|
||||
return "Not exist application: " + appName;
|
||||
}
|
||||
}
|
||||
|
||||
private String allApplication(List<ApplicationModel> models) {
|
||||
Map<String, String> appResultMap = new HashMap<>();
|
||||
for (ApplicationModel model : models) {
|
||||
appResultMap.put(model.getApplicationName(), getResponseByApplication(model, null));
|
||||
}
|
||||
return JsonUtils.toJson(appResultMap);
|
||||
}
|
||||
|
||||
private String getResponseByApplication(ApplicationModel applicationModel, String metricsName) {
|
||||
String response = "DefaultMetricsReporter not init";
|
||||
MetricsReporter metricsReporter = applicationModel.getBeanFactory().getBean(DefaultMetricsReporter.class);
|
||||
if (metricsReporter != null) {
|
||||
metricsReporter.refreshData();
|
||||
response = metricsReporter.getResponseWithName(metricsName);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
private static long getLineNumber(String content) {
|
||||
LineNumberReader lnr = new LineNumberReader(new CharArrayReader(content.toCharArray()));
|
||||
try {
|
||||
lnr.skip(Long.MAX_VALUE);
|
||||
lnr.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
return lnr.getLineNumber();
|
||||
}
|
||||
}
|
||||
|
|
@ -37,3 +37,4 @@ serializeWarnedClasses=org.apache.dubbo.qos.command.impl.SerializeWarnedClasses
|
|||
getConfig=org.apache.dubbo.qos.command.impl.GetConfig
|
||||
getAddress=org.apache.dubbo.qos.command.impl.GetAddress
|
||||
gracefulShutdown=org.apache.dubbo.qos.command.impl.GracefulShutdown
|
||||
metrics_default=org.apache.dubbo.qos.command.impl.DefaultMetricsReporterCmd
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.apache.dubbo.qos.command.util;
|
|||
import org.apache.dubbo.qos.command.GreetingCommand;
|
||||
import org.apache.dubbo.qos.command.impl.ChangeTelnet;
|
||||
import org.apache.dubbo.qos.command.impl.CountTelnet;
|
||||
import org.apache.dubbo.qos.command.impl.DefaultMetricsReporterCmd;
|
||||
import org.apache.dubbo.qos.command.impl.DisableDetailProfiler;
|
||||
import org.apache.dubbo.qos.command.impl.DisableRouterSnapshot;
|
||||
import org.apache.dubbo.qos.command.impl.DisableSimpleProfiler;
|
||||
|
|
@ -125,6 +126,7 @@ class CommandHelperTest {
|
|||
expectedClasses.add(GetConfig.class);
|
||||
expectedClasses.add(GetAddress.class);
|
||||
expectedClasses.add(GracefulShutdown.class);
|
||||
expectedClasses.add(DefaultMetricsReporterCmd.class);
|
||||
assertThat(classes, containsInAnyOrder(expectedClasses.toArray(new Class<?>[0])));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue