001package nl.nlighten.prometheus.tomcat; 002 003import io.prometheus.client.Collector; 004import io.prometheus.client.GaugeMetricFamily; 005 006import javax.management.MBeanServer; 007import javax.management.ObjectInstance; 008import javax.management.ObjectName; 009import java.lang.management.ManagementFactory; 010import java.util.*; 011 012/** 013 * Exports Tomcat <a href="http://tomcat.apache.org/tomcat-8.5-doc/jdbc-pool.html">jdbc-pool</a> metrics. 014 * <p> 015 * Example usage: 016 * <pre> 017 * {@code 018 * new TomcatJdbcPoolExports().register(); 019 * } 020 * </pre> 021 * Example metrics being exported: 022 * <pre> 023 * tomcat_jdbc_connections_max{pool="jdbc/mypool"} 20.0 024 * tomcat_jdbc_connections_active_total{pool="jdbc/mypool"} 2.0 025 * tomcat_jdbc_connections_idle_total{pool="jdbc/mypool"} 6.0 026 * tomcat_jdbc_connections_total{pool="jdbc/mypool"} 8.0 027 * tomcat_jdbc_connections_threadswaiting_total{pool="jdbc/mypool"} 0.0 028 * </pre> 029 */ 030 031public class TomcatJdbcPoolExports extends Collector { 032 033 public List<MetricFamilySamples> collect() { 034 List<MetricFamilySamples> mfs = new ArrayList<MetricFamilySamples>(); 035 try { 036 final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); 037 ObjectName filterName = new ObjectName("tomcat.jdbc:class=org.apache.tomcat.jdbc.pool.DataSource,type=ConnectionPool,*"); 038 Set<ObjectInstance> mBeans = server.queryMBeans(filterName, null); 039 040 if (mBeans.size() > 0) { 041 List<String> labelList = Collections.singletonList("pool"); 042 043 GaugeMetricFamily maxActiveConnectionsGauge = new GaugeMetricFamily( 044 "tomcat_jdbc_connections_max", 045 "Maximum number of active connections that can be allocated from this pool at the same time", 046 labelList); 047 048 GaugeMetricFamily activeConnectionsGauge = new GaugeMetricFamily( 049 "tomcat_jdbc_connections_active_total", 050 "Number of active connections allocated from this pool", 051 labelList); 052 053 GaugeMetricFamily idleConnectionsGauge = new GaugeMetricFamily( 054 "tomcat_jdbc_connections_idle_total", 055 "Number of idle connections in this pool", 056 labelList); 057 058 GaugeMetricFamily totalConnectionsGauge = new GaugeMetricFamily( 059 "tomcat_jdbc_connections_total", 060 "Total number of connections in this pool", 061 labelList); 062 063 GaugeMetricFamily waitingThreadsCountGauge = new GaugeMetricFamily( 064 "tomcat_jdbc_waitingthreads_total", 065 "Number of threads waiting for connections from this pool", 066 labelList); 067 068 GaugeMetricFamily borrowedConnectionsGauge = new GaugeMetricFamily( 069 "tomcat_jdbc_connections_borrowed_total", 070 "Number of connections borrowed from this pool", 071 labelList); 072 073 GaugeMetricFamily returnedConnectionsGauge = new GaugeMetricFamily( 074 "tomcat_jdbc_connections_returned_total", 075 "Number of connections returned to this pool", 076 labelList); 077 078 GaugeMetricFamily createdConnectionsGauge = new GaugeMetricFamily( 079 "tomcat_jdbc_connections_created_total", 080 "Number of connections created by this pool", 081 labelList); 082 083 GaugeMetricFamily releasedConnectionsGauge = new GaugeMetricFamily( 084 "tomcat_jdbc_connections_released_total", 085 "Number of connections released by this pool", 086 labelList); 087 088 GaugeMetricFamily reconnectedConnectionsGauge = new GaugeMetricFamily( 089 "tomcat_jdbc_connections_reconnected_total", 090 "Number of reconnected connections by this pool", 091 labelList); 092 093 GaugeMetricFamily removeAbandonedConnectionsGauge = new GaugeMetricFamily( 094 "tomcat_jdbc_connections_removeabandoned_total", 095 "Number of abandoned connections that have been removed", 096 labelList); 097 098 GaugeMetricFamily releasedIdleConnectionsGauge = new GaugeMetricFamily( 099 "tomcat_jdbc_connections_releasedidle_total", 100 "Number of idle connections that have been released", 101 labelList); 102 103 for (final ObjectInstance mBean : mBeans) { 104 List<String> labelValueList = Collections.singletonList(mBean.getObjectName().getKeyProperty("name").replaceAll("[\"\\\\]", "")); 105 if (mBean.getObjectName().getKeyProperty("connections") == null) { // Tomcat 8.5.33 ignore PooledConnections 106 107 maxActiveConnectionsGauge.addMetric( 108 labelValueList, 109 ((Integer) server.getAttribute(mBean.getObjectName(), "MaxActive")).doubleValue()); 110 111 activeConnectionsGauge.addMetric( 112 labelValueList, 113 ((Integer) server.getAttribute(mBean.getObjectName(), "Active")).doubleValue()); 114 115 idleConnectionsGauge.addMetric( 116 labelValueList, 117 ((Integer) server.getAttribute(mBean.getObjectName(), "Idle")).doubleValue()); 118 119 totalConnectionsGauge.addMetric( 120 labelValueList, 121 ((Integer) server.getAttribute(mBean.getObjectName(), "Size")).doubleValue()); 122 123 waitingThreadsCountGauge.addMetric( 124 labelValueList, 125 ((Integer) server.getAttribute(mBean.getObjectName(), "WaitCount")).doubleValue()); 126 127 borrowedConnectionsGauge.addMetric( 128 labelValueList, 129 ((Long) server.getAttribute(mBean.getObjectName(), "BorrowedCount")).doubleValue()); 130 131 returnedConnectionsGauge.addMetric( 132 labelValueList, 133 ((Long) server.getAttribute(mBean.getObjectName(), "ReturnedCount")).doubleValue()); 134 135 createdConnectionsGauge.addMetric( 136 labelValueList, 137 ((Long) server.getAttribute(mBean.getObjectName(), "CreatedCount")).doubleValue()); 138 139 releasedConnectionsGauge.addMetric( 140 labelValueList, 141 ((Long) server.getAttribute(mBean.getObjectName(), "ReleasedCount")).doubleValue()); 142 143 reconnectedConnectionsGauge.addMetric( 144 labelValueList, 145 ((Long) server.getAttribute(mBean.getObjectName(), "ReconnectedCount")).doubleValue()); 146 147 removeAbandonedConnectionsGauge.addMetric( 148 labelValueList, 149 ((Long) server.getAttribute(mBean.getObjectName(), "RemoveAbandonedCount")).doubleValue()); 150 151 releasedIdleConnectionsGauge.addMetric( 152 labelValueList, 153 ((Long) server.getAttribute(mBean.getObjectName(), "ReleasedIdleCount")).doubleValue()); 154 155 } 156 } 157 mfs.add(maxActiveConnectionsGauge); 158 mfs.add(activeConnectionsGauge); 159 mfs.add(idleConnectionsGauge); 160 mfs.add(totalConnectionsGauge); 161 mfs.add(waitingThreadsCountGauge); 162 mfs.add(borrowedConnectionsGauge); 163 mfs.add(returnedConnectionsGauge); 164 mfs.add(createdConnectionsGauge); 165 mfs.add(releasedConnectionsGauge); 166 mfs.add(reconnectedConnectionsGauge); 167 mfs.add(removeAbandonedConnectionsGauge); 168 mfs.add(releasedIdleConnectionsGauge); 169 } 170 } catch (Exception e) { 171 e.printStackTrace(); 172 } 173 return mfs; 174 } 175 176 public static boolean isTomcatJdbcUsed() { 177 try { 178 final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); 179 ObjectName filterName = new ObjectName("tomcat.jdbc:class=org.apache.tomcat.jdbc.pool.DataSource,type=ConnectionPool,*"); 180 Set<ObjectInstance> mBeans = server.queryMBeans(filterName, null); 181 return !mBeans.isEmpty(); 182 } catch (Exception e) { 183 e.printStackTrace(); 184 } 185 return false; 186 } 187 188}