func mapToSpanModel()

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"
	}
}