in input/elasticapm/internal/modeldecoder/v2/decoder.go [974:1249]
func mapToSpanModel(from *span, event *modelpb.APMEvent) {
out := modelpb.Span{}
event.Span = &out
// map span specific data
if !from.Action.IsSet() && !from.Subtype.IsSet() {
sep := "."
before, after, ok := strings.Cut(from.Type.Val, sep)
out.Type = before
if ok {
out.Subtype, out.Action, _ = strings.Cut(after, sep)
}
} else {
if from.Action.IsSet() {
out.Action = from.Action.Val
}
if from.Subtype.IsSet() {
out.Subtype = from.Subtype.Val
}
if from.Type.IsSet() {
out.Type = from.Type.Val
}
}
if from.Composite.IsSet() {
composite := modelpb.Composite{}
if from.Composite.Count.IsSet() {
composite.Count = uint32(from.Composite.Count.Val)
}
if from.Composite.Sum.IsSet() {
composite.Sum = from.Composite.Sum.Val
}
if strategy, ok := compressionStrategyText[from.Composite.CompressionStrategy.Val]; ok {
composite.CompressionStrategy = strategy
}
out.Composite = &composite
}
if len(from.ChildIDs) > 0 {
event.ChildIds = modeldecoderutil.Reslice(event.ChildIds, len(from.ChildIDs))
copy(event.ChildIds, from.ChildIDs)
}
if from.Context.Database.IsSet() {
db := modelpb.DB{}
if from.Context.Database.Instance.IsSet() {
db.Instance = from.Context.Database.Instance.Val
}
if from.Context.Database.Link.IsSet() {
db.Link = from.Context.Database.Link.Val
}
if from.Context.Database.RowsAffected.IsSet() {
val := uint32(from.Context.Database.RowsAffected.Val)
db.RowsAffected = &val
}
if from.Context.Database.Statement.IsSet() {
db.Statement = from.Context.Database.Statement.Val
}
if from.Context.Database.Type.IsSet() {
db.Type = from.Context.Database.Type.Val
}
if from.Context.Database.User.IsSet() {
db.UserName = from.Context.Database.User.Val
}
out.Db = &db
}
if from.Context.Destination.Address.IsSet() || from.Context.Destination.Port.IsSet() {
if from.Context.Destination.Address.IsSet() {
if event.Destination == nil {
event.Destination = &modelpb.Destination{}
}
event.Destination.Address = from.Context.Destination.Address.Val
}
if from.Context.Destination.Port.IsSet() {
if event.Destination == nil {
event.Destination = &modelpb.Destination{}
}
event.Destination.Port = uint32(from.Context.Destination.Port.Val)
}
}
if from.Context.Destination.Service.IsSet() {
service := modelpb.DestinationService{}
if from.Context.Destination.Service.Name.IsSet() {
service.Name = from.Context.Destination.Service.Name.Val
}
if from.Context.Destination.Service.Resource.IsSet() {
service.Resource = from.Context.Destination.Service.Resource.Val
}
if from.Context.Destination.Service.Type.IsSet() {
service.Type = from.Context.Destination.Service.Type.Val
}
out.DestinationService = &service
}
if from.Context.HTTP.IsSet() {
if from.Context.HTTP.Method.IsSet() {
if event.Http == nil {
event.Http = &modelpb.HTTP{}
}
if event.Http.Request == nil {
event.Http.Request = &modelpb.HTTPRequest{}
}
event.Http.Request.Method = from.Context.HTTP.Method.Val
}
if from.Context.HTTP.Request.IsSet() {
if event.Http == nil {
event.Http = &modelpb.HTTP{}
}
if event.Http.Request == nil {
event.Http.Request = &modelpb.HTTPRequest{}
}
if from.Context.HTTP.Request.ID.IsSet() {
event.Http.Request.Id = from.Context.HTTP.Request.ID.Val
}
if from.Context.HTTP.Request.Body.IsSet() {
event.Http.Request.Body = modeldecoderutil.ToValue(from.Context.HTTP.Request.Body.Val)
}
}
if from.Context.HTTP.Response.IsSet() {
if event.Http == nil {
event.Http = &modelpb.HTTP{}
}
response := modelpb.HTTPResponse{}
if from.Context.HTTP.Response.DecodedBodySize.IsSet() {
val := uint64(from.Context.HTTP.Response.DecodedBodySize.Val)
response.DecodedBodySize = &val
}
if from.Context.HTTP.Response.EncodedBodySize.IsSet() {
val := uint64(from.Context.HTTP.Response.EncodedBodySize.Val)
response.EncodedBodySize = &val
}
if from.Context.HTTP.Response.Headers.IsSet() {
response.Headers = modeldecoderutil.HTTPHeadersToModelpb(from.Context.HTTP.Response.Headers.Val, response.Headers)
}
if from.Context.HTTP.Response.StatusCode.IsSet() {
response.StatusCode = uint32(from.Context.HTTP.Response.StatusCode.Val)
}
if from.Context.HTTP.Response.TransferSize.IsSet() {
val := uint64(from.Context.HTTP.Response.TransferSize.Val)
response.TransferSize = &val
}
event.Http.Response = &response
}
if from.Context.HTTP.StatusCode.IsSet() {
if event.Http == nil {
event.Http = &modelpb.HTTP{}
}
if event.Http.Response == nil {
event.Http.Response = &modelpb.HTTPResponse{}
}
event.Http.Response.StatusCode = uint32(from.Context.HTTP.StatusCode.Val)
}
if from.Context.HTTP.URL.IsSet() {
if event.Url == nil {
event.Url = &modelpb.URL{}
}
event.Url.Original = from.Context.HTTP.URL.Val
}
}
if from.Context.Message.IsSet() {
message := modelpb.Message{}
if from.Context.Message.Body.IsSet() {
message.Body = from.Context.Message.Body.Val
}
if from.Context.Message.Headers.IsSet() {
message.Headers = modeldecoderutil.HTTPHeadersToModelpb(from.Context.Message.Headers.Val, message.Headers)
}
if from.Context.Message.Age.Milliseconds.IsSet() {
val := uint64(from.Context.Message.Age.Milliseconds.Val)
message.AgeMillis = &val
}
if from.Context.Message.Queue.Name.IsSet() {
message.QueueName = from.Context.Message.Queue.Name.Val
}
if from.Context.Message.RoutingKey.IsSet() {
message.RoutingKey = from.Context.Message.RoutingKey.Val
}
out.Message = &message
}
if from.Context.Service.IsSet() {
mapToServiceModel(from.Context.Service, &event.Service)
mapToAgentModel(from.Context.Service.Agent, &event.Agent)
}
if !from.Context.Service.Target.Type.IsSet() && from.Context.Destination.Service.Resource.IsSet() {
if event.Service == nil {
event.Service = &modelpb.Service{}
}
outTarget := targetFromDestinationResource(from.Context.Destination.Service.Resource.Val)
event.Service.Target = outTarget
}
if len(from.Context.Tags) > 0 {
modeldecoderutil.MergeLabels(from.Context.Tags, event)
}
if from.Duration.IsSet() {
if event.Event == nil {
event.Event = &modelpb.Event{}
}
event.Event.Duration = uint64(from.Duration.Val * float64(time.Millisecond))
}
if from.ID.IsSet() {
out.Id = from.ID.Val
}
if from.Name.IsSet() {
out.Name = from.Name.Val
}
if event.Event == nil {
event.Event = &modelpb.Event{}
}
if from.Outcome.IsSet() {
event.Event.Outcome = from.Outcome.Val
} else {
if from.Context.HTTP.StatusCode.IsSet() {
statusCode := from.Context.HTTP.StatusCode.Val
if statusCode >= http.StatusBadRequest {
event.Event.Outcome = "failure"
} else {
event.Event.Outcome = "success"
}
} else {
event.Event.Outcome = "unknown"
}
}
if from.ParentID.IsSet() {
event.ParentId = from.ParentID.Val
}
if from.SampleRate.IsSet() {
if from.SampleRate.Val > 0 {
out.RepresentativeCount = 1 / from.SampleRate.Val
}
} else {
// NOTE: we don't know the sample rate, so we need to make an assumption.
//
// Agents never send spans for non-sampled transactions, so assuming a
// representative count of 1 (i.e. sampling rate of 100%) may be invalid; but
// this is more useful than producing no metrics at all (i.e. assuming 0).
out.RepresentativeCount = 1
}
if len(from.Stacktrace) > 0 {
out.Stacktrace = modeldecoderutil.ResliceAndPopulateNil(
out.Stacktrace,
len(from.Stacktrace),
modeldecoderutil.NewType[modelpb.StacktraceFrame],
)
mapToStracktraceModel(from.Stacktrace, out.Stacktrace)
}
if from.Sync.IsSet() {
val := from.Sync.Val
out.Sync = &val
}
if !from.Timestamp.Val.IsZero() {
event.Timestamp = modelpb.FromTime(from.Timestamp.Val)
} else if from.Start.IsSet() {
// event.Timestamp should have been initialized to the time the
// payload was received; offset that by "start" milliseconds for
// RUM.
event.Timestamp += uint64(float64(time.Millisecond) * from.Start.Val)
}
if from.TraceID.IsSet() {
event.Trace = &modelpb.Trace{}
event.Trace.Id = from.TraceID.Val
}
if from.TransactionID.IsSet() {
event.Transaction = &modelpb.Transaction{}
event.Transaction.Id = from.TransactionID.Val
}
if from.OTel.IsSet() {
mapOTelAttributesSpan(from.OTel, event)
}
if len(from.Links) > 0 {
out.Links = modeldecoderutil.ResliceAndPopulateNil(
out.Links,
len(from.Links),
modeldecoderutil.NewType[modelpb.SpanLink],
)
mapSpanLinks(from.Links, out.Links)
}
if out.Type == "" {
out.Type = "unknown"
}
}