Skip to content

Commit

Permalink
Restructure new relic events (fixes #476)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Schneider committed Feb 27, 2018
1 parent 657f3d7 commit 59e8bfd
Showing 1 changed file with 96 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
Expand All @@ -42,6 +43,7 @@
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
import static java.util.stream.StreamSupport.stream;

/**
* Publishes metrics to New Relic Insights.
Expand Down Expand Up @@ -82,6 +84,16 @@ protected void publish() {
return writeTimer((FunctionTimer) meter);
} else if (meter instanceof DistributionSummary) {
return writeSummary((DistributionSummary) meter);
} else if (meter instanceof TimeGauge) {
return writeGauge((TimeGauge) meter);
} else if (meter instanceof Gauge) {
return writeGauge((Gauge) meter);
} else if (meter instanceof Counter) {
return writeCounter((Counter) meter);
} else if (meter instanceof FunctionCounter) {
return writeCounter((FunctionCounter) meter);
} else if (meter instanceof LongTaskTimer) {
return writeLongTaskTimer((LongTaskTimer) meter);
} else {
return writeMeter(meter);
}
Expand All @@ -106,67 +118,93 @@ protected void publish() {
}
}

private Stream<String> writeSummary(DistributionSummary summary) {
final Stream.Builder<String> events = Stream.builder();
Meter.Id id = summary.getId();
HistogramSnapshot t = summary.takeSnapshot(false);

events.add(event(id, "count", t.count()));
events.add(event(id, "sum", t.total()));
events.add(event(id, "avg", t.mean()));
events.add(event(id, "max", t.max()));
private Stream<String> writeLongTaskTimer(LongTaskTimer ltt) {
return Stream.of(
event(ltt.getId(),
new Attribute("activeTasks", ltt.activeTasks()),
new Attribute("duration", ltt.duration(getBaseTimeUnit())))
);
}

return events.build();
private Stream<String> writeCounter(FunctionCounter counter) {
return Stream.of(event(counter.getId(), new Attribute("throughput", counter.count())));
}

private Stream<String> writeTimer(Timer timer) {
final Stream.Builder<String> events = Stream.builder();
Meter.Id id = timer.getId();
HistogramSnapshot t = timer.takeSnapshot(false);
private Stream<String> writeCounter(Counter counter) {
return Stream.of(event(counter.getId(), new Attribute("throughput", counter.count())));
}

events.add(event(id, "count", t.count()));
events.add(event(id, "sum", t.total(getBaseTimeUnit())));
events.add(event(id, "avg", t.mean(getBaseTimeUnit())));
events.add(event(id, "max", t.max(getBaseTimeUnit())));
private Stream<String> writeGauge(Gauge gauge) {
return Stream.of(event(gauge.getId(), new Attribute("value", gauge.value())));
}

return events.build();
private Stream<String> writeGauge(TimeGauge gauge) {
return Stream.of(event(gauge.getId(), new Attribute("value", gauge.value(getBaseTimeUnit()))));
}

private Stream<String> writeTimer(FunctionTimer timer) {
final Stream.Builder<String> events = Stream.builder();
Meter.Id id = timer.getId();
private Stream<String> writeSummary(DistributionSummary summary) {
HistogramSnapshot t = summary.takeSnapshot(false);
return Stream.of(
event(summary.getId(),
new Attribute("count", t.count()),
new Attribute("avg", t.mean()),
new Attribute("total", t.total()),
new Attribute("max", t.max())
)
);
}

events.add(event(id, "count", timer.count()));
events.add(event(id, "sum", timer.count()));
events.add(event(id, "mean", timer.mean(getBaseTimeUnit())));
private Stream<String> writeTimer(Timer timer) {
HistogramSnapshot t = timer.takeSnapshot(false);
return Stream.of(event(timer.getId(),
new Attribute("count", t.count()),
new Attribute("avg", t.mean(getBaseTimeUnit())),
new Attribute("totalTime", t.total(getBaseTimeUnit())),
new Attribute("max", t.max(getBaseTimeUnit()))
));
}

return events.build();
private Stream<String> writeTimer(FunctionTimer timer) {
return Stream.of(
event(timer.getId(),
new Attribute("count", timer.count()),
new Attribute("avg", timer.mean(getBaseTimeUnit())),
new Attribute("totalTime", timer.totalTime(getBaseTimeUnit()))
)
);
}

private Stream<String> writeMeter(Meter meter) {
final Stream.Builder<String> events = Stream.builder();
for (Measurement measurement : meter.measure()) {
events.add(event(meter.getId(), measurement.getStatistic().toString().toLowerCase(), measurement.getValue()));
}
return events.build();
return Stream.of(
event(meter.getId(),
stream(meter.measure().spliterator(), false)
.map(measure -> new Attribute(measure.getStatistic().getTagValueRepresentation(), measure.getValue()))
.toArray(Attribute[]::new)
)
);
}

private String event(Meter.Id id, String statistic, Number value, String... additionalTags) {
private String event(Meter.Id id, Attribute... attributes) {
return event(id, Tags.empty(), attributes);
}

StringBuilder additionalTagsJson = new StringBuilder();
for (int i = 0; i < additionalTags.length; i += 2) {
additionalTagsJson.append(",\"").append(additionalTags[i]).append("\":\"").append(additionalTags[i + 1]).append("\"");
}
private String event(Meter.Id id, Iterable<Tag> extraTags, Attribute... attributes) {
StringBuilder tagsJson = new StringBuilder();

for (Tag tag : getConventionTags(id)) {
additionalTagsJson.append(",\"").append(tag.getKey()).append("\":\"").append(tag.getValue()).append("\"");
tagsJson.append(",\"").append(tag.getKey()).append("\":\"").append(tag.getValue()).append("\"");
}

return "{\"eventType\":\"" + getConventionName(id) + "\",\"statistic\":\"" + statistic + "\"," +
"\"value\":" + Double.toString(value.doubleValue()) + additionalTagsJson.toString() + "}";
NamingConvention convention = config().namingConvention();
for (Tag tag : extraTags) {
tagsJson.append(",\"").append(convention.tagKey(tag.getKey())).append("\":\"").append(convention.tagValue(tag.getValue())).append("\"");
}

return "{\"eventType\":\"" + getConventionName(id) + "\"" +
Arrays.stream(attributes).map(attr -> ",\"" + attr.getName() + "\":" + Double.toString(attr.getValue().doubleValue()))
.collect(Collectors.joining("")) + tagsJson.toString() + "}";
}

// TODO HTTP/1.1 Persistent connections are supported
private void sendEvents(URL insightsEndpoint, List<String> events) {

HttpURLConnection con = null;
Expand Down Expand Up @@ -221,4 +259,22 @@ private void quietlyCloseUrlConnection(@Nullable HttpURLConnection con) {
protected TimeUnit getBaseTimeUnit() {
return TimeUnit.SECONDS;
}

private class Attribute {
private final String name;
private final Number value;

private Attribute(String name, Number value) {
this.name = name;
this.value = value;
}

public String getName() {
return name;
}

public Number getValue() {
return value;
}
}
}

0 comments on commit 59e8bfd

Please sign in to comment.