001package nl.nlighten.prometheus.wildfly;
002
003import io.prometheus.client.Collector;
004import io.prometheus.client.CounterMetricFamily;
005import io.prometheus.client.GaugeMetricFamily;
006
007import javax.management.MBeanServer;
008import javax.management.ObjectInstance;
009import javax.management.ObjectName;
010import java.lang.management.ManagementFactory;
011import java.util.ArrayList;
012import java.util.Collections;
013import java.util.List;
014import java.util.Set;
015
016/**
017 * Exports metrics about Jboss Wildfly JDBC datasources.
018 * <p>
019 * Example usage:
020 * <pre>
021 * {@code
022 *   new JbossJdbcPoolExports().register();
023 * }
024 * </pre>
025 * Example metrics being exported:
026 * <pre>
027 *   jboss_jdbc_connections_total{pool="ExampleDS",} 10.0
028 *   jboss_jdbc_connections_threadswaiting_total{pool="ExampleDS",} 0.0
029 *   jboss_jdbc_connections_idle_total{pool="ExampleDS",} 8.0
030 *   jboss_jdbc_connections_active_total{pool="ExampleDS",} 2.0
031 *   jboss_jdbc_xacommit_total{pool="ExampleDS",} 9837.0
032 *   jboss_jdbc_xarollback_total{pool="ExampleDS",} 7.0
033 *   jboss_jdbc_xarecover_total{pool="ExampleDS",} 0.0
034 *   jboss_jdbc_preparedstatementcache_size_total{pool="ExampleDS",} 100.0
035 *   jboss_jdbc_preparedstatementcache_miss_total{pool="ExampleDS",} 0.0
036 *   jboss_jdbc_preparedstatementcache_hit_total{pool="ExampleDS",} 94837.0
037 * </pre>
038 * <p>
039 * Note that you need to enable datasource statistics to see anything
040 */
041public class JbossJdbcPoolExports extends Collector {
042
043    public List<MetricFamilySamples> collect() {
044        List<MetricFamilySamples> mfs = new ArrayList<>();
045        try {
046            MBeanServer server = ManagementFactory.getPlatformMBeanServer();
047
048            // data source stats
049            ObjectName filterName = new ObjectName("jboss.as:subsystem=datasources,data-source=*,statistics=pool");
050            Set<ObjectInstance> mBeans = server.queryMBeans(filterName, null);
051            if (mBeans.size() > 0) {
052                List<String> labelList = Collections.singletonList("pool");
053
054                GaugeMetricFamily activeCountGauge = new GaugeMetricFamily(
055                        "jboss_jdbc_connections_total",
056                        "Total number of connections in this pool",
057                        labelList);
058
059                GaugeMetricFamily waitCountGauge = new GaugeMetricFamily(
060                        "jboss_jdbc_connections_threadswaiting_total",
061                        "Number of threads waiting for connections from this pool",
062                        labelList);
063
064                GaugeMetricFamily idleCountGauge = new GaugeMetricFamily(
065                        "jboss_jdbc_connections_idle_total",
066                        "Number of idle connections in this pool",
067                        labelList);
068
069                GaugeMetricFamily inUseCountGauge = new GaugeMetricFamily(
070                        "jboss_jdbc_connections_active_total",
071                        "Number of connections in use",
072                        labelList);
073
074                CounterMetricFamily xaCommitCounter = new CounterMetricFamily(
075                        "jboss_jdbc_xacommit_total",
076                        "Number of xa commits",
077                        labelList);
078
079                CounterMetricFamily xaRollbackCounter = new CounterMetricFamily(
080                        "jboss_jdbc_xarollback_total",
081                        "Number of xa recoveries",
082                        labelList);
083
084                CounterMetricFamily xaRecoverCounter = new CounterMetricFamily(
085                        "jboss_jdbc_xarecover_total",
086                        "Number of xa recoveries",
087                        labelList);
088
089                for (final ObjectInstance mBean : mBeans) {
090
091                    activeCountGauge.addMetric(
092                            Collections.singletonList(mBean.getObjectName().getKeyProperty("data-source")),
093                            ((Integer) server.getAttribute(mBean.getObjectName(), "ActiveCount")).doubleValue());
094
095                    waitCountGauge.addMetric(
096                            Collections.singletonList(mBean.getObjectName().getKeyProperty("data-source")),
097                            ((Integer) server.getAttribute(mBean.getObjectName(), "WaitCount")).doubleValue());
098
099                    idleCountGauge.addMetric(
100                            Collections.singletonList(mBean.getObjectName().getKeyProperty("data-source")),
101                            ((Integer) server.getAttribute(mBean.getObjectName(), "IdleCount")).doubleValue());
102
103                    inUseCountGauge.addMetric(
104                            Collections.singletonList(mBean.getObjectName().getKeyProperty("data-source")),
105                            ((Integer) server.getAttribute(mBean.getObjectName(), "InUseCount")).doubleValue());
106
107                    xaCommitCounter.addMetric(
108                            Collections.singletonList(mBean.getObjectName().getKeyProperty("data-source")),
109                            ((Long) server.getAttribute(mBean.getObjectName(), "XACommitCount")).doubleValue());
110
111                    xaRollbackCounter.addMetric(
112                            Collections.singletonList(mBean.getObjectName().getKeyProperty("data-source")),
113                            ((Long) server.getAttribute(mBean.getObjectName(), "XARollbackCount")).doubleValue());
114
115                    xaRecoverCounter.addMetric(
116                            Collections.singletonList(mBean.getObjectName().getKeyProperty("data-source")),
117                            ((Long) server.getAttribute(mBean.getObjectName(), "XARecoverCount")).doubleValue());
118                }
119                mfs.add(activeCountGauge);
120                mfs.add(waitCountGauge);
121                mfs.add(inUseCountGauge);
122                mfs.add(xaCommitCounter);
123                mfs.add(xaRollbackCounter);
124                mfs.add(xaRecoverCounter);
125            }
126
127            // jdbc stats
128            filterName = new ObjectName("jboss.as:subsystem=datasources,data-source=*,statistics=jdbc");
129            mBeans = server.queryMBeans(filterName, null);
130            if (mBeans.size() > 0) {
131                List<String> labelList = Collections.singletonList("pool");
132
133                GaugeMetricFamily preparedStatementCacheCurrentSizeGauge = new GaugeMetricFamily(
134                        "jboss_jdbc_preparedstatementcache_size_total",
135                        "Prepared statement cache size",
136                        labelList);
137
138                CounterMetricFamily preparedStatementCacheMissCounter = new CounterMetricFamily(
139                        "jboss_jdbc_preparedstatementcache_miss_total",
140                        "Prepared statement cache miss count",
141                        labelList);
142
143                CounterMetricFamily preparedStatementCacheHitCounter = new CounterMetricFamily(
144                        "jboss_jdbc_preparedstatementcache_hit_total",
145                        "Prepared statement cache hit count",
146                        labelList);
147
148                for (final ObjectInstance mBean : mBeans) {
149                    preparedStatementCacheCurrentSizeGauge.addMetric(
150                            Collections.singletonList(mBean.getObjectName().getKeyProperty("data-source")),
151                            ((Integer) server.getAttribute(mBean.getObjectName(), "PreparedStatementCacheCurrentSize")).doubleValue());
152
153                    preparedStatementCacheMissCounter.addMetric(
154                            Collections.singletonList(mBean.getObjectName().getKeyProperty("data-source")),
155                            ((Long) server.getAttribute(mBean.getObjectName(), "PreparedStatementCacheMissCount")).doubleValue());
156
157                    preparedStatementCacheHitCounter.addMetric(
158                            Collections.singletonList(mBean.getObjectName().getKeyProperty("data-source")),
159                            ((Long) server.getAttribute(mBean.getObjectName(), "PreparedStatementCacheHitCount")).doubleValue());
160
161                }
162                mfs.add(preparedStatementCacheCurrentSizeGauge);
163                mfs.add(preparedStatementCacheMissCounter);
164                mfs.add(preparedStatementCacheHitCounter);
165            }
166
167        } catch (Exception e) {
168            e.printStackTrace();
169        }
170        return mfs;
171    }
172}
173