Skip to content

Commit

Permalink
[receivertest] add metrics support to contract_checker (#9551)
Browse files Browse the repository at this point in the history
**Description:**
add support for metrics in contract checker

---------

Co-authored-by: Dmitrii Anoshin <anoshindx@gmail.com>
  • Loading branch information
atoulme and dmitryax committed Feb 23, 2024
1 parent 08a6922 commit 6be5fe9
Show file tree
Hide file tree
Showing 3 changed files with 404 additions and 15 deletions.
25 changes: 25 additions & 0 deletions .chloggen/implement_contract_checker.yaml
@@ -0,0 +1,25 @@
# Use this changelog template to create an entry for release notes.

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

# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
component: receivertest

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: add support for metrics in contract checker

# One or more tracking issues or pull requests related to the change
issues: [9551]

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

# 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: [api]
134 changes: 131 additions & 3 deletions receiver/receivertest/contract_checker.go
Expand Up @@ -22,6 +22,7 @@ import (
"go.opentelemetry.io/collector/consumer/consumererror"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.opentelemetry.io/collector/pdata/ptrace"
"go.opentelemetry.io/collector/receiver"
)
Expand Down Expand Up @@ -116,8 +117,7 @@ func checkConsumeContractScenario(params CheckConsumeContractParams, decisionFun
case component.DataTypeTraces:
receiver, err = params.Factory.CreateTracesReceiver(ctx, NewNopCreateSettings(), params.Config, consumer)
case component.DataTypeMetrics:
// TODO: add metrics support to mockConsumer so that this case can be also implemented.
require.FailNow(params.T, "DataTypeMetrics is not implemented")
receiver, err = params.Factory.CreateMetricsReceiver(ctx, NewNopCreateSettings(), params.Config, consumer)
default:
require.FailNow(params.T, "must specify a valid DataType to test for")
}
Expand Down Expand Up @@ -384,7 +384,76 @@ func idSetFromLogs(data plog.Logs) (idSet, error) {
return ds, nil
}

// TODO: Implement mockConsumer.ConsumeMetrics()
func (m *mockConsumer) ConsumeMetrics(_ context.Context, data pmetric.Metrics) error {
ids, err := idSetFromMetrics(data)
require.NoError(m.t, err)
return m.consume(ids)
}

// idSetFromLogs computes an idSet from given pmetric.Metrics. The idSet will contain ids of all metric data points.
func idSetFromMetrics(data pmetric.Metrics) (idSet, error) {
ds := map[UniqueIDAttrVal]bool{}
rss := data.ResourceMetrics()
for i := 0; i < rss.Len(); i++ {
ils := rss.At(i).ScopeMetrics()
for j := 0; j < ils.Len(); j++ {
ss := ils.At(j).Metrics()
for k := 0; k < ss.Len(); k++ {
elem := ss.At(k)
switch elem.Type() {
case pmetric.MetricTypeGauge:
for l := 0; l < elem.Gauge().DataPoints().Len(); l++ {
dp := elem.Gauge().DataPoints().At(l)
if err := idSetFromDataPoint(ds, dp.Attributes()); err != nil {
return ds, err
}
}
case pmetric.MetricTypeSum:
for l := 0; l < elem.Sum().DataPoints().Len(); l++ {
dp := elem.Sum().DataPoints().At(l)
if err := idSetFromDataPoint(ds, dp.Attributes()); err != nil {
return ds, err
}
}
case pmetric.MetricTypeSummary:
for l := 0; l < elem.Summary().DataPoints().Len(); l++ {
dp := elem.Summary().DataPoints().At(l)
if err := idSetFromDataPoint(ds, dp.Attributes()); err != nil {
return ds, err
}
}
case pmetric.MetricTypeHistogram:
for l := 0; l < elem.Histogram().DataPoints().Len(); l++ {
dp := elem.Histogram().DataPoints().At(l)
if err := idSetFromDataPoint(ds, dp.Attributes()); err != nil {
return ds, err
}
}
case pmetric.MetricTypeExponentialHistogram:
for l := 0; l < elem.ExponentialHistogram().DataPoints().Len(); l++ {
dp := elem.ExponentialHistogram().DataPoints().At(l)
if err := idSetFromDataPoint(ds, dp.Attributes()); err != nil {
return ds, err
}
}
}
}
}
}
return ds, nil
}

func idSetFromDataPoint(ds map[UniqueIDAttrVal]bool, attributes pcommon.Map) error {
key, exists := attributes.Get(UniqueIDAttrName)
if !exists {
return fmt.Errorf("invalid data element, attribute %q is missing", UniqueIDAttrName)
}
if key.Type() != pcommon.ValueTypeStr {
return fmt.Errorf("invalid data element, attribute %q is wrong type %v", UniqueIDAttrName, key.Type())
}
ds[UniqueIDAttrVal(key.Str())] = true
return nil
}

// consume the elements with the specified ids, regardless of the element data type.
func (m *mockConsumer) consume(ids idSet) error {
Expand Down Expand Up @@ -431,3 +500,62 @@ func CreateOneLogWithID(id UniqueIDAttrVal) plog.Logs {
)
return data
}

func CreateGaugeMetricWithID(id UniqueIDAttrVal) pmetric.Metrics {
data := pmetric.NewMetrics()
gauge := data.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics()
gauge.AppendEmpty().SetEmptyGauge().DataPoints().AppendEmpty().Attributes().PutStr(
UniqueIDAttrName,
string(id),
)
return data
}

func CreateSumMetricWithID(id UniqueIDAttrVal) pmetric.Metrics {
data := pmetric.NewMetrics()
sum := data.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics()
sum.AppendEmpty().SetEmptySum().DataPoints().AppendEmpty().Attributes().PutStr(
UniqueIDAttrName,
string(id),
)
return data
}

func CreateSummaryMetricWithID(id UniqueIDAttrVal) pmetric.Metrics {
data := pmetric.NewMetrics()
summary := data.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics()
summary.AppendEmpty().SetEmptySummary().DataPoints().AppendEmpty().Attributes().PutStr(
UniqueIDAttrName,
string(id),
)
return data
}

func CreateHistogramMetricWithID(id UniqueIDAttrVal) pmetric.Metrics {
data := pmetric.NewMetrics()
histogram := data.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics()
histogram.AppendEmpty().SetEmptyHistogram().DataPoints().AppendEmpty().Attributes().PutStr(
UniqueIDAttrName,
string(id),
)
return data
}

func CreateExponentialHistogramMetricWithID(id UniqueIDAttrVal) pmetric.Metrics {
data := pmetric.NewMetrics()
exponentialHistogram := data.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics()
exponentialHistogram.AppendEmpty().SetEmptyExponentialHistogram().DataPoints().AppendEmpty().Attributes().PutStr(
UniqueIDAttrName,
string(id),
)
return data
}

func CreateOneSpanWithID(id UniqueIDAttrVal) ptrace.Traces {
data := ptrace.NewTraces()
data.ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty().Attributes().PutStr(
UniqueIDAttrName,
string(id),
)
return data
}

0 comments on commit 6be5fe9

Please sign in to comment.