@@ -19,6 +19,7 @@ package elasticapmconnector // import "github.com/elastic/opentelemetry-collecto
1919
2020import (
2121 "fmt"
22+ "slices"
2223 "time"
2324
2425 signaltometricsconfig "github.com/open-telemetry/opentelemetry-collector-contrib/connector/signaltometricsconnector/config"
@@ -39,6 +40,25 @@ type Config struct {
3940 // Aggregation holds configuration related to aggregation of Elastic APM
4041 // metrics from other signals.
4142 Aggregation * AggregationConfig `mapstructure:"aggregation"`
43+
44+ // CustomResourceAttributes define a list of resource attributes that will
45+ // be added to all the aggregated metrics as optional attributes i.e. the
46+ // attribute will be added to the aggregated metrics if they are present in
47+ // the incoming signal, otherwise, the attribute will be ignored.
48+ //
49+ // NOTE: any custom attributes should have a bounded and preferably low
50+ // cardinality to be performant.
51+ CustomResourceAttributes []string `mapstructure:"custom_resource_attributes"`
52+
53+ // CustomSpanAttributes define a list of span attributes that will be added
54+ // to the aggregated `service_transaction`, `transaction`, and `span_destination`
55+ // metrics as optional attributes i.e. the attribute will be added to the
56+ // aggregated metrics if they are present in the incoming signal, otherwise,
57+ // the attribute will be ignored.
58+ //
59+ // NOTE: any custom attributes should have a bounded and preferably low
60+ // cardinality to be performant.
61+ CustomSpanAttributes []string `mapstructure:"custom_span_attributes"`
4262}
4363
4464type AggregationConfig struct {
@@ -66,8 +86,8 @@ type AggregationConfig struct {
6686 // and will not be supported.
6787 Intervals []time.Duration `mapstructure:"intervals"`
6888
69- // Limit holds optional cardinality limits for aggregated metrics
70- Limit AggregationLimitConfig `mapstructure:"limit "`
89+ // Limits holds optional cardinality limits for aggregated metrics
90+ Limits AggregationLimitConfig `mapstructure:"limits "`
7191}
7292
7393type AggregationLimitConfig struct {
@@ -119,7 +139,7 @@ func (cfg Config) lsmConfig() *lsmconfig.Config {
119139 lsmConfig .Directory = cfg .Aggregation .Directory
120140 lsmConfig .MetadataKeys = cfg .Aggregation .MetadataKeys
121141 lsmConfig .ResourceLimit = lsmconfig.LimitConfig {
122- MaxCardinality : cfg .Aggregation .Limit .ResourceLimit .MaxCardinality ,
142+ MaxCardinality : cfg .Aggregation .Limits .ResourceLimit .MaxCardinality ,
123143 Overflow : lsmconfig.OverflowConfig {
124144 Attributes : []lsmconfig.Attribute {
125145 {Key : "service.name" , Value : "_other" }, // Specific attribute required for APU UI compatibility
@@ -128,23 +148,23 @@ func (cfg Config) lsmConfig() *lsmconfig.Config {
128148 },
129149 }
130150 lsmConfig .ScopeLimit = lsmconfig.LimitConfig {
131- MaxCardinality : cfg .Aggregation .Limit .ScopeLimit .MaxCardinality ,
151+ MaxCardinality : cfg .Aggregation .Limits .ScopeLimit .MaxCardinality ,
132152 Overflow : lsmconfig.OverflowConfig {
133153 Attributes : []lsmconfig.Attribute {
134154 {Key : "overflow" , Value : "scope" },
135155 },
136156 },
137157 }
138158 lsmConfig .MetricLimit = lsmconfig.LimitConfig {
139- MaxCardinality : cfg .Aggregation .Limit .MetricLimit .MaxCardinality ,
159+ MaxCardinality : cfg .Aggregation .Limits .MetricLimit .MaxCardinality ,
140160 Overflow : lsmconfig.OverflowConfig {
141161 Attributes : []lsmconfig.Attribute {
142162 {Key : "overflow" , Value : "metric" },
143163 },
144164 },
145165 }
146166 lsmConfig .DatapointLimit = lsmconfig.LimitConfig {
147- MaxCardinality : cfg .Aggregation .Limit .DatapointLimit .MaxCardinality ,
167+ MaxCardinality : cfg .Aggregation .Limits .DatapointLimit .MaxCardinality ,
148168 Overflow : lsmconfig.OverflowConfig {
149169 Attributes : []lsmconfig.Attribute {
150170 {Key : "overflow" , Value : "datapoint" },
@@ -156,72 +176,88 @@ func (cfg Config) lsmConfig() *lsmconfig.Config {
156176}
157177
158178func (cfg Config ) signaltometricsConfig () * signaltometricsconfig.Config {
159- // serviceResourceAttributes is the resource attributes included in
160- // service-level aggregated metrics.
161- serviceResourceAttributes := []signaltometricsconfig.Attribute {
162- {Key : "service.name" },
163- {Key : "deployment.environment" }, // service.environment
164- {Key : "telemetry.sdk.language" }, // service.language.name
165-
166- // agent.name is set via elastictraceprocessor for traces,
167- // but not for other signals. Default to "unknown" for the
168- // others.
169- {
170- Key : "agent.name" ,
171- DefaultValue : "unknown" ,
172- },
173- }
179+ // commonResourceAttributes are resource attributes included in
180+ // all aggregated metrics.
181+ commonResourceAttributes := append (
182+ []signaltometricsconfig.Attribute {
183+ {Key : "service.name" },
184+ {Key : "deployment.environment" }, // service.environment
185+ {Key : "telemetry.sdk.language" }, // service.language.name
186+
187+ // agent.name is set via elastictraceprocessor for traces,
188+ // but not for other signals. Default to "unknown" for the
189+ // others.
190+ {
191+ Key : "agent.name" ,
192+ DefaultValue : "unknown" ,
193+ },
194+ }, toSignalToMetricsAttributes (cfg .CustomResourceAttributes )... ,
195+ )
196+
197+ // serviceSummaryResourceAttributes are resource attributes for service
198+ // summary metrics.
199+ serviceSummaryResourceAttributes := slices .Clone (commonResourceAttributes )
200+
201+ // serviceTransactionResourceAttributes are resource attributes for service
202+ // transaction metrics
203+ serviceTransactionResourceAttributes := slices .Clone (commonResourceAttributes )
174204
175- // transactionResourceAttributes is the resource attributes included
205+ // transactionResourceAttributes are resource attributes included
176206 // in transaction group-level aggregated metrics.
177- transactionResourceAttributes := append ([]signaltometricsconfig.Attribute {
178- {Key : "container.id" },
179- {Key : "k8s.pod.name" },
180- {Key : "service.version" },
181- {Key : "service.instance.id" }, // service.node.name
182- {Key : "process.runtime.name" }, // service.runtime.name
183- {Key : "process.runtime.version" }, // service.runtime.version
184- {Key : "telemetry.sdk.version" }, // service.language.version??
185- {Key : "host.name" },
186- {Key : "os.type" }, // host.os.platform
187- {Key : "faas.instance" },
188- {Key : "faas.name" },
189- {Key : "faas.version" },
190- {Key : "cloud.provider" },
191- {Key : "cloud.region" },
192- {Key : "cloud.availability_zone" },
193- {Key : "cloud.platform" }, // cloud.service.name
194- {Key : "cloud.account.id" },
195- }, serviceResourceAttributes ... )
207+ transactionResourceAttributes := append (
208+ []signaltometricsconfig.Attribute {
209+ {Key : "container.id" },
210+ {Key : "k8s.pod.name" },
211+ {Key : "service.version" },
212+ {Key : "service.instance.id" }, // service.node.name
213+ {Key : "process.runtime.name" }, // service.runtime.name
214+ {Key : "process.runtime.version" }, // service.runtime.version
215+ {Key : "telemetry.sdk.version" }, // service.language.version??
216+ {Key : "host.name" },
217+ {Key : "os.type" }, // host.os.platform
218+ {Key : "faas.instance" },
219+ {Key : "faas.name" },
220+ {Key : "faas.version" },
221+ {Key : "cloud.provider" },
222+ {Key : "cloud.region" },
223+ {Key : "cloud.availability_zone" },
224+ {Key : "cloud.platform" }, // cloud.service.name
225+ {Key : "cloud.account.id" },
226+ }, commonResourceAttributes ... ,
227+ )
228+
229+ // spanDestinationResourceAttributes are resource attributes included
230+ // in service destination aggregations
231+ spanDestinationResourceAttributes := slices .Clone (commonResourceAttributes )
196232
197233 serviceSummaryAttributes := []signaltometricsconfig.Attribute {{
198234 Key : "metricset.name" ,
199235 DefaultValue : "service_summary" ,
200236 }}
201237
202- serviceTransactionAttributes := []signaltometricsconfig.Attribute {
238+ serviceTransactionAttributes := append ( []signaltometricsconfig.Attribute {
203239 {Key : "transaction.root" },
204240 {Key : "transaction.type" },
205241 {Key : "metricset.name" , DefaultValue : "service_transaction" },
206- }
242+ }, toSignalToMetricsAttributes ( cfg . CustomSpanAttributes ) ... )
207243
208- transactionAttributes := []signaltometricsconfig.Attribute {
244+ transactionAttributes := append ( []signaltometricsconfig.Attribute {
209245 {Key : "transaction.root" },
210246 {Key : "transaction.name" },
211247 {Key : "transaction.type" },
212248 {Key : "transaction.result" },
213249 {Key : "event.outcome" },
214250 {Key : "metricset.name" , DefaultValue : "transaction" },
215- }
251+ }, toSignalToMetricsAttributes ( cfg . CustomSpanAttributes ) ... )
216252
217- serviceDestinationAttributes := []signaltometricsconfig.Attribute {
253+ spanDestinationAttributes := append ( []signaltometricsconfig.Attribute {
218254 {Key : "span.name" },
219255 {Key : "event.outcome" },
220256 {Key : "service.target.type" },
221257 {Key : "service.target.name" },
222258 {Key : "span.destination.service.resource" },
223259 {Key : "metricset.name" , DefaultValue : "service_destination" },
224- }
260+ }, toSignalToMetricsAttributes ( cfg . CustomSpanAttributes ) ... )
225261
226262 transactionDurationHistogram := & signaltometricsconfig.ExponentialHistogram {
227263 Count : "Int(AdjustedCount())" ,
@@ -237,30 +273,30 @@ func (cfg Config) signaltometricsConfig() *signaltometricsconfig.Config {
237273 return & signaltometricsconfig.Config {
238274 Logs : []signaltometricsconfig.MetricInfo {{
239275 Name : "service_summary" ,
240- IncludeResourceAttributes : serviceResourceAttributes ,
276+ IncludeResourceAttributes : serviceSummaryResourceAttributes ,
241277 Attributes : serviceSummaryAttributes ,
242278 Sum : & signaltometricsconfig.Sum {Value : "1" },
243279 }},
244280
245281 Datapoints : []signaltometricsconfig.MetricInfo {{
246282 Name : "service_summary" ,
247- IncludeResourceAttributes : serviceResourceAttributes ,
283+ IncludeResourceAttributes : serviceSummaryResourceAttributes ,
248284 Attributes : serviceSummaryAttributes ,
249285 Sum : & signaltometricsconfig.Sum {Value : "1" },
250286 }},
251287
252288 Spans : []signaltometricsconfig.MetricInfo {{
253289 Name : "service_summary" ,
254- IncludeResourceAttributes : serviceResourceAttributes ,
290+ IncludeResourceAttributes : serviceSummaryResourceAttributes ,
255291 Attributes : serviceSummaryAttributes ,
256292 Sum : & signaltometricsconfig.Sum {
257293 Value : "Int(AdjustedCount())" ,
258294 },
259295 }, {
260296 Name : "transaction.duration.histogram" ,
261297 Description : "APM service transaction aggregated metrics as histogram" ,
262- IncludeResourceAttributes : serviceResourceAttributes ,
263- Attributes : append (serviceTransactionAttributes [:] , signaltometricsconfig.Attribute {
298+ IncludeResourceAttributes : serviceTransactionResourceAttributes ,
299+ Attributes : append (slices . Clone ( serviceTransactionAttributes ) , signaltometricsconfig.Attribute {
264300 Key : "elasticsearch.mapping.hints" ,
265301 DefaultValue : []any {"_doc_count" },
266302 }),
@@ -269,8 +305,8 @@ func (cfg Config) signaltometricsConfig() *signaltometricsconfig.Config {
269305 }, {
270306 Name : "transaction.duration.summary" ,
271307 Description : "APM service transaction aggregated metrics as summary" ,
272- IncludeResourceAttributes : serviceResourceAttributes ,
273- Attributes : append (serviceTransactionAttributes [:] , signaltometricsconfig.Attribute {
308+ IncludeResourceAttributes : serviceTransactionResourceAttributes ,
309+ Attributes : append (slices . Clone ( serviceTransactionAttributes ) , signaltometricsconfig.Attribute {
274310 Key : "elasticsearch.mapping.hints" ,
275311 DefaultValue : []any {"aggregate_metric_double" },
276312 }),
@@ -280,7 +316,7 @@ func (cfg Config) signaltometricsConfig() *signaltometricsconfig.Config {
280316 Name : "transaction.duration.histogram" ,
281317 Description : "APM transaction aggregated metrics as histogram" ,
282318 IncludeResourceAttributes : transactionResourceAttributes ,
283- Attributes : append (transactionAttributes [:] , signaltometricsconfig.Attribute {
319+ Attributes : append (slices . Clone ( transactionAttributes ) , signaltometricsconfig.Attribute {
284320 Key : "elasticsearch.mapping.hints" ,
285321 DefaultValue : []any {"_doc_count" },
286322 }),
@@ -290,7 +326,7 @@ func (cfg Config) signaltometricsConfig() *signaltometricsconfig.Config {
290326 Name : "transaction.duration.summary" ,
291327 Description : "APM transaction aggregated metrics as summary" ,
292328 IncludeResourceAttributes : transactionResourceAttributes ,
293- Attributes : append (transactionAttributes [:] , signaltometricsconfig.Attribute {
329+ Attributes : append (slices . Clone ( transactionAttributes ) , signaltometricsconfig.Attribute {
294330 Key : "elasticsearch.mapping.hints" ,
295331 DefaultValue : []any {"aggregate_metric_double" },
296332 }),
@@ -299,17 +335,17 @@ func (cfg Config) signaltometricsConfig() *signaltometricsconfig.Config {
299335 }, {
300336 Name : "span.destination.service.response_time.sum.us" ,
301337 Description : "APM span destination metrics" ,
302- IncludeResourceAttributes : serviceResourceAttributes ,
303- Attributes : serviceDestinationAttributes ,
338+ IncludeResourceAttributes : spanDestinationResourceAttributes ,
339+ Attributes : spanDestinationAttributes ,
304340 Unit : "us" ,
305341 Sum : & signaltometricsconfig.Sum {
306342 Value : "Double(Microseconds(end_time - start_time))" ,
307343 },
308344 }, {
309345 Name : "span.destination.service.response_time.count" ,
310346 Description : "APM span destination metrics" ,
311- IncludeResourceAttributes : serviceResourceAttributes ,
312- Attributes : serviceDestinationAttributes ,
347+ IncludeResourceAttributes : spanDestinationResourceAttributes ,
348+ Attributes : spanDestinationAttributes ,
313349 Sum : & signaltometricsconfig.Sum {
314350 Value : "Int(AdjustedCount())" ,
315351 },
@@ -321,8 +357,8 @@ func (cfg Config) signaltometricsConfig() *signaltometricsconfig.Config {
321357 // values are required and the actual histogram bucket is ignored.
322358 Name : "event.success_count" ,
323359 Description : "Success count as a metric for service transaction" ,
324- IncludeResourceAttributes : serviceResourceAttributes ,
325- Attributes : append (serviceTransactionAttributes [:] , signaltometricsconfig.Attribute {
360+ IncludeResourceAttributes : serviceTransactionResourceAttributes ,
361+ Attributes : append (slices . Clone ( serviceTransactionAttributes ) , signaltometricsconfig.Attribute {
326362 Key : "elasticsearch.mapping.hints" ,
327363 DefaultValue : []any {"aggregate_metric_double" },
328364 }),
@@ -338,8 +374,8 @@ func (cfg Config) signaltometricsConfig() *signaltometricsconfig.Config {
338374 }, {
339375 Name : "event.success_count" ,
340376 Description : "Success count as a metric for service transaction" ,
341- IncludeResourceAttributes : serviceResourceAttributes ,
342- Attributes : append (serviceTransactionAttributes [:] , signaltometricsconfig.Attribute {
377+ IncludeResourceAttributes : serviceTransactionResourceAttributes ,
378+ Attributes : append (slices . Clone ( serviceTransactionAttributes ) , signaltometricsconfig.Attribute {
343379 Key : "elasticsearch.mapping.hints" ,
344380 DefaultValue : []any {"aggregate_metric_double" },
345381 }),
@@ -355,3 +391,16 @@ func (cfg Config) signaltometricsConfig() *signaltometricsconfig.Config {
355391 }},
356392 }
357393}
394+
395+ // toSignalToMetricsAttributes converts slice to string to signal to metricsa attributes
396+ // assuming `optional: true` for each attribute.
397+ func toSignalToMetricsAttributes (in []string ) []signaltometricsconfig.Attribute {
398+ attrs := make ([]signaltometricsconfig.Attribute , 0 , len (in ))
399+ for _ , k := range in {
400+ attrs = append (attrs , signaltometricsconfig.Attribute {
401+ Key : k ,
402+ Optional : true ,
403+ })
404+ }
405+ return attrs
406+ }
0 commit comments