zoukankan      html  css  js  c++  java
  • Metrics的开发代码与配置

    依赖jar的pom配置

    <!--metrics相关-->
            <dependency>
                <groupId>io.dropwizard.metrics</groupId>
                <artifactId>metrics-core</artifactId>
                <version>4.0.0</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/io.dropwizard.metrics/metrics-jvm -->
            <dependency>
                <groupId>io.dropwizard.metrics</groupId>
                <artifactId>metrics-jvm</artifactId>
                <version>4.0.0</version>
            </dependency>
            <dependency>
                <groupId>com.github.davidb</groupId>
                <artifactId>metrics-influxdb</artifactId>
                <version>1.1.0</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <scope>compile</scope>
            </dependency>

    spring中bean配置

        <context:component-scan base-package="com.example.common.metrics"/>
        <bean id="metricRegistry" class="com.codahale.metrics.MetricRegistry"/>

    基础工具:MetricsBase.java

    import com.codahale.metrics.Histogram;
    import com.codahale.metrics.Meter;
    import com.codahale.metrics.MetricRegistry;
    import com.codahale.metrics.Timer;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    public class MetricsBase {
        private final Map<String, Meter> meterMap = new ConcurrentHashMap<>();
        private final Map<String, Timer> timerMap = new ConcurrentHashMap<>();
        private final Map<String, Histogram> histogramMap = new ConcurrentHashMap<>();
    
        public static String keyGen(String meterMeasurements) {
            String[] parent = parent();
            return MetricRegistry.name(parent[0], parent[1], meterMeasurements);
        }
    
        /**
         * 获取Meter实例
         *
         * @param metricsKey
         * @return
         */
        public Meter getMeter(String metricsKey, MetricRegistry metricRegistry) {
            Meter m = meterMap.get(metricsKey);
            if (m != null) {
                return m;
            }
            synchronized (MetricsBase.class) {
                Meter metrics = meterMap.get(metricsKey);
                if (metrics != null) {
                    return metrics;
                } else {
                    Meter object = metricRegistry.meter(metricsKey);
                    meterMap.putIfAbsent(metricsKey, object);
                    return object;
                }
            }
        }
    
        /**
         * 获取Timer实例
         *
         * @param metricsKey
         * @return
         */
        public Timer getTimer(String metricsKey, MetricRegistry metricRegistry) {
            Timer t = timerMap.get(metricsKey);
            if (t != null) {
                return t;
            }
            synchronized (MetricsBase.class) {
                Timer timer = timerMap.get(metricsKey);
                if (timer != null) {
                    return timer;
                } else {
                    Timer object = metricRegistry.timer(metricsKey);
                    timerMap.putIfAbsent(metricsKey, object);
                    return object;
                }
            }
        }
    
        /**
         * Histogram 直方图数据
         * @param metricsKey
         * @return
         */
        public Histogram getHistogram(String metricsKey, MetricRegistry metricRegistry) {
            Histogram t = histogramMap.get(metricsKey);
            if (t != null) {
                return t;
            }
            synchronized (MetricsBase.class) {
                Histogram histogram = histogramMap.get(metricsKey);
                if (histogram != null) {
                    return histogram;
                } else {
                    Histogram object = metricRegistry.histogram(metricsKey);
                    histogramMap.putIfAbsent(metricsKey, object);
                    return object;
                }
            }
        }
    
    
        public static String[] parent(){
            StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
            StackTraceElement stackTraceElement = stackTrace[4];
            String className = stackTraceElement.getClassName();
            String []classNames = className.split("\.");
            return new String[]{classNames[classNames.length-1], stackTraceElement.getMethodName()};
        }
    }

    调用方法:MetricsFactory.java

    import com.codahale.metrics.Histogram;
    import com.codahale.metrics.Meter;
    import com.codahale.metrics.MetricRegistry;
    import com.codahale.metrics.Timer;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class MetricsFactory extends MetricsBase{
        protected Logger log = LoggerFactory.getLogger(this.getClass());
        private final static String TIMER_MEASUREMENTS = "smsTimer";
        private final static String METER_MEASUREMENTS = "smsMeter";
        private final static String HISTOGRAM_MEASUREMENTS = "smsHistogram";
    
        private MetricsFactory() {
        }
    
        private static class MetricsFactoryInstance {
            private static final MetricsFactory INSTANCE = new MetricsFactory();
        }
    
        public static MetricsFactory getInstance() {
            return MetricsFactoryInstance.INSTANCE;
        }
    
    
        /**
         * 接口TPS统计
         * @param metricRegistry
         * @return
         */
        public void getMeter(MetricRegistry metricRegistry) {
            try {
                String metricKey = keyGen(METER_MEASUREMENTS);
                log.info("MetricsFactory.getMeter.metricKey:{}",metricKey);
                getMeter(metricKey, metricRegistry).mark();
            } catch (Exception e) {
                log.error("[NoticeCenter]create metrics(meter) error", e);
            }
        }
    
        /**
         * 接口耗时统计
         * @param metricRegistry
         * @return
         */
        public Timer.Context getTimer(MetricRegistry metricRegistry) {
            try {
                String metricKey = keyGen(TIMER_MEASUREMENTS);
                log.info("MetricsFactory.getTimer.metricKey:{}",metricKey);
                return getTimer(metricKey, metricRegistry).time();
            } catch (Exception e) {
                log.error("[NoticeCenter]create metrics(timer) error", e);
                return null;
            }
        }
        /**
         * 停止Metrics.Timer记录
         * @param context
         */
        public void stopTimer(Timer.Context context) {
            try {
                if (context != null) {
                    context.stop();
                }
            } catch (Exception e) {
                log.error("[NoticeCenter]metrics(timer) stop error", e);
            }
        }
    
        /**
         * 直方图数据
         * @param metricRegistry
         * @return
         */
        public Histogram getHistogram(MetricRegistry metricRegistry) {
            try {
                String metricKey = keyGen(HISTOGRAM_MEASUREMENTS);
                return getHistogram(metricKey, metricRegistry);
            } catch (Exception e) {
                log.error("[NoticeCenter]create metrics(timer) error", e);
                return null;
            }
        }
    }

    初始化:APPMertics.java

    import com.codahale.metrics.ConsoleReporter;
    import com.codahale.metrics.MetricFilter;
    import com.codahale.metrics.MetricRegistry;
    import com.codahale.metrics.ScheduledReporter;
    import com.codahale.metrics.jvm.*;
    import metrics_influxdb.HttpInfluxdbProtocol;
    import metrics_influxdb.InfluxdbReporter;
    import metrics_influxdb.api.measurements.CategoriesMetricMeasurementTransformer;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    import org.springframework.util.StringUtils;
    
    import java.lang.management.ManagementFactory;
    import java.net.InetAddress;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.concurrent.TimeUnit;
    
    @Component
    public class AppMetrics implements InitializingBean {
    
        private static final Logger log = LoggerFactory.getLogger(AppMetrics.class);
    
        @Autowired
        private MetricRegistry metricRegistry;
    
        @Value("${server.port}")
        private int port;
    
        @Value("${influxdb.reportJvm}")
        private boolean reportJvm;
    
        @Value("${influxdb.host}")
        private String influxHost;
    
    //    @Value("${influxdb.user}")
    //    private String influxUser;
    //
    //    @Value("${influxdb.passwd}")
    //    private String influxPasswd;
    
        @Value("${influxdb.db}")
        private String influxDB;
    
        @Value("${influxdb.port}")
        private int influxPort;
    
        @Value("${metrics.reporterInterval}")
        private long reporterInterval;
    
        public void afterPropertiesSet() throws Exception {
            log.info("AppMetrics init ***********,port: {}, reportJvm: {}, influxdb: {}, influxPort: {},influxDB: {}", port,reportJvm, influxHost, influxPort, influxDB);
            if (reportJvm){
                initJVM();
            }
    
            if (StringUtils.isEmpty(influxHost)) {
                startConsoleReporter();
            } else {
                try {
                    influxDbReporter();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        private void initJVM() {
            metricRegistry.register("jvm.gc", new GarbageCollectorMetricSet());
            metricRegistry.register("jvm.thread-state", new CachedThreadStatesGaugeSet(10, TimeUnit.SECONDS));
            metricRegistry.register("jvm.mem", new MemoryUsageGaugeSet());
            metricRegistry.register("jvm.attr", new JvmAttributeGaugeSet());
            metricRegistry.register("jvm.buffer-pool", new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()));
            metricRegistry.register("jvm.fd.usage", new FileDescriptorRatioGauge());
        }
    
    
        private void influxDbReporter() throws Exception{
            log.info("use influxdb as reporter {}:{}, {}", influxHost, influxPort, influxDB);
            final ScheduledReporter reporter = InfluxdbReporter.forRegistry(metricRegistry)
    //                .protocol(new HttpInfluxdbProtocol("http", influxHost, influxPort, influxUser, influxPasswd, influxDB))
                    .protocol(new HttpInfluxdbProtocol(influxHost, influxPort, influxDB))
                    .convertRatesTo(TimeUnit.SECONDS)
                    .convertDurationsTo(TimeUnit.MILLISECONDS)
                    .filter(MetricFilter.ALL)
                    .skipIdleMetrics(false)
                    .tag("client", Integer.toString(port))
                    .tag("server", InetAddress.getLocalHost().getHostAddress())
                    .transformer(new CategoriesMetricMeasurementTransformer("noticeName", "ruleName", "measurement"))
                    .build();
            long initalDelay = getBeginTime().getTimeInMillis() - System.currentTimeMillis();
            long period = reporterInterval * 1000;
            reporter.start(initalDelay, period, TimeUnit.MILLISECONDS);
        }
    
        private void startConsoleReporter() {
            log.info("use console as reporter");
            ConsoleReporter reporter = ConsoleReporter.forRegistry(metricRegistry)
                    .convertRatesTo(TimeUnit.SECONDS)
                    .convertDurationsTo(TimeUnit.MILLISECONDS)
                    .build();
            long initalDelay = getBeginTime().getTimeInMillis() - System.currentTimeMillis();
            long period = reporterInterval * 1000;
            reporter.start(initalDelay, period, TimeUnit.MILLISECONDS);
        }
    
        /**
         * 获取Metrics报告时间:
         * Metrics报告时间设定为启动后1分钟0秒开始,
         * 保证所有机器上的数据的开始时间都是从某分钟开始
         *
         * @return
         */
        private Calendar getBeginTime() {
            Calendar beginTime = Calendar.getInstance();
            beginTime.setTime(new Date());
            beginTime.add(Calendar.MINUTE, 1);
            beginTime.set(Calendar.SECOND, 0);//
            beginTime.set(Calendar.MILLISECOND, 0);// 毫秒
            return beginTime;
        }
    }

    以上工具类完成后在项目中就可以使用了!

    项目中properties属性配置

    #influxdb 配置参数
    #是否上报JVM性能数据
    influxdb.reportJvm=false
    influxdb.host=${content.influxdb.host}
    #当前服务端口
    server.port=-1
    #influxdb.port=${content.influxdb.port}
    influxdb.port=8086
    
    influxdb.user=root
    influxdb.passwd=root
    
    #influxdb.db=#{content.influxdb.name}
    influxdb.db=metrics
    #metrics数据上报时间间隔
    metrics.reporterInterval=10

     工具类的使用demo:

    @CrossOrigin(methods={RequestMethod.GET, RequestMethod.POST,RequestMethod.OPTIONS})
    @Controller
    @RequestMapping("/metrics")
    public class MetricsController extends BaseController {
        private final static Logger logger = LoggerFactory.getLogger(MetricsController.class);
    
        @Autowired
        MetricRegistry metricRegistry;
        @ResponseBody()
        @ResponseStatus(HttpStatus.CREATED)
        @RequestMapping(value="/detailQuery",method={RequestMethod.GET,RequestMethod.POST,RequestMethod.OPTIONS})
        public void detailQuery(
                HttpServletResponse response,
                @RequestParam(required = false) String jsonpcallback) {
            logger.info("metrics detailQuery");
            RpcResponseDTO<String> result = new RpcResponseDTO<>();
            result.setPayload("hello word");
            //接口耗时统计
            Timer.Context timerContext = MetricsFactory.getInstance().getTimer(metricRegistry);
          // excute method ... MetricsFactory.getInstance().stopTimer(timerContext);
    //接口TPS统计 MetricsFactory.getInstance().getMeter(metricRegistry); SpringMVCRpcHelper.renderJson(response, jsonpcallback, result); } }

    参考文献

      Metrics+Influxdb+Grafana构建监控系统(可能全网最详)

  • 相关阅读:
    MySQL中删除重复数据只保留一条
    js 的try catch应用
    jQuery中on()方法用法实例
    js老生常谈之this,constructor ,prototype
    spring自定义标签之 规范定义XSD
    jquery jgrid filterToolBar beforeSearch 修改postData
    Guava学习笔记:Optional优雅的使用null
    Java之Collections.emptyList()、emptySet()、emptyMap()的作用和好处以及要注意的地方
    Druid SQL 解析器概览
    访问者模式
  • 原文地址:https://www.cnblogs.com/bluesky-yuan/p/14835996.html
Copyright © 2011-2022 走看看