package org.kairosdb.plugin.carbon; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Template { private List<String> tagNames; private Pattern filter; private Pattern metricNamePattern; private Pattern tagsPattern; private String sourceSeparator = "."; private String targetSeparator = "."; private String template; private Map<String, String> staticTags = new HashMap<String, String>(); public Template(String string) { List<String> parts = Arrays.asList(string.split(" ")); if (parts.size() >= 2) { this.filter = Pattern.compile(parts.get(0)); this.template = parts.get(1); for(int i = 2; i < parts.size(); i++) { String part = parts.get(i); if (part.matches("^\\[\\S(?:,\\S)?\\]$")) { part = part.replaceAll("([\\[\\]])", ""); List<String> separators = new LinkedList<String>(Arrays.asList(part.split(","))); if (separators.size() < 2) { separators.add(separators.get(0)); } this.sourceSeparator = separators.get(0); this.targetSeparator = separators.get(1); } else if (part.matches("^(?:\\w+=\\w+,?)*(?:\\w+=\\w+)$")) { List<String> tags = Arrays.asList(part.split(",")); for (String tag : tags) { List<String> tagParts = Arrays.asList(tag.split("=")); staticTags.put(tagParts.get(0), tagParts.get(1)); } } else { throw new IllegalArgumentException("unknown parameter: " + part); } } buildTemplatePatterns(); } else { throw new IllegalArgumentException("less than 2 space separated parts"); } } public void addTags(CarbonMetric ret, String metricName) { Matcher matcher = tagsPattern.matcher(metricName); matcher.find(); for (int i = 1; i <= matcher.groupCount(); i++) { ret.addTag(tagNames.get(i - 1), matcher.group(i)); } addStaticTags(ret); } public void addStaticTags(CarbonMetric ret) { for (Map.Entry<String, String> tag : staticTags.entrySet()) { ret.addTag(tag.getKey(), tag.getValue()); } } public String buildMetricName(String metric) { List<String> matches = new ArrayList<String>(); Matcher matcher = metricNamePattern.matcher(metric); matcher.find(); for(int i = 1; i <= matcher.groupCount(); i++) { matches.add(matcher.group(i)); } String r_sourceSep = "\\" + sourceSeparator; String metricName = String.join(targetSeparator, matches); return metricName.replaceAll(r_sourceSep, targetSeparator); } private void buildTemplatePatterns() { String r_sourceSep = "\\" + sourceSeparator; String r_skip = "[^" + sourceSeparator + "]*"; String r_capture = "(" + r_skip + ")"; List<String> templateParts = Arrays.asList(template.split(r_sourceSep)); List<String> metricNamePatternParts = new ArrayList<String>(); List<String> tagsPatternParts = new ArrayList<String>(); List<String> tagNames = new ArrayList<String>(); for (String templatePart : templateParts) { if ("metric".equals(templatePart)) { metricNamePatternParts.add(r_capture); tagsPatternParts.add(r_skip); } else if ("metric*".equals(templatePart)) { metricNamePatternParts.add("(.*)"); tagsPatternParts.add(".*"); } else { metricNamePatternParts.add(r_skip); if (templatePart.length() > 0) { tagsPatternParts.add(r_capture); tagNames.add(templatePart); } else { tagsPatternParts.add(r_skip); } } } this.tagNames = tagNames; this.metricNamePattern = Pattern.compile( "^" + String.join(r_sourceSep, metricNamePatternParts) + "$" ); this.tagsPattern = Pattern.compile( "^" + String.join(r_sourceSep, tagsPatternParts) + "$" ); } public Pattern getFilter() { return filter; } public Pattern getMetricNamePattern() { return metricNamePattern; } public Pattern getTagsPattern() { return tagsPattern; } public String getSourceSeparator() { return sourceSeparator; } public Map<String,String> getStaticTags() { return staticTags; } public String getTargetSeparator() { return targetSeparator; } public List<String> getTagNames() { return tagNames; } public String getTemplate() { return template; } public boolean matches(String metricName) { Matcher matcher = filter.matcher(metricName); return matcher.lookingAt(); } }