Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: newrelic/dropwizard-metrics-newrelic
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.6.0
Choose a base ref
...
head repository: newrelic/dropwizard-metrics-newrelic
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.7.0
Choose a head ref
  • 8 commits
  • 15 files changed
  • 2 contributors

Commits on May 6, 2022

  1. Issue #89 - implement transformer customizers

    Add functional interfaces to allow custom metric names and attributes.
    
    Expand testing for backwards compatibility and new codepaths.
    
    Update README.md with an example.
    Ch4ni committed May 6, 2022
    Copy the full SHA
    d02f12d View commit details
  2. Copy the full SHA
    ea1f5cc View commit details

Commits on May 31, 2022

  1. Update CHANGELOG.md

    jasonjkeller authored May 31, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e08c16b View commit details

Commits on Jun 1, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    199172d View commit details
  2. Bump to next version

    jasonjkeller authored Jun 1, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0bb7d41 View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6cb84c0 View commit details
  4. Merge pull request #92 from eurythmia/custom_transformers

    Customizable Transformers
    jasonjkeller authored Jun 1, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    7f2b88e View commit details
  5. Fix typo in readme

    jasonjkeller authored Jun 1, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    bcb0308 View commit details
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.6.0] - 2022-05-31
- Update to telemetry SDK 0.13.2 and fix API breakage.
- Clean up readme examples.

## [0.5.0] - 2020-06-30
- Upgrade to Telemetry SDK 0.6.1
- Allow URI override to include or omit the full endpoint path component.
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -64,6 +64,53 @@ NewRelicReporter reporter = NewRelicReporter.build(metricRegistry, metricBatchSe
.commonAttributes(commonAttributes)
.build();
reporter.start(15, TimeUnit.SECONDS);
```
## Customizing Reported Metrics
If you would like to customize the way metric names or attributes are reported to New Relic, you will want to supply
customizers to the `NewRelicReporterBuilder`.

Consider metrics with tags encoded in their names, formatted like so: `"metricName[tag:value,othertag:othervalue]"`,
you might set up a reporter to report the metric name as `metricName` and add merge of the key/value pairs in `name`
with the `commonAttributes`.

```
MetricRegistry metricRegistry = new MetricRegistry(); // If you're already using dropwizard-metrics you may already have one of these.
...
String apiKey = "<YOUR_SECRET_API_KEY>";
MetricBatchSender metricBatchSender = MetricBatchSenderFactory
.fromHttpImplementation(OkHttpPoster::new)
.createBatchSender(apiKey);
Attributes commonAttributes = new Attributes()
.put("host", InetAddress.getLocalHost().getHostName())
.put("appName", "Your Application Name Here")
.put("other", "any other common attributes you wish");
MetricAttributesCustomizer mergeAttributesFromTaggedMetricName =
(name, metric, attributes) -> {
Attributes tagsAsAttributes = new Attributes();
// get a stream of each tag:value pair within the square brackets of name and add
// each pair to the tagsAsAttributes Attributes object
Stream.of(name.substring(name.indexOf('['), name.indexOf(']')).split(","))
.forEach(
str -> {
String[] keyValuePair = str.split(":");
tagsAsAttributes.put(keyValuePair[0], keyValuePair[1]);
});
return tagsAsAttributes.putAll(attributes);
};
NewRelicReporter reporter = NewRelicReporter.build(metricRegistry, metricBatchSender)
.commonAttributes(commonAttributes)
// customizer to strip encoded tags from metric name
.metricNameCustomizer(name -> name.substring(0, name.indexOf('[')))
.metricAttributeCustomizer(mergeAttributesFromTaggedMetricName)
.build();
reporter.start(15, TimeUnit.SECONDS);
```

4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
releaseVersion = 0.6.0
releaseVersion = 0.7.0

# set this to true to enable using a local sonatype (for debugging publishing issues)
# (start a local sonatype in docker with this command: $ docker run -d -p 8081:8081 --name nexus sonatype/nexus3)
# access the nexus container at http://localhost:8081
useLocalSonatype = false
useLocalSonatype = false
Original file line number Diff line number Diff line change
@@ -16,6 +16,8 @@
import com.codahale.metrics.newrelic.transformer.HistogramTransformer;
import com.codahale.metrics.newrelic.transformer.MeterTransformer;
import com.codahale.metrics.newrelic.transformer.TimerTransformer;
import com.codahale.metrics.newrelic.transformer.customizer.MetricAttributesCustomizer;
import com.codahale.metrics.newrelic.transformer.customizer.MetricNameCustomizer;
import com.codahale.metrics.newrelic.util.TimeTracker;
import com.newrelic.telemetry.Attributes;
import com.newrelic.telemetry.TelemetryClient;
@@ -35,6 +37,8 @@ public class NewRelicReporterBuilder {
private TimeUnit durationUnit = TimeUnit.MILLISECONDS;
private Attributes commonAttributes = new Attributes();
private Set<MetricAttribute> disabledMetricAttributes = Collections.emptySet();
private MetricNameCustomizer nameCustomizer = MetricNameCustomizer.DEFAULT;
private MetricAttributesCustomizer attributeCustomizer = MetricAttributesCustomizer.DEFAULT;

public static NewRelicReporterBuilder forRegistry(
MetricRegistry registry, MetricBatchSender metricBatchSender) {
@@ -77,6 +81,17 @@ public NewRelicReporterBuilder disabledMetricAttributes(
return this;
}

public NewRelicReporterBuilder metricNameCustomizer(MetricNameCustomizer nameCustomizer) {
this.nameCustomizer = nameCustomizer;
return this;
}

public NewRelicReporterBuilder metricAttributeCustomizer(
MetricAttributesCustomizer attributeCustomizer) {
this.attributeCustomizer = attributeCustomizer;
return this;
}

public NewRelicReporter build() {
long rateFactor = rateUnit.toSeconds(1);
double durationFactor = durationUnit.toNanos(1);
@@ -85,12 +100,21 @@ public NewRelicReporter build() {

TimeTracker timeTracker = new TimeTracker(Clock.defaultClock());
MeterTransformer meterTransformer =
MeterTransformer.build(timeTracker, rateFactor, metricAttributePredicate);
MeterTransformer.build(
timeTracker, rateFactor, metricAttributePredicate, nameCustomizer, attributeCustomizer);
TimerTransformer timerTransformer =
TimerTransformer.build(timeTracker, rateFactor, durationFactor, metricAttributePredicate);
GaugeTransformer gaugeTransformer = new GaugeTransformer();
CounterTransformer counterTransformer = new CounterTransformer();
HistogramTransformer histogramTransformer = HistogramTransformer.build(timeTracker);
TimerTransformer.build(
timeTracker,
rateFactor,
durationFactor,
metricAttributePredicate,
nameCustomizer,
attributeCustomizer);
GaugeTransformer gaugeTransformer = new GaugeTransformer(nameCustomizer, attributeCustomizer);
CounterTransformer counterTransformer =
new CounterTransformer(nameCustomizer, attributeCustomizer);
HistogramTransformer histogramTransformer =
HistogramTransformer.build(timeTracker, nameCustomizer, attributeCustomizer);

return new NewRelicReporter(
timeTracker,
Original file line number Diff line number Diff line change
@@ -11,26 +11,49 @@

import com.codahale.metrics.Clock;
import com.codahale.metrics.Counter;
import com.codahale.metrics.newrelic.transformer.customizer.MetricAttributesCustomizer;
import com.codahale.metrics.newrelic.transformer.customizer.MetricNameCustomizer;
import com.newrelic.telemetry.Attributes;
import com.newrelic.telemetry.metrics.Gauge;
import com.newrelic.telemetry.metrics.Metric;
import java.util.Collection;
import java.util.Objects;

public class CounterTransformer implements DropWizardMetricTransformer<Counter> {

private final Clock clock;
private final MetricNameCustomizer nameCustomizer;
private final MetricAttributesCustomizer attributeCustomizer;

public CounterTransformer() {
this(Clock.defaultClock());
}

public CounterTransformer(
MetricNameCustomizer nameCustomizer, MetricAttributesCustomizer attributeCustomizer) {
this(Clock.defaultClock(), nameCustomizer, attributeCustomizer);
}

// exists for testing
CounterTransformer(Clock clock) {
this(clock, MetricNameCustomizer.DEFAULT, MetricAttributesCustomizer.DEFAULT);
}

CounterTransformer(
Clock clock,
MetricNameCustomizer nameCustomizer,
MetricAttributesCustomizer attributeCustomizer) {
this.clock = clock;
this.nameCustomizer = Objects.requireNonNull(nameCustomizer);
this.attributeCustomizer = Objects.requireNonNull(attributeCustomizer);
}

@Override
public Collection<Metric> transform(String name, Counter counter) {
return singleton(new Gauge(name, counter.getCount(), clock.getTime(), new Attributes()));
String customizedName = nameCustomizer.customizeMetricName(name);
Attributes customizedAttributes =
attributeCustomizer.customizeMetricAttributes(name, counter, new Attributes());
return singleton(
new Gauge(customizedName, counter.getCount(), clock.getTime(), customizedAttributes));
}
}
Original file line number Diff line number Diff line change
@@ -12,43 +12,69 @@

import com.codahale.metrics.Clock;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.newrelic.transformer.customizer.MetricAttributesCustomizer;
import com.codahale.metrics.newrelic.transformer.customizer.MetricNameCustomizer;
import com.newrelic.telemetry.Attributes;
import com.newrelic.telemetry.metrics.Metric;
import java.util.Collection;
import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GaugeTransformer implements DropWizardMetricTransformer<Gauge> {

private static final Logger LOG = LoggerFactory.getLogger(GaugeTransformer.class);
private final Clock clock;
private final MetricNameCustomizer nameCustomizer;
private final MetricAttributesCustomizer attributeCustomizer;

public GaugeTransformer() {
this(Clock.defaultClock());
this(MetricNameCustomizer.DEFAULT, MetricAttributesCustomizer.DEFAULT);
}

public GaugeTransformer(
MetricNameCustomizer nameCustomizer, MetricAttributesCustomizer attributeCustomizer) {
this(Clock.defaultClock(), nameCustomizer, attributeCustomizer);
}

// exists for testing
public GaugeTransformer(Clock clock) {
this(clock, MetricNameCustomizer.DEFAULT, MetricAttributesCustomizer.DEFAULT);
}

public GaugeTransformer(
Clock clock,
MetricNameCustomizer nameCustomizer,
MetricAttributesCustomizer attributeCustomizer) {
this.clock = clock;
this.nameCustomizer = Objects.requireNonNull(nameCustomizer);
this.attributeCustomizer = Objects.requireNonNull(attributeCustomizer);
}

@Override
public Collection<Metric> transform(String name, Gauge gauge) {
String customizedName = nameCustomizer.customizeMetricName(name);
Attributes customizedAttributes =
attributeCustomizer.customizeMetricAttributes(name, gauge, new Attributes());
long timestamp = clock.getTime();
Object gaugeValue = gauge.getValue();
if (gaugeValue == null) {
LOG.debug("Ignoring gauge with null value. Gauge name: {}", name);
LOG.debug(
"Ignoring gauge with null value. Gauge name: {}, Gauge attributes: {}",
customizedName,
customizedAttributes);
return emptySet();
}
if (gaugeValue instanceof Number) {
Metric metric =
new com.newrelic.telemetry.metrics.Gauge(
name, ((Number) gaugeValue).doubleValue(), timestamp, new Attributes());
customizedName, ((Number) gaugeValue).doubleValue(), timestamp, customizedAttributes);
return singleton(metric);
}
LOG.debug(
"Ignoring gauge [name: {}] with value of type {} (non-numeric gauges are unsupported)",
name,
"Ignoring gauge [name: {}, Attributes: {}] with value of type {} (non-numeric gauges are unsupported)",
customizedName,
customizedAttributes,
gaugeValue.getClass().getName());
return emptySet();
}
Original file line number Diff line number Diff line change
@@ -11,12 +11,15 @@
import static java.util.stream.Stream.concat;

import com.codahale.metrics.Histogram;
import com.codahale.metrics.newrelic.transformer.customizer.MetricAttributesCustomizer;
import com.codahale.metrics.newrelic.transformer.customizer.MetricNameCustomizer;
import com.codahale.metrics.newrelic.transformer.interfaces.CountingTransformer;
import com.codahale.metrics.newrelic.transformer.interfaces.SamplingTransformer;
import com.codahale.metrics.newrelic.util.TimeTracker;
import com.newrelic.telemetry.Attributes;
import com.newrelic.telemetry.metrics.Metric;
import java.util.Collection;
import java.util.Objects;
import java.util.function.Supplier;

public class HistogramTransformer implements DropWizardMetricTransformer<Histogram> {
@@ -25,30 +28,65 @@ public class HistogramTransformer implements DropWizardMetricTransformer<Histogr

private final CountingTransformer countingTransformer;
private final SamplingTransformer samplingTransformer;
private final MetricNameCustomizer nameCustomizer;
private final MetricAttributesCustomizer attributeCustomizer;

public static HistogramTransformer build(TimeTracker timeTracker) {
return build(timeTracker, MetricNameCustomizer.DEFAULT, MetricAttributesCustomizer.DEFAULT);
}

public static HistogramTransformer build(
TimeTracker timeTracker,
MetricNameCustomizer nameCustomizer,
MetricAttributesCustomizer attributeCustomizer) {
return new HistogramTransformer(
new CountingTransformer(timeTracker), new SamplingTransformer(timeTracker, 1L));
new CountingTransformer(timeTracker),
new SamplingTransformer(timeTracker, 1L),
nameCustomizer,
attributeCustomizer);
}

HistogramTransformer(
CountingTransformer countingTransformer, SamplingTransformer samplingTransformer) {
CountingTransformer countingTransformer,
SamplingTransformer samplingTransformer,
MetricNameCustomizer nameCustomizer,
MetricAttributesCustomizer attributeCustomizer) {
this.countingTransformer = countingTransformer;
this.samplingTransformer = samplingTransformer;
this.nameCustomizer = Objects.requireNonNull(nameCustomizer);
this.attributeCustomizer = Objects.requireNonNull(attributeCustomizer);
}

HistogramTransformer(
CountingTransformer countingTransformer, SamplingTransformer samplingTransformer) {
this(
countingTransformer,
samplingTransformer,
MetricNameCustomizer.DEFAULT,
MetricAttributesCustomizer.DEFAULT);
}

@Override
public Collection<Metric> transform(String name, Histogram histogram) {
Collection<Metric> counts = countingTransformer.transform(name, histogram, ATTRIBUTES_SUPPLIER);
String customizedName = nameCustomizer.customizeMetricName(name);
Supplier<Attributes> customizedAttributeSupplier =
() ->
attributeCustomizer.customizeMetricAttributes(
name, histogram, ATTRIBUTES_SUPPLIER.get());

Collection<Metric> counts =
countingTransformer.transform(customizedName, histogram, customizedAttributeSupplier);

return concat(
counts.stream(),
samplingTransformer.transform(name, histogram, ATTRIBUTES_SUPPLIER).stream())
samplingTransformer
.transform(customizedName, histogram, customizedAttributeSupplier)
.stream())
.collect(toSet());
}

@Override
public void onHistogramRemoved(String name) {
countingTransformer.remove(name);
countingTransformer.remove(nameCustomizer.customizeMetricName(name));
}
}
Loading