Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import io.prometheus.client.exporter.MetricsServlet;
import io.prometheus.client.hotspot.DefaultExports;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Enumeration;
import java.util.Objects;
import java.util.Optional;
Expand Down Expand Up @@ -54,10 +53,16 @@
import org.apache.zookeeper.server.RateLogger;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -102,6 +107,9 @@ public class PrometheusMetricsProvider implements MetricsProvider {
private final RateLogger rateLogger = new RateLogger(LOG, 60 * 1000);
private String host = "0.0.0.0";
private int port = 7000;
private boolean sslEnabled = false;
private String keyStoreLocation;
private String keyStorePassword;
private boolean exportJvmInfo = true;
private Server server;
private final MetricsServletImpl servlet = new MetricsServletImpl();
Expand All @@ -113,16 +121,23 @@ public class PrometheusMetricsProvider implements MetricsProvider {

@Override
public void configure(Properties configuration) throws MetricsProviderLifeCycleException {
LOG.info("Initializing metrics, configuration: {}", configuration);
this.host = configuration.getProperty("httpHost", "0.0.0.0");
this.port = Integer.parseInt(configuration.getProperty("httpPort", "7000"));
this.sslEnabled = Boolean.parseBoolean(configuration.getProperty("sslEnabled", "false"));
this.keyStoreLocation = configuration.getProperty("keyStore.location");
this.keyStorePassword = configuration.getProperty("keyStore.password");
this.exportJvmInfo = Boolean.parseBoolean(configuration.getProperty("exportJvmInfo", "true"));
this.numWorkerThreads = Integer.parseInt(
configuration.getProperty(NUM_WORKER_THREADS, "1"));
this.maxQueueSize = Integer.parseInt(
configuration.getProperty(MAX_QUEUE_SIZE, "1000000"));
this.workerShutdownTimeoutMs = Long.parseLong(
configuration.getProperty(WORKER_SHUTDOWN_TIMEOUT_MS, "1000"));
LOG.info("Initializing metrics, configuration: httpHost: {}, httpPort: {}, sslEnabled: {}, exportJvmInfo: {}",
this.host,
this.port,
this.sslEnabled,
this.exportJvmInfo);
}

@Override
Expand All @@ -134,7 +149,34 @@ public void start() throws MetricsProviderLifeCycleException {
if (exportJvmInfo) {
DefaultExports.initialize();
}
server = new Server(new InetSocketAddress(host, port));
server = new Server();
ServerConnector connector;
if (sslEnabled) {
LOG.info("SSL enabled for /metrics endpoint");
if (keyStoreLocation == null || keyStoreLocation.isEmpty()) {
throw new MetricsProviderLifeCycleException("keyStore.location is not configured");
}
if (keyStorePassword == null || keyStorePassword.isEmpty()) {
throw new MetricsProviderLifeCycleException("keyStore.password is not configured");
}
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath(keyStoreLocation);
sslContextFactory.setKeyStorePassword(keyStorePassword);

HttpConfiguration httpsConfig = new HttpConfiguration();
httpsConfig.setSecureScheme("https");
httpsConfig.setSecurePort(port);
httpsConfig.addCustomizer(new SecureRequestCustomizer());

connector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory, "http/1.1"),
new HttpConnectionFactory(httpsConfig));
} else {
connector = new ServerConnector(server, new HttpConnectionFactory(new HttpConfiguration()));
}
connector.setHost(host);
connector.setPort(port);
server.setConnectors(new ServerConnector[]{connector});
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
constrainTraceMethod(context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,33 @@ public void testInvalidAddr() {
});
}

@Test
public void testInvalidKeystoreLocation() {
assertThrows(MetricsProviderLifeCycleException.class, () -> {
CollectorRegistry.defaultRegistry.clear();
PrometheusMetricsProvider provider = new PrometheusMetricsProvider();
Properties configuration = new Properties();
configuration.setProperty("sslEnabled", "true");
configuration.setProperty("keyStore.location", "");
provider.configure(configuration);
provider.start();
});
}

@Test
public void testInvalidKeystorePassword() {
assertThrows(MetricsProviderLifeCycleException.class, () -> {
CollectorRegistry.defaultRegistry.clear();
PrometheusMetricsProvider provider = new PrometheusMetricsProvider();
Properties configuration = new Properties();
configuration.setProperty("sslEnabled", "true");
configuration.setProperty("keyStore.location", "/tmp/key.jks");
configuration.setProperty("keyStore.password", "");
provider.configure(configuration);
provider.start();
});
}

@Test
public void testValidConfig() throws MetricsProviderLifeCycleException {
CollectorRegistry.defaultRegistry.clear();
Expand Down
Loading