-
Notifications
You must be signed in to change notification settings - Fork 0
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
METRICS-1302: Added prefix support for resource labels. #14
Changes from all commits
f308d59
1fb603a
8f5aa97
eb477fb
fd7efe9
0cb9aa3
f481a62
d9b5e80
c0398bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ | |
|
||
import com.fasterxml.jackson.annotation.JsonCreator; | ||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.google.common.base.Strings; | ||
import com.google.common.collect.Lists; | ||
import com.google.common.collect.Sets; | ||
import com.google.protobuf.ByteString; | ||
|
@@ -32,12 +33,14 @@ | |
import org.apache.druid.data.input.InputRow; | ||
import org.apache.druid.data.input.MapBasedInputRow; | ||
import org.apache.druid.data.input.impl.ParseSpec; | ||
import org.apache.druid.java.util.common.StringUtils; | ||
import org.apache.druid.java.util.common.logger.Logger; | ||
import org.apache.druid.java.util.common.parsers.ParseException; | ||
|
||
import java.nio.ByteBuffer; | ||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
|
@@ -48,19 +51,31 @@ public class OpenCensusProtobufInputRowParser implements ByteBufferInputRowParse | |
private static final Logger LOG = new Logger(OpenCensusProtobufInputRowParser.class); | ||
|
||
private static final String SEPARATOR = "-"; | ||
public static final String NAME = "name"; | ||
public static final String VALUE = "value"; | ||
public static final String TIMESTAMP_COLUMN = "timestamp"; | ||
private static final String DEFAULT_METRIC_DIMENSION = "name"; | ||
private static final String VALUE = "value"; | ||
private static final String TIMESTAMP_COLUMN = "timestamp"; | ||
private static final String DEFAULT_RESOURCE_PREFIX = "resource."; | ||
private final ParseSpec parseSpec; | ||
private final List<String> dimensions; | ||
|
||
private final String metricDimension; | ||
private final String metricLabelPrefix; | ||
private final String resourceLabelPrefix; | ||
|
||
@JsonCreator | ||
public OpenCensusProtobufInputRowParser( | ||
@JsonProperty("parseSpec") ParseSpec parseSpec | ||
@JsonProperty("parseSpec") ParseSpec parseSpec, | ||
@JsonProperty("metricDimension") String metricDimension, | ||
@JsonProperty("metricLabelPrefix") String metricPrefix, | ||
@JsonProperty("resourceLabelPrefix") String resourcePrefix | ||
) | ||
{ | ||
this.parseSpec = parseSpec; | ||
this.dimensions = parseSpec.getDimensionsSpec().getDimensionNames(); | ||
this.metricDimension = Strings.isNullOrEmpty(metricDimension) ? DEFAULT_METRIC_DIMENSION : metricDimension; | ||
this.metricLabelPrefix = StringUtils.nullToEmptyNonDruidDataString(metricPrefix); | ||
this.resourceLabelPrefix = resourcePrefix != null ? resourcePrefix : DEFAULT_RESOURCE_PREFIX; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why are we handling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As per the discussion we had I think we agreed to have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. right, we could do this by explicitly having There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Leaving it as it is for now. Will change if needed for some other default prefix. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that's fine, it was mostly a suggestion to make the pattern more obvious to someone reading the code. |
||
|
||
LOG.info("Creating Open Census Protobuf parser with spec:" + parseSpec); | ||
} | ||
|
||
|
@@ -73,7 +88,11 @@ public ParseSpec getParseSpec() | |
@Override | ||
public OpenCensusProtobufInputRowParser withParseSpec(ParseSpec parseSpec) | ||
{ | ||
return new OpenCensusProtobufInputRowParser(parseSpec); | ||
return new OpenCensusProtobufInputRowParser( | ||
parseSpec, | ||
metricDimension, | ||
metricLabelPrefix, | ||
resourceLabelPrefix); | ||
} | ||
|
||
@Override | ||
|
@@ -88,22 +107,30 @@ public List<InputRow> parseBatch(ByteBuffer input) | |
throw new ParseException(e, "Protobuf message could not be parsed"); | ||
} | ||
|
||
// Process metric descriptor labels map keys. | ||
List<String> descriptorLabels = metric.getMetricDescriptor().getLabelKeysList().stream() | ||
.map(s -> this.metricLabelPrefix + s.getKey()) | ||
.collect(Collectors.toList()); | ||
|
||
// Process resource labels map. | ||
Map<String, Object> resourceLabelsMap = metric.getResource().getLabelsMap().entrySet().stream() | ||
.collect(Collectors.toMap(entry -> this.resourceLabelPrefix + entry.getKey(), | ||
Map.Entry::getValue)); | ||
|
||
final List<String> dimensions; | ||
|
||
if (!this.dimensions.isEmpty()) { | ||
dimensions = this.dimensions; | ||
} else { | ||
Set<String> recordDimensions = metric.getMetricDescriptor().getLabelKeysList().stream() | ||
.map(s -> s.getKey()) | ||
.collect(Collectors.toSet()); | ||
Set<String> recordDimensions = new HashSet<>(descriptorLabels); | ||
|
||
// Add resource map key set to record dimensions. | ||
recordDimensions.addAll(metric.getResource().getLabelsMap().keySet()); | ||
recordDimensions.addAll(resourceLabelsMap.keySet()); | ||
|
||
// NAME, VALUE dimensions will not be present in labelKeysList or Metric.Resource map as they | ||
// are derived dimensions, which get populated while parsing data for timeSeries hence add | ||
// them to recordDimensions. | ||
recordDimensions.add(NAME); | ||
// MetricDimension, VALUE dimensions will not be present in labelKeysList or Metric.Resource | ||
// map as they are derived dimensions, which get populated while parsing data for timeSeries | ||
// hence add them to recordDimensions. | ||
recordDimensions.add(metricDimension); | ||
recordDimensions.add(VALUE); | ||
|
||
dimensions = Lists.newArrayList( | ||
|
@@ -116,11 +143,11 @@ public List<InputRow> parseBatch(ByteBuffer input) | |
for (TimeSeries ts : metric.getTimeseriesList()) { | ||
|
||
// Add common resourceLabels. | ||
Map<String, Object> labels = new HashMap<>(metric.getResource().getLabelsMap()); | ||
Map<String, Object> labels = new HashMap<>(resourceLabelsMap); | ||
|
||
// Add labels to record. | ||
for (int i = 0; i < metric.getMetricDescriptor().getLabelKeysCount(); i++) { | ||
labels.put(metric.getMetricDescriptor().getLabelKeys(i).getKey(), ts.getLabelValues(i).getValue()); | ||
labels.put(descriptorLabels.get(i), ts.getLabelValues(i).getValue()); | ||
} | ||
|
||
// One row per timeSeries point. | ||
|
@@ -132,29 +159,29 @@ public List<InputRow> parseBatch(ByteBuffer input) | |
case DOUBLE_VALUE: | ||
Map<String, Object> doubleGauge = new HashMap<>(); | ||
doubleGauge.putAll(labels); | ||
doubleGauge.put(NAME, metric.getMetricDescriptor().getName()); | ||
doubleGauge.put(metricDimension, metric.getMetricDescriptor().getName()); | ||
doubleGauge.put(VALUE, point.getDoubleValue()); | ||
addDerivedMetricsRow(doubleGauge, dimensions, rows); | ||
break; | ||
case INT64_VALUE: | ||
HashMap<String, Object> intGauge = new HashMap<>(); | ||
intGauge.putAll(labels); | ||
intGauge.put(VALUE, point.getInt64Value()); | ||
intGauge.put(NAME, metric.getMetricDescriptor().getName()); | ||
intGauge.put(metricDimension, metric.getMetricDescriptor().getName()); | ||
addDerivedMetricsRow(intGauge, dimensions, rows); | ||
break; | ||
case SUMMARY_VALUE: | ||
// count | ||
Map<String, Object> summaryCount = new HashMap<>(); | ||
summaryCount.putAll(labels); | ||
summaryCount.put(NAME, metric.getMetricDescriptor().getName() + SEPARATOR + "count"); | ||
summaryCount.put(metricDimension, metric.getMetricDescriptor().getName() + SEPARATOR + "count"); | ||
summaryCount.put(VALUE, point.getSummaryValue().getCount().getValue()); | ||
addDerivedMetricsRow(summaryCount, dimensions, rows); | ||
|
||
// sum | ||
Map<String, Object> summarySum = new HashMap<>(); | ||
summarySum.putAll(labels); | ||
summarySum.put(NAME, metric.getMetricDescriptor().getName() + SEPARATOR + "sum"); | ||
summarySum.put(metricDimension, metric.getMetricDescriptor().getName() + SEPARATOR + "sum"); | ||
summarySum.put(VALUE, point.getSummaryValue().getSnapshot().getSum().getValue()); | ||
addDerivedMetricsRow(summarySum, dimensions, rows); | ||
|
||
|
@@ -163,13 +190,13 @@ public List<InputRow> parseBatch(ByteBuffer input) | |
case DISTRIBUTION_VALUE: | ||
// count | ||
Map<String, Object> distCount = new HashMap<>(); | ||
distCount.put(NAME, metric.getMetricDescriptor().getName() + SEPARATOR + "count"); | ||
distCount.put(metricDimension, metric.getMetricDescriptor().getName() + SEPARATOR + "count"); | ||
distCount.put(VALUE, point.getDistributionValue().getCount()); | ||
addDerivedMetricsRow(distCount, dimensions, rows); | ||
|
||
// sum | ||
Map<String, Object> distSum = new HashMap<>(); | ||
distSum.put(NAME, metric.getMetricDescriptor().getName() + SEPARATOR + "sum"); | ||
distSum.put(metricDimension, metric.getMetricDescriptor().getName() + SEPARATOR + "sum"); | ||
distSum.put(VALUE, point.getDistributionValue().getSum()); | ||
addDerivedMetricsRow(distSum, dimensions, rows); | ||
// TODO: How to handle buckets ? | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just realized you didn't add any @UsonProperty annotated getters for those properties, which means they will be left out when serializing to json. This is required for nodes to communicate the parser spec to each-other
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xvrl Created PR: #15
Added additional test cases and
labels
fordistribution
metric too.