@@ -5,6 +5,7 @@ package operationsmanagement // import "github.com/open-telemetry/opentelemetry-
55
66import (
77 "fmt"
8+ "slices"
89
910 "go.opentelemetry.io/collector/pdata/pcommon"
1011 "go.opentelemetry.io/collector/pdata/pmetric"
@@ -57,17 +58,25 @@ func (mp *MetricsProducer) ProduceHelixPayload(metrics pmetric.Metrics) ([]BMCHe
5758
5859 // Iterate through each individual pmetric.Metric instance
5960 metrics := scopeMetric .Metrics ()
61+
6062 for k := 0 ; k < metrics .Len (); k ++ {
6163 metric := metrics .At (k )
6264
6365 // Create the payload for each metric
64- newHelixMetric , err := mp .createHelixMetric (metric , resourceAttrs )
66+ newMetrics , err := mp .createHelixMetrics (metric , resourceAttrs )
6567 if err != nil {
66- mp .logger .Warn ("Failed to create Helix metric " , zap .Error (err ))
68+ mp .logger .Warn ("Failed to create Helix metrics " , zap .Error (err ))
6769 continue
6870 }
6971
70- helixMetrics = appendMetricWithParentEntity (helixMetrics , * newHelixMetric , containerParentEntities )
72+ // Grow the helixMetrics slice for the new metrics
73+ helixMetrics = slices .Grow (helixMetrics , len (newMetrics ))
74+
75+ // Loop through the newly created metrics and append them to the helixMetrics slice
76+ // while also creating parent entities for container metrics
77+ for _ , m := range newMetrics {
78+ helixMetrics = appendMetricWithParentEntity (helixMetrics , m , containerParentEntities )
79+ }
7180 }
7281 }
7382 }
@@ -106,12 +115,48 @@ func appendMetricWithParentEntity(helixMetrics []BMCHelixOMMetric, helixMetric B
106115 return append (helixMetrics , helixMetric )
107116}
108117
109- // createHelixMetric converts a single OpenTelemetry metric into a BMCHelixOMMetric payload
110- func (mp * MetricsProducer ) createHelixMetric (metric pmetric.Metric , resourceAttrs map [string ]string ) (* BMCHelixOMMetric , error ) {
118+ // createHelixMetrics converts each OpenTelemetry datapoint into an individual BMCHelixOMMetric
119+ func (mp * MetricsProducer ) createHelixMetrics (metric pmetric.Metric , resourceAttrs map [string ]string ) ([]BMCHelixOMMetric , error ) {
120+ var helixMetrics []BMCHelixOMMetric
121+
122+ switch metric .Type () {
123+ case pmetric .MetricTypeSum :
124+ sliceLen := metric .Sum ().DataPoints ().Len ()
125+ helixMetrics = slices .Grow (helixMetrics , sliceLen )
126+ for i := 0 ; i < sliceLen ; i ++ {
127+ dp := metric .Sum ().DataPoints ().At (i )
128+ metricPayload , err := mp .createSingleDatapointMetric (dp , metric , resourceAttrs )
129+ if err != nil {
130+ mp .logger .Warn ("Failed to create Helix metric from datapoint" , zap .Error (err ))
131+ continue
132+ }
133+ helixMetrics = append (helixMetrics , * metricPayload )
134+ }
135+ case pmetric .MetricTypeGauge :
136+ sliceLen := metric .Gauge ().DataPoints ().Len ()
137+ helixMetrics = slices .Grow (helixMetrics , sliceLen )
138+ for i := 0 ; i < sliceLen ; i ++ {
139+ dp := metric .Gauge ().DataPoints ().At (i )
140+ metricPayload , err := mp .createSingleDatapointMetric (dp , metric , resourceAttrs )
141+ if err != nil {
142+ mp .logger .Warn ("Failed to create Helix metric from datapoint" , zap .Error (err ))
143+ continue
144+ }
145+ helixMetrics = append (helixMetrics , * metricPayload )
146+ }
147+ default :
148+ return nil , fmt .Errorf ("unsupported metric type %s" , metric .Type ())
149+ }
150+
151+ return helixMetrics , nil
152+ }
153+
154+ // createSingleDatapointMetric creates a single BMCHelixOMMetric from a single OpenTelemetry datapoint
155+ func (mp * MetricsProducer ) createSingleDatapointMetric (dp pmetric.NumberDataPoint , metric pmetric.Metric , resourceAttrs map [string ]string ) (* BMCHelixOMMetric , error ) {
111156 labels := make (map [string ]string )
112157 labels ["source" ] = "OTEL"
113158
114- // Add resource attributes as labels
159+ // Add resource attributes
115160 for k , v := range resourceAttrs {
116161 labels [k ] = v
117162 }
@@ -128,58 +173,20 @@ func (mp *MetricsProducer) createHelixMetric(metric pmetric.Metric, resourceAttr
128173 // Update the metric name for the BMC Helix Operations Management payload
129174 labels ["metricName" ] = metric .Name ()
130175
131- // Samples to hold the metric values
132- samples := []BMCHelixOMSample {}
133-
134- // Handle different types of metrics (sum and gauge)
135- // BMC Helix Operations Management only supports simple metrics (sum, gauge, etc.) and not histograms or summaries
136- switch metric .Type () {
137- case pmetric .MetricTypeSum :
138- dataPoints := metric .Sum ().DataPoints ()
139- for i := 0 ; i < dataPoints .Len (); i ++ {
140- samples = mp .processDatapoint (samples , dataPoints .At (i ), labels , metric , resourceAttrs )
141- }
142- case pmetric .MetricTypeGauge :
143- dataPoints := metric .Gauge ().DataPoints ()
144- for i := 0 ; i < dataPoints .Len (); i ++ {
145- samples = mp .processDatapoint (samples , dataPoints .At (i ), labels , metric , resourceAttrs )
146- }
147- default :
148- return nil , fmt .Errorf ("unsupported metric type %s" , metric .Type ())
149- }
150-
151- // Check if the hostname is set
152- if labels ["hostname" ] == "" {
153- return nil , fmt .Errorf ("hostname is required for the BMC Helix Operations Management payload but not set for metric %s" , metric .Name ())
154- }
155-
156- // Check if the entityTypeId is set
157- if labels ["entityTypeId" ] == "" {
158- return nil , fmt .Errorf ("entityTypeId is required for the BMC Helix Operations Management payload but not set for metric %s" , metric .Name ())
176+ // Update the entity information
177+ err := mp .updateEntityInformation (labels , metric .Name (), resourceAttrs , dp .Attributes ().AsRaw ())
178+ if err != nil {
179+ return nil , err
159180 }
160181
161- // Check if the entityName is set
162- if labels ["entityName" ] == "" {
163- return nil , fmt .Errorf ("entityName is required for the BMC Helix Operations Management payload but not set for metric %s" , metric .Name ())
164- }
182+ sample := newSample (dp )
165183
166184 return & BMCHelixOMMetric {
167185 Labels : labels ,
168- Samples : samples ,
186+ Samples : [] BMCHelixOMSample { sample } ,
169187 }, nil
170188}
171189
172- // Updates the metric information for the BMC Helix Operations Management payload and returns the updated samples
173- func (mp * MetricsProducer ) processDatapoint (samples []BMCHelixOMSample , dp pmetric.NumberDataPoint , labels map [string ]string , metric pmetric.Metric , resourceAttrs map [string ]string ) []BMCHelixOMSample {
174- // Update the entity information for the BMC Helix Operations Management payload
175- err := mp .updateEntityInformation (labels , metric .Name (), resourceAttrs , dp .Attributes ().AsRaw ())
176- if err != nil {
177- mp .logger .Warn ("Failed to update entity information" , zap .Error (err ))
178- }
179-
180- return append (samples , newSample (dp ))
181- }
182-
183190// Update the entity information for the BMC Helix Operations Management payload
184191func (mp * MetricsProducer ) updateEntityInformation (labels map [string ]string , metricName string , resourceAttrs map [string ]string , dpAttributes map [string ]any ) error {
185192 // Try to get the hostname from resource attributes first
0 commit comments