Skip to content

Commit

Permalink
[processor/metricsgeneration] Generate metrics even when the second m…
Browse files Browse the repository at this point in the history
…etric's value is 0 (open-telemetry#35537)

**Description:**
Originally, this processor would not generate a new metric if the value
of the metric configured as `metric2` was `0`. There are valid reasons
why this calculation should still be done, and a new metric should be
calculated.

**Link to tracking Issue:** Resolves open-telemetry#35533

**Testing:**
Added tests for each calculation type to show expected results when the
second metric's value is 0.
  • Loading branch information
crobert-1 authored and jriguera committed Oct 4, 2024
1 parent 3987783 commit 2be8a43
Show file tree
Hide file tree
Showing 29 changed files with 388 additions and 103 deletions.
27 changes: 27 additions & 0 deletions .chloggen/metricsgeneration_metric2_0.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: metricsgenerationprocessor

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Generate metrics even when the second metric's value is 0

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

# (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:

# 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: []
3 changes: 0 additions & 3 deletions processor/metricsgenerationprocessor/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,6 @@ func (mgp *metricsGenerationProcessor) processMetrics(_ context.Context, md pmet
continue
}
operand2 = getMetricValue(metric2)
if operand2 <= 0 {
continue
}

} else if rule.ruleType == string(scale) {
operand2 = rule.scaleBy
Expand Down
153 changes: 89 additions & 64 deletions processor/metricsgenerationprocessor/processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,76 +391,101 @@ func getOutputForIntGaugeTest() pmetric.Metrics {
return intGaugeOutputMetrics
}

func TestSumCalculateNewMetric(t *testing.T) {
next := new(consumertest.MetricsSink)
cfg := &Config{
Rules: []Rule{
{
Name: "system.filesystem.capacity",
Unit: "bytes",
Type: "calculate",
Metric1: "system.filesystem.usage",
Metric2: "system.filesystem.utilization",
Operation: "divide",
},
},
}
factory := NewFactory()
mgp, err := factory.CreateMetricsProcessor(
context.Background(),
processortest.NewNopSettings(),
cfg,
next,
)
assert.NotNil(t, mgp)
assert.NoError(t, err)

assert.True(t, mgp.Capabilities().MutatesData)
require.NoError(t, mgp.Start(context.Background(), nil))

inputMetrics, err := golden.ReadMetrics(filepath.Join("testdata", "filesystem_metrics_input.yaml"))
assert.NoError(t, err)

err = mgp.ConsumeMetrics(context.Background(), inputMetrics)
assert.NoError(t, err)

got := next.AllMetrics()
// golden.WriteMetrics(t, filepath.Join(".", "testdata", "filesystem_metrics_expected.yaml"), got[0])
expected, err := golden.ReadMetrics(filepath.Join("testdata", "filesystem_metrics_expected.yaml"))
assert.NoError(t, err)
assert.Len(t, got, 1)
err = pmetrictest.CompareMetrics(expected, got[0],
pmetrictest.IgnoreMetricDataPointsOrder(),
pmetrictest.IgnoreStartTimestamp(),
pmetrictest.IgnoreTimestamp())
assert.NoError(t, err)
type goldenTestCases struct {
name string
testDir string
}

func TestResultingMetricTypes(t *testing.T) {
testCaseNames := []string{
"add_sum_sum",
"add_gauge_gauge",
"add_gauge_sum",
"add_sum_gauge",
"multiply_gauge_sum",
"multiply_sum_gauge",
"divide_gauge_sum",
"divide_sum_gauge",
"subtract_gauge_sum",
"subtract_sum_gauge",
"percent_sum_gauge",
"percent_gauge_sum",
func TestGoldenFileMetrics(t *testing.T) {
// Test description by test data directory:
// input_metric_types: These tests are to ensure calculations can be done on both sums and gauges
// result_metric_types: These tests are to ensure the created metric's type is correct
// metric2_zero_value: These tests are to ensure metrics are created properly when the second metric's (metric2)
// value is 0.
testCaseNames := []goldenTestCases{
{
name: "sum_gauge_metric",
testDir: "input_metric_types",
},
{
name: "add_sum_sum",
testDir: "result_metric_types",
},
{
name: "add_gauge_gauge",
testDir: "result_metric_types",
},
{
name: "add_gauge_sum",
testDir: "result_metric_types",
},
{
name: "add_sum_gauge",
testDir: "result_metric_types",
},
{
name: "multiply_gauge_sum",
testDir: "result_metric_types",
},
{
name: "multiply_sum_gauge",
testDir: "result_metric_types",
},
{
name: "divide_gauge_sum",
testDir: "result_metric_types",
},
{
name: "divide_sum_gauge",
testDir: "result_metric_types",
},
{
name: "subtract_gauge_sum",
testDir: "result_metric_types",
},
{
name: "subtract_sum_gauge",
testDir: "result_metric_types",
},
{
name: "percent_sum_gauge",
testDir: "result_metric_types",
},
{
name: "percent_gauge_sum",
testDir: "result_metric_types",
},
{
name: "metric2_zero_add",
testDir: "metric2_zero_value",
},
{
name: "metric2_zero_subtract",
testDir: "metric2_zero_value",
},
{
name: "metric2_zero_multiply",
testDir: "metric2_zero_value",
},
{
name: "metric2_zero_divide",
testDir: "metric2_zero_value",
},
{
name: "metric2_zero_percent",
testDir: "metric2_zero_value",
},
}

cm, err := confmaptest.LoadConf(filepath.Join("testdata", "metric_types", "gauge_sum_metrics_config.yaml"))
assert.NoError(t, err)

for _, testCase := range testCaseNames {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", testCase.testDir, "config.yaml"))
assert.NoError(t, err)

next := new(consumertest.MetricsSink)
factory := NewFactory()
cfg := factory.CreateDefaultConfig()

sub, err := cm.Sub(fmt.Sprintf("%s/%s", "experimental_metricsgeneration", testCase))
sub, err := cm.Sub(fmt.Sprintf("%s/%s", "experimental_metricsgeneration", testCase.name))
require.NoError(t, err)
require.NoError(t, sub.Unmarshal(cfg))

Expand All @@ -476,15 +501,15 @@ func TestResultingMetricTypes(t *testing.T) {
assert.True(t, mgp.Capabilities().MutatesData)
require.NoError(t, mgp.Start(context.Background(), nil))

inputMetrics, err := golden.ReadMetrics(filepath.Join("testdata", "metric_types", "gauge_sum_metrics_input.yaml"))
inputMetrics, err := golden.ReadMetrics(filepath.Join("testdata", testCase.testDir, "metrics_input.yaml"))
assert.NoError(t, err)

err = mgp.ConsumeMetrics(context.Background(), inputMetrics)
assert.NoError(t, err)

got := next.AllMetrics()
// golden.WriteMetrics(t, filepath.Join("testdata", "metric_types", fmt.Sprintf("%s_%s", testCase, "expected.yaml")), got[0])
expected, err := golden.ReadMetrics(filepath.Join("testdata", "metric_types", fmt.Sprintf("%s_%s", testCase, "expected.yaml")))
// golden.WriteMetrics(t, filepath.Join("testdata", testCase.testDir, fmt.Sprintf("%s_%s", testCase.name, "expected.yaml")), got[0])
expected, err := golden.ReadMetrics(filepath.Join("testdata", testCase.testDir, fmt.Sprintf("%s_%s", testCase.name, "expected.yaml")))
assert.NoError(t, err)
assert.Len(t, got, 1)
err = pmetrictest.CompareMetrics(expected, got[0],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
experimental_metricsgeneration/sum_gauge_metric:
rules:
- name: system.filesystem.capacity
unit: bytes
type: calculate
metric1: system.filesystem.usage
metric2: system.filesystem.utilization
operation: divide
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
experimental_metricsgeneration/metric2_zero_add:
rules:
- name: new_metric
metric1: capacity.total
metric2: capacity.used
operation: add
experimental_metricsgeneration/metric2_zero_subtract:
rules:
- name: new_metric
metric1: capacity.total
metric2: capacity.used
operation: subtract
experimental_metricsgeneration/metric2_zero_multiply:
rules:
- name: new_metric
metric1: capacity.total
metric2: capacity.used
operation: multiply
experimental_metricsgeneration/metric2_zero_divide:
rules:
- name: new_metric
metric1: capacity.total
metric2: capacity.used
operation: divide
experimental_metricsgeneration/metric2_zero_percent:
rules:
- name: new_metric
metric1: capacity.total
metric2: capacity.used
operation: percent
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
resourceMetrics:
- resource: {}
schemaUrl: https://opentelemetry.io/schemas/1.9.0
scopeMetrics:
- metrics:
- description: total capacity
name: capacity.total
sum:
aggregationTemporality: 2
dataPoints:
- asInt: "50"
startTimeUnixNano: "1000000"
timeUnixNano: "2000000"
unit: By
- description: used capacity
gauge:
dataPoints:
- asInt: "0"
startTimeUnixNano: "1000000"
timeUnixNano: "2000000"
name: capacity.used
unit: By
- name: new_metric
sum:
dataPoints:
- asDouble: 50
startTimeUnixNano: "1000000"
timeUnixNano: "2000000"
scope:
name: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper
version: latest
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
resourceMetrics:
- resource: {}
schemaUrl: https://opentelemetry.io/schemas/1.9.0
scopeMetrics:
- metrics:
- description: total capacity
name: capacity.total
sum:
aggregationTemporality: 2
dataPoints:
- asInt: "50"
startTimeUnixNano: "1000000"
timeUnixNano: "2000000"
unit: By
- description: used capacity
gauge:
dataPoints:
- asInt: "0"
startTimeUnixNano: "1000000"
timeUnixNano: "2000000"
name: capacity.used
unit: By
scope:
name: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper
version: latest
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
resourceMetrics:
- resource: {}
schemaUrl: https://opentelemetry.io/schemas/1.9.0
scopeMetrics:
- metrics:
- description: total capacity
name: capacity.total
sum:
aggregationTemporality: 2
dataPoints:
- asInt: "50"
startTimeUnixNano: "1000000"
timeUnixNano: "2000000"
unit: By
- description: used capacity
gauge:
dataPoints:
- asInt: "0"
startTimeUnixNano: "1000000"
timeUnixNano: "2000000"
name: capacity.used
unit: By
- name: new_metric
sum:
dataPoints:
- asDouble: 0
startTimeUnixNano: "1000000"
timeUnixNano: "2000000"
scope:
name: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper
version: latest
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
resourceMetrics:
- resource: {}
schemaUrl: https://opentelemetry.io/schemas/1.9.0
scopeMetrics:
- metrics:
- description: total capacity
name: capacity.total
sum:
aggregationTemporality: 2
dataPoints:
- asInt: "50"
startTimeUnixNano: "1000000"
timeUnixNano: "2000000"
unit: By
- description: used capacity
gauge:
dataPoints:
- asInt: "0"
startTimeUnixNano: "1000000"
timeUnixNano: "2000000"
name: capacity.used
unit: By
scope:
name: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper
version: latest
Loading

0 comments on commit 2be8a43

Please sign in to comment.