Skip to content

Commit 1da3fff

Browse files
[receiver/elasticapmintake] Apm intake span updates (#905)
* Update `event.Span.Composite.Sum` attribute name and use double instead of int * Update `event.Span.Action` to only be set when it is not empty * Update mapping to avoid setting empty fields * Update span kind logic to first attempt to enumerate the provided span.kind value before attempting to derive
1 parent f6afb20 commit 1da3fff

16 files changed

+208
-241
lines changed

receiver/elasticapmintakereceiver/internal/attributes.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const (
2323
SpanDBLink = "span.db.link"
2424
SpanDBRowsAffected = "span.db.rows_affected"
2525
SpanDBUserName = "span.db.user.name"
26-
SpanCompositeSum = "span.composite.sum"
26+
SpanCompositeSumUs = "span.composite.sum.us"
2727
SpanCompositeCompressionStrategy = "span.composite.compression_strategy"
2828
SpanCompositeCount = "span.composite.count"
2929
SpanDestinationServiceName = "span.destination.service.name"
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Licensed to Elasticsearch B.V. under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Elasticsearch B.V. licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package mappers // import "github.com/elastic/opentelemetry-collector-components/receiver/elasticapmintakereceiver/internal/mappers"
19+
20+
import (
21+
"go.opentelemetry.io/collector/pdata/pcommon"
22+
)
23+
24+
// putNonEmptyStr puts a string attribute in the given map
25+
// only if the provided value is not empty.
26+
func putNonEmptyStr(attributes pcommon.Map, key, value string) {
27+
if value != "" {
28+
attributes.PutStr(key, value)
29+
}
30+
}

receiver/elasticapmintakereceiver/internal/mappers/intakeV2ToDerivedFields.go

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,28 @@ import (
3434
// SetDerivedFieldsForTransaction sets fields that are NOT part of OTel for transactions. These fields are derived by the Enrichment lib in case of OTLP input
3535
func SetDerivedFieldsForTransaction(event *modelpb.APMEvent, attributes pcommon.Map) {
3636
attributes.PutStr(elasticattr.ProcessorEvent, "transaction")
37-
attributes.PutStr(elasticattr.TransactionName, event.Transaction.Name)
38-
attributes.PutBool(elasticattr.TransactionSampled, event.Transaction.Sampled)
39-
// from whatever reason Transaction.Root is always false. That seems to be a derived field already - I don't see that fields directly on IntakeV2 - there is only ParentId
40-
attributes.PutBool(elasticattr.TransactionRoot, event.ParentId == "")
41-
attributes.PutStr(elasticattr.TransactionType, event.Transaction.Type)
42-
attributes.PutStr(elasticattr.TransactionResult, event.Transaction.Result)
4337
attributes.PutInt(elasticattr.TransactionDurationUs, int64(event.Event.Duration/1_000))
4438

4539
setCommonDerivedRecordAttributes(event, attributes)
40+
41+
// from whatever reason Transaction.Root is always false. That seems to be a derived field already - I don't see that fields directly on IntakeV2 - there is only ParentId
42+
attributes.PutBool(elasticattr.TransactionRoot, event.ParentId == "")
43+
44+
if event.Transaction == nil {
45+
return
46+
}
47+
48+
putNonEmptyStr(attributes, elasticattr.TransactionName, event.Transaction.Name)
49+
putNonEmptyStr(attributes, elasticattr.TransactionType, event.Transaction.Type)
50+
putNonEmptyStr(attributes, elasticattr.TransactionResult, event.Transaction.Result)
51+
attributes.PutBool(elasticattr.TransactionSampled, event.Transaction.Sampled)
4652
}
4753

4854
// setCommonDerivedRecordAttributes sets common attributes which are shared at the record
4955
// level for span, transaction, and error events.
5056
func setCommonDerivedRecordAttributes(event *modelpb.APMEvent, attributes pcommon.Map) {
51-
if event.Transaction != nil && event.Transaction.Id != "" {
52-
attributes.PutStr(elasticattr.TransactionID, event.Transaction.Id)
57+
if event.Transaction != nil {
58+
putNonEmptyStr(attributes, elasticattr.TransactionID, event.Transaction.Id)
5359
}
5460

5561
if event.Service != nil && event.Service.Target != nil {
@@ -70,17 +76,18 @@ func SetDerivedFieldsForSpan(event *modelpb.APMEvent, attributes pcommon.Map) {
7076
}
7177

7278
attributes.PutStr("span.id", event.Span.Id)
73-
attributes.PutStr(elasticattr.SpanName, event.Span.Name)
74-
attributes.PutStr(elasticattr.SpanType, event.Span.Type)
75-
attributes.PutStr(elasticattr.SpanSubtype, event.Span.Subtype)
76-
attributes.PutStr("span.action", event.Span.Action)
79+
80+
putNonEmptyStr(attributes, elasticattr.SpanName, event.Span.Name)
81+
putNonEmptyStr(attributes, elasticattr.SpanType, event.Span.Type)
82+
putNonEmptyStr(attributes, elasticattr.SpanSubtype, event.Span.Subtype)
83+
putNonEmptyStr(attributes, "span.action", event.Span.Action)
7784

7885
if event.Span.Sync != nil {
7986
attributes.PutBool("span.sync", *event.Span.Sync)
8087
}
8188

8289
if event.Span.DestinationService != nil {
83-
attributes.PutStr(elasticattr.SpanDestinationServiceResource, event.Span.DestinationService.Resource)
90+
putNonEmptyStr(attributes, elasticattr.SpanDestinationServiceResource, event.Span.DestinationService.Resource)
8491
}
8592
}
8693

receiver/elasticapmintakereceiver/internal/mappers/intakeV2ToElasticSpecificFields.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func SetElasticSpecificFieldsForSpan(event *modelpb.APMEvent, attributesMap pcom
7575
attributesMap.PutStr(attr.SpanCompositeCompressionStrategy, compressionStrategy)
7676
}
7777
attributesMap.PutInt(attr.SpanCompositeCount, int64(event.Span.Composite.Count))
78-
attributesMap.PutInt(attr.SpanCompositeSum, int64(event.Span.Composite.Sum))
78+
attributesMap.PutDouble(attr.SpanCompositeSumUs, event.Span.Composite.Sum)
7979
}
8080

8181
if event.Span.DestinationService != nil {

receiver/elasticapmintakereceiver/internal/mappers/intakeV2ToSemConv.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,12 @@ import (
3232
// TranslateToOtelResourceAttributes translates resource attributes from the Elastic APM model to SemConv resource attributes
3333
func TranslateToOtelResourceAttributes(event *modelpb.APMEvent, attributes pcommon.Map) {
3434
if event.Service != nil {
35-
attributes.PutStr(string(semconv.ServiceNameKey), event.Service.Name)
36-
attributes.PutStr(string(semconv.ServiceVersionKey), event.Service.Version)
35+
if event.Service.Name != "" {
36+
attributes.PutStr(string(semconv.ServiceNameKey), event.Service.Name)
37+
}
38+
if event.Service.Version != "" {
39+
attributes.PutStr(string(semconv.ServiceVersionKey), event.Service.Version)
40+
}
3741
if event.Service.Language != nil && event.Service.Language.Name != "" {
3842
attributes.PutStr(string(semconv.TelemetrySDKLanguageKey), translateElasticServiceLanguageToOtelSdkLanguage(event.Service.Language.Name))
3943
}

receiver/elasticapmintakereceiver/receiver.go

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"hash"
2626
"net"
2727
"net/http"
28+
"strings"
2829
"sync"
2930
"time"
3031

@@ -576,11 +577,16 @@ func (r *elasticAPMIntakeReceiver) elasticTransactionToOtelSpan(s *ptrace.Span,
576577
mappers.TranslateIntakeV2TransactionToOTelAttributes(event, s.Attributes())
577578
mappers.SetElasticSpecificFieldsForTransaction(event, s.Attributes())
578579

579-
if event.Http != nil && event.Http.Request != nil {
580-
s.SetKind(ptrace.SpanKindServer)
581-
} else if event.Message != "" { // this check is TBD
582-
s.SetKind(ptrace.SpanKindConsumer)
580+
spanKind := mapSpanKind(event.GetSpan().GetKind())
581+
if spanKind == ptrace.SpanKindUnspecified {
582+
// derive span kind
583+
if event.Http != nil && event.Http.Request != nil {
584+
spanKind = ptrace.SpanKindServer
585+
} else if event.Message != "" { // this check is TBD
586+
spanKind = ptrace.SpanKindConsumer
587+
}
583588
}
589+
s.SetKind(spanKind)
584590
}
585591

586592
func (r *elasticAPMIntakeReceiver) elasticSpanToOTelSpan(s *ptrace.Span, event *modelpb.APMEvent) {
@@ -591,8 +597,29 @@ func (r *elasticAPMIntakeReceiver) elasticSpanToOTelSpan(s *ptrace.Span, event *
591597
mappers.TranslateIntakeV2SpanToOTelAttributes(event, s.Attributes())
592598
mappers.SetElasticSpecificFieldsForSpan(event, s.Attributes())
593599

594-
if event.Http != nil || event.Message != "" {
595-
s.SetKind(ptrace.SpanKindClient)
600+
spanKind := mapSpanKind(event.GetSpan().GetKind())
601+
if spanKind == ptrace.SpanKindUnspecified {
602+
if event.Http != nil || event.Message != "" {
603+
spanKind = ptrace.SpanKindClient
604+
}
605+
}
606+
s.SetKind(spanKind)
607+
}
608+
609+
func mapSpanKind(kind string) ptrace.SpanKind {
610+
switch strings.ToUpper(kind) {
611+
case "INTERNAL":
612+
return ptrace.SpanKindInternal
613+
case "CLIENT":
614+
return ptrace.SpanKindClient
615+
case "PRODUCER":
616+
return ptrace.SpanKindProducer
617+
case "CONSUMER":
618+
return ptrace.SpanKindConsumer
619+
case "SERVER":
620+
return ptrace.SpanKindServer
621+
default:
622+
return ptrace.SpanKindUnspecified
596623
}
597624
}
598625

receiver/elasticapmintakereceiver/testdata/errors_expected.yaml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ resourceLogs:
44
- key: service.name
55
value:
66
stringValue: service1
7-
- key: service.version
8-
value:
9-
stringValue: ""
107
- key: telemetry.sdk.language
118
value:
129
stringValue: ecmascript
@@ -1086,12 +1083,12 @@ resourceLogs:
10861083
- key: processor.event
10871084
value:
10881085
stringValue: error
1089-
- key: error.id
1090-
value:
1091-
stringValue: abcdef0123456789
10921086
- key: transaction.id
10931087
value:
10941088
stringValue: "1234567890987654"
1089+
- key: error.id
1090+
value:
1091+
stringValue: abcdef0123456789
10951092
- key: parent.id
10961093
value:
10971094
stringValue: 9632587410abcdef

receiver/elasticapmintakereceiver/testdata/hostdata_expected.yaml

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ resourceSpans:
44
- key: service.name
55
value:
66
stringValue: SampleAspNetCoreApp
7-
- key: service.version
8-
value:
9-
stringValue: ""
107
- key: telemetry.sdk.language
118
value:
129
stringValue: dotnet
@@ -62,12 +59,12 @@ resourceSpans:
6259
- key: processor.event
6360
value:
6461
stringValue: transaction
65-
- key: transaction.name
62+
- key: transaction.duration.us
6663
value:
67-
stringValue: ""
68-
- key: transaction.sampled
64+
intValue: "32592"
65+
- key: transaction.id
6966
value:
70-
boolValue: true
67+
stringValue: 945254c567a5417e
7168
- key: transaction.root
7269
value:
7370
boolValue: false
@@ -77,12 +74,9 @@ resourceSpans:
7774
- key: transaction.result
7875
value:
7976
stringValue: Success
80-
- key: transaction.duration.us
81-
value:
82-
intValue: "32592"
83-
- key: transaction.id
77+
- key: transaction.sampled
8478
value:
85-
stringValue: 945254c567a5417e
79+
boolValue: true
8680
- key: transaction.span_count.started
8781
value:
8882
intValue: "43"
@@ -94,6 +88,7 @@ resourceSpans:
9488
- stringValue: bar
9589
- stringValue: foo
9690
endTimeUnixNano: "1496170407186592981"
91+
kind: 2
9792
parentSpanId: abcdefabcdef0123
9893
spanId: 945254c567a5417e
9994
startTimeUnixNano: "1496170407154000000"

receiver/elasticapmintakereceiver/testdata/invalid_ids_expected.yaml

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -146,27 +146,21 @@ resourceSpans:
146146
- key: processor.event
147147
value:
148148
stringValue: transaction
149-
- key: transaction.name
149+
- key: transaction.duration.us
150150
value:
151-
stringValue: ""
152-
- key: transaction.sampled
151+
intValue: "32592"
152+
- key: transaction.id
153153
value:
154-
boolValue: true
154+
stringValue: foobarInvalid
155155
- key: transaction.root
156156
value:
157157
boolValue: false
158158
- key: transaction.type
159159
value:
160160
stringValue: request
161-
- key: transaction.result
162-
value:
163-
stringValue: ""
164-
- key: transaction.duration.us
165-
value:
166-
intValue: "32592"
167-
- key: transaction.id
161+
- key: transaction.sampled
168162
value:
169-
stringValue: foobarInvalid
163+
boolValue: true
170164
- key: transaction.span_count.started
171165
value:
172166
intValue: "43"

receiver/elasticapmintakereceiver/testdata/language_name_mapping_expected.yaml

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ resourceSpans:
5959
- key: processor.event
6060
value:
6161
stringValue: transaction
62-
- key: transaction.name
62+
- key: transaction.duration.us
6363
value:
64-
stringValue: ""
65-
- key: transaction.sampled
64+
intValue: "32592"
65+
- key: transaction.id
6666
value:
67-
boolValue: true
67+
stringValue: 945254c567a5417e
6868
- key: transaction.root
6969
value:
7070
boolValue: false
@@ -74,12 +74,9 @@ resourceSpans:
7474
- key: transaction.result
7575
value:
7676
stringValue: Success
77-
- key: transaction.duration.us
78-
value:
79-
intValue: "32592"
80-
- key: transaction.id
77+
- key: transaction.sampled
8178
value:
82-
stringValue: 945254c567a5417e
79+
boolValue: true
8380
- key: transaction.span_count.started
8481
value:
8582
intValue: "43"
@@ -91,6 +88,7 @@ resourceSpans:
9188
- stringValue: bar
9289
- stringValue: foo
9390
endTimeUnixNano: "1496170407186592981"
91+
kind: 2
9492
parentSpanId: abcdefabcdef0123
9593
spanId: 945254c567a5417e
9694
startTimeUnixNano: "1496170407154000000"

0 commit comments

Comments
 (0)