in exporter/awsxrayexporter/internal/translator/segment.go [316:478]
func MakeSegment(span ptrace.Span, resource pcommon.Resource, indexedAttrs []string, indexAllAttrs bool, logGroupNames []string, skipTimestampValidation bool) (*awsxray.Segment, error) {
var segmentType string
storeResource := true
if span.Kind() != ptrace.SpanKindServer &&
!span.ParentSpanID().IsEmpty() {
segmentType = "subsegment"
// We only store the resource information for segments, the local root.
storeResource = false
}
// convert trace id
traceID, err := convertToAmazonTraceID(span.TraceID(), skipTimestampValidation)
if err != nil {
return nil, err
}
attributes := span.Attributes()
var (
startTime = timestampToFloatSeconds(span.StartTimestamp())
endTime = timestampToFloatSeconds(span.EndTimestamp())
httpfiltered, http = makeHTTP(span)
isError, isFault, isThrottle, causefiltered, cause = makeCause(span, httpfiltered, resource)
origin = determineAwsOrigin(resource)
awsfiltered, aws = makeAws(causefiltered, resource, logGroupNames)
service = makeService(resource)
sqlfiltered, sql = makeSQL(span, awsfiltered)
additionalAttrs = addSpecialAttributes(sqlfiltered, indexedAttrs, attributes)
user, annotations, metadata = makeXRayAttributes(additionalAttrs, resource, storeResource, indexedAttrs, indexAllAttrs)
spanLinks, makeSpanLinkErr = makeSpanLinks(span.Links(), skipTimestampValidation)
name string
namespace string
)
if makeSpanLinkErr != nil {
return nil, makeSpanLinkErr
}
// X-Ray segment names are service names, unlike span names which are methods. Try to find a service name.
// support x-ray specific service name attributes as segment name if it exists
if span.Kind() == ptrace.SpanKindServer {
if localServiceName, ok := attributes.Get(awsLocalService); ok {
name = localServiceName.Str()
}
}
myAwsSpanKind, _ := span.Attributes().Get(awsSpanKind)
if span.Kind() == ptrace.SpanKindInternal && myAwsSpanKind.Str() == localRoot {
if localServiceName, ok := attributes.Get(awsLocalService); ok {
name = localServiceName.Str()
}
}
if span.Kind() == ptrace.SpanKindClient || span.Kind() == ptrace.SpanKindProducer || span.Kind() == ptrace.SpanKindConsumer {
if remoteServiceName, ok := attributes.Get(awsRemoteService); ok {
name = remoteServiceName.Str()
// only strip the prefix for AWS spans
name = trimAwsSdkPrefix(name, span)
}
}
// peer.service should always be prioritized for segment names when it set by users and
// the new x-ray specific service name attributes are not found
if name == "" {
if peerService, ok := attributes.Get(conventionsv112.AttributePeerService); ok {
name = peerService.Str()
}
}
if namespace == "" {
if isAwsSdkSpan(span) {
namespace = conventionsv112.AttributeCloudProviderAWS
}
}
if name == "" {
if awsService, ok := attributes.Get(awsxray.AWSServiceAttribute); ok {
// Generally spans are named something like "Method" or "Service.Method" but for AWS spans, X-Ray expects spans
// to be named "Service"
name = awsService.Str()
if namespace == "" {
namespace = conventionsv112.AttributeCloudProviderAWS
}
}
}
if name == "" {
if dbInstance, ok := attributes.Get(conventionsv112.AttributeDBName); ok {
// For database queries, the segment name convention is <db name>@<db host>
name = dbInstance.Str()
if dbURL, ok := attributes.Get(conventionsv112.AttributeDBConnectionString); ok {
// Trim JDBC connection string if starts with "jdbc:", otherwise no change
// jdbc:mysql://db.dev.example.com:3306
dbURLStr := strings.TrimPrefix(dbURL.Str(), "jdbc:")
if parsed, _ := url.Parse(dbURLStr); parsed != nil {
if parsed.Hostname() != "" {
name += "@" + parsed.Hostname()
}
}
}
}
}
if name == "" && span.Kind() == ptrace.SpanKindServer {
// Only for a server span, we can use the resource.
if service, ok := resource.Attributes().Get(conventionsv112.AttributeServiceName); ok {
name = service.Str()
}
}
if name == "" {
if rpcservice, ok := attributes.Get(conventionsv112.AttributeRPCService); ok {
name = rpcservice.Str()
}
}
if name == "" {
if host, ok := attributes.Get(conventionsv112.AttributeHTTPHost); ok {
name = host.Str()
}
}
if name == "" {
if peer, ok := attributes.Get(conventionsv112.AttributeNetPeerName); ok {
name = peer.Str()
}
}
if name == "" {
name = fixSegmentName(span.Name())
}
if namespace == "" && span.Kind() == ptrace.SpanKindClient {
namespace = "remote"
}
return &awsxray.Segment{
ID: awsxray.String(traceutil.SpanIDToHexOrEmptyString(span.SpanID())),
TraceID: awsxray.String(traceID),
Name: awsxray.String(name),
StartTime: awsP.Float64(startTime),
EndTime: awsP.Float64(endTime),
ParentID: awsxray.String(traceutil.SpanIDToHexOrEmptyString(span.ParentSpanID())),
Fault: awsP.Bool(isFault),
Error: awsP.Bool(isError),
Throttle: awsP.Bool(isThrottle),
Cause: cause,
Origin: awsxray.String(origin),
Namespace: awsxray.String(namespace),
User: awsxray.String(user),
HTTP: http,
AWS: aws,
Service: service,
SQL: sql,
Annotations: annotations,
Metadata: metadata,
Type: awsxray.String(segmentType),
Links: spanLinks,
}, nil
}