001package nl.nlighten.prometheus.tomcat; 002 003import io.prometheus.client.Collector; 004import io.prometheus.client.GaugeMetricFamily; 005import javax.management.*; 006import java.lang.management.ManagementFactory; 007import java.util.ArrayList; 008import java.util.Collections; 009import java.util.List; 010import java.util.Set; 011 012/** 013 * Exports Tomcat <a href="https://tomcat.apache.org/tomcat-8.5-doc/jndi-datasource-examples-howto.html#Database_Connection_Pool_(DBCP_2)_Configurations">DBCP2-pool</a> metrics. 014 * <p> 015 * Example usage: 016 * <pre> 017 * {@code 018 * new TomcatDbcp2PoolExports().register(); 019 * } 020 * </pre> 021 * Example metrics being exported: 022 * <pre> 023 * tomcat_dpcp2_connections_max{pool="jdbc/mypool"} 20.0 024 * tomcat_dbcp2_connections_active_total{pool="jdbc/mypool"} 2.0 025 * tomcat_dbcp2_connections_idle_total{pool="jdbc/mypool"} 6.0 026 * </pre> 027 */ 028 029public class TomcatDbcp2PoolExports extends Collector { 030 031 public List<MetricFamilySamples> collect() { 032 List<MetricFamilySamples> mfs = new ArrayList<MetricFamilySamples>(); 033 try { 034 final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); 035 ObjectName filterName = new ObjectName("Tomcat:class=javax.sql.DataSource,type=DataSource,*"); 036 Set<ObjectInstance> mBeans = server.queryMBeans(filterName, null); 037 038 if (mBeans.size() > 0) { 039 List<String> labelList = Collections.singletonList("pool"); 040 041 GaugeMetricFamily maxActiveConnectionsGauge = new GaugeMetricFamily( 042 "tomcat_dbcp2_connections_max", 043 "Maximum number of active connections that can be allocated from this pool at the same time", 044 labelList); 045 046 GaugeMetricFamily activeConnectionsGauge = new GaugeMetricFamily( 047 "tomcat_dbcp2_connections_active_total", 048 "Number of active connections allocated from this pool", 049 labelList); 050 051 GaugeMetricFamily idleConnectionsGauge = new GaugeMetricFamily( 052 "tomcat_dbcp2_connections_idle_total", 053 "Number of idle connections in this pool", 054 labelList); 055 056 057 for (final ObjectInstance mBean : mBeans) { 058 if (mBean.getObjectName().getKeyProperty("connectionpool") == null){ 059 List<String> labelValueList = Collections.singletonList(mBean.getObjectName().getKeyProperty("name").replaceAll("[\"\\\\]", "")); 060 061 maxActiveConnectionsGauge.addMetric( 062 labelValueList, 063 ((Integer) server.getAttribute(mBean.getObjectName(), "maxTotal")).doubleValue()); 064 065 activeConnectionsGauge.addMetric( 066 labelValueList, 067 ((Integer) server.getAttribute(mBean.getObjectName(), "numActive")).doubleValue()); 068 069 idleConnectionsGauge.addMetric( 070 labelValueList, 071 ((Integer) server.getAttribute(mBean.getObjectName(), "numIdle")).doubleValue()); 072 073 } 074 075 mfs.add(maxActiveConnectionsGauge); 076 mfs.add(activeConnectionsGauge); 077 mfs.add(idleConnectionsGauge); 078 } 079 } 080 } catch (javax.management.AttributeNotFoundException e) { 081 // Can happen in exception cases where TomcatDbcp2PoolExports is configured with a TomcatJdcpPool configured 082 } 083 catch (Exception e) { 084 System.out.println ("####### " + e.getLocalizedMessage()); 085 e.printStackTrace(); 086 } 087 return mfs; 088 } 089 090 public static boolean isDbcp2Used() { 091 try { 092 final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); 093 ObjectName filterName = new ObjectName("tomcat.jdbc:class=org.apache.tomcat.jdbc.pool.DataSource,type=ConnectionPool,*"); 094 Set<ObjectInstance> mBeans = server.queryMBeans(filterName, null); 095 return !mBeans.isEmpty(); 096 } catch (Exception e) { 097 e.printStackTrace(); 098 } 099 return false; 100 } 101 102}