Skip to content

Commit

Permalink
Add support for error code metrics (#12125) (#12661)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
namelessssssssssss and songxiaosheng authored Aug 9, 2023
1 parent 04f3fe7 commit 5ae875d
Show file tree
Hide file tree
Showing 17 changed files with 455 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
Original file line number Diff line number Diff line change
@@ -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);

}
Original file line number Diff line number Diff line change
@@ -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);

}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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<LogListener> GLOBAL_LISTENERS = Collections.synchronizedList(new ArrayList<>());

/**
* Listeners that listened to this listener.
*/
private final AtomicReference<List<LogListener>> listeners = new AtomicReference<>();

public FailsafeErrorTypeAwareLogger(Logger logger) {
super(logger);
}
Expand Down Expand Up @@ -80,6 +96,7 @@ public void warn(String code, String cause, String extendedInformation, String m
}

try {
onEvent(code, msg);
getLogger().warn(appendContextMessageWithInstructions(code, cause, extendedInformation, msg));
} catch (Throwable t) {
// ignored.
Expand All @@ -93,6 +110,7 @@ public void warn(String code, String cause, String extendedInformation, String m
}

try {
onEvent(code, msg);
getLogger().warn(appendContextMessageWithInstructions(code, cause, extendedInformation, msg), e);
} catch (Throwable t) {
// ignored.
Expand All @@ -106,6 +124,7 @@ public void error(String code, String cause, String extendedInformation, String
}

try {
onEvent(code, msg);
getLogger().error(appendContextMessageWithInstructions(code, cause, extendedInformation, msg));
} catch (Throwable t) {
// ignored.
Expand All @@ -119,9 +138,45 @@ public void error(String code, String cause, String extendedInformation, String
}

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.
}
});
}

}
Original file line number Diff line number Diff line change
@@ -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<String, String> getTags() {
Map<String, String> tags = new HashMap<>();
tags.put(TAG_ERROR_CODE, errorCode);
tags.put(TAG_APPLICATION_NAME, applicationName);
return tags;
}

public String getErrorCode() {
return errorCode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ public enum MetricsCategory {
REGISTRY,
METADATA,
THREAD_POOL,
ERROR_CODE,
NETTY,
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public int hashCode() {
return Objects.hash(applicationName, threadPoolName);
}

@Override
public Map<String, String> getTags() {
Map<String, String> tags = new HashMap<>();
tags.put(TAG_IP, getLocalHost());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_IP;

public class ThreadPoolRejectMetric implements Metric{

private String applicationName;

private String threadPoolName;
Expand Down Expand Up @@ -69,6 +70,7 @@ public int hashCode() {
return Objects.hash(applicationName, threadPoolName);
}

@Override
public Map<String, String> getTags() {
Map<String, String> tags = new HashMap<>();
tags.put(TAG_IP, getLocalHost());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@
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;
Expand Down Expand Up @@ -53,9 +54,15 @@ public class DefaultMetricsCollector extends CombMetricsCollector<RequestEvent>
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<MetricsSampler> samplers = new ArrayList<>();

public DefaultMetricsCollector(ApplicationModel applicationModel) {
Expand All @@ -74,8 +81,9 @@ protected void init(RtStatComposite rtStatComposite) {
}
});
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;
}

Expand All @@ -99,6 +107,7 @@ public void setCollectEnabled(Boolean collectEnabled) {
this.collectEnabled = collectEnabled;
}

@Override
public boolean isCollectEnabled() {
return collectEnabled;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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());
}
}
Loading

0 comments on commit 5ae875d

Please sign in to comment.