From 05c39a0d8a322f2dccc7e667cd3c47e36c336fe6 Mon Sep 17 00:00:00 2001 From: SH98011ML Date: Fri, 20 Aug 2021 18:59:33 +0800 Subject: [PATCH 1/6] init nightingale backend --- .../prometheus/client/smoketest/Server.java | 2 + pom.xml | 5 +- .../client/hotspot/DefaultExports.java | 2 + simpleclient_nightingale_bridge/pom.xml | 62 ++++++++ .../io/prometheus/client/bridge/Encoder.java | 135 ++++++++++++++++++ .../prometheus/client/bridge/Nightingale.java | 104 ++++++++++++++ .../client/bridge/StringEscapeUtils.java | 88 ++++++++++++ .../client/bridge/NightingaleTest.java | 49 +++++++ 8 files changed, 445 insertions(+), 2 deletions(-) create mode 100644 simpleclient_nightingale_bridge/pom.xml create mode 100644 simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/Encoder.java create mode 100644 simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/Nightingale.java create mode 100644 simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/StringEscapeUtils.java create mode 100644 simpleclient_nightingale_bridge/src/test/java/io/prometheus/client/bridge/NightingaleTest.java diff --git a/integration_tests/example_application/src/main/java/io/prometheus/client/smoketest/Server.java b/integration_tests/example_application/src/main/java/io/prometheus/client/smoketest/Server.java index 1a5f481f0..5630ac63b 100644 --- a/integration_tests/example_application/src/main/java/io/prometheus/client/smoketest/Server.java +++ b/integration_tests/example_application/src/main/java/io/prometheus/client/smoketest/Server.java @@ -1,5 +1,6 @@ package io.prometheus.client.smoketest; +import io.prometheus.client.CollectorRegistry; import io.prometheus.client.Counter; import io.prometheus.client.exporter.HTTPServer; import io.prometheus.client.hotspot.DefaultExports; @@ -19,6 +20,7 @@ public static void main(String[] args) throws IOException, InterruptedException .labelNames("path") .register(); counter.labels("/hello-world").inc(); + CollectorRegistry.defaultRegistry.metricFamilySamples(); new HTTPServer(9000); Thread.currentThread().join(); // sleep forever } diff --git a/pom.xml b/pom.xml index 2b4a05bde..3d0b571aa 100644 --- a/pom.xml +++ b/pom.xml @@ -62,6 +62,7 @@ simpleclient_bom benchmark integration_tests + simpleclient_nightingale_bridge @@ -224,8 +225,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.6 - 1.6 + 1.8 + 1.8 diff --git a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/DefaultExports.java b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/DefaultExports.java index 79cd6ed5e..737978c6d 100644 --- a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/DefaultExports.java +++ b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/DefaultExports.java @@ -30,6 +30,8 @@ public static synchronized void initialize() { } } + + /** * Register the default Hotspot collectors with the given registry. */ diff --git a/simpleclient_nightingale_bridge/pom.xml b/simpleclient_nightingale_bridge/pom.xml new file mode 100644 index 000000000..692ce5476 --- /dev/null +++ b/simpleclient_nightingale_bridge/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + + io.prometheus + parent + 0.11.1-SNAPSHOT + + + io.prometheus + simpleclient_nightingale_bridge + bundle + + Prometheus Java Simpleclient Nightingale Bridge + + Nightingale bridge for the simpleclient. + + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + + brian-brazil + Brian Brazil + brian.brazil@robustperception.io + + + + + + + io.prometheus + simpleclient + 0.11.1-SNAPSHOT + + + com.alibaba + fastjson + 1.2.76 + + + + org.apache.httpcomponents + httpclient + 4.5.13 + + + + junit + junit + 4.13.2 + test + + + diff --git a/simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/Encoder.java b/simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/Encoder.java new file mode 100644 index 000000000..e5865b1b3 --- /dev/null +++ b/simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/Encoder.java @@ -0,0 +1,135 @@ +package io.prometheus.client.bridge; + +import io.prometheus.client.Collector; +import io.prometheus.client.Collector.MetricFamilySamples; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import com.alibaba.fastjson.JSON; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static io.prometheus.client.bridge.StringEscapeUtils.escapeJson; + +public class Encoder { + private final HttpClient client; + private ArrayList samples; + private static final Logger logger = Logger.getLogger(Encoder.class.getName()); + + private final String url; + private final int batchSize; + private final long stepS; + private final String nid; + private StringBuilder builder = new StringBuilder(); + + + Encoder(String url, int batchSize, long stepS, String nid) { + this.stepS = stepS; + this.nid = nid; + this.url = url; + this.client = HttpClients.createDefault(); + this.batchSize = batchSize; + this.samples = new ArrayList<>(batchSize); + } + + void add(Collector.MetricFamilySamples.Sample sample) { + this.samples.add(sample); + if (this.samples.size() == 100) { + send(); + } + } + + + protected Long generateTimestamp() { + return System.currentTimeMillis() / 1000; + } + + void writeMessage(StringBuilder sb, Collector.MetricFamilySamples.Sample sample) { + Long timestamp = generateTimestamp(); + String type = "GAUGE"; + String name = sample.name; + sb.append("{\"").append("timestamp").append("\":").append(timestamp) + .append(",\"metric\":\"").append(escapeJson(name)).append('"') + .append(",\"counterType\":\"").append(type).append('"') + .append(",\"step\":").append(stepS); + sb.append(",\"nid\":\"").append(nid).append('"'); + writeTags(sb, sample); + sb.append(",\"value\":"); + sb.append(sample.value); + sb.append("}"); + } + + void writeTags(StringBuilder sb, Collector.MetricFamilySamples.Sample sample) { + if (sample.labelNames.size() == 0) { + return; + } + sb.append(",\"tags\":\""); + for (int i = 0; i < sample.labelNames.size(); ++i) { + sb.append(escapeJson(sample.labelNames.get(i))).append("=") + .append(escapeJson(sample.labelValues.get(i).replace(" ", "-"))); + } + sb.append('"'); + } + + void end() { + send(); + } + + String marshalBatch() { + builder.append("["); + this.samples.stream().peek(sample -> { + writeMessage(builder, sample); + }).skip(1).forEach(sample -> { + builder.append(",\n"); + writeMessage(builder, sample); + }); + builder.append("]"); + String body=builder.toString(); + builder.setLength(0); + return body; + } + + private void send() { + if (this.samples.size() > 0) { + String body = marshalBatch(); + this.samples.clear(); + HttpPost post = new HttpPost(this.url); + StringEntity requestEntity = new StringEntity( + body, ContentType.APPLICATION_JSON); + post.setEntity(requestEntity); + try { + HttpResponse response = client.execute(post); + final HttpEntity entity = response.getEntity(); + System.out.println(response.getStatusLine()); + System.out.println(EntityUtils.toString(entity)); + if (entity != null) { + try (final InputStream inStream = entity.getContent()) { + //inStream.read(); + + // do something useful with the response + } catch (final IOException ex) { + logger.log(Level.WARNING, "Exception " + ex + " get response from " +this.url, ex); + + // In case of an IOException the connection will be released + // back to the connection manager automatically + } + } + } catch (Exception e) { + logger.log(Level.WARNING, "Exception " + e + " pushing to " +this.url, e); + + } + + } + } +} diff --git a/simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/Nightingale.java b/simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/Nightingale.java new file mode 100644 index 000000000..314fe531a --- /dev/null +++ b/simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/Nightingale.java @@ -0,0 +1,104 @@ +package io.prometheus.client.bridge; + +import io.prometheus.client.Collector; +import io.prometheus.client.CollectorRegistry; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClientBuilder; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.Socket; +import java.nio.charset.Charset; +import java.util.Collections; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +/** + * Export metrics in the Graphite plaintext format. + *

+ *

+ * {@code
+ *  Graphite g = new Graphite("localhost", 2003);
+ *  // Push the default registry once.
+ *  g.push(CollectorRegistry.defaultRegistry);
+ *
+ *  // Push the default registry every 60 seconds.
+ *  Thread thread = g.start(CollectorRegistry.defaultRegistry, 60);
+ *  // Stop pushing.
+ *  thread.interrupt();
+ *  thread.join();
+ * }
+ * 
+ *

+ */ +public class Nightingale { + private static final Logger logger = Logger.getLogger(Nightingale.class.getName()); + + private final Encoder encoder; + public Nightingale(String url) { + this.encoder = new Encoder(url, 100, 10, "sdk"); + } + + /** + * Push samples from the given registry to Graphite. + */ + public void push(CollectorRegistry registry) { + for (Collector.MetricFamilySamples metricFamilySamples : Collections.list(registry.metricFamilySamples())) { + for (Collector.MetricFamilySamples.Sample sample : metricFamilySamples.samples) { + this.encoder.add(sample); + } + } + this.encoder.end(); + } + + /** + * Push samples from the given registry to Graphite every minute. + */ + public Thread start(CollectorRegistry registry) { + return start(registry, 60); + } + + /** + * Push samples from the given registry to Graphite at the given interval. + */ + public Thread start(CollectorRegistry registry, int intervalSeconds) { + Thread thread = new PushThread(registry, intervalSeconds); + thread.setDaemon(true); + thread.start(); + return thread; + } + + private class PushThread extends Thread { + private final CollectorRegistry registry; + private final int intervalSeconds; + + PushThread(CollectorRegistry registry, int intervalSeconds) { + this.registry = registry; + this.intervalSeconds = intervalSeconds; + } + + public void run() { + long waitUntil = System.currentTimeMillis(); + while (true) { + push(registry); + long now = System.currentTimeMillis(); + // We may skip some pushes if we're falling behind. + while (now >= waitUntil) { + waitUntil += intervalSeconds * 1000; + } + try { + Thread.sleep(waitUntil - now); + } catch (InterruptedException e) { + return; + } + } + } + } +} diff --git a/simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/StringEscapeUtils.java b/simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/StringEscapeUtils.java new file mode 100644 index 000000000..2b73d42b8 --- /dev/null +++ b/simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/StringEscapeUtils.java @@ -0,0 +1,88 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package io.prometheus.client.bridge; + + +public final class StringEscapeUtils { + private static final String[] REPLACEMENT_CHARS = new String[128]; + private static final String U2028 = "\\u2028"; + private static final String U2029 = "\\u2029"; + + public static String escapeJson(String v) { + if (v == null) { + return ""; + } else { + int length = v.length(); + if (length == 0) { + return v; + } else { + int afterReplacement = 0; + StringBuilder builder = null; + + for(int i = 0; i < length; ++i) { + char c = v.charAt(i); + String replacement; + if (c < 128) { + replacement = REPLACEMENT_CHARS[c]; + if (replacement == null) { + continue; + } + } else if (c == 8232) { + replacement = "\\u2028"; + } else { + if (c != 8233) { + continue; + } + + replacement = "\\u2029"; + } + + if (afterReplacement < i) { + if (builder == null) { + builder = new StringBuilder(length); + } + + builder.append(v, afterReplacement, i); + } + + if (builder == null) { + builder = new StringBuilder(length); + } + + builder.append(replacement); + afterReplacement = i + 1; + } + + if (builder == null) { + return v; + } else { + if (afterReplacement < length) { + builder.append(v, afterReplacement, length); + } + + return builder.toString(); + } + } + } + } + + private StringEscapeUtils() { + } + + static { + for(int i = 0; i <= 31; ++i) { + REPLACEMENT_CHARS[i] = String.format("\\u%04x", i); + } + + REPLACEMENT_CHARS[34] = "\\\""; + REPLACEMENT_CHARS[92] = "\\\\"; + REPLACEMENT_CHARS[9] = "\\t"; + REPLACEMENT_CHARS[8] = "\\b"; + REPLACEMENT_CHARS[10] = "\\n"; + REPLACEMENT_CHARS[13] = "\\r"; + REPLACEMENT_CHARS[12] = "\\f"; + } +} diff --git a/simpleclient_nightingale_bridge/src/test/java/io/prometheus/client/bridge/NightingaleTest.java b/simpleclient_nightingale_bridge/src/test/java/io/prometheus/client/bridge/NightingaleTest.java new file mode 100644 index 000000000..19db7914b --- /dev/null +++ b/simpleclient_nightingale_bridge/src/test/java/io/prometheus/client/bridge/NightingaleTest.java @@ -0,0 +1,49 @@ +package io.prometheus.client.bridge; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import io.prometheus.client.Collector; +import org.junit.Test; + +import io.prometheus.client.CollectorRegistry; +import io.prometheus.client.Gauge; +import io.prometheus.client.bridge.Nightingale; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Collections; + +public class NightingaleTest { + @Test + public void testMarshalBatch(){ + CollectorRegistry registry = new CollectorRegistry(); + + for (int i=0;i<1;i++){ + Gauge labels = Gauge.build().name("labels"+i).help("help").labelNames("l").register(registry); + labels.labels("fo*o").inc(); + } + Encoder encoder =new Encoder("dsadf",100,1000,"11"); + for (Collector.MetricFamilySamples metricFamilySamples : Collections.list(registry.metricFamilySamples())) { + for (Collector.MetricFamilySamples.Sample sample : metricFamilySamples.samples) { + encoder.add(sample); + } + } + String body=encoder.marshalBatch(); + System.out.println(body); + } + @Test + public void testPush() throws Exception { + // Create a metric. + CollectorRegistry registry = new CollectorRegistry(); + Gauge labels = Gauge.build().name("labels").help("help").labelNames("l").register(registry); + labels.labels("fo*o").inc(); + // Push. + Nightingale g = new Nightingale("http://n9e.example.com/api/transfer/push"); + g.push(registry); + + } +} From c7267c78f81e52e302930ce14804c32b48c155bc Mon Sep 17 00:00:00 2001 From: SH98011ML Date: Tue, 24 Aug 2021 19:05:49 +0800 Subject: [PATCH 2/6] update --- .../client/{bridge => sdk}/Graphite.java | 2 +- .../client/{bridge => sdk}/GraphiteTest.java | 3 +- .../pom.xml | 6 +++ .../io/prometheus/client/sdk}/Encoder.java | 35 ++++++------ .../io/prometheus/client/sdk/Metrics.java | 53 +++++++++++++++++++ .../prometheus/client/sdk}/Nightingale.java | 50 +++++------------ .../client/sdk}/StringEscapeUtils.java | 2 +- .../client/sdk}/NightingaleTest.java | 31 +++++++---- 8 files changed, 115 insertions(+), 67 deletions(-) rename simpleclient_graphite_bridge/src/main/java/io/prometheus/client/{bridge => sdk}/Graphite.java (98%) rename simpleclient_graphite_bridge/src/test/java/io/prometheus/client/{bridge => sdk}/GraphiteTest.java (95%) rename {simpleclient_nightingale_bridge => simpleclient_sdk}/pom.xml (91%) rename {simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge => simpleclient_sdk/src/main/java/io/prometheus/client/sdk}/Encoder.java (84%) create mode 100644 simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Metrics.java rename {simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge => simpleclient_sdk/src/main/java/io/prometheus/client/sdk}/Nightingale.java (65%) rename {simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge => simpleclient_sdk/src/main/java/io/prometheus/client/sdk}/StringEscapeUtils.java (98%) rename {simpleclient_nightingale_bridge/src/test/java/io/prometheus/client/bridge => simpleclient_sdk/src/test/java/io/prometheus/client/sdk}/NightingaleTest.java (60%) diff --git a/simpleclient_graphite_bridge/src/main/java/io/prometheus/client/bridge/Graphite.java b/simpleclient_graphite_bridge/src/main/java/io/prometheus/client/sdk/Graphite.java similarity index 98% rename from simpleclient_graphite_bridge/src/main/java/io/prometheus/client/bridge/Graphite.java rename to simpleclient_graphite_bridge/src/main/java/io/prometheus/client/sdk/Graphite.java index 5e292800c..120fa416f 100644 --- a/simpleclient_graphite_bridge/src/main/java/io/prometheus/client/bridge/Graphite.java +++ b/simpleclient_graphite_bridge/src/main/java/io/prometheus/client/sdk/Graphite.java @@ -1,4 +1,4 @@ -package io.prometheus.client.bridge; +package io.prometheus.client.sdk; import io.prometheus.client.Collector; import io.prometheus.client.CollectorRegistry; diff --git a/simpleclient_graphite_bridge/src/test/java/io/prometheus/client/bridge/GraphiteTest.java b/simpleclient_graphite_bridge/src/test/java/io/prometheus/client/sdk/GraphiteTest.java similarity index 95% rename from simpleclient_graphite_bridge/src/test/java/io/prometheus/client/bridge/GraphiteTest.java rename to simpleclient_graphite_bridge/src/test/java/io/prometheus/client/sdk/GraphiteTest.java index dbe6099ef..4a2fc3246 100644 --- a/simpleclient_graphite_bridge/src/test/java/io/prometheus/client/bridge/GraphiteTest.java +++ b/simpleclient_graphite_bridge/src/test/java/io/prometheus/client/sdk/GraphiteTest.java @@ -1,4 +1,4 @@ -package io.prometheus.client.bridge; +package io.prometheus.client.sdk; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; @@ -9,7 +9,6 @@ import io.prometheus.client.Gauge; import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; diff --git a/simpleclient_nightingale_bridge/pom.xml b/simpleclient_sdk/pom.xml similarity index 91% rename from simpleclient_nightingale_bridge/pom.xml rename to simpleclient_sdk/pom.xml index 692ce5476..2362298ad 100644 --- a/simpleclient_nightingale_bridge/pom.xml +++ b/simpleclient_sdk/pom.xml @@ -40,6 +40,12 @@ simpleclient 0.11.1-SNAPSHOT + + io.prometheus + simpleclient_httpserver + 0.11.1-SNAPSHOT + + com.alibaba fastjson diff --git a/simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/Encoder.java b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Encoder.java similarity index 84% rename from simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/Encoder.java rename to simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Encoder.java index e5865b1b3..87eea7200 100644 --- a/simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/Encoder.java +++ b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Encoder.java @@ -1,11 +1,9 @@ -package io.prometheus.client.bridge; +package io.prometheus.client.sdk; import io.prometheus.client.Collector; -import io.prometheus.client.Collector.MetricFamilySamples; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; -import com.alibaba.fastjson.JSON; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; @@ -14,35 +12,42 @@ import java.io.IOException; import java.io.InputStream; -import java.lang.reflect.Array; import java.util.ArrayList; -import java.util.List; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.stream.Collectors; -import static io.prometheus.client.bridge.StringEscapeUtils.escapeJson; +import static io.prometheus.client.sdk.StringEscapeUtils.escapeJson; public class Encoder { private final HttpClient client; private ArrayList samples; private static final Logger logger = Logger.getLogger(Encoder.class.getName()); - private final String url; private final int batchSize; private final long stepS; private final String nid; private StringBuilder builder = new StringBuilder(); - - - Encoder(String url, int batchSize, long stepS, String nid) { + private final Map tags; + private String tagStr; + Encoder(String url, int batchSize, long stepS, String nid,Map tags) { this.stepS = stepS; this.nid = nid; this.url = url; this.client = HttpClients.createDefault(); this.batchSize = batchSize; this.samples = new ArrayList<>(batchSize); + this.tags = tags; + this.tagStr = this.tags.entrySet().stream().map((e)->{ + return escapeJson(e.getKey())+"="+escapeJson(e.getValue()); + }).collect(Collectors.joining(",")); + + } + + void add(Collector.MetricFamilySamples.Sample sample) { this.samples.add(sample); if (this.samples.size() == 100) { @@ -75,8 +80,9 @@ void writeTags(StringBuilder sb, Collector.MetricFamilySamples.Sample sample) { return; } sb.append(",\"tags\":\""); + sb.append(this.tagStr); for (int i = 0; i < sample.labelNames.size(); ++i) { - sb.append(escapeJson(sample.labelNames.get(i))).append("=") + sb.append(',').append(escapeJson(sample.labelNames.get(i))).append("=") .append(escapeJson(sample.labelValues.get(i).replace(" ", "-"))); } sb.append('"'); @@ -95,7 +101,7 @@ String marshalBatch() { writeMessage(builder, sample); }); builder.append("]"); - String body=builder.toString(); + String body = builder.toString(); builder.setLength(0); return body; } @@ -119,15 +125,14 @@ private void send() { // do something useful with the response } catch (final IOException ex) { - logger.log(Level.WARNING, "Exception " + ex + " get response from " +this.url, ex); + logger.log(Level.WARNING, "Exception " + ex + " get response from " + this.url, ex); // In case of an IOException the connection will be released // back to the connection manager automatically } } } catch (Exception e) { - logger.log(Level.WARNING, "Exception " + e + " pushing to " +this.url, e); - + logger.log(Level.WARNING, "Exception " + e + " pushing to " + this.url, e); } } diff --git a/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Metrics.java b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Metrics.java new file mode 100644 index 000000000..0ec72f2aa --- /dev/null +++ b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Metrics.java @@ -0,0 +1,53 @@ +package io.prometheus.client.sdk; + +import io.prometheus.client.CollectorRegistry; +import io.prometheus.client.exporter.HTTPServer; + +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.util.HashMap; +import java.util.Map; + +public class Metrics { + private CollectorRegistry registry; + private HashMap tags; + + public Metrics(String bu, String project, String app, Map globalTags) { + this(bu, project, app, globalTags, CollectorRegistry.defaultRegistry); + + } + + public Metrics(String bu, String project, String app, Map globalTags, CollectorRegistry registry) { + this.registry = registry; + this.tags = new HashMap<>(); + if (globalTags != null) { + globalTags.forEach((k, v) -> { + this.tags.put(k, v); + }); + } + this.tags.put("bu", bu); + this.tags.put("project", project); + this.tags.put("app", app); + String podName = System.getenv("MY_POD_NAME"); + if (podName == null) { + podName = ManagementFactory.getRuntimeMXBean().getName(); + } + this.tags.put("pid", podName); + } + + public void StartPushLoop(int interval) { + this.StartPushLoop(interval, Nightingale.defaultUrl); + } + + public void StartPushLoop(int interval, String url) { + Nightingale nightingale = new Nightingale(url, interval, this.tags); + nightingale.start(this.registry, interval); + } + + public HTTPServer StartPullHttpServer(int port) throws IOException { + HTTPServer server = new HTTPServer(port); + return server; + } + + +} diff --git a/simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/Nightingale.java b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Nightingale.java similarity index 65% rename from simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/Nightingale.java rename to simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Nightingale.java index 314fe531a..2312a9603 100644 --- a/simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/Nightingale.java +++ b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Nightingale.java @@ -1,55 +1,31 @@ -package io.prometheus.client.bridge; +package io.prometheus.client.sdk; import io.prometheus.client.Collector; import io.prometheus.client.CollectorRegistry; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.HttpClientBuilder; -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.net.Socket; -import java.nio.charset.Charset; import java.util.Collections; -import java.util.logging.Level; +import java.util.Map; import java.util.logging.Logger; -import java.util.regex.Pattern; -import java.util.regex.Matcher; -/** - * Export metrics in the Graphite plaintext format. - *

- *

- * {@code
- *  Graphite g = new Graphite("localhost", 2003);
- *  // Push the default registry once.
- *  g.push(CollectorRegistry.defaultRegistry);
- *
- *  // Push the default registry every 60 seconds.
- *  Thread thread = g.start(CollectorRegistry.defaultRegistry, 60);
- *  // Stop pushing.
- *  thread.interrupt();
- *  thread.join();
- * }
- * 
- *

- */ + public class Nightingale { private static final Logger logger = Logger.getLogger(Nightingale.class.getName()); - + static final String defaultUrl = "http://localhost:2080/v1/push"; private final Encoder encoder; - public Nightingale(String url) { - this.encoder = new Encoder(url, 100, 10, "sdk"); + + public Nightingale(String url, int batchSize, int interval, String tenantId, Map globalTags) { + this.encoder = new Encoder(url, 100, 10, tenantId,globalTags); } + public Nightingale(String url,int interval, Map globalTags) { + this(url, 1000, interval, "1", globalTags); + } + + /** * Push samples from the given registry to Graphite. */ - public void push(CollectorRegistry registry) { + public void push(CollectorRegistry registry) { for (Collector.MetricFamilySamples metricFamilySamples : Collections.list(registry.metricFamilySamples())) { for (Collector.MetricFamilySamples.Sample sample : metricFamilySamples.samples) { this.encoder.add(sample); diff --git a/simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/StringEscapeUtils.java b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/StringEscapeUtils.java similarity index 98% rename from simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/StringEscapeUtils.java rename to simpleclient_sdk/src/main/java/io/prometheus/client/sdk/StringEscapeUtils.java index 2b73d42b8..75fe55918 100644 --- a/simpleclient_nightingale_bridge/src/main/java/io/prometheus/client/bridge/StringEscapeUtils.java +++ b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/StringEscapeUtils.java @@ -3,7 +3,7 @@ // (powered by FernFlower decompiler) // -package io.prometheus.client.bridge; +package io.prometheus.client.sdk; public final class StringEscapeUtils { diff --git a/simpleclient_nightingale_bridge/src/test/java/io/prometheus/client/bridge/NightingaleTest.java b/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java similarity index 60% rename from simpleclient_nightingale_bridge/src/test/java/io/prometheus/client/bridge/NightingaleTest.java rename to simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java index 19db7914b..afd7b3732 100644 --- a/simpleclient_nightingale_bridge/src/test/java/io/prometheus/client/bridge/NightingaleTest.java +++ b/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java @@ -1,4 +1,4 @@ -package io.prometheus.client.bridge; +package io.prometheus.client.sdk; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; @@ -8,14 +8,10 @@ import io.prometheus.client.CollectorRegistry; import io.prometheus.client.Gauge; -import io.prometheus.client.bridge.Nightingale; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.ServerSocket; -import java.net.Socket; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; public class NightingaleTest { @Test @@ -26,7 +22,7 @@ public void testMarshalBatch(){ Gauge labels = Gauge.build().name("labels"+i).help("help").labelNames("l").register(registry); labels.labels("fo*o").inc(); } - Encoder encoder =new Encoder("dsadf",100,1000,"11"); + Encoder encoder =new Encoder("dsadf",100,1000,"11",null); for (Collector.MetricFamilySamples metricFamilySamples : Collections.list(registry.metricFamilySamples())) { for (Collector.MetricFamilySamples.Sample sample : metricFamilySamples.samples) { encoder.add(sample); @@ -39,11 +35,24 @@ public void testMarshalBatch(){ public void testPush() throws Exception { // Create a metric. CollectorRegistry registry = new CollectorRegistry(); - Gauge labels = Gauge.build().name("labels").help("help").labelNames("l").register(registry); + Gauge labels = Gauge.build().name("test_test").help("help").labelNames("l").register(registry); labels.labels("fo*o").inc(); // Push. - Nightingale g = new Nightingale("http://n9e.example.com/api/transfer/push"); + Nightingale g = new Nightingale("http://n9e.example.com/api/transfer/push",10,null); g.push(registry); - + } + @Test + public void testPushLoop(){ + Map tags=new HashMap<>(); + tags.put("test","test2"); + Metrics metric= new Metrics("infra","metrics","test", tags); + Gauge labels = Gauge.build().name("test_test2").help("help").labelNames("l").register(); + labels.labels("fo*o").inc(); + metric.StartPushLoop(1,"http://10.110.20.100:8080/api/transfer/push"); + try { + Thread.sleep(1000*60); + } catch (InterruptedException e) { + e.printStackTrace(); + } } } From 8be4224351290abdbcd2e59076f6f7a957ab9140 Mon Sep 17 00:00:00 2001 From: SH98011ML Date: Wed, 25 Aug 2021 14:25:55 +0800 Subject: [PATCH 3/6] update --- .../prometheus/client/CollectorRegistry.java | 9 + .../client/exporter/common/TextFormat.java | 604 ++++++++++-------- .../client/exporter/HTTPServer.java | 18 +- .../io/prometheus/client/sdk/Encoder.java | 18 +- .../io/prometheus/client/sdk/Metrics.java | 4 +- .../client/sdk/NightingaleTest.java | 18 +- 6 files changed, 400 insertions(+), 271 deletions(-) diff --git a/simpleclient/src/main/java/io/prometheus/client/CollectorRegistry.java b/simpleclient/src/main/java/io/prometheus/client/CollectorRegistry.java index 0d37cca27..98ddd5de8 100644 --- a/simpleclient/src/main/java/io/prometheus/client/CollectorRegistry.java +++ b/simpleclient/src/main/java/io/prometheus/client/CollectorRegistry.java @@ -31,6 +31,15 @@ public class CollectorRegistry { private final Map> collectorsToNames = new HashMap>(); private final Map namesToCollectors = new HashMap(); + public Map getGlobalTags() { + return globalTags; + } + + public void setGlobalTags(Map globalTags) { + this.globalTags = globalTags; + } + + private Map globalTags; private final boolean autoDescribe; public CollectorRegistry() { diff --git a/simpleclient_common/src/main/java/io/prometheus/client/exporter/common/TextFormat.java b/simpleclient_common/src/main/java/io/prometheus/client/exporter/common/TextFormat.java index db2de3a5b..d99a64187 100644 --- a/simpleclient_common/src/main/java/io/prometheus/client/exporter/common/TextFormat.java +++ b/simpleclient_common/src/main/java/io/prometheus/client/exporter/common/TextFormat.java @@ -12,292 +12,382 @@ import io.prometheus.client.Collector; public class TextFormat { - /** - * Content-type for Prometheus text version 0.0.4. - */ - public final static String CONTENT_TYPE_004 = "text/plain; version=0.0.4; charset=utf-8"; + /** + * Content-type for Prometheus text version 0.0.4. + */ + public final static String CONTENT_TYPE_004 = "text/plain; version=0.0.4; charset=utf-8"; - /** - * Content-type for Openmetrics text version 1.0.0. - * - * @since 0.10.0 - */ - public final static String CONTENT_TYPE_OPENMETRICS_100 = "application/openmetrics-text; version=1.0.0; charset=utf-8"; + /** + * Content-type for Openmetrics text version 1.0.0. + * + * @since 0.10.0 + */ + public final static String CONTENT_TYPE_OPENMETRICS_100 = "application/openmetrics-text; version=1.0.0; charset=utf-8"; - /** - * Return the content type that should be used for a given Accept HTTP header. - * - * @since 0.10.0 - */ - public static String chooseContentType(String acceptHeader) { - if (acceptHeader == null) { - return CONTENT_TYPE_004; - } + /** + * Return the content type that should be used for a given Accept HTTP header. + * + * @since 0.10.0 + */ + public static String chooseContentType(String acceptHeader) { + if (acceptHeader == null) { + return CONTENT_TYPE_004; + } - for (String accepts : acceptHeader.split(",")) { - if ("application/openmetrics-text".equals(accepts.split(";")[0].trim())) { - return CONTENT_TYPE_OPENMETRICS_100; - } - } + for (String accepts : acceptHeader.split(",")) { + if ("application/openmetrics-text".equals(accepts.split(";")[0].trim())) { + return CONTENT_TYPE_OPENMETRICS_100; + } + } - return CONTENT_TYPE_004; - } + return CONTENT_TYPE_004; + } - /** - * Write out the given MetricFamilySamples in a format per the contentType. - * - * @since 0.10.0 - */ - public static void writeFormat(String contentType, Writer writer, Enumeration mfs) throws IOException { - if (CONTENT_TYPE_004.equals(contentType)) { - write004(writer, mfs); - return; + /** + * Write out the given MetricFamilySamples in a format per the contentType. + * + * @since 0.10.0 + */ + public static void writeFormat(String contentType, Writer writer, Enumeration mfs) throws IOException { + if (CONTENT_TYPE_004.equals(contentType)) { + write004(writer, mfs); + return; + } + if (CONTENT_TYPE_OPENMETRICS_100.equals(contentType)) { + writeOpenMetrics100(writer, mfs); + return; + } + throw new IllegalArgumentException("Unknown contentType " + contentType); } - if (CONTENT_TYPE_OPENMETRICS_100.equals(contentType)) { - writeOpenMetrics100(writer, mfs); - return; + + public static void writeFormat(String contentType, Writer writer, Enumeration mfs, String globalTagsString) throws IOException { + if (CONTENT_TYPE_004.equals(contentType)) { + write004(writer, mfs, globalTagsString); + return; + } + if (CONTENT_TYPE_OPENMETRICS_100.equals(contentType)) { + writeOpenMetrics100(writer, mfs); + return; + } + throw new IllegalArgumentException("Unknown contentType " + contentType); } - throw new IllegalArgumentException("Unknown contentType " + contentType); - } - /** - * Write out the text version 0.0.4 of the given MetricFamilySamples. - */ - public static void write004(Writer writer, Enumeration mfs) throws IOException { - Map omFamilies = new TreeMap(); - /* See http://prometheus.io/docs/instrumenting/exposition_formats/ - * for the output format specification. */ - while(mfs.hasMoreElements()) { - Collector.MetricFamilySamples metricFamilySamples = mfs.nextElement(); - String name = metricFamilySamples.name; - writer.write("# HELP "); - writer.write(name); - if (metricFamilySamples.type == Collector.Type.COUNTER) { - writer.write("_total"); - } - if (metricFamilySamples.type == Collector.Type.INFO) { - writer.write("_info"); - } - writer.write(' '); - writeEscapedHelp(writer, metricFamilySamples.help); - writer.write('\n'); + /** + * Write out the text version 0.0.4 of the given MetricFamilySamples. + */ + public static void write004(Writer writer, Enumeration mfs) throws IOException { + Map omFamilies = new TreeMap(); + /* See http://prometheus.io/docs/instrumenting/exposition_formats/ + * for the output format specification. */ + while (mfs.hasMoreElements()) { + Collector.MetricFamilySamples metricFamilySamples = mfs.nextElement(); + String name = metricFamilySamples.name; + writer.write("# HELP "); + writer.write(name); + if (metricFamilySamples.type == Collector.Type.COUNTER) { + writer.write("_total"); + } + if (metricFamilySamples.type == Collector.Type.INFO) { + writer.write("_info"); + } + writer.write(' '); + writeEscapedHelp(writer, metricFamilySamples.help); + writer.write('\n'); - writer.write("# TYPE "); - writer.write(name); - if (metricFamilySamples.type == Collector.Type.COUNTER) { - writer.write("_total"); - } - if (metricFamilySamples.type == Collector.Type.INFO) { - writer.write("_info"); - } - writer.write(' '); - writer.write(typeString(metricFamilySamples.type)); - writer.write('\n'); + writer.write("# TYPE "); + writer.write(name); + if (metricFamilySamples.type == Collector.Type.COUNTER) { + writer.write("_total"); + } + if (metricFamilySamples.type == Collector.Type.INFO) { + writer.write("_info"); + } + writer.write(' '); + writer.write(typeString(metricFamilySamples.type)); + writer.write('\n'); - String createdName = name + "_created"; - String gcountName = name + "_gcount"; - String gsumName = name + "_gsum"; - for (Collector.MetricFamilySamples.Sample sample: metricFamilySamples.samples) { - /* OpenMetrics specific sample, put in a gauge at the end. */ - if (sample.name.equals(createdName) - || sample.name.equals(gcountName) - || sample.name.equals(gsumName)) { - Collector.MetricFamilySamples omFamily = omFamilies.get(sample.name); - if (omFamily == null) { - omFamily = new Collector.MetricFamilySamples(sample.name, Collector.Type.GAUGE, metricFamilySamples.help, new ArrayList()); - omFamilies.put(sample.name, omFamily); - } - omFamily.samples.add(sample); - continue; - } - writer.write(sample.name); - if (sample.labelNames.size() > 0) { - writer.write('{'); - for (int i = 0; i < sample.labelNames.size(); ++i) { - writer.write(sample.labelNames.get(i)); - writer.write("=\""); - writeEscapedLabelValue(writer, sample.labelValues.get(i)); - writer.write("\","); - } - writer.write('}'); + String createdName = name + "_created"; + String gcountName = name + "_gcount"; + String gsumName = name + "_gsum"; + for (Collector.MetricFamilySamples.Sample sample : metricFamilySamples.samples) { + /* OpenMetrics specific sample, put in a gauge at the end. */ + if (sample.name.equals(createdName) + || sample.name.equals(gcountName) + || sample.name.equals(gsumName)) { + Collector.MetricFamilySamples omFamily = omFamilies.get(sample.name); + if (omFamily == null) { + omFamily = new Collector.MetricFamilySamples(sample.name, Collector.Type.GAUGE, metricFamilySamples.help, new ArrayList()); + omFamilies.put(sample.name, omFamily); + } + omFamily.samples.add(sample); + continue; + } + writer.write(sample.name); + if (sample.labelNames.size() > 0) { + writer.write('{'); + for (int i = 0; i < sample.labelNames.size(); ++i) { + writer.write(sample.labelNames.get(i)); + writer.write("=\""); + writeEscapedLabelValue(writer, sample.labelValues.get(i)); + writer.write("\","); + } + writer.write('}'); + } + writer.write(' '); + writer.write(Collector.doubleToGoString(sample.value)); + if (sample.timestampMs != null) { + writer.write(' '); + writer.write(sample.timestampMs.toString()); + } + writer.write('\n'); + } } - writer.write(' '); - writer.write(Collector.doubleToGoString(sample.value)); - if (sample.timestampMs != null){ - writer.write(' '); - writer.write(sample.timestampMs.toString()); + // Write out any OM-specific samples. + if (!omFamilies.isEmpty()) { + write004(writer, Collections.enumeration(omFamilies.values())); } - writer.write('\n'); - } - } - // Write out any OM-specific samples. - if (!omFamilies.isEmpty()) { - write004(writer, Collections.enumeration(omFamilies.values())); } - } - private static void writeEscapedHelp(Writer writer, String s) throws IOException { - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - switch (c) { - case '\\': - writer.append("\\\\"); - break; - case '\n': - writer.append("\\n"); - break; - default: - writer.append(c); - } + public static void write004(Writer writer, Enumeration mfs, String tags) throws IOException { + Map omFamilies = new TreeMap(); + /* See http://prometheus.io/docs/instrumenting/exposition_formats/ + * for the output format specification. */ + while (mfs.hasMoreElements()) { + Collector.MetricFamilySamples metricFamilySamples = mfs.nextElement(); + String name = metricFamilySamples.name; + writer.write("# HELP "); + writer.write(name); + if (metricFamilySamples.type == Collector.Type.COUNTER) { + writer.write("_total"); + } + if (metricFamilySamples.type == Collector.Type.INFO) { + writer.write("_info"); + } + writer.write(' '); + writeEscapedHelp(writer, metricFamilySamples.help); + writer.write('\n'); + + writer.write("# TYPE "); + writer.write(name); + if (metricFamilySamples.type == Collector.Type.COUNTER) { + writer.write("_total"); + } + if (metricFamilySamples.type == Collector.Type.INFO) { + writer.write("_info"); + } + writer.write(' '); + writer.write(typeString(metricFamilySamples.type)); + writer.write('\n'); + + String createdName = name + "_created"; + String gcountName = name + "_gcount"; + String gsumName = name + "_gsum"; + for (Collector.MetricFamilySamples.Sample sample : metricFamilySamples.samples) { + /* OpenMetrics specific sample, put in a gauge at the end. */ + if (sample.name.equals(createdName) + || sample.name.equals(gcountName) + || sample.name.equals(gsumName)) { + Collector.MetricFamilySamples omFamily = omFamilies.get(sample.name); + if (omFamily == null) { + omFamily = new Collector.MetricFamilySamples(sample.name, Collector.Type.GAUGE, metricFamilySamples.help, new ArrayList()); + omFamilies.put(sample.name, omFamily); + } + omFamily.samples.add(sample); + continue; + } + writer.write(sample.name); + if (sample.labelNames.size() > 0) { + writer.write('{'); + writer.write(""); + if (tags != null) { + writer.write(tags); + writer.write(','); + } + for (int i = 0; i < sample.labelNames.size(); ++i) { + writer.write(sample.labelNames.get(i)); + writer.write("=\""); + writeEscapedLabelValue(writer, sample.labelValues.get(i)); + writer.write("\","); + } + writer.write('}'); + } + writer.write(' '); + writer.write(Collector.doubleToGoString(sample.value)); + if (sample.timestampMs != null) { + writer.write(' '); + writer.write(sample.timestampMs.toString()); + } + writer.write('\n'); + } + } + // Write out any OM-specific samples. + if (!omFamilies.isEmpty()) { + write004(writer, Collections.enumeration(omFamilies.values())); + } } - } - private static void writeEscapedLabelValue(Writer writer, String s) throws IOException { - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - switch (c) { - case '\\': - writer.append("\\\\"); - break; - case '\"': - writer.append("\\\""); - break; - case '\n': - writer.append("\\n"); - break; - default: - writer.append(c); - } + private static void writeEscapedHelp(Writer writer, String s) throws IOException { + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + switch (c) { + case '\\': + writer.append("\\\\"); + break; + case '\n': + writer.append("\\n"); + break; + default: + writer.append(c); + } + } } - } - private static String typeString(Collector.Type t) { - switch (t) { - case GAUGE: - return "gauge"; - case COUNTER: - return "counter"; - case SUMMARY: - return "summary"; - case HISTOGRAM: - return "histogram"; - case GAUGE_HISTOGRAM: - return "histogram"; - case STATE_SET: - return "gauge"; - case INFO: - return "gauge"; - default: - return "untyped"; + private static void writeEscapedLabelValue(Writer writer, String s) throws IOException { + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + switch (c) { + case '\\': + writer.append("\\\\"); + break; + case '\"': + writer.append("\\\""); + break; + case '\n': + writer.append("\\n"); + break; + default: + writer.append(c); + } + } } - } - /** - * Write out the OpenMetrics text version 1.0.0 of the given MetricFamilySamples. - * - * @since 0.10.0 - */ - public static void writeOpenMetrics100(Writer writer, Enumeration mfs) throws IOException { - while(mfs.hasMoreElements()) { - Collector.MetricFamilySamples metricFamilySamples = mfs.nextElement(); - String name = metricFamilySamples.name; + private static String typeString(Collector.Type t) { + switch (t) { + case GAUGE: + return "gauge"; + case COUNTER: + return "counter"; + case SUMMARY: + return "summary"; + case HISTOGRAM: + return "histogram"; + case GAUGE_HISTOGRAM: + return "histogram"; + case STATE_SET: + return "gauge"; + case INFO: + return "gauge"; + default: + return "untyped"; + } + } - writer.write("# TYPE "); - writer.write(name); - writer.write(' '); - writer.write(omTypeString(metricFamilySamples.type)); - writer.write('\n'); + /** + * Write out the OpenMetrics text version 1.0.0 of the given MetricFamilySamples. + * + * @since 0.10.0 + */ + public static void writeOpenMetrics100(Writer writer, Enumeration mfs) throws IOException { + while (mfs.hasMoreElements()) { + Collector.MetricFamilySamples metricFamilySamples = mfs.nextElement(); + String name = metricFamilySamples.name; - if (!metricFamilySamples.unit.isEmpty()) { - writer.write("# UNIT "); - writer.write(name); - writer.write(' '); - writer.write(metricFamilySamples.unit); - writer.write('\n'); - } + writer.write("# TYPE "); + writer.write(name); + writer.write(' '); + writer.write(omTypeString(metricFamilySamples.type)); + writer.write('\n'); - writer.write("# HELP "); - writer.write(name); - writer.write(' '); - writeEscapedLabelValue(writer, metricFamilySamples.help); - writer.write('\n'); - - for (Collector.MetricFamilySamples.Sample sample: metricFamilySamples.samples) { - writer.write(sample.name); - if (sample.labelNames.size() > 0) { - writer.write('{'); - for (int i = 0; i < sample.labelNames.size(); ++i) { - if (i > 0) { - writer.write(","); - } - writer.write(sample.labelNames.get(i)); - writer.write("=\""); - writeEscapedLabelValue(writer, sample.labelValues.get(i)); - writer.write("\""); - } - writer.write('}'); - } - writer.write(' '); - writer.write(Collector.doubleToGoString(sample.value)); - if (sample.timestampMs != null){ - writer.write(' '); - omWriteTimestamp(writer, sample.timestampMs); - } - if (sample.exemplar != null) { - writer.write(" # {"); - for (int i=0; i 0) { - writer.write(","); + if (!metricFamilySamples.unit.isEmpty()) { + writer.write("# UNIT "); + writer.write(name); + writer.write(' '); + writer.write(metricFamilySamples.unit); + writer.write('\n'); } - writer.write(sample.exemplar.getLabelName(i)); - writer.write("=\""); - writeEscapedLabelValue(writer, sample.exemplar.getLabelValue(i)); - writer.write("\""); - } - writer.write("} "); - writer.write(Collector.doubleToGoString(sample.exemplar.getValue())); - if (sample.exemplar.getTimestampMs() != null) { + + writer.write("# HELP "); + writer.write(name); writer.write(' '); - omWriteTimestamp(writer, sample.exemplar.getTimestampMs()); - } + writeEscapedLabelValue(writer, metricFamilySamples.help); + writer.write('\n'); + + for (Collector.MetricFamilySamples.Sample sample : metricFamilySamples.samples) { + writer.write(sample.name); + if (sample.labelNames.size() > 0) { + writer.write('{'); + for (int i = 0; i < sample.labelNames.size(); ++i) { + if (i > 0) { + writer.write(","); + } + writer.write(sample.labelNames.get(i)); + writer.write("=\""); + writeEscapedLabelValue(writer, sample.labelValues.get(i)); + writer.write("\""); + } + writer.write('}'); + } + writer.write(' '); + writer.write(Collector.doubleToGoString(sample.value)); + if (sample.timestampMs != null) { + writer.write(' '); + omWriteTimestamp(writer, sample.timestampMs); + } + if (sample.exemplar != null) { + writer.write(" # {"); + for (int i = 0; i < sample.exemplar.getNumberOfLabels(); i++) { + if (i > 0) { + writer.write(","); + } + writer.write(sample.exemplar.getLabelName(i)); + writer.write("=\""); + writeEscapedLabelValue(writer, sample.exemplar.getLabelValue(i)); + writer.write("\""); + } + writer.write("} "); + writer.write(Collector.doubleToGoString(sample.exemplar.getValue())); + if (sample.exemplar.getTimestampMs() != null) { + writer.write(' '); + omWriteTimestamp(writer, sample.exemplar.getTimestampMs()); + } + } + writer.write('\n'); + } } - writer.write('\n'); - } + writer.write("# EOF\n"); } - writer.write("# EOF\n"); - } - static void omWriteTimestamp(Writer writer, long timestampMs) throws IOException { - writer.write(Long.toString(timestampMs / 1000L)); - writer.write("."); - long ms = timestampMs % 1000; - if (ms < 100) { - writer.write("0"); - } - if (ms < 10) { - writer.write("0"); + static void omWriteTimestamp(Writer writer, long timestampMs) throws IOException { + writer.write(Long.toString(timestampMs / 1000L)); + writer.write("."); + long ms = timestampMs % 1000; + if (ms < 100) { + writer.write("0"); + } + if (ms < 10) { + writer.write("0"); + } + writer.write(Long.toString(timestampMs % 1000)); } - writer.write(Long.toString(timestampMs % 1000)); - } - private static String omTypeString(Collector.Type t) { - switch (t) { - case GAUGE: - return "gauge"; - case COUNTER: - return "counter"; - case SUMMARY: - return "summary"; - case HISTOGRAM: - return "histogram"; - case GAUGE_HISTOGRAM: - return "gaugehistogram"; - case STATE_SET: - return "stateset"; - case INFO: - return "info"; - default: - return "unknown"; + private static String omTypeString(Collector.Type t) { + switch (t) { + case GAUGE: + return "gauge"; + case COUNTER: + return "counter"; + case SUMMARY: + return "summary"; + case HISTOGRAM: + return "histogram"; + case GAUGE_HISTOGRAM: + return "gaugehistogram"; + case STATE_SET: + return "stateset"; + case INFO: + return "info"; + default: + return "unknown"; + } } - } } diff --git a/simpleclient_httpserver/src/main/java/io/prometheus/client/exporter/HTTPServer.java b/simpleclient_httpserver/src/main/java/io/prometheus/client/exporter/HTTPServer.java index d6afdcd69..a08775b49 100644 --- a/simpleclient_httpserver/src/main/java/io/prometheus/client/exporter/HTTPServer.java +++ b/simpleclient_httpserver/src/main/java/io/prometheus/client/exporter/HTTPServer.java @@ -12,6 +12,7 @@ import java.nio.charset.Charset; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -19,6 +20,7 @@ import java.util.concurrent.FutureTask; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; import java.util.zip.GZIPOutputStream; import com.sun.net.httpserver.HttpExchange; @@ -34,7 +36,7 @@ * HTTPServer server = new HTTPServer(1234); * } * - * */ + */ public class HTTPServer { static { @@ -49,8 +51,7 @@ public class HTTPServer { private static class LocalByteArray extends ThreadLocal { @Override - protected ByteArrayOutputStream initialValue() - { + protected ByteArrayOutputStream initialValue() { return new ByteArrayOutputStream(1 << 20); } } @@ -62,9 +63,16 @@ public static class HTTPMetricHandler implements HttpHandler { private final CollectorRegistry registry; private final LocalByteArray response = new LocalByteArray(); private final static String HEALTHY_RESPONSE = "Exporter is Healthy."; + private String tagsString; HTTPMetricHandler(CollectorRegistry registry) { - this.registry = registry; + this.registry = registry; + Map tags = registry.getGlobalTags(); + if (tags != null && tags.size() > 0) { + tagsString = tags.entrySet().stream().map((e) -> + e.getKey() + "=\"" + e.getValue()+"\"" + ).collect(Collectors.joining(",")); + } } @Override @@ -81,7 +89,7 @@ public void handle(HttpExchange t) throws IOException { String contentType = TextFormat.chooseContentType(t.getRequestHeaders().getFirst("Accept")); t.getResponseHeaders().set("Content-Type", contentType); TextFormat.writeFormat(contentType, osw, - registry.filteredMetricFamilySamples(parseQuery(query))); + registry.filteredMetricFamilySamples(parseQuery(query)),tagsString); } osw.close(); diff --git a/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Encoder.java b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Encoder.java index 87eea7200..0b1e6bee4 100644 --- a/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Encoder.java +++ b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Encoder.java @@ -30,8 +30,9 @@ public class Encoder { private final String nid; private StringBuilder builder = new StringBuilder(); private final Map tags; - private String tagStr; - Encoder(String url, int batchSize, long stepS, String nid,Map tags) { + private String tagStr; + + Encoder(String url, int batchSize, long stepS, String nid, Map tags) { this.stepS = stepS; this.nid = nid; this.url = url; @@ -39,15 +40,14 @@ public class Encoder { this.batchSize = batchSize; this.samples = new ArrayList<>(batchSize); this.tags = tags; - this.tagStr = this.tags.entrySet().stream().map((e)->{ - return escapeJson(e.getKey())+"="+escapeJson(e.getValue()); + this.tagStr = this.tags.entrySet().stream().map((e) -> { + return escapeJson(e.getKey()) + "=" + escapeJson(e.getValue()); }).collect(Collectors.joining(",")); } - void add(Collector.MetricFamilySamples.Sample sample) { this.samples.add(sample); if (this.samples.size() == 100) { @@ -117,8 +117,12 @@ private void send() { try { HttpResponse response = client.execute(post); final HttpEntity entity = response.getEntity(); - System.out.println(response.getStatusLine()); - System.out.println(EntityUtils.toString(entity)); + String resp = EntityUtils.toString(entity); + if (!resp.startsWith("{\"dat\":\"ok\"")) { + logger.log(Level.WARNING, "nightingale get response"+resp+" from " + this.url ); + } + + System.out.println(); if (entity != null) { try (final InputStream inStream = entity.getContent()) { //inStream.read(); diff --git a/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Metrics.java b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Metrics.java index 0ec72f2aa..cba38daba 100644 --- a/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Metrics.java +++ b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Metrics.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.lang.management.ManagementFactory; +import java.net.InetSocketAddress; import java.util.HashMap; import java.util.Map; @@ -33,6 +34,7 @@ public Metrics(String bu, String project, String app, Map global podName = ManagementFactory.getRuntimeMXBean().getName(); } this.tags.put("pid", podName); + this.registry.setGlobalTags(this.tags); } public void StartPushLoop(int interval) { @@ -45,7 +47,7 @@ public void StartPushLoop(int interval, String url) { } public HTTPServer StartPullHttpServer(int port) throws IOException { - HTTPServer server = new HTTPServer(port); + HTTPServer server = new HTTPServer(new InetSocketAddress(port), this.registry, false); return server; } diff --git a/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java b/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java index afd7b3732..f6d410857 100644 --- a/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java +++ b/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java @@ -9,6 +9,7 @@ import io.prometheus.client.CollectorRegistry; import io.prometheus.client.Gauge; +import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -47,7 +48,8 @@ public void testPushLoop(){ tags.put("test","test2"); Metrics metric= new Metrics("infra","metrics","test", tags); Gauge labels = Gauge.build().name("test_test2").help("help").labelNames("l").register(); - labels.labels("fo*o").inc(); + labels.labels("foo").inc(); + labels.labels("foo").inc(); metric.StartPushLoop(1,"http://10.110.20.100:8080/api/transfer/push"); try { Thread.sleep(1000*60); @@ -55,4 +57,18 @@ public void testPushLoop(){ e.printStackTrace(); } } + @Test + public void testExport() throws IOException { + Map tags=new HashMap<>(); + tags.put("test","test2"); + Metrics metric= new Metrics("infra","metrics","test", tags); + Gauge labels = Gauge.build().name("test_test2").help("help").labelNames("l","l2").register(); + labels.labels("foo","f2").inc(); + metric.StartPullHttpServer(9000); + try { + Thread.sleep(1000*60); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } From 587ab680c517e1a5ee3d9425e02a8da217f705cf Mon Sep 17 00:00:00 2001 From: SH98011ML Date: Wed, 25 Aug 2021 14:41:15 +0800 Subject: [PATCH 4/6] update --- .../main/java/io/prometheus/client/sdk/Encoder.java | 2 -- .../main/java/io/prometheus/client/sdk/Metrics.java | 5 +++++ .../io/prometheus/client/sdk/NightingaleTest.java | 11 ++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Encoder.java b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Encoder.java index 0b1e6bee4..f0acf6c7d 100644 --- a/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Encoder.java +++ b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Encoder.java @@ -121,8 +121,6 @@ private void send() { if (!resp.startsWith("{\"dat\":\"ok\"")) { logger.log(Level.WARNING, "nightingale get response"+resp+" from " + this.url ); } - - System.out.println(); if (entity != null) { try (final InputStream inStream = entity.getContent()) { //inStream.read(); diff --git a/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Metrics.java b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Metrics.java index cba38daba..5dfbbf67d 100644 --- a/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Metrics.java +++ b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Metrics.java @@ -18,6 +18,11 @@ public Metrics(String bu, String project, String app, Map global } + public Metrics(String bu, String project, String app) { + this(bu, project, app, null); + + } + public Metrics(String bu, String project, String app, Map globalTags, CollectorRegistry registry) { this.registry = registry; this.tags = new HashMap<>(); diff --git a/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java b/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java index f6d410857..97ad348d0 100644 --- a/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java +++ b/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java @@ -44,10 +44,9 @@ public void testPush() throws Exception { } @Test public void testPushLoop(){ - Map tags=new HashMap<>(); - tags.put("test","test2"); - Metrics metric= new Metrics("infra","metrics","test", tags); - Gauge labels = Gauge.build().name("test_test2").help("help").labelNames("l").register(); + Metrics metric= new Metrics("infra","metrics","test"); + Gauge labels = Gauge.build().name("test_test3").help("help").labelNames("l").register(); + labels.labels("foo").inc(); labels.labels("foo").inc(); labels.labels("foo").inc(); metric.StartPushLoop(1,"http://10.110.20.100:8080/api/transfer/push"); @@ -59,9 +58,7 @@ public void testPushLoop(){ } @Test public void testExport() throws IOException { - Map tags=new HashMap<>(); - tags.put("test","test2"); - Metrics metric= new Metrics("infra","metrics","test", tags); + Metrics metric= new Metrics("infra","metrics","test"); Gauge labels = Gauge.build().name("test_test2").help("help").labelNames("l","l2").register(); labels.labels("foo","f2").inc(); metric.StartPullHttpServer(9000); From a6bb686e92a8f497e08acf7e29f00e9b7dbf7c3d Mon Sep 17 00:00:00 2001 From: SH98011ML Date: Wed, 25 Aug 2021 15:50:49 +0800 Subject: [PATCH 5/6] update --- .../io/prometheus/client/sdk/Encoder.java | 41 +++++++++++-------- .../io/prometheus/client/sdk/Nightingale.java | 2 +- .../client/sdk/NightingaleTest.java | 13 +++--- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Encoder.java b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Encoder.java index f0acf6c7d..5fc105ee7 100644 --- a/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Encoder.java +++ b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Encoder.java @@ -40,9 +40,12 @@ public class Encoder { this.batchSize = batchSize; this.samples = new ArrayList<>(batchSize); this.tags = tags; - this.tagStr = this.tags.entrySet().stream().map((e) -> { - return escapeJson(e.getKey()) + "=" + escapeJson(e.getValue()); - }).collect(Collectors.joining(",")); + if (this.tags!=null){ + this.tagStr = this.tags.entrySet().stream().map((e) -> { + return escapeJson(e.getKey()) + "=" + escapeJson(e.getValue()); + }).collect(Collectors.joining(",")); + } + } @@ -50,9 +53,6 @@ public class Encoder { void add(Collector.MetricFamilySamples.Sample sample) { this.samples.add(sample); - if (this.samples.size() == 100) { - send(); - } } @@ -60,8 +60,10 @@ protected Long generateTimestamp() { return System.currentTimeMillis() / 1000; } - void writeMessage(StringBuilder sb, Collector.MetricFamilySamples.Sample sample) { - Long timestamp = generateTimestamp(); + void writeMessage(StringBuilder sb, Collector.MetricFamilySamples.Sample sample,Long timestamp) { + if (sample.labelNames.size() != sample.labelValues.size()) { + return; + } String type = "GAUGE"; String name = sample.name; sb.append("{\"").append("timestamp").append("\":").append(timestamp) @@ -92,24 +94,27 @@ void end() { send(); } - String marshalBatch() { + String marshalBatch(Long timestamp) { + builder.append("["); - this.samples.stream().peek(sample -> { - writeMessage(builder, sample); - }).skip(1).forEach(sample -> { - builder.append(",\n"); - writeMessage(builder, sample); - }); + int len = this.samples.size(); + for (int i = 0; i < len; i++) { + if (i != 0) { + builder.append(",\n"); + } + writeMessage(builder, this.samples.get(i),timestamp); + } builder.append("]"); String body = builder.toString(); builder.setLength(0); + this.samples.clear(); return body; } private void send() { + Long timestamp = generateTimestamp(); if (this.samples.size() > 0) { - String body = marshalBatch(); - this.samples.clear(); + String body = marshalBatch(timestamp); HttpPost post = new HttpPost(this.url); StringEntity requestEntity = new StringEntity( body, ContentType.APPLICATION_JSON); @@ -119,7 +124,7 @@ private void send() { final HttpEntity entity = response.getEntity(); String resp = EntityUtils.toString(entity); if (!resp.startsWith("{\"dat\":\"ok\"")) { - logger.log(Level.WARNING, "nightingale get response"+resp+" from " + this.url ); + logger.log(Level.WARNING, "nightingale get response" + resp + " from " + this.url); } if (entity != null) { try (final InputStream inStream = entity.getContent()) { diff --git a/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Nightingale.java b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Nightingale.java index 2312a9603..feb6553fe 100644 --- a/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Nightingale.java +++ b/simpleclient_sdk/src/main/java/io/prometheus/client/sdk/Nightingale.java @@ -14,7 +14,7 @@ public class Nightingale { private final Encoder encoder; public Nightingale(String url, int batchSize, int interval, String tenantId, Map globalTags) { - this.encoder = new Encoder(url, 100, 10, tenantId,globalTags); + this.encoder = new Encoder(url, 100, interval, tenantId,globalTags); } public Nightingale(String url,int interval, Map globalTags) { diff --git a/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java b/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java index 97ad348d0..c658c718a 100644 --- a/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java +++ b/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java @@ -3,12 +3,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; -import io.prometheus.client.Collector; +import io.prometheus.client.*; import org.junit.Test; -import io.prometheus.client.CollectorRegistry; -import io.prometheus.client.Gauge; - import java.io.IOException; import java.util.Collections; import java.util.HashMap; @@ -29,7 +26,7 @@ public void testMarshalBatch(){ encoder.add(sample); } } - String body=encoder.marshalBatch(); + String body=encoder.marshalBatch(2212111l); System.out.println(body); } @Test @@ -49,6 +46,12 @@ public void testPushLoop(){ labels.labels("foo").inc(); labels.labels("foo").inc(); labels.labels("foo").inc(); + Histogram s= Histogram.build().name("histogram1").help("help").labelNames("sl").register(); + s.labels("l1").observe(0.88); + s.labels("l1").observe(0.77); + s.labels("l2").observe(0.66); + Gauge labels2 = Gauge.build().name("test_test4").help("help").labelNames("l").register(); + labels2.labels("foo").inc(); metric.StartPushLoop(1,"http://10.110.20.100:8080/api/transfer/push"); try { Thread.sleep(1000*60); From b366fc463a027b39dd55c0892f9d54ca280bbbda Mon Sep 17 00:00:00 2001 From: SH98011ML Date: Wed, 25 Aug 2021 15:53:31 +0800 Subject: [PATCH 6/6] update --- .../test/java/io/prometheus/client/sdk/NightingaleTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java b/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java index c658c718a..ab473f52f 100644 --- a/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java +++ b/simpleclient_sdk/src/test/java/io/prometheus/client/sdk/NightingaleTest.java @@ -64,6 +64,10 @@ public void testExport() throws IOException { Metrics metric= new Metrics("infra","metrics","test"); Gauge labels = Gauge.build().name("test_test2").help("help").labelNames("l","l2").register(); labels.labels("foo","f2").inc(); + Histogram s= Histogram.build().name("histogram1").help("help").labelNames("sl").register(); + s.labels("l1").observe(0.88); + s.labels("l1").observe(0.77); + s.labels("l2").observe(0.66); metric.StartPullHttpServer(9000); try { Thread.sleep(1000*60);