001package io.prometheus.client.jetty;
002
003import io.prometheus.client.Collector;
004import java.util.ArrayList;
005import java.util.Arrays;
006import java.util.Collections;
007import java.util.List;
008import org.eclipse.jetty.server.handler.StatisticsHandler;
009
010/**
011 * Collect metrics from jetty's org.eclipse.jetty.server.handler.StatisticsHandler.
012 * <p>
013 * <pre>{@code
014 * Server server = new Server(8080);
015 *
016 * ServletContextHandler context = new ServletContextHandler();
017 * context.setContextPath("/");
018 * server.setHandler(context);
019 *
020 * HandlerCollection handlers = new HandlerCollection();
021 *
022 * StatisticsHandler statisticsHandler = new StatisticsHandler();
023 * statisticsHandler.setServer(server);
024 * handlers.addHandler(statisticsHandler);
025 *
026 * // Register collector.
027 * new JettyStatisticsCollector(statisticsHandler).register();
028 *
029 * server.setHandler(handlers);
030 *
031 * server.start();
032 * }</pre>
033 */
034public class JettyStatisticsCollector extends Collector {
035  private final StatisticsHandler statisticsHandler;
036  private static final List<String> EMPTY_LIST = new ArrayList<String>();
037
038  public JettyStatisticsCollector(StatisticsHandler statisticsHandler) {
039    this.statisticsHandler = statisticsHandler;
040  }
041
042  @Override
043  public List<MetricFamilySamples> collect() {
044    return Arrays.asList(
045            buildCounter("jetty_requests_total", "Number of requests", statisticsHandler.getRequests()),
046            buildGauge("jetty_requests_active", "Number of requests currently active", statisticsHandler.getRequestsActive()),
047            buildGauge("jetty_requests_active_max", "Maximum number of requests that have been active at once", statisticsHandler.getRequestsActiveMax()),
048            buildGauge("jetty_request_time_max_seconds", "Maximum time spent handling requests", statisticsHandler.getRequestTimeMax() / 1000.0),
049            buildCounter("jetty_request_time_seconds_total", "Total time spent in all request handling", statisticsHandler.getRequestTimeTotal() / 1000.0),
050            buildCounter("jetty_dispatched_total", "Number of dispatches", statisticsHandler.getDispatched()),
051            buildGauge("jetty_dispatched_active", "Number of dispatches currently active", statisticsHandler.getDispatchedActive()),
052            buildGauge("jetty_dispatched_active_max", "Maximum number of active dispatches being handled", statisticsHandler.getDispatchedActiveMax()),
053            buildGauge("jetty_dispatched_time_max", "Maximum time spent in dispatch handling", statisticsHandler.getDispatchedTimeMax()),
054            buildCounter("jetty_dispatched_time_seconds_total", "Total time spent in dispatch handling", statisticsHandler.getDispatchedTimeTotal() / 1000.0),
055            buildCounter("jetty_async_requests_total", "Total number of async requests", statisticsHandler.getAsyncRequests()),
056            buildGauge("jetty_async_requests_waiting", "Currently waiting async requests", statisticsHandler.getAsyncRequestsWaiting()),
057            buildGauge("jetty_async_requests_waiting_max", "Maximum number of waiting async requests", statisticsHandler.getAsyncRequestsWaitingMax()),
058            buildCounter("jetty_async_dispatches_total", "Number of requested that have been asynchronously dispatched", statisticsHandler.getAsyncDispatches()),
059            buildCounter("jetty_expires_total", "Number of async requests requests that have expired", statisticsHandler.getExpires()),
060            buildStatusCounter(),
061            buildGauge("jetty_stats_seconds", "Time in seconds stats have been collected for", statisticsHandler.getStatsOnMs() / 1000.0),
062            buildCounter("jetty_responses_bytes_total", "Total number of bytes across all responses", statisticsHandler.getResponsesBytesTotal())
063    );
064  }
065
066  private static MetricFamilySamples buildGauge(String name, String help, double value) {
067    return new MetricFamilySamples(
068            name,
069            Type.GAUGE,
070            help,
071            Collections.singletonList(new MetricFamilySamples.Sample(name, EMPTY_LIST, EMPTY_LIST, value)));
072  }
073
074  private static MetricFamilySamples buildCounter(String name, String help, double value) {
075    return new MetricFamilySamples(
076        name,
077        Type.COUNTER,
078        help,
079        Collections.singletonList(new MetricFamilySamples.Sample(name, EMPTY_LIST, EMPTY_LIST, value)));
080  }
081
082  private MetricFamilySamples buildStatusCounter() {
083    String name = "jetty_responses_total";
084    return new MetricFamilySamples(
085            name,
086            Type.COUNTER,
087            "Number of requests with response status",
088            Arrays.asList(
089                    buildStatusSample(name, "1xx", statisticsHandler.getResponses1xx()),
090                    buildStatusSample(name, "2xx", statisticsHandler.getResponses2xx()),
091                    buildStatusSample(name, "3xx", statisticsHandler.getResponses3xx()),
092                    buildStatusSample(name, "4xx", statisticsHandler.getResponses4xx()),
093                    buildStatusSample(name, "5xx", statisticsHandler.getResponses5xx())
094            )
095    );
096  }
097
098  private static MetricFamilySamples.Sample buildStatusSample(String name, String status, double value) {
099    return new MetricFamilySamples.Sample(
100            name,
101            Collections.singletonList("code"),
102            Collections.singletonList(status),
103            value);
104  }
105}