Skip to content

Commit c0d1b97

Browse files
authored
Add dropwizard metrics reporter for grafana cloud metrics (StubbornJava#75)
* Add dropwizard metrics reporter for grafana cloud metrics
1 parent 7006c16 commit c0d1b97

File tree

9 files changed

+194
-26
lines changed

9 files changed

+194
-26
lines changed
Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,32 @@
11
$ANSIBLE_VAULT;1.1;AES256
2-
62383035313961363234303436316238633235343139323264356462393132303962383033623136
3-
3463383832376634343961373932646132666663643732650a333763393432633635303735393163
4-
34623936316439646666303663656462376234646561626635353465396332623933346132386664
5-
3365613034663366660a666133333263326230373235623635633732333661656636383938663863
6-
31643339653664663766303063353062356230313239663030626233323434346631663137623465
7-
65353935346530333734656364656362376234623935636633363638353063653534353031306430
8-
31393233353561616634346231343265663132306366303035313466653036653232306433343564
9-
35323736316462323664666434643938623636373131623635353365376336346538353538616266
10-
33666662343638663464323661366339346364633232333335643464393066363832333830303132
11-
38626130613939373161393266343837343161336130613162333036376562353261313538646666
12-
33306630323664363131303032633131316466333366363465306464626566386336656136663939
13-
36613834653638323463373534376365346131613838366130663630626431643530386434373133
14-
35663763656364363237366666323231386130653365386263623463656232343239373362386530
15-
32393832666333383337336261393332373934343262613066353931393839306639376134623334
16-
61616262353362393931656536346663346164333064313532383035666438626163643733333137
17-
31383263626666316130336536323761646232326532633739623431316134383266623435636134
18-
38346333303664326237636236646161303761326464633635643763336134636566396166356263
19-
64636639323338326366376335636131373532663936623763346565383631366166396332386535
20-
376464376465633439326131623036343763
2+
61313238636666353031616265616533666263613030613261623865386636393664323631366139
3+
6461383234653263656461373164396237313432323866320a653533653164323064613633613234
4+
37373161626138343437333462306463313265633161346665653430373765663632656166373237
5+
6430626430303336340a383231316365633836623661636534303338303338653339353762643934
6+
37376331323864616164643262366334656538643331633935353866616236626165343337323032
7+
33366166383261623039613338373237336332623532616632363363636437383737343461633066
8+
62333733666265643866373130666265656138393163383838633861343766323137616662646631
9+
35386363666430306130323835376534623462613739366431613638653036623361653461303965
10+
63303334373235323931306336316631393830663937393832356437343430616466643664323565
11+
32663638646365303866326161643336633939316237353961303132376665613666396332613938
12+
61346238383366633463623362626637333533323239616663343663633064386536376362666638
13+
62356661623461363834643031376131626536353139353439353734346365343035356463306565
14+
65626465313738626562393866343761636638343066316437373737333136366639316333656431
15+
63383332323137356463303262646533383735636631353065646131323834656237336137386235
16+
31323438656164646531346333613538663061393266323630393530386233336236353731656238
17+
38616535363333336439336531353064623564323464316130633362353131313961613938633339
18+
34363437343766313661636239346165323831333732323232363466663231626236613132373266
19+
32373531323431316534663564353537663061333835336662626463616163303433303833306437
20+
64353337643731343839376566356639333630646164393939653165303636616662393236363362
21+
35643138316661656430646138353630643332653936323861646634663435393638623864623261
22+
64323536303263663361303663376662356634653066376635336464376133356633333632666164
23+
31613561346262343731366133643339613833386133626638613534313265393038313736643964
24+
33613339656562383330306138643634363462633632613331636232633762373134653736353863
25+
65316239333836643734623831396537383563306165616362326231613539626130623762613832
26+
64373834303266366339653738343738346431623562393233323434383931323036373065323434
27+
31653632383535383435393664323833383263613735353365633264396163333334376533393933
28+
37363336643765303936653530383738646662326332643765613365386433383366636331373361
29+
64303432323061646464623539643061363364393338643465613431356461623532623031306633
30+
35333233333734643666386565333831373239356261623465393163663933376637626436393166
31+
61303436306262386365346530333531626635323534633634376665313165396538643632396264
32+
653335353635343964336661643131393839

ansible/inventories/production/group_vars/stubbornjava/webserver_vars.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,9 @@
77
github:
88
client_id: "{{_vault['github']['client_id']}}"
99
client_secret: "{{_vault['github']['client_secret']}}"
10+
11+
metrics:
12+
graphite:
13+
host: "{{_vault.metrics.graphite.host}}"
14+
grafana:
15+
api_key: "{{_vault.metrics.grafana.api_key}}"

ansible/roles/apps/jvm_app_base/templates/secure.conf.j2

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,8 @@ github {
88
clientId="{{github['client_id']}}"
99
clientSecret="{{github['client_secret']}}"
1010
}
11+
12+
metrics {
13+
graphite.host="{{metrics.graphite.host}}"
14+
grafana.api_key="{{metrics.grafana.api_key}}"
15+
}

gradle/dependencies.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ext {
66
slf4j : '1.7.25', // Logging
77
logback : '1.2.3', // Logging
88
undertow : '1.4.20.Final',// Webserver
9-
metrics : '3.2.5', // Metrics
9+
metrics : '4.0.2', // Metrics
1010
guava : '23.3-jre', // Common / Helper libraries
1111
typesafeConfig : '1.3.2', // Configuration
1212
handlebars : '4.0.6', // HTML templating
@@ -42,6 +42,7 @@ ext {
4242
metricsJson : "io.dropwizard.metrics:metrics-json:$versions.metrics",
4343
metricsLogback : "io.dropwizard.metrics:metrics-logback:$versions.metrics",
4444
metricsHealthchecks : "io.dropwizard.metrics:metrics-healthchecks:$versions.metrics",
45+
metricsGraphite : "io.dropwizard.metrics:metrics-graphite:$versions.metrics",
4546
undertowCore : "io.undertow:undertow-core:$versions.undertow",
4647
slf4j : "org.slf4j:slf4j-api:$versions.slf4j",
4748
slf4jLog4j : "org.slf4j:log4j-over-slf4j:$versions.slf4j",

stubbornjava-common/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ dependencies {
1616
compile libs.metricsJson
1717
compile libs.metricsLogback
1818
compile libs.metricsHealthchecks
19+
compile libs.metricsGraphite
1920
compile libs.guava
2021
compile libs.typesafeConfig
2122
compile libs.handlebars
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package com.stubbornjava.common;
2+
3+
import java.io.IOException;
4+
import java.util.List;
5+
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
9+
import com.codahale.metrics.graphite.GraphiteSender;
10+
import com.fasterxml.jackson.annotation.JsonProperty;
11+
import com.google.common.collect.Lists;
12+
13+
import okhttp3.MediaType;
14+
import okhttp3.OkHttpClient;
15+
import okhttp3.Request;
16+
import okhttp3.RequestBody;
17+
import okhttp3.logging.HttpLoggingInterceptor;
18+
import okhttp3.logging.HttpLoggingInterceptor.Level;
19+
20+
class GraphiteHttpSender implements GraphiteSender {
21+
private static final Logger log = LoggerFactory.getLogger(GraphiteHttpSender.class);
22+
23+
private final OkHttpClient client;
24+
private final String host;
25+
private final List<GraphiteMetric> metrics = Lists.newArrayList();
26+
27+
public GraphiteHttpSender(OkHttpClient client, String host, String apiKey) {
28+
this.client = client.newBuilder()
29+
.addInterceptor(HttpClient.getHeaderInterceptor("Authorization", "Bearer " + apiKey))
30+
.build();
31+
this.host = host;
32+
}
33+
34+
@Override
35+
public void connect() throws IllegalStateException, IOException {
36+
// Just no op here
37+
}
38+
39+
@Override
40+
public void close() throws IOException {
41+
// no op
42+
}
43+
44+
@Override
45+
public void send(String name, String value, long timestamp) throws IOException {
46+
metrics.add(new GraphiteMetric(name, 10, Double.parseDouble(value), timestamp));
47+
}
48+
49+
@Override
50+
public void flush() throws IOException {
51+
Request request = new Request.Builder()
52+
.url(host + "/metrics")
53+
.post(RequestBody.create(MediaType.parse("application/json"), Json.serializer().toByteArray(metrics)))
54+
.build();
55+
String response = Retry.retryUntilSuccessfulWithBackoff(() -> client.newCall(request).execute());
56+
metrics.clear();
57+
}
58+
59+
@Override
60+
public boolean isConnected() {
61+
// TODO Auto-generated method stub
62+
return false;
63+
}
64+
65+
@Override
66+
public int getFailures() {
67+
// TODO Auto-generated method stub
68+
return 0;
69+
}
70+
71+
private static final HttpLoggingInterceptor getLogger(Level level) {
72+
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor((msg) -> {
73+
log.debug(msg);
74+
});
75+
loggingInterceptor.setLevel(level);
76+
return loggingInterceptor;
77+
}
78+
79+
private static final class GraphiteMetric {
80+
private final String name;
81+
private final int interval;
82+
private final double value;
83+
private final long time;
84+
85+
public GraphiteMetric(@JsonProperty("name") String name,
86+
@JsonProperty("interval") int interval,
87+
@JsonProperty("value") double value,
88+
@JsonProperty("time") long time) {
89+
this.name = name;
90+
this.interval = interval;
91+
this.value = value;
92+
this.time = time;
93+
}
94+
95+
public String getName() {
96+
return name;
97+
}
98+
public int getInterval() {
99+
return interval;
100+
}
101+
public double getValue() {
102+
return value;
103+
}
104+
public long getTime() {
105+
return time;
106+
}
107+
}
108+
}

stubbornjava-common/src/main/java/com/stubbornjava/common/Metrics.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,27 @@
44
import java.util.concurrent.ConcurrentHashMap;
55
import java.util.concurrent.TimeUnit;
66

7+
import org.slf4j.Logger;
78
import org.slf4j.LoggerFactory;
89

10+
import com.amazonaws.util.EC2MetadataUtils;
911
import com.codahale.metrics.Meter;
1012
import com.codahale.metrics.Metric;
13+
import com.codahale.metrics.MetricFilter;
1114
import com.codahale.metrics.MetricRegistry;
1215
import com.codahale.metrics.Timer;
16+
import com.codahale.metrics.graphite.GraphiteReporter;
1317
import com.codahale.metrics.jvm.CachedThreadStatesGaugeSet;
1418
import com.codahale.metrics.jvm.GarbageCollectorMetricSet;
1519
import com.codahale.metrics.jvm.MemoryUsageGaugeSet;
1620
import com.codahale.metrics.logback.InstrumentedAppender;
1721

18-
import ch.qos.logback.classic.Logger;
1922
import ch.qos.logback.classic.LoggerContext;
23+
import okhttp3.OkHttpClient;
2024
// {{start:metrics}}
2125
public class Metrics {
26+
private static final Logger log = LoggerFactory.getLogger(Metrics.class);
27+
2228
/*
2329
* Use a concurrent map to cache metrics we generate on the fly.
2430
* For example we generate status code metrics on the fly.
@@ -33,12 +39,29 @@ public class Metrics {
3339

3440
// Logback metrics
3541
final LoggerContext factory = (LoggerContext) LoggerFactory.getILoggerFactory();
36-
final Logger root = factory.getLogger(Logger.ROOT_LOGGER_NAME);
42+
final ch.qos.logback.classic.Logger root = factory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
3743
final InstrumentedAppender metrics = new InstrumentedAppender(registry);
3844
metrics.setContext(root.getLoggerContext());
3945
metrics.start();
4046
root.addAppender(metrics);
4147

48+
49+
// Graphite reporter to Grafana Cloud
50+
OkHttpClient client = new OkHttpClient.Builder()
51+
//.addNetworkInterceptor(HttpClient.getLoggingInterceptor())
52+
.build();
53+
54+
String graphiteHost = Configs.properties().getString("metrics.graphite.host");
55+
String grafanaApiKey = Configs.properties().getString("metrics.grafana.api_key");
56+
final GraphiteHttpSender graphite = new GraphiteHttpSender(client, graphiteHost, grafanaApiKey);
57+
final GraphiteReporter reporter = GraphiteReporter.forRegistry(registry)
58+
.prefixedWith(metricPrefix("stubbornjava"))
59+
.convertRatesTo(TimeUnit.SECONDS)
60+
.convertDurationsTo(TimeUnit.MILLISECONDS)
61+
.filter(MetricFilter.ALL)
62+
.build(graphite);
63+
reporter.start(10, TimeUnit.SECONDS);
64+
4265
// Register reporters here.
4366
}
4467

@@ -63,5 +86,17 @@ public static Meter meter(String first, String... keys) {
6386
return metric;
6487
});
6588
}
89+
90+
private static String metricPrefix(String app) {
91+
Env env = Env.get();
92+
String host = env == Env.LOCAL ? "localhost" : getHost();
93+
String prefix = MetricRegistry.name(app, env.getName(), host);
94+
log.info("Setting Metrics Prefix {}", prefix);
95+
return prefix;
96+
}
97+
98+
private static String getHost() {
99+
return EC2MetadataUtils.getLocalHostName().split("\\.")[0];
100+
}
66101
}
67102
// {{end:metrics}}

stubbornjava-common/src/main/java/com/stubbornjava/common/undertow/handlers/CustomHandlers.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public static StatusCodeHandler statusCodeMetrics(HttpHandler next) {
9090
}
9191

9292
public static TimingHttpHandler timed(String name, HttpHandler next) {
93-
return new TimingHttpHandler(next, name);
93+
return new TimingHttpHandler(next, "routes." + name);
9494
}
9595

9696
public static void metrics(HttpServerExchange exchange) {

stubbornjava-webapp/src/main/java/com/stubbornjava/webapp/StubbornJavaBootstrap.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ public class StubbornJavaBootstrap {
1414

1515
public static Config getConfig() {
1616
Config config = Configs.newBuilder()
17-
.withOptionalRelativeFile("./secure.conf")
18-
.withResource("application." + Env.get().getName() + ".conf")
19-
.withResource("application.conf")
17+
.withOptionalRelativeFile("/secure.conf")
18+
.withResource("sjweb." + Env.get().getName() + ".conf")
19+
.withResource("sjweb.conf")
2020
.build();
2121
logger.debug(Json.serializer().toPrettyString(Configs.asMap(config)));
2222
return config;

0 commit comments

Comments
 (0)