mirror of
https://gitee.com/dromara/hmily.git
synced 2024-12-02 03:08:12 +08:00
refactor hmily metrics (#312)
This commit is contained in:
parent
5cf086cdc4
commit
76fa0136ec
@ -89,7 +89,8 @@
|
|||||||
<motan.version>1.0.0</motan.version>
|
<motan.version>1.0.0</motan.version>
|
||||||
<disruptor.version>3.4.0</disruptor.version>
|
<disruptor.version>3.4.0</disruptor.version>
|
||||||
<hikaricp.version>3.2.0</hikaricp.version>
|
<hikaricp.version>3.2.0</hikaricp.version>
|
||||||
<prometheus-java-client.version>0.6.0</prometheus-java-client.version>
|
<prometheus-java-client.version>0.10.0</prometheus-java-client.version>
|
||||||
|
<prometheus-jmx.version>0.15.0</prometheus-jmx.version>
|
||||||
<zookeeper.version>3.6.0</zookeeper.version>
|
<zookeeper.version>3.6.0</zookeeper.version>
|
||||||
<zkClient.version>0.4</zkClient.version>
|
<zkClient.version>0.4</zkClient.version>
|
||||||
<aspectj.version>1.8.9</aspectj.version>
|
<aspectj.version>1.8.9</aspectj.version>
|
||||||
@ -185,6 +186,13 @@
|
|||||||
<version>${prometheus-java-client.version}</version>
|
<version>${prometheus-java-client.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- https://mvnrepository.com/artifact/io.prometheus.jmx/collector -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.prometheus.jmx</groupId>
|
||||||
|
<artifactId>collector</artifactId>
|
||||||
|
<version>${prometheus-jmx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.gson</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
|
@ -17,16 +17,13 @@
|
|||||||
|
|
||||||
package org.dromara.hmily.config.api.entity;
|
package org.dromara.hmily.config.api.entity;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import javax.management.ObjectName;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.dromara.hmily.config.api.AbstractConfig;
|
import org.dromara.hmily.config.api.AbstractConfig;
|
||||||
import org.dromara.hmily.config.api.constant.PrefixConstants;
|
import org.dromara.hmily.config.api.constant.PrefixConstants;
|
||||||
import org.dromara.hmily.spi.HmilySPI;
|
import org.dromara.hmily.spi.HmilySPI;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metrics config.
|
* Metrics config.
|
||||||
*
|
*
|
||||||
@ -42,10 +39,6 @@ public final class HmilyMetricsConfig extends AbstractConfig {
|
|||||||
|
|
||||||
private Integer port = 9091;
|
private Integer port = 9091;
|
||||||
|
|
||||||
private boolean async = true;
|
|
||||||
|
|
||||||
private Integer threadCount = Runtime.getRuntime().availableProcessors() << 1;
|
|
||||||
|
|
||||||
private String jmxConfig;
|
private String jmxConfig;
|
||||||
|
|
||||||
private Properties props;
|
private Properties props;
|
||||||
@ -54,134 +47,5 @@ public final class HmilyMetricsConfig extends AbstractConfig {
|
|||||||
public String prefix() {
|
public String prefix() {
|
||||||
return PrefixConstants.METRICS_PREFIX;
|
return PrefixConstants.METRICS_PREFIX;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
|
||||||
public static class HmilyJmxConfig {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Start delay seconds.
|
|
||||||
*/
|
|
||||||
private Integer startDelaySeconds = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Jmx url.
|
|
||||||
*/
|
|
||||||
private String jmxUrl = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Username.
|
|
||||||
*/
|
|
||||||
private String username = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Password.
|
|
||||||
*/
|
|
||||||
private String password = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Ssl.
|
|
||||||
*/
|
|
||||||
private boolean ssl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Lowercase output name.
|
|
||||||
*/
|
|
||||||
private boolean lowercaseOutputName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Lowercase output label names.
|
|
||||||
*/
|
|
||||||
private boolean lowercaseOutputLabelNames;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Whitelist object names.
|
|
||||||
*/
|
|
||||||
private List<ObjectName> whitelistObjectNames = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Blacklist object names.
|
|
||||||
*/
|
|
||||||
private List<ObjectName> blacklistObjectNames = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Rules.
|
|
||||||
*/
|
|
||||||
private List<Rule> rules = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The type Rule.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public static class Rule {
|
|
||||||
|
|
||||||
private Pattern pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Name.
|
|
||||||
*/
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Value.
|
|
||||||
*/
|
|
||||||
private String value;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Value factor.
|
|
||||||
*/
|
|
||||||
private Double valueFactor = 1.0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Help.
|
|
||||||
*/
|
|
||||||
private String help;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Attr name snake case.
|
|
||||||
*/
|
|
||||||
private boolean attrNameSnakeCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Type.
|
|
||||||
*/
|
|
||||||
private Type type = Type.UNTYPED;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Label names.
|
|
||||||
*/
|
|
||||||
private List<String> labelNames = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Label values.
|
|
||||||
*/
|
|
||||||
private List<String> labelValues = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The enum Type.
|
|
||||||
*/
|
|
||||||
public enum Type {
|
|
||||||
/**
|
|
||||||
* Counter type.
|
|
||||||
*/
|
|
||||||
COUNTER,
|
|
||||||
/**
|
|
||||||
* Gauge type.
|
|
||||||
*/
|
|
||||||
GAUGE,
|
|
||||||
/**
|
|
||||||
* Summary type.
|
|
||||||
*/
|
|
||||||
SUMMARY,
|
|
||||||
/**
|
|
||||||
* Histogram type.
|
|
||||||
*/
|
|
||||||
HISTOGRAM,
|
|
||||||
/**
|
|
||||||
* Untyped type.
|
|
||||||
*/
|
|
||||||
UNTYPED,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
package org.dromara.hmily.core.bootstrap;
|
package org.dromara.hmily.core.bootstrap;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import org.dromara.hmily.common.exception.HmilyRuntimeException;
|
import org.dromara.hmily.common.exception.HmilyRuntimeException;
|
||||||
import org.dromara.hmily.common.hook.HmilyShutdownHook;
|
import org.dromara.hmily.common.hook.HmilyShutdownHook;
|
||||||
import org.dromara.hmily.common.utils.StringUtils;
|
import org.dromara.hmily.common.utils.StringUtils;
|
||||||
@ -33,13 +32,15 @@ import org.dromara.hmily.core.provide.ObjectProvide;
|
|||||||
import org.dromara.hmily.core.provide.ReflectObject;
|
import org.dromara.hmily.core.provide.ReflectObject;
|
||||||
import org.dromara.hmily.core.repository.HmilyRepositoryFacade;
|
import org.dromara.hmily.core.repository.HmilyRepositoryFacade;
|
||||||
import org.dromara.hmily.core.schedule.HmilyTransactionSelfRecoveryScheduled;
|
import org.dromara.hmily.core.schedule.HmilyTransactionSelfRecoveryScheduled;
|
||||||
import org.dromara.hmily.metrics.spi.MetricsInit;
|
import org.dromara.hmily.metrics.facade.MetricsTrackerFacade;
|
||||||
import org.dromara.hmily.repository.spi.HmilyRepository;
|
import org.dromara.hmily.repository.spi.HmilyRepository;
|
||||||
import org.dromara.hmily.serializer.spi.HmilySerializer;
|
import org.dromara.hmily.serializer.spi.HmilySerializer;
|
||||||
import org.dromara.hmily.spi.ExtensionLoaderFactory;
|
import org.dromara.hmily.spi.ExtensionLoaderFactory;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type Hmily bootstrap.
|
* The type Hmily bootstrap.
|
||||||
*
|
*
|
||||||
@ -92,9 +93,9 @@ public final class HmilyBootstrap {
|
|||||||
private void initMetrics() {
|
private void initMetrics() {
|
||||||
HmilyMetricsConfig metricsConfig = ConfigEnv.getInstance().getConfig(HmilyMetricsConfig.class);
|
HmilyMetricsConfig metricsConfig = ConfigEnv.getInstance().getConfig(HmilyMetricsConfig.class);
|
||||||
if (Objects.nonNull(metricsConfig) && StringUtils.isNoneBlank(metricsConfig.getMetricsName())) {
|
if (Objects.nonNull(metricsConfig) && StringUtils.isNoneBlank(metricsConfig.getMetricsName())) {
|
||||||
MetricsInit metricsInit = ExtensionLoaderFactory.load(MetricsInit.class);
|
MetricsTrackerFacade facade = new MetricsTrackerFacade();
|
||||||
metricsInit.init(metricsConfig);
|
facade.start(metricsConfig);
|
||||||
registerAutoCloseable(metricsInit);
|
registerAutoCloseable(facade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.facade;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import java.util.Optional;
|
|
||||||
import org.dromara.hmily.config.api.entity.HmilyMetricsConfig;
|
|
||||||
import org.dromara.hmily.metrics.facade.handler.MetricsTrackerHandler;
|
|
||||||
import org.dromara.hmily.metrics.spi.MetricsInit;
|
|
||||||
import org.dromara.hmily.metrics.spi.MetricsTrackerManager;
|
|
||||||
import org.dromara.hmily.spi.ExtensionLoaderFactory;
|
|
||||||
import org.dromara.hmily.spi.HmilySPI;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The type Metrics init facade.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
@HmilySPI(value = "metricsInit")
|
|
||||||
public class MetricsInitFacade implements MetricsInit {
|
|
||||||
|
|
||||||
private static volatile boolean enabled;
|
|
||||||
|
|
||||||
private static MetricsTrackerManager metricsTrackerManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets enabled.
|
|
||||||
*
|
|
||||||
* @return the enabled
|
|
||||||
*/
|
|
||||||
public static boolean getEnabled() {
|
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(final HmilyMetricsConfig metricsConfig) {
|
|
||||||
if (!enabled) {
|
|
||||||
doInit(metricsConfig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
if (!enabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (null != metricsTrackerManager) {
|
|
||||||
metricsTrackerManager.stop();
|
|
||||||
}
|
|
||||||
MetricsTrackerHandler.getInstance().close();
|
|
||||||
enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void doInit(final HmilyMetricsConfig metricsConfig) {
|
|
||||||
Preconditions.checkNotNull(metricsConfig, "metrics configuration can not be null.");
|
|
||||||
metricsTrackerManager = ExtensionLoaderFactory.load(MetricsTrackerManager.class, metricsConfig.getMetricsName());
|
|
||||||
Preconditions.checkNotNull(metricsTrackerManager, "Can not find metrics tracker manager with metrics name in metrics configuration.");
|
|
||||||
metricsTrackerManager.start(metricsConfig);
|
|
||||||
Integer threadCount = Optional.ofNullable(metricsConfig.getThreadCount()).orElse(Runtime.getRuntime().availableProcessors());
|
|
||||||
MetricsTrackerHandler.getInstance().init(metricsConfig.isAsync(), threadCount, metricsTrackerManager);
|
|
||||||
enabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* 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.dromara.hmily.metrics.facade;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.hmily.config.api.entity.HmilyMetricsConfig;
|
||||||
|
import org.dromara.hmily.metrics.spi.MetricsBootService;
|
||||||
|
import org.dromara.hmily.metrics.spi.MetricsRegister;
|
||||||
|
import org.dromara.hmily.spi.ExtensionLoaderFactory;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metrics tracker facade.
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public final class MetricsTrackerFacade implements AutoCloseable {
|
||||||
|
|
||||||
|
private MetricsBootService metricsBootService;
|
||||||
|
|
||||||
|
private final AtomicBoolean isStarted = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init for metrics tracker manager.
|
||||||
|
*
|
||||||
|
* @param metricsConfig metrics config
|
||||||
|
*/
|
||||||
|
public void start(final HmilyMetricsConfig metricsConfig) {
|
||||||
|
if (this.isStarted.compareAndSet(false, true)) {
|
||||||
|
metricsBootService = ExtensionLoaderFactory.load(MetricsBootService.class, metricsConfig.getMetricsName());
|
||||||
|
Preconditions.checkNotNull(metricsBootService,
|
||||||
|
"Can not find metrics tracker manager with metrics name : %s in metrics configuration.", metricsConfig.getMetricsName());
|
||||||
|
metricsBootService.start(metricsConfig, ExtensionLoaderFactory.load(MetricsRegister.class, metricsConfig.getMetricsName()));
|
||||||
|
} else {
|
||||||
|
log.info("metrics tracker has started !");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
this.isStarted.compareAndSet(true, false);
|
||||||
|
if (null != metricsBootService) {
|
||||||
|
metricsBootService.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.facade;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.dromara.hmily.metrics.api.HistogramMetricsTrackerDelegate;
|
|
||||||
import org.dromara.hmily.metrics.api.SummaryMetricsTrackerDelegate;
|
|
||||||
import org.dromara.hmily.metrics.facade.handler.MetricsTrackerHandler;
|
|
||||||
import org.dromara.hmily.metrics.spi.MetricsHandlerFacade;
|
|
||||||
import org.dromara.hmily.spi.HmilySPI;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metrics tracker facade.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@HmilySPI(value = "metricsTrackerHandlerFacade")
|
|
||||||
public final class MetricsTrackerHandlerFacade implements MetricsHandlerFacade {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void counterIncrement(final String metricsLabel, final String... labelValues) {
|
|
||||||
if (MetricsInitFacade.getEnabled()) {
|
|
||||||
MetricsTrackerHandler.getInstance().counterInc(metricsLabel, labelValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void gaugeIncrement(final String metricsLabel, final String... labelValues) {
|
|
||||||
if (MetricsInitFacade.getEnabled()) {
|
|
||||||
MetricsTrackerHandler.getInstance().gaugeInc(metricsLabel, labelValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void gaugeDecrement(final String metricsLabel, final String... labelValues) {
|
|
||||||
if (MetricsInitFacade.getEnabled()) {
|
|
||||||
MetricsTrackerHandler.getInstance().gaugeDec(metricsLabel, labelValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Supplier<Boolean> histogramStartTimer(final String metricsLabel, final String... labelValues) {
|
|
||||||
if (!MetricsInitFacade.getEnabled()) {
|
|
||||||
return () -> false;
|
|
||||||
}
|
|
||||||
Optional<HistogramMetricsTrackerDelegate> histogramMetricsTrackerDelegate = MetricsTrackerHandler.getInstance().histogramStartTimer(metricsLabel, labelValues);
|
|
||||||
return () -> {
|
|
||||||
histogramMetricsTrackerDelegate.ifPresent(this::histogramObserveDuration);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private void histogramObserveDuration(final HistogramMetricsTrackerDelegate delegate) {
|
|
||||||
if (MetricsInitFacade.getEnabled()) {
|
|
||||||
MetricsTrackerHandler.getInstance().histogramObserveDuration(delegate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Supplier<Boolean> summaryStartTimer(final String metricsLabel, final String... labelValues) {
|
|
||||||
if (!MetricsInitFacade.getEnabled()) {
|
|
||||||
return () -> false;
|
|
||||||
}
|
|
||||||
Optional<SummaryMetricsTrackerDelegate> optionalSummaryMetricsTrackerDelegate = MetricsTrackerHandler.getInstance().summaryStartTimer(metricsLabel, labelValues);
|
|
||||||
return () -> {
|
|
||||||
optionalSummaryMetricsTrackerDelegate.ifPresent(this::summaryObserveDuration);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private void summaryObserveDuration(final SummaryMetricsTrackerDelegate delegate) {
|
|
||||||
if (MetricsInitFacade.getEnabled()) {
|
|
||||||
MetricsTrackerHandler.getInstance().summaryObserveDuration(delegate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.facade.executor;
|
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
|
||||||
import java.util.concurrent.RejectedExecutionHandler;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.dromara.hmily.common.concurrent.HmilyThreadFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metrics thread pool executor.
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public final class MetricsThreadPoolExecutor extends ThreadPoolExecutor {
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiates a new Metrics thread pool executor.
|
|
||||||
*
|
|
||||||
* @param threadCount core and max thread count
|
|
||||||
* @param queueSize queue size
|
|
||||||
*/
|
|
||||||
public MetricsThreadPoolExecutor(final int threadCount, final int queueSize) {
|
|
||||||
super(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(queueSize),
|
|
||||||
HmilyThreadFactory.create("metrics", true), buildRejectedExecutionHandler(queueSize));
|
|
||||||
this.name = "metrics";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static RejectedExecutionHandler buildRejectedExecutionHandler(final int size) {
|
|
||||||
return (r, executor) -> {
|
|
||||||
BlockingQueue<Runnable> queue = executor.getQueue();
|
|
||||||
while (queue.size() >= size) {
|
|
||||||
if (executor.isShutdown()) {
|
|
||||||
throw new RejectedExecutionException("metrics thread pool executor closed");
|
|
||||||
}
|
|
||||||
((MetricsThreadPoolExecutor) executor).onRejected();
|
|
||||||
}
|
|
||||||
if (!executor.isShutdown()) {
|
|
||||||
executor.execute(r);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onRejected() {
|
|
||||||
log.info("...thread:{}, Saturation occurs, actuator:{}", Thread.currentThread().getName(), name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,238 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.facade.handler;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.dromara.hmily.metrics.api.CounterMetricsTracker;
|
|
||||||
import org.dromara.hmily.metrics.api.GaugeMetricsTracker;
|
|
||||||
import org.dromara.hmily.metrics.api.HistogramMetricsTracker;
|
|
||||||
import org.dromara.hmily.metrics.api.HistogramMetricsTrackerDelegate;
|
|
||||||
import org.dromara.hmily.metrics.api.MetricsTracker;
|
|
||||||
import org.dromara.hmily.metrics.api.NoneHistogramMetricsTrackerDelegate;
|
|
||||||
import org.dromara.hmily.metrics.api.NoneSummaryMetricsTrackerDelegate;
|
|
||||||
import org.dromara.hmily.metrics.api.SummaryMetricsTracker;
|
|
||||||
import org.dromara.hmily.metrics.api.SummaryMetricsTrackerDelegate;
|
|
||||||
import org.dromara.hmily.metrics.enums.MetricsTypeEnum;
|
|
||||||
import org.dromara.hmily.metrics.facade.executor.MetricsThreadPoolExecutor;
|
|
||||||
import org.dromara.hmily.metrics.spi.MetricsTrackerManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metrics tracker handler.
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public final class MetricsTrackerHandler {
|
|
||||||
|
|
||||||
private static final int FUTURE_GET_TIME_OUT_MILLISECONDS = 500;
|
|
||||||
|
|
||||||
private static final int QUEUE_SIZE = 5000;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private MetricsTrackerManager metricsTrackerManager;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private ExecutorService executorService;
|
|
||||||
|
|
||||||
private volatile boolean async;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get metrics tracker handler of lazy load singleton.
|
|
||||||
*
|
|
||||||
* @return Metrics tracker handler
|
|
||||||
*/
|
|
||||||
public static MetricsTrackerHandler getInstance() {
|
|
||||||
return MetricsTrackerHandlerHolder.INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init for metrics tracker handler.
|
|
||||||
*
|
|
||||||
* @param async async
|
|
||||||
* @param threadCount thread count
|
|
||||||
* @param metricsTrackerManager metrics tracker manager
|
|
||||||
*/
|
|
||||||
public void init(final boolean async, final int threadCount, final MetricsTrackerManager metricsTrackerManager) {
|
|
||||||
this.async = async;
|
|
||||||
this.metricsTrackerManager = metricsTrackerManager;
|
|
||||||
if (async) {
|
|
||||||
executorService = new MetricsThreadPoolExecutor(threadCount, QUEUE_SIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Increment of counter metrics tracker.
|
|
||||||
*
|
|
||||||
* @param metricsLabel metrics label
|
|
||||||
* @param labelValues label values
|
|
||||||
*/
|
|
||||||
public void counterInc(final String metricsLabel, final String... labelValues) {
|
|
||||||
if (async) {
|
|
||||||
executorService.execute(() -> handlerCounter(metricsLabel, labelValues));
|
|
||||||
} else {
|
|
||||||
handlerCounter(metricsLabel, labelValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Increment of gauge metrics tracker.
|
|
||||||
*
|
|
||||||
* @param metricsLabel metrics label
|
|
||||||
* @param labelValues label values
|
|
||||||
*/
|
|
||||||
public void gaugeInc(final String metricsLabel, final String... labelValues) {
|
|
||||||
if (async) {
|
|
||||||
executorService.execute(() -> handlerGaugeInc(metricsLabel, labelValues));
|
|
||||||
} else {
|
|
||||||
handlerGaugeInc(metricsLabel, labelValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decrement of gauge metrics tracker.
|
|
||||||
*
|
|
||||||
* @param metricsLabel metrics label
|
|
||||||
* @param labelValues label values
|
|
||||||
*/
|
|
||||||
public void gaugeDec(final String metricsLabel, final String... labelValues) {
|
|
||||||
if (async) {
|
|
||||||
executorService.execute(() -> handlerGaugeDec(metricsLabel, labelValues));
|
|
||||||
} else {
|
|
||||||
handlerGaugeDec(metricsLabel, labelValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start timer of histogram metrics tracker.
|
|
||||||
*
|
|
||||||
* @param metricsLabel metrics label
|
|
||||||
* @param labelValues label values
|
|
||||||
* @return histogram metrics tracker delegate
|
|
||||||
*/
|
|
||||||
public Optional<HistogramMetricsTrackerDelegate> histogramStartTimer(final String metricsLabel, final String... labelValues) {
|
|
||||||
if (async) {
|
|
||||||
try {
|
|
||||||
return executorService.submit(() -> handlerHistogramStartTimer(metricsLabel, labelValues)).get(FUTURE_GET_TIME_OUT_MILLISECONDS, TimeUnit.MILLISECONDS);
|
|
||||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
|
||||||
throw new IllegalStateException(String.format("Error while fetching histogram metric with metricsLabel= %s and labelValues=%s", metricsLabel, Arrays.toString(labelValues)), e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return handlerHistogramStartTimer(metricsLabel, labelValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Observe amount of time since start time with histogram metrics tracker.
|
|
||||||
*
|
|
||||||
* @param delegate histogram metrics tracker delegate
|
|
||||||
*/
|
|
||||||
public void histogramObserveDuration(final HistogramMetricsTrackerDelegate delegate) {
|
|
||||||
if (async) {
|
|
||||||
executorService.execute(delegate::observeDuration);
|
|
||||||
} else {
|
|
||||||
delegate.observeDuration();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start timer of summary metrics tracker.
|
|
||||||
*
|
|
||||||
* @param metricsLabel metrics label
|
|
||||||
* @param labelValues label values
|
|
||||||
* @return summary metrics tracker delegate
|
|
||||||
*/
|
|
||||||
public Optional<SummaryMetricsTrackerDelegate> summaryStartTimer(final String metricsLabel, final String... labelValues) {
|
|
||||||
if (async) {
|
|
||||||
try {
|
|
||||||
return executorService.submit(() -> handlerSummaryStartTimer(metricsLabel, labelValues)).get(FUTURE_GET_TIME_OUT_MILLISECONDS, TimeUnit.SECONDS);
|
|
||||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
|
||||||
throw new IllegalStateException(String.format("Error while fetching summary metric with metricsLabel= %s and labelValues=%s", metricsLabel, Arrays.toString(labelValues)), e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return handlerSummaryStartTimer(metricsLabel, labelValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Observe amount of time since start time with summary metrics tracker.
|
|
||||||
*
|
|
||||||
* @param delegate summary metrics tracker delegate
|
|
||||||
*/
|
|
||||||
public void summaryObserveDuration(final SummaryMetricsTrackerDelegate delegate) {
|
|
||||||
if (async) {
|
|
||||||
executorService.execute(delegate::observeDuration);
|
|
||||||
} else {
|
|
||||||
delegate.observeDuration();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executor service close.
|
|
||||||
*/
|
|
||||||
public void close() {
|
|
||||||
async = false;
|
|
||||||
if (null != executorService && !executorService.isShutdown()) {
|
|
||||||
executorService.shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handlerCounter(final String metricsLabel, final String... labelValues) {
|
|
||||||
metricsTrackerManager.getMetricsTrackerFactory().create(MetricsTypeEnum.COUNTER.name(), metricsLabel)
|
|
||||||
.ifPresent(metricsTracker -> ((CounterMetricsTracker) metricsTracker).inc(1.0, labelValues));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handlerGaugeInc(final String metricsLabel, final String... labelValues) {
|
|
||||||
metricsTrackerManager.getMetricsTrackerFactory().create(MetricsTypeEnum.GAUGE.name(), metricsLabel)
|
|
||||||
.ifPresent(metricsTracker -> ((GaugeMetricsTracker) metricsTracker).inc(1.0, labelValues));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler gauge dec.
|
|
||||||
*
|
|
||||||
* @param metricsLabel the metrics label
|
|
||||||
* @param labelValues the label values
|
|
||||||
*/
|
|
||||||
public void handlerGaugeDec(final String metricsLabel, final String... labelValues) {
|
|
||||||
metricsTrackerManager.getMetricsTrackerFactory().create(MetricsTypeEnum.GAUGE.name(), metricsLabel)
|
|
||||||
.ifPresent(metricsTracker -> ((GaugeMetricsTracker) metricsTracker).dec(1.0, labelValues));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<HistogramMetricsTrackerDelegate> handlerHistogramStartTimer(final String metricsLabel, final String... labelValues) {
|
|
||||||
Optional<MetricsTracker> metricsTracker = metricsTrackerManager.getMetricsTrackerFactory().create(MetricsTypeEnum.HISTOGRAM.name(), metricsLabel);
|
|
||||||
return metricsTracker.map(tracker -> Optional.of(((HistogramMetricsTracker) tracker).startTimer(labelValues))).orElseGet(() -> Optional.of(new NoneHistogramMetricsTrackerDelegate()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<SummaryMetricsTrackerDelegate> handlerSummaryStartTimer(final String metricsLabel, final String... labelValues) {
|
|
||||||
Optional<MetricsTracker> metricsTracker = metricsTrackerManager.getMetricsTrackerFactory().create(MetricsTypeEnum.SUMMARY.name(), metricsLabel);
|
|
||||||
return metricsTracker.map(tracker -> Optional.of(((SummaryMetricsTracker) tracker).startTimer(labelValues))).orElseGet(() -> Optional.of(new NoneSummaryMetricsTrackerDelegate()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metrics tracker handler holder.
|
|
||||||
*/
|
|
||||||
private static class MetricsTrackerHandlerHolder {
|
|
||||||
|
|
||||||
private static final MetricsTrackerHandler INSTANCE = new MetricsTrackerHandler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
|||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
org.dromara.hmily.metrics.facade.MetricsTrackerHandlerFacade
|
|
@ -1,18 +0,0 @@
|
|||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
org.dromara.hmily.metrics.facade.MetricsInitFacade
|
|
@ -56,5 +56,9 @@
|
|||||||
<groupId>io.prometheus</groupId>
|
<groupId>io.prometheus</groupId>
|
||||||
<artifactId>simpleclient_hotspot</artifactId>
|
<artifactId>simpleclient_hotspot</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.prometheus.jmx</groupId>
|
||||||
|
<artifactId>collector</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.prometheus;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Optional;
|
|
||||||
import org.dromara.hmily.metrics.api.MetricsTracker;
|
|
||||||
import org.dromara.hmily.metrics.api.MetricsTrackerFactory;
|
|
||||||
import org.dromara.hmily.metrics.prometheus.impl.counter.TransactionStatusCounterMetricsTracker;
|
|
||||||
import org.dromara.hmily.metrics.prometheus.impl.counter.TransactionTotalCounterMetricsTracker;
|
|
||||||
import org.dromara.hmily.metrics.prometheus.impl.histogram.TransactionLatencyHistogramMetricsTracker;
|
|
||||||
import org.dromara.hmily.metrics.prometheus.impl.summary.TransactionLatencySummaryMetricsTracker;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prometheus metrics tracker factory.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public final class PrometheusMetricsTrackerFactory implements MetricsTrackerFactory {
|
|
||||||
|
|
||||||
private static final Collection<MetricsTracker> REGISTER = new ArrayList<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
REGISTER.add(new TransactionTotalCounterMetricsTracker());
|
|
||||||
REGISTER.add(new TransactionStatusCounterMetricsTracker());
|
|
||||||
REGISTER.add(new TransactionLatencyHistogramMetricsTracker());
|
|
||||||
REGISTER.add(new TransactionLatencySummaryMetricsTracker());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<MetricsTracker> create(final String metricsType, final String metricsLabel) {
|
|
||||||
return REGISTER.stream().filter(each -> each.metricsLabel().equals(metricsLabel) && each.metricsType().equals(metricsType)).findFirst();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -15,19 +15,17 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.dromara.hmily.metrics.prometheus.impl.collector;
|
package org.dromara.hmily.metrics.prometheus.collector;
|
||||||
|
|
||||||
import io.prometheus.client.Collector;
|
import io.prometheus.client.Collector;
|
||||||
import io.prometheus.client.GaugeMetricFamily;
|
import io.prometheus.client.GaugeMetricFamily;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type Build info collector.
|
* The type Build info collector.
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
*/
|
||||||
public class BuildInfoCollector extends Collector {
|
public class BuildInfoCollector extends Collector {
|
||||||
|
|
@ -1,408 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.prometheus.impl.collector;
|
|
||||||
|
|
||||||
import io.prometheus.client.Collector;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentSkipListMap;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
import javax.management.ObjectName;
|
|
||||||
import org.dromara.hmily.common.utils.GsonUtils;
|
|
||||||
import org.dromara.hmily.config.api.entity.HmilyMetricsConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The type Jmx collector.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public class JmxCollector extends Collector implements Collector.Describable {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(JmxCollector.class.getName());
|
|
||||||
|
|
||||||
private HmilyMetricsConfig.HmilyJmxConfig config;
|
|
||||||
|
|
||||||
private long createTimeNanoSecs = System.nanoTime();
|
|
||||||
|
|
||||||
private final JmxMBeanPropertyCache jmxMBeanPropertyCache = new JmxMBeanPropertyCache();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiates a new Jmx collector.
|
|
||||||
*
|
|
||||||
* @param json the json
|
|
||||||
* @throws MalformedObjectNameException the malformed object name exception
|
|
||||||
*/
|
|
||||||
public JmxCollector(final String json) throws MalformedObjectNameException {
|
|
||||||
config = loadConfig(GsonUtils.getInstance().toObjectMap(json));
|
|
||||||
}
|
|
||||||
|
|
||||||
private HmilyMetricsConfig.HmilyJmxConfig loadConfig(final Map<String, Object> paramMap) throws MalformedObjectNameException {
|
|
||||||
HmilyMetricsConfig.HmilyJmxConfig cfg = new HmilyMetricsConfig.HmilyJmxConfig();
|
|
||||||
if (paramMap == null || paramMap.size() == 0) {
|
|
||||||
return cfg;
|
|
||||||
}
|
|
||||||
if (paramMap.containsKey("startDelaySeconds")) {
|
|
||||||
try {
|
|
||||||
cfg.setStartDelaySeconds((Integer) paramMap.get("startDelaySeconds"));
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
throw new IllegalArgumentException("Invalid number provided for startDelaySeconds", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (paramMap.containsKey("hostPort")) {
|
|
||||||
if (paramMap.containsKey("jmxUrl")) {
|
|
||||||
throw new IllegalArgumentException("At most one of hostPort and jmxUrl must be provided");
|
|
||||||
}
|
|
||||||
cfg.setJmxUrl("service:jmx:rmi:///jndi/rmi://" + paramMap.get("hostPort") + "/jmxrmi");
|
|
||||||
} else if (paramMap.containsKey("jmxUrl")) {
|
|
||||||
cfg.setJmxUrl((String) paramMap.get("jmxUrl"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paramMap.containsKey("username")) {
|
|
||||||
cfg.setUsername((String) paramMap.get("username"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paramMap.containsKey("password")) {
|
|
||||||
cfg.setPassword((String) paramMap.get("password"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paramMap.containsKey("ssl")) {
|
|
||||||
cfg.setSsl((Boolean) paramMap.get("ssl"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paramMap.containsKey("lowercaseOutputName")) {
|
|
||||||
cfg.setLowercaseOutputName((Boolean) paramMap.get("lowercaseOutputName"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paramMap.containsKey("lowercaseOutputLabelNames")) {
|
|
||||||
cfg.setLowercaseOutputLabelNames((Boolean) paramMap.get("lowercaseOutputLabelNames"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paramMap.containsKey("whitelistObjectNames")) {
|
|
||||||
List<String> names = GsonUtils.getInstance().fromList(paramMap.get("whitelistObjectNames").toString(), String.class);
|
|
||||||
for (String name : names) {
|
|
||||||
cfg.getWhitelistObjectNames().add(new ObjectName(name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paramMap.containsKey("blacklistObjectNames")) {
|
|
||||||
List<String> names = GsonUtils.getInstance().fromList(paramMap.get("blacklistObjectNames").toString(), String.class);
|
|
||||||
for (String name : names) {
|
|
||||||
cfg.getBlacklistObjectNames().add(new ObjectName(name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paramMap.containsKey("rules")) {
|
|
||||||
List<Map<String, Object>> configRules = GsonUtils.getInstance().toListMap(paramMap.get("rules").toString());
|
|
||||||
for (Map<String, Object> ruleObject : configRules) {
|
|
||||||
HmilyMetricsConfig.HmilyJmxConfig.Rule rule = new HmilyMetricsConfig.HmilyJmxConfig.Rule();
|
|
||||||
cfg.getRules().add(rule);
|
|
||||||
if (ruleObject.containsKey("pattern")) {
|
|
||||||
rule.setPattern(Pattern.compile("^.*(?:" + ruleObject.get("pattern") + ").*$"));
|
|
||||||
}
|
|
||||||
if (ruleObject.containsKey("name")) {
|
|
||||||
rule.setName((String) ruleObject.get("name"));
|
|
||||||
}
|
|
||||||
if (ruleObject.containsKey("value")) {
|
|
||||||
rule.setValue(String.valueOf(ruleObject.get("value")));
|
|
||||||
}
|
|
||||||
if (ruleObject.containsKey("valueFactor")) {
|
|
||||||
String valueFactor = String.valueOf(ruleObject.get("valueFactor"));
|
|
||||||
try {
|
|
||||||
rule.setValueFactor(Double.valueOf(valueFactor));
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
// use default value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ruleObject.containsKey("attrNameSnakeCase")) {
|
|
||||||
rule.setAttrNameSnakeCase((Boolean) ruleObject.get("attrNameSnakeCase"));
|
|
||||||
}
|
|
||||||
if (ruleObject.containsKey("type")) {
|
|
||||||
rule.setType(HmilyMetricsConfig.HmilyJmxConfig.Type.valueOf(String.valueOf(ruleObject.containsKey("type"))));
|
|
||||||
}
|
|
||||||
if (ruleObject.containsKey("help")) {
|
|
||||||
rule.setHelp(String.valueOf(ruleObject.get("help")));
|
|
||||||
}
|
|
||||||
if (ruleObject.containsKey("labels")) {
|
|
||||||
ConcurrentSkipListMap<String, Object> labels = GsonUtils.getInstance().toTreeMap(ruleObject.get("labels").toString());
|
|
||||||
for (Map.Entry<String, Object> entry : labels.entrySet()) {
|
|
||||||
rule.getLabelNames().add(entry.getKey());
|
|
||||||
rule.getLabelValues().add((String) entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Validation.
|
|
||||||
if ((rule.getLabelValues() != null || rule.getHelp() != null) && rule.getName() == null) {
|
|
||||||
throw new IllegalArgumentException("Must provide name, if help or labels are given: " + ruleObject);
|
|
||||||
}
|
|
||||||
if (rule.getName() != null && rule.getPattern() == null) {
|
|
||||||
throw new IllegalArgumentException("Must provide pattern, if name is given: " + ruleObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Default to a single default rule.
|
|
||||||
cfg.getRules().add(new HmilyMetricsConfig.HmilyJmxConfig.Rule());
|
|
||||||
}
|
|
||||||
return cfg;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String toSnakeAndLowerCase(final String attrName) {
|
|
||||||
if (attrName == null || attrName.isEmpty()) {
|
|
||||||
return attrName;
|
|
||||||
}
|
|
||||||
char firstChar = attrName.subSequence(0, 1).charAt(0);
|
|
||||||
boolean prevCharIsUpperCaseOrUnderscore = Character.isUpperCase(firstChar) || firstChar == '_';
|
|
||||||
StringBuilder resultBuilder = new StringBuilder(attrName.length()).append(Character.toLowerCase(firstChar));
|
|
||||||
for (char attrChar : attrName.substring(1).toCharArray()) {
|
|
||||||
boolean charIsUpperCase = Character.isUpperCase(attrChar);
|
|
||||||
if (!prevCharIsUpperCaseOrUnderscore && charIsUpperCase) {
|
|
||||||
resultBuilder.append("_");
|
|
||||||
}
|
|
||||||
resultBuilder.append(Character.toLowerCase(attrChar));
|
|
||||||
prevCharIsUpperCaseOrUnderscore = charIsUpperCase || attrChar == '_';
|
|
||||||
}
|
|
||||||
return resultBuilder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String safeName(final String name) {
|
|
||||||
if (name == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
boolean prevCharIsUnderscore = false;
|
|
||||||
StringBuilder safeNameBuilder = new StringBuilder(name.length());
|
|
||||||
if (!name.isEmpty() && Character.isDigit(name.charAt(0))) {
|
|
||||||
// prevent a numeric prefix.
|
|
||||||
safeNameBuilder.append("_");
|
|
||||||
}
|
|
||||||
for (char nameChar : name.toCharArray()) {
|
|
||||||
boolean isUnsafeChar = !JmxCollector.isLegalCharacter(nameChar);
|
|
||||||
if (isUnsafeChar || nameChar == '_') {
|
|
||||||
if (!prevCharIsUnderscore) {
|
|
||||||
safeNameBuilder.append("_");
|
|
||||||
prevCharIsUnderscore = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
safeNameBuilder.append(nameChar);
|
|
||||||
prevCharIsUnderscore = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return safeNameBuilder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isLegalCharacter(final char input) {
|
|
||||||
return (input == ':') || (input == '_') || (input >= 'a' && input <= 'z') || (input >= 'A' && input <= 'Z') || (input >= '0' && input <= '9');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<MetricFamilySamples> collect() {
|
|
||||||
Receiver receiver = new Receiver();
|
|
||||||
JmxScraper scraper = new JmxScraper(config.getJmxUrl(), config.getUsername(), config.getPassword(), config.isSsl(),
|
|
||||||
config.getWhitelistObjectNames(), config.getBlacklistObjectNames(), receiver, jmxMBeanPropertyCache);
|
|
||||||
long start = System.nanoTime();
|
|
||||||
double error = 0;
|
|
||||||
if ((config.getStartDelaySeconds() > 0) && ((start - createTimeNanoSecs) / 1000000000L < config.getStartDelaySeconds())) {
|
|
||||||
throw new IllegalStateException("JMXCollector waiting for startDelaySeconds");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
scraper.doScrape();
|
|
||||||
} catch (IOException e) {
|
|
||||||
error = 1;
|
|
||||||
StringWriter sw = new StringWriter();
|
|
||||||
e.printStackTrace(new PrintWriter(sw));
|
|
||||||
LOGGER.severe("JMX scrape failed: " + sw.toString());
|
|
||||||
}
|
|
||||||
List<MetricFamilySamples> mfsList = new ArrayList<>(receiver.metricFamilySamplesMap.values());
|
|
||||||
List<MetricFamilySamples.Sample> samples = new ArrayList<>();
|
|
||||||
samples.add(new MetricFamilySamples.Sample(
|
|
||||||
"jmx_scrape_duration_seconds", new ArrayList<>(), new ArrayList<>(), (System.nanoTime() - start) / 1.0E9));
|
|
||||||
mfsList.add(new MetricFamilySamples("jmx_scrape_duration_seconds", Type.GAUGE, "Time this JMX scrape took, in seconds.", samples));
|
|
||||||
samples = new ArrayList<>();
|
|
||||||
samples.add(new MetricFamilySamples.Sample(
|
|
||||||
"jmx_scrape_error", new ArrayList<>(), new ArrayList<>(), error));
|
|
||||||
mfsList.add(new MetricFamilySamples("jmx_scrape_error", Type.GAUGE, "Non-zero if this scrape failed.", samples));
|
|
||||||
return mfsList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<MetricFamilySamples> describe() {
|
|
||||||
List<MetricFamilySamples> sampleFamilies = new ArrayList<>();
|
|
||||||
sampleFamilies.add(new MetricFamilySamples("jmx_scrape_duration_seconds", Type.GAUGE, "Time this JMX scrape took, in seconds.", new ArrayList<>()));
|
|
||||||
sampleFamilies.add(new MetricFamilySamples("jmx_scrape_error", Type.GAUGE, "Non-zero if this scrape failed.", new ArrayList<>()));
|
|
||||||
return sampleFamilies;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The type Receiver.
|
|
||||||
*/
|
|
||||||
class Receiver implements MBeanReceiver {
|
|
||||||
|
|
||||||
private static final char SEP = '_';
|
|
||||||
|
|
||||||
private Map<String, MetricFamilySamples> metricFamilySamplesMap = new HashMap<>();
|
|
||||||
|
|
||||||
// [] and () are special in regexes, so swtich to <>.
|
|
||||||
private String angleBrackets(final String s) {
|
|
||||||
return "<" + s.substring(1, s.length() - 1) + ">";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add sample.
|
|
||||||
*
|
|
||||||
* @param sample the sample
|
|
||||||
* @param type the type
|
|
||||||
* @param help the help
|
|
||||||
*/
|
|
||||||
void addSample(final MetricFamilySamples.Sample sample, final Type type, final String help) {
|
|
||||||
MetricFamilySamples mfs = metricFamilySamplesMap.get(sample.name);
|
|
||||||
if (mfs == null) {
|
|
||||||
// JmxScraper.MBeanReceiver is only called from one thread,
|
|
||||||
// so there's no race here.
|
|
||||||
mfs = new MetricFamilySamples(sample.name, type, help, new ArrayList<>());
|
|
||||||
metricFamilySamplesMap.put(sample.name, mfs);
|
|
||||||
}
|
|
||||||
mfs.samples.add(sample);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void defaultExport(final String domain, final Map<String, String> beanProperties,
|
|
||||||
final LinkedList<String> attrKeys, final String attrName, final String help, final Object value, final Type type) {
|
|
||||||
StringBuilder name = new StringBuilder();
|
|
||||||
name.append(domain);
|
|
||||||
if (beanProperties.size() > 0) {
|
|
||||||
name.append(SEP);
|
|
||||||
name.append(beanProperties.values().iterator().next());
|
|
||||||
}
|
|
||||||
for (String k : attrKeys) {
|
|
||||||
name.append(SEP);
|
|
||||||
name.append(k);
|
|
||||||
}
|
|
||||||
name.append(SEP);
|
|
||||||
name.append(attrName);
|
|
||||||
String fullname = safeName(name.toString());
|
|
||||||
|
|
||||||
if (config.isLowercaseOutputName()) {
|
|
||||||
fullname = fullname.toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> labelNames = new ArrayList<>();
|
|
||||||
List<String> labelValues = new ArrayList<>();
|
|
||||||
if (beanProperties.size() > 1) {
|
|
||||||
Iterator<Map.Entry<String, String>> iter = beanProperties.entrySet().iterator();
|
|
||||||
// Skip the first one, it's been used in the name.
|
|
||||||
iter.next();
|
|
||||||
while (iter.hasNext()) {
|
|
||||||
Map.Entry<String, String> entry = iter.next();
|
|
||||||
String labelName = safeName(entry.getKey());
|
|
||||||
if (config.isLowercaseOutputName()) {
|
|
||||||
labelName = labelName.toLowerCase();
|
|
||||||
}
|
|
||||||
labelNames.add(labelName);
|
|
||||||
labelValues.add(entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addSample(new MetricFamilySamples.Sample(fullname, labelNames, labelValues, ((Number) value).doubleValue()), type, help);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void recordBean(final String domain, final Map<String, String> beanProperties, final LinkedList<String> attrKeys,
|
|
||||||
final String attrName, final String attrType, final String attrDescription, final Object beanObject) {
|
|
||||||
String beanName = domain + angleBrackets(beanProperties.toString()) + angleBrackets(attrKeys.toString());
|
|
||||||
// attrDescription tends not to be useful, so give the fully qualified name too.
|
|
||||||
String help = attrDescription + " (" + beanName + attrName + ")";
|
|
||||||
String attrNameSnakeCase = toSnakeAndLowerCase(attrName);
|
|
||||||
for (HmilyMetricsConfig.HmilyJmxConfig.Rule rule : config.getRules()) {
|
|
||||||
Matcher matcher = null;
|
|
||||||
String matchName = beanName + (rule.isAttrNameSnakeCase() ? attrNameSnakeCase : attrName);
|
|
||||||
if (rule.getPattern() != null) {
|
|
||||||
matcher = rule.getPattern().matcher(matchName + ": " + beanObject);
|
|
||||||
if (!matcher.matches()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Number value;
|
|
||||||
Object beanValue = beanObject;
|
|
||||||
if (rule.getValue() != null && !rule.getValue().isEmpty()) {
|
|
||||||
assert matcher != null;
|
|
||||||
String val = matcher.replaceAll(rule.getValue());
|
|
||||||
|
|
||||||
try {
|
|
||||||
beanValue = Double.valueOf(val);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
LOGGER.fine("Unable to parse configured value '" + val + "' to number for bean: " + beanName + attrName + ": " + beanValue);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (beanValue instanceof Number) {
|
|
||||||
value = ((Number) beanValue).doubleValue() * rule.getValueFactor();
|
|
||||||
} else if (beanValue instanceof Boolean) {
|
|
||||||
value = (Boolean) beanValue ? 1 : 0;
|
|
||||||
} else {
|
|
||||||
LOGGER.fine("Ignoring unsupported bean: " + beanName + attrName + ": " + beanValue);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// If there's no name provided, use default export format.
|
|
||||||
if (rule.getName() == null) {
|
|
||||||
defaultExport(domain, beanProperties, attrKeys, rule.isAttrNameSnakeCase() ? attrNameSnakeCase : attrName, help, value, Type.valueOf(rule.getType().name()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Matcher is set below here due to validation in the constructor.
|
|
||||||
assert matcher != null;
|
|
||||||
String name = safeName(matcher.replaceAll(rule.getName()));
|
|
||||||
if (name.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (config.isLowercaseOutputName()) {
|
|
||||||
name = name.toLowerCase();
|
|
||||||
}
|
|
||||||
// Set the help.
|
|
||||||
if (rule.getHelp() != null) {
|
|
||||||
help = matcher.replaceAll(rule.getHelp());
|
|
||||||
}
|
|
||||||
// Set the labels.
|
|
||||||
ArrayList<String> labelNames = new ArrayList<>();
|
|
||||||
ArrayList<String> labelValues = new ArrayList<>();
|
|
||||||
if (rule.getLabelNames() != null) {
|
|
||||||
for (int i = 0; i < rule.getLabelNames().size(); i++) {
|
|
||||||
final String unsafeLabelName = rule.getLabelNames().get(i);
|
|
||||||
final String labelValReplacement = rule.getLabelValues().get(i);
|
|
||||||
String labelName = safeName(matcher.replaceAll(unsafeLabelName));
|
|
||||||
String labelValue = matcher.replaceAll(labelValReplacement);
|
|
||||||
if (config.isLowercaseOutputName()) {
|
|
||||||
labelName = labelName.toLowerCase();
|
|
||||||
}
|
|
||||||
if (!labelName.isEmpty() && !labelValue.isEmpty()) {
|
|
||||||
labelNames.add(labelName);
|
|
||||||
labelValues.add(labelValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Add to samples.
|
|
||||||
LOGGER.fine("add metric sample: " + name + " " + labelNames + " " + labelValues + " " + value.doubleValue());
|
|
||||||
addSample(new MetricFamilySamples.Sample(name, labelNames, labelValues, value.doubleValue()), Type.valueOf(rule.getType().name()), help);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,99 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.prometheus.impl.collector;
|
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import javax.management.ObjectName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This object stores a mapping of mBean objectNames to mBean key property lists. The main purpose of it is to reduce
|
|
||||||
* the frequency with which we invoke PROPERTY_PATTERN when discovering mBeans.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public class JmxMBeanPropertyCache {
|
|
||||||
|
|
||||||
private static final Pattern PROPERTY_PATTERN = Pattern.compile(
|
|
||||||
"([^,=:*?]+)"
|
|
||||||
+ "="
|
|
||||||
+ "("
|
|
||||||
+ "\""
|
|
||||||
+ "(?:"
|
|
||||||
+ "[^\\\\\"]*"
|
|
||||||
+ "(?:\\\\.)?"
|
|
||||||
+ ")*"
|
|
||||||
+ "\""
|
|
||||||
+ "|"
|
|
||||||
+ "[^,=:\"]*"
|
|
||||||
+ ")");
|
|
||||||
|
|
||||||
// Implement a version of ObjectName.getKeyPropertyList that returns the
|
|
||||||
// properties in the ordered they were added (the ObjectName stores them
|
|
||||||
// in the order they were added).
|
|
||||||
private final Map<ObjectName, Map<String, String>> keyPropertiesPerBean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiates a new Jmx m bean property cache.
|
|
||||||
*/
|
|
||||||
public JmxMBeanPropertyCache() {
|
|
||||||
this.keyPropertiesPerBean = new ConcurrentHashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets key property list.
|
|
||||||
*
|
|
||||||
* @param mbeanName the mbean name
|
|
||||||
* @return the key property list
|
|
||||||
*/
|
|
||||||
public Map<String, String> getKeyPropertyList(final ObjectName mbeanName) {
|
|
||||||
Map<String, String> keyProperties = keyPropertiesPerBean.get(mbeanName);
|
|
||||||
if (keyProperties == null) {
|
|
||||||
keyProperties = new LinkedHashMap<>();
|
|
||||||
String properties = mbeanName.getKeyPropertyListString();
|
|
||||||
Matcher match = PROPERTY_PATTERN.matcher(properties);
|
|
||||||
while (match.lookingAt()) {
|
|
||||||
keyProperties.put(match.group(1), match.group(2));
|
|
||||||
properties = properties.substring(match.end());
|
|
||||||
if (properties.startsWith(",")) {
|
|
||||||
properties = properties.substring(1);
|
|
||||||
}
|
|
||||||
match.reset(properties);
|
|
||||||
}
|
|
||||||
keyPropertiesPerBean.put(mbeanName, keyProperties);
|
|
||||||
}
|
|
||||||
return keyProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only keep m beans.
|
|
||||||
*
|
|
||||||
* @param latestBeans the latest beans
|
|
||||||
*/
|
|
||||||
public void onlyKeepMBeans(final Set<ObjectName> latestBeans) {
|
|
||||||
for (ObjectName prevName : keyPropertiesPerBean.keySet()) {
|
|
||||||
if (!latestBeans.contains(prevName)) {
|
|
||||||
keyPropertiesPerBean.remove(prevName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,296 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.prometheus.impl.collector;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.management.ManagementFactory;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import javax.management.Attribute;
|
|
||||||
import javax.management.AttributeList;
|
|
||||||
import javax.management.InstanceNotFoundException;
|
|
||||||
import javax.management.JMException;
|
|
||||||
import javax.management.MBeanAttributeInfo;
|
|
||||||
import javax.management.MBeanInfo;
|
|
||||||
import javax.management.MBeanServerConnection;
|
|
||||||
import javax.management.ObjectInstance;
|
|
||||||
import javax.management.ObjectName;
|
|
||||||
import javax.management.ReflectionException;
|
|
||||||
import javax.management.openmbean.CompositeData;
|
|
||||||
import javax.management.openmbean.CompositeType;
|
|
||||||
import javax.management.openmbean.TabularData;
|
|
||||||
import javax.management.openmbean.TabularType;
|
|
||||||
import javax.management.remote.JMXConnector;
|
|
||||||
import javax.management.remote.JMXConnectorFactory;
|
|
||||||
import javax.management.remote.JMXServiceURL;
|
|
||||||
import javax.management.remote.rmi.RMIConnectorServer;
|
|
||||||
import javax.naming.Context;
|
|
||||||
import javax.rmi.ssl.SslRMIClientSocketFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The type Jmx scraper.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public class JmxScraper {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(JmxScraper.class.getName());
|
|
||||||
|
|
||||||
private final MBeanReceiver receiver;
|
|
||||||
|
|
||||||
private final String jmxUrl;
|
|
||||||
|
|
||||||
private final String username;
|
|
||||||
|
|
||||||
private final String password;
|
|
||||||
|
|
||||||
private final boolean ssl;
|
|
||||||
|
|
||||||
private final List<ObjectName> whitelistObjectNames;
|
|
||||||
|
|
||||||
private final List<ObjectName> blacklistObjectNames;
|
|
||||||
|
|
||||||
private final JmxMBeanPropertyCache jmxMBeanPropertyCache;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiates a new Jmx scraper.
|
|
||||||
*
|
|
||||||
* @param jmxUrl the jmx url
|
|
||||||
* @param username the username
|
|
||||||
* @param password the password
|
|
||||||
* @param ssl the ssl
|
|
||||||
* @param whitelistObjectNames the whitelist object names
|
|
||||||
* @param blacklistObjectNames the blacklist object names
|
|
||||||
* @param receiver the receiver
|
|
||||||
* @param jmxMBeanPropertyCache the jmx m bean property cache
|
|
||||||
*/
|
|
||||||
public JmxScraper(final String jmxUrl, final String username, final String password, final boolean ssl,
|
|
||||||
final List<ObjectName> whitelistObjectNames, final List<ObjectName> blacklistObjectNames,
|
|
||||||
final MBeanReceiver receiver, final JmxMBeanPropertyCache jmxMBeanPropertyCache) {
|
|
||||||
this.jmxUrl = jmxUrl;
|
|
||||||
this.receiver = receiver;
|
|
||||||
this.username = username;
|
|
||||||
this.password = password;
|
|
||||||
this.ssl = ssl;
|
|
||||||
this.whitelistObjectNames = whitelistObjectNames;
|
|
||||||
this.blacklistObjectNames = blacklistObjectNames;
|
|
||||||
this.jmxMBeanPropertyCache = jmxMBeanPropertyCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void logScrape(final ObjectName mbeanName, final Set<String> names, final String msg) {
|
|
||||||
logScrape(mbeanName + "_" + names, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void logScrape(final ObjectName mbeanName, final MBeanAttributeInfo attr, final String msg) {
|
|
||||||
logScrape(mbeanName + "'_'" + attr.getName(), msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void logScrape(final String name, final String msg) {
|
|
||||||
LOGGER.log(Level.FINE, "scrape: '" + name + "': " + msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a list of mbeans on host_port and scrape their values.
|
|
||||||
* Values are passed to the receiver in a single thread.
|
|
||||||
*
|
|
||||||
* @throws IOException the exception
|
|
||||||
*/
|
|
||||||
public void doScrape() throws IOException {
|
|
||||||
MBeanServerConnection beanConn;
|
|
||||||
JMXConnector jmxc = null;
|
|
||||||
if (jmxUrl.isEmpty()) {
|
|
||||||
beanConn = ManagementFactory.getPlatformMBeanServer();
|
|
||||||
} else {
|
|
||||||
Map<String, Object> environment = new HashMap<>();
|
|
||||||
if (username != null && username.length() != 0 && password != null && password.length() != 0) {
|
|
||||||
String[] credent = new String[]{username, password};
|
|
||||||
environment.put(JMXConnector.CREDENTIALS, credent);
|
|
||||||
}
|
|
||||||
if (ssl) {
|
|
||||||
environment.put(Context.SECURITY_PROTOCOL, "ssl");
|
|
||||||
SslRMIClientSocketFactory clientSocketFactory = new SslRMIClientSocketFactory();
|
|
||||||
environment.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, clientSocketFactory);
|
|
||||||
environment.put("com.sun.jndi.rmi.factory.socket", clientSocketFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
jmxc = JMXConnectorFactory.connect(new JMXServiceURL(jmxUrl), environment);
|
|
||||||
beanConn = jmxc.getMBeanServerConnection();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
// Query MBean names, see #89 for reasons queryMBeans() is used instead of queryNames()
|
|
||||||
Set<ObjectName> mBeanNames = new HashSet<>();
|
|
||||||
for (ObjectName name : whitelistObjectNames) {
|
|
||||||
for (ObjectInstance instance : beanConn.queryMBeans(name, null)) {
|
|
||||||
mBeanNames.add(instance.getObjectName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ObjectName name : blacklistObjectNames) {
|
|
||||||
for (ObjectInstance instance : beanConn.queryMBeans(name, null)) {
|
|
||||||
mBeanNames.remove(instance.getObjectName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that we have *only* the whitelisted mBeans, remove any old ones from the cache:
|
|
||||||
jmxMBeanPropertyCache.onlyKeepMBeans(mBeanNames);
|
|
||||||
|
|
||||||
for (ObjectName objectName : mBeanNames) {
|
|
||||||
long start = System.nanoTime();
|
|
||||||
scrapeBean(beanConn, objectName);
|
|
||||||
LOGGER.fine("TIME: " + (System.nanoTime() - start) + " ns for " + objectName.toString());
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (jmxc != null) {
|
|
||||||
jmxc.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scrapeBean(final MBeanServerConnection beanConn, final ObjectName mbeanName) {
|
|
||||||
MBeanInfo info;
|
|
||||||
try {
|
|
||||||
info = beanConn.getMBeanInfo(mbeanName);
|
|
||||||
} catch (IOException | JMException e) {
|
|
||||||
logScrape(mbeanName.toString(), "getMBeanInfo Fail: " + e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MBeanAttributeInfo[] attrInfos = info.getAttributes();
|
|
||||||
|
|
||||||
Map<String, MBeanAttributeInfo> name2AttrInfo = new LinkedHashMap<>();
|
|
||||||
for (MBeanAttributeInfo attr : attrInfos) {
|
|
||||||
if (!attr.isReadable()) {
|
|
||||||
logScrape(mbeanName, attr, "not readable");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
name2AttrInfo.put(attr.getName(), attr);
|
|
||||||
}
|
|
||||||
final AttributeList attributes;
|
|
||||||
try {
|
|
||||||
attributes = beanConn.getAttributes(mbeanName, name2AttrInfo.keySet().toArray(new String[0]));
|
|
||||||
if (attributes == null) {
|
|
||||||
logScrape(mbeanName.toString(), "getAttributes Fail: attributes are null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (InstanceNotFoundException | ReflectionException | IOException e) {
|
|
||||||
logScrape(mbeanName, name2AttrInfo.keySet(), "Fail: " + e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (Attribute attribute : attributes.asList()) {
|
|
||||||
MBeanAttributeInfo attr = name2AttrInfo.get(attribute.getName());
|
|
||||||
logScrape(mbeanName, attr, "process");
|
|
||||||
processBeanValue(mbeanName.getDomain(), jmxMBeanPropertyCache.getKeyPropertyList(mbeanName),
|
|
||||||
new LinkedList<>(), attr.getName(), attr.getType(), attr.getDescription(), attribute.getValue());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursive function for exporting the values of an mBean.
|
|
||||||
* JMX is a very open technology, without any prescribed way of declaring mBeans
|
|
||||||
* so this function tries to do a best-effort pass of getting the values/names
|
|
||||||
* out in a way it can be processed elsewhere easily.
|
|
||||||
*/
|
|
||||||
private void processBeanValue(final String domain, final Map<String, String> beanProperties,
|
|
||||||
final LinkedList<String> attrKeysParam, final String attrName, final String attrTypeParam,
|
|
||||||
final String attrDescription, final Object valueParam) {
|
|
||||||
LinkedList<String> attrKeys = attrKeysParam;
|
|
||||||
String attrType = attrTypeParam;
|
|
||||||
Object value = valueParam;
|
|
||||||
if (value == null) {
|
|
||||||
logScrape(domain + beanProperties + attrName, "null");
|
|
||||||
} else if (value instanceof Number || value instanceof String || value instanceof Boolean || value instanceof java.util.Date) {
|
|
||||||
if (value instanceof java.util.Date) {
|
|
||||||
attrType = "java.lang.Double";
|
|
||||||
value = ((java.util.Date) value).getTime() / 1000.0;
|
|
||||||
}
|
|
||||||
logScrape(domain + beanProperties + attrName, value.toString());
|
|
||||||
this.receiver.recordBean(domain, beanProperties, attrKeys, attrName, attrType, attrDescription, value);
|
|
||||||
} else if (value instanceof CompositeData) {
|
|
||||||
logScrape(domain + beanProperties + attrName, "compositedata");
|
|
||||||
CompositeData composite = (CompositeData) value;
|
|
||||||
CompositeType type = composite.getCompositeType();
|
|
||||||
attrKeys = new LinkedList<>(attrKeys);
|
|
||||||
attrKeys.add(attrName);
|
|
||||||
for (String key : type.keySet()) {
|
|
||||||
String typ = type.getType(key).getTypeName();
|
|
||||||
Object valu = composite.get(key);
|
|
||||||
processBeanValue(domain, beanProperties, attrKeys, key, typ, type.getDescription(), valu);
|
|
||||||
}
|
|
||||||
} else if (value instanceof TabularData) {
|
|
||||||
// I don't pretend to have a good understanding of TabularData.
|
|
||||||
// The real world usage doesn't appear to match how they were
|
|
||||||
// meant to be used according to the docs. I've only seen them
|
|
||||||
// used as 'key' 'value' pairs even when 'value' is itself a
|
|
||||||
// CompositeData of multiple values.
|
|
||||||
logScrape(domain + beanProperties + attrName, "tabulardata");
|
|
||||||
TabularData tds = (TabularData) value;
|
|
||||||
TabularType tt = tds.getTabularType();
|
|
||||||
List<String> rowKeys = tt.getIndexNames();
|
|
||||||
CompositeType type = tt.getRowType();
|
|
||||||
Set<String> valueKeys = new TreeSet<>(type.keySet());
|
|
||||||
valueKeys.removeAll(rowKeys);
|
|
||||||
LinkedList<String> extendedAttrKeys = new LinkedList<>(attrKeys);
|
|
||||||
extendedAttrKeys.add(attrName);
|
|
||||||
for (Object valu : tds.values()) {
|
|
||||||
if (valu instanceof CompositeData) {
|
|
||||||
CompositeData composite = (CompositeData) valu;
|
|
||||||
Map<String, String> rowKeyMap = new LinkedHashMap<>(beanProperties);
|
|
||||||
String resultKey;
|
|
||||||
for (String rowKey : rowKeys) {
|
|
||||||
resultKey = rowKey;
|
|
||||||
Object obj = composite.get(resultKey);
|
|
||||||
if (obj != null) {
|
|
||||||
// Nested tabulardata will repeat the 'key' label, so
|
|
||||||
// append a suffix to distinguish each.
|
|
||||||
while (rowKeyMap.containsKey(resultKey)) {
|
|
||||||
resultKey = resultKey + "_";
|
|
||||||
}
|
|
||||||
rowKeyMap.put(resultKey, obj.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (String valueIdx : valueKeys) {
|
|
||||||
LinkedList<String> attrNames = extendedAttrKeys;
|
|
||||||
String typ = type.getType(valueIdx).getTypeName();
|
|
||||||
String name = valueIdx;
|
|
||||||
if ("value".equalsIgnoreCase(valueIdx.toLowerCase())) {
|
|
||||||
// Skip appending 'value' to the name
|
|
||||||
attrNames = attrKeys;
|
|
||||||
name = attrName;
|
|
||||||
}
|
|
||||||
processBeanValue(domain, rowKeyMap, attrNames, name, typ, type.getDescription(), composite.get(valueIdx));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logScrape(domain, "not a correct tabulardata format");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (value.getClass().isArray()) {
|
|
||||||
logScrape(domain, "arrays are unsupported");
|
|
||||||
} else {
|
|
||||||
logScrape(domain + beanProperties, attrType + " is not exported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.prometheus.impl.collector;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The interface M bean receiver.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public interface MBeanReceiver {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Record bean.
|
|
||||||
*
|
|
||||||
* @param domain the domain
|
|
||||||
* @param beanProperties the bean properties
|
|
||||||
* @param attrKeys the attr keys
|
|
||||||
* @param attrName the attr name
|
|
||||||
* @param attrType the attr type
|
|
||||||
* @param attrDescription the attr description
|
|
||||||
* @param value the value
|
|
||||||
*/
|
|
||||||
void recordBean(String domain, Map<String, String> beanProperties,
|
|
||||||
LinkedList<String> attrKeys, String attrName, String attrType,
|
|
||||||
String attrDescription, Object value);
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.prometheus.impl.counter;
|
|
||||||
|
|
||||||
import io.prometheus.client.Counter;
|
|
||||||
import org.dromara.hmily.metrics.api.CounterMetricsTracker;
|
|
||||||
import org.dromara.hmily.metrics.enums.MetricsLabelEnum;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transaction counter metrics tracker.
|
|
||||||
*/
|
|
||||||
public final class TransactionStatusCounterMetricsTracker implements CounterMetricsTracker {
|
|
||||||
|
|
||||||
private static final Counter TRANSACTION_STATUS = Counter.build()
|
|
||||||
.name("transaction")
|
|
||||||
.labelNames("type", "role", "status")
|
|
||||||
.help("collect transaction status count")
|
|
||||||
.register();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void inc(final double amount, final String... labelValues) {
|
|
||||||
TRANSACTION_STATUS.labels(labelValues).inc(amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String metricsLabel() {
|
|
||||||
return MetricsLabelEnum.TRANSACTION_STATUS.getName();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.prometheus.impl.counter;
|
|
||||||
|
|
||||||
import io.prometheus.client.Counter;
|
|
||||||
import org.dromara.hmily.metrics.api.CounterMetricsTracker;
|
|
||||||
import org.dromara.hmily.metrics.enums.MetricsLabelEnum;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request total counter metrics tracker.
|
|
||||||
*/
|
|
||||||
public final class TransactionTotalCounterMetricsTracker implements CounterMetricsTracker {
|
|
||||||
|
|
||||||
private static final Counter TRANSACTION_TOTAL = Counter.build()
|
|
||||||
.name("transaction_total")
|
|
||||||
.labelNames("type")
|
|
||||||
.help("hmily request total count")
|
|
||||||
.register();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void inc(final double amount, final String... labelValues) {
|
|
||||||
TRANSACTION_TOTAL.labels(labelValues).inc(amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String metricsLabel() {
|
|
||||||
return MetricsLabelEnum.TRANSACTION_TOTAL.getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.prometheus.impl.histogram;
|
|
||||||
|
|
||||||
import io.prometheus.client.Histogram;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.dromara.hmily.metrics.api.HistogramMetricsTrackerDelegate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prometheus histogram metrics tracker delegate.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public final class PrometheusHistogramMetricsTrackerDelegate implements HistogramMetricsTrackerDelegate {
|
|
||||||
|
|
||||||
private final Histogram.Timer timer;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void observeDuration() {
|
|
||||||
timer.observeDuration();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.prometheus.impl.histogram;
|
|
||||||
|
|
||||||
import io.prometheus.client.Histogram;
|
|
||||||
import org.dromara.hmily.metrics.api.HistogramMetricsTracker;
|
|
||||||
import org.dromara.hmily.metrics.api.HistogramMetricsTrackerDelegate;
|
|
||||||
import org.dromara.hmily.metrics.enums.MetricsLabelEnum;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transaction latency histogram metrics tracker.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public final class TransactionLatencyHistogramMetricsTracker implements HistogramMetricsTracker {
|
|
||||||
|
|
||||||
private static final Histogram TRANSACTION_LATENCY = Histogram.build()
|
|
||||||
.labelNames("type")
|
|
||||||
.name("transaction_latency_histogram_millis").help("Transaction Latency Histogram Millis (ms)")
|
|
||||||
.register();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HistogramMetricsTrackerDelegate startTimer(final String... labelValues) {
|
|
||||||
Histogram.Timer timer = TRANSACTION_LATENCY.labels(labelValues).startTimer();
|
|
||||||
return new PrometheusHistogramMetricsTrackerDelegate(timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String metricsLabel() {
|
|
||||||
return MetricsLabelEnum.TRANSACTION_LATENCY.getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.prometheus.impl.summary;
|
|
||||||
|
|
||||||
import io.prometheus.client.Summary;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.dromara.hmily.metrics.api.SummaryMetricsTrackerDelegate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prometheus summary metrics tracker delegate.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public final class PrometheusSummaryMetricsTrackerDelegate implements SummaryMetricsTrackerDelegate {
|
|
||||||
|
|
||||||
private final Summary.Timer timer;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void observeDuration() {
|
|
||||||
timer.observeDuration();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.prometheus.impl.summary;
|
|
||||||
|
|
||||||
import io.prometheus.client.Summary;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import org.dromara.hmily.metrics.api.SummaryMetricsTracker;
|
|
||||||
import org.dromara.hmily.metrics.api.SummaryMetricsTrackerDelegate;
|
|
||||||
import org.dromara.hmily.metrics.enums.MetricsLabelEnum;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transaction latency summary metrics tracker.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public final class TransactionLatencySummaryMetricsTracker implements SummaryMetricsTracker {
|
|
||||||
|
|
||||||
private static final Summary TRANSACTION_LATENCY = Summary.build()
|
|
||||||
.name("transaction_latency_summary_millis").labelNames("type")
|
|
||||||
.help("Requests Latency Summary Millis (ms)")
|
|
||||||
.quantile(0.5, 0.05)
|
|
||||||
.quantile(0.95, 0.01)
|
|
||||||
.quantile(0.99, 0.001)
|
|
||||||
.maxAgeSeconds(TimeUnit.MINUTES.toSeconds(5))
|
|
||||||
.ageBuckets(5)
|
|
||||||
.register();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SummaryMetricsTrackerDelegate startTimer(final String... labelValues) {
|
|
||||||
Summary.Timer timer = TRANSACTION_LATENCY.labels(labelValues).startTimer();
|
|
||||||
return new PrometheusSummaryMetricsTrackerDelegate(timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String metricsLabel() {
|
|
||||||
return MetricsLabelEnum.TRANSACTION_LATENCY.getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* 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.dromara.hmily.metrics.prometheus.register;
|
||||||
|
|
||||||
|
import io.prometheus.client.Counter;
|
||||||
|
import io.prometheus.client.Gauge;
|
||||||
|
import io.prometheus.client.Histogram;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.hmily.metrics.spi.MetricsRegister;
|
||||||
|
import org.dromara.hmily.spi.HmilySPI;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prometheus metrics register.
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@HmilySPI("prometheus")
|
||||||
|
public final class PrometheusMetricsRegister implements MetricsRegister {
|
||||||
|
|
||||||
|
private static final Map<String, Counter> COUNTER_MAP = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private static final Map<String, Gauge> GAUGE_MAP = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private static final Map<String, Histogram> HISTOGRAM_MAP = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get instance prometheus metrics register.
|
||||||
|
*
|
||||||
|
* @return the prometheus metrics register
|
||||||
|
*/
|
||||||
|
public static PrometheusMetricsRegister getInstance() {
|
||||||
|
return PrometheusMetricsRegisterHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerCounter(final String name, final String[] labelNames, final String document) {
|
||||||
|
if (!COUNTER_MAP.containsKey(name)) {
|
||||||
|
Counter.Builder builder = Counter.build().name(name).help(document);
|
||||||
|
if (null != labelNames) {
|
||||||
|
builder.labelNames(labelNames);
|
||||||
|
}
|
||||||
|
COUNTER_MAP.put(name, builder.register());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerGauge(final String name, final String[] labelNames, final String document) {
|
||||||
|
if (!GAUGE_MAP.containsKey(name)) {
|
||||||
|
Gauge.Builder builder = Gauge.build().name(name).help(document);
|
||||||
|
if (null != labelNames) {
|
||||||
|
builder.labelNames(labelNames);
|
||||||
|
}
|
||||||
|
GAUGE_MAP.put(name, builder.register());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerHistogram(final String name, final String[] labelNames, final String document) {
|
||||||
|
if (!HISTOGRAM_MAP.containsKey(name)) {
|
||||||
|
Histogram.Builder builder = Histogram.build().name(name).help(document);
|
||||||
|
if (null != labelNames) {
|
||||||
|
builder.labelNames(labelNames);
|
||||||
|
}
|
||||||
|
HISTOGRAM_MAP.put(name, builder.register());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void counterIncrement(final String name, final String[] labelValues, final long count) {
|
||||||
|
Counter counter = COUNTER_MAP.get(name);
|
||||||
|
if (null != labelValues) {
|
||||||
|
counter.labels(labelValues).inc(count);
|
||||||
|
} else {
|
||||||
|
counter.inc(count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void gaugeIncrement(final String name, final String[] labelValues) {
|
||||||
|
Gauge gauge = GAUGE_MAP.get(name);
|
||||||
|
if (null != labelValues) {
|
||||||
|
gauge.labels(labelValues).inc();
|
||||||
|
} else {
|
||||||
|
gauge.inc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void gaugeDecrement(final String name, final String[] labelValues) {
|
||||||
|
Gauge gauge = GAUGE_MAP.get(name);
|
||||||
|
if (null != labelValues) {
|
||||||
|
gauge.labels(labelValues).dec();
|
||||||
|
} else {
|
||||||
|
gauge.dec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recordTime(final String name, final String[] labelValues, final long duration) {
|
||||||
|
Histogram histogram = HISTOGRAM_MAP.get(name);
|
||||||
|
if (null != labelValues) {
|
||||||
|
histogram.labels(labelValues).observe(duration);
|
||||||
|
} else {
|
||||||
|
histogram.observe(duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class PrometheusMetricsRegisterHolder {
|
||||||
|
|
||||||
|
private static final PrometheusMetricsRegister INSTANCE = new PrometheusMetricsRegister();
|
||||||
|
}
|
||||||
|
}
|
@ -15,24 +15,26 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.dromara.hmily.metrics.prometheus;
|
package org.dromara.hmily.metrics.prometheus.service;
|
||||||
|
|
||||||
import io.prometheus.client.CollectorRegistry;
|
import io.prometheus.client.CollectorRegistry;
|
||||||
import io.prometheus.client.exporter.HTTPServer;
|
import io.prometheus.client.exporter.HTTPServer;
|
||||||
import io.prometheus.client.hotspot.DefaultExports;
|
import io.prometheus.client.hotspot.DefaultExports;
|
||||||
|
import io.prometheus.jmx.JmxCollector;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dromara.hmily.config.api.entity.HmilyMetricsConfig;
|
||||||
|
import org.dromara.hmily.metrics.prometheus.collector.BuildInfoCollector;
|
||||||
|
import org.dromara.hmily.metrics.reporter.MetricsReporter;
|
||||||
|
import org.dromara.hmily.metrics.spi.MetricsBootService;
|
||||||
|
import org.dromara.hmily.metrics.spi.MetricsRegister;
|
||||||
|
import org.dromara.hmily.spi.HmilySPI;
|
||||||
|
|
||||||
|
import javax.management.MalformedObjectNameException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.dromara.hmily.config.api.entity.HmilyMetricsConfig;
|
|
||||||
import org.dromara.hmily.metrics.api.MetricsTrackerFactory;
|
|
||||||
import org.dromara.hmily.metrics.prometheus.impl.collector.BuildInfoCollector;
|
|
||||||
import org.dromara.hmily.metrics.prometheus.impl.collector.JmxCollector;
|
|
||||||
import org.dromara.hmily.metrics.spi.MetricsTrackerManager;
|
|
||||||
import org.dromara.hmily.spi.HmilySPI;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prometheus metrics tracker manager.
|
* Prometheus metrics tracker manager.
|
||||||
@ -40,31 +42,43 @@ import org.dromara.hmily.spi.HmilySPI;
|
|||||||
@Getter
|
@Getter
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@HmilySPI("prometheus")
|
@HmilySPI("prometheus")
|
||||||
public final class PrometheusMetricsTrackerManager implements MetricsTrackerManager {
|
public final class PrometheusBootService implements MetricsBootService {
|
||||||
|
|
||||||
private final MetricsTrackerFactory metricsTrackerFactory = new PrometheusMetricsTrackerFactory();
|
|
||||||
|
|
||||||
private HTTPServer server;
|
private HTTPServer server;
|
||||||
|
|
||||||
private volatile AtomicBoolean registered = new AtomicBoolean(false);
|
private volatile AtomicBoolean registered = new AtomicBoolean(false);
|
||||||
|
|
||||||
@SneakyThrows(IOException.class)
|
|
||||||
@Override
|
@Override
|
||||||
public void start(final HmilyMetricsConfig metricsConfig) {
|
public void start(final HmilyMetricsConfig metricsConfig, final MetricsRegister register) {
|
||||||
register(metricsConfig.getJmxConfig());
|
startServer(metricsConfig);
|
||||||
InetSocketAddress inetSocketAddress;
|
MetricsReporter.register(register);
|
||||||
if ("".equals(metricsConfig.getHost()) || null == metricsConfig.getHost()) {
|
|
||||||
inetSocketAddress = new InetSocketAddress(metricsConfig.getPort());
|
|
||||||
} else {
|
|
||||||
inetSocketAddress = new InetSocketAddress(metricsConfig.getHost(), metricsConfig.getPort());
|
|
||||||
}
|
|
||||||
server = new HTTPServer(inetSocketAddress, CollectorRegistry.defaultRegistry, true);
|
|
||||||
log.info("you start prometheus metrics http server host is :{}, port is :{} ", inetSocketAddress.getHostString(), inetSocketAddress.getPort());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
server.stop();
|
if (server != null) {
|
||||||
|
server.stop();
|
||||||
|
registered.set(false);
|
||||||
|
CollectorRegistry.defaultRegistry.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startServer(final HmilyMetricsConfig metricsConfig) {
|
||||||
|
register(metricsConfig.getJmxConfig());
|
||||||
|
int port = metricsConfig.getPort();
|
||||||
|
String host = metricsConfig.getHost();
|
||||||
|
InetSocketAddress inetSocketAddress;
|
||||||
|
if (null == host || "".equalsIgnoreCase(host)) {
|
||||||
|
inetSocketAddress = new InetSocketAddress(port);
|
||||||
|
} else {
|
||||||
|
inetSocketAddress = new InetSocketAddress(host, port);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
server = new HTTPServer(inetSocketAddress, CollectorRegistry.defaultRegistry, true);
|
||||||
|
log.info(String.format("Prometheus metrics HTTP server `%s:%s` start success.", inetSocketAddress.getHostString(), inetSocketAddress.getPort()));
|
||||||
|
} catch (final IOException ex) {
|
||||||
|
log.error("Prometheus metrics HTTP server start fail", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void register(final String jmxConfig) {
|
private void register(final String jmxConfig) {
|
||||||
@ -72,11 +86,13 @@ public final class PrometheusMetricsTrackerManager implements MetricsTrackerMana
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
new BuildInfoCollector().register();
|
new BuildInfoCollector().register();
|
||||||
|
DefaultExports.initialize();
|
||||||
try {
|
try {
|
||||||
new JmxCollector(jmxConfig).register();
|
if (StringUtils.isNotEmpty(jmxConfig)) {
|
||||||
DefaultExports.initialize();
|
new JmxCollector(jmxConfig).register();
|
||||||
|
}
|
||||||
} catch (MalformedObjectNameException e) {
|
} catch (MalformedObjectNameException e) {
|
||||||
log.error("init jxm collector error", e);
|
log.error("init jmx collector error", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1 @@
|
|||||||
|
org.dromara.hmily.metrics.prometheus.service.PrometheusBootService
|
@ -0,0 +1 @@
|
|||||||
|
org.dromara.hmily.metrics.prometheus.register.PrometheusMetricsRegister
|
@ -1 +0,0 @@
|
|||||||
org.dromara.hmily.metrics.prometheus.PrometheusMetricsTrackerManager
|
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.api;
|
|
||||||
|
|
||||||
import org.dromara.hmily.metrics.enums.MetricsTypeEnum;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Counter metrics tracker interface.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public interface CounterMetricsTracker extends MetricsTracker {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Increment the counter with label values by the given amount.
|
|
||||||
*
|
|
||||||
* @param amount amount
|
|
||||||
* @param labelValues label values
|
|
||||||
*/
|
|
||||||
void inc(double amount, String... labelValues);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metrics type.
|
|
||||||
*
|
|
||||||
* @return metrics type
|
|
||||||
*/
|
|
||||||
default String metricsType() {
|
|
||||||
return MetricsTypeEnum.COUNTER.name();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.api;
|
|
||||||
|
|
||||||
import org.dromara.hmily.metrics.enums.MetricsTypeEnum;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gauge metrics tracker interface.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public interface GaugeMetricsTracker extends MetricsTracker {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Increment the Gauge with label values by the given amount.
|
|
||||||
*
|
|
||||||
* @param amount amount
|
|
||||||
* @param labelValues label values
|
|
||||||
*/
|
|
||||||
void inc(double amount, String... labelValues);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decrement the Gauge with label values by the given amount.
|
|
||||||
*
|
|
||||||
* @param amount amount
|
|
||||||
* @param labelValues label values
|
|
||||||
*/
|
|
||||||
void dec(double amount, String... labelValues);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metrics type.
|
|
||||||
*
|
|
||||||
* @return metrics type
|
|
||||||
*/
|
|
||||||
default String metricsType() {
|
|
||||||
return MetricsTypeEnum.GAUGE.name();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.api;
|
|
||||||
|
|
||||||
import org.dromara.hmily.metrics.enums.MetricsTypeEnum;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Histogram metrics tracker.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public interface HistogramMetricsTracker extends MetricsTracker {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start timer with histogram.
|
|
||||||
*
|
|
||||||
* @param labelValues label values
|
|
||||||
* @return histogram metrics tracker delegate
|
|
||||||
*/
|
|
||||||
default HistogramMetricsTrackerDelegate startTimer(String... labelValues) {
|
|
||||||
return new NoneHistogramMetricsTrackerDelegate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Observe the given amount.
|
|
||||||
*
|
|
||||||
* @param amount amount
|
|
||||||
*/
|
|
||||||
default void observer(long amount) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metrics type.
|
|
||||||
*
|
|
||||||
* @return metrics type
|
|
||||||
*/
|
|
||||||
default String metricsType() {
|
|
||||||
return MetricsTypeEnum.HISTOGRAM.name();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.api;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Histogram metrics tracker delegate.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public interface HistogramMetricsTrackerDelegate {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Observe amount of time since start time.
|
|
||||||
*/
|
|
||||||
default void observeDuration() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.api;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metrics tracker factory.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public interface MetricsTrackerFactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create of metrics tracker.
|
|
||||||
*
|
|
||||||
* @param metricsType metrics type
|
|
||||||
* @param metricsLabel metrics label
|
|
||||||
* @return metrics tracker
|
|
||||||
*/
|
|
||||||
Optional<MetricsTracker> create(String metricsType, String metricsLabel);
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.api;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The type None histogram metrics tracker delegate.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public final class NoneHistogramMetricsTrackerDelegate implements HistogramMetricsTrackerDelegate {
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.api;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* None summary metrics tracker delegate.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public final class NoneSummaryMetricsTrackerDelegate implements SummaryMetricsTrackerDelegate {
|
|
||||||
}
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.api;
|
|
||||||
|
|
||||||
import org.dromara.hmily.metrics.enums.MetricsTypeEnum;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Summary metrics tracker.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public interface SummaryMetricsTracker extends MetricsTracker {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start timer with summary.
|
|
||||||
*
|
|
||||||
* @param labelValues label values
|
|
||||||
* @return Summary metrics tracker delegate
|
|
||||||
*/
|
|
||||||
default SummaryMetricsTrackerDelegate startTimer(String... labelValues) {
|
|
||||||
return new NoneSummaryMetricsTrackerDelegate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Observe the given amount.
|
|
||||||
*
|
|
||||||
* @param amount amount
|
|
||||||
*/
|
|
||||||
default void observer(long amount) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metrics type.
|
|
||||||
*
|
|
||||||
* @return metrics type
|
|
||||||
*/
|
|
||||||
default String metricsType() {
|
|
||||||
return MetricsTypeEnum.SUMMARY.name();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.api;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Summary metrics tracker delegate.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public interface SummaryMetricsTrackerDelegate {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Observe amount of time in seconds since start time.
|
|
||||||
*/
|
|
||||||
default void observeDuration() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
|||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
* 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 not use this file except in compliance with
|
||||||
* the License. You may obtain a copy of the License at
|
* the License. You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
@ -15,27 +15,25 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.dromara.hmily.metrics.api;
|
package org.dromara.hmily.metrics.constant;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metrics tracker.
|
* The Label names.
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
*/
|
||||||
public interface MetricsTracker {
|
public final class LabelNames {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metrics label.
|
* The constant TRANSACTION_STATUS.
|
||||||
*
|
|
||||||
* @return metrics label
|
|
||||||
*/
|
*/
|
||||||
String metricsLabel();
|
public static final String TRANSACTION_STATUS = "hmily_transaction_status";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metrics type.
|
* The constant TRANSACTION_TOTAL.
|
||||||
*
|
|
||||||
* @return metrics type
|
|
||||||
*/
|
*/
|
||||||
String metricsType();
|
public static final String TRANSACTION_TOTAL = "hmily_transaction_total";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The constant TRANSACTION_LATENCY.
|
||||||
|
*/
|
||||||
|
public static final String TRANSACTION_LATENCY = "hmily_transaction_latency_histogram_millis";
|
||||||
}
|
}
|
||||||
|
|
@ -15,34 +15,26 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.dromara.hmily.metrics.enums;
|
package org.dromara.hmily.metrics.entity;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.dromara.hmily.metrics.enums.MetricType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metrics label enum.
|
* Metric.
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Getter
|
@Getter
|
||||||
public enum MetricsLabelEnum {
|
@RequiredArgsConstructor
|
||||||
|
public final class Metric {
|
||||||
|
|
||||||
/**
|
private final MetricType type;
|
||||||
* transaction total metrics label.
|
|
||||||
*/
|
|
||||||
TRANSACTION_TOTAL("transaction_total"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* transaction latency metrics label.
|
|
||||||
*/
|
|
||||||
TRANSACTION_LATENCY("transaction_latency"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transaction status metrics label enum.
|
|
||||||
*/
|
|
||||||
TRANSACTION_STATUS("transaction_status");
|
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
private final String document;
|
||||||
|
|
||||||
|
private final List<String> labels;
|
||||||
}
|
}
|
@ -17,31 +17,28 @@
|
|||||||
|
|
||||||
package org.dromara.hmily.metrics.enums;
|
package org.dromara.hmily.metrics.enums;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metrics type enum.
|
* Metric type.
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
*/
|
||||||
public enum MetricsTypeEnum {
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum MetricType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counter metrics type.
|
* Counter metric type.
|
||||||
*/
|
*/
|
||||||
COUNTER,
|
COUNTER,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gauge metrics type.
|
* Gauge metric type.
|
||||||
*/
|
*/
|
||||||
GAUGE,
|
GAUGE,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Histogram metrics type.
|
* Histogram metric type.
|
||||||
*/
|
*/
|
||||||
HISTOGRAM,
|
HISTOGRAM
|
||||||
|
|
||||||
/**
|
|
||||||
* Summary metrics type.
|
|
||||||
*/
|
|
||||||
SUMMARY
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,221 @@
|
|||||||
|
/*
|
||||||
|
* 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.dromara.hmily.metrics.reporter;
|
||||||
|
|
||||||
|
import org.dromara.hmily.metrics.spi.MetricsRegister;
|
||||||
|
import org.dromara.hmily.metrics.entity.Metric;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metrics reporter.
|
||||||
|
*/
|
||||||
|
public final class MetricsReporter {
|
||||||
|
|
||||||
|
private static MetricsRegister metricsRegister;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register.
|
||||||
|
*
|
||||||
|
* @param metricsRegister metrics register
|
||||||
|
*/
|
||||||
|
public static void register(final MetricsRegister metricsRegister) {
|
||||||
|
MetricsReporter.metricsRegister = metricsRegister;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register metrics.
|
||||||
|
*
|
||||||
|
* @param metrics metric collection
|
||||||
|
*/
|
||||||
|
public static void registerMetrics(final Collection<Metric> metrics) {
|
||||||
|
for (Metric metric : metrics) {
|
||||||
|
switch (metric.getType()) {
|
||||||
|
case COUNTER:
|
||||||
|
registerCounter(metric.getName(), getLabelNames(metric.getLabels()), metric.getDocument());
|
||||||
|
break;
|
||||||
|
case GAUGE:
|
||||||
|
registerGauge(metric.getName(), getLabelNames(metric.getLabels()), metric.getDocument());
|
||||||
|
break;
|
||||||
|
case HISTOGRAM:
|
||||||
|
registerHistogram(metric.getName(), getLabelNames(metric.getLabels()), metric.getDocument());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("we not support metric registration for type: " + metric.getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register counter.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param labelNames label names
|
||||||
|
* @param document document for counter
|
||||||
|
*/
|
||||||
|
public static void registerCounter(final String name, final String[] labelNames, final String document) {
|
||||||
|
Optional.ofNullable(metricsRegister).ifPresent(register -> register.registerCounter(name, labelNames, document));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register counter.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param document document for counter
|
||||||
|
*/
|
||||||
|
public static void registerCounter(final String name, final String document) {
|
||||||
|
registerCounter(name, null, document);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register gauge.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param labelNames label names
|
||||||
|
* @param document document for gauge
|
||||||
|
*/
|
||||||
|
public static void registerGauge(final String name, final String[] labelNames, final String document) {
|
||||||
|
Optional.ofNullable(metricsRegister).ifPresent(register -> register.registerGauge(name, labelNames, document));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register gauge.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param document document for gauge
|
||||||
|
*/
|
||||||
|
public static void registerGauge(final String name, final String document) {
|
||||||
|
registerGauge(name, null, document);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register histogram by label names.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param labelNames label names
|
||||||
|
* @param document document for histogram
|
||||||
|
*/
|
||||||
|
public static void registerHistogram(final String name, final String[] labelNames, final String document) {
|
||||||
|
Optional.ofNullable(metricsRegister).ifPresent(register -> register.registerHistogram(name, labelNames, document));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register histogram.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param document document for histogram
|
||||||
|
*/
|
||||||
|
public static void registerHistogram(final String name, final String document) {
|
||||||
|
registerHistogram(name, null, document);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counter increment.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param labelValues label values
|
||||||
|
*/
|
||||||
|
public static void counterIncrement(final String name, final String[] labelValues) {
|
||||||
|
counterIncrement(name, labelValues, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counter increment.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
*/
|
||||||
|
public static void counterIncrement(final String name) {
|
||||||
|
counterIncrement(name, null, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counter increment by count.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param labelValues label values
|
||||||
|
* @param count count
|
||||||
|
*/
|
||||||
|
public static void counterIncrement(final String name, final String[] labelValues, final long count) {
|
||||||
|
Optional.ofNullable(metricsRegister).ifPresent(register -> register.counterIncrement(name, labelValues, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gauge increment.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param labelValues label values
|
||||||
|
*/
|
||||||
|
public static void gaugeIncrement(final String name, final String[] labelValues) {
|
||||||
|
Optional.ofNullable(metricsRegister).ifPresent(register -> register.gaugeIncrement(name, labelValues));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gauge increment.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
*/
|
||||||
|
public static void gaugeIncrement(final String name) {
|
||||||
|
gaugeIncrement(name, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gauge decrement.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param labelValues label values
|
||||||
|
*/
|
||||||
|
public static void gaugeDecrement(final String name, final String[] labelValues) {
|
||||||
|
Optional.ofNullable(metricsRegister).ifPresent(register -> register.gaugeDecrement(name, labelValues));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gauge decrement.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
*/
|
||||||
|
public static void gaugeDecrement(final String name) {
|
||||||
|
gaugeDecrement(name, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record time by duration.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param labelValues label values
|
||||||
|
* @param duration duration
|
||||||
|
*/
|
||||||
|
public static void recordTime(final String name, final String[] labelValues, final long duration) {
|
||||||
|
Optional.ofNullable(metricsRegister).ifPresent(register -> register.recordTime(name, labelValues, duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record time by duration.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param duration duration
|
||||||
|
*/
|
||||||
|
public static void recordTime(final String name, final long duration) {
|
||||||
|
recordTime(name, null, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] getLabelNames(final List<String> labels) {
|
||||||
|
return labels.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
}
|
@ -18,28 +18,19 @@
|
|||||||
package org.dromara.hmily.metrics.spi;
|
package org.dromara.hmily.metrics.spi;
|
||||||
|
|
||||||
import org.dromara.hmily.config.api.entity.HmilyMetricsConfig;
|
import org.dromara.hmily.config.api.entity.HmilyMetricsConfig;
|
||||||
import org.dromara.hmily.metrics.api.MetricsTrackerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metrics tracker manager.
|
* Metrics tracker manager.
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
*/
|
||||||
public interface MetricsTrackerManager {
|
public interface MetricsBootService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start metrics tracker.
|
* Start metrics tracker.
|
||||||
*
|
*
|
||||||
* @param metricsConfig metrics config
|
* @param metricsConfig metrics config
|
||||||
|
* @param register the register
|
||||||
*/
|
*/
|
||||||
void start(HmilyMetricsConfig metricsConfig);
|
void start(HmilyMetricsConfig metricsConfig, MetricsRegister register);
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets metrics tracker factory.
|
|
||||||
*
|
|
||||||
* @return metrics tracker factory
|
|
||||||
*/
|
|
||||||
MetricsTrackerFactory getMetricsTrackerFactory();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop metrics tracker.
|
* Stop metrics tracker.
|
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.spi;
|
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metrics Handler facade.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public interface MetricsHandlerFacade {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Increment of counter metrics tracker.
|
|
||||||
*
|
|
||||||
* @param metricsLabel metrics label
|
|
||||||
* @param labelValues label values
|
|
||||||
*/
|
|
||||||
void counterIncrement(String metricsLabel, String... labelValues);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Increment of gauge metrics tracker.
|
|
||||||
*
|
|
||||||
* @param metricsLabel metrics label
|
|
||||||
* @param labelValues label values
|
|
||||||
*/
|
|
||||||
void gaugeIncrement(String metricsLabel, String... labelValues);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decrement of gauge metrics tracker.
|
|
||||||
*
|
|
||||||
* @param metricsLabel metrics label
|
|
||||||
* @param labelValues label values
|
|
||||||
*/
|
|
||||||
void gaugeDecrement(String metricsLabel, String... labelValues);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start timer of histogram metrics tracker.
|
|
||||||
*
|
|
||||||
* @param metricsLabel metrics label
|
|
||||||
* @param labelValues label values
|
|
||||||
* @return histogram metrics tracker delegate
|
|
||||||
*/
|
|
||||||
Supplier<Boolean> histogramStartTimer(String metricsLabel, String... labelValues);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start timer of summary metrics tracker.
|
|
||||||
*
|
|
||||||
* @param metricsLabel metrics label
|
|
||||||
* @param labelValues label values
|
|
||||||
* @return summary metrics tracker delegate
|
|
||||||
*/
|
|
||||||
Supplier<Boolean> summaryStartTimer(String metricsLabel, String... labelValues);
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.spi;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import org.dromara.hmily.spi.ExtensionLoaderFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The type Metrics handler facade engine.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public final class MetricsHandlerFacadeEngine {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load MetricsHandlerFacade optional.
|
|
||||||
*
|
|
||||||
* @return the optional
|
|
||||||
*/
|
|
||||||
public static Optional<MetricsHandlerFacade> load() {
|
|
||||||
return Optional.ofNullable(ExtensionLoaderFactory.load(MetricsHandlerFacade.class));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dromara.hmily.metrics.spi;
|
|
||||||
|
|
||||||
import org.dromara.hmily.config.api.entity.HmilyMetricsConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The interface Metrics init.
|
|
||||||
*
|
|
||||||
* @author xiaoyu
|
|
||||||
*/
|
|
||||||
public interface MetricsInit extends AutoCloseable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init.
|
|
||||||
*
|
|
||||||
* @param metricsConfig the metrics config
|
|
||||||
*/
|
|
||||||
void init(HmilyMetricsConfig metricsConfig);
|
|
||||||
}
|
|
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* 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.dromara.hmily.metrics.spi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metrics register.
|
||||||
|
*/
|
||||||
|
public interface MetricsRegister {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register gauge.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param labelNames label names
|
||||||
|
* @param document document for gauge
|
||||||
|
*/
|
||||||
|
void registerGauge(String name, String[] labelNames, String document);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register counter.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param labelNames label names
|
||||||
|
* @param document document for counter
|
||||||
|
*/
|
||||||
|
void registerCounter(String name, String[] labelNames, String document);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register histogram.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param labelNames label names
|
||||||
|
* @param document document for histogram
|
||||||
|
*/
|
||||||
|
void registerHistogram(String name, String[] labelNames, String document);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counter increment by count.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param labelValues label values
|
||||||
|
* @param count count
|
||||||
|
*/
|
||||||
|
void counterIncrement(String name, String[] labelValues, long count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gauge increment.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param labelValues label values
|
||||||
|
*/
|
||||||
|
void gaugeIncrement(String name, String[] labelValues);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gauge decrement.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param labelValues label values
|
||||||
|
*/
|
||||||
|
void gaugeDecrement(String name, String[] labelValues);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record time by duration.
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param labelValues label values
|
||||||
|
* @param duration duration
|
||||||
|
*/
|
||||||
|
void recordTime(String name, String[] labelValues, long duration);
|
||||||
|
}
|
@ -20,8 +20,8 @@
|
|||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hmily</artifactId>
|
|
||||||
<groupId>org.dromara</groupId>
|
<groupId>org.dromara</groupId>
|
||||||
|
<artifactId>hmily</artifactId>
|
||||||
<version>2.1.2-SNAPSHOT</version>
|
<version>2.1.2-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -28,8 +28,8 @@ import org.dromara.hmily.core.context.HmilyContextHolder;
|
|||||||
import org.dromara.hmily.core.context.HmilyTransactionContext;
|
import org.dromara.hmily.core.context.HmilyTransactionContext;
|
||||||
import org.dromara.hmily.core.repository.HmilyRepositoryStorage;
|
import org.dromara.hmily.core.repository.HmilyRepositoryStorage;
|
||||||
import org.dromara.hmily.core.service.HmilyTransactionHandler;
|
import org.dromara.hmily.core.service.HmilyTransactionHandler;
|
||||||
import org.dromara.hmily.metrics.enums.MetricsLabelEnum;
|
import org.dromara.hmily.metrics.constant.LabelNames;
|
||||||
import org.dromara.hmily.metrics.spi.MetricsHandlerFacadeEngine;
|
import org.dromara.hmily.metrics.reporter.MetricsReporter;
|
||||||
import org.dromara.hmily.repository.spi.entity.HmilyParticipant;
|
import org.dromara.hmily.repository.spi.entity.HmilyParticipant;
|
||||||
import org.dromara.hmily.tac.core.transaction.HmilyTacParticipantCoordinator;
|
import org.dromara.hmily.tac.core.transaction.HmilyTacParticipantCoordinator;
|
||||||
|
|
||||||
@ -46,6 +46,10 @@ public class ParticipantHmilyTacTransactionHandler implements HmilyTransactionHa
|
|||||||
|
|
||||||
private final HmilyTacParticipantCoordinator coordinator = HmilyTacParticipantCoordinator.getInstance();
|
private final HmilyTacParticipantCoordinator coordinator = HmilyTacParticipantCoordinator.getInstance();
|
||||||
|
|
||||||
|
static {
|
||||||
|
MetricsReporter.registerCounter(LabelNames.TRANSACTION_STATUS, new String[]{"type", "role", "status"}, "collect hmily transaction count");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object handleTransaction(final ProceedingJoinPoint point, final HmilyTransactionContext context) throws Throwable {
|
public Object handleTransaction(final ProceedingJoinPoint point, final HmilyTransactionContext context) throws Throwable {
|
||||||
HmilyParticipant hmilyParticipant = null;
|
HmilyParticipant hmilyParticipant = null;
|
||||||
@ -69,14 +73,12 @@ public class ParticipantHmilyTacTransactionHandler implements HmilyTransactionHa
|
|||||||
HmilyContextHolder.remove();
|
HmilyContextHolder.remove();
|
||||||
}
|
}
|
||||||
case CONFIRMING:
|
case CONFIRMING:
|
||||||
MetricsHandlerFacadeEngine.load().ifPresent(metricsHandlerFacade -> metricsHandlerFacade.counterIncrement(MetricsLabelEnum.TRANSACTION_STATUS.getName(),
|
MetricsReporter.counterIncrement(LabelNames.TRANSACTION_STATUS, new String[]{TransTypeEnum.TAC.name(), HmilyRoleEnum.PARTICIPANT.name(), HmilyActionEnum.CONFIRMING.name()});
|
||||||
TransTypeEnum.TAC.name(), HmilyRoleEnum.PARTICIPANT.name(), HmilyActionEnum.CONFIRMING.name()));
|
|
||||||
List<HmilyParticipant> confirmList = HmilyParticipantCacheManager.getInstance().get(context.getParticipantId());
|
List<HmilyParticipant> confirmList = HmilyParticipantCacheManager.getInstance().get(context.getParticipantId());
|
||||||
coordinator.commitParticipant(confirmList, context.getParticipantId());
|
coordinator.commitParticipant(confirmList, context.getParticipantId());
|
||||||
break;
|
break;
|
||||||
case CANCELING:
|
case CANCELING:
|
||||||
MetricsHandlerFacadeEngine.load().ifPresent(metricsHandlerFacade -> metricsHandlerFacade.counterIncrement(MetricsLabelEnum.TRANSACTION_STATUS.getName(),
|
MetricsReporter.counterIncrement(LabelNames.TRANSACTION_STATUS, new String[]{TransTypeEnum.TAC.name(), HmilyRoleEnum.PARTICIPANT.name(), HmilyActionEnum.CANCELING.name()});
|
||||||
TransTypeEnum.TAC.name(), HmilyRoleEnum.PARTICIPANT.name(), HmilyActionEnum.CANCELING.name()));
|
|
||||||
List<HmilyParticipant> cancelList = HmilyParticipantCacheManager.getInstance().get(context.getParticipantId());
|
List<HmilyParticipant> cancelList = HmilyParticipantCacheManager.getInstance().get(context.getParticipantId());
|
||||||
coordinator.rollbackParticipant(cancelList, context.getParticipantId());
|
coordinator.rollbackParticipant(cancelList, context.getParticipantId());
|
||||||
break;
|
break;
|
||||||
|
@ -27,14 +27,13 @@ import org.dromara.hmily.core.disruptor.HmilyDisruptor;
|
|||||||
import org.dromara.hmily.core.disruptor.handler.HmilyTransactionEventConsumer;
|
import org.dromara.hmily.core.disruptor.handler.HmilyTransactionEventConsumer;
|
||||||
import org.dromara.hmily.core.service.HmilyTransactionHandler;
|
import org.dromara.hmily.core.service.HmilyTransactionHandler;
|
||||||
import org.dromara.hmily.core.service.HmilyTransactionTask;
|
import org.dromara.hmily.core.service.HmilyTransactionTask;
|
||||||
import org.dromara.hmily.metrics.enums.MetricsLabelEnum;
|
import org.dromara.hmily.metrics.constant.LabelNames;
|
||||||
import org.dromara.hmily.metrics.spi.MetricsHandlerFacade;
|
import org.dromara.hmily.metrics.reporter.MetricsReporter;
|
||||||
import org.dromara.hmily.metrics.spi.MetricsHandlerFacadeEngine;
|
|
||||||
import org.dromara.hmily.repository.spi.entity.HmilyTransaction;
|
import org.dromara.hmily.repository.spi.entity.HmilyTransaction;
|
||||||
import org.dromara.hmily.tac.core.transaction.HmilyTacTransactionManager;
|
import org.dromara.hmily.tac.core.transaction.HmilyTacTransactionManager;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.time.LocalDateTime;
|
||||||
import java.util.function.Supplier;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,6 +47,12 @@ public class StarterHmilyTacTransactionHandler implements HmilyTransactionHandle
|
|||||||
|
|
||||||
private final HmilyDisruptor<HmilyTransactionTask> disruptor;
|
private final HmilyDisruptor<HmilyTransactionTask> disruptor;
|
||||||
|
|
||||||
|
static {
|
||||||
|
MetricsReporter.registerCounter(LabelNames.TRANSACTION_TOTAL, new String[]{"type"}, "hmily transaction total count");
|
||||||
|
MetricsReporter.registerHistogram(LabelNames.TRANSACTION_LATENCY, "hmily transaction Latency Histogram Millis (ms)");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new Starter hmily tac transaction handler.
|
* Instantiates a new Starter hmily tac transaction handler.
|
||||||
*/
|
*/
|
||||||
@ -61,13 +66,9 @@ public class StarterHmilyTacTransactionHandler implements HmilyTransactionHandle
|
|||||||
public Object handleTransaction(final ProceedingJoinPoint point, final HmilyTransactionContext context)
|
public Object handleTransaction(final ProceedingJoinPoint point, final HmilyTransactionContext context)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
Object returnValue;
|
Object returnValue;
|
||||||
Supplier<Boolean> histogramSupplier = null;
|
MetricsReporter.counterIncrement(LabelNames.TRANSACTION_TOTAL, new String[]{TransTypeEnum.TAC.name()});
|
||||||
Optional<MetricsHandlerFacade> metricsFacade = MetricsHandlerFacadeEngine.load();
|
LocalDateTime starterTime = LocalDateTime.now();
|
||||||
try {
|
try {
|
||||||
if (metricsFacade.isPresent()) {
|
|
||||||
metricsFacade.get().counterIncrement(MetricsLabelEnum.TRANSACTION_TOTAL.getName(), TransTypeEnum.TAC.name());
|
|
||||||
histogramSupplier = metricsFacade.get().histogramStartTimer(MetricsLabelEnum.TRANSACTION_LATENCY.getName(), TransTypeEnum.TAC.name());
|
|
||||||
}
|
|
||||||
tm.begin();
|
tm.begin();
|
||||||
try {
|
try {
|
||||||
//execute try
|
//execute try
|
||||||
@ -76,8 +77,7 @@ public class StarterHmilyTacTransactionHandler implements HmilyTransactionHandle
|
|||||||
//if exception ,execute cancel
|
//if exception ,execute cancel
|
||||||
final HmilyTransaction currentTransaction = tm.getHmilyTransaction();
|
final HmilyTransaction currentTransaction = tm.getHmilyTransaction();
|
||||||
disruptor.getProvider().onData(() -> {
|
disruptor.getProvider().onData(() -> {
|
||||||
metricsFacade.ifPresent(metricsHandlerFacade -> metricsHandlerFacade.counterIncrement(MetricsLabelEnum.TRANSACTION_STATUS.getName(),
|
MetricsReporter.counterIncrement(LabelNames.TRANSACTION_STATUS, new String[]{TransTypeEnum.TAC.name(), HmilyRoleEnum.START.name(), HmilyActionEnum.CANCELING.name()});
|
||||||
TransTypeEnum.TAC.name(), HmilyRoleEnum.START.name(), HmilyActionEnum.CANCELING.name()));
|
|
||||||
tm.rollback(currentTransaction);
|
tm.rollback(currentTransaction);
|
||||||
});
|
});
|
||||||
throw throwable;
|
throw throwable;
|
||||||
@ -85,16 +85,13 @@ public class StarterHmilyTacTransactionHandler implements HmilyTransactionHandle
|
|||||||
// execute confirm
|
// execute confirm
|
||||||
final HmilyTransaction currentTransaction = tm.getHmilyTransaction();
|
final HmilyTransaction currentTransaction = tm.getHmilyTransaction();
|
||||||
disruptor.getProvider().onData(() -> {
|
disruptor.getProvider().onData(() -> {
|
||||||
metricsFacade.ifPresent(metricsHandlerFacade -> metricsHandlerFacade.counterIncrement(MetricsLabelEnum.TRANSACTION_STATUS.getName(),
|
MetricsReporter.counterIncrement(LabelNames.TRANSACTION_STATUS, new String[]{TransTypeEnum.TAC.name(), HmilyRoleEnum.START.name(), HmilyActionEnum.CONFIRMING.name()});
|
||||||
TransTypeEnum.TAC.name(), HmilyRoleEnum.START.name(), HmilyActionEnum.CONFIRMING.name()));
|
|
||||||
tm.commit(currentTransaction);
|
tm.commit(currentTransaction);
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
HmilyContextHolder.remove();
|
HmilyContextHolder.remove();
|
||||||
tm.remove();
|
tm.remove();
|
||||||
if (null != histogramSupplier) {
|
MetricsReporter.recordTime(LabelNames.TRANSACTION_LATENCY, starterTime.until(LocalDateTime.now(), ChronoUnit.MILLIS));
|
||||||
histogramSupplier.get();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
@ -28,8 +28,8 @@ import org.dromara.hmily.core.context.HmilyContextHolder;
|
|||||||
import org.dromara.hmily.core.context.HmilyTransactionContext;
|
import org.dromara.hmily.core.context.HmilyTransactionContext;
|
||||||
import org.dromara.hmily.core.repository.HmilyRepositoryStorage;
|
import org.dromara.hmily.core.repository.HmilyRepositoryStorage;
|
||||||
import org.dromara.hmily.core.service.HmilyTransactionHandler;
|
import org.dromara.hmily.core.service.HmilyTransactionHandler;
|
||||||
import org.dromara.hmily.metrics.enums.MetricsLabelEnum;
|
import org.dromara.hmily.metrics.constant.LabelNames;
|
||||||
import org.dromara.hmily.metrics.spi.MetricsHandlerFacadeEngine;
|
import org.dromara.hmily.metrics.reporter.MetricsReporter;
|
||||||
import org.dromara.hmily.repository.spi.entity.HmilyParticipant;
|
import org.dromara.hmily.repository.spi.entity.HmilyParticipant;
|
||||||
import org.dromara.hmily.tcc.executor.HmilyTccTransactionExecutor;
|
import org.dromara.hmily.tcc.executor.HmilyTccTransactionExecutor;
|
||||||
|
|
||||||
@ -46,6 +46,10 @@ public class ParticipantHmilyTccTransactionHandler implements HmilyTransactionHa
|
|||||||
|
|
||||||
private final HmilyTccTransactionExecutor executor = HmilyTccTransactionExecutor.getInstance();
|
private final HmilyTccTransactionExecutor executor = HmilyTccTransactionExecutor.getInstance();
|
||||||
|
|
||||||
|
static {
|
||||||
|
MetricsReporter.registerCounter(LabelNames.TRANSACTION_STATUS, new String[]{"type", "role", "status"}, "collect hmily transaction count");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object handleTransaction(final ProceedingJoinPoint point, final HmilyTransactionContext context) throws Throwable {
|
public Object handleTransaction(final ProceedingJoinPoint point, final HmilyTransactionContext context) throws Throwable {
|
||||||
HmilyParticipant hmilyParticipant = null;
|
HmilyParticipant hmilyParticipant = null;
|
||||||
@ -69,13 +73,11 @@ public class ParticipantHmilyTccTransactionHandler implements HmilyTransactionHa
|
|||||||
HmilyContextHolder.remove();
|
HmilyContextHolder.remove();
|
||||||
}
|
}
|
||||||
case CONFIRMING:
|
case CONFIRMING:
|
||||||
MetricsHandlerFacadeEngine.load().ifPresent(metricsHandlerFacade -> metricsHandlerFacade.counterIncrement(MetricsLabelEnum.TRANSACTION_STATUS.getName(),
|
MetricsReporter.counterIncrement(LabelNames.TRANSACTION_STATUS, new String[]{TransTypeEnum.TCC.name(), HmilyRoleEnum.PARTICIPANT.name(), HmilyActionEnum.CONFIRMING.name()});
|
||||||
TransTypeEnum.TCC.name(), HmilyRoleEnum.PARTICIPANT.name(), HmilyActionEnum.CONFIRMING.name()));
|
|
||||||
List<HmilyParticipant> confirmList = HmilyParticipantCacheManager.getInstance().get(context.getParticipantId());
|
List<HmilyParticipant> confirmList = HmilyParticipantCacheManager.getInstance().get(context.getParticipantId());
|
||||||
return executor.participantConfirm(confirmList, context.getParticipantId());
|
return executor.participantConfirm(confirmList, context.getParticipantId());
|
||||||
case CANCELING:
|
case CANCELING:
|
||||||
MetricsHandlerFacadeEngine.load().ifPresent(metricsHandlerFacade -> metricsHandlerFacade.counterIncrement(MetricsLabelEnum.TRANSACTION_STATUS.getName(),
|
MetricsReporter.counterIncrement(LabelNames.TRANSACTION_STATUS, new String[]{TransTypeEnum.TCC.name(), HmilyRoleEnum.PARTICIPANT.name(), HmilyActionEnum.CANCELING.name()});
|
||||||
TransTypeEnum.TCC.name(), HmilyRoleEnum.PARTICIPANT.name(), HmilyActionEnum.CANCELING.name()));
|
|
||||||
List<HmilyParticipant> cancelList = HmilyParticipantCacheManager.getInstance().get(context.getParticipantId());
|
List<HmilyParticipant> cancelList = HmilyParticipantCacheManager.getInstance().get(context.getParticipantId());
|
||||||
return executor.participantCancel(cancelList, context.getParticipantId());
|
return executor.participantCancel(cancelList, context.getParticipantId());
|
||||||
default:
|
default:
|
||||||
|
@ -28,14 +28,13 @@ import org.dromara.hmily.core.disruptor.handler.HmilyTransactionEventConsumer;
|
|||||||
import org.dromara.hmily.core.holder.HmilyTransactionHolder;
|
import org.dromara.hmily.core.holder.HmilyTransactionHolder;
|
||||||
import org.dromara.hmily.core.service.HmilyTransactionHandler;
|
import org.dromara.hmily.core.service.HmilyTransactionHandler;
|
||||||
import org.dromara.hmily.core.service.HmilyTransactionTask;
|
import org.dromara.hmily.core.service.HmilyTransactionTask;
|
||||||
import org.dromara.hmily.metrics.enums.MetricsLabelEnum;
|
import org.dromara.hmily.metrics.constant.LabelNames;
|
||||||
import org.dromara.hmily.metrics.spi.MetricsHandlerFacade;
|
import org.dromara.hmily.metrics.reporter.MetricsReporter;
|
||||||
import org.dromara.hmily.metrics.spi.MetricsHandlerFacadeEngine;
|
|
||||||
import org.dromara.hmily.repository.spi.entity.HmilyTransaction;
|
import org.dromara.hmily.repository.spi.entity.HmilyTransaction;
|
||||||
import org.dromara.hmily.tcc.executor.HmilyTccTransactionExecutor;
|
import org.dromara.hmily.tcc.executor.HmilyTccTransactionExecutor;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.time.LocalDateTime;
|
||||||
import java.util.function.Supplier;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,6 +48,11 @@ public class StarterHmilyTccTransactionHandler implements HmilyTransactionHandle
|
|||||||
|
|
||||||
private HmilyDisruptor<HmilyTransactionTask> disruptor;
|
private HmilyDisruptor<HmilyTransactionTask> disruptor;
|
||||||
|
|
||||||
|
static {
|
||||||
|
MetricsReporter.registerCounter(LabelNames.TRANSACTION_TOTAL, new String[]{"type"}, "hmily transaction total count");
|
||||||
|
MetricsReporter.registerHistogram(LabelNames.TRANSACTION_LATENCY, "hmily transaction Latency Histogram Millis (ms)");
|
||||||
|
}
|
||||||
|
|
||||||
public StarterHmilyTccTransactionHandler() {
|
public StarterHmilyTccTransactionHandler() {
|
||||||
disruptor = new HmilyDisruptor<>(new HmilyTransactionEventConsumer(),
|
disruptor = new HmilyDisruptor<>(new HmilyTransactionEventConsumer(),
|
||||||
Runtime.getRuntime().availableProcessors() << 1, HmilyDisruptor.DEFAULT_SIZE);
|
Runtime.getRuntime().availableProcessors() << 1, HmilyDisruptor.DEFAULT_SIZE);
|
||||||
@ -59,13 +63,9 @@ public class StarterHmilyTccTransactionHandler implements HmilyTransactionHandle
|
|||||||
public Object handleTransaction(final ProceedingJoinPoint point, final HmilyTransactionContext context)
|
public Object handleTransaction(final ProceedingJoinPoint point, final HmilyTransactionContext context)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
Object returnValue;
|
Object returnValue;
|
||||||
Supplier<Boolean> histogramSupplier = null;
|
MetricsReporter.counterIncrement(LabelNames.TRANSACTION_TOTAL, new String[]{TransTypeEnum.TCC.name()});
|
||||||
Optional<MetricsHandlerFacade> handlerFacade = MetricsHandlerFacadeEngine.load();
|
LocalDateTime starterTime = LocalDateTime.now();
|
||||||
try {
|
try {
|
||||||
if (handlerFacade.isPresent()) {
|
|
||||||
handlerFacade.get().counterIncrement(MetricsLabelEnum.TRANSACTION_TOTAL.getName(), TransTypeEnum.TCC.name());
|
|
||||||
histogramSupplier = handlerFacade.get().histogramStartTimer(MetricsLabelEnum.TRANSACTION_LATENCY.getName(), TransTypeEnum.TCC.name());
|
|
||||||
}
|
|
||||||
HmilyTransaction hmilyTransaction = executor.preTry(point);
|
HmilyTransaction hmilyTransaction = executor.preTry(point);
|
||||||
try {
|
try {
|
||||||
//execute try
|
//execute try
|
||||||
@ -76,8 +76,7 @@ public class StarterHmilyTccTransactionHandler implements HmilyTransactionHandle
|
|||||||
//if exception ,execute cancel
|
//if exception ,execute cancel
|
||||||
final HmilyTransaction currentTransaction = HmilyTransactionHolder.getInstance().getCurrentTransaction();
|
final HmilyTransaction currentTransaction = HmilyTransactionHolder.getInstance().getCurrentTransaction();
|
||||||
disruptor.getProvider().onData(() -> {
|
disruptor.getProvider().onData(() -> {
|
||||||
handlerFacade.ifPresent(metricsHandlerFacade -> metricsHandlerFacade.counterIncrement(MetricsLabelEnum.TRANSACTION_STATUS.getName(),
|
MetricsReporter.counterIncrement(LabelNames.TRANSACTION_STATUS, new String[]{TransTypeEnum.TCC.name(), HmilyRoleEnum.START.name(), HmilyActionEnum.CANCELING.name()});
|
||||||
TransTypeEnum.TCC.name(), HmilyRoleEnum.START.name(), HmilyActionEnum.CANCELING.name()));
|
|
||||||
executor.globalCancel(currentTransaction);
|
executor.globalCancel(currentTransaction);
|
||||||
});
|
});
|
||||||
throw throwable;
|
throw throwable;
|
||||||
@ -85,16 +84,13 @@ public class StarterHmilyTccTransactionHandler implements HmilyTransactionHandle
|
|||||||
//execute confirm
|
//execute confirm
|
||||||
final HmilyTransaction currentTransaction = HmilyTransactionHolder.getInstance().getCurrentTransaction();
|
final HmilyTransaction currentTransaction = HmilyTransactionHolder.getInstance().getCurrentTransaction();
|
||||||
disruptor.getProvider().onData(() -> {
|
disruptor.getProvider().onData(() -> {
|
||||||
handlerFacade.ifPresent(metricsHandlerFacade -> metricsHandlerFacade.counterIncrement(MetricsLabelEnum.TRANSACTION_STATUS.getName(),
|
MetricsReporter.counterIncrement(LabelNames.TRANSACTION_STATUS, new String[]{TransTypeEnum.TCC.name(), HmilyRoleEnum.START.name(), HmilyActionEnum.CONFIRMING.name()});
|
||||||
TransTypeEnum.TCC.name(), HmilyRoleEnum.START.name(), HmilyActionEnum.CONFIRMING.name()));
|
|
||||||
executor.globalConfirm(currentTransaction);
|
executor.globalConfirm(currentTransaction);
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
HmilyContextHolder.remove();
|
HmilyContextHolder.remove();
|
||||||
executor.remove();
|
executor.remove();
|
||||||
if (null != histogramSupplier) {
|
MetricsReporter.recordTime(LabelNames.TRANSACTION_LATENCY, starterTime.until(LocalDateTime.now(), ChronoUnit.MILLIS));
|
||||||
histogramSupplier.get();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user