From 5ae875d951d354a2f2d3316fc08cab406a3e947e Mon Sep 17 00:00:00 2001 From: namelessssssssssss <100946116+namelessssssssssss@users.noreply.github.com> Date: Wed, 9 Aug 2023 17:56:47 +0800 Subject: [PATCH] Add support for error code metrics (#12125) (#12661) * Add metrics support of error code * Add metrics support of error code * Add metrics support of error code * add license * remove hashcode override * Update DefaultSubDispatcher.java * Update ErrorCodeSampleTest.java * Update DefaultMetricsCollector.java --------- Co-authored-by: songxiaosheng --- .../common/constants/MetricsConstants.java | 2 + .../dubbo/common/logger/ListenableLogger.java | 32 ++++++++ .../dubbo/common/logger/LogListener.java | 27 +++++++ .../support/FailsafeErrorTypeAwareLogger.java | 59 ++++++++++++++- .../dubbo/metrics/model/ErrorCodeMetric.java | 51 +++++++++++++ .../dubbo/metrics/model/MetricsCategory.java | 1 + .../dubbo/metrics/model/ThreadPoolMetric.java | 1 + .../metrics/model/ThreadPoolRejectMetric.java | 2 + .../dubbo/metrics/model/key/MetricsKey.java | 3 + .../collector/DefaultMetricsCollector.java | 15 +++- .../ErrorCodeMetricsListenRegister.java | 41 ++++++++++ .../collector/sample/ErrorCodeSampler.java | 74 +++++++++++++++++++ .../sample/MetricsNameCountSampler.java | 69 +++++++++++++++++ .../sample/SimpleMetricsCountSampler.java | 1 + .../ThreadRejectMetricsCountSampler.java | 54 +++----------- .../metrics/event/DefaultSubDispatcher.java | 1 + .../model/sample/ErrorCodeSampleTest.java | 70 ++++++++++++++++++ 17 files changed, 455 insertions(+), 48 deletions(-) create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/logger/ListenableLogger.java create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/logger/LogListener.java create mode 100644 dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ErrorCodeMetric.java create mode 100644 dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/ErrorCodeMetricsListenRegister.java create mode 100644 dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/ErrorCodeSampler.java create mode 100644 dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/MetricsNameCountSampler.java create mode 100644 dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/metrics/model/sample/ErrorCodeSampleTest.java diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java index e7805eaa32..49bd9665c7 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java @@ -47,6 +47,8 @@ public interface MetricsConstants { String TAG_CHANGE_TYPE = "change.type"; + String TAG_ERROR_CODE = "error"; + String ENABLE_JVM_METRICS_KEY = "enable.jvm"; String AGGREGATION_COLLECTOR_KEY = "aggregation"; diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/ListenableLogger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/ListenableLogger.java new file mode 100644 index 0000000000..e0d3c76cae --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/ListenableLogger.java @@ -0,0 +1,32 @@ +/* + * 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.common.logger; + +/** + * Loggers that can register to listen to log messages. + */ +public interface ListenableLogger extends ErrorTypeAwareLogger{ + + /** + * Register a listener to this logger,and get notified when a log happens. + * + * @param listener log listener + */ + void registerListen(LogListener listener); + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LogListener.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LogListener.java new file mode 100644 index 0000000000..c0308e8a41 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LogListener.java @@ -0,0 +1,27 @@ +/* + * 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.common.logger; + +/** + * Log Listener, can registered to an {@link ListenableLogger}. + */ +public interface LogListener { + + void onMessage(String code, String msg); + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/support/FailsafeErrorTypeAwareLogger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/support/FailsafeErrorTypeAwareLogger.java index 8438c0ebfd..f5b7d5ef5a 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/support/FailsafeErrorTypeAwareLogger.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/support/FailsafeErrorTypeAwareLogger.java @@ -18,16 +18,22 @@ package org.apache.dubbo.common.logger.support; import org.apache.dubbo.common.Version; -import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.ListenableLogger; +import org.apache.dubbo.common.logger.LogListener; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.utils.NetUtils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; /** * A fail-safe (ignoring exception thrown by logger) wrapper of error type aware logger. */ -public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements ErrorTypeAwareLogger { +public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements ListenableLogger { /** * Template address for formatting. @@ -36,6 +42,16 @@ public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements Erro private static final Pattern ERROR_CODE_PATTERN = Pattern.compile("\\d+-\\d+"); + /** + * Listeners that listened to all Loggers. + */ + private static final List GLOBAL_LISTENERS = Collections.synchronizedList(new ArrayList<>()); + + /** + * Listeners that listened to this listener. + */ + private final AtomicReference> listeners = new AtomicReference<>(); + public FailsafeErrorTypeAwareLogger(Logger logger) { super(logger); } @@ -80,6 +96,7 @@ public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements Erro } try { + onEvent(code, msg); getLogger().warn(appendContextMessageWithInstructions(code, cause, extendedInformation, msg)); } catch (Throwable t) { // ignored. @@ -93,6 +110,7 @@ public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements Erro } try { + onEvent(code, msg); getLogger().warn(appendContextMessageWithInstructions(code, cause, extendedInformation, msg), e); } catch (Throwable t) { // ignored. @@ -106,6 +124,7 @@ public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements Erro } try { + onEvent(code, msg); getLogger().error(appendContextMessageWithInstructions(code, cause, extendedInformation, msg)); } catch (Throwable t) { // ignored. @@ -119,9 +138,45 @@ public class FailsafeErrorTypeAwareLogger extends FailsafeLogger implements Erro } try { + onEvent(code, msg); getLogger().error(appendContextMessageWithInstructions(code, cause, extendedInformation, msg), e); } catch (Throwable t) { // ignored. } } + + public static void registerGlobalListen(LogListener listener) { + GLOBAL_LISTENERS.add(listener); + } + + @Override + public void registerListen(LogListener listener) { + listeners.getAndUpdate(logListeners -> { + if (logListeners == null) { + logListeners = Collections.synchronizedList(new ArrayList<>()); + } + logListeners.add(listener); + return logListeners; + }); + } + + private void onEvent(String code, String msg) { + Optional.ofNullable(listeners.get()).ifPresent( + logListeners -> logListeners.forEach(logListener -> { + try { + logListener.onMessage(code, msg); + } catch (Exception e) { + // ignored. + } + })); + + GLOBAL_LISTENERS.forEach(logListener -> { + try { + logListener.onMessage(code, msg); + } catch (Exception e) { + // ignored. + } + }); + } + } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ErrorCodeMetric.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ErrorCodeMetric.java new file mode 100644 index 0000000000..6553761783 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ErrorCodeMetric.java @@ -0,0 +1,51 @@ +/* + * 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.model; + +import java.util.HashMap; +import java.util.Map; + +import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME; +import static org.apache.dubbo.common.constants.MetricsConstants.TAG_ERROR_CODE; + +/** + * ErrorCodeMetric. Provide tags for error code metrics. + */ +public class ErrorCodeMetric implements Metric { + + private final String errorCode; + + private final String applicationName; + + public ErrorCodeMetric(String applicationName, String errorCode) { + this.errorCode = errorCode; + this.applicationName = applicationName; + } + + @Override + public Map getTags() { + Map tags = new HashMap<>(); + tags.put(TAG_ERROR_CODE, errorCode); + tags.put(TAG_APPLICATION_NAME, applicationName); + return tags; + } + + public String getErrorCode() { + return errorCode; + } +} diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MetricsCategory.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MetricsCategory.java index e071a7ddff..66d5d8b492 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MetricsCategory.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MetricsCategory.java @@ -29,5 +29,6 @@ public enum MetricsCategory { REGISTRY, METADATA, THREAD_POOL, + ERROR_CODE, NETTY, } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ThreadPoolMetric.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ThreadPoolMetric.java index 002653359b..c45815f106 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ThreadPoolMetric.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ThreadPoolMetric.java @@ -85,6 +85,7 @@ public class ThreadPoolMetric implements Metric{ return Objects.hash(applicationName, threadPoolName); } + @Override public Map getTags() { Map tags = new HashMap<>(); tags.put(TAG_IP, getLocalHost()); diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ThreadPoolRejectMetric.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ThreadPoolRejectMetric.java index 8706070847..c2daf4b5a9 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ThreadPoolRejectMetric.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ThreadPoolRejectMetric.java @@ -30,6 +30,7 @@ import static org.apache.dubbo.common.constants.MetricsConstants.TAG_HOSTNAME; import static org.apache.dubbo.common.constants.MetricsConstants.TAG_IP; public class ThreadPoolRejectMetric implements Metric{ + private String applicationName; private String threadPoolName; @@ -69,6 +70,7 @@ public class ThreadPoolRejectMetric implements Metric{ return Objects.hash(applicationName, threadPoolName); } + @Override public Map getTags() { Map tags = new HashMap<>(); tags.put(TAG_IP, getLocalHost()); diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKey.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKey.java index 5f0c003876..d426898255 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKey.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKey.java @@ -124,6 +124,9 @@ public enum MetricsKey { // consumer metrics key INVOKER_NO_AVAILABLE_COUNT("dubbo.consumer.invoker.no.available.count", "Request Throw No Invoker Available Exception Count"), + // count the number of occurrences of each error code + ERROR_CODE_COUNT("dubbo.error.code.count","The Count Of Occurrences for Each Error Code"), + // netty metrics key NETTY_ALLOCATOR_HEAP_MEMORY_USED("netty.allocator.memory.used", "Netty Allocator Memory Used"), NETTY_ALLOCATOR_DIRECT_MEMORY_USED("netty.allocator.direct.memory.used", "Netty Allocator Direct Memory Used"), diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/DefaultMetricsCollector.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/DefaultMetricsCollector.java index 4581141771..39376d344f 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/DefaultMetricsCollector.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/DefaultMetricsCollector.java @@ -20,10 +20,11 @@ package org.apache.dubbo.metrics.collector; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.metrics.DefaultConstants; -import org.apache.dubbo.metrics.collector.sample.MetricsCountSampleConfigurer; +import org.apache.dubbo.metrics.collector.sample.ErrorCodeSampler; import org.apache.dubbo.metrics.collector.sample.MetricsSampler; import org.apache.dubbo.metrics.collector.sample.SimpleMetricsCountSampler; import org.apache.dubbo.metrics.collector.sample.ThreadPoolMetricsSampler; +import org.apache.dubbo.metrics.collector.sample.MetricsCountSampleConfigurer; import org.apache.dubbo.metrics.data.BaseStatComposite; import org.apache.dubbo.metrics.data.MethodStatComposite; import org.apache.dubbo.metrics.data.RtStatComposite; @@ -53,9 +54,15 @@ public class DefaultMetricsCollector extends CombMetricsCollector private boolean collectEnabled = false; private volatile boolean threadpoolCollectEnabled = false; + private final ThreadPoolMetricsSampler threadPoolSampler = new ThreadPoolMetricsSampler(this); + + private final ErrorCodeSampler errorCodeSampler; + private String applicationName; + private final ApplicationModel applicationModel; + private final List samplers = new ArrayList<>(); public DefaultMetricsCollector(ApplicationModel applicationModel) { @@ -74,8 +81,9 @@ public class DefaultMetricsCollector extends CombMetricsCollector } }); super.setEventMulticaster(new DefaultSubDispatcher(this)); - samplers.add(applicationSampler); - samplers.add(threadPoolSampler); + this.samplers.add(applicationSampler); + this.samplers.add(threadPoolSampler); + this.errorCodeSampler = new ErrorCodeSampler(this); this.applicationModel = applicationModel; } @@ -99,6 +107,7 @@ public class DefaultMetricsCollector extends CombMetricsCollector this.collectEnabled = collectEnabled; } + @Override public boolean isCollectEnabled() { return collectEnabled; } diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/ErrorCodeMetricsListenRegister.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/ErrorCodeMetricsListenRegister.java new file mode 100644 index 0000000000..82860dab51 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/ErrorCodeMetricsListenRegister.java @@ -0,0 +1,41 @@ +/* + * 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.collector.sample; + +import org.apache.dubbo.common.logger.LogListener; +import org.apache.dubbo.common.logger.support.FailsafeErrorTypeAwareLogger; +import org.apache.dubbo.metrics.model.key.MetricsKey; + +/** + * Listen the log of all {@link FailsafeErrorTypeAwareLogger} instances, and add error code count to {@link ErrorCodeSampler}. + */ +public class ErrorCodeMetricsListenRegister implements LogListener { + + private final ErrorCodeSampler errorCodeSampler; + + public ErrorCodeMetricsListenRegister(ErrorCodeSampler errorCodeSampler){ + FailsafeErrorTypeAwareLogger.registerGlobalListen(this); + this.errorCodeSampler = errorCodeSampler; + this.errorCodeSampler.addMetricName(MetricsKey.ERROR_CODE_COUNT.getName()); + } + + @Override + public void onMessage(String code, String msg) { + errorCodeSampler.inc(code, MetricsKey.ERROR_CODE_COUNT.getName()); + } +} diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/ErrorCodeSampler.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/ErrorCodeSampler.java new file mode 100644 index 0000000000..86fdf79237 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/ErrorCodeSampler.java @@ -0,0 +1,74 @@ +/* + * 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.collector.sample; + +import org.apache.dubbo.metrics.collector.DefaultMetricsCollector; +import org.apache.dubbo.metrics.model.ErrorCodeMetric; +import org.apache.dubbo.metrics.model.MetricsCategory; +import org.apache.dubbo.metrics.model.key.MetricsKey; +import org.apache.dubbo.metrics.model.sample.CounterMetricSample; +import org.apache.dubbo.metrics.model.sample.MetricSample; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + +/** + * This sampler is used to count the number of occurrences of each error code. + */ +public class ErrorCodeSampler extends MetricsNameCountSampler { + + private final ErrorCodeMetricsListenRegister register; + + /** + * Map + */ + private final Map errorCodeMetrics; + + public ErrorCodeSampler(DefaultMetricsCollector collector) { + super(collector, MetricsCategory.ERROR_CODE, MetricsKey.ERROR_CODE_COUNT); + this.register = new ErrorCodeMetricsListenRegister(this); + this.errorCodeMetrics = new ConcurrentHashMap<>(); + } + + @Override + protected MetricSample provideMetricsSample(ErrorCodeMetric metric, AtomicLong count, MetricsKey metricsKey, MetricsCategory metricsCategory) { + return new CounterMetricSample<>( + metricsKey.getNameByType(metric.getErrorCode()), + metricsKey.getDescription(), + metric.getTags(), + metricsCategory, + count + ); + } + + @Override + protected void countConfigure(MetricsCountSampleConfigurer sampleConfigure) { + sampleConfigure.configureMetrics(configure -> { + + String errorCode = configure.getSource(); + ErrorCodeMetric metric = errorCodeMetrics.get(errorCode); + + if (metric == null) { + metric = new ErrorCodeMetric(collector.getApplicationModel().getApplicationName(), errorCode); + errorCodeMetrics.put(errorCode, metric); + } + return metric; + }); + } +} diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/MetricsNameCountSampler.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/MetricsNameCountSampler.java new file mode 100644 index 0000000000..ebf7e437ce --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/MetricsNameCountSampler.java @@ -0,0 +1,69 @@ +/* + * 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.collector.sample; + +import org.apache.dubbo.common.utils.ConcurrentHashSet; +import org.apache.dubbo.metrics.collector.DefaultMetricsCollector; +import org.apache.dubbo.metrics.model.Metric; +import org.apache.dubbo.metrics.model.MetricsCategory; +import org.apache.dubbo.metrics.model.key.MetricsKey; +import org.apache.dubbo.metrics.model.sample.MetricSample; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; + +public abstract class MetricsNameCountSampler extends SimpleMetricsCountSampler { + + protected final DefaultMetricsCollector collector; + + protected final Set metricNames = new ConcurrentHashSet<>(); + + protected final MetricsCategory metricsCategory; + + protected final MetricsKey metricsKey; + + public MetricsNameCountSampler(DefaultMetricsCollector collector,MetricsCategory metricsCategory,MetricsKey metricsKey) { + this.metricsCategory = metricsCategory; + this.metricsKey = metricsKey; + this.collector = collector; + this.collector.addSampler(this); + } + + public void addMetricName(K name) { + this.metricNames.add(name); + } + + @Override + public List sample() { + List metricSamples = new ArrayList<>(); + metricNames.forEach(name -> collect(metricSamples, name)); + return metricSamples; + } + + private void collect(List samples, K metricName) { + getCount(metricName) + .filter(e -> !e.isEmpty()) + .ifPresent(map -> map.forEach((k, v) -> + samples.add(provideMetricsSample(k,v,metricsKey,metricsCategory)))); + } + + protected abstract MetricSample provideMetricsSample(M metric,AtomicLong count,MetricsKey metricsKey,MetricsCategory metricsCategory); + +} diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/SimpleMetricsCountSampler.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/SimpleMetricsCountSampler.java index 9c31973740..666af13f30 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/SimpleMetricsCountSampler.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/SimpleMetricsCountSampler.java @@ -36,6 +36,7 @@ public abstract class SimpleMetricsCountSampler implements MetricsCountSampler { private final ConcurrentMap EMPTY_COUNT = new ConcurrentHashMap<>(); + private final Map> metricCounter = new ConcurrentHashMap<>(); @Override diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/ThreadRejectMetricsCountSampler.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/ThreadRejectMetricsCountSampler.java index e9e55f9448..2638777574 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/ThreadRejectMetricsCountSampler.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/ThreadRejectMetricsCountSampler.java @@ -16,65 +16,33 @@ */ package org.apache.dubbo.metrics.collector.sample; -import org.apache.dubbo.common.utils.ConcurrentHashSet; + import org.apache.dubbo.metrics.collector.DefaultMetricsCollector; -import org.apache.dubbo.metrics.model.Metric; import org.apache.dubbo.metrics.model.MetricsCategory; -import org.apache.dubbo.metrics.model.key.MetricsKey; import org.apache.dubbo.metrics.model.ThreadPoolRejectMetric; +import org.apache.dubbo.metrics.model.key.MetricsKey; import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; import org.apache.dubbo.metrics.model.sample.MetricSample; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; + import java.util.concurrent.atomic.AtomicLong; -import java.util.function.ToDoubleFunction; + import static org.apache.dubbo.metrics.model.MetricsCategory.THREAD_POOL; -public class ThreadRejectMetricsCountSampler extends SimpleMetricsCountSampler { +public class ThreadRejectMetricsCountSampler extends MetricsNameCountSampler { - private final DefaultMetricsCollector collector; - - private final Set metricNames = new ConcurrentHashSet<>(); public ThreadRejectMetricsCountSampler(DefaultMetricsCollector collector) { - this.collector = collector; - this.collector.addSampler(this); - } - - public void addMetricName(String name){ - this.metricNames.add(name); + super(collector, THREAD_POOL,MetricsKey.THREAD_POOL_THREAD_REJECT_COUNT); } @Override - public List sample() { - List metricSamples = new ArrayList<>(); - metricNames.stream().forEach(name->collect(metricSamples,name)); - return metricSamples; - } - - - private void collect(List list, String metricName) { - count(list, metricName, MetricsKey.THREAD_POOL_THREAD_REJECT_COUNT); - } - - private void count(List list, String metricName, MetricsKey metricsKey) { - getCount(metricName).filter(e -> !e.isEmpty()) - .ifPresent(map -> map.forEach((k, v) -> - list.add(getGaugeMetricSample(metricsKey, k, THREAD_POOL, v, AtomicLong::get)))); - } - - private GaugeMetricSample getGaugeMetricSample(MetricsKey metricsKey, - ThreadPoolRejectMetric methodMetric, - MetricsCategory metricsCategory, - T value, - ToDoubleFunction apply) { + protected MetricSample provideMetricsSample(ThreadPoolRejectMetric metric, AtomicLong count, MetricsKey metricsKey, MetricsCategory metricsCategory) { return new GaugeMetricSample<>( - metricsKey.getNameByType(methodMetric.getThreadPoolName()), + metricsKey.getNameByType(metric.getThreadPoolName()), metricsKey.getDescription(), - methodMetric.getTags(), + metric.getTags(), metricsCategory, - value, - apply); + count, + AtomicLong::get); } @Override diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/DefaultSubDispatcher.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/DefaultSubDispatcher.java index 807736709b..d9a88c466d 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/DefaultSubDispatcher.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/DefaultSubDispatcher.java @@ -96,6 +96,7 @@ public final class DefaultSubDispatcher extends SimpleMetricsEventMulticaster { MetricsSupport.incrAndAddRt(targetKey, dynamicPlaceType, (MethodMetricsCollector) collector, event); } ))); + } } diff --git a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/metrics/model/sample/ErrorCodeSampleTest.java b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/metrics/model/sample/ErrorCodeSampleTest.java new file mode 100644 index 0000000000..89b2ca5fa3 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/metrics/model/sample/ErrorCodeSampleTest.java @@ -0,0 +1,70 @@ +/* + * 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.metrics.model.sample; + +import org.apache.dubbo.common.utils.Assert; +import org.apache.dubbo.common.utils.ReflectionUtils; +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.metrics.collector.DefaultMetricsCollector; +import org.apache.dubbo.metrics.collector.sample.ErrorCodeMetricsListenRegister; +import org.apache.dubbo.metrics.collector.sample.ErrorCodeSampler; +import org.apache.dubbo.metrics.model.sample.CounterMetricSample; +import org.apache.dubbo.metrics.model.sample.MetricSample; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; + +public class ErrorCodeSampleTest { + + @Test + void testErrorCodeMetric() { + FrameworkModel frameworkModel = FrameworkModel.defaultModel(); + ApplicationModel applicationModel = frameworkModel.newApplication(); + + ApplicationConfig applicationConfig = new ApplicationConfig(); + applicationConfig.setName("MyApplication1"); + + applicationModel.getApplicationConfigManager().setApplication(applicationConfig); + + DefaultMetricsCollector defaultMetricsCollector = new DefaultMetricsCollector(applicationModel); + defaultMetricsCollector.setCollectEnabled(true); + + ErrorCodeSampler sampler = (ErrorCodeSampler) ReflectionUtils.getField(defaultMetricsCollector, "errorCodeSampler"); + + ErrorCodeMetricsListenRegister register = (ErrorCodeMetricsListenRegister) ReflectionUtils.getField(sampler, "register"); + + register.onMessage("0-1", null); + register.onMessage("0-1", null); + register.onMessage("0-2", null); + register.onMessage("0-2", null); + register.onMessage("1-2", null); + register.onMessage("1-2", null); + register.onMessage("1-3", null); + register.onMessage("1-3", null); + + List samples = defaultMetricsCollector.collect(); + + Assert.assertTrue(samples.size() == 4,"Wrong number of samples."); + samples.forEach(metricSample -> Assert.assertTrue(((AtomicLong)((CounterMetricSample)metricSample).getValue()).get() == 2L,"Sample count error.")); + + System.out.println(samples); + } +}