diff --git a/CHANGELOG.md b/CHANGELOG.md index 05fdef3db377..30689c5233b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - `datadogexporter`: add error checks for datadog exporter (#9964) - `groupbyattrsprocessor`: copied aggregationtemporality when grouping metrics. (#9088) - `mongodbreceiver`: Fix issue where receiver startup could hang (#10111) +- `transformprocessor`: Fix issue where metric.aggregation_temporality and metric.is_monotic were not actually gettable or settable (#10197) ## v0.51.0 diff --git a/processor/transformprocessor/README.md b/processor/transformprocessor/README.md index 1154223a33ec..e0e68c00fc76 100644 --- a/processor/transformprocessor/README.md +++ b/processor/transformprocessor/README.md @@ -15,6 +15,8 @@ in the OTLP protobuf definition. e.g., `status.code`, `attributes["http.method"] `resource.` or `instrumentation_library.`, it will reference those values. For metrics, `name`, `description`, `unit`, `type`, `is_monotonic`, and `aggregation_temporality` are accessed via `metric.` - The name `instrumentation_library` within OpenTelemetry is currently under discussion and may be changed in the future. - Metric data types are `None`, `Gauge`, `Sum`, `Histogram`, `ExponentialHistogram`, and `Summary` + - `aggregation_temporality` is converted to and from the [protobuf's numeric definition](https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/metrics/v1/metrics.proto#L291). Interact with this field using 0, 1, or 2. + - Until the grammar can handle booleans, `is_monotic` is handled via strings the strings `"true"` and `"false"`. - Literals: Strings, ints, and floats can be referenced as literal values - Function invocations: Functions can be invoked with arguments matching the function's expected arguments - Where clause: Telemetry to modify can be filtered by appending `where a b`, with `a` and `b` being any of the above. diff --git a/processor/transformprocessor/internal/metrics/metrics.go b/processor/transformprocessor/internal/metrics/metrics.go index 13d96244ed40..91ccf2c5d5c3 100644 --- a/processor/transformprocessor/internal/metrics/metrics.go +++ b/processor/transformprocessor/internal/metrics/metrics.go @@ -15,6 +15,7 @@ package metrics // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor/internal/metrics" import ( "fmt" + "strconv" "time" "go.opentelemetry.io/collector/pdata/pcommon" @@ -310,24 +311,24 @@ func accessMetricAggTemporality() pathGetSetter { metric := ctx.(metricTransformContext).GetMetric() switch metric.DataType() { case pmetric.MetricDataTypeSum: - return metric.Sum().AggregationTemporality() + return int64(metric.Sum().AggregationTemporality()) case pmetric.MetricDataTypeHistogram: - return metric.Histogram().AggregationTemporality() + return int64(metric.Histogram().AggregationTemporality()) case pmetric.MetricDataTypeExponentialHistogram: - return metric.ExponentialHistogram().AggregationTemporality() + return int64(metric.ExponentialHistogram().AggregationTemporality()) } return nil }, setter: func(ctx common.TransformContext, val interface{}) { - if newAggTemporality, ok := val.(pmetric.MetricAggregationTemporality); ok { + if newAggTemporality, ok := val.(int64); ok { metric := ctx.(metricTransformContext).GetMetric() switch metric.DataType() { case pmetric.MetricDataTypeSum: - metric.Sum().SetAggregationTemporality(newAggTemporality) + metric.Sum().SetAggregationTemporality(pmetric.MetricAggregationTemporality(newAggTemporality)) case pmetric.MetricDataTypeHistogram: - metric.Histogram().SetAggregationTemporality(newAggTemporality) + metric.Histogram().SetAggregationTemporality(pmetric.MetricAggregationTemporality(newAggTemporality)) case pmetric.MetricDataTypeExponentialHistogram: - metric.ExponentialHistogram().SetAggregationTemporality(newAggTemporality) + metric.ExponentialHistogram().SetAggregationTemporality(pmetric.MetricAggregationTemporality(newAggTemporality)) } } }, @@ -340,16 +341,18 @@ func accessMetricIsMonotonic() pathGetSetter { metric := ctx.(metricTransformContext).GetMetric() switch metric.DataType() { case pmetric.MetricDataTypeSum: - return metric.Sum().IsMonotonic() + return strconv.FormatBool(metric.Sum().IsMonotonic()) } return nil }, setter: func(ctx common.TransformContext, val interface{}) { - if newIsMonotonic, ok := val.(bool); ok { + if newIsMonotonic, ok := val.(string); ok { metric := ctx.(metricTransformContext).GetMetric() switch metric.DataType() { case pmetric.MetricDataTypeSum: - metric.Sum().SetIsMonotonic(newIsMonotonic) + if boolVal, err := strconv.ParseBool(newIsMonotonic); err == nil { + metric.Sum().SetIsMonotonic(boolVal) + } } } }, diff --git a/processor/transformprocessor/internal/metrics/metrics_test.go b/processor/transformprocessor/internal/metrics/metrics_test.go index 3254dc50b3b1..f75087b125e9 100644 --- a/processor/transformprocessor/internal/metrics/metrics_test.go +++ b/processor/transformprocessor/internal/metrics/metrics_test.go @@ -1532,8 +1532,8 @@ func Test_newPathGetSetter_Metric(t *testing.T) { Name: "aggregation_temporality", }, }, - orig: pmetric.MetricAggregationTemporalityCumulative, - new: pmetric.MetricAggregationTemporalityDelta, + orig: int64(2), + new: int64(1), modified: func(metric pmetric.Metric) { metric.Sum().SetAggregationTemporality(pmetric.MetricAggregationTemporalityDelta) }, @@ -1548,8 +1548,8 @@ func Test_newPathGetSetter_Metric(t *testing.T) { Name: "is_monotonic", }, }, - orig: true, - new: false, + orig: "true", + new: "false", modified: func(metric pmetric.Metric) { metric.Sum().SetIsMonotonic(false) }, diff --git a/processor/transformprocessor/internal/metrics/processor_test.go b/processor/transformprocessor/internal/metrics/processor_test.go index 0004cd081cf9..149197f2d895 100644 --- a/processor/transformprocessor/internal/metrics/processor_test.go +++ b/processor/transformprocessor/internal/metrics/processor_test.go @@ -80,6 +80,19 @@ func TestProcess(t *testing.T) { td.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().At(0).SetDescription("Sum") }, }, + { + query: `set(metric.aggregation_temporality, 1) where metric.aggregation_temporality == 0`, + want: func(td pmetric.Metrics) { + td.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().At(0).Sum().SetAggregationTemporality(pmetric.MetricAggregationTemporalityDelta) + td.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().At(1).Histogram().SetAggregationTemporality(pmetric.MetricAggregationTemporalityDelta) + }, + }, + { + query: `set(metric.is_monotonic, "true") where metric.is_monotonic == "false"`, + want: func(td pmetric.Metrics) { + td.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().At(0).Sum().SetIsMonotonic(true) + }, + }, } for _, tt := range tests {