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;
import com.fasterxml.jackson.dataformat.smile.SmileFactory;
import com.netflix.servo.Metric;
import com.netflix.servo.annotations.DataSourceType;
import com.netflix.servo.monitor.MonitorConfig;
import com.netflix.servo.publish.MetricObserver;
import com.netflix.servo.tag.BasicTag;
import com.netflix.servo.tag.Tag;
......@@ -96,7 +97,7 @@ public class AtlasMetricObserver implements MetricObserver {
return true;
}
protected static String normalizeAtlasUri(String uri) {
static String normalizeAtlasUri(String uri) {
if (uri != null) {
Matcher matcher = Pattern.compile("(.+?)(/api/v1/publish)?/?").matcher(uri);
if (matcher.matches())
......@@ -119,7 +120,7 @@ public class AtlasMetricObserver implements MetricObserver {
return;
}
List<Metric> metrics = addTypeTagsAsNecessary(rawMetrics);
List<Metric> metrics = sanitizeTags(addTypeTagsAsNecessary(rawMetrics));
for (int i = 0; i < metrics.size(); i += config.getBatchSize()) {
List<Metric> batch = metrics.subList(i,
......@@ -217,8 +218,25 @@ public class AtlasMetricObserver implements MetricObserver {
return totalMetricsInBatch;
}
protected static List<Metric> addTypeTagsAsNecessary(List<Metric> metrics) {
List<Metric> typedMetrics = new ArrayList<>();
static List<Metric> sanitizeTags(List<Metric> metrics) {
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) {
String value = m.getConfig().getTags().getValue(DataSourceType.KEY);
Metric transformed;
......
......@@ -17,6 +17,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.netflix.servo.tag.Tag;
import org.junit.Test;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
......@@ -191,6 +192,23 @@ public class AtlasMetricObserverTests {
assertThat(obs.sendMetricsBatch(generateMetrics(2)),
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) {
List<Metric> metrics = new ArrayList<>();
......
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