001/**
002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com).
003 * <p>
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 * http://www.apache.org/licenses/LICENSE-2.0
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package io.jboot.support.metric;
017
018import com.codahale.metrics.Gauge;
019import com.codahale.metrics.MetricRegistry;
020import com.codahale.metrics.health.HealthCheckRegistry;
021import com.codahale.metrics.health.jvm.ThreadDeadlockHealthCheck;
022import com.codahale.metrics.jvm.*;
023import com.jfinal.log.Log;
024import io.jboot.Jboot;
025import io.jboot.core.spi.JbootSpiLoader;
026import io.jboot.support.metric.reporter.console.JbootConsoleReporter;
027import io.jboot.support.metric.reporter.csv.CSVReporter;
028import io.jboot.support.metric.reporter.elasticsearch.ElasticsearchReporter;
029import io.jboot.support.metric.reporter.ganglia.GangliaReporter;
030import io.jboot.support.metric.reporter.graphite.JbootGraphiteReporter;
031import io.jboot.support.metric.reporter.influxdb.InfluxdbReporter;
032import io.jboot.support.metric.reporter.jmx.JMXReporter;
033import io.jboot.support.metric.reporter.prometheus.PrometheusReporter;
034import io.jboot.support.metric.reporter.slf4j.JbootSlf4jReporter;
035import io.jboot.utils.ArrayUtil;
036import io.jboot.utils.StrUtil;
037
038import java.lang.management.ManagementFactory;
039import java.util.ArrayList;
040import java.util.List;
041import java.util.concurrent.TimeUnit;
042
043
044public class JbootMetricManager {
045
046    private static final Log LOG = Log.getLog(JbootMetricManager.class);
047
048    private static JbootMetricManager me;
049
050    public static JbootMetricManager me() {
051        if (me == null) {
052            me = new JbootMetricManager();
053        }
054        return me;
055    }
056
057    private MetricRegistry metricRegistry;
058    private HealthCheckRegistry healthCheckRegistry;
059    private JbootMetricConfig metricsConfig = Jboot.config(JbootMetricConfig.class);
060
061    private boolean enable = false;
062
063    private JbootMetricManager() {
064
065        if (!metricsConfig.isConfigOk() || !metricsConfig.isEnable()) {
066            return;
067        }
068
069
070        metricRegistry = new MetricRegistry();
071        healthCheckRegistry = new HealthCheckRegistry();
072
073
074        if (metricsConfig.isJvmMetricEnable()) {
075
076            metricRegistry.register("jvm.uptime", (Gauge<Long>) () -> ManagementFactory.getRuntimeMXBean().getUptime());
077            metricRegistry.register("jvm.start_time", (Gauge<Long>) () -> ManagementFactory.getRuntimeMXBean().getStartTime());
078            metricRegistry.register("jvm.current_time", (Gauge<Long>) () -> System.nanoTime());
079            metricRegistry.register("jvm.classes", new ClassLoadingGaugeSet());
080            metricRegistry.register("jvm.attribute", new JvmAttributeGaugeSet());
081            metricRegistry.register("jvm.fd", new FileDescriptorRatioGauge());
082            metricRegistry.register("jvm.buffers", new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()));
083            metricRegistry.register("jvm.gc", new GarbageCollectorMetricSet());
084            metricRegistry.register("jvm.memory", new MemoryUsageGaugeSet());
085            metricRegistry.register("jvm.threads", new CachedThreadStatesGaugeSet(10, TimeUnit.SECONDS));
086
087            metricRegistry.registerAll(new JvmCpuGaugeSet());
088            metricRegistry.registerAll(new JvmGcMetrics(metricRegistry));
089            metricRegistry.registerAll(new ProcessFilesGaugeSet());
090
091            healthCheckRegistry.register("jvm.thread_deadlocks", new ThreadDeadlockHealthCheck());
092        }
093
094
095        List<JbootMetricReporter> reporters = getReporters();
096        if (ArrayUtil.isNullOrEmpty(reporters)) {
097            return;
098        }
099
100        for (JbootMetricReporter reporter : reporters) {
101            try {
102                reporter.report(metricRegistry);
103            } catch (Throwable ex) {
104                LOG.error(ex.toString(), ex);
105            }
106        }
107
108        this.enable = true;
109    }
110
111
112    public boolean isEnable() {
113        return enable;
114    }
115
116    private List<JbootMetricReporter> getReporters() {
117        String repoterString = metricsConfig.getReporter();
118        if (StrUtil.isBlank(repoterString)) {
119            return null;
120        }
121        List<JbootMetricReporter> reporters = new ArrayList<>();
122
123        String[] repoterStrings = repoterString.split(",");
124        for (String repoterName : repoterStrings) {
125            JbootMetricReporter reporter = getReporterByName(repoterName);
126            if (reporter != null) {
127                reporters.add(reporter);
128            }
129        }
130
131        return reporters;
132    }
133
134
135    private JbootMetricReporter getReporterByName(String repoterName) {
136
137        JbootMetricReporter reporter = null;
138
139        switch (repoterName) {
140            case JbootMetricConfig.REPORTER_JMX:
141                reporter = new JMXReporter();
142                break;
143            case JbootMetricConfig.REPORTER_INFLUXDB:
144                reporter = new InfluxdbReporter();
145                break;
146            case JbootMetricConfig.REPORTER_GRAPHITE:
147                reporter = new JbootGraphiteReporter();
148                break;
149            case JbootMetricConfig.REPORTER_ELASTICSEARCH:
150                reporter = new ElasticsearchReporter();
151                break;
152            case JbootMetricConfig.REPORTER_GANGLIA:
153                reporter = new GangliaReporter();
154                break;
155            case JbootMetricConfig.REPORTER_CONSOLE:
156                reporter = new JbootConsoleReporter();
157                break;
158            case JbootMetricConfig.REPORTER_CSV:
159                reporter = new CSVReporter();
160                break;
161            case JbootMetricConfig.REPORTER_SLF4J:
162                reporter = new JbootSlf4jReporter();
163                break;
164            case JbootMetricConfig.REPORTER_PROMETHEUS:
165                reporter = new PrometheusReporter();
166                break;
167            default:
168                reporter = JbootSpiLoader.load(JbootMetricReporter.class, repoterName);
169        }
170
171        return reporter;
172    }
173
174
175    public MetricRegistry metric() {
176        return metricRegistry;
177    }
178
179    public HealthCheckRegistry healthCheck() {
180        return healthCheckRegistry;
181    }
182
183
184}