in exporter/awsxrayexporter/internal/translator/cause.go [32:189]
func makeCause(span ptrace.Span, attributes map[string]pcommon.Value, resource pcommon.Resource) (isError, isFault, isThrottle bool,
filtered map[string]pcommon.Value, cause *awsxray.CauseData,
) {
status := span.Status()
filtered = attributes
var (
message string
errorKind string
)
isAwsSdkSpan := isAwsSdkSpan(span)
hasExceptionEvents := false
hasAwsIndividualHTTPError := false
for i := 0; i < span.Events().Len(); i++ {
event := span.Events().At(i)
if event.Name() == ExceptionEventName {
hasExceptionEvents = true
break
}
if isAwsSdkSpan && event.Name() == AwsIndividualHTTPEventName {
hasAwsIndividualHTTPError = true
break
}
}
hasExceptions := hasExceptionEvents || hasAwsIndividualHTTPError
switch {
case hasExceptions:
language := ""
if val, ok := resource.Attributes().Get(conventionsv112.AttributeTelemetrySDKLanguage); ok {
language = val.Str()
}
isRemote := false
if span.Kind() == ptrace.SpanKindClient || span.Kind() == ptrace.SpanKindProducer {
isRemote = true
}
var exceptions []awsxray.Exception
for i := 0; i < span.Events().Len(); i++ {
event := span.Events().At(i)
if event.Name() == ExceptionEventName {
exceptionType := ""
message = ""
stacktrace := ""
if val, ok := event.Attributes().Get(conventionsv112.AttributeExceptionType); ok {
exceptionType = val.Str()
}
if val, ok := event.Attributes().Get(conventionsv112.AttributeExceptionMessage); ok {
message = val.Str()
}
if val, ok := event.Attributes().Get(conventionsv112.AttributeExceptionStacktrace); ok {
stacktrace = val.Str()
}
parsed := parseException(exceptionType, message, stacktrace, isRemote, language)
exceptions = append(exceptions, parsed...)
} else if isAwsSdkSpan && event.Name() == AwsIndividualHTTPEventName {
errorCode, ok1 := event.Attributes().Get(conventions.AttributeHTTPResponseStatusCode)
errorMessage, ok2 := event.Attributes().Get(AwsIndividualHTTPErrorMsgAttr)
if ok1 && ok2 {
eventEpochTime := event.Timestamp().AsTime().UnixMicro()
strs := []string{
errorCode.AsString(),
strconv.FormatFloat(float64(eventEpochTime)/1_000_000, 'f', 6, 64),
errorMessage.Str(),
}
message = strings.Join(strs, "@")
segmentID := newSegmentID()
exception := awsxray.Exception{
ID: aws.String(hex.EncodeToString(segmentID[:])),
Type: aws.String(AwsIndividualHTTPErrorEventType),
Remote: aws.Bool(true),
Message: aws.String(message),
}
exceptions = append(exceptions, exception)
}
}
}
cause = &awsxray.CauseData{
Type: awsxray.CauseTypeObject,
CauseObject: awsxray.CauseObject{
Exceptions: exceptions,
},
}
case status.Code() != ptrace.StatusCodeError:
cause = nil
default:
// Use OpenCensus behavior if we didn't find any exception events to ease migration.
message = status.Message()
filtered = make(map[string]pcommon.Value)
for key, value := range attributes {
switch key {
case "http.status_text":
if message == "" {
message = value.Str()
}
default:
filtered[key] = value
}
}
if message != "" {
segmentID := newSegmentID()
cause = &awsxray.CauseData{
Type: awsxray.CauseTypeObject,
CauseObject: awsxray.CauseObject{
Exceptions: []awsxray.Exception{
{
ID: aws.String(hex.EncodeToString(segmentID[:])),
Type: aws.String(errorKind),
Message: aws.String(message),
},
},
},
}
}
}
val, ok := span.Attributes().Get(conventionsv112.AttributeHTTPStatusCode)
if !ok {
val, ok = span.Attributes().Get(conventions.AttributeHTTPResponseStatusCode)
}
// The segment status for http spans will be based on their http.statuscode as we found some http
// spans does not fill with status.Code() but always filled with http.statuscode
var code int64
if ok {
code = val.Int()
}
// Default values
isThrottle = false
isError = false
isFault = false
switch {
case !ok || code < 400 || code > 599:
if status.Code() == ptrace.StatusCodeError {
isFault = true
}
case code >= 400 && code <= 499:
isError = true
if code == 429 {
isThrottle = true
}
case code >= 500 && code <= 599:
isFault = true
}
return isError, isFault, isThrottle, filtered, cause
}