1METRICS(1) Metrics METRICS(1)
2
3
4
6 metrics - Metrics Documentation
7
8 Metrics provides a powerful toolkit of ways to measure the behavior of
9 critical components in your production environment.
10
11 With modules for common libraries like Jetty, Logback, Log4j, Apache
12 HttpClient, Ehcache, JDBI, Jersey and reporting backends like Ganglia
13 and Graphite, Metrics provides you with full-stack visibility.
14
16 Getting Started will guide you through the process of adding Metrics to
17 an existing application. We’ll go through the various measuring instru‐
18 ments that Metrics provides, how to use them, and when they’ll come in
19 handy..SS Setting Up Maven
20
21 You need the metrics-core library as a dependency:
22
23 <dependencies>
24 <dependency>
25 <groupId>io.dropwizard.metrics</groupId>
26 <artifactId>metrics-core</artifactId>
27 <version>${metrics.version}</version>
28 </dependency>
29 </dependencies>
30
31 NOTE:
32 Make sure you have a metrics.version property declared in your POM
33 with the current version, which is 3.1.0.
34
35 Now it’s time to add some metrics to your application!
36
37 Meters
38 A meter measures the rate of events over time (e.g., “requests per sec‐
39 ond”). In addition to the mean rate, meters also track 1-, 5-, and
40 15-minute moving averages.
41
42 private final Meter requests = metrics.meter("requests");
43
44 public void handleRequest(Request request, Response response) {
45 requests.mark();
46 // etc
47 }
48
49 This meter will measure the rate of requests in requests per second.
50
51 Console Reporter
52 A Console Reporter is exactly what it sounds like - report to the con‐
53 sole. This reporter will print every second.
54
55 ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics)
56 .convertRatesTo(TimeUnit.SECONDS)
57 .convertDurationsTo(TimeUnit.MILLISECONDS)
58 .build();
59 reporter.start(1, TimeUnit.SECONDS);
60
61 Complete getting started
62 So the complete Getting Started is
63
64 package sample;
65 import com.codahale.metrics.*;
66 import java.util.concurrent.TimeUnit;
67
68 public class GetStarted {
69 static final MetricRegistry metrics = new MetricRegistry();
70 public static void main(String args[]) {
71 startReport();
72 Meter requests = metrics.meter("requests");
73 requests.mark();
74 wait5Seconds();
75 }
76
77 static void startReport() {
78 ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics)
79 .convertRatesTo(TimeUnit.SECONDS)
80 .convertDurationsTo(TimeUnit.MILLISECONDS)
81 .build();
82 reporter.start(1, TimeUnit.SECONDS);
83 }
84
85 static void wait5Seconds() {
86 try {
87 Thread.sleep(5*1000);
88 }
89 catch(InterruptedException e) {}
90 }
91 }
92
93 <?xml version="1.0" encoding="UTF-8"?>
94 <project xmlns="http://maven.apache.org/POM/4.0.0" 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">
95 <modelVersion>4.0.0</modelVersion>
96
97 <groupId>somegroup</groupId>
98 <artifactId>sample</artifactId>
99 <version>0.0.1-SNAPSHOT</version>
100 <name>Example project for Metrics</name>
101
102 <dependencies>
103 <dependency>
104 <groupId>io.dropwizard.metrics</groupId>
105 <artifactId>metrics-core</artifactId>
106 <version>${metrics.version}</version>
107 </dependency>
108 </dependencies>
109 </project>
110
111 NOTE:
112 Make sure you have a metrics.version property declared in your POM
113 with the current version, which is 3.1.0.
114
115 To run
116
117 mvn package exec:java -Dexec.mainClass=sample.First
118
119 The Registry
120 The centerpiece of Metrics is the MetricRegistry class, which is the
121 container for all your application’s metrics. Go ahead and create a new
122 one:
123
124 final MetricRegistry metrics = new MetricRegistry();
125
126 You’ll probably want to integrate this into your application’s lifecy‐
127 cle (maybe using your dependency injection framework), but static field
128 is fine.
129
130 Gauges
131 A gauge is an instantaneous measurement of a value. For example, we may
132 want to measure the number of pending jobs in a queue:
133
134 public class QueueManager {
135 private final Queue queue;
136
137 public QueueManager(MetricRegistry metrics, String name) {
138 this.queue = new Queue();
139 metrics.register(MetricRegistry.name(QueueManager.class, name, "size"),
140 new Gauge<Integer>() {
141 @Override
142 public Integer getValue() {
143 return queue.size();
144 }
145 });
146 }
147 }
148
149 When this gauge is measured, it will return the number of jobs in the
150 queue.
151
152 Every metric in a registry has a unique name, which is just a dot‐
153 ted-name string like "things.count" or "com.example.Thing.latency".
154 MetricRegistry has a static helper method for constructing these names:
155
156 MetricRegistry.name(QueueManager.class, "jobs", "size")
157
158 This will return a string with something like "com.example.QueueMan‐
159 ager.jobs.size".
160
161 For most queue and queue-like structures, you won’t want to simply
162 return queue.size(). Most of java.util and java.util.concurrent have
163 implementations of #size() which are O(n), which means your gauge will
164 be slow (potentially while holding a lock).
165
166 Counters
167 A counter is just a gauge for an AtomicLong instance. You can increment
168 or decrement its value. For example, we may want a more efficient way
169 of measuring the pending job in a queue:
170
171 private final Counter pendingJobs = metrics.counter(name(QueueManager.class, "pending-jobs"));
172
173 public void addJob(Job job) {
174 pendingJobs.inc();
175 queue.offer(job);
176 }
177
178 public Job takeJob() {
179 pendingJobs.dec();
180 return queue.take();
181 }
182
183 Every time this counter is measured, it will return the number of jobs
184 in the queue.
185
186 As you can see, the API for counters is slightly different:
187 #counter(String) instead of #register(String, Metric). While you can
188 use register and create your own Counter instance, #counter(String)
189 does all the work for you, and allows you to reuse metrics with the
190 same name.
191
192 Also, we’ve statically imported MetricRegistry’s name method in this
193 scope to reduce clutter.
194
195 Histograms
196 A histogram measures the statistical distribution of values in a stream
197 of data. In addition to minimum, maximum, mean, etc., it also measures
198 median, 75th, 90th, 95th, 98th, 99th, and 99.9th percentiles.
199
200 private final Histogram responseSizes = metrics.histogram(name(RequestHandler.class, "response-sizes"));
201
202 public void handleRequest(Request request, Response response) {
203 // etc
204 responseSizes.update(response.getContent().length);
205 }
206
207 This histogram will measure the size of responses in bytes.
208
209 Timers
210 A timer measures both the rate that a particular piece of code is
211 called and the distribution of its duration.
212
213 private final Timer responses = metrics.timer(name(RequestHandler.class, "responses"));
214
215 public String handleRequest(Request request, Response response) {
216 final Timer.Context context = responses.time();
217 try {
218 // etc;
219 return "OK";
220 } finally {
221 context.stop();
222 }
223 }
224
225 This timer will measure the amount of time it takes to process each
226 request in nanoseconds and provide a rate of requests in requests per
227 second.
228
229 Health Checks
230 Metrics also has the ability to centralize your service’s health checks
231 with the metrics-healthchecks module.
232
233 First, create a new HealthCheckRegistry instance:
234
235 final HealthCheckRegistry healthChecks = new HealthCheckRegistry();
236
237 Second, implement a HealthCheck subclass:
238
239 public class DatabaseHealthCheck extends HealthCheck {
240 private final Database database;
241
242 public DatabaseHealthCheck(Database database) {
243 this.database = database;
244 }
245
246 @Override
247 public HealthCheck.Result check() throws Exception {
248 if (database.isConnected()) {
249 return HealthCheck.Result.healthy();
250 } else {
251 return HealthCheck.Result.unhealthy("Cannot connect to " + database.getUrl());
252 }
253 }
254 }
255
256 Then register an instance of it with Metrics:
257
258 healthChecks.register("postgres", new DatabaseHealthCheck(database));
259
260 To run all of the registered health checks:
261
262 final Map<String, HealthCheck.Result> results = healthChecks.runHealthChecks();
263 for (Entry<String, HealthCheck.Result> entry : results.entrySet()) {
264 if (entry.getValue().isHealthy()) {
265 System.out.println(entry.getKey() + " is healthy");
266 } else {
267 System.err.println(entry.getKey() + " is UNHEALTHY: " + entry.getValue().getMessage());
268 final Throwable e = entry.getValue().getError();
269 if (e != null) {
270 e.printStackTrace();
271 }
272 }
273 }
274
275 Metrics comes with a pre-built health check: ThreadDeadlockHealthCheck,
276 which uses Java’s built-in thread deadlock detection to determine if
277 any threads are deadlocked.
278
279 Reporting Via JMX
280 To report metrics via JMX:
281
282 final JmxReporter reporter = JmxReporter.forRegistry(registry).build();
283 reporter.start();
284
285 Once the reporter is started, all of the metrics in the registry will
286 become visible via JConsole or VisualVM (if you install the MBeans
287 plugin): [image: Metrics exposed as JMX MBeans being viewed in Visu‐
288 alVM's MBeans browser] [image]
289
290 TIP:
291 If you double-click any of the metric properties, VisualVM will
292 start graphing the data for that property. Sweet, eh?
293
294 Reporting Via HTTP
295 Metrics also ships with a servlet (AdminServlet) which will serve a
296 JSON representation of all registered metrics. It will also run health
297 checks, print out a thread dump, and provide a simple “ping” response
298 for load-balancers. (It also has single servlets–MetricsServlet,
299 HealthCheckServlet, ThreadDumpServlet, and PingServlet–which do these
300 individual tasks.)
301
302 To use this servlet, include the metrics-servlets module as a depen‐
303 dency:
304
305 <dependency>
306 <groupId>io.dropwizard.metrics</groupId>
307 <artifactId>metrics-servlets</artifactId>
308 <version>${metrics.version}</version>
309 </dependency>
310
311 NOTE:
312 Make sure you have a metrics.version property declared in your POM
313 with the current version, which is 3.1.0.
314
315 From there on, you can map the servlet to whatever path you see fit.
316
317 Other Reporting
318 In addition to JMX and HTTP, Metrics also has reporters for the follow‐
319 ing outputs:
320
321 · STDOUT, using ConsoleReporter from metrics-core
322
323 · CSV files, using CsvReporter from metrics-core
324
325 · SLF4J loggers, using Slf4jReporter from metrics-core
326
327 · Ganglia, using GangliaReporter from metrics-ganglia
328
329 · Graphite, using GraphiteReporter from metrics-graphite
330
332 This goal of this document is to provide you with all the information
333 required to effectively use the Metrics library in your application. If
334 you’re new to Metrics, you should read the getting-started guide
335 first..SS Metrics Core
336
337 The central library for Metrics is metrics-core, which provides some
338 basic functionality:
339
340 · Metric registries.
341
342 · The five metric types: Gauges, Counters, Histograms, Meters, and
343 Timers.
344
345 · Reporting metrics values via JMX, the console, CSV files, and SLF4J
346 loggers.
347
348 Metric Registries
349 The starting point for Metrics is the MetricRegistry class, which is a
350 collection of all the metrics for your application (or a subset of your
351 application). If your application is running alongside other applica‐
352 tions in a single JVM instance (e.g., multiple WARs deployed to an
353 application server), you should use per-application MetricRegistry
354 instances with different names.
355
356 Metric Names
357 Each metric has a unique name, which is a simple dotted name, like
358 com.example.Queue.size. This flexibility allows you to encode a wide
359 variety of context directly into a metric’s name. If you have two
360 instances of com.example.Queue, you can give them more specific:
361 com.example.Queue.requests.size vs. com.example.Queue.responses.size,
362 for example.
363
364 MetricRegistry has a set of static helper methods for easily creating
365 names:
366
367 MetricRegistry.name(Queue.class, "requests", "size")
368 MetricRegistry.name(Queue.class, "responses", "size")
369
370 These methods will also elide any null values, allowing for easy
371 optional scopes.
372
373 Gauges
374 A gauge is the simplest metric type. It just returns a value. If, for
375 example, your application has a value which is maintained by a
376 third-party library, you can easily expose it by registering a Gauge
377 instance which returns that value:
378
379 registry.register(name(SessionStore.class, "cache-evictions"), new Gauge<Integer>() {
380 @Override
381 public Integer getValue() {
382 return cache.getEvictionsCount();
383 }
384 });
385
386 This will create a new gauge named com.example.proj.auth.Session‐
387 Store.cache-evictions which will return the number of evictions from
388 the cache.
389
390 JMX Gauges
391 Given that many third-party library often expose metrics only via JMX,
392 Metrics provides the JmxAttributeGauge class, which takes the object
393 name of a JMX MBean and the name of an attribute and produces a gauge
394 implementation which returns the value of that attribute:
395
396 registry.register(name(SessionStore.class, "cache-evictions"),
397 new JmxAttributeGauge("net.sf.ehcache:type=Cache,scope=sessions,name=eviction-count", "Value"));
398
399 Ratio Gauges
400 A ratio gauge is a simple way to create a gauge which is the ratio
401 between two numbers:
402
403 public class CacheHitRatio extends RatioGauge {
404 private final Meter hits;
405 private final Timer calls;
406
407 public CacheHitRatio(Meter hits, Timer calls) {
408 this.hits = hits;
409 this.calls = calls;
410 }
411
412 @Override
413 public Ratio getRatio() {
414 return Ratio.of(hits.getOneMinuteRate(),
415 calls.getOneMinuteRate());
416 }
417 }
418
419 This gauge returns the ratio of cache hits to misses using a meter and
420 a timer.
421
422 Cached Gauges
423 A cached gauge allows for a more efficient reporting of values which
424 are expensive to calculate:
425
426 registry.register(name(Cache.class, cache.getName(), "size"),
427 new CachedGauge<Long>(10, TimeUnit.MINUTES) {
428 @Override
429 protected Long loadValue() {
430 // assume this does something which takes a long time
431 return cache.getSize();
432 }
433 });
434
435 Derivative Gauges
436 A derivative gauge allows you to derive values from other gauges’ val‐
437 ues:
438
439 public class CacheSizeGauge extends DerivativeGauge<CacheStats, Long> {
440 public CacheSizeGauge(Gauge<CacheStats> statsGauge) {
441 super(statsGauge);
442 }
443
444 @Override
445 protected Long transform(CacheStats stats) {
446 return stats.getSize();
447 }
448 }
449
450 Counters
451 A counter is a simple incrementing and decrementing 64-bit integer:
452
453 final Counter evictions = registry.counter(name(SessionStore.class, "cache-evictions"));
454 evictions.inc();
455 evictions.inc(3);
456 evictions.dec();
457 evictions.dec(2);
458
459 All Counter metrics start out at 0.
460
461 Histograms
462 A Histogram measures the distribution of values in a stream of data:
463 e.g., the number of results returned by a search:
464
465 final Histogram resultCounts = registry.histogram(name(ProductDAO.class, "result-counts");
466 resultCounts.update(results.size());
467
468 Histogram metrics allow you to measure not just easy things like the
469 min, mean, max, and standard deviation of values, but also quantiles
470 like the median or 95th percentile.
471
472 Traditionally, the way the median (or any other quantile) is calculated
473 is to take the entire data set, sort it, and take the value in the mid‐
474 dle (or 1% from the end, for the 99th percentile). This works for small
475 data sets, or batch processing systems, but not for high-throughput,
476 low-latency services.
477
478 The solution for this is to sample the data as it goes through. By
479 maintaining a small, manageable reservoir which is statistically repre‐
480 sentative of the data stream as a whole, we can quickly and easily cal‐
481 culate quantiles which are valid approximations of the actual quan‐
482 tiles. This technique is called reservoir sampling.
483
484 Metrics provides a number of different Reservoir implementations, each
485 of which is useful.
486
487 Uniform Reservoirs
488 A histogram with a uniform reservoir produces quantiles which are valid
489 for the entirely of the histogram’s lifetime. It will return a median
490 value, for example, which is the median of all the values the histogram
491 has ever been updated with. It does this by using an algorithm called
492 Vitter’s R), which randomly selects values for the reservoir with lin‐
493 early-decreasing probability.
494
495 Use a uniform histogram when you’re interested in long-term measure‐
496 ments. Don’t use one where you’d want to know if the distribution of
497 the underlying data stream has changed recently.
498
499 Exponentially Decaying Reservoirs
500 A histogram with an exponentially decaying reservoir produces quantiles
501 which are representative of (roughly) the last five minutes of data. It
502 does so by using a forward-decaying priority reservoir with an exponen‐
503 tial weighting towards newer data. Unlike the uniform reservoir, an
504 exponentially decaying reservoir represents recent data, allowing you
505 to know very quickly if the distribution of the data has changed.
506 Timers use histograms with exponentially decaying reservoirs by
507 default.
508
509 Sliding Window Reservoirs
510 A histogram with a sliding window reservoir produces quantiles which
511 are representative of the past N measurements.
512
513 Sliding Time Window Reservoirs
514 A histogram with a sliding time window reservoir produces quantiles
515 which are strictly representative of the past N seconds (or other time
516 period).
517
518 WARNING:
519 While SlidingTimeWindowReservoir is easier to understand than Expo‐
520 nentiallyDecayingReservoir, it is not bounded in size, so using it
521 to sample a high-frequency process can require a significant amount
522 of memory. Because it records every measurement, it’s also the slow‐
523 est reservoir type.
524
525 Meters
526 A meter measures the rate at which a set of events occur:
527
528 final Meter getRequests = registry.meter(name(WebProxy.class, "get-requests", "requests"));
529 getRequests.mark();
530 getRequests.mark(requests.size());
531
532 Meters measure the rate of the events in a few different ways. The mean
533 rate is the average rate of events. It’s generally useful for trivia,
534 but as it represents the total rate for your application’s entire life‐
535 time (e.g., the total number of requests handled, divided by the number
536 of seconds the process has been running), it doesn’t offer a sense of
537 recency. Luckily, meters also record three different exponen‐
538 tially-weighted moving average rates: the 1-, 5-, and 15-minute moving
539 averages.
540
541 HINT:
542 Just like the Unix load averages visible in uptime or top.
543
544 Timers
545 A timer is basically a histogram of the duration of a type of event and
546 a meter of the rate of its occurrence.
547
548 final Timer timer = registry.timer(name(WebProxy.class, "get-requests"));
549
550 final Timer.Context context = timer.time();
551 try {
552 // handle request
553 } finally {
554 context.stop();
555 }
556
557 NOTE:
558 Elapsed times for it events are measured internally in nanoseconds,
559 using Java’s high-precision System.nanoTime() method. Its precision
560 and accuracy vary depending on operating system and hardware.
561
562 Metric Sets
563 Metrics can also be grouped together into reusable metric sets using
564 the MetricSet interface. This allows library authors to provide a sin‐
565 gle entry point for the instrumentation of a wide variety of function‐
566 ality.
567
568 Reporters
569 Reporters are the way that your application exports all the measure‐
570 ments being made by its metrics. metrics-core comes with four ways of
571 exporting your metrics: JMX, console, SLF4J, and CSV.
572
573 JMX
574 With JmxReporter, you can expose your metrics as JMX MBeans. To explore
575 this you can use VisualVM (which ships with most JDKs as jvisualvm)
576 with the VisualVM-MBeans plugins installed or JConsole (which ships
577 with most JDKs as jconsole): [image: Metrics exposed as JMX MBeans
578 being viewed in VisualVM's MBeans browser] [image]
579
580 TIP:
581 If you double-click any of the metric properties, VisualVM will
582 start graphing the data for that property. Sweet, eh?
583
584 WARNING:
585 We don’t recommend that you try to gather metrics from your produc‐
586 tion environment. JMX’s RPC API is fragile and bonkers. For develop‐
587 ment purposes and browsing, though, it can be very useful.
588
589 To report metrics via JMX:
590
591 final JmxReporter reporter = JmxReporter.forRegistry(registry).build();
592 reporter.start();
593
594 Console
595 For simple benchmarks, Metrics comes with ConsoleReporter, which peri‐
596 odically reports all registered metrics to the console:
597
598 final ConsoleReporter reporter = ConsoleReporter.forRegistry(registry)
599 .convertRatesTo(TimeUnit.SECONDS)
600 .convertDurationsTo(TimeUnit.MILLISECONDS)
601 .build();
602 reporter.start(1, TimeUnit.MINUTES);
603
604 CSV
605 For more complex benchmarks, Metrics comes with CsvReporter, which
606 periodically appends to a set of .csv files in a given directory:
607
608 final CsvReporter reporter = CsvReporter.forRegistry(registry)
609 .formatFor(Locale.US)
610 .convertRatesTo(TimeUnit.SECONDS)
611 .convertDurationsTo(TimeUnit.MILLISECONDS)
612 .build(new File("~/projects/data/"));
613 reporter.start(1, TimeUnit.SECONDS);
614
615 For each metric registered, a .csv file will be created, and every sec‐
616 ond its state will be written to it as a new row.
617
618 SLF4J
619 It’s also possible to log metrics to an SLF4J logger:
620
621 final Slf4jReporter reporter = Slf4jReporter.forRegistry(registry)
622 .outputTo(LoggerFactory.getLogger("com.example.metrics"))
623 .convertRatesTo(TimeUnit.SECONDS)
624 .convertDurationsTo(TimeUnit.MILLISECONDS)
625 .build();
626 reporter.start(1, TimeUnit.MINUTES);
627
628 Other Reporters
629 Metrics has other reporter implementations, too:
630
631 · MetricsServlet is a servlet which not only exposes your metrics as a
632 JSON object, but it also runs your health checks, performs thread
633 dumps, and exposes valuable JVM-level and OS-level information.
634
635 · GangliaReporter allows you to constantly stream metrics data to your
636 Ganglia servers.
637
638 · GraphiteReporter allows you to constantly stream metrics data to your
639 Graphite servers.
640
641 Health Checks
642 Metrics also provides you with a consistent, unified way of performing
643 application health checks. A health check is basically a small
644 self-test which your application performs to verify that a specific
645 component or responsibility is performing correctly.
646
647 To create a health check, extend the HealthCheck class:
648
649 public class DatabaseHealthCheck extends HealthCheck {
650 private final Database database;
651
652 public DatabaseHealthCheck(Database database) {
653 this.database = database;
654 }
655
656 @Override
657 protected Result check() throws Exception {
658 if (database.ping()) {
659 return Result.healthy();
660 }
661 return Result.unhealthy("Can't ping database");
662 }
663 }
664
665 In this example, we’ve created a health check for a Database class on
666 which our application depends. Our fictitious Database class has a
667 #ping() method, which executes a safe test query (e.g., SELECT 1).
668 #ping() returns true if the query returns the expected result, returns
669 false if it returns something else, and throws an exception if things
670 have gone seriously wrong.
671
672 Our DatabaseHealthCheck, then, takes a Database instance and in its
673 #check() method, attempts to ping the database. If it can, it returns a
674 healthy result. If it can’t, it returns an unhealthy result.
675
676 NOTE:
677 Exceptions thrown inside a health check’s #check() method are auto‐
678 matically caught and turned into unhealthy results with the full
679 stack trace.
680
681 To register a health check, either use a HealthCheckRegistry instance:
682
683 registry.register("database", new DatabaseHealthCheck(database));
684
685 You can also run the set of registered health checks:
686
687 for (Entry<String, Result> entry : registry.runHealthChecks().entrySet()) {
688 if (entry.getValue().isHealthy()) {
689 System.out.println(entry.getKey() + ": OK");
690 } else {
691 System.out.println(entry.getKey() + ": FAIL");
692 }
693 }
694
695 Instrumenting Ehcache
696 The metrics-ehcache module provides InstrumentedEhcache, a decorator
697 for Ehcache caches:.INDENT 0.0
698
699 final Cache c = new Cache(new CacheConfiguration("test", 100));
700 MANAGER.addCache(c);
701 this.cache = InstrumentedEhcache.instrument(registry, c);
702
703Instrumenting an Ehcache instance creates gauges for all of the Ehcache-pro‐
704vided statistics:
705
706 ┌────────────────────┬────────────────────────────┐
707 │hits │ The number of times a │
708 │ │ requested item was found │
709 │ │ in the cache. │
710 ├────────────────────┼────────────────────────────┤
711 │in-memory-hits │ Number of times a │
712 │ │ requested item was found │
713 │ │ in the memory store. │
714 ├────────────────────┼────────────────────────────┤
715 │off-heap-hits │ Number of times a │
716 │ │ requested item was found │
717 │ │ in the off-heap store. │
718 ├────────────────────┼────────────────────────────┤
719 │on-disk-hits │ Number of times a │
720 │ │ requested item was found │
721 │ │ in the disk store. │
722 ├────────────────────┼────────────────────────────┤
723 │misses │ Number of times a │
724 │ │ requested item was not │
725 │ │ found in the cache. │
726 ├────────────────────┼────────────────────────────┤
727 │in-memory-misses │ Number of times a │
728 │ │ requested item was not │
729 │ │ found in the memory store. │
730 └────────────────────┴────────────────────────────┘
731
732 │off-heap-misses │ Number of times a │
733 │ │ requested item was not │
734 │ │ found in the off-heap │
735 │ │ store. │
736 ├────────────────────┼────────────────────────────┤
737 │on-disk-misses │ Number of times a │
738 │ │ requested item was not │
739 │ │ found in the disk store. │
740 ├────────────────────┼────────────────────────────┤
741 │objects │ Number of elements stored │
742 │ │ in the cache. │
743 ├────────────────────┼────────────────────────────┤
744 │in-memory-objects │ Number of objects in the │
745 │ │ memory store. │
746 ├────────────────────┼────────────────────────────┤
747 │off-heap-objects │ Number of objects in the │
748 │ │ off-heap store. │
749 ├────────────────────┼────────────────────────────┤
750 │on-disk-objects │ Number of objects in the │
751 │ │ disk store. │
752 ├────────────────────┼────────────────────────────┤
753 │mean-get-time │ The average get time. │
754 │ │ Because ehcache supports │
755 │ │ JDK1.4.2, each get time │
756 │ │ uses System.current‐ │
757 │ │ TimeMillis(), rather than │
758 │ │ nanoseconds. The accuracy │
759 │ │ is thus limited. │
760 ├────────────────────┼────────────────────────────┤
761 │mean-search-time │ The average execution time │
762 │ │ (in milliseconds) within │
763 │ │ the last sample period. │
764 ├────────────────────┼────────────────────────────┤
765 │eviction-count │ The number of cache evic‐ │
766 │ │ tions, since the cache was │
767 │ │ created, or statistics │
768 │ │ were cleared. │
769 ├────────────────────┼────────────────────────────┤
770 │searches-per-second │ The number of search exe‐ │
771 │ │ cutions that have com‐ │
772 │ │ pleted in the last second. │
773 ├────────────────────┼────────────────────────────┤
774 │accuracy │ A human readable descrip‐ │
775 │ │ tion of the accuracy set‐ │
776 │ │ ting. One of “None”, “Best │
777 │ │ Effort” or “Guaranteed”. │
778 └────────────────────┴────────────────────────────┘
779
780It also adds full timers for the cache’s get and put methods.
781
782The metrics are all scoped to the cache’s class and name, so a Cache instance
783named users would have metric names like net.sf.ehcache.Cache.users.get, etc.
784
785 Reporting to Ganglia
786 The metrics-ganglia module provides GangliaReporter, which allows your
787 application to constantly stream metric values to a Ganglia server:
788
789 final GMetric ganglia = new GMetric("ganglia.example.com", 8649, UDPAddressingMode.MULTICAST, 1);
790 final GangliaReporter reporter = GangliaReporter.forRegistry(registry)
791 .convertRatesTo(TimeUnit.SECONDS)
792 .convertDurationsTo(TimeUnit.MILLISECONDS)
793 .build(ganglia);
794 reporter.start(1, TimeUnit.MINUTES);
795
796 Reporting to Graphite
797 The metrics-graphite module provides GraphiteReporter, which allows
798 your application to constantly stream metric values to a Graphite
799 server:
800
801 final Graphite graphite = new Graphite(new InetSocketAddress("graphite.example.com", 2003));
802 final GraphiteReporter reporter = GraphiteReporter.forRegistry(registry)
803 .prefixedWith("web1.example.com")
804 .convertRatesTo(TimeUnit.SECONDS)
805 .convertDurationsTo(TimeUnit.MILLISECONDS)
806 .filter(MetricFilter.ALL)
807 .build(graphite);
808 reporter.start(1, TimeUnit.MINUTES);
809
810 If you prefer to write metrics in batches using pickle, you can use the
811 PickledGraphite:
812
813 final Graphite pickledGraphite = new PickledGraphite(new InetSocketAddress("graphite.example.com", 2004));
814 final GraphiteReporter reporter = GraphiteReporter.forRegistry(registry)
815 .prefixedWith("web1.example.com")
816 .convertRatesTo(TimeUnit.SECONDS)
817 .convertDurationsTo(TimeUnit.MILLISECONDS)
818 .filter(MetricFilter.ALL)
819 .build(pickledGraphite);
820 reporter.start(1, TimeUnit.MINUTES);
821
822 Instrumenting Apache HttpClient
823 The metrics-httpclient module provides InstrumentedHttpClientConnMan‐
824 ager and InstrumentedHttpClients, two instrumented versions of Apache
825 HttpClient 4.x classes.
826
827 InstrumentedHttpClientConnManager is a thread-safe HttpClientConnec‐
828 tionManager implementation which measures the number of open connec‐
829 tions in the pool and the rate at which new connections are opened.
830
831 InstrumentedHttpClients follows the HttpClients builder pattern and
832 adds per-HTTP method timers for HTTP requests.
833
834 Metric naming strategies
835 The default per-method metric naming and scoping strategy can be over‐
836 ridden by passing an implementation of HttpClientMetricNameStrategy to
837 the InstrumentedHttpClients.createDefault method.
838
839 A number of pre-rolled strategies are available, e.g.:
840
841 HttpClient client = InstrumentedHttpClients.createDefault(registry, HttpClientMetricNameStrategies.HOST_AND_METHOD);
842
843 Instrumenting JDBI
844 The metrics-jdbi module provides a TimingCollector implementation for
845 JDBI, an SQL convenience library.
846
847 To use it, just add a InstrumentedTimingCollector instance to your DBI:
848
849 final DBI dbi = new DBI(dataSource);
850 dbi.setTimingCollector(new InstrumentedTimingCollector(registry));
851
852 InstrumentedTimingCollector keeps per-SQL-object timing data, as well
853 as general raw SQL timing data. The metric names for each query are
854 constructed by an StatementNameStrategy instance, of which there are
855 many implementations. By default, StatementNameStrategy uses Smart‐
856 NameStrategy, which attempts to effectively handle both queries from
857 bound objects and raw SQL.
858
859 Instrumenting Jersey 1.x
860 The metrics-jersey module provides InstrumentedResourceMethodDis‐
861 patchAdapter, which allows you to instrument methods on your Jersey 1.x
862 resource classes:
863
864 An instance of InstrumentedResourceMethodDispatchAdapter must be regis‐
865 tered with your Jersey application’s ResourceConfig as a singleton
866 provider for this to work.
867
868 public class ExampleApplication {
869 private final DefaultResourceConfig config = new DefaultResourceConfig();
870
871 public void init() {
872 config.getSingletons().add(new InstrumentedResourceMethodDispatchAdapter(registry));
873 config.getClasses().add(ExampleResource.class);
874 }
875 }
876
877
878 @Path("/example")
879 @Produces(MediaType.TEXT_PLAIN)
880 public class ExampleResource {
881 @GET
882 @Timed
883 public String show() {
884 return "yay";
885 }
886 }
887
888 The show method in the above example will have a timer attached to it,
889 measuring the time spent in that method.
890
891 Use of the @Metered and @ExceptionMetered annotations is also sup‐
892 ported.
893
894 Instrumenting Jersey 2.x
895 Jersey 2.x changed the API for how resource method monitoring works, so
896 a new module metrics-jersey2 provides InstrumentedResourceMethodAppli‐
897 cationListener, which allows you to instrument methods on your Jersey
898 2.x resource classes:
899
900 The metrics-jersey2 module provides InstrumentedResourceMethodApplica‐
901 tionListener, which allows you to instrument methods on your Jersey 2.x
902 resource classes:
903
904 An instance of InstrumentedResourceMethodApplicationListener must be
905 registered with your Jersey application’s ResourceConfig as a singleton
906 provider for this to work.
907
908 public class ExampleApplication extends ResourceConfig {
909 .
910 .
911 .
912 register(new InstrumentedResourceMethodApplicationListener (new MetricRegistry()));
913 config = config.register(ExampleResource.class);
914 .
915 .
916 .
917 }
918
919 @Path("/example")
920 @Produces(MediaType.TEXT_PLAIN)
921 public class ExampleResource {
922 @GET
923 @Timed
924 public String show() {
925 return "yay";
926 }
927 }
928
929 The show method in the above example will have a timer attached to it,
930 measuring the time spent in that method.
931
932 Use of the @Metered and @ExceptionMetered annotations is also sup‐
933 ported.
934
935 Instrumenting Jetty
936 The metrics-jetty8 (Jetty 8.0), metrics-jetty9-legacy (Jetty 9.0), and
937 metrics-jetty9 (Jetty 9.1 and higher) modules provides a set of instru‐
938 mented equivalents of Jetty classes: InstrumentedBlockingChannelConnec‐
939 tor, InstrumentedHandler, InstrumentedQueuedThreadPool, InstrumentedSe‐
940 lectChannelConnector, and InstrumentedSocketConnector.
941
942 The Connector implementations are simple, instrumented subclasses of
943 the Jetty connector types which measure connection duration, the rate
944 of accepted connections, connections, disconnections, and the total
945 number of active connections.
946
947 InstrumentedQueuedThreadPool is a QueuedThreadPool subclass which mea‐
948 sures the ratio of idle threads to working threads as well as the abso‐
949 lute number of threads (idle and otherwise).
950
951 InstrumentedHandler is a Handler decorator which measures a wide range
952 of HTTP behavior: dispatch times, requests, resumes, suspends, expires,
953 the number of active, suspected, and dispatched requests, as well as
954 meters of responses with 1xx, 2xx, 3xx, 4xx, and 5xx status codes. It
955 even has gauges for the ratios of 4xx and 5xx response rates to overall
956 response rates. Finally, it includes meters for requests by the HTTP
957 method: GET, POST, etc.
958
959 Instrumenting Log4j
960 The metrics-log4j and metrics-log4j2 modules provide InstrumentedAppen‐
961 der, a Log4j Appender implementation (for log4j 1.x and log4j 2.x cor‐
962 respondingly) which records the rate of logged events by their logging
963 level.
964
965 You can add it to the root logger programmatically.
966
967 For log4j 1.x:
968
969 InstrumentedAppender appender = new InstrumentedAppender(registry);
970 appender.activateOptions();
971 LogManager.getRootLogger().addAppender(appender);
972
973 For log4j 2.x:
974
975 Filter filter = null; // That's fine if we don't use filters; https://logging.apache.org/log4j/2.x/manual/filters.html
976 PatternLayout layout = null; // The layout isn't used in InstrumentedAppender
977
978 InstrumentedAppender appender = new InstrumentedAppender(metrics, filter, layout, false);
979 appender.start();
980
981 LoggerContext context = (LoggerContext) LogManager.getContext(false);
982 Configuration config = context.getConfiguration();
983 config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME).addAppender(appender, level, filter);
984 context.updateLoggers(config);
985
986 Instrumenting Logback
987 The metrics-logback module provides InstrumentedAppender, a Logback
988 Appender implementation which records the rate of logged events by
989 their logging level.
990
991 You add it to the root logger programmatically:
992
993 final LoggerContext factory = (LoggerContext) LoggerFactory.getILoggerFactory();
994 final Logger root = factory.getLogger(Logger.ROOT_LOGGER_NAME);
995
996 final InstrumentedAppender metrics = new InstrumentedAppender(registry);
997 metrics.setContext(root.getLoggerContext());
998 metrics.start();
999 root.addAppender(metrics);
1000
1001 JVM Instrumentation
1002 The metrics-jvm module contains a number of reusable gauges and metric
1003 sets which allow you to easily instrument JVM internals.
1004
1005 Supported metrics include:
1006
1007 · Run count and elapsed times for all supported garbage collectors
1008
1009 · Memory usage for all memory pools, including off-heap memory
1010
1011 · Breakdown of thread states, including deadlocks
1012
1013 · File descriptor usage
1014
1015 · Buffer pool sizes and utilization (Java 7 only)
1016
1017 JSON Support
1018 Metrics comes with metrics-json, which features two reusable modules
1019 for Jackson.
1020
1021 This allows for the serialization of all metric types and health checks
1022 to a standard, easily-parsable JSON format.
1023
1024 Metrics Servlets
1025 The metrics-servlets module provides a handful of useful servlets:
1026
1027 HealthCheckServlet
1028 HealthCheckServlet responds to GET requests by running all the [health
1029 checks](#health-checks) and returning 501 Not Implemented if no health
1030 checks are registered, 200 OK if all pass, or 500 Internal Service
1031 Error if one or more fail. The results are returned as a human-readable
1032 text/plain entity.
1033
1034 HealthCheckServlet requires that the servlet context has a HealthCheck‐
1035 Registry named com.codahale.metrics.servlets.HealthCheckServlet.reg‐
1036 istry. You can subclass MetricsServletContextListener, which will add a
1037 specific HealthCheckRegistry to the servlet context.
1038
1039 ThreadDumpServlet
1040 ThreadDumpServlet responds to GET requests with a text/plain represen‐
1041 tation of all the live threads in the JVM, their states, their stack
1042 traces, and the state of any locks they may be waiting for.
1043
1044 MetricsServlet
1045 MetricsServlet exposes the state of the metrics in a particular reg‐
1046 istry as a JSON object.
1047
1048 MetricsServlet requires that the servlet context has a MetricRegistry
1049 named com.codahale.metrics.servlets.MetricsServlet.registry. You can
1050 subclass MetricsServletContextListener, which will add a specific Met‐
1051 ricRegistry to the servlet context.
1052
1053 MetricsServlet also takes an initialization parameter, show-jvm-met‐
1054 rics, which if "false" will disable the outputting of JVM-level infor‐
1055 mation in the JSON object.
1056
1057 PingServlet
1058 PingServlet responds to GET requests with a text/plain/200 OK response
1059 of pong. This is useful for determining liveness for load balancers,
1060 etc.
1061
1062 AdminServlet
1063 AdminServlet aggregates HealthCheckServlet, ThreadDumpServlet, Metric‐
1064 sServlet, and PingServlet into a single, easy-to-use servlet which pro‐
1065 vides a set of URIs:
1066
1067 · /: an HTML admin menu with links to the following:
1068
1069 · /healthcheck: HealthCheckServlet
1070
1071 · /metrics: MetricsServlet
1072
1073 · /ping: PingServlet
1074
1075 · /threads: ThreadDumpServlet
1076
1077 You will need to add your MetricRegistry and HealthCheckRegistry
1078 instances to the servlet context as attributes named com.codahale.met‐
1079 rics.servlets.MetricsServlet.registry and com.codahale.met‐
1080 rics.servlets.HealthCheckServlet.registry, respectively. You can do
1081 this using the Servlet API by extending MetricsServlet.ContextListener
1082 for MetricRegistry:
1083
1084 public class MyMetricsServletContextListener extends MetricsServlet.ContextListener {
1085
1086 public static final MetricRegistry METRIC_REGISTRY = new MetricRegistry();
1087
1088 @Override
1089 protected MetricRegistry getMetricRegistry() {
1090 return METRIC_REGISTRY;
1091 }
1092
1093 }
1094
1095 And by extending HealthCheckServlet.ContextListener for HealthCheckReg‐
1096 istry:
1097
1098 public class MyHealthCheckServletContextListener extends HealthCheckServlet.ContextListener {
1099
1100 public static final HealthCheckRegistry HEALTH_CHECK_REGISTRY = new HealthCheckRegistry();
1101
1102 @Override
1103 protected HealthCheckRegistry getHealthCheckRegistry() {
1104 return HEALTH_CHECK_REGISTRY;
1105 }
1106
1107 }
1108
1109 Then you will need to register servlet context listeners either in you
1110 web.xml or annotating the class with @WebListener if you are in servlet
1111 3.0 environment. In web.xml:
1112
1113 <listener>
1114 <listener-class>com.example.MyMetricsServletContextListener</listener-class>
1115 </listener>
1116 <listener>
1117 <listener-class>com.example.MyHealthCheckServletContextListener</listener-class>
1118 </listener>
1119
1120 You will also need to register AdminServlet in web.xml:
1121
1122 <servlet>
1123 <servlet-name>metrics</servlet-name>
1124 <servlet-class>com.codahale.metrics.servlets.AdminServlet</servlet-class>
1125 </servlet>
1126 <servlet-mapping>
1127 <servlet-name>metrics</servlet-name>
1128 <url-pattern>/metrics/*</url-pattern>
1129 </servlet-mapping>
1130
1131 Instrumenting Web Applications
1132 The metrics-servlet module provides a Servlet filter which has meters
1133 for status codes, a counter for the number of active requests, and a
1134 timer for request duration. By default the filter will use com.coda‐
1135 hale.metrics.servlet.InstrumentedFilter as the base name of the met‐
1136 rics. You can use the filter in your web.xml like this:
1137
1138 <filter>
1139 <filter-name>instrumentedFilter</filter-name>
1140 <filter-class>com.codahale.metrics.servlet.InstrumentedFilter</filter-class>
1141 </filter>
1142 <filter-mapping>
1143 <filter-name>instrumentedFilter</filter-name>
1144 <url-pattern>/*</url-pattern>
1145 </filter-mapping>
1146
1147 An optional filter init-param name-prefix can be specified to override
1148 the base name of the metrics associated with the filter mapping. This
1149 can be helpful if you need to instrument multiple url patterns and give
1150 each a unique name.
1151
1152 <filter>
1153 <filter-name>instrumentedFilter</filter-name>
1154 <filter-class>com.codahale.metrics.servlet.InstrumentedFilter</filter-class>
1155 <init-param>
1156 <param-name>name-prefix</param-name>
1157 <param-value>authentication</param-value>
1158 </init-param>
1159 </filter>
1160 <filter-mapping>
1161 <filter-name>instrumentedFilter</filter-name>
1162 <url-pattern>/auth/*</url-pattern>
1163 </filter-mapping>
1164
1165 You will need to add your MetricRegistry to the servlet context as an
1166 attribute named com.codahale.metrics.servlet.InstrumentedFilter.reg‐
1167 istry. You can do this using the Servlet API by extending Instrumented‐
1168 FilterContextListener:
1169
1170 public class MyInstrumentedFilterContextListener extends InstrumentedFilterContextListener {
1171 public static final MetricRegistry REGISTRY = new MetricRegistry();
1172
1173 @Override
1174 protected MetricRegistry getMetricRegistry() {
1175 return REGISTRY;
1176 }
1177 }
1178
1179 Third Party Libraries
1180 If you’re looking to integrate with something not provided by the main
1181 Metrics libraries, check out the many third-party libraries which
1182 extend Metrics:
1183
1184 · metrics-librato provides a reporter for Librato Metrics, a scalable
1185 metric collection, aggregation, monitoring, and alerting service.
1186
1187 · metrics-spring provides integration with Spring
1188
1189 · sematext-metrics-reporter provides a reporter for SPM.
1190
1191 · wicket-metrics provides easy integration for your Wicket application.
1192
1193 · metrics-guice provides integration with Guice.
1194
1195 · metrics-scala provides an API optimized for Scala.
1196
1197 · metrics-clojure provides an API optimized for Clojure.
1198
1199 · metrics-cassandra provides a reporter for Apache Cassandra.
1200
1201 · MetricCatcher Turns JSON over UDP into Metrics so that non-jvm lan‐
1202 guages can know what’s going on too.
1203
1204 · metrics-reporter-config DropWizard-eqsue YAML configuration of
1205 reporters.
1206
1207 · metrics-elasticsearch-reporter provides a reporter for elasticsearch
1208
1209 · metrics-statsd provides a Metrics 2.x and 3.x reporter for StatsD
1210
1211 · metrics-datadog provides a reporter to send data to Datadog
1212
1213 · metrics-influxdb provides a reporter which announces measurements to
1214 InfluxDB
1215
1216 · metrics-cdi provides integration with CDI environments
1217
1218 · metrics-aspectj provides integration with AspectJ
1219
1220 · camel-metrics provides component for your Apache Camel route
1221
1223 Contributors
1224 Many, many thanks to:
1225
1226 · Alan Woodward
1227
1228 · Alex Lambert
1229
1230 · Basil James Whitehouse III
1231
1232 · Benjamin Gehrels
1233
1234 · Bernardo Gomez Palacio
1235
1236 · Brian Ehmann
1237
1238 · Brian Roberts
1239
1240 · Bruce Mitchener
1241
1242 · C. Scott Andreas
1243
1244 · ceetav
1245
1246 · Charles Care
1247
1248 · Chris Birchall
1249
1250 · Chris Burroughs
1251
1252 · Christopher Swenson
1253
1254 · Ciamac Moallemi
1255
1256 · Cliff Moon
1257
1258 · Collin VanDyck
1259
1260 · Dag Liodden
1261
1262 · Dale Wijnand
1263
1264 · Dan Brown
1265
1266 · Dan Everton
1267
1268 · Dan Revel
1269
1270 · David Sutherland
1271
1272 · Diwaker Gupta
1273
1274 · Drew Stephens
1275
1276 · Edwin Shin
1277
1278 · Eric Daigneault
1279
1280 · Evan Jones
1281
1282 · François Beausoleil
1283
1284 · Gerolf Seitz
1285
1286 · Greg Bowyer
1287
1288 · Jackson Davis
1289
1290 · James Casey
1291
1292 · Jan-Helge Bergesen
1293
1294 · Jason A. Beranek
1295
1296 · Jason Slagle
1297
1298 · JD Maturen
1299
1300 · Jeff Hodges
1301
1302 · Jesper Blomquist
1303
1304 · Jesse Eichar
1305
1306 · John Ewart
1307
1308 · John Wang
1309
1310 · Justin Plock
1311
1312 · Kevin Clark
1313
1314 · Mahesh Tiyyagura
1315
1316 · Martin Traverso
1317
1318 · Matt Abrams
1319
1320 · Matt Ryall
1321
1322 · Matthew Gilliard
1323
1324 · Matthew O’Connor
1325
1326 · Mathijs Vogelzang
1327
1328 · Mårten Gustafson
1329
1330 · Michał Minicki
1331
1332 · Neil Prosser
1333
1334 · Nick Telford
1335
1336 · Niklas Konstenius
1337
1338 · Norbert Potocki
1339
1340 · Pablo Fernandez
1341
1342 · Paul Bloch
1343
1344 · Paul Brown
1345
1346 · Paul Doran
1347
1348 · Paul Sandwald
1349
1350 · Realbot
1351
1352 · Robby Walker
1353
1354 · Ryan Kennedy
1355
1356 · Ryan W Tenney
1357
1358 · Sam Perman
1359
1360 · Sean Laurent
1361
1362 · Shaneal Manek
1363
1364 · Steven Schlansker
1365
1366 · Stewart Allen
1367
1368 · Thomas Dudziak
1369
1370 · Tobias Lidskog
1371
1372 · Yang Ye
1373
1374 · Wolfgang Schell
1375
1376 Release Notes
1377 v3.0.1: Jul 23 2013
1378 · Fixed NPE in MetricRegistry#name.
1379
1380 · ScheduledReporter and JmxReporter now implement Closeable.
1381
1382 · Fixed cast exception for async requests in metrics-jetty9.
1383
1384 · Added support for Access-Control-Allow-Origin to MetricsServlet.
1385
1386 · Fixed numerical issue with Meter EWMA rates.
1387
1388 · Deprecated AdminServletContextListener in favor of Metric‐
1389 sServlet.ContextListener and HealthCheckServlet.ContextListener.
1390
1391 · Added additional constructors to HealthCheckServlet and Metric‐
1392 sServlet.
1393
1394 v3.0.0: June 10 2013
1395 · Renamed DefaultWebappMetricsFilter to InstrumentedFilter.
1396
1397 · Renamed MetricsContextListener to InstrumentedFilterContextListener
1398 and made it fully abstract to avoid confusion.
1399
1400 · Renamed MetricsServletContextListener to AdminServletContextListener
1401 and made it fully abstract to avoid confusion.
1402
1403 · Upgraded to Servlet API 3.1.
1404
1405 · Upgraded to Jackson 2.2.2.
1406
1407 · Upgraded to Jetty 8.1.11.
1408
1409 v3.0.0-RC1: May 31 2013
1410 · Added SharedMetricRegistries, a singleton for sharing named metric
1411 registries.
1412
1413 · Fixed XML configuration for metrics-ehcache.
1414
1415 · Fixed XML configuration for metrics-jersey.
1416
1417 · Fixed XML configuration for metrics-log4j.
1418
1419 · Fixed XML configuration for metrics-logback.
1420
1421 · Fixed a counting bug in metrics-jetty9’s InstrumentedHandler.
1422
1423 · Added MetricsContextListener to metrics-servlet.
1424
1425 · Added MetricsServletContextListener to metrics-servlets.
1426
1427 · Extracted the Counting interface.
1428
1429 · Reverted SlidingWindowReservoir to a synchronized implementation.
1430
1431 · Added the implementation version to the JAR manifests.
1432
1433 · Made dependencies for all modules conform to Maven Enforcer’s conver‐
1434 gence rules.
1435
1436 · Fixed Slf4jReporter’s logging of 99th percentiles.
1437
1438 · Added optional name prefixing to GraphiteReporter.
1439
1440 · Added metric-specific overrides of rate and duration units to JmxRe‐
1441 porter.
1442
1443 · Documentation fixes.
1444
1445 v3.0.0-BETA3: May 13 2013
1446 · Added ScheduledReporter#report() for manual reporting.
1447
1448 · Fixed overly-grabby catches in HealthCheck and Instrumente‐
1449 dResourceMethodDispatchProvider.
1450
1451 · Fixed phantom reads in SlidingWindowReservoir.
1452
1453 · Revamped metrics-jetty9, removing InstrumentedConnector and improving
1454 the API.
1455
1456 · Fixed OSGi imports for sun.misc.
1457
1458 · Added a strategy class for HttpClient metrics.
1459
1460 · Upgraded to Jetty 9.0.3.
1461
1462 · Upgraded to Jackson 2.2.1.
1463
1464 · Upgraded to Ehcache 2.6.6.
1465
1466 · Upgraded to Logback 1.0.13.
1467
1468 · Upgraded to HttpClient 4.2.5.
1469
1470 · Upgraded to gmetric4j 1.0.3, which allows for host spoofing.
1471
1472 v3.0.0-BETA2: Apr 22 2013
1473 · Metrics is now under the com.codahale.metrics package, with the cor‐
1474 responding changes in Maven artifact groups. This should allow for an
1475 easier upgrade path without classpath conflicts.
1476
1477 · MetricRegistry no longer has a name.
1478
1479 · Added metrics-jetty9 for Jetty 9.
1480
1481 · JmxReporter takes an optional domain property to disambiguate multi‐
1482 ple reporters.
1483
1484 · Fixed Java 6 compatibility problem. (Also added Java 6 as a CI envi‐
1485 ronment.)
1486
1487 · Added MetricRegistryListener.Base.
1488
1489 · Switched Counter, Meter, and EWMA to use JSR133’s LongAdder instead
1490 of AtomicLong, improving contended concurrency.
1491
1492 · Added MetricRegistry#buildMap(), allowing for custom map implementa‐
1493 tions in MetricRegistry.
1494
1495 · Added MetricRegistry#removeMatching(MetricFilter).
1496
1497 · Changed metrics-json to optionally depend on metrics-healthcheck.
1498
1499 · Upgraded to Jetty 8.1.10 for metrics-jetty8.
1500
1501 v3.0.0-BETA1: Apr 01 2013
1502 · Total overhaul of most of the core Metrics classes:
1503
1504 · Metric names are now just dotted paths like com.example.Thing,
1505 allowing for very flexible scopes, etc.
1506
1507 · Meters and timers no longer have rate or duration units; those are
1508 properties of reporters.
1509
1510 · Reporter architecture has been radically simplified, fixing many
1511 bugs.
1512
1513 · Histograms and timers can take arbitrary reservoir implementations.
1514
1515 · Added sliding window reservoir implementations.
1516
1517 · Added MetricSet for sets of metrics.
1518
1519 · Changed package names to be OSGi-compatible and added OSGi bundling.
1520
1521 · Extracted JVM instrumentation to metrics-jvm.
1522
1523 · Extracted Jackson integration to metrics-json.
1524
1525 · Removed metrics-guice, metrics-scala, and metrics-spring.
1526
1527 · Renamed metrics-servlet to metrics-servlets.
1528
1529 · Renamed metrics-web to metrics-servlet.
1530
1531 · Renamed metrics-jetty to metrics-jetty8.
1532
1533 · Many more small changes!
1534
1535 v2.2.0: Nov 26 2012
1536 · Removed all OSGi bundling. This will be back in 3.0.
1537
1538 · Added InstrumentedSslSelectChannelConnector and InstrumentedSslSock‐
1539 etConnector.
1540
1541 · Made all metric names JMX-safe.
1542
1543 · Upgraded to Ehcache 2.6.2.
1544
1545 · Upgraded to Apache HttpClient 4.2.2.
1546
1547 · Upgraded to Jersey 1.15.
1548
1549 · Upgraded to Log4j 1.2.17.
1550
1551 · Upgraded to Logback 1.0.7.
1552
1553 · Upgraded to Spring 3.1.3.
1554
1555 · Upgraded to Jetty 8.1.8.
1556
1557 · Upgraded to SLF4J 1.7.2.
1558
1559 · Replaced usage of Unsafe in InstrumentedResourceMethodDispatch‐
1560 Provider with type erasure trickery.
1561
1562 v2.1.5: Nov 19 2012
1563 · Upgraded to Jackson 2.1.1.
1564
1565 v2.1.4: Nov 15 2012
1566 · Added OSGi bundling manifests.
1567
1568 v2.1.3: Aug 06 2012
1569 · Upgraded to Apache HttpClient 4.2.1.
1570
1571 · Changed InstrumentedClientConnManager to extend PoolingClientConnec‐
1572 tionManager instead of the deprecated ThreadSafeClientConnManager.
1573
1574 · Fixed a bug in ExponentiallyDecayingSample with long periods of inac‐
1575 tivity.
1576
1577 · Fixed problems with re-registering metrics in JMX.
1578
1579 · Added support for DnsResolver instances to InstrumentedClientConnMan‐
1580 ager.
1581
1582 · Added support for formatted health check error messages.
1583
1584 v2.1.2: Apr 11 2012
1585 · Fixed double-registration in metrics-guice.
1586
1587 v2.1.1: Mar 13 2012
1588 · Fixed instrumentation of all usages of InstrumentedHttpClient.
1589
1590 v2.1.0: Mar 12 2012
1591 · Added support for Java 7’s direct and mapped buffer pool stats in
1592 VirtualMachineMetrics and metrics-servlet.
1593
1594 · Added support for XML configuration in metrics-ehcache.
1595
1596 · metrics-spring now support @Gauge-annotated fields.
1597
1598 · Opened GraphiteReporter up for extension.
1599
1600 · Added group and type to metrics-annotations, metrics-guice, met‐
1601 rics-jersey, and metrics-spring.
1602
1603 · Fixed handling of non-int gauges in GangliaReporter.
1604
1605 · Fixed NullPointerException errors in metrics-spring.
1606
1607 · General improvements to metrics-spring, including allowing custom
1608 Clock instances.
1609
1610 v2.0.3: Feb 24 2012
1611 · Change logging of InstanceNotFoundException exceptions thrown while
1612 unregistering a metric in JmxReporter to TRACE. It being WARN
1613 resulted in huge log dumps preventing process shutdowns when applica‐
1614 tions had ~1K+ metrics.
1615
1616 · Upgraded to Spring 3.1.1 for metrics-spring.
1617
1618 · Upgraded to JDBI 2.31.2.
1619
1620 · Upgraded to Jersey 1.12.
1621
1622 · Upgraded to Jetty 7.6.1.
1623
1624 · Fixed rate units for meters in GangliaReporter.
1625
1626 v2.0.2: Feb 09 2012
1627 · InstrumentationModule in metrics-guice now uses the default Metric‐
1628 sRegistry and HealthCheckRegistry.
1629
1630 v2.0.1: Feb 08 2012
1631 · Fixed a concurrency bug in JmxReporter.
1632
1633 v2.0.0: Feb 07 2012
1634 · Upgraded to Jackson 1.9.4.
1635
1636 · Upgraded to Jetty 7.6.0.
1637
1638 · Added escaping for garbage collector and memory pool names in
1639 GraphiteReporter.
1640
1641 · Fixed the inability to start and stop multiple reporter instances.
1642
1643 · Switched to using a backported version of ThreadLocalRandom for Uni‐
1644 formSample and ExponentiallyDecayingSample to reduce lock contention
1645 on random number generation.
1646
1647 · Removed Ordered from TimedAnnotationBeanPostProcessor in met‐
1648 rics-spring.
1649
1650 · Upgraded to JDBI 2.31.1.
1651
1652 · Upgraded to Ehcache 2.5.1.
1653
1654 · Added #timerContext() to Scala Timer.
1655
1656 v2.0.0-RC0: Jan 19 2012
1657 · Added FindBugs checks to the build process.
1658
1659 · Fixed the catching of Error instances thrown during health checks.
1660
1661 · Added enable static methods to CsvReporter and changed CsvRe‐
1662 porter(File, MetricsRegistry) to CsvReporter(MetricsRegistry, File).
1663
1664 · Slimmed down InstrumentedEhcache.
1665
1666 · Hid the internals of GangliaReporter.
1667
1668 · Hid the internals of metrics-guice.
1669
1670 · Changed metrics-httpclient to consistently associate metrics with the
1671 org.apache class being extended.
1672
1673 · Hid the internals of metrics-httpclient.
1674
1675 · Rewrote InstrumentedAppender in metrics-log4j. It no longer forwards
1676 events to an appender. Instead, you can just attach it to your root
1677 logger to instrument logging.
1678
1679 · Rewrote InstrumentedAppender in metrics-logback. No major API
1680 changes.
1681
1682 · Fixed bugs with @ExceptionMetered-annotated resource methods in met‐
1683 rics-jersey.
1684
1685 · Fixed bugs generating Snapshot instances from concurrently modified
1686 collections.
1687
1688 · Fixed edge case in MetricsServlet’s thread dumps where one thread
1689 could be missed.
1690
1691 · Added RatioGauge and PercentGauge.
1692
1693 · Changed InstrumentedQueuedThreadPool’s percent-idle gauge to be a
1694 ratio.
1695
1696 · Decomposed MetricsServlet into a set of focused servlets:
1697 HealthCheckServlet, MetricsServlet, PingServlet, and Thread‐
1698 DumpServlet. The top-level servlet which provides the HTML menu page
1699 is now AdminServlet.
1700
1701 · Added metrics-spring.
1702
1703 v2.0.0-BETA19: Jan 07 2012
1704 · Added absolute memory usage to MetricsServlet.
1705
1706 · Extracted @Timed etc. to metrics-annotations.
1707
1708 · Added metrics-jersey, which provides a class allowing you to automat‐
1709 ically instrument all @Timed, @Metered, and @ExceptionMetered-anno‐
1710 tated resource methods.
1711
1712 · Moved all classes in metrics-scala from com.yammer.metrics to
1713 com.yammer.metrics.scala.
1714
1715 · Renamed CounterMetric to Counter.
1716
1717 · Renamed GaugeMetric to Gauge.
1718
1719 · Renamed HistogramMetric to Histogram.
1720
1721 · Renamed MeterMetric to Meter.
1722
1723 · Renamed TimerMetric to Timer.
1724
1725 · Added ToggleGauge, which returns 1 the first time it’s called and 0
1726 every time after that.
1727
1728 · Now licensed under Apache License 2.0.
1729
1730 · Converted VirtualMachineMetrics to a non-singleton class.
1731
1732 · Removed Utils.
1733
1734 · Removed deprecated constructors from Meter and Timer.
1735
1736 · Removed LoggerMemoryLeakFix.
1737
1738 · DeathRattleExceptionHandler now logs to SLF4J, not syserr.
1739
1740 · Added MetricsRegistry#groupedMetrics().
1741
1742 · Removed Metrics#allMetrics().
1743
1744 · Removed Metrics#remove(MetricName).
1745
1746 · Removed MetricsRegistry#threadPools() and #newMeterTickThreadPool()
1747 and added #newScheduledThreadPool.
1748
1749 · Added MetricsRegistry#shutdown().
1750
1751 · Renamed ThreadPools#shutdownThreadPools() to #shutdown().
1752
1753 · Replaced HealthCheck’s abstract name method with a required construc‐
1754 tor parameter.
1755
1756 · HealthCheck#check() is now protected.
1757
1758 · Moved DeadlockHealthCheck from com.yammer.metrics.core to com.yam‐
1759 mer.metrics.utils.
1760
1761 · Added HealthCheckRegistry#unregister(HealthCheck).
1762
1763 · Fixed typo in VirtualMachineMetrics and MetricsServlet: commited to
1764 committed.
1765
1766 · Changed MetricsRegistry#createName to protected.
1767
1768 · All metric types are created exclusively through MetricsRegistry now.
1769
1770 · Metrics.newJmxGauge and MetricsRegistry.newJmxGauge are deprecated.
1771
1772 · Fixed heap metrics in VirtualMachineMetrics.
1773
1774 · Added Snapshot, which calculates quantiles.
1775
1776 · Renamed Percentiled to Sampling and dropped percentile and per‐
1777 centiles in favor of producing Snapshot instances. This affects both
1778 Histogram and Timer.
1779
1780 · Renamed Summarized to Summarizable.
1781
1782 · Changed order of CsvReporter’s construction parameters.
1783
1784 · Renamed VirtualMachineMetrics.GarbageCollector to VirtualMachineMet‐
1785 rics.GarbageCollectorStats.
1786
1787 · Moved Guice/Servlet support from metrics-servlet to metrics-guice.
1788
1789 · Removed metrics-aop.
1790
1791 · Removed newJmxGauge from both Metrics and MetricsRegistry. Just use
1792 JmxGauge.
1793
1794 · Moved JmxGauge to com.yammer.metrics.util.
1795
1796 · Moved MetricPredicate to com.yammer.metrics.core.
1797
1798 · Moved NameThreadFactory into ThreadPools and made ThreadPools pack‐
1799 age-visible.
1800
1801 · Removed Timer#values(), Histogram#values(), and Sample#values(). Use
1802 getSnapshot() instead.
1803
1804 · Removed Timer#dump(File) and Histogram#dump(File), and Sam‐
1805 ple#dump(File). Use Snapshot#dump(File) instead.
1806
1807 v2.0.0-BETA18: Dec 16 2011
1808 · Added DeathRattleExceptionHandler.
1809
1810 · Fixed NPE in VirtualMachineMetrics.
1811
1812 · Added decorators for connectors and thread pools in metrics-jetty.
1813
1814 · Added TimerMetric#time() and TimerContext.
1815
1816 · Added a shorter factory method for millisecond/second timers.
1817
1818 · Switched tests to JUnit.
1819
1820 · Improved logging in GangliaReporter.
1821
1822 · Improved random number generation for UniformSample.
1823
1824 · Added metrics-httpclient for instrumenting Apache HttpClient 4.1.
1825
1826 · Massively overhauled the reporting code.
1827
1828 · Added support for instrumented, non-public methods in metrics-guice.
1829
1830 · Added @ExceptionMetered to metrics-guice.
1831
1832 · Added group prefixes to GangliaReporter.
1833
1834 · Added CvsReporter, which outputs metric values to .csv files.
1835
1836 · Improved metric name sanitization in GangliaReporter.
1837
1838 · Added Metrics.shutdown() and improved metrics lifecycle behavior.
1839
1840 · Added metrics-web.
1841
1842 · Upgraded to ehcache 2.5.0.
1843
1844 · Many, many refactorings.
1845
1846 · metrics-servlet now responds with 501 Not Implememented when no
1847 health checks have been registered.
1848
1849 · Many internal refactorings for testability.
1850
1851 · Added histogram counts to metrics-servlet.
1852
1853 · Fixed a race condition in ExponentiallyDecayingSample.
1854
1855 · Added timezone and locale support to ConsoleReporter.
1856
1857 · Added metrics-aop for Guiceless support of method annotations.
1858
1859 · Added metrics-jdbi which adds instrumentation to JDBI.
1860
1861 · Fixed NPE for metrics which belong to classes in the default package.
1862
1863 · Now deploying artifacts to Maven Central.
1864
1865 v2.0.0-BETA17: Oct 07 2011
1866 · Added an option message to successful health check results.
1867
1868 · Fixed locale issues in GraphiteReporter.
1869
1870 · Added GangliaReporter.
1871
1872 · Added per-HTTP method timers to InstrumentedHandler in metrics-jetty.
1873
1874 · Fixed a thread pool leak for meters.
1875
1876 · Added #dump(File) to HistogramMetric and TimerMetric.
1877
1878 · Upgraded to Jackson 1.9.x.
1879
1880 · Upgraded to slf4j 1.6.2.
1881
1882 · Upgraded to logback 0.9.30.
1883
1884 · Upgraded to ehcache 2.4.5.
1885
1886 · Surfaced Metrics.removeMetric().
1887
1888 v2.0.0-BETA16: Aug 23 2011
1889 · Fixed a bug in GC monitoring.
1890
1891 v2.0.0-BETA15: Aug 15 2011
1892 · Fixed dependency scopes for metrics-jetty.
1893
1894 · Added time and VM version to vm output of MetricsServlet.
1895
1896 · Dropped com.sun.mangement-based GC instrumentation in favor of a
1897 java.lang.management-based one. getLastGcInfo has a nasty native mem‐
1898 ory leak in it, plus it often returned incorrect data.
1899
1900 · Upgraded to Jackson 1.8.5.
1901
1902 · Upgraded to Jetty 7.4.5.
1903
1904 · Added sanitization for metric names in GraphiteReporter.
1905
1906 · Extracted out a Clock interface for timers for non-wall-clock timing.
1907
1908 · Extracted out most of the remaining statics into MetricsRegistry and
1909 HealthCheckRegistry.
1910
1911 · Added an init parameter to MetricsServlet for disabling the jvm sec‐
1912 tion.
1913
1914 · Added a Guice module for MetricsServlet.
1915
1916 · Added dynamic metric names.
1917
1918 · Upgraded to ehcache 2.4.5.
1919
1920 · Upgraded to logback 0.9.29.
1921
1922 · Allowed for the removal of metrics.
1923
1924 · Added the ability to filter metrics exposed by a reporter to those
1925 which match a given predicate.
1926
1927 v2.0.0-BETA14: Jul 05 2011
1928 · Moved to Maven for a build system and extracted the Scala façade to a
1929 metrics-scala module which is now the only cross-built module. All
1930 other modules dropped the Scala version suffix in their artifactId.
1931
1932 · Fixed non-heap metric name in GraphiteReporter.
1933
1934 · Fixed stability error in GraphiteReporter when dealing with unavail‐
1935 able servers.
1936
1937 · Fixed error with anonymous, instrumented classes.
1938
1939 · Fixed error in MetricsServlet when a gauge throws an exception.
1940
1941 · Fixed error with bogus GC run times.
1942
1943 · Link to the pretty JSON output from the MetricsServlet menu page.
1944
1945 · Fixed potential race condition in histograms’ variance calculations.
1946
1947 · Fixed memory pool reporting for the G1 collector.
1948
1949 v2.0.0-BETA13: May 13 2011
1950 · Fixed a bug in the initial startup phase of the JmxReporter.
1951
1952 · Added metrics-ehcache, for the instrumentation of Ehcache instances.
1953
1954 · Fixed a typo in metrics-jetty’s InstrumentedHandler.
1955
1956 · Added name prefixes to GraphiteReporter.
1957
1958 · Added JVM metrics reporting to GraphiteReporter.
1959
1960 · Actually fixed MetricsServlet’s links when the servlet has a non-root
1961 context path.
1962
1963 · Now cross-building for Scala 2.9.0.
1964
1965 · Added pretty query parameter for MetricsServlet to format the JSON
1966 object for human consumption.
1967
1968 · Added no-cache headers to the MetricsServlet responses.
1969
1970 v2.0.0-BETA12: May 09 2011
1971 · Upgraded to Jackson 1.7.6.
1972
1973 · Added a new instrumented Log4J appender.
1974
1975 · Added a new instrumented Logback appender. Thanks to Bruce Mitchener
1976 (@waywardmonkeys) for the patch.
1977
1978 · Added a new reporter for the Graphite aggregation system. Thanks to
1979 Mahesh Tiyyagura (@tmahesh) for the patch.
1980
1981 · Added scoped metric names.
1982
1983 · Added Scala 2.9.0.RC{2,3,4} as build targets.
1984
1985 · Added meters to Jetty handler for the percent of responses which have
1986 4xx or 5xx status codes.
1987
1988 · Changed the Servlet API to be a provided dependency. Thanks to Mårten
1989 Gustafson (@chids) for the patch.
1990
1991 · Separated project into modules:
1992
1993 · metrics-core: A dependency-less project with all the core metrics.
1994
1995 · metrics-graphite: A reporter for the [Graphite](‐
1996 http://graphite.wikidot.com) aggregation system.
1997
1998 · metrics-guice: Guice AOP support.
1999
2000 · metrics-jetty: An instrumented Jetty handler.
2001
2002 · metrics-log4j: An instrumented Log4J appender.
2003
2004 · metrics-logback: An instrumented Logback appender.
2005
2006 · metrics-servlet: The Metrics servlet with context listener.
2007
2008 v2.0.0-BETA11: Apr 27 2011
2009 · Added thread state and deadlock detection metrics.
2010
2011 · Fix VirtualMachineMetrics’ initialization.
2012
2013 · Context path fixes for the servlet.
2014
2015 · Added the @Gauge annotation.
2016
2017 · Big reworking of the exponentially-weighted moving average code for
2018 meters. Thanks to JD Maturen (@sku) and John Ewart (@johnewart) for
2019 pointing this out.
2020
2021 · Upgraded to Guice 3.0.
2022
2023 · Upgraded to Jackson 1.7.5.
2024
2025 · Upgraded to Jetty 7.4.0.
2026
2027 · Big rewrite of the servlet’s thread dump code.
2028
2029 · Fixed race condition in ExponentiallyDecayingSample. Thanks to Martin
2030 Traverso (@martint) for the patch.
2031
2032 · Lots of spelling fixes in Javadocs. Thanks to Bruce Mitchener (@way‐
2033 wardmonkeys) for the patch.
2034
2035 · Added Scala 2.9.0.RC1 as a build target. Thanks to Bruce Mitchener
2036 (@waywardmonkeys) for the patch.
2037
2038 · Patched a hilarious memory leak in java.util.logging.
2039
2040 v2.0.0-BETA10: Mar 25 2011
2041 · Added Guice AOP annotations: @Timed and @Metered.
2042
2043 · Added HealthCheck#name().
2044
2045 · Added Metrics.newJmxGauge().
2046
2047 · Moved health checks into HealthChecks.
2048
2049 · Upgraded to Jackson 1.7.3 and Jetty 7.3.1.
2050
2051 v2.0.0-BETA9: Mar 14 2011
2052 · Fixed JmxReporter lag.
2053
2054 · Added default arguments to timers and meters.
2055
2056 · Added default landing page to the servlet.
2057
2058 · Improved the performance of ExponentiallyDecayingSample.
2059
2060 · Fixed an integer overflow bug in UniformSample.
2061
2062 · Added linear scaling to ExponentiallyDecayingSample.
2063
2064 v2.0.0-BETA8: Mar 01 2011
2065 · Added histograms.
2066
2067 · Added biased sampling for timers.
2068
2069 · Added dumping of timer/histogram samples via the servlet.
2070
2071 · Added dependency on jackon-mapper.
2072
2073 · Added classname filtering for the servlet.
2074
2075 · Added URI configuration for the servlet.
2076
2077 v2.0.0-BETA7: Jan 12 2011
2078 · Added JettyHandler.
2079
2080 · Made the Servlet dependency optional.
2081
2082 v2.0.0-BETA6: Jan 12 2011
2083 · Fix JmxReporter initialization.
2084
2085 v2.0.0-BETA5: Jan 11 2011
2086 · Dropped Counter#++ and Counter#--.
2087
2088 · Added Timer#update.
2089
2090 · Upgraded to Jackson 1.7.0.
2091
2092 · Made JMX reporting implicit.
2093
2094 · Added health checks.
2095
2096 v2.0.0-BETA3: Dec 23 2010
2097 · Fixed thread names and some docs.
2098
2099 v2.0.0-BETA2: Dec 22 2010
2100 · Fixed a memory leak in MeterMetric.
2101
2102 v2.0.0-BETA1: Dec 22 2010
2103 · Total rewrite in Java.
2104
2105 v1.0.7: Sep 21 2010
2106 · Added median to Timer.
2107
2108 · Added p95 to Timer (95th percentile).
2109
2110 · Added p98 to Timer (98th percentile).
2111
2112 · Added p99 to Timer (99th percentile).
2113
2114 v1.0.6: Jul 15 2010
2115 · Now compiled exclusively for 2.8.0 final.
2116
2117 v1.0.5: Jun 01 2010
2118 · Documentation fix.
2119
2120 · Added TimedToggle, which may or may not be useful at all.
2121
2122 · Now cross-building for RC2 and RC3.
2123
2124 v1.0.4: Apr 27 2010
2125 · Blank Timer instances (i.e., those which have recorded no timings
2126 yet) no longer explode when asked for metrics for that which does not
2127 yet exist.
2128
2129 · Nested classes, companion objects, and singletons don’t have trailing
2130 $ characters messing up JMX’s good looks.
2131
2132 v1.0.3: Apr 16 2010
2133 · Fixed some issues with the implicit.ly plumbing.
2134
2135 · Tweaked the sample size for Timer, giving it 99.9% confidence level
2136 with a %5 margin of error (for a normally distributed variable, which
2137 it almost certainly isn’t.)
2138
2139 · Sample#iterator returns only the recorded data, not a bunch of zeros.
2140
2141 · Moved units of Timer, Meter, and LoadMeter to their own attributes,
2142 which allows for easy export of Metrics data via JMX to things like
2143 Ganglia or whatever.
2144
2145 v1.0.2: Mar 08 2010
2146 · Timer now uses Welford’s algorithm for calculating running variance,
2147 which means no more hilariously wrong standard deviations (e.g.,
2148 NaN).
2149
2150 · Timer now supports +=(Long) for pre-recorded, nanosecond-precision
2151 timings.
2152
2153 v1.0.1: Mar 05 2010
2154 · changed Sample to use an AtomicReferenceArray
2155
2156 v1.0.0: Feb 27 2010
2157 · Initial release
2158
2160 Coda Hale
2161
2163 2010-2014, Coda Hale, Yammer Inc.
2164
2165
2166
2167
21683.1 Jul 14, 2018 METRICS(1)