jaegerthrift_to_traces.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package jaeger // import "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger"
  4. import (
  5. "encoding/base64"
  6. "fmt"
  7. "reflect"
  8. "github.com/jaegertracing/jaeger/thrift-gen/jaeger"
  9. "go.opentelemetry.io/collector/pdata/pcommon"
  10. "go.opentelemetry.io/collector/pdata/ptrace"
  11. conventions "go.opentelemetry.io/collector/semconv/v1.9.0"
  12. "github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/idutils"
  13. "github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/tracetranslator"
  14. )
  15. var blankJaegerThriftSpan = new(jaeger.Span)
  16. // ThriftToTraces transforms a Thrift trace batch into ptrace.Traces.
  17. func ThriftToTraces(batches *jaeger.Batch) (ptrace.Traces, error) {
  18. traceData := ptrace.NewTraces()
  19. jProcess := batches.GetProcess()
  20. jSpans := batches.GetSpans()
  21. if jProcess == nil && len(jSpans) == 0 {
  22. return traceData, nil
  23. }
  24. rs := traceData.ResourceSpans().AppendEmpty()
  25. jThriftProcessToInternalResource(jProcess, rs.Resource())
  26. if len(jSpans) == 0 {
  27. return traceData, nil
  28. }
  29. jThriftSpansToInternal(jSpans, rs.ScopeSpans().AppendEmpty().Spans())
  30. return traceData, nil
  31. }
  32. func jThriftProcessToInternalResource(process *jaeger.Process, dest pcommon.Resource) {
  33. if process == nil {
  34. return
  35. }
  36. serviceName := process.GetServiceName()
  37. tags := process.GetTags()
  38. if serviceName == "" && tags == nil {
  39. return
  40. }
  41. attrs := dest.Attributes()
  42. if serviceName != "" {
  43. attrs.EnsureCapacity(len(tags) + 1)
  44. attrs.PutStr(conventions.AttributeServiceName, serviceName)
  45. } else {
  46. attrs.EnsureCapacity(len(tags))
  47. }
  48. jThriftTagsToInternalAttributes(tags, attrs)
  49. // Handle special keys translations.
  50. translateHostnameAttr(attrs)
  51. translateJaegerVersionAttr(attrs)
  52. }
  53. func jThriftSpansToInternal(spans []*jaeger.Span, dest ptrace.SpanSlice) {
  54. if len(spans) == 0 {
  55. return
  56. }
  57. dest.EnsureCapacity(len(spans))
  58. for _, span := range spans {
  59. if span == nil || reflect.DeepEqual(span, blankJaegerThriftSpan) {
  60. continue
  61. }
  62. jThriftSpanToInternal(span, dest.AppendEmpty())
  63. }
  64. }
  65. func jThriftSpanToInternal(span *jaeger.Span, dest ptrace.Span) {
  66. dest.SetTraceID(idutils.UInt64ToTraceID(uint64(span.TraceIdHigh), uint64(span.TraceIdLow)))
  67. dest.SetSpanID(idutils.UInt64ToSpanID(uint64(span.SpanId)))
  68. dest.SetName(span.OperationName)
  69. dest.SetStartTimestamp(microsecondsToUnixNano(span.StartTime))
  70. dest.SetEndTimestamp(microsecondsToUnixNano(span.StartTime + span.Duration))
  71. parentSpanID := span.ParentSpanId
  72. if parentSpanID != 0 {
  73. dest.SetParentSpanID(idutils.UInt64ToSpanID(uint64(parentSpanID)))
  74. }
  75. attrs := dest.Attributes()
  76. attrs.EnsureCapacity(len(span.Tags))
  77. jThriftTagsToInternalAttributes(span.Tags, attrs)
  78. if spanKindAttr, ok := attrs.Get(tracetranslator.TagSpanKind); ok {
  79. dest.SetKind(jSpanKindToInternal(spanKindAttr.Str()))
  80. attrs.Remove(tracetranslator.TagSpanKind)
  81. }
  82. setInternalSpanStatus(attrs, dest)
  83. // drop the attributes slice if all of them were replaced during translation
  84. if attrs.Len() == 0 {
  85. attrs.Clear()
  86. }
  87. jThriftLogsToSpanEvents(span.Logs, dest.Events())
  88. jThriftReferencesToSpanLinks(span.References, parentSpanID, dest.Links())
  89. }
  90. // jThriftTagsToInternalAttributes sets internal span links based on jaeger span references skipping excludeParentID
  91. func jThriftTagsToInternalAttributes(tags []*jaeger.Tag, dest pcommon.Map) {
  92. for _, tag := range tags {
  93. switch tag.GetVType() {
  94. case jaeger.TagType_STRING:
  95. dest.PutStr(tag.Key, tag.GetVStr())
  96. case jaeger.TagType_BOOL:
  97. dest.PutBool(tag.Key, tag.GetVBool())
  98. case jaeger.TagType_LONG:
  99. dest.PutInt(tag.Key, tag.GetVLong())
  100. case jaeger.TagType_DOUBLE:
  101. dest.PutDouble(tag.Key, tag.GetVDouble())
  102. case jaeger.TagType_BINARY:
  103. dest.PutStr(tag.Key, base64.StdEncoding.EncodeToString(tag.GetVBinary()))
  104. default:
  105. dest.PutStr(tag.Key, fmt.Sprintf("<Unknown Jaeger TagType %q>", tag.GetVType()))
  106. }
  107. }
  108. }
  109. func jThriftLogsToSpanEvents(logs []*jaeger.Log, dest ptrace.SpanEventSlice) {
  110. if len(logs) == 0 {
  111. return
  112. }
  113. dest.EnsureCapacity(len(logs))
  114. for _, log := range logs {
  115. event := dest.AppendEmpty()
  116. event.SetTimestamp(microsecondsToUnixNano(log.Timestamp))
  117. if len(log.Fields) == 0 {
  118. continue
  119. }
  120. attrs := event.Attributes()
  121. attrs.EnsureCapacity(len(log.Fields))
  122. jThriftTagsToInternalAttributes(log.Fields, attrs)
  123. if name, ok := attrs.Get(eventNameAttr); ok {
  124. event.SetName(name.Str())
  125. attrs.Remove(eventNameAttr)
  126. }
  127. }
  128. }
  129. func jThriftReferencesToSpanLinks(refs []*jaeger.SpanRef, excludeParentID int64, dest ptrace.SpanLinkSlice) {
  130. if len(refs) == 0 || len(refs) == 1 && refs[0].SpanId == excludeParentID && refs[0].RefType == jaeger.SpanRefType_CHILD_OF {
  131. return
  132. }
  133. dest.EnsureCapacity(len(refs))
  134. for _, ref := range refs {
  135. if ref.SpanId == excludeParentID && ref.RefType == jaeger.SpanRefType_CHILD_OF {
  136. continue
  137. }
  138. link := dest.AppendEmpty()
  139. link.SetTraceID(idutils.UInt64ToTraceID(uint64(ref.TraceIdHigh), uint64(ref.TraceIdLow)))
  140. link.SetSpanID(idutils.UInt64ToSpanID(uint64(ref.SpanId)))
  141. link.Attributes().PutStr(conventions.AttributeOpentracingRefType, jThriftRefTypeToAttribute(ref.RefType))
  142. }
  143. }
  144. // microsecondsToUnixNano converts epoch microseconds to pcommon.Timestamp
  145. func microsecondsToUnixNano(ms int64) pcommon.Timestamp {
  146. return pcommon.Timestamp(uint64(ms) * 1000)
  147. }
  148. func jThriftRefTypeToAttribute(ref jaeger.SpanRefType) string {
  149. if ref == jaeger.SpanRefType_CHILD_OF {
  150. return conventions.AttributeOpentracingRefTypeChildOf
  151. }
  152. return conventions.AttributeOpentracingRefTypeFollowsFrom
  153. }