-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5bf7828
commit 581da7c
Showing
7 changed files
with
594 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
<?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>fr.loghub</groupId> | ||
<artifactId>loghub-pom</artifactId> | ||
<version>0.0.1-SNAPSHOT</version> | ||
</parent> | ||
|
||
<artifactId>loghub-prometheus</artifactId> | ||
<name>LogHub :: Prometheus exporter</name> | ||
|
||
<properties> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
<prometheus.version>1.3.5</prometheus.version> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>fr.loghub</groupId> | ||
<artifactId>loghub-core</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.prometheus</groupId> | ||
<artifactId>prometheus-metrics-exporter-common</artifactId> | ||
<version>${prometheus.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.prometheus</groupId> | ||
<artifactId>prometheus-metrics-core</artifactId> | ||
<version>${prometheus.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.prometheus</groupId> | ||
<artifactId>prometheus-metrics-instrumentation-jvm</artifactId> | ||
<version>${prometheus.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.prometheus</groupId> | ||
<artifactId>prometheus-metrics-exporter-opentelemetry</artifactId> | ||
<version>${prometheus.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>fr.loghub</groupId> | ||
<artifactId>loghub-core</artifactId> | ||
<classifier>tests</classifier> | ||
<version>0.0.1-SNAPSHOT</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-shade-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<phase>package</phase> | ||
<goals> | ||
<goal>shade</goal> | ||
</goals> | ||
<configuration> | ||
<transformers> | ||
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" /> | ||
</transformers> | ||
<filters> | ||
<filter> | ||
<!-- Shading signed JARs will fail without this. http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar --> | ||
<artifact>*:*</artifact> | ||
<excludes> | ||
<exclude>META-INF/*.SF</exclude> | ||
<exclude>META-INF/*.DSA</exclude> | ||
<exclude>META-INF/*.RSA</exclude> | ||
</excludes> | ||
</filter> | ||
<filter> | ||
<artifact>io.prometheus:*</artifact> | ||
<excludes> | ||
<exclude>lib/**</exclude> | ||
</excludes> | ||
</filter> | ||
</filters> | ||
<artifactSet> | ||
<includes> | ||
<include>io.prometheus:*</include> | ||
</includes> | ||
</artifactSet> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
</project> |
120 changes: 120 additions & 0 deletions
120
loghub-prometheus/src/main/java/loghub/prometheus/NettyPrometheusHttpExchange.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package loghub.prometheus; | ||
|
||
import java.io.ByteArrayOutputStream; | ||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
import java.net.URI; | ||
import java.util.Collections; | ||
import java.util.Enumeration; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import io.netty.channel.ChannelHandlerContext; | ||
import io.netty.handler.codec.http.FullHttpRequest; | ||
import io.netty.handler.codec.http.HttpHeaders; | ||
import io.prometheus.metrics.exporter.common.PrometheusHttpExchange; | ||
import io.prometheus.metrics.exporter.common.PrometheusHttpRequest; | ||
import io.prometheus.metrics.exporter.common.PrometheusHttpResponse; | ||
import loghub.netty.http.HttpHandler; | ||
|
||
class NettyPrometheusHttpExchange implements PrometheusHttpExchange { | ||
|
||
private class HttpRequest implements PrometheusHttpRequest { | ||
@Override | ||
public String getQueryString() { | ||
return uri.getQuery(); | ||
} | ||
|
||
@Override | ||
public Enumeration<String> getHeaders(String name) { | ||
return Collections.enumeration(nettyRequest.headers().getAll(name)); | ||
} | ||
|
||
@Override | ||
public String getMethod() { | ||
return nettyRequest.method().name(); | ||
} | ||
|
||
/** | ||
* Absolute path of the HTTP request. | ||
*/ | ||
@Override | ||
public String getRequestPath() { | ||
return uri.getPath().replace("/prometheus/", ""); | ||
} | ||
} | ||
|
||
private class HttpResponse implements PrometheusHttpResponse { | ||
@Override | ||
public void setHeader(String name, String value) { | ||
NettyPrometheusHttpExchange.this.headers.put(name, value); | ||
} | ||
|
||
@Override | ||
public OutputStream sendHeadersAndGetBody(int statusCode, int contentLength) { | ||
NettyPrometheusHttpExchange.this.status = statusCode; | ||
NettyPrometheusHttpExchange.this.content = new ByteArrayOutputStream(contentLength); | ||
return content; | ||
} | ||
} | ||
|
||
private final HttpRequest request = new HttpRequest(); | ||
private final HttpResponse response = new HttpResponse(); | ||
private final URI uri; | ||
private final Map<String, String> headers = new HashMap<>(); | ||
int status; | ||
ByteArrayOutputStream content; | ||
|
||
private final FullHttpRequest nettyRequest; | ||
private final HttpHandler handler; | ||
private final ChannelHandlerContext ctx; | ||
|
||
NettyPrometheusHttpExchange(HttpHandler handler, FullHttpRequest nettyRequest, ChannelHandlerContext ctx) { | ||
this.nettyRequest = nettyRequest; | ||
this.uri = URI.create(nettyRequest.uri()); | ||
this.handler = handler; | ||
this.ctx = ctx; | ||
} | ||
|
||
void copyHeader(HttpHeaders nettyHeaders) { | ||
for (Map.Entry<String, String> e: headers.entrySet()) { | ||
if (! nettyHeaders.contains(e.getKey() )) { | ||
nettyHeaders.add(e.getKey(), e.getValue()); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public PrometheusHttpRequest getRequest() { | ||
return request; | ||
} | ||
|
||
@Override | ||
public PrometheusHttpResponse getResponse() { | ||
return response; | ||
} | ||
|
||
@Override | ||
public void handleException(IOException e) { | ||
try { | ||
handler.exceptionCaught(ctx, e); | ||
} catch (Exception ex) { | ||
throw new IllegalStateException(ex); | ||
} | ||
} | ||
|
||
@Override | ||
public void handleException(RuntimeException e) { | ||
try { | ||
handler.exceptionCaught(ctx, e); | ||
} catch (Exception ex) { | ||
throw new IllegalStateException(ex); | ||
} | ||
} | ||
|
||
@Override | ||
public void close() { | ||
// Nothing to do | ||
} | ||
|
||
} |
58 changes: 58 additions & 0 deletions
58
loghub-prometheus/src/main/java/loghub/prometheus/PrometheusDashboardService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package loghub.prometheus; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.function.BiConsumer; | ||
|
||
import io.netty.channel.SimpleChannelInboundHandler; | ||
import io.netty.handler.codec.http.FullHttpRequest; | ||
import io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter; | ||
import io.prometheus.metrics.model.registry.PrometheusRegistry; | ||
import loghub.Helpers; | ||
import loghub.netty.DashboardService; | ||
|
||
/** | ||
* Resolved the properties as described by <a href="https://prometheus.github.io/client_java/config/config/">client_java/config</a> | ||
*/ | ||
public class PrometheusDashboardService implements DashboardService { | ||
|
||
@Override | ||
public String getPrefix() { | ||
return "prometheus"; | ||
} | ||
|
||
@Override | ||
public List<SimpleChannelInboundHandler<FullHttpRequest>> getServices(Map<String, Object> properties) { | ||
PrometheusRegistry registry = new PrometheusRegistry(); | ||
PrometheusMetricsEndpoint.Builder builder = PrometheusMetricsEndpoint.getBuilder(); | ||
if (properties.containsKey("withJvmMetrics")) { | ||
builder.setWithJvmMetrics(Boolean.TRUE.equals(properties.remove("withJvmMetrics"))); | ||
} | ||
if (Boolean.TRUE.equals(properties.remove("withOpenTelemetry"))) { | ||
OpenTelemetryExporter.Builder openTelemetryExporterBuilder = OpenTelemetryExporter.builder(); | ||
|
||
openTelemetryExporterBuilder.registry(registry); | ||
Map<String, Object> otlpProperties = Helpers.filterPrefix(properties, "openTelemetry"); | ||
Optional.ofNullable(otlpProperties.remove("endpoint")).map(String.class::cast).ifPresent(openTelemetryExporterBuilder::endpoint); | ||
Optional.ofNullable(otlpProperties.remove("protocol")).map(String.class::cast).ifPresent(openTelemetryExporterBuilder::protocol); | ||
Optional.ofNullable(otlpProperties.remove("interval")).map(Integer.class::cast).ifPresent(openTelemetryExporterBuilder::intervalSeconds); | ||
Optional.ofNullable(otlpProperties.remove("timeoutSeconds")).map(Integer.class::cast).ifPresent(openTelemetryExporterBuilder::timeoutSeconds); | ||
Optional.ofNullable(otlpProperties.remove("headers")).map(Map.class::cast).ifPresent(m -> fillMap(m, openTelemetryExporterBuilder::header)); | ||
Optional.ofNullable(otlpProperties.remove("resourceAttributes")).map(Map.class::cast).ifPresent(m -> fillMap(m, openTelemetryExporterBuilder::resourceAttribute)); | ||
Optional.ofNullable(otlpProperties.remove("serviceInstanceId")).map(String.class::cast).ifPresent(openTelemetryExporterBuilder::serviceInstanceId); | ||
Optional.ofNullable(otlpProperties.remove("serviceNamespace")).map(String.class::cast).ifPresent(openTelemetryExporterBuilder::serviceNamespace); | ||
Optional.ofNullable(otlpProperties.remove("serviceName")).map(String.class::cast).ifPresent(openTelemetryExporterBuilder::serviceName); | ||
Optional.ofNullable(otlpProperties.remove("serviceVersion")).map(String.class::cast).ifPresent(openTelemetryExporterBuilder::serviceVersion); | ||
openTelemetryExporterBuilder.buildAndStart(); | ||
} | ||
builder.setRegistry(registry); | ||
PrometheusMetricsEndpoint ps = builder.build(); | ||
return List.of(ps); | ||
} | ||
|
||
private void fillMap(Map<?, ?> m, BiConsumer<String, String> filler) { | ||
m.forEach((k, v) -> filler.accept(k.toString(), v.toString())); | ||
} | ||
|
||
} |
Oops, something went wrong.