001package nl.nlighten.prometheus.wildfly;
002
003import io.prometheus.client.Collector;
004import io.prometheus.client.GaugeMetricFamily;
005
006import javax.management.AttributeNotFoundException;
007import javax.management.MBeanServer;
008import javax.management.ObjectInstance;
009import javax.management.ObjectName;
010import java.lang.management.ManagementFactory;
011import java.util.*;
012
013/**
014 * Exports undertow session and http-listener related metrics.
015 * <p>
016 * Example usage:
017 * <pre>
018 * {@code
019 *   new UndertowExports().register();
020 * }
021 * </pre>
022 * Example metrics being exported:
023 * <pre>
024 *   undertow_listener_request_total{server="default-server",listener="default",} 11000.0
025 *   undertow_listener_error_total{server="default-server",listener="default",} 3.0
026 *   undertow_listener_processingtime_nanos{server="default-server",listener="default",} 0.0
027 *   undertow_listener_sent_bytes{server="default-server",listener="default",} 5056098.0
028 *   undertow_listener_received_bytes{server="default-server",listener="default",} 406234.0
029 *   undertow_session_active_total{deployment="foo",context="/bar",} 53.0
030 *   undertow_session_rejected_total{deployment="foo",context="/bar",} 0.0
031 *   undertow_session_created_total{deployment="foo",context="/bar",} 343.0
032 *   undertow_session_expired_total{deployment="foo",context="/bar",} 290.0
033 *   undertow_session_alivetime_avg_seconds{deployment="foo",context="/bar",} 2304482.0
034 *   undertow_session_alivetime_max_seconds{deployment="foo",context="/bar",} 8983372.0
035 *
036 *
037 * </pre>
038 * Note that you need to enable undertow statistics to see anything
039 */
040public class UndertowExports extends Collector {
041
042    public List<MetricFamilySamples> collect() {
043        List<MetricFamilySamples> mfs = new ArrayList<>();
044        try {
045            final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
046            ObjectName filterName = new ObjectName("jboss.as:subsystem=undertow,server=*,http-listener=*");
047            Set<ObjectInstance> mBeans = server.queryMBeans(filterName, null);
048
049            if (mBeans.size() > 0) {
050
051                GaugeMetricFamily errorCountGauge = new GaugeMetricFamily(
052                        "undertow_listener_error_total",
053                        "Number of errors for this http-listener",
054                        Arrays.asList("server", "listener"));
055
056                GaugeMetricFamily processingTimeGauge = new GaugeMetricFamily(
057                        "undertow_listener_processingtime_nanos",
058                        "Total processing time for this http-listener",
059                        Arrays.asList("server", "listener"));
060
061                GaugeMetricFamily requestCountGauge = new GaugeMetricFamily(
062                        "undertow_listener_request_total",
063                        "Total request count for this http-listener",
064                        Arrays.asList("server", "listener"));
065
066                GaugeMetricFamily bytesSentGauge = new GaugeMetricFamily(
067                        "undertow_listener_sent_bytes",
068                        "Number of bytes sent by this http-listener",
069                        Arrays.asList("server", "listener"));
070
071                GaugeMetricFamily bytesReceivedGauge = new GaugeMetricFamily(
072                        "undertow_listener_received_bytes",
073                        "Number of bytes received by this http-listener",
074                        Arrays.asList("server", "listener"));
075
076                for (final ObjectInstance mBean : mBeans) {
077
078                    errorCountGauge.addMetric(
079                            Arrays.asList(mBean.getObjectName().getKeyProperty("server"), mBean.getObjectName().getKeyProperty("http-listener")),
080                            ((Long) server.getAttribute(mBean.getObjectName(), "errorCount")).doubleValue());
081
082                    processingTimeGauge.addMetric(
083                            Arrays.asList(mBean.getObjectName().getKeyProperty("server"), mBean.getObjectName().getKeyProperty("http-listener")),
084                            ((Long) server.getAttribute(mBean.getObjectName(), "processingTime")).doubleValue());
085
086                    requestCountGauge.addMetric(
087                            Arrays.asList(mBean.getObjectName().getKeyProperty("server"), mBean.getObjectName().getKeyProperty("http-listener")),
088                            ((Long) server.getAttribute(mBean.getObjectName(), "requestCount")).doubleValue());
089
090                    bytesSentGauge.addMetric(
091                            Arrays.asList(mBean.getObjectName().getKeyProperty("server"), mBean.getObjectName().getKeyProperty("http-listener")),
092                            ((Long) server.getAttribute(mBean.getObjectName(), "bytesSent")).doubleValue());
093
094                    bytesReceivedGauge.addMetric(
095                            Arrays.asList(mBean.getObjectName().getKeyProperty("server"), mBean.getObjectName().getKeyProperty("http-listener")),
096                            ((Long) server.getAttribute(mBean.getObjectName(), "bytesReceived")).doubleValue());
097                }
098                mfs.add(errorCountGauge);
099                mfs.add(processingTimeGauge);
100                mfs.add(requestCountGauge);
101
102                filterName = new ObjectName("jboss.as.expr:deployment=*,subsystem=undertow");
103                mBeans = server.queryMBeans(filterName, null);
104
105                if (mBeans.size() > 0) {
106                    GaugeMetricFamily activeSessionCountGauge = new GaugeMetricFamily(
107                            "undertow_session_active_total",
108                            "Number of active sessions",
109                            Arrays.asList("deployment", "context"));
110
111                    GaugeMetricFamily rejectedSessionCountGauge = new GaugeMetricFamily(
112                            "undertow_session_rejected_total",
113                            "Number of rejected sessions",
114                            Arrays.asList("deployment", "context"));
115
116                    GaugeMetricFamily createdSessionCountGauge = new GaugeMetricFamily(
117                            "undertow_session_created_total",
118                            "Number of sessions created",
119                            Arrays.asList("deployment", "context"));
120
121                    GaugeMetricFamily expiredSessionCountGauge = new GaugeMetricFamily(
122                            "undertow_session_expired_total",
123                            "Number of sessions expired",
124                            Arrays.asList("deployment", "context"));
125
126                    GaugeMetricFamily sessionAvgAliveTimeGauge = new GaugeMetricFamily(
127                            "undertow_session_alivetime_avg_seconds",
128                            "Average session alive time",
129                            Arrays.asList("deployment", "context"));
130
131                    GaugeMetricFamily sessionMaxAliveTimeGauge = new GaugeMetricFamily(
132                            "undertow_session_alivetime_max_seconds",
133                            "Average session alive time",
134                            Arrays.asList("deployment", "context"));
135
136                    for (final ObjectInstance mBean : mBeans) {
137                        String deployment = mBean.getObjectName().getKeyProperty("deployment");
138                        String context = (String) server.getAttribute(mBean.getObjectName(), "contextRoot");
139
140                        activeSessionCountGauge.addMetric(
141                                Arrays.asList(deployment, context),
142                                Double.parseDouble((String) server.getAttribute(mBean.getObjectName(), "activeSessions")));
143
144                        rejectedSessionCountGauge.addMetric(
145                                Arrays.asList(deployment, context),
146                                Double.parseDouble((String) server.getAttribute(mBean.getObjectName(), "rejectedSessions")));
147
148                        createdSessionCountGauge.addMetric(
149                                Arrays.asList(deployment, context),
150                                Double.parseDouble((String) server.getAttribute(mBean.getObjectName(), "sessionsCreated")));
151
152                        expiredSessionCountGauge.addMetric(
153                                Arrays.asList(deployment, context),
154                                Double.parseDouble((String) server.getAttribute(mBean.getObjectName(), "expiredSessions")));
155
156                        sessionAvgAliveTimeGauge.addMetric(
157                                Arrays.asList(deployment, context),
158                                Double.parseDouble((String) server.getAttribute(mBean.getObjectName(), "sessionAvgAliveTime")));
159
160                        sessionMaxAliveTimeGauge.addMetric(
161                                Arrays.asList(deployment, context),
162                                Double.parseDouble((String) server.getAttribute(mBean.getObjectName(), "sessionMaxAliveTime")));
163                    }
164                    mfs.add(activeSessionCountGauge);
165                    mfs.add(rejectedSessionCountGauge);
166                    mfs.add(createdSessionCountGauge);
167                    mfs.add(expiredSessionCountGauge);
168                    mfs.add(sessionAvgAliveTimeGauge);
169                    mfs.add(sessionMaxAliveTimeGauge);
170
171                }
172
173            }
174        } catch (AttributeNotFoundException e) {
175            // ignore, can happen during server startup.
176        } catch (Exception e) {
177            e.printStackTrace();
178        }
179        return mfs;
180    }
181}
182