metrics code optimization (#11352)

This commit is contained in:
wxbty 2023-02-06 13:36:36 +08:00 committed by GitHub
parent bce9082e3b
commit cdc2d85f2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 365 additions and 284 deletions

View File

@ -17,13 +17,17 @@
package org.apache.dubbo.metrics.collector.stat;
import org.apache.dubbo.metrics.event.MetricsEvent;
import org.apache.dubbo.metrics.model.MethodMetric;
import org.apache.dubbo.rpc.Invocation;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
public interface MetricsStatHandler {
Map<MethodMetric, AtomicLong> get();
void increase(String applicationName, String interfaceName, String methodName, String group, String version);
void decrease(String applicationName, String interfaceName, String methodName, String group, String version);
MetricsEvent increase(String applicationName, Invocation invocation);
MetricsEvent decrease(String applicationName, Invocation invocation);
}

View File

@ -0,0 +1,34 @@
/*
* 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.event;
/**
* EmptyEvent, do nothing.
*/
public class EmptyEvent extends MetricsEvent {
private static final EmptyEvent empty = new EmptyEvent(new Object());
public EmptyEvent(Object source) {
super(source);
}
public static EmptyEvent instance() {
return empty;
}
}

View File

@ -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.metrics.event;
import org.apache.dubbo.metrics.listener.MetricsListener;
public interface MetricsEventMulticaster {
void addListener(MetricsListener listener);
void publishEvent(MetricsEvent event);
}

View File

@ -0,0 +1,61 @@
/*
* 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.event;
import org.apache.dubbo.metrics.listener.MetricsListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public final class SimpleMetricsEventMulticaster implements MetricsEventMulticaster {
@SuppressWarnings("java:S3077")
private static volatile SimpleMetricsEventMulticaster instance;
private SimpleMetricsEventMulticaster() {
}
private final List<MetricsListener> listeners = Collections.synchronizedList(new ArrayList<>());
public static SimpleMetricsEventMulticaster getInstance() {
if (instance == null) {
synchronized (SimpleMetricsEventMulticaster.class) {
if (instance == null) {
instance = new SimpleMetricsEventMulticaster();
}
}
}
return instance;
}
@Override
public void addListener(MetricsListener listener) {
listeners.add(listener);
}
@Override
public void publishEvent(MetricsEvent event) {
if (event instanceof EmptyEvent) {
return;
}
for (MetricsListener listener : listeners) {
listener.onEvent(event);
}
}
}

View File

@ -17,6 +17,9 @@
package org.apache.dubbo.metrics.model;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.RpcInvocation;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@ -30,6 +33,7 @@ import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY;
import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
import static org.apache.dubbo.rpc.support.RpcUtils.isGenericCall;
/**
* Metric class for method.
@ -45,12 +49,9 @@ public class MethodMetric {
}
public MethodMetric(String applicationName, String interfaceName, String methodName, String group, String version) {
public MethodMetric(String applicationName, Invocation invocation) {
this.applicationName = applicationName;
this.interfaceName = interfaceName;
this.methodName = methodName;
this.group = group;
this.version = version;
init(invocation);
}
public String getInterfaceName() {
@ -121,4 +122,33 @@ public class MethodMetric {
", version='" + version + '\'' +
'}';
}
private void init(Invocation invocation) {
String serviceUniqueName = invocation.getTargetServiceUniqueName();
String methodName = invocation.getMethodName();
if (invocation instanceof RpcInvocation
&& isGenericCall(((RpcInvocation) invocation).getParameterTypesDesc(), methodName)
&& invocation.getArguments() != null
&& invocation.getArguments().length == 3) {
methodName = ((String) invocation.getArguments()[0]).trim();
}
String group = null;
String interfaceAndVersion;
String[] arr = serviceUniqueName.split("/");
if (arr.length == 2) {
group = arr[0];
interfaceAndVersion = arr[1];
} else {
interfaceAndVersion = arr[0];
}
String[] ivArr = interfaceAndVersion.split(":");
String interfaceName = ivArr[0];
String version = ivArr.length == 2 ? ivArr[1] : null;
this.interfaceName = interfaceName;
this.methodName = methodName;
this.group = group;
this.version = version;
}
}

View File

@ -19,18 +19,21 @@ package org.apache.dubbo.metrics.collector;
import org.apache.dubbo.metrics.collector.stat.MetricsStatComposite;
import org.apache.dubbo.metrics.collector.stat.MetricsStatHandler;
import org.apache.dubbo.metrics.event.EmptyEvent;
import org.apache.dubbo.metrics.event.MetricsEvent;
import org.apache.dubbo.metrics.event.RequestEvent;
import org.apache.dubbo.metrics.event.SimpleMetricsEventMulticaster;
import org.apache.dubbo.metrics.listener.MetricsListener;
import org.apache.dubbo.metrics.model.MetricsKey;
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.rpc.Invocation;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
import java.util.function.Function;
import static org.apache.dubbo.metrics.model.MetricsCategory.REQUESTS;
@ -43,11 +46,12 @@ import static org.apache.dubbo.metrics.model.MetricsCategory.RT;
public class DefaultMetricsCollector implements MetricsCollector {
private AtomicBoolean collectEnabled = new AtomicBoolean(false);
private final List<MetricsListener> listeners = new ArrayList<>();
private final MetricsStatComposite stats;
private final SimpleMetricsEventMulticaster eventMulticaster;
public DefaultMetricsCollector() {
this.stats = new MetricsStatComposite( this);
this.stats = new MetricsStatComposite(this);
this.eventMulticaster = SimpleMetricsEventMulticaster.getInstance();
}
public void setCollectEnabled(Boolean collectEnabled) {
@ -58,80 +62,52 @@ public class DefaultMetricsCollector implements MetricsCollector {
return collectEnabled.get();
}
public void addListener(MetricsListener listener) {
listeners.add(listener);
public void increaseTotalRequests(String applicationName, Invocation invocation) {
increaseAndPublishEvent(applicationName, RequestEvent.Type.TOTAL, invocation);
}
public List<MetricsListener> getListener() {
return this.listeners;
public void increaseSucceedRequests(String applicationName, Invocation invocation) {
increaseAndPublishEvent(applicationName, RequestEvent.Type.SUCCEED, invocation);
}
public void increaseTotalRequests(String applicationName, String interfaceName, String methodName,
String group, String version) {
doExecute(RequestEvent.Type.TOTAL,statHandler-> {
statHandler.increase(applicationName, interfaceName, methodName, group, version);
});
public void increaseUnknownFailedRequests(String applicationName, Invocation invocation) {
increaseAndPublishEvent(applicationName, RequestEvent.Type.UNKNOWN_FAILED, invocation);
}
public void increaseSucceedRequests(String applicationName, String interfaceName, String methodName,
String group, String version) {
doExecute(RequestEvent.Type.SUCCEED,statHandler->{
statHandler.increase(applicationName, interfaceName, methodName, group, version);
});
public void businessFailedRequests(String applicationName, Invocation invocation) {
increaseAndPublishEvent(applicationName, RequestEvent.Type.BUSINESS_FAILED, invocation);
}
public void increaseUnknownFailedRequests(String applicationName, String interfaceName,
String methodName,
String group,
String version) {
doExecute(RequestEvent.Type.UNKNOWN_FAILED, statHandler->{
statHandler.increase(applicationName, interfaceName, methodName, group, version);
});
public void timeoutRequests(String applicationName, Invocation invocation) {
increaseAndPublishEvent(applicationName,RequestEvent.Type.REQUEST_TIMEOUT, invocation);
}
public void businessFailedRequests(String applicationName, String interfaceName, String methodName,
String group, String version) {
doExecute(RequestEvent.Type.BUSINESS_FAILED,statHandler->{
statHandler.increase(applicationName, interfaceName, methodName, group, version);
});
public void limitRequests(String applicationName, Invocation invocation) {
increaseAndPublishEvent(applicationName,RequestEvent.Type.REQUEST_LIMIT, invocation);
}
public void timeoutRequests(String applicationName, String interfaceName, String methodName, String group,
String version) {
doExecute(RequestEvent.Type.REQUEST_TIMEOUT,statHandler->{
statHandler.increase(applicationName, interfaceName, methodName, group, version);
});
public void increaseProcessingRequests(String applicationName, Invocation invocation) {
increaseAndPublishEvent(applicationName,RequestEvent.Type.PROCESSING, invocation);
}
public void limitRequests(String applicationName, String interfaceName, String methodName, String group, String version) {
doExecute(RequestEvent.Type.REQUEST_LIMIT,statHandler->{
statHandler.increase(applicationName, interfaceName, methodName, group, version);
});
public void decreaseProcessingRequests(String applicationName, Invocation invocation) {
decreaseAndPublishEvent(applicationName,RequestEvent.Type.PROCESSING, invocation);
}
public void increaseProcessingRequests(String applicationName, String interfaceName, String methodName,
String group, String version) {
doExecute(RequestEvent.Type.PROCESSING,statHandler-> {
statHandler.increase(applicationName, interfaceName, methodName, group, version);
});
public void totalFailedRequests(String applicationName, Invocation invocation) {
increaseAndPublishEvent(applicationName,RequestEvent.Type.TOTAL_FAILED, invocation);
}
public void decreaseProcessingRequests(String applicationName, String interfaceName, String methodName,
String group, String version) {
doExecute(RequestEvent.Type.PROCESSING,statHandler-> {
statHandler.decrease(applicationName, interfaceName, methodName, group, version);
});
private void increaseAndPublishEvent(String applicationName, RequestEvent.Type total, Invocation invocation) {
this.eventMulticaster.publishEvent(doExecute(total, statHandler -> statHandler.increase(applicationName,invocation)));
}
public void totalFailedRequests(String applicationName, String interfaceName, String methodName, String group,
String version) {
doExecute(RequestEvent.Type.TOTAL_FAILED,statHandler-> {
statHandler.increase(applicationName, interfaceName, methodName, group, version);
});
private void decreaseAndPublishEvent(String applicationName, RequestEvent.Type total, Invocation invocation) {
this.eventMulticaster.publishEvent(doExecute(total, statHandler -> statHandler.decrease(applicationName,invocation)));
}
public void addRT(String applicationName, String interfaceName, String methodName, String group, String version, Long responseTime) {
stats.addRT(applicationName, interfaceName, methodName, group, version, responseTime);
public void addRT(String applicationName,Invocation invocation, Long responseTime) {
this.eventMulticaster.publishEvent(stats.addRtAndRetrieveEvent(applicationName,invocation, responseTime));
}
@Override
@ -144,29 +120,29 @@ public class DefaultMetricsCollector implements MetricsCollector {
}
private void collectRequests(List<MetricSample> list) {
doExecute(RequestEvent.Type.TOTAL, MetricsStatHandler::get).filter(e->!e.isEmpty())
.ifPresent(map-> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUESTS, k.getTags(), REQUESTS, v::get))));
doCollect(RequestEvent.Type.TOTAL, MetricsStatHandler::get).filter(e -> !e.isEmpty())
.ifPresent(map -> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUESTS, k.getTags(), REQUESTS, v::get))));
doExecute(RequestEvent.Type.SUCCEED, MetricsStatHandler::get).filter(e->!e.isEmpty())
.ifPresent(map-> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUESTS_SUCCEED, k.getTags(), REQUESTS, v::get))));
doCollect(RequestEvent.Type.SUCCEED, MetricsStatHandler::get).filter(e -> !e.isEmpty())
.ifPresent(map -> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUESTS_SUCCEED, k.getTags(), REQUESTS, v::get))));
doExecute(RequestEvent.Type.UNKNOWN_FAILED, MetricsStatHandler::get).filter(e->!e.isEmpty())
.ifPresent(map-> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUESTS_FAILED, k.getTags(), REQUESTS, v::get))));
doCollect(RequestEvent.Type.UNKNOWN_FAILED, MetricsStatHandler::get).filter(e -> !e.isEmpty())
.ifPresent(map -> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUESTS_FAILED, k.getTags(), REQUESTS, v::get))));
doExecute(RequestEvent.Type.PROCESSING, MetricsStatHandler::get).filter(e->!e.isEmpty())
.ifPresent(map-> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUESTS_PROCESSING, k.getTags(), REQUESTS, v::get))));
doCollect(RequestEvent.Type.PROCESSING, MetricsStatHandler::get).filter(e -> !e.isEmpty())
.ifPresent(map -> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUESTS_PROCESSING, k.getTags(), REQUESTS, v::get))));
doExecute(RequestEvent.Type.BUSINESS_FAILED, MetricsStatHandler::get).filter(e->!e.isEmpty())
.ifPresent(map-> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUEST_BUSINESS_FAILED, k.getTags(), REQUESTS, v::get))));
doCollect(RequestEvent.Type.BUSINESS_FAILED, MetricsStatHandler::get).filter(e -> !e.isEmpty())
.ifPresent(map -> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUEST_BUSINESS_FAILED, k.getTags(), REQUESTS, v::get))));
doExecute(RequestEvent.Type.REQUEST_TIMEOUT, MetricsStatHandler::get).filter(e->!e.isEmpty())
.ifPresent(map-> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUESTS_TIMEOUT, k.getTags(), REQUESTS, v::get))));
doCollect(RequestEvent.Type.REQUEST_TIMEOUT, MetricsStatHandler::get).filter(e -> !e.isEmpty())
.ifPresent(map -> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUESTS_TIMEOUT, k.getTags(), REQUESTS, v::get))));
doExecute(RequestEvent.Type.REQUEST_LIMIT, MetricsStatHandler::get).filter(e->!e.isEmpty())
.ifPresent(map-> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUESTS_LIMIT, k.getTags(), REQUESTS, v::get))));
doCollect(RequestEvent.Type.REQUEST_LIMIT, MetricsStatHandler::get).filter(e -> !e.isEmpty())
.ifPresent(map -> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUESTS_LIMIT, k.getTags(), REQUESTS, v::get))));
doExecute(RequestEvent.Type.TOTAL_FAILED, MetricsStatHandler::get).filter(e->!e.isEmpty())
.ifPresent(map-> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUESTS_TOTAL_FAILED, k.getTags(), REQUESTS, v::get))));
doCollect(RequestEvent.Type.TOTAL_FAILED, MetricsStatHandler::get).filter(e -> !e.isEmpty())
.ifPresent(map -> map.forEach((k, v) -> list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_REQUESTS_TOTAL_FAILED, k.getTags(), REQUESTS, v::get))));
}
@ -184,19 +160,27 @@ public class DefaultMetricsCollector implements MetricsCollector {
list.add(new GaugeMetricSample(MetricsKey.PROVIDER_METRIC_RT_AVG, k.getTags(), RT, avg::get));
});
}
private <T> Optional<T> doExecute(RequestEvent.Type requestType, Function<MetricsStatHandler,T> statExecutor) {
private <
T> Optional<T> doCollect(RequestEvent.Type requestType, Function<MetricsStatHandler, T> statExecutor) {
if (isCollectEnabled()) {
MetricsStatHandler handler = stats.getHandler(requestType);
T result = statExecutor.apply(handler);
T result = statExecutor.apply(handler);
return Optional.ofNullable(result);
}
return Optional.empty();
}
private void doExecute(RequestEvent.Type requestType, Consumer<MetricsStatHandler> statExecutor) {
private MetricsEvent doExecute(RequestEvent.Type
requestType, Function<MetricsStatHandler, MetricsEvent> statExecutor) {
if (isCollectEnabled()) {
MetricsStatHandler handler = stats.getHandler(requestType);
statExecutor.accept(handler);
return statExecutor.apply(handler);
}
return EmptyEvent.instance();
}
public void addListener(MetricsListener listener) {
this.eventMulticaster.addListener(listener);
}
}

View File

@ -21,7 +21,10 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiConsumer;
import org.apache.dubbo.metrics.event.EmptyEvent;
import org.apache.dubbo.metrics.event.MetricsEvent;
import org.apache.dubbo.metrics.model.MethodMetric;
import org.apache.dubbo.rpc.Invocation;
public class DefaultMetricsStatHandler implements MetricsStatHandler {
@ -32,34 +35,34 @@ public class DefaultMetricsStatHandler implements MetricsStatHandler {
}
@Override
public void increase(String applicationName, String interfaceName, String methodName, String group, String version) {
this.doIncrExecute(applicationName, interfaceName,methodName,group,version);
public MetricsEvent increase(String applicationName, Invocation invocation) {
return this.doIncrExecute(applicationName, invocation);
}
public void decrease(String applicationName, String interfaceName, String methodName, String group, String version){
this.doDecrExecute(applicationName, interfaceName,methodName,group,version);
public MetricsEvent decrease(String applicationName, Invocation invocation) {
return this.doDecrExecute(applicationName,invocation);
}
protected void doExecute(String applicationName, String interfaceName, String methodName, String version,
BiConsumer<MethodMetric,Map<MethodMetric, AtomicLong>> execute, String group){
MethodMetric metric = new MethodMetric(applicationName, interfaceName, methodName, group, version);
execute.accept(metric,counts);
protected MetricsEvent doExecute(String applicationName, Invocation invocation, BiConsumer<MethodMetric, Map<MethodMetric, AtomicLong>> execute) {
MethodMetric metric = new MethodMetric(applicationName, invocation);
execute.accept(metric, counts);
this.doNotify(metric);
return this.retrieveMetricsEvent(metric);
}
protected void doIncrExecute(String applicationName, String interfaceName, String methodName, String group, String version){
this.doExecute(applicationName, interfaceName,methodName, version, (metric, counts)->{
protected MetricsEvent doIncrExecute(String applicationName, Invocation invocation) {
return this.doExecute(applicationName, invocation, (metric, counts) -> {
AtomicLong count = counts.computeIfAbsent(metric, k -> new AtomicLong(0L));
count.incrementAndGet();
}, group);
});
}
protected void doDecrExecute(String applicationName, String interfaceName, String methodName, String group, String version){
this.doExecute(applicationName, interfaceName,methodName, version, (metric, counts)->{
protected MetricsEvent doDecrExecute(String applicationName, Invocation invocation) {
return this.doExecute(applicationName, invocation, (metric, counts) -> {
AtomicLong count = counts.computeIfAbsent(metric, k -> new AtomicLong(0L));
count.decrementAndGet();
}, group);
});
}
@Override
@ -67,5 +70,7 @@ public class DefaultMetricsStatHandler implements MetricsStatHandler {
return counts;
}
public void doNotify(MethodMetric metric){}
public MetricsEvent retrieveMetricsEvent(MethodMetric metric) {
return EmptyEvent.instance();
}
}

View File

@ -19,13 +19,13 @@ package org.apache.dubbo.metrics.collector.stat;
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
import org.apache.dubbo.metrics.event.EmptyEvent;
import org.apache.dubbo.metrics.event.MetricsEvent;
import org.apache.dubbo.metrics.event.RTEvent;
import org.apache.dubbo.metrics.event.RequestEvent;
import org.apache.dubbo.metrics.listener.MetricsListener;
import org.apache.dubbo.metrics.model.MethodMetric;
import org.apache.dubbo.rpc.Invocation;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@ -41,11 +41,9 @@ public class MetricsStatComposite {
private final ConcurrentMap<MethodMetric, AtomicLong> avgRT = new ConcurrentHashMap<>();
private final ConcurrentMap<MethodMetric, AtomicLong> totalRT = new ConcurrentHashMap<>();
private final ConcurrentMap<MethodMetric, AtomicLong> rtCount = new ConcurrentHashMap<>();
private final List<MetricsListener> listeners;
private DefaultMetricsCollector collector;
public MetricsStatComposite(DefaultMetricsCollector collector) {
this.listeners = collector.getListener();
this.collector = collector;
this.init();
}
@ -78,87 +76,49 @@ public class MetricsStatComposite {
return this.rtCount;
}
public void addRT(String applicationName, String interfaceName, String methodName, String group, String version, Long responseTime) {
if (collector.isCollectEnabled()) {
MethodMetric metric = new MethodMetric(applicationName, interfaceName, methodName, group, version);
AtomicLong last = ConcurrentHashMapUtils.computeIfAbsent(lastRT, metric, k -> new AtomicLong());
last.set(responseTime);
LongAccumulator min = ConcurrentHashMapUtils.computeIfAbsent(minRT, metric, k -> new LongAccumulator(Long::min, Long.MAX_VALUE));
min.accumulate(responseTime);
LongAccumulator max = ConcurrentHashMapUtils.computeIfAbsent(maxRT, metric, k -> new LongAccumulator(Long::max, Long.MIN_VALUE));
max.accumulate(responseTime);
AtomicLong total = ConcurrentHashMapUtils.computeIfAbsent(totalRT, metric, k -> new AtomicLong());
total.addAndGet(responseTime);
AtomicLong count = ConcurrentHashMapUtils.computeIfAbsent(rtCount, metric, k -> new AtomicLong());
count.incrementAndGet();
ConcurrentHashMapUtils.computeIfAbsent(avgRT, metric, k -> new AtomicLong());
publishEvent(new RTEvent(metric, responseTime));
public MetricsEvent addRtAndRetrieveEvent(String applicationName, Invocation invocation, Long responseTime) {
if (!collector.isCollectEnabled()) {
return EmptyEvent.instance();
}
MethodMetric metric = new MethodMetric(applicationName, invocation);
AtomicLong last = ConcurrentHashMapUtils.computeIfAbsent(lastRT, metric, k -> new AtomicLong());
last.set(responseTime);
LongAccumulator min = ConcurrentHashMapUtils.computeIfAbsent(minRT, metric, k -> new LongAccumulator(Long::min, Long.MAX_VALUE));
min.accumulate(responseTime);
LongAccumulator max = ConcurrentHashMapUtils.computeIfAbsent(maxRT, metric, k -> new LongAccumulator(Long::max, Long.MIN_VALUE));
max.accumulate(responseTime);
AtomicLong total = ConcurrentHashMapUtils.computeIfAbsent(totalRT, metric, k -> new AtomicLong());
total.addAndGet(responseTime);
AtomicLong count = ConcurrentHashMapUtils.computeIfAbsent(rtCount, metric, k -> new AtomicLong());
count.incrementAndGet();
ConcurrentHashMapUtils.computeIfAbsent(avgRT, metric, k -> new AtomicLong());
return new RTEvent(metric, responseTime);
}
private void init() {
stats.put(RequestEvent.Type.TOTAL, new DefaultMetricsStatHandler() {
@Override
public void doNotify(MethodMetric metric) {
publishEvent(new RequestEvent(metric, RequestEvent.Type.TOTAL));
}
});
stats.put(RequestEvent.Type.SUCCEED, new DefaultMetricsStatHandler() {
@Override
public void doNotify(MethodMetric metric) {
publishEvent(new RequestEvent(metric, RequestEvent.Type.SUCCEED));
}
});
stats.put(RequestEvent.Type.UNKNOWN_FAILED, new DefaultMetricsStatHandler() {
@Override
public void doNotify(MethodMetric metric) {
publishEvent(new RequestEvent(metric, RequestEvent.Type.UNKNOWN_FAILED));
}
});
stats.put(RequestEvent.Type.BUSINESS_FAILED, new DefaultMetricsStatHandler() {
@Override
public void doNotify(MethodMetric metric) {
publishEvent(new RequestEvent(metric, RequestEvent.Type.BUSINESS_FAILED));
}
});
stats.put(RequestEvent.Type.TOTAL, buildMetricsStatHandler(RequestEvent.Type.TOTAL));
stats.put(RequestEvent.Type.SUCCEED, buildMetricsStatHandler(RequestEvent.Type.SUCCEED));
stats.put(RequestEvent.Type.UNKNOWN_FAILED, buildMetricsStatHandler(RequestEvent.Type.UNKNOWN_FAILED));
stats.put(RequestEvent.Type.BUSINESS_FAILED, buildMetricsStatHandler(RequestEvent.Type.BUSINESS_FAILED));
stats.put(RequestEvent.Type.PROCESSING, new DefaultMetricsStatHandler());
stats.put(RequestEvent.Type.REQUEST_LIMIT, new DefaultMetricsStatHandler() {
@Override
public void doNotify(MethodMetric metric) {
publishEvent(new RequestEvent(metric, RequestEvent.Type.REQUEST_LIMIT));
}
});
stats.put(RequestEvent.Type.REQUEST_TIMEOUT, new DefaultMetricsStatHandler() {
@Override
public void doNotify(MethodMetric metric) {
publishEvent(new RequestEvent(metric, RequestEvent.Type.REQUEST_TIMEOUT));
}
});
stats.put(RequestEvent.Type.TOTAL_FAILED, new DefaultMetricsStatHandler() {
@Override
public void doNotify(MethodMetric metric) {
publishEvent(new RequestEvent(metric, RequestEvent.Type.TOTAL_FAILED));
}
});
stats.put(RequestEvent.Type.REQUEST_LIMIT, buildMetricsStatHandler(RequestEvent.Type.REQUEST_LIMIT));
stats.put(RequestEvent.Type.REQUEST_TIMEOUT, buildMetricsStatHandler(RequestEvent.Type.REQUEST_TIMEOUT));
stats.put(RequestEvent.Type.TOTAL_FAILED, buildMetricsStatHandler(RequestEvent.Type.TOTAL_FAILED));
}
private void publishEvent(MetricsEvent event) {
for (MetricsListener listener : listeners) {
listener.onEvent(event);
}
private DefaultMetricsStatHandler buildMetricsStatHandler(RequestEvent.Type type) {
return new DefaultMetricsStatHandler() {
@Override
public MetricsEvent retrieveMetricsEvent(MethodMetric metric) {
return new RequestEvent(metric, type);
}
};
}
}

View File

@ -17,117 +17,71 @@
package org.apache.dubbo.metrics.filter;
import java.util.function.Supplier;
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
import java.util.function.Supplier;
import static org.apache.dubbo.common.constants.MetricsConstants.METRIC_FILTER_START_TIME;
import static org.apache.dubbo.rpc.support.RpcUtils.isGenericCall;
public class MetricsCollectExecutor {
private final DefaultMetricsCollector collector;
private final Invocation invocation;
private final String applicationName;
private String interfaceName;
private String methodName;
private String group;
private String version;
public MetricsCollectExecutor(String applicationName, DefaultMetricsCollector collector, Invocation invocation) {
init(invocation);
this.collector = collector;
this.invocation = invocation;
this.applicationName = applicationName;
}
public void beforeExecute() {
collector.increaseTotalRequests(applicationName, interfaceName, methodName, group, version);
collector.increaseProcessingRequests(applicationName, interfaceName, methodName, group, version);
public static void beforeExecute(String applicationName, DefaultMetricsCollector collector, Invocation invocation) {
collector.increaseTotalRequests(applicationName, invocation);
collector.increaseProcessingRequests(applicationName, invocation);
invocation.put(METRIC_FILTER_START_TIME, System.currentTimeMillis());
}
public void postExecute(Result result) {
public static void postExecute(String applicationName, DefaultMetricsCollector collector, Invocation invocation, Result result) {
if (result.hasException()) {
this.throwExecute(result.getException());
throwExecute(applicationName, collector, invocation, result.getException());
return;
}
collector.increaseSucceedRequests(applicationName, interfaceName, methodName, group, version);
endExecute();
collector.increaseSucceedRequests(applicationName, invocation);
endExecute(applicationName, collector, invocation);
}
public void throwExecute(Throwable throwable){
public static void throwExecute(String applicationName, DefaultMetricsCollector collector, Invocation invocation, Throwable throwable) {
if (throwable instanceof RpcException) {
RpcException rpcException = (RpcException)throwable;
RpcException rpcException = (RpcException) throwable;
switch (rpcException.getCode()) {
case RpcException.TIMEOUT_EXCEPTION:
collector.timeoutRequests(applicationName, interfaceName, methodName, group, version);
collector.timeoutRequests(applicationName, invocation);
break;
case RpcException.LIMIT_EXCEEDED_EXCEPTION:
collector.limitRequests(applicationName, interfaceName, methodName, group, version);
collector.limitRequests(applicationName, invocation);
break;
case RpcException.BIZ_EXCEPTION:
collector.businessFailedRequests(applicationName, interfaceName, methodName, group, version);
collector.businessFailedRequests(applicationName, invocation);
break;
default:
collector.increaseUnknownFailedRequests(applicationName, interfaceName, methodName, group, version);
collector.increaseUnknownFailedRequests(applicationName, invocation);
}
}
collector.totalFailedRequests(applicationName, interfaceName, methodName, group, version);
collector.totalFailedRequests(applicationName, invocation);
endExecute(()-> throwable instanceof RpcException && ((RpcException) throwable).isBiz());
endExecute(applicationName, collector, invocation, () -> throwable instanceof RpcException && ((RpcException) throwable).isBiz());
}
private void endExecute(){
this.endExecute(() -> true);
private static void endExecute(String applicationName, DefaultMetricsCollector collector, Invocation invocation) {
endExecute(applicationName, collector, invocation, () -> true);
}
private void endExecute(Supplier<Boolean> rtStat){
private static void endExecute(String applicationName, DefaultMetricsCollector collector, Invocation invocation, Supplier<Boolean> rtStat) {
if (rtStat.get()) {
Long endTime = System.currentTimeMillis();
Long beginTime = (Long) invocation.get(METRIC_FILTER_START_TIME);
Long rt = endTime - beginTime;
collector.addRT(applicationName, interfaceName, methodName, group, version, rt);
collector.addRT(applicationName, invocation, rt);
}
collector.decreaseProcessingRequests(applicationName, interfaceName, methodName, group, version);
collector.decreaseProcessingRequests(applicationName, invocation);
}
private void init(Invocation invocation) {
String serviceUniqueName = invocation.getTargetServiceUniqueName();
String methodName = invocation.getMethodName();
if (invocation instanceof RpcInvocation
&& isGenericCall(((RpcInvocation) invocation).getParameterTypesDesc(), methodName)
&& invocation.getArguments() != null
&& invocation.getArguments().length == 3) {
methodName = ((String) invocation.getArguments()[0]).trim();
}
String group = null;
String interfaceAndVersion;
String[] arr = serviceUniqueName.split("/");
if (arr.length == 2) {
group = arr[0];
interfaceAndVersion = arr[1];
} else {
interfaceAndVersion = arr[0];
}
String[] ivArr = interfaceAndVersion.split(":");
String interfaceName = ivArr[0];
String version = ivArr.length == 2 ? ivArr[1] : null;
this.interfaceName = interfaceName;
this.methodName = methodName;
this.group = group;
this.version = version;
}
}

View File

@ -27,8 +27,6 @@ import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ScopeModelAware;
import java.util.function.Consumer;
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
@Activate(group = PROVIDER, order = -1)
@ -50,28 +48,25 @@ public class MetricsFilter implements Filter, BaseFilter.Listener, ScopeModelAwa
if (collector == null || !collector.isCollectEnabled()) {
return invoker.invoke(invocation);
}
collect(invocation, MetricsCollectExecutor::beforeExecute);
MetricsCollectExecutor.beforeExecute(applicationModel.getApplicationName(), collector, invocation);
return invoker.invoke(invocation);
}
@Override
public void onResponse(Result result, Invoker<?> invoker, Invocation invocation) {
collect(invocation, collector->collector.postExecute(result));
if (collector == null || !collector.isCollectEnabled()) {
return;
}
MetricsCollectExecutor.postExecute(applicationModel.getApplicationName(), collector, invocation, result);
}
@Override
public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
collect(invocation, collector-> collector.throwExecute(t));
}
private void collect(Invocation invocation, Consumer<MetricsCollectExecutor> execute) {
if (collector == null || !collector.isCollectEnabled()) {
return;
}
MetricsCollectExecutor collectorExecutor = new MetricsCollectExecutor(applicationModel.getApplicationName(),
collector, invocation);
execute.accept(collectorExecutor);
MetricsCollectExecutor.throwExecute(applicationModel.getApplicationName(), collector, invocation, t);
}
}

View File

@ -17,16 +17,13 @@
package org.apache.dubbo.metrics.collector;
import org.apache.dubbo.metrics.model.MetricsKey;
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.MetricsConfig;
import org.apache.dubbo.config.nested.AggregationConfig;
import org.apache.dubbo.metrics.model.MetricsKey;
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.junit.jupiter.api.AfterEach;
@ -34,6 +31,12 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY;
@ -48,6 +51,7 @@ class AggregateMetricsCollectorTest {
private String methodName;
private String group;
private String version;
private RpcInvocation invocation;
@BeforeEach
public void setup() {
@ -72,6 +76,11 @@ class AggregateMetricsCollectorTest {
methodName = "mockMethod";
group = "mockGroup";
version = "1.0.0";
invocation = new RpcInvocation(methodName, interfaceName, "serviceKey", null, null);
invocation.setTargetServiceUniqueName(group + "/" + interfaceName + ":" + version);
invocation.setAttachment(GROUP_KEY, group);
invocation.setAttachment(VERSION_KEY, version);
}
@AfterEach
@ -81,12 +90,12 @@ class AggregateMetricsCollectorTest {
@Test
void testRequestsMetrics() {
AggregateMetricsCollector collector = new AggregateMetricsCollector(applicationModel);
String applicationName = applicationModel.getApplicationName();
defaultCollector.increaseTotalRequests(applicationName, interfaceName, methodName, group, version);
defaultCollector.increaseSucceedRequests(applicationName, interfaceName, methodName, group, version);
defaultCollector.increaseUnknownFailedRequests(applicationName, interfaceName, methodName, group, version);
defaultCollector.businessFailedRequests(applicationName, interfaceName,methodName,group,version);
AggregateMetricsCollector collector = new AggregateMetricsCollector(applicationModel);
defaultCollector.increaseTotalRequests(applicationName,invocation);
defaultCollector.increaseSucceedRequests(applicationName,invocation);
defaultCollector.increaseUnknownFailedRequests(applicationName,invocation);
defaultCollector.businessFailedRequests(applicationName,invocation);
List<MetricSample> samples = collector.collect();
for (MetricSample sample : samples) {
@ -115,7 +124,7 @@ class AggregateMetricsCollectorTest {
@Test
void testRTMetrics() {
AggregateMetricsCollector collector = new AggregateMetricsCollector(applicationModel);
defaultCollector.addRT(applicationModel.getApplicationName(), interfaceName, methodName, group, version, 10L);
defaultCollector.addRT(applicationModel.getApplicationName(),invocation, 10L);
List<MetricSample> samples = collector.collect();
for (MetricSample sample : samples) {

View File

@ -17,10 +17,6 @@
package org.apache.dubbo.metrics.metrics.collector;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
import org.apache.dubbo.metrics.event.MetricsEvent;
@ -30,6 +26,7 @@ import org.apache.dubbo.metrics.listener.MetricsListener;
import org.apache.dubbo.metrics.model.MetricsKey;
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.junit.jupiter.api.AfterEach;
@ -37,6 +34,13 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY;
@ -50,6 +54,7 @@ class DefaultMetricsCollectorTest {
private String methodName;
private String group;
private String version;
private RpcInvocation invocation;
@BeforeEach
public void setup() {
@ -64,6 +69,11 @@ class DefaultMetricsCollectorTest {
methodName = "mockMethod";
group = "mockGroup";
version = "1.0.0";
invocation = new RpcInvocation(methodName, interfaceName, "serviceKey", null, null);
invocation.setTargetServiceUniqueName(group + "/" + interfaceName + ":" + version);
invocation.setAttachment(GROUP_KEY, group);
invocation.setAttachment(VERSION_KEY, version);
}
@AfterEach
@ -76,10 +86,10 @@ class DefaultMetricsCollectorTest {
DefaultMetricsCollector collector = new DefaultMetricsCollector();
collector.setCollectEnabled(true);
String applicationName = applicationModel.getApplicationName();
collector.increaseTotalRequests(applicationName, interfaceName, methodName, group, version);
collector.increaseProcessingRequests(applicationName, interfaceName, methodName, group, version);
collector.increaseSucceedRequests(applicationName, interfaceName, methodName, group, version);
collector.increaseUnknownFailedRequests(applicationName, interfaceName, methodName, group, version);
collector.increaseTotalRequests(applicationName, invocation);
collector.increaseProcessingRequests(applicationName, invocation);
collector.increaseSucceedRequests(applicationName, invocation);
collector.increaseUnknownFailedRequests(applicationName, invocation);
List<MetricSample> samples = collector.collect();
for (MetricSample sample : samples) {
@ -95,7 +105,7 @@ class DefaultMetricsCollectorTest {
Assertions.assertEquals(supplier.get().longValue(), 1);
}
collector.decreaseProcessingRequests(applicationName, interfaceName, methodName, group, version);
collector.decreaseProcessingRequests(applicationName, invocation);
samples = collector.collect();
Map<String, Long> sampleMap = samples.stream().collect(Collectors.toMap(MetricSample::getName, k -> {
Number number = ((GaugeMetricSample) k).getSupplier().get();
@ -110,8 +120,8 @@ class DefaultMetricsCollectorTest {
DefaultMetricsCollector collector = new DefaultMetricsCollector();
collector.setCollectEnabled(true);
String applicationName = applicationModel.getApplicationName();
collector.addRT(applicationName, interfaceName, methodName, group, version, 10L);
collector.addRT(applicationName, interfaceName, methodName, group, version, 0L);
collector.addRT(applicationName, invocation, 10L);
collector.addRT(applicationName, invocation, 0L);
List<MetricSample> samples = collector.collect();
for (MetricSample sample : samples) {
@ -144,12 +154,12 @@ class DefaultMetricsCollectorTest {
collector.addListener(mockListener);
String applicationName = applicationModel.getApplicationName();
collector.increaseTotalRequests(applicationName, interfaceName, methodName, group, version);
collector.increaseTotalRequests(applicationName, invocation);
Assertions.assertNotNull(mockListener.getCurEvent());
Assertions.assertTrue(mockListener.getCurEvent() instanceof RequestEvent);
Assertions.assertEquals(((RequestEvent) mockListener.getCurEvent()).getType(), RequestEvent.Type.TOTAL);
collector.addRT(applicationName, interfaceName, methodName, group, version, 5L);
collector.addRT(applicationName, invocation, 5L);
Assertions.assertTrue(mockListener.getCurEvent() instanceof RTEvent);
Assertions.assertEquals(((RTEvent) mockListener.getCurEvent()).getRt(), 5L);
}

View File

@ -18,12 +18,15 @@
package org.apache.dubbo.metrics.metrics.model;
import org.apache.dubbo.metrics.model.MethodMetric;
import org.apache.dubbo.rpc.RpcInvocation;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_HOSTNAME;
@ -41,6 +44,7 @@ class MethodMetricTest {
private static String methodName;
private static String group;
private static String version;
private static RpcInvocation invocation;
@BeforeAll
public static void setup() {
@ -48,11 +52,15 @@ class MethodMetricTest {
methodName = "mockMethod";
group = "mockGroup";
version = "1.0.0";
invocation = new RpcInvocation(methodName, interfaceName, "serviceKey", null, null);
invocation.setTargetServiceUniqueName(group + "/" + interfaceName + ":" + version);
invocation.setAttachment(GROUP_KEY, group);
invocation.setAttachment(VERSION_KEY, version);
}
@Test
void test() {
MethodMetric metric = new MethodMetric(applicationName, interfaceName, methodName, group, version);
MethodMetric metric = new MethodMetric(applicationName, invocation);
Assertions.assertEquals(metric.getInterfaceName(), interfaceName);
Assertions.assertEquals(metric.getMethodName(), methodName);
Assertions.assertEquals(metric.getGroup(), group);