Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Graphite: Replace names with non-alphanumeric chars with '-' #936

Merged
merged 1 commit into from
Apr 11, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,12 @@
import java.net.Socket;
import java.nio.charset.Charset;
import java.util.concurrent.TimeoutException;
import java.util.regex.Pattern;

/**
* A rabbit-mq client to a Carbon server.
*/
public class GraphiteRabbitMQ implements GraphiteSender {

private static final Pattern WHITESPACE = Pattern.compile("[\\s]+");

private static final Charset UTF_8 = Charset.forName("UTF-8");

private static final Integer DEFAULT_RABBIT_CONNECTION_TIMEOUT_MS = 500;
Expand Down Expand Up @@ -167,7 +164,7 @@ public int getFailures() {
}

public String sanitize(String s) {
return WHITESPACE.matcher(s).replaceAll("-");
return GraphiteSanitize.sanitize(s, '-');
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package io.dropwizard.metrics.graphite;

class GraphiteSanitize {
/** Replaces all characters from a given string that are not ascii and not alphanumeric
* with a dash */
static String sanitize(String string, char replacement) {
String replaced = replaceFrom(string, replacement);

// Consolidate multiple dashes into a single one
String result = replaced.replace("--", "-");
while (!result.equals(replaced)) {
replaced = result;
result = replaced.replace("--", "-");
}

// Remove any leading or trailing dashes
return strip(result, replacement);
}

/** A char matches when it is a letter or digit and it is ASCII, in Guava terminology,
* this would be CharMatcher.ASCII.and(CharMatcher.JAVA_LETTER_OR_DIGIT).negate() */
private static boolean matches(char c) {
return !(Character.isLetterOrDigit(c) && c <= '\u007f');
}

/** Replace all characters that we're interested in with a replacement character,
* heavily inspired by the same code in Guava's CharMatcher */
private static String replaceFrom(String string, char replacement) {
int pos = indexIn(string, 0);
if (pos == -1) {
return string;
}
char[] chars = string.toCharArray();
chars[pos] = replacement;
for (int i = pos + 1; i < chars.length; i++) {
if (matches(chars[i])) {
chars[i] = replacement;
}
}
return new String(chars).trim();
}

/** Finds the first index (or -1) of a character we're interested in */
private static int indexIn(String sequence, int start) {
int length = sequence.length();
for (int i = start; i < length; i++) {
if (matches(sequence.charAt(i))) {
return i;
}
}
return -1;
}

/** Strips a given character from the beginning and end of a string,
* heavily inspired by Apache's StringUtils.strip
*/
private static String strip(String str, char strip) {
int strLen = str.length();
int start = 0;
int end = strLen - 1;
while (start != strLen && str.charAt(start) == strip) {
start++;
}

while (end > start && str.charAt(end) == strip) {
end--;
}

return start != 0 || end != strLen - 1 ? str.substring(start, end + 1) : str;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.charset.Charset;
import java.util.regex.Pattern;

/**
* A client to a Carbon server using unconnected UDP
*/
public class GraphiteUDP implements GraphiteSender {

private static final Pattern WHITESPACE = Pattern.compile("[\\s]+");

private static final Charset UTF_8 = Charset.forName("UTF-8");

private final String hostname;
Expand Down Expand Up @@ -111,7 +108,7 @@ public void close() throws IOException {
}

protected String sanitize(String s) {
return WHITESPACE.matcher(s).replaceAll("-");
return GraphiteSanitize.sanitize(s, '-');
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,12 @@
import java.nio.charset.Charset;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;

/**
* A client to a Carbon server that sends all metrics after they have been pickled in configurable sized batches
*/
public class PickledGraphite implements GraphiteSender {

private static final Pattern WHITESPACE = Pattern.compile("[\\s]+");
private static final Charset UTF_8 = Charset.forName("UTF-8");

private static final Logger LOGGER = LoggerFactory.getLogger(PickledGraphite.class);
Expand Down Expand Up @@ -360,7 +358,7 @@ static class MetricTuple {
}

protected String sanitize(String s) {
return WHITESPACE.matcher(s).replaceAll("-");
return GraphiteSanitize.sanitize(s, '-');
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.dropwizard.metrics.graphite;

import org.assertj.core.api.SoftAssertions;
import org.junit.Test;

public class GraphiteSanitizeTest {
@Test
public void sanitizeGraphiteValues() {
SoftAssertions softly = new SoftAssertions();

softly.assertThat(GraphiteSanitize.sanitize("Foo Bar", '-')).isEqualTo("Foo-Bar");
softly.assertThat(GraphiteSanitize.sanitize(" Foo Bar ", '-')).isEqualTo("Foo-Bar");
softly.assertThat(GraphiteSanitize.sanitize(" Foo Bar", '-')).isEqualTo("Foo-Bar");
softly.assertThat(GraphiteSanitize.sanitize("Foo Bar ", '-')).isEqualTo("Foo-Bar");
softly.assertThat(GraphiteSanitize.sanitize(" Foo Bar ", '-')).isEqualTo("Foo-Bar");
softly.assertThat(GraphiteSanitize.sanitize("Foo@Bar", '-')).isEqualTo("Foo-Bar");
softly.assertThat(GraphiteSanitize.sanitize("Foó Bar", '-')).isEqualTo("Fo-Bar");
softly.assertThat(GraphiteSanitize.sanitize("||ó/.", '-')).isEqualTo("");
softly.assertThat(GraphiteSanitize.sanitize("${Foo:Bar:baz}", '-')).isEqualTo("Foo-Bar-baz");
softly.assertThat(GraphiteSanitize.sanitize("St. Foo's of Bar", '-')).isEqualTo("St-Foo-s-of-Bar");
softly.assertThat(GraphiteSanitize.sanitize("(Foo and (Bar and (Baz)))", '-')).isEqualTo("Foo-and-Bar-and-Baz");
softly.assertThat(GraphiteSanitize.sanitize("Foo.bar.baz", '-')).isEqualTo("Foo-bar-baz");
softly.assertThat(GraphiteSanitize.sanitize("FooBar", '-')).isEqualTo("FooBar");

softly.assertAll();
}
}