11# Prometheus JVM Client
22It supports Java, Clojure, Scala, JRuby, and anything else that runs on the JVM.
3-
3+
44[ ![ Build Status] ( https://travis-ci.org/prometheus/client_java.png?branch=master )] ( https://travis-ci.org/prometheus/client_java )
55
66Table of Contents
@@ -85,7 +85,7 @@ import io.prometheus.client.Counter;
8585class YourClass {
8686 static final Counter requests = Counter . build()
8787 .name(" requests_total" ). help(" Total requests." ). register();
88-
88+
8989 void processRequest () {
9090 requests. inc();
9191 // Your code here.
@@ -101,7 +101,7 @@ Gauges can go up and down.
101101class YourClass {
102102 static final Gauge inprogressRequests = Gauge . build()
103103 .name(" inprogress_requests" ). help(" Inprogress requests." ). register();
104-
104+
105105 void processRequest () {
106106 inprogressRequests. inc();
107107 // Your code here.
@@ -116,9 +116,9 @@ There are utilities for common use cases:
116116gauge. setToCurrentTime(); // Set to current unixtime.
117117```
118118
119- As an advanced use case, a ` Gauge ` can also take its value from a callback by using the
120- [ setChild()] ( https://prometheus.io/client_java/io/prometheus/client/SimpleCollector.html#setChild-Child-java.lang.String...- )
121- method. Keep in mind that the default ` inc() ` , ` dec() ` and ` set() ` methods on Gauge take care of thread safety, so
119+ As an advanced use case, a ` Gauge ` can also take its value from a callback by using the
120+ [ setChild()] ( https://prometheus.io/client_java/io/prometheus/client/SimpleCollector.html#setChild-Child-java.lang.String...- )
121+ method. Keep in mind that the default ` inc() ` , ` dec() ` and ` set() ` methods on Gauge take care of thread safety, so
122122when using this approach ensure the value you are reporting accounts for concurrency.
123123
124124
@@ -132,7 +132,7 @@ class YourClass {
132132 .name(" requests_size_bytes" ). help(" Request size in bytes." ). register();
133133 static final Summary requestLatency = Summary . build()
134134 .name(" requests_latency_seconds" ). help(" Request latency in seconds." ). register();
135-
135+
136136 void processRequest (Request req ) {
137137 Summary . Timer requestTimer = requestLatency. startTimer();
138138 try {
@@ -154,16 +154,16 @@ class YourClass {
154154 .quantile(0.5 , 0.05 ) // Add 50th percentile (= median) with 5% tolerated error
155155 .quantile(0.9 , 0.01 ) // Add 90th percentile with 1% tolerated error
156156 .name(" requests_latency_seconds" ). help(" Request latency in seconds." ). register();
157-
157+
158158 void processRequest (Request req ) {
159159 requestLatency. time(new Runnable () {
160160 public abstract void run () {
161- // Your code here.
161+ // Your code here.
162162 }
163- });
164-
165-
166- // Or the Java 8 lambda equivalent
163+ });
164+
165+
166+ // Or the Java 8 lambda equivalent
167167 requestLatency. time(() - > {
168168 // Your code here.
169169 });
@@ -201,18 +201,18 @@ There are utilities for timing code:
201201class YourClass {
202202 static final Histogram requestLatency = Histogram . build()
203203 .name(" requests_latency_seconds" ). help(" Request latency in seconds." ). register();
204-
204+
205205 void processRequest (Request req ) {
206206 requestLatency. time(new Runnable () {
207207 public abstract void run () {
208- // Your code here.
208+ // Your code here.
209209 }
210- });
211-
212-
213- // Or the Java 8 lambda equivalent
210+ });
211+
212+
213+ // Or the Java 8 lambda equivalent
214214 requestLatency. time(() - > {
215- // Your code here.
215+ // Your code here.
216216 });
217217 }
218218}
@@ -232,7 +232,7 @@ class YourClass {
232232 static final Counter requests = Counter . build()
233233 .name(" my_library_requests_total" ). help(" Total requests." )
234234 .labelNames(" method" ). register();
235-
235+
236236 void processGetRequest () {
237237 requests. labels(" get" ). inc();
238238 // Your code here.
@@ -248,10 +248,10 @@ The best way to register a metric is via a `static final` class variable as is c
248248static final Counter requests = Counter . build()
249249 .name(" my_library_requests_total" ). help(" Total requests." ). labelNames(" path" ). register();
250250```
251-
252- Using the default registry with variables that are ` static ` is ideal since registering a metric with the same name
253- is not allowed and the default registry is also itself static. You can think of registering a metric, more like
254- registering a definition (as in the ` TYPE ` and ` HELP ` sections). The metric 'definition' internally holds the samples
251+
252+ Using the default registry with variables that are ` static ` is ideal since registering a metric with the same name
253+ is not allowed and the default registry is also itself static. You can think of registering a metric, more like
254+ registering a definition (as in the ` TYPE ` and ` HELP ` sections). The metric 'definition' internally holds the samples
255255that are reported and pulled out by Prometheus. Here is an example of registering a metric that has no labels.
256256
257257``` java
@@ -260,19 +260,19 @@ class YourClass {
260260 .name(" my_library_transactions_active" )
261261 .help(" Active transactions." )
262262 .register();
263-
263+
264264 void processThatCalculates (String key ) {
265265 activeTransactions. inc();
266266 try {
267- // Perform work.
267+ // Perform work.
268268 } finally {
269269 activeTransactions. dec();
270270 }
271271 }
272272}
273273```
274274
275- To create timeseries with labels, include ` labelNames() ` with the builder. The ` labels() ` method looks up or creates
275+ To create timeseries with labels, include ` labelNames() ` with the builder. The ` labels() ` method looks up or creates
276276the corresponding labelled timeseries. You might also consider storing the labelled timeseries as an instance variable if it is
277277appropriate. It is thread safe and can be used multiple times, which can help performance.
278278
@@ -282,7 +282,7 @@ class YourClass {
282282 static final Counter calculationsCounter = Counter . build()
283283 .name(" my_library_calculations_total" ). help(" Total calls." )
284284 .labelNames(" key" ). register();
285-
285+
286286 void processThatCalculates (String key ) {
287287 calculationsCounter. labels(key). inc();
288288 // Run calculations.
@@ -294,7 +294,7 @@ class YourClass {
294294## Included Collectors
295295
296296The Java client includes collectors for garbage collection, memory pools, JMX, classloading, and thread counts.
297- These can be added individually or just use the ` DefaultExports ` to conveniently register them.
297+ These can be added individually or just use the ` DefaultExports ` to conveniently register them.
298298
299299``` java
300300DefaultExports . initialize();
@@ -353,7 +353,7 @@ To register the log4j2 collector at root level:
353353### Caches
354354
355355To register the Guava cache collector, be certain to add ` recordStats() ` when building
356- the cache and adding it to the registered collector.
356+ the cache and adding it to the registered collector.
357357
358358``` java
359359CacheMetricsCollector cacheMetrics = new CacheMetricsCollector (). register();
@@ -374,8 +374,8 @@ cacheMetrics.addCache("myCacheLabel", cache);
374374
375375### Hibernate
376376
377- There is a collector for Hibernate which allows to collect metrics from one or more
378- ` SessionFactory ` instances.
377+ There is a collector for Hibernate which allows to collect metrics from one or more
378+ ` SessionFactory ` instances.
379379
380380If you want to collect metrics from a single ` SessionFactory ` , you can register
381381the collector like this:
@@ -415,7 +415,7 @@ new JettyStatisticsCollector(stats).register();
415415```
416416
417417Also, you can collect ` QueuedThreadPool ` metrics. If there is a single ` QueuedThreadPool `
418- to keep track of, use the following:
418+ to keep track of, use the following:
419419
420420``` java
421421new QueuedThreadPoolStatisticsCollector (queuedThreadPool, " myapp" ). register();
@@ -522,7 +522,7 @@ The simplest of these is the HTTPServer:
522522HTTPServer server = new HTTPServer (1234 );
523523```
524524
525- To add Prometheus exposition to an existing HTTP server using servlets, see the ` MetricsServlet ` .
525+ To add Prometheus exposition to an existing HTTP server using servlets, see the ` MetricsServlet ` .
526526It also serves as a simple example of how to write a custom endpoint.
527527
528528To expose the metrics used in your code, you would add the Prometheus servlet to your Jetty server:
@@ -554,7 +554,7 @@ void executeBatchJob() throws Exception {
554554 Gauge . Timer durationTimer = duration. startTimer();
555555 try {
556556 // Your code here.
557-
557+
558558 // This is only added to the registry after success,
559559 // so that a previous success in the Pushgateway isn't overwritten on failure.
560560 Gauge lastSuccess = Gauge . build()
@@ -568,8 +568,8 @@ void executeBatchJob() throws Exception {
568568}
569569 ```
570570
571- A separate registry is used, as the default registry may contain other metrics
572- such as those from the Process Collector. See the
571+ A separate registry is used, as the default registry may contain other metrics
572+ such as those from the Process Collector. See the
573573[ Pushgateway documentation] ( https://github.com/prometheus/pushgateway/blob/master/README.md )
574574for more information.
575575
@@ -593,7 +593,7 @@ class MyHttpConnectionFactory implements HttpConnectionFactory {
593593 HttpURLConnection connection = (HttpURLConnection ) new URL (url). openConnection();
594594 // add any connection preparation logic you need
595595 return connection;
596- }
596+ }
597597}
598598```
599599
@@ -659,6 +659,56 @@ registration time instead of `describe`. If this could cause problems, either
659659implement a proper ` describe ` , or if that's not practical have ` describe `
660660return an empty list.
661661
662+ ### DropwizardExports Collector
663+
664+ DropwizardExports collector is available to proxy metrics from Dropwizard.
665+
666+ ``` java
667+ // Dropwizard MetricRegistry
668+ MetricRegistry metricRegistry = new MetricRegistry ();
669+ new DropwizardExports (metricRegistry). register();
670+ ```
671+
672+ By default Dropwizard metrics are translated to Prometheus sample sanitizing their names, i.e. replacing unsupported chars with ` _ ` , for example:
673+ ```
674+ Dropwizard metric name:
675+ org.company.controller.save.status.400
676+ Prometheus metric:
677+ org_company_controller_save_status_400
678+ ```
679+
680+ It is also possible add custom labels and name to newly created ` Sample ` s by using a ` CustomMappingSampleBuilder ` with custom ` MapperConfig ` s:
681+
682+ ``` java
683+ // Dropwizard MetricRegistry
684+ MetricRegistry metricRegistry = new MetricRegistry ();
685+ MapperConfig config = new MapperConfig ();
686+ // The match field in MapperConfig is a simplified glob expression that only allows * wildcard.
687+ config. setMatch(" org.company.controller.*.status.*" );
688+ // The new Sample's template name.
689+ config. setName(" org.company.controller" );
690+ Map<String , String > labels = new HashMap<String ,String > ();
691+ // ... more configs
692+ // Labels to be extracted from the metric. Key=label name. Value=label template
693+ labels. put(" name" , " ${0}" );
694+ labels. put(" status" , " ${1}" );
695+ config. setLabels(labels);
696+
697+ SampleBuilder sampleBuilder = new CustomMappingSampleBuilder (Arrays . asList(config));
698+ new DropwizardExports (metricRegistry, sampleBuilder). register();
699+ ```
700+
701+ When a new metric comes to the collector, ` MapperConfig ` s are scanned to find the first one that matches the incoming metric name. The name set in the configuration will
702+ be used and labels will be extracted. Using the ` CustomMappingSampleBuilder ` in the previous example leads to the following result:
703+ ```
704+ Dropwizard metric name
705+ org.company.controller.save.status.400
706+ Prometheus metric
707+ org_company_controller{name="save",status="400"}
708+ ```
709+
710+ Template with placeholders can be used both as names and label values. Placeholders are in the ` ${n} ` format where n is the zero based index of the Dropwizard metric name wildcard group we want to extract.
711+
662712## Contact
663713The [ Prometheus Users Mailinglist] ( https://groups.google.com/forum/?fromgroups#!forum/prometheus-users ) is the best place to ask questions.
664714
0 commit comments