From 042cd6895649c4b25abdc20ba482f0a97e789e7d Mon Sep 17 00:00:00 2001 From: Roger Coll Date: Thu, 27 Jan 2022 14:40:05 +0100 Subject: [PATCH] fix: entity commondimension aligned with telemetry sdk --- integration/entity.go | 46 ++++++++++++--- integration/entity_test.go | 101 +++++++++++++++++++++++++++----- integration/integration_test.go | 24 +++++++- 3 files changed, 144 insertions(+), 27 deletions(-) diff --git a/integration/entity.go b/integration/entity.go index cc12697c..58ee595a 100644 --- a/integration/entity.go +++ b/integration/entity.go @@ -3,6 +3,7 @@ package integration import ( "errors" "sync" + "time" "github.com/newrelic/infra-integrations-sdk/v4/data/event" "github.com/newrelic/infra-integrations-sdk/v4/data/inventory" @@ -12,7 +13,7 @@ import ( // Entity is the producer of the data. Entity could be a host, a container, a pod, or whatever unit of meaning. type Entity struct { - CommonDimensions map[string]string `json:"common"` // dimensions common to every entity metric + CommonDimensions Common `json:"common"` // dimensions common to every entity metric Metadata *metadata.Metadata `json:"entity,omitempty"` Metrics metric.Metrics `json:"metrics"` Inventory *inventory.Inventory `json:"inventory"` @@ -20,6 +21,15 @@ type Entity struct { lock sync.Locker } +// Common is the producer of the common dimensions/attributes. +type Common struct { + Timestamp *int64 `json:"timestamp,omitempty"` + Interval *int64 `json:"interval.ms,omitempty"` + // Attributes are optional, they represent additional information that + // can be attached to an event. + Attributes map[string]interface{} `json:"attributes,omitempty"` +} + // SameAs return true when is same entity func (e *Entity) SameAs(b *Entity) bool { if e.Metadata == nil || b.Metadata == nil { @@ -60,7 +70,25 @@ func (e *Entity) AddCommonDimension(key string, value string) { e.lock.Lock() defer e.lock.Unlock() - e.CommonDimensions[key] = value + e.CommonDimensions.Attributes[key] = value +} + +// AddCommonTimestamp adds a new common timestamp to the entity. +func (e *Entity) AddCommonTimestamp(timestamp time.Time) { + e.lock.Lock() + defer e.lock.Unlock() + + t := timestamp.Unix() + e.CommonDimensions.Timestamp = &t +} + +// AddCommonInterval adds a common interval in milliseconds from a time.Duration (nanoseconds). +func (e *Entity) AddCommonInterval(timestamp time.Duration) { + e.lock.Lock() + defer e.lock.Unlock() + + t := timestamp.Milliseconds() + e.CommonDimensions.Interval = &t } // GetMetadata returns all the Entity's metadata @@ -96,12 +124,14 @@ func (e *Entity) Name() string { // newHostEntity creates a entity without metadata. func newHostEntity() *Entity { return &Entity{ - CommonDimensions: make(metric.Dimensions), - Metadata: nil, - Metrics: metric.Metrics{}, - Inventory: inventory.New(), - Events: event.Events{}, - lock: &sync.Mutex{}, + CommonDimensions: Common{ + Attributes: make(map[string]interface{}), + }, + Metadata: nil, + Metrics: metric.Metrics{}, + Inventory: inventory.New(), + Events: event.Events{}, + lock: &sync.Mutex{}, } } diff --git a/integration/entity_test.go b/integration/entity_test.go index a836e724..1e677f0b 100644 --- a/integration/entity_test.go +++ b/integration/entity_test.go @@ -217,26 +217,35 @@ func Test_Entity_EntitiesWithSameMetadataAreSameAs(t *testing.T) { func TestEntity_AddCommonDimension(t *testing.T) { tests := []struct { - name string - commons metric.Dimensions - expeceted *Entity + name string + commons metric.Dimensions + expected *Entity }{ {"empty", nil, newHostEntity()}, {"one entry", metric.Dimensions{"k": "v"}, &Entity{ - CommonDimensions: metric.Dimensions{"k": "v"}, - Metadata: nil, - Metrics: metric.Metrics{}, - Inventory: inventory.New(), - Events: event.Events{}, - lock: &sync.Mutex{}, + CommonDimensions: Common{ + Attributes: map[string]interface{}{ + "k": "v", + }, + }, + Metadata: nil, + Metrics: metric.Metrics{}, + Inventory: inventory.New(), + Events: event.Events{}, + lock: &sync.Mutex{}, }}, {"two entries", metric.Dimensions{"k1": "v1", "k2": "v2"}, &Entity{ - CommonDimensions: metric.Dimensions{"k1": "v1", "k2": "v2"}, - Metadata: nil, - Metrics: metric.Metrics{}, - Inventory: inventory.New(), - Events: event.Events{}, - lock: &sync.Mutex{}, + CommonDimensions: Common{ + Attributes: map[string]interface{}{ + "k1": "v1", + "k2": "v2", + }, + }, + Metadata: nil, + Metrics: metric.Metrics{}, + Inventory: inventory.New(), + Events: event.Events{}, + lock: &sync.Mutex{}, }}, } for _, tt := range tests { @@ -247,7 +256,67 @@ func TestEntity_AddCommonDimension(t *testing.T) { got.AddCommonDimension(k, v) } - assert.Equal(t, tt.expeceted, got) + assert.Equal(t, tt.expected, got) + }) + } +} + +func TestEntity_AddCommonTimestamp(t *testing.T) { + asPtr := func(i int64) *int64 { + return &i + } + tests := []struct { + name string + timestamp time.Time + expected *Entity + }{ + {"one entry", time.Unix(10000000, 0), &Entity{ + CommonDimensions: Common{ + Timestamp: asPtr(10000000), + }, + Metadata: nil, + Metrics: metric.Metrics{}, + Inventory: inventory.New(), + Events: event.Events{}, + lock: &sync.Mutex{}, + }}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := newHostEntity() + got.AddCommonTimestamp(tt.timestamp) + assert.NotNil(t, got.CommonDimensions.Timestamp) + assert.Equal(t, *tt.expected.CommonDimensions.Timestamp, *got.CommonDimensions.Timestamp) + }) + } +} + +func TestEntity_AddCommonInterval(t *testing.T) { + asPtr := func(i int64) *int64 { + return &i + } + tests := []struct { + name string + interval time.Duration + expected *Entity + }{ + {"one entry", time.Duration(100000000), &Entity{ + CommonDimensions: Common{ + Interval: asPtr(100), + }, + Metadata: nil, + Metrics: metric.Metrics{}, + Inventory: inventory.New(), + Events: event.Events{}, + lock: &sync.Mutex{}, + }}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := newHostEntity() + got.AddCommonInterval(tt.interval) + assert.NotNil(t, got.CommonDimensions.Interval) + assert.Equal(t, *tt.expected.CommonDimensions.Interval, *got.CommonDimensions.Interval) }) } } diff --git a/integration/integration_test.go b/integration/integration_test.go index 654299d1..9cc5b3d2 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -223,7 +223,11 @@ func Test_Integration_PublishThrowsNoError(t *testing.T) { ] }, { - "common": {}, + "common": { + "attributes": { + "targetName": "localhost" + } + }, "entity": { "name": "EntityTwo", "displayName": "", @@ -245,7 +249,14 @@ func Test_Integration_PublishThrowsNoError(t *testing.T) { "events": [] }, { - "common": {}, + "common": { + "attributes": { + "scrapedTargetKind": "user_provided", + "scrapedTargetName": "localhost:9122", + "scrapedTargetURL": "http://localhost:9122/metrics", + "targetName": "localhost:9122" + } + }, "entity": { "name": "EntityThree", "displayName": "", @@ -393,6 +404,8 @@ func Test_Integration_PublishThrowsNoError(t *testing.T) { // add entity 2 e2, err := i.NewEntity("EntityTwo", "test", "") assert.NoError(t, err) + // add common attributes + e2.AddCommonDimension("targetName", "localhost") // add metric to entity 2 gauge, _ = Gauge(time.Unix(10000000, 0), "metricOne", 2) _ = gauge.AddDimension("processName", "java") @@ -423,7 +436,12 @@ func Test_Integration_PublishThrowsNoError(t *testing.T) { // add entity 3 e3, err := i.NewEntity("EntityThree", "test", "") assert.NoError(t, err) - // add metric to entity 2 + // add common attributes + e3.AddCommonDimension("scrapedTargetKind", "user_provided") + e3.AddCommonDimension("scrapedTargetName", "localhost:9122") + e3.AddCommonDimension("scrapedTargetURL", "http://localhost:9122/metrics") + e3.AddCommonDimension("targetName", "localhost:9122") + // add metric to entity 3 summary2, _ := Summary(time.Unix(10000000, 0), "metric-summary-with-nan", 1, math.NaN(), 100, math.NaN(), math.NaN()) e3.AddMetric(summary2) // add entity 3 to integration