Skip to content

Commit

Permalink
can add scalar resource attributes to scalar metrics successfully
Browse files Browse the repository at this point in the history
  • Loading branch information
kuiperda committed Aug 21, 2023
1 parent 0fb327a commit b177fa9
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 11 deletions.
1 change: 1 addition & 0 deletions receiver/snmpreceiver/config_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func newConfigHelper(cfg *Config) *configHelper {
ch.metricScalarOIDs = append(ch.metricScalarOIDs, oid.OID)
ch.metricNamesByOID[oid.OID] = name
ch.metricAttributesByOID[oid.OID] = oid.Attributes
ch.resourceAttributesByOID[oid.OID] = oid.ResourceAttributes
}

for i, oid := range metricCfg.ColumnOIDs {
Expand Down
41 changes: 33 additions & 8 deletions receiver/snmpreceiver/scraper.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,12 @@ func (s *snmpScraper) scrapeScalarMetrics(
if len(scalarData) == 0 {
return
}

// Create general resource if we're about to make scalar metrics
resource := metricHelper.getResource(generalResourceKey)
if resource == nil {
metricHelper.createResource(generalResourceKey, map[string]string{})
}
// Retrieve scalar OID SNMP data for resource attributes
scalarOIDScalarResourceAttributeValues := s.scrapeScalarResourceAttributes(configHelper.getResourceAttributeScalarOIDs(), scraperErrors)

// For each piece of SNMP data, attempt to create the necessary OTEL structures (resources/metrics/datapoints)
for _, data := range scalarData {
if err := s.scalarDataToMetric(data, metricHelper, configHelper); err != nil {
if err := s.scalarDataToMetric(data, metricHelper, configHelper, scalarOIDScalarResourceAttributeValues); err != nil {
scraperErrors.AddPartial(1, fmt.Errorf(errMsgScalarOIDProcessing, data.oid, err))
}
}
Expand Down Expand Up @@ -158,6 +154,7 @@ func (s *snmpScraper) scalarDataToMetric(
data SNMPData,
metricHelper *otelMetricHelper,
configHelper *configHelper,
scalarOIDScalarResourceAttributeValues map[string]string,
) error {
// Get the related metric name for this SNMP indexed data
metricName := configHelper.getMetricName(data.oid)
Expand All @@ -166,7 +163,35 @@ func (s *snmpScraper) scalarDataToMetric(
// the metric config's attribute values.
dataPointAttributes := getScalarDataPointAttributes(configHelper, data.oid)

return addMetricDataPointToResource(data, metricHelper, configHelper, metricName, generalResourceKey, dataPointAttributes)
// Get resource attributes
resourceAttributes, err := getResourceAttributes(configHelper, data.oid, "0", map[string]indexedAttributeValues{}, scalarOIDScalarResourceAttributeValues)
if err != nil {
return fmt.Errorf(errMsgOIDResourceAttributeEmptyValue, metricName, err)
}

// Create a resource key using all of the relevant resource attribute names
resourceAttributeNames := configHelper.getResourceAttributeNames(data.oid)

if len(resourceAttributeNames) > 0 {
resourceKey := getResourceKey(resourceAttributeNames, "0")

// Create a new resource if needed
resource := metricHelper.getResource(resourceKey)
if resource == nil {
metricHelper.createResource(resourceKey, resourceAttributes)
}

return addMetricDataPointToResource(data, metricHelper, configHelper, metricName, resourceKey, dataPointAttributes)
} else {
// Create general resource if we don't have any resource attributes
resource := metricHelper.getResource(generalResourceKey)
if resource == nil {
metricHelper.createResource(generalResourceKey, map[string]string{})
}

return addMetricDataPointToResource(data, metricHelper, configHelper, metricName, generalResourceKey, dataPointAttributes)
}

}

// indexedDataToMetric will take one piece of column OID SNMP indexed metric data and turn it
Expand Down
132 changes: 129 additions & 3 deletions receiver/snmpreceiver/scraper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@ import (
"path/filepath"
"testing"

"github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/golden"
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/pmetrictest"
"github.com/stretchr/testify/mock" // client is an autogenerated mock type for the client type
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/component/componenttest"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.opentelemetry.io/collector/receiver/receivertest"
"go.opentelemetry.io/collector/receiver/scrapererror"
"go.uber.org/zap"

"github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/golden"
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/pmetrictest"
)
type MockClient struct {
mock.Mock
Expand Down Expand Up @@ -2779,6 +2778,133 @@ func TestScrape(t *testing.T) {
require.NoError(t, err)
},
},
{
desc: "ScalarOID (string) resource attribute attached to ScalarOID metric creates metric (26)",
testFunc: func (t *testing.T) {
mockClient := new(MockClient)
scalarRA := SNMPData{
oid: ".5.0",
value: "scalar",
valueType: stringVal,
}
scalarOID := SNMPData{
oid: ".6.0",
value: int64(6),
valueType: integerVal,
}
mockClient.On("Connect").Return(nil)
mockClient.On("Close").Return(nil)
mockClient.On("GetScalarData", []string{".5.0"}, mock.Anything).Return([]SNMPData{scalarRA}).Once()
mockClient.On("GetScalarData", []string{".6.0"}, mock.Anything).Return([]SNMPData{scalarOID}).Once()
scraper := &snmpScraper{
cfg: &Config{
ResourceAttributes: map[string]*ResourceAttributeConfig{
"rattr1": {
ScalarOID: ".5.0",
},
},
Metrics: map[string]*MetricConfig{
"metric1": {
Description: "test description",
Unit: "By",
Gauge: &GaugeMetric{
ValueType: "int",
},
ScalarOIDs: []ScalarOID{
{
OID: ".6.0",
ResourceAttributes: []string{"rattr1"},
},
},
},
},
},
settings: receivertest.NewNopCreateSettings(),
client: mockClient,
logger: zap.NewNop(),
}

expectedMetricGen := func(t *testing.T) pmetric.Metrics {
goldenPath := filepath.Join("testdata", "expected_metrics", "26_scalar_ra_string_on_scalar_metric_golden.yaml")
expectedMetrics, err := golden.ReadMetrics(goldenPath)
require.NoError(t, err)
return expectedMetrics
}
expectedMetrics := expectedMetricGen(t)
metrics, err := scraper.scrape(context.Background())
require.NoError(t, err)
err = pmetrictest.CompareMetrics(expectedMetrics, metrics, pmetrictest.IgnoreTimestamp())
require.NoError(t, err)
},
},
// same issue with mock values being right order 50% (or less, haha) of the time
// {
// desc: "Multiple ScalarOID (string) resource attributes attached to ScalarOID metric creates single resource for metric (27)",
// testFunc: func (t *testing.T) {
// mockClient := new(MockClient)
// scalarRA1 := SNMPData{
// oid: ".5.0",
// value: "scalar",
// valueType: stringVal,
// }
// scalarRA2 := SNMPData{
// oid: ".7.0",
// value: "also scalar",
// valueType: stringVal,
// }
// scalarOID := SNMPData{
// oid: ".6.0",
// value: int64(6),
// valueType: integerVal,
// }
// mockClient.On("Connect").Return(nil)
// mockClient.On("Close").Return(nil)
// mockClient.On("GetScalarData", []string{".5.0", ".7.0"}, mock.Anything).Return([]SNMPData{scalarRA1, scalarRA2}).Once()
// mockClient.On("GetScalarData", []string{".6.0"}, mock.Anything).Return([]SNMPData{scalarOID}).Once()
// scraper := &snmpScraper{
// cfg: &Config{
// ResourceAttributes: map[string]*ResourceAttributeConfig{
// "rattr1": {
// ScalarOID: ".5.0",
// },
// "rattr2": {
// ScalarOID: ".7.0",
// },
// },
// Metrics: map[string]*MetricConfig{
// "metric1": {
// Description: "test description",
// Unit: "By",
// Gauge: &GaugeMetric{
// ValueType: "int",
// },
// ScalarOIDs: []ScalarOID{
// {
// OID: ".6.0",
// ResourceAttributes: []string{"rattr1", "rattr2"},
// },
// },
// },
// },
// },
// settings: receivertest.NewNopCreateSettings(),
// client: mockClient,
// logger: zap.NewNop(),
// }

// expectedMetricGen := func(t *testing.T) pmetric.Metrics {
// goldenPath := filepath.Join("testdata", "expected_metrics", "27_multiple_scalar_ra_string_on_scalar_metric_golden.yaml")
// expectedMetrics, err := golden.ReadMetrics(goldenPath)
// require.NoError(t, err)
// return expectedMetrics
// }
// expectedMetrics := expectedMetricGen(t)
// metrics, err := scraper.scrape(context.Background())
// require.NoError(t, err)
// err = pmetrictest.CompareMetrics(expectedMetrics, metrics, pmetrictest.IgnoreTimestamp())
// require.NoError(t, err)
// },
// },
}

for _, tc := range testCases {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
resourceMetrics:
- resource:
attributes:
- key: rattr1
value:
stringValue: scalar
scopeMetrics:
- metrics:
- description: test description
gauge:
dataPoints:
- asInt: "6"
timeUnixNano: "1651783494931319000"
name: metric1
unit: By
scope:
name: otelcol/snmpreceiver
version: latest
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
resourceMetrics:
- resource:
attributes:
- key: rattr1
value:
stringValue: scalar
- key: rattr2
value:
stringValue: also scalar
scopeMetrics:
- metrics:
- description: test description
gauge:
dataPoints:
- asInt: "6"
timeUnixNano: "1651783494931319000"
name: metric1
unit: By
scope:
name: otelcol/snmpreceiver
version: latest

0 comments on commit b177fa9

Please sign in to comment.