Skip to content

Commit

Permalink
Add a javax.servlet-api exporter (#918)
Browse files Browse the repository at this point in the history
* Add prometheus-metrics-exporter-servlet-javax

Signed-off-by: Kinshuk Bairagi <[email protected]>

* Add comments for ci to pass

Signed-off-by: Kinshuk Bairagi <[email protected]>

---------

Signed-off-by: Kinshuk Bairagi <[email protected]>
  • Loading branch information
kingster authored Feb 9, 2024
1 parent 051ff61 commit c1442e8
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 0 deletions.
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
<module>prometheus-metrics-exposition-formats</module>
<module>prometheus-metrics-exporter-common</module>
<module>prometheus-metrics-exporter-servlet-jakarta</module>
<module>prometheus-metrics-exporter-servlet-javax</module>
<module>prometheus-metrics-exporter-httpserver</module>
<module>prometheus-metrics-exporter-opentelemetry</module>
<module>prometheus-metrics-instrumentation-jvm</module>
Expand Down
53 changes: 53 additions & 0 deletions prometheus-metrics-exporter-servlet-javax/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>io.prometheus</groupId>
<artifactId>client_java</artifactId>
<version>1.2.0-SNAPSHOT</version>
</parent>

<artifactId>prometheus-metrics-exporter-servlet-javax</artifactId>
<packaging>bundle</packaging>

<name>Prometheus Metrics Exporter - Servlet JavaX</name>
<description>
JavaX Servlet for exposing a Prometheus scrape endpoint.
</description>

<properties>
<automatic.module.name>io.prometheus.metrics.exporter.servlet.javax</automatic.module.name>
</properties>

<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>

<developers>
<developer>
<id>kingster</id>
<name>Kinshuk Bairagi</name>
<email>[email protected]</email>
</developer>
</developers>

<dependencies>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>prometheus-metrics-exporter-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package io.prometheus.metrics.exporter.servlet.javax;

import io.prometheus.metrics.exporter.common.PrometheusHttpExchange;
import io.prometheus.metrics.exporter.common.PrometheusHttpRequest;
import io.prometheus.metrics.exporter.common.PrometheusHttpResponse;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Enumeration;

/**
* This class is an adapter for HTTP exchanges, implementing the PrometheusHttpExchange interface.
* It wraps HttpServletRequest and HttpServletResponse objects into Request and Response inner classes.
*/
public class HttpExchangeAdapter implements PrometheusHttpExchange {

private final Request request;
private final Response response;

/**
* Constructs a new HttpExchangeAdapter with the given HttpServletRequest and HttpServletResponse.
*
* @param request the HttpServletRequest to be adapted
* @param response the HttpServletResponse to be adapted
*/
public HttpExchangeAdapter(HttpServletRequest request, HttpServletResponse response) {
this.request = new Request(request);
this.response = new Response(response);
}

/**
* Returns the adapted HttpServletRequest.
*
* @return the adapted HttpServletRequest
*/
@Override
public PrometheusHttpRequest getRequest() {
return request;
}

/**
* Returns the adapted HttpServletResponse.
*
* @return the adapted HttpServletResponse
*/
@Override
public PrometheusHttpResponse getResponse() {
return response;
}

@Override
public void handleException(IOException e) throws IOException {
throw e; // leave exception handling to the servlet container
}

@Override
public void handleException(RuntimeException e) {
throw e; // leave exception handling to the servlet container
}

@Override
public void close() {
// nothing to do for Servlets.
}

/**
* This inner class adapts a HttpServletRequest to a PrometheusHttpRequest.
*/
public static class Request implements PrometheusHttpRequest {

private final HttpServletRequest request;

/**
* Constructs a new Request with the given HttpServletRequest.
*
* @param request the HttpServletRequest to be adapted
*/
public Request(HttpServletRequest request) {
this.request = request;
}

@Override
public String getQueryString() {
return request.getQueryString();
}


@Override
public Enumeration<String> getHeaders(String name) {
return request.getHeaders(name);
}


@Override
public String getMethod() {
return request.getMethod();
}


@Override
public String getRequestPath() {
StringBuilder uri = new StringBuilder();
String contextPath = request.getContextPath();
if (contextPath.startsWith("/")) {
uri.append(contextPath);
}
String servletPath = request.getServletPath();
if (servletPath.startsWith("/")) {
uri.append(servletPath);
}
String pathInfo = request.getPathInfo();
if (pathInfo != null) {
uri.append(pathInfo);
}
return uri.toString();
}
}

/**
* This inner class adapts a HttpServletResponse to a PrometheusHttpResponse.
*/
public static class Response implements PrometheusHttpResponse {

private final HttpServletResponse response;

/**
* Constructs a new Response with the given HttpServletResponse.
*
* @param response the HttpServletResponse to be adapted
*/
public Response(HttpServletResponse response) {
this.response = response;
}


@Override
public void setHeader(String name, String value) {
response.setHeader(name, value);
}


@Override
public OutputStream sendHeadersAndGetBody(int statusCode, int contentLength) throws IOException {
if (response.getHeader("Content-Length") == null && contentLength > 0) {
response.setContentLength(contentLength);
}
response.setStatus(statusCode);
return response.getOutputStream();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package io.prometheus.metrics.exporter.servlet.javax;

import io.prometheus.metrics.config.PrometheusProperties;
import io.prometheus.metrics.exporter.common.PrometheusScrapeHandler;
import io.prometheus.metrics.model.registry.PrometheusRegistry;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
* This class extends HttpServlet to create a servlet for exporting Prometheus metrics.
* It uses a PrometheusScrapeHandler to handle HTTP GET requests and export metrics.
* The servlet can be configured with custom PrometheusProperties and a PrometheusRegistry.
*/
public class PrometheusMetricsServlet extends HttpServlet {

private final PrometheusScrapeHandler handler;

/**
* Default constructor. Uses the default PrometheusProperties and PrometheusRegistry.
*/
public PrometheusMetricsServlet() {
this(PrometheusProperties.get(), PrometheusRegistry.defaultRegistry);
}

/**
* Constructor with a custom PrometheusRegistry. Uses the default PrometheusProperties.
*
* @param registry the PrometheusRegistry to use
*/
public PrometheusMetricsServlet(PrometheusRegistry registry) {
this(PrometheusProperties.get(), registry);
}

/**
* Constructor with custom PrometheusProperties. Uses the default PrometheusRegistry.
*
* @param config the PrometheusProperties to use
*/
public PrometheusMetricsServlet(PrometheusProperties config) {
this(config, PrometheusRegistry.defaultRegistry);
}

/**
* Constructor with custom PrometheusProperties and PrometheusRegistry.
*
* @param config the PrometheusProperties to use
* @param registry the PrometheusRegistry to use
*/
public PrometheusMetricsServlet(PrometheusProperties config, PrometheusRegistry registry) {
this.handler = new PrometheusScrapeHandler(config, registry);
}

/**
* Handles HTTP GET requests. Exports Prometheus metrics by delegating to the PrometheusScrapeHandler.
*
* @param request the HttpServletRequest
* @param response the HttpServletResponse
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
handler.handleRequest(new HttpExchangeAdapter(request, response));
}
}
6 changes: 6 additions & 0 deletions prometheus-metrics-exporter-servlet-javax/version-rules.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<ruleset comparisonMethod="maven"
xmlns="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0 https://www.mojohaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd">
<rules>
</rules>
</ruleset>

0 comments on commit c1442e8

Please sign in to comment.