Commit 9587003d by Jon Schneider Committed by Spencer Gibb

Sanitize Servo metric tag key/value pairs before publishing to Atlas (#1315)

parent 8f7ea41f
...@@ -38,6 +38,7 @@ import com.fasterxml.jackson.core.JsonGenerator; ...@@ -38,6 +38,7 @@ import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.dataformat.smile.SmileFactory; import com.fasterxml.jackson.dataformat.smile.SmileFactory;
import com.netflix.servo.Metric; import com.netflix.servo.Metric;
import com.netflix.servo.annotations.DataSourceType; import com.netflix.servo.annotations.DataSourceType;
import com.netflix.servo.monitor.MonitorConfig;
import com.netflix.servo.publish.MetricObserver; import com.netflix.servo.publish.MetricObserver;
import com.netflix.servo.tag.BasicTag; import com.netflix.servo.tag.BasicTag;
import com.netflix.servo.tag.Tag; import com.netflix.servo.tag.Tag;
...@@ -96,7 +97,7 @@ public class AtlasMetricObserver implements MetricObserver { ...@@ -96,7 +97,7 @@ public class AtlasMetricObserver implements MetricObserver {
return true; return true;
} }
protected static String normalizeAtlasUri(String uri) { static String normalizeAtlasUri(String uri) {
if (uri != null) { if (uri != null) {
Matcher matcher = Pattern.compile("(.+?)(/api/v1/publish)?/?").matcher(uri); Matcher matcher = Pattern.compile("(.+?)(/api/v1/publish)?/?").matcher(uri);
if (matcher.matches()) if (matcher.matches())
...@@ -119,7 +120,7 @@ public class AtlasMetricObserver implements MetricObserver { ...@@ -119,7 +120,7 @@ public class AtlasMetricObserver implements MetricObserver {
return; return;
} }
List<Metric> metrics = addTypeTagsAsNecessary(rawMetrics); List<Metric> metrics = sanitizeTags(addTypeTagsAsNecessary(rawMetrics));
for (int i = 0; i < metrics.size(); i += config.getBatchSize()) { for (int i = 0; i < metrics.size(); i += config.getBatchSize()) {
List<Metric> batch = metrics.subList(i, List<Metric> batch = metrics.subList(i,
...@@ -217,8 +218,25 @@ public class AtlasMetricObserver implements MetricObserver { ...@@ -217,8 +218,25 @@ public class AtlasMetricObserver implements MetricObserver {
return totalMetricsInBatch; return totalMetricsInBatch;
} }
protected static List<Metric> addTypeTagsAsNecessary(List<Metric> metrics) { static List<Metric> sanitizeTags(List<Metric> metrics) {
List<Metric> typedMetrics = new ArrayList<>(); List<Metric> sanitized = new ArrayList<>(metrics.size());
for (Metric m : metrics) {
MonitorConfig.Builder config = MonitorConfig.builder(toValidCharset(m.getConfig().getName()));
for (Tag tag : m.getConfig().getTags()) {
config.withTag(toValidCharset(tag.getKey()), toValidCharset(tag.getValue()));
}
config.withPublishingPolicy(m.getConfig().getPublishingPolicy());
sanitized.add(new Metric(config.build(), m.getTimestamp(), m.getValue()));
}
return sanitized;
}
private static String toValidCharset(String name) {
return name.replaceAll("[^\\.\\-\\w]", "_");
}
static List<Metric> addTypeTagsAsNecessary(List<Metric> metrics) {
List<Metric> typedMetrics = new ArrayList<>(metrics.size());
for (Metric m : metrics) { for (Metric m : metrics) {
String value = m.getConfig().getTags().getValue(DataSourceType.KEY); String value = m.getConfig().getTags().getValue(DataSourceType.KEY);
Metric transformed; Metric transformed;
......
...@@ -17,6 +17,7 @@ import java.util.ArrayList; ...@@ -17,6 +17,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import com.netflix.servo.tag.Tag;
import org.junit.Test; import org.junit.Test;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
...@@ -192,6 +193,23 @@ public class AtlasMetricObserverTests { ...@@ -192,6 +193,23 @@ public class AtlasMetricObserverTests {
is(equalTo(AtlasMetricObserver.PublishMetricsBatchStatus.PartialSuccess))); is(equalTo(AtlasMetricObserver.PublishMetricsBatchStatus.PartialSuccess)));
} }
@Test
public void sanitizeMetrics() {
String mixtureOfValidAndInvalidChars = "a_1.2-Z/ A";
Metric m = new Metric(new MonitorConfig.Builder(mixtureOfValidAndInvalidChars)
.withTag(mixtureOfValidAndInvalidChars, mixtureOfValidAndInvalidChars).build(), 0, 1);
Metric sanitizedMetric = AtlasMetricObserver.sanitizeTags(Collections.singletonList(m)).get(0);
String valid = "a_1.2-Z__A";
assertThat(sanitizedMetric.getConfig().getName(), is(equalTo(valid)));
Tag tag = sanitizedMetric.getConfig().getTags().iterator().next();
assertThat(tag.getKey(), is(equalTo(valid)));
assertThat(tag.getValue(), is(equalTo(valid)));
}
private List<Metric> generateMetrics(int numberOfMetrics) { private List<Metric> generateMetrics(int numberOfMetrics) {
List<Metric> metrics = new ArrayList<>(); List<Metric> metrics = new ArrayList<>();
for (int i = 0; i < numberOfMetrics; i++) for (int i = 0; i < numberOfMetrics; i++)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment