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