Metrics 主要有五大基本组件
1:Counter
记录执行次数
2:Gauge
获取某个值
3:Meter
用来计算事件的速率
4:Histogram
可以为数据流提供统计数据。 除了最大值,最小值,平均值外,它还可以测量 中值(median),百分比比如XX%这样的Quantile数据
5:Timer
用来测量一段代码被调用的速率和用时。等于Meter+Hitogram,既算TPS,也算执行时间。
这篇博文主要实现:
1.这五种指标的基本实现,写到控制台
2.指标实现队列长度监控
3.指标写入csv,jmx,jdbc
1.
基础类:
package com.newland.learning; import com.codahale.metrics.MetricRegistry; import java.util.concurrent.TimeUnit; /** * Created by garfield on 2018/1/28. * Project test * Package com.newland.learning */ public class Base { protected static MetricRegistry metric = Constants.REGISTER; protected static void secondSleep(long value) { try { TimeUnit.SECONDS.sleep(value); } catch (InterruptedException e) { e.printStackTrace(); } } protected static void milliSecondSleep(long value) { try { TimeUnit.MILLISECONDS.sleep(value); } catch (InterruptedException e) { e.printStackTrace(); } } }
核心类:MetricRegistry是常量
package com.newland.learning; import com.codahale.metrics.MetricRegistry; /** * Created by garfield on 2018/1/28. * Project test * Package com.newland.learning */ public class Constants { public static MetricRegistry REGISTER = new MetricRegistry(); }
先写控制台输出:
package com.newland.learning; import com.codahale.metrics.ConsoleReporter; import java.util.concurrent.TimeUnit; /** * Created by garfield on 2018/1/28. * Project test * Package com.newland.learning */ public class ConsoleReport { public static void startReport() { final ConsoleReporter reporter = ConsoleReporter.forRegistry(Constants.REGISTER) .convertRatesTo(TimeUnit.SECONDS) .convertDurationsTo(TimeUnit.SECONDS) .build(); //一秒钟执行一次 reporter.start(1, TimeUnit.SECONDS); } }
gauge:
package com.newland.learning; import com.codahale.metrics.Gauge; /** * Created by garfield on 2018/1/28. * Project test * Package com.newland.learning */ /** * 获取某个值,瞬时 */ public class GaugeTest extends Base { public static void main(String[] args) { ConsoleReport.startReport(); metric.register("com.learn.gauge.freeMemory", new Gauge<Long>(){ @Override public Long getValue() { //这里是获取当前JVM可用内存 return Runtime.getRuntime().freeMemory(); } }); secondSleep(2); } }
结果:
18-1-28 19:18:54 =============================================================== -- Gauges ---------------------------------------------------------------------- com.learn.gauge.freeMemory value = 90862672 18-1-28 19:18:55 =============================================================== -- Gauges ---------------------------------------------------------------------- com.learn.gauge.freeMemory value = 90862672
counter:
package com.newland.learning; import com.codahale.metrics.Counter; import java.util.Random; /** * Created by garfield on 2018/1/28. * Project test * Package com.newland.learning */ /** * 记录执行次数 */ public class CounterTest extends Base{ final static Counter exec = metric.counter("com.learn.counter.invoke"); public static void main(String[] args) { ConsoleReport.startReport(); new Thread(()->{ for(int i=1;i<=3;i++) { exec.inc(); milliSecondSleep(new Random().nextInt(500)*2); } }).start(); secondSleep(3); } }
结果:
18-1-28 19:19:34 =============================================================== -- Counters -------------------------------------------------------------------- com.learn.counter.invoke count = 2 18-1-28 19:19:35 =============================================================== -- Counters -------------------------------------------------------------------- com.learn.counter.invoke count = 3 18-1-28 19:19:36 =============================================================== -- Counters -------------------------------------------------------------------- com.learn.counter.invoke count = 3
Meter:
package com.newland.learning; import com.codahale.metrics.Meter; import java.util.Random; /** * Created by garfield on 2018/1/28. * Project test * Package com.newland.learning */ /** * Meter用来计算事件的速率 */ public class MeterTest extends Base { static final Meter requests = metric.meter("com.learn.meter.invoke"); public static void main(String[] args) { ConsoleReport.startReport(); new Thread(()->{ for(int i=1;i<=2;i++) { requests.mark(); milliSecondSleep(new Random().nextInt(500)*2); } }).start(); secondSleep(2); } }
结果:
18-1-28 19:20:52 =============================================================== -- Meters ---------------------------------------------------------------------- com.learn.meter.invoke count = 2 mean rate = 1.69 events/second 1-minute rate = 0.00 events/second 5-minute rate = 0.00 events/second 15-minute rate = 0.00 events/second 18-1-28 19:20:53 =============================================================== -- Meters ---------------------------------------------------------------------- com.learn.meter.invoke count = 2 mean rate = 0.93 events/second 1-minute rate = 0.00 events/second 5-minute rate = 0.00 events/second 15-minute rate = 0.00 events/second
Histogram:
package com.newland.learning; import com.codahale.metrics.Histogram; import java.util.Arrays; import java.util.List; import java.util.Random; /** * Created by garfield on 2018/1/28. * Project test * Package com.newland.learning */ /** * Histogram可以为数据流提供统计数据。 除了最大值,最小值,平均值外,它还可以测量 中值(median), * 百分比比如XX%这样的Quantile数据 */ public class HistogramTest extends Base{ static final Histogram his = metric.histogram("com.learn.histogram.score"); static List<Integer> scores = Arrays.asList(60, 75, 80, 62, 90, 42, 33, 95, 61, 73); public static void main(String[] args) { ConsoleReport.startReport(); new Thread(()->{ scores.forEach( (score) -> { his.update(score); milliSecondSleep(new Random().nextInt(500)*2); }); }).start(); secondSleep(10); } }
结果:
18-1-28 19:21:36 =============================================================== -- Histograms ------------------------------------------------------------------ com.learn.histogram.score count = 10 min = 33 max = 95 mean = 67.08 stddev = 18.68 median = 62.00 75% <= 80.00 95% <= 95.00 98% <= 95.00 99% <= 95.00 99.9% <= 95.00 18-1-28 19:21:37 =============================================================== -- Histograms ------------------------------------------------------------------ com.learn.histogram.score count = 10 min = 33 max = 95 mean = 67.08 stddev = 18.68 median = 62.00 75% <= 80.00 95% <= 95.00 98% <= 95.00 99% <= 95.00 99.9% <= 95.00 18-1-28 19:21:38 =============================================================== -- Histograms ------------------------------------------------------------------ com.learn.histogram.score count = 10 min = 33 max = 95 mean = 67.08 stddev = 18.68 median = 62.00 75% <= 80.00 95% <= 95.00 98% <= 95.00 99% <= 95.00 99.9% <= 95.00 18-1-28 19:21:39 =============================================================== -- Histograms ------------------------------------------------------------------ com.learn.histogram.score count = 10 min = 33 max = 95 mean = 67.08 stddev = 18.68 median = 62.00 75% <= 80.00 95% <= 95.00 98% <= 95.00 99% <= 95.00 99.9% <= 95.00
Timer:
package com.newland.learning; import com.codahale.metrics.Timer; /** * Created by garfield on 2018/1/28. * Project test * Package com.newland.learning */ /** * Timer用来测量一段代码被调用的速率和用时。 * 等于Meter+Hitogram,既算TPS,也算执行时间。 */ public class TimerTest extends Base { static final Timer timer = metric.timer("com.learn.timer.invoke"); static void inovke(long time) { final Timer.Context context = timer.time(); try { secondSleep(time); }finally { context.stop(); } } public static void main(String[] args) { ConsoleReport.startReport(); inovke(1); inovke(2); inovke(2); inovke(8); secondSleep(1); } }
结果:
18-1-28 19:22:28 =============================================================== -- Timers ---------------------------------------------------------------------- com.learn.timer.invoke count = 3 mean rate = 0.23 calls/second 1-minute rate = 0.38 calls/second 5-minute rate = 0.40 calls/second 15-minute rate = 0.40 calls/second min = 1.00 seconds max = 2.00 seconds mean = 1.68 seconds stddev = 0.47 seconds median = 2.00 seconds 75% <= 2.00 seconds 95% <= 2.00 seconds 98% <= 2.00 seconds 99% <= 2.00 seconds 99.9% <= 2.00 seconds 18-1-28 19:22:29 =============================================================== -- Timers ---------------------------------------------------------------------- com.learn.timer.invoke count = 4 mean rate = 0.28 calls/second 1-minute rate = 0.38 calls/second 5-minute rate = 0.40 calls/second 15-minute rate = 0.40 calls/second min = 1.00 seconds max = 8.00 seconds mean = 3.44 seconds stddev = 2.86 seconds median = 2.00 seconds 75% <= 8.00 seconds 95% <= 8.00 seconds 98% <= 8.00 seconds 99% <= 8.00 seconds 99.9% <= 8.00 seconds
2.Counter获取队列长度
package com.newland.learning; import com.codahale.metrics.Counter; import java.util.Queue; import java.util.Random; import java.util.concurrent.LinkedBlockingQueue; /** * Created by garfield on 2018/1/28. * Project test * Package com.newland.learning */ public class QueueSize extends Base{ final static Counter exec = metric.counter("com.learn.counter2.invoke"); public static Queue<String> q = new LinkedBlockingQueue<String>(); public static Random random = new Random(); public static void addJob(String job) { exec.inc(); q.offer(job); } public static String takeJob() { exec.dec(); return q.poll(); } public static void main(String[] args) throws InterruptedException { ConsoleReport.startReport(); int num = 1; while(true){ Thread.sleep(200); if (random.nextDouble() > 0.7){ String job = takeJob(); System.out.println("take job : "+job); }else{ String job = "Job-"+num; addJob(job); System.out.println("add job : "+job); } num++; } } }
结果:
take job : null add job : Job-2 take job : Job-2 add job : Job-4 add job : Job-5 18-1-28 19:23:12 =============================================================== -- Counters -------------------------------------------------------------------- com.learn.counter2.invoke count = 1 add job : Job-6 add job : Job-7 take job : Job-4 add job : Job-9 18-1-28 19:23:13 =============================================================== -- Counters -------------------------------------------------------------------- com.learn.counter2.invoke count = 3 add job : Job-10 take job : Job-5 add job : Job-12 add job : Job-13 add job : Job-14
3.写入csv,jmx,jdbc
package com.newland.learning; import com.codahale.metrics.CsvReporter; import com.codahale.metrics.JmxReporter; import javax.sql.DataSource; import java.io.File; import java.util.concurrent.TimeUnit; /** * Created by garfield on 2018/1/28. * Project test * Package com.newland.learning */ public class MetricReport { private JmxReporter jmxReporter; private JdbcReporter jdbcReporter; private CsvReporter csvReporter; public void startJdbcReport() { //获取jdbc... DataSource dataSource = null; String source = "test_db"; jdbcReporter = JdbcReporter.forRegistry(Constants.REGISTER) .convertRatesTo(TimeUnit.SECONDS) .convertDurationsTo(TimeUnit.MILLISECONDS) .isDelOldData(true) .build(source, dataSource); jdbcReporter.start(5, TimeUnit.SECONDS); } public void startCsvReport(){ //路径 File fileDir = new File(""); if (!fileDir.exists()) { fileDir.mkdirs(); } csvReporter = CsvReporter.forRegistry(Constants.REGISTER) .convertRatesTo(TimeUnit.SECONDS) .convertDurationsTo(TimeUnit.MILLISECONDS) .build(fileDir); csvReporter.start(5, TimeUnit.SECONDS); } public void startJmxReport(){ jmxReporter = JmxReporter.forRegistry(Constants.REGISTER).build(); jmxReporter.start(); } }
写入jdbc,需要自己实现继承:
package com.newland.learning; import com.codahale.metrics.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.sql.DataSource; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Map; import java.util.SortedMap; import java.util.concurrent.TimeUnit; /** * Created by garfield on 2018/1/28. * Project test * Package com.newland.learning */ public class JdbcReporter extends ScheduledReporter { /** * Returns a new {@link Builder} for {@link JdbcReporter}. * * @param registry the registry to report * @return a {@link Builder} instance for a {@link JdbcReporter} */ public static Builder forRegistry(MetricRegistry registry) { return new Builder(registry); } /** * A builder for {@link JdbcReporter} instances. Defaults to converting rates to events/second, converting durations * to milliseconds, and not filtering metrics. */ public static class Builder { private final MetricRegistry registry; private TimeUnit rateUnit; private TimeUnit durationUnit; private Clock clock; private MetricFilter filter; private TimeUnit timestampUnit; private boolean isDelOldData; private Builder(MetricRegistry registry) { this.registry = registry; this.rateUnit = TimeUnit.SECONDS; this.durationUnit = TimeUnit.MILLISECONDS; this.clock = Clock.defaultClock(); this.filter = MetricFilter.ALL; this.timestampUnit = TimeUnit.SECONDS; this.isDelOldData = true; } /** * Convert rates to the given time unit. * * @param rateUnit a unit of time * @return {@code this} */ public Builder convertRatesTo(TimeUnit rateUnit) { this.rateUnit = rateUnit; return this; } /** * Convert durations to the given time unit. * * @param durationUnit a unit of time * @return {@code this} */ public Builder convertDurationsTo(TimeUnit durationUnit) { this.durationUnit = durationUnit; return this; } /** * Use the given {@link Clock} instance for the time. * * @param clock a {@link Clock} instance * @return {@code this} */ public Builder withClock(Clock clock) { this.clock = clock; return this; } /** * Only report metrics which match the given filter. * * @param filter a {@link MetricFilter} * @return {@code this} */ public Builder filter(MetricFilter filter) { this.filter = filter; return this; } /** * Convert reporting timestamp to the given time unit. * * @param timestampUnit a unit of time * @return {@code this} */ public Builder convertTimestampTo(TimeUnit timestampUnit) { this.timestampUnit = timestampUnit; return this; } public Builder isDelOldData(boolean isDelOldData) { this.isDelOldData = isDelOldData; return this; } /** * Builds a {@link JdbcReporter} with the given properties to report metrics to a database * * @param source A value to identify the source of each metrics in database * @param dataSource The {@link DataSource}, which will be used to store the data from each metric * @return a {@link JdbcReporter} */ public JdbcReporter build(String source, DataSource dataSource) { return new JdbcReporter(registry, source, dataSource, rateUnit, durationUnit, timestampUnit, clock, filter, isDelOldData); } } private static final Logger logger = LoggerFactory.getLogger(JdbcReporter.class); private final Clock clock; private final String source; private final DataSource dataSource; private final TimeUnit timestampUnit; private final boolean isDelOldData; private static final String INSERT_GAUGE_QUERY = "INSERT INTO METRIC_GAUGE (SOURCE, TIMESTAMP, NAME, VALUE) VALUES (?,?,?,?)"; private static final String INSERT_COUNTER_QUERY = "INSERT INTO METRIC_COUNTER (SOURCE, TIMESTAMP, NAME, COUNT) VALUES (?,?,?,?)"; private static final String INSERT_METER_QUERY = "INSERT INTO METRIC_METER (SOURCE,TIMESTAMP,NAME,COUNT,MEAN_RATE,M1_RATE,M5_RATE,M15_RATE,RATE_UNIT) " + "VALUES (?,?,?,?,?,?,?,?,?)"; private static final String INSERT_HISTOGRAM_QUERY = "INSERT INTO METRIC_HISTOGRAM (SOURCE,TIMESTAMP,NAME,COUNT,MAX,MEAN,MIN,STDDEV,P50,P75,P95,P98,P99,P999) " + "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; private static final String INSERT_TIMER_QUERY = "INSERT INTO METRIC_TIMER (SOURCE,TIMESTAMP,NAME,COUNT,MAX,MEAN,MIN,STDDEV,P50,P75,P95,P98,P99,P999," + "MEAN_RATE,M1_RATE,M5_RATE,M15_RATE,RATE_UNIT,DURATION_UNIT) " + "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; private static final String DELETE_GAUGE_QUERY = "DELETE FROM METRIC_GAUGE WHERE SOURCE=? AND NAME=?"; private static final String DELETE_COUNTER_QUERY = "DELETE FROM METRIC_COUNTER WHERE SOURCE=? AND NAME=?"; private static final String DELETE_METER_QUERY = "DELETE FROM METRIC_METER WHERE SOURCE=? AND NAME=?"; private static final String DELETE_HISTOGRAM_QUERY = "DELETE FROM METRIC_HISTOGRAM WHERE SOURCE=? AND NAME=?"; private static final String DELETE_TIMER_QUERY = "DELETE FROM METRIC_TIMER WHERE SOURCE=? AND NAME=?"; private static final String DELETE_ALL_GAUGE_QUERY = "DELETE FROM METRIC_GAUGE WHERE SOURCE=?"; private static final String DELETE_ALL_COUNTER_QUERY = "DELETE FROM METRIC_COUNTER WHERE SOURCE=?"; private static final String DELETE_ALL_METER_QUERY = "DELETE FROM METRIC_METER WHERE SOURCE=?"; private static final String DELETE_ALL_HISTOGRAM_QUERY = "DELETE FROM METRIC_HISTOGRAM WHERE SOURCE=?"; private static final String DELETE_ALL_TIMER_QUERY = "DELETE FROM METRIC_TIMER WHERE SOURCE=?"; private JdbcReporter(MetricRegistry registry, String source, DataSource dataSource, TimeUnit rateUnit, TimeUnit durationUnit, TimeUnit timestampUnit, Clock clock, MetricFilter filter, boolean isDelOldData) { super(registry, "jdbc-reporter", filter, rateUnit, durationUnit); this.source = source; this.dataSource = dataSource; this.timestampUnit = timestampUnit; this.clock = clock; if (source == null || source.trim().isEmpty()) { throw new IllegalArgumentException("Source cannot be null or empty"); } if (dataSource == null) { throw new IllegalArgumentException("Data source cannot be null"); } this.isDelOldData = isDelOldData; } @Override public void start(long period, TimeUnit unit) { if (isDelOldData) { delAllMetric(); } super.start(period, unit); } @SuppressWarnings("rawtypes") @Override public void report(SortedMap<String, Gauge> gauges, SortedMap<String, Counter> counters, SortedMap<String, Histogram> histograms, SortedMap<String, Meter> meters, SortedMap<String, Timer> timers) { final long timestamp = timestampUnit.convert(clock.getTime(), TimeUnit.MILLISECONDS); if (!gauges.isEmpty()) { reportGauges(timestamp, gauges); } if (!counters.isEmpty()) { reportCounters(timestamp, counters); } if (!histograms.isEmpty()) { reportHistograms(timestamp, histograms); } if (!meters.isEmpty()) { reportMeters(timestamp, meters); } if (!timers.isEmpty()) { reportTimers(timestamp, timers); } } @Override protected String getRateUnit() { return super.getRateUnit(); } private void delAllMetric() { Connection connection = null; PreparedStatement ps = null; try { connection = dataSource.getConnection(); connection.setAutoCommit(true); ps = connection.prepareStatement(DELETE_ALL_COUNTER_QUERY); ps.setString(1, source); ps.execute(); ps.close(); ps = connection.prepareStatement(DELETE_ALL_GAUGE_QUERY); ps.setString(1, source); ps.execute(); ps.close(); ps = connection.prepareStatement(DELETE_ALL_METER_QUERY); ps.setString(1, source); ps.execute(); ps.close(); ps = connection.prepareStatement(DELETE_ALL_HISTOGRAM_QUERY); ps.setString(1, source); ps.execute(); ps.close(); ps = connection.prepareStatement(DELETE_ALL_TIMER_QUERY); ps.setString(1, source); ps.execute(); ps.close(); ps = null; connection.close(); connection = null; } catch (SQLException e) { rollbackTransaction(connection); logger.error("Error when delAllMetric", e); } finally { closeQuietly(connection, ps, null); } } private void delMetric(PreparedStatement ps, String name) throws SQLException { ps.setString(1, source); ps.setString(2, name); } @SuppressWarnings("rawtypes") private void reportGauges(final long timestamp, final SortedMap<String, Gauge> gauges) { Connection connection = null; PreparedStatement ps = null; PreparedStatement dps = null; try { connection = dataSource.getConnection(); connection.setAutoCommit(false); ps = connection.prepareStatement(INSERT_GAUGE_QUERY); dps = connection.prepareStatement(DELETE_GAUGE_QUERY); for (Map.Entry<String, Gauge> entry : gauges.entrySet()) { String name = entry.getKey(); Gauge gauge = entry.getValue(); reportGauge(timestamp, ps, name, gauge); ps.addBatch(); delMetric(dps, name); dps.addBatch(); } if (isDelOldData) { dps.executeBatch(); } ps.executeBatch(); connection.commit(); dps.close(); dps = null; ps.close(); ps = null; connection.close(); connection = null; } catch (SQLException e) { rollbackTransaction(connection); logger.error("Error when reporting gauges", e); } finally { closeQuietly(connection, ps, dps); } } @SuppressWarnings("rawtypes") private void reportGauge(final long timestamp, PreparedStatement ps, String name, Gauge gauge) throws SQLException { ps.setString(1, source); ps.setLong(2, timestamp); ps.setString(3, name); ps.setObject(4, gauge.getValue()); } private void reportCounters(final long timestamp, final SortedMap<String, Counter> counters) { Connection connection = null; PreparedStatement ps = null; PreparedStatement dps = null; try { connection = dataSource.getConnection(); connection.setAutoCommit(false); ps = connection.prepareStatement(INSERT_COUNTER_QUERY); dps = connection.prepareStatement(DELETE_COUNTER_QUERY); for (Map.Entry<String, Counter> entry : counters.entrySet()) { String name = entry.getKey(); Counter counter = entry.getValue(); reportCounter(timestamp, ps, name, counter); ps.addBatch(); delMetric(dps, name); dps.addBatch(); } if (isDelOldData) { dps.executeBatch(); } ps.executeBatch(); connection.commit(); dps.close(); dps = null; ps.close(); ps = null; connection.close(); connection = null; } catch (SQLException e) { rollbackTransaction(connection); logger.error("Error when reporting counters", e); } finally { closeQuietly(connection, ps, dps); } } private void reportCounter(final long timestamp, PreparedStatement ps, String name, Counter counter) throws SQLException { ps.setString(1, source); ps.setLong(2, timestamp); ps.setString(3, name); ps.setLong(4, counter.getCount()); } private void reportHistograms(final long timestamp, final SortedMap<String, Histogram> histograms) { Connection connection = null; PreparedStatement ps = null; PreparedStatement dps = null; try { connection = dataSource.getConnection(); connection.setAutoCommit(false); ps = connection.prepareStatement(INSERT_HISTOGRAM_QUERY); dps = connection.prepareStatement(DELETE_HISTOGRAM_QUERY); for (Map.Entry<String, Histogram> entry : histograms.entrySet()) { String name = entry.getKey(); Histogram histogram = entry.getValue(); reportHistogram(timestamp, ps, name, histogram); ps.addBatch(); delMetric(dps, name); dps.addBatch(); } if (isDelOldData) { dps.executeBatch(); } ps.executeBatch(); connection.commit(); dps.close(); dps = null; ps.close(); ps = null; connection.close(); connection = null; } catch (SQLException e) { rollbackTransaction(connection); logger.error("Error when reporting histograms", e); } finally { closeQuietly(connection, ps, dps); } } private void reportHistogram(final long timestamp, PreparedStatement ps, String name, Histogram histogram) throws SQLException { final Snapshot snapshot = histogram.getSnapshot(); ps.setString(1, source); ps.setLong(2, timestamp); ps.setString(3, name); ps.setLong(4, histogram.getCount()); ps.setDouble(5, snapshot.getMax()); ps.setDouble(6, snapshot.getMean()); ps.setDouble(7, snapshot.getMin()); ps.setDouble(8, snapshot.getStdDev()); ps.setDouble(9, snapshot.getMedian()); ps.setDouble(10, snapshot.get75thPercentile()); ps.setDouble(11, snapshot.get95thPercentile()); ps.setDouble(12, snapshot.get98thPercentile()); ps.setDouble(13, snapshot.get99thPercentile()); ps.setDouble(14, snapshot.get999thPercentile()); } private void reportMeters(final long timestamp, final SortedMap<String, Meter> meters) { Connection connection = null; PreparedStatement ps = null; PreparedStatement dps = null; try { connection = dataSource.getConnection(); connection.setAutoCommit(false); ps = connection.prepareStatement(INSERT_METER_QUERY); dps = connection.prepareStatement(DELETE_METER_QUERY); for (Map.Entry<String, Meter> entry : meters.entrySet()) { String name = entry.getKey(); Meter meter = entry.getValue(); reportMeter(timestamp, ps, name, meter); ps.addBatch(); delMetric(dps, name); dps.addBatch(); } if (isDelOldData) { dps.executeBatch(); } ps.executeBatch(); connection.commit(); dps.close(); dps = null; ps.close(); ps = null; connection.close(); connection = null; } catch (SQLException e) { rollbackTransaction(connection); logger.error("Error when reporting meters", e); } finally { closeQuietly(connection, ps, dps); } } private void reportMeter(final long timestamp, PreparedStatement ps, String name, Meter meter) throws SQLException { ps.setString(1, source); ps.setLong(2, timestamp); ps.setString(3, name); ps.setLong(4, meter.getCount()); ps.setDouble(5, convertRate(meter.getMeanRate())); ps.setDouble(6, convertRate(meter.getOneMinuteRate())); ps.setDouble(7, convertRate(meter.getFiveMinuteRate())); ps.setDouble(8, convertRate(meter.getFifteenMinuteRate())); ps.setString(9, String.format("events/%s", getRateUnit())); } private void reportTimers(final long timestamp, final SortedMap<String, Timer> timers) { Connection connection = null; PreparedStatement ps = null; PreparedStatement dps = null; try { connection = dataSource.getConnection(); connection.setAutoCommit(false); ps = connection.prepareStatement(INSERT_TIMER_QUERY); dps = connection.prepareStatement(DELETE_TIMER_QUERY); for (Map.Entry<String, Timer> entry : timers.entrySet()) { String name = entry.getKey(); Timer timer = entry.getValue(); reportTimer(timestamp, ps, name, timer); ps.addBatch(); delMetric(dps, name); dps.addBatch(); } if (isDelOldData) { dps.executeBatch(); } ps.executeBatch(); connection.commit(); dps.close(); dps = null; ps.close(); ps = null; connection.close(); connection = null; } catch (SQLException e) { rollbackTransaction(connection); logger.error("Error when reporting timers", e); } finally { closeQuietly(connection, ps, dps); } } private void reportTimer(final long timestamp, PreparedStatement ps, String name, Timer timer) throws SQLException { final Snapshot snapshot = timer.getSnapshot(); ps.setString(1, source); ps.setLong(2, timestamp); ps.setString(3, name); ps.setLong(4, timer.getCount()); ps.setDouble(5, convertDuration(snapshot.getMax())); ps.setDouble(6, convertDuration(snapshot.getMean())); ps.setDouble(7, convertDuration(snapshot.getMin())); ps.setDouble(8, convertDuration(snapshot.getStdDev())); ps.setDouble(9, convertDuration(snapshot.getMedian())); ps.setDouble(10, convertDuration(snapshot.get75thPercentile())); ps.setDouble(11, convertDuration(snapshot.get95thPercentile())); ps.setDouble(12, convertDuration(snapshot.get98thPercentile())); ps.setDouble(13, convertDuration(snapshot.get99thPercentile())); ps.setDouble(14, convertDuration(snapshot.get999thPercentile())); ps.setDouble(15, convertRate(timer.getMeanRate())); ps.setDouble(16, convertRate(timer.getOneMinuteRate())); ps.setDouble(17, convertRate(timer.getFiveMinuteRate())); ps.setDouble(18, convertRate(timer.getFifteenMinuteRate())); ps.setString(19, String.format("calls/%s", getRateUnit())); ps.setString(20, getDurationUnit()); } private void rollbackTransaction(Connection connection) { if (connection != null) { try { connection.rollback(); } catch (SQLException e) { if (logger.isWarnEnabled()) { logger.warn("Error when rolling back the transaction", e); } } } } private void closeQuietly(Connection connection, PreparedStatement ps, PreparedStatement dps) { if (ps != null) { try { ps.close(); } catch (SQLException e) { // Ignore } } if (dps != null) { try { dps.close(); } catch (SQLException e) { // Ignore } } if (connection != null) { try { connection.close(); } catch (SQLException e) { // Ignore } } } }
done
学习:blog.csdn.net/tracymkgld/article/details/51899721
http://blog.csdn.net/wzygis/article/details/52789105