Skip to content

Commit

Permalink
[processor/transform] Introduce optional metric name suffix setup for…
Browse files Browse the repository at this point in the history
… convert summary and extract histogram functions

Signed-off-by: odubajDT <[email protected]>
  • Loading branch information
odubajDT committed Jan 15, 2025
1 parent 09d7cde commit 24ae419
Show file tree
Hide file tree
Showing 11 changed files with 205 additions and 53 deletions.
27 changes: 27 additions & 0 deletions .chloggen/transform-name-suffix.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: breaking

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: processor/transform

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: "Introduce optional metric name suffix setup for convert summary and extract histogram functions"

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [33850]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext: "Adaptations of the metric name suffix were made to match the latest OTel convention which uses '.' instead of '_' in suffix"

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: []
32 changes: 22 additions & 10 deletions processor/transformprocessor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ In addition to OTTL functions, the processor defines its own functions to help w
**Metrics only functions**
- [convert_sum_to_gauge](#convert_sum_to_gauge)
- [convert_gauge_to_sum](#convert_gauge_to_sum)
- [extract_count_metric](#extract_count_metric)
- [extract_sum_metric](#extract_sum_metric)
- [convert_summary_count_val_to_sum](#convert_summary_count_val_to_sum)
- [convert_summary_sum_val_to_sum](#convert_summary_sum_val_to_sum)
- [copy_metric](#copy_metric)
Expand Down Expand Up @@ -258,13 +260,14 @@ Examples:
> [!NOTE]
> This function supports Histograms, ExponentialHistograms and Summaries.

`extract_count_metric(is_monotonic)`
`extract_count_metric(is_monotonic, Optional[suffix])`

The `extract_count_metric` function creates a new Sum metric from a Histogram, ExponentialHistogram or Summary's count value. A metric will only be created if there is at least one data point.

`is_monotonic` is a boolean representing the monotonicity of the new metric.
`suffix` is an optional string representing the suffix of the metric name. The default value is `.count`.

The name for the new metric will be `<original metric name>_count`. The fields that are copied are: `timestamp`, `starttimestamp`, `attributes`, `description`, and `aggregation_temporality`. As metrics of type Summary don't have an `aggregation_temporality` field, this field will be set to `AGGREGATION_TEMPORALITY_CUMULATIVE` for those metrics.
The name for the new metric will be `<original metric name>.count`. The fields that are copied are: `timestamp`, `starttimestamp`, `attributes`, `description`, and `aggregation_temporality`. As metrics of type Summary don't have an `aggregation_temporality` field, this field will be set to `AGGREGATION_TEMPORALITY_CUMULATIVE` for those metrics.

The new metric that is created will be passed to all subsequent statements in the metrics statements list.

Expand All @@ -277,18 +280,21 @@ Examples:

- `extract_count_metric(false)`

- `extract_count_metric(false, "custom_suffix")`

### extract_sum_metric

> [!NOTE]
> This function supports Histograms, ExponentialHistograms and Summaries.

`extract_sum_metric(is_monotonic)`
`extract_sum_metric(is_monotonic, Optional[suffix])`

The `extract_sum_metric` function creates a new Sum metric from a Histogram, ExponentialHistogram or Summary's sum value. If the sum value of a Histogram or ExponentialHistogram data point is missing, no data point is added to the output metric. A metric will only be created if there is at least one data point.

`is_monotonic` is a boolean representing the monotonicity of the new metric.
`suffix` is an optional string representing the suffix of the metric name. The default value is `.sum`.

The name for the new metric will be `<original metric name>_sum`. The fields that are copied are: `timestamp`, `starttimestamp`, `attributes`, `description`, and `aggregation_temporality`. As metrics of type Summary don't have an `aggregation_temporality` field, this field will be set to `AGGREGATION_TEMPORALITY_CUMULATIVE` for those metrics.
The name for the new metric will be `<original metric name>.sum`. The fields that are copied are: `timestamp`, `starttimestamp`, `attributes`, `description`, and `aggregation_temporality`. As metrics of type Summary don't have an `aggregation_temporality` field, this field will be set to `AGGREGATION_TEMPORALITY_CUMULATIVE` for those metrics.

The new metric that is created will be passed to all subsequent statements in the metrics statements list.

Expand All @@ -301,44 +307,50 @@ Examples:

- `extract_sum_metric(false)`

- `extract_sum_metric(false, "custom_suffix")`

### convert_summary_count_val_to_sum

`convert_summary_count_val_to_sum(aggregation_temporality, is_monotonic)`
`convert_summary_count_val_to_sum(aggregation_temporality, is_monotonic, Optional[suffix])`

The `convert_summary_count_val_to_sum` function creates a new Sum metric from a Summary's count value.

`aggregation_temporality` is a string (`"cumulative"` or `"delta"`) representing the desired aggregation temporality of the new metric. `is_monotonic` is a boolean representing the monotonicity of the new metric.
`suffix` is an optional string representing the suffix of the metric name. The default value is `.count`.

The name for the new metric will be `<summary metric name>_count`. The fields that are copied are: `timestamp`, `starttimestamp`, `attributes`, and `description`. The new metric that is created will be passed to all functions in the metrics statements list. Function conditions will apply.
The name for the new metric will be `<summary metric name>.count`. The fields that are copied are: `timestamp`, `starttimestamp`, `attributes`, and `description`. The new metric that is created will be passed to all functions in the metrics statements list. Function conditions will apply.

**NOTE:** This function may cause a metric to break semantics for [Sum metrics](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/data-model.md#sums). Use at your own risk.

Examples:

- `convert_summary_count_val_to_sum("delta", true)`


- `convert_summary_count_val_to_sum("cumulative", false)`

- `convert_summary_count_val_to_sum("cumulative", false, "custom_suffix")`

### convert_summary_sum_val_to_sum

`convert_summary_sum_val_to_sum(aggregation_temporality, is_monotonic)`
`convert_summary_sum_val_to_sum(aggregation_temporality, is_monotonic, Optional[suffix])`

The `convert_summary_sum_val_to_sum` function creates a new Sum metric from a Summary's sum value.

`aggregation_temporality` is a string (`"cumulative"` or `"delta"`) representing the desired aggregation temporality of the new metric. `is_monotonic` is a boolean representing the monotonicity of the new metric.
`suffix` is an optional string representing the suffix of the metric name. The default value is `.sum`.

The name for the new metric will be `<summary metric name>_sum`. The fields that are copied are: `timestamp`, `starttimestamp`, `attributes`, and `description`. The new metric that is created will be passed to all functions in the metrics statements list. Function conditions will apply.
The name for the new metric will be `<summary metric name>.sum`. The fields that are copied are: `timestamp`, `starttimestamp`, `attributes`, and `description`. The new metric that is created will be passed to all functions in the metrics statements list. Function conditions will apply.

**NOTE:** This function may cause a metric to break semantics for [Sum metrics](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/data-model.md#sums). Use at your own risk.

Examples:

- `convert_summary_sum_val_to_sum("delta", true)`


- `convert_summary_sum_val_to_sum("cumulative", false)`

- `convert_summary_sum_val_to_sum("cumulative", false, "custom_suffix")`

### copy_metric

`copy_metric(Optional[name], Optional[description], Optional[unit])`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
type convertSummaryCountValToSumArguments struct {
StringAggTemp string
Monotonic bool
Suffix ottl.Optional[string]
}

func newConvertSummaryCountValToSumFactory() ottl.Factory[ottldatapoint.TransformContext] {
Expand All @@ -29,10 +30,14 @@ func createConvertSummaryCountValToSumFunction(_ ottl.FunctionContext, oArgs ott
return nil, fmt.Errorf("convertSummaryCountValToSumFactory args must be of type *convertSummaryCountValToSumArguments")
}

return convertSummaryCountValToSum(args.StringAggTemp, args.Monotonic)
return convertSummaryCountValToSum(args.StringAggTemp, args.Monotonic, args.Suffix)
}

func convertSummaryCountValToSum(stringAggTemp string, monotonic bool) (ottl.ExprFunc[ottldatapoint.TransformContext], error) {
func convertSummaryCountValToSum(stringAggTemp string, monotonic bool, suffix ottl.Optional[string]) (ottl.ExprFunc[ottldatapoint.TransformContext], error) {
metricNameSuffix := ".count"
if !suffix.IsEmpty() {
metricNameSuffix = suffix.Get()
}
var aggTemp pmetric.AggregationTemporality
switch stringAggTemp {
case "delta":
Expand All @@ -50,7 +55,7 @@ func convertSummaryCountValToSum(stringAggTemp string, monotonic bool) (ottl.Exp

sumMetric := tCtx.GetMetrics().AppendEmpty()
sumMetric.SetDescription(metric.Description())
sumMetric.SetName(metric.Name() + "_count")
sumMetric.SetName(metric.Name() + metricNameSuffix)
sumMetric.SetUnit(metric.Unit())
sumMetric.SetEmptySum().SetAggregationTemporality(aggTemp)
sumMetric.Sum().SetIsMonotonic(monotonic)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"

"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl"
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/contexts/ottldatapoint"
)

Expand All @@ -28,7 +29,7 @@ func Test_ConvertSummaryCountValToSum(t *testing.T) {
sumMetric.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityDelta)
sumMetric.Sum().SetIsMonotonic(false)

sumMetric.SetName("summary_metric_count")
sumMetric.SetName("summary_metric.count")
dp := sumMetric.Sum().DataPoints().AppendEmpty()
dp.SetIntValue(100)

Expand All @@ -49,7 +50,7 @@ func Test_ConvertSummaryCountValToSum(t *testing.T) {
sumMetric.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityDelta)
sumMetric.Sum().SetIsMonotonic(true)

sumMetric.SetName("summary_metric_count")
sumMetric.SetName("summary_metric.count")
dp := sumMetric.Sum().DataPoints().AppendEmpty()
dp.SetIntValue(100)

Expand All @@ -70,7 +71,29 @@ func Test_ConvertSummaryCountValToSum(t *testing.T) {
sumMetric.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative)
sumMetric.Sum().SetIsMonotonic(false)

sumMetric.SetName("summary_metric_count")
sumMetric.SetName("summary_metric.count")
dp := sumMetric.Sum().DataPoints().AppendEmpty()
dp.SetIntValue(100)

attrs := getTestAttributes()
attrs.CopyTo(dp.Attributes())
},
},
{
name: "convert_summary_count_val_to_sum custom suffix",
input: getTestSummaryMetric(),
temporality: "cumulative",
monotonicity: false,
suffix: ottl.NewTestingOptional("_custom_suf"),
want: func(metrics pmetric.MetricSlice) {
summaryMetric := getTestSummaryMetric()
summaryMetric.CopyTo(metrics.AppendEmpty())
sumMetric := metrics.AppendEmpty()
sumMetric.SetEmptySum()
sumMetric.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative)
sumMetric.Sum().SetIsMonotonic(false)

sumMetric.SetName("summary_metric_custom_suf")
dp := sumMetric.Sum().DataPoints().AppendEmpty()
dp.SetIntValue(100)

Expand All @@ -94,7 +117,7 @@ func Test_ConvertSummaryCountValToSum(t *testing.T) {
actualMetrics := pmetric.NewMetricSlice()
tt.input.CopyTo(actualMetrics.AppendEmpty())

evaluate, err := convertSummaryCountValToSum(tt.temporality, tt.monotonicity)
evaluate, err := convertSummaryCountValToSum(tt.temporality, tt.monotonicity, tt.suffix)
assert.NoError(t, err)

_, err = evaluate(nil, ottldatapoint.NewTransformContext(pmetric.NewNumberDataPoint(), tt.input, actualMetrics, pcommon.NewInstrumentationScope(), pcommon.NewResource(), pmetric.NewScopeMetrics(), pmetric.NewResourceMetrics()))
Expand All @@ -119,7 +142,7 @@ func Test_ConvertSummaryCountValToSum_validation(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := convertSummaryCountValToSum(tt.stringAggTemp, true)
_, err := convertSummaryCountValToSum(tt.stringAggTemp, true, ottl.Optional[string]{})
assert.Error(t, err, "unknown aggregation temporality: not a real aggregation temporality")
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
type convertSummarySumValToSumArguments struct {
StringAggTemp string
Monotonic bool
Suffix ottl.Optional[string]
}

func newConvertSummarySumValToSumFactory() ottl.Factory[ottldatapoint.TransformContext] {
Expand All @@ -29,10 +30,14 @@ func createConvertSummarySumValToSumFunction(_ ottl.FunctionContext, oArgs ottl.
return nil, fmt.Errorf("convertSummarySumValToSumFactory args must be of type *convertSummarySumValToSumArguments")
}

return convertSummarySumValToSum(args.StringAggTemp, args.Monotonic)
return convertSummarySumValToSum(args.StringAggTemp, args.Monotonic, args.Suffix)
}

func convertSummarySumValToSum(stringAggTemp string, monotonic bool) (ottl.ExprFunc[ottldatapoint.TransformContext], error) {
func convertSummarySumValToSum(stringAggTemp string, monotonic bool, suffix ottl.Optional[string]) (ottl.ExprFunc[ottldatapoint.TransformContext], error) {
metricNameSuffix := ".sum"
if !suffix.IsEmpty() {
metricNameSuffix = suffix.Get()
}
var aggTemp pmetric.AggregationTemporality
switch stringAggTemp {
case "delta":
Expand All @@ -50,7 +55,7 @@ func convertSummarySumValToSum(stringAggTemp string, monotonic bool) (ottl.ExprF

sumMetric := tCtx.GetMetrics().AppendEmpty()
sumMetric.SetDescription(metric.Description())
sumMetric.SetName(metric.Name() + "_sum")
sumMetric.SetName(metric.Name() + metricNameSuffix)
sumMetric.SetUnit(metric.Unit())
sumMetric.SetEmptySum().SetAggregationTemporality(aggTemp)
sumMetric.Sum().SetIsMonotonic(monotonic)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"

"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl"
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/contexts/ottldatapoint"
)

Expand All @@ -18,6 +19,7 @@ type summaryTestCase struct {
input pmetric.Metric
temporality string
monotonicity bool
suffix ottl.Optional[string]
want func(pmetric.MetricSlice)
}

Expand All @@ -36,7 +38,7 @@ func Test_ConvertSummarySumValToSum(t *testing.T) {
sumMetric.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityDelta)
sumMetric.Sum().SetIsMonotonic(false)

sumMetric.SetName("summary_metric_sum")
sumMetric.SetName("summary_metric.sum")
dp := sumMetric.Sum().DataPoints().AppendEmpty()
dp.SetDoubleValue(12.34)

Expand All @@ -57,7 +59,7 @@ func Test_ConvertSummarySumValToSum(t *testing.T) {
sumMetric.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityDelta)
sumMetric.Sum().SetIsMonotonic(true)

sumMetric.SetName("summary_metric_sum")
sumMetric.SetName("summary_metric.sum")
dp := sumMetric.Sum().DataPoints().AppendEmpty()
dp.SetDoubleValue(12.34)

Expand All @@ -78,7 +80,29 @@ func Test_ConvertSummarySumValToSum(t *testing.T) {
sumMetric.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative)
sumMetric.Sum().SetIsMonotonic(false)

sumMetric.SetName("summary_metric_sum")
sumMetric.SetName("summary_metric.sum")
dp := sumMetric.Sum().DataPoints().AppendEmpty()
dp.SetDoubleValue(12.34)

attrs := getTestAttributes()
attrs.CopyTo(dp.Attributes())
},
},
{
name: "convert_summary_sum_val_to_sum custom suffix",
input: getTestSummaryMetric(),
temporality: "delta",
monotonicity: false,
suffix: ottl.NewTestingOptional("_custom_suf"),
want: func(metrics pmetric.MetricSlice) {
summaryMetric := getTestSummaryMetric()
summaryMetric.CopyTo(metrics.AppendEmpty())
sumMetric := metrics.AppendEmpty()
sumMetric.SetEmptySum()
sumMetric.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityDelta)
sumMetric.Sum().SetIsMonotonic(false)

sumMetric.SetName("summary_metric_custom_suf")
dp := sumMetric.Sum().DataPoints().AppendEmpty()
dp.SetDoubleValue(12.34)

Expand All @@ -102,7 +126,7 @@ func Test_ConvertSummarySumValToSum(t *testing.T) {
actualMetrics := pmetric.NewMetricSlice()
tt.input.CopyTo(actualMetrics.AppendEmpty())

evaluate, err := convertSummarySumValToSum(tt.temporality, tt.monotonicity)
evaluate, err := convertSummarySumValToSum(tt.temporality, tt.monotonicity, tt.suffix)
assert.NoError(t, err)

_, err = evaluate(nil, ottldatapoint.NewTransformContext(pmetric.NewNumberDataPoint(), tt.input, actualMetrics, pcommon.NewInstrumentationScope(), pcommon.NewResource(), pmetric.NewScopeMetrics(), pmetric.NewResourceMetrics()))
Expand All @@ -127,7 +151,7 @@ func Test_ConvertSummarySumValToSum_validation(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := convertSummarySumValToSum(tt.stringAggTemp, true)
_, err := convertSummarySumValToSum(tt.stringAggTemp, true, ottl.Optional[string]{})
assert.Error(t, err, "unknown aggregation temporality: not a real aggregation temporality")
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const sumCountName = "extract_count_metric"

type extractCountMetricArguments struct {
Monotonic bool
Suffix ottl.Optional[string]
}

func newExtractCountMetricFactory() ottl.Factory[ottlmetric.TransformContext] {
Expand All @@ -30,10 +31,14 @@ func createExtractCountMetricFunction(_ ottl.FunctionContext, oArgs ottl.Argumen
return nil, fmt.Errorf("extractCountMetricFactory args must be of type *extractCountMetricArguments")
}

return extractCountMetric(args.Monotonic)
return extractCountMetric(args.Monotonic, args.Suffix)
}

func extractCountMetric(monotonic bool) (ottl.ExprFunc[ottlmetric.TransformContext], error) {
func extractCountMetric(monotonic bool, suffix ottl.Optional[string]) (ottl.ExprFunc[ottlmetric.TransformContext], error) {
metricNameSuffix := ".count"
if !suffix.IsEmpty() {
metricNameSuffix = suffix.Get()
}
return func(_ context.Context, tCtx ottlmetric.TransformContext) (any, error) {
metric := tCtx.GetMetric()

Expand All @@ -44,7 +49,7 @@ func extractCountMetric(monotonic bool) (ottl.ExprFunc[ottlmetric.TransformConte

countMetric := pmetric.NewMetric()
countMetric.SetDescription(metric.Description())
countMetric.SetName(metric.Name() + "_count")
countMetric.SetName(metric.Name() + metricNameSuffix)
// Use the default unit as the original metric unit does not apply to the 'count' field
countMetric.SetUnit("1")
countMetric.SetEmptySum().SetAggregationTemporality(aggTemp)
Expand Down
Loading

0 comments on commit 24ae419

Please sign in to comment.