tracer.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package sdk
  4. import (
  5. "context"
  6. "time"
  7. "go.opentelemetry.io/otel/trace"
  8. "go.opentelemetry.io/otel/trace/noop"
  9. "go.opentelemetry.io/auto/sdk/internal/telemetry"
  10. )
  11. type tracer struct {
  12. noop.Tracer
  13. name, schemaURL, version string
  14. }
  15. var _ trace.Tracer = tracer{}
  16. func (t tracer) Start(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
  17. var psc trace.SpanContext
  18. sampled := true
  19. span := new(span)
  20. // Ask eBPF for sampling decision and span context info.
  21. t.start(ctx, span, &psc, &sampled, &span.spanContext)
  22. span.sampled.Store(sampled)
  23. ctx = trace.ContextWithSpan(ctx, span)
  24. if sampled {
  25. // Only build traces if sampled.
  26. cfg := trace.NewSpanStartConfig(opts...)
  27. span.traces, span.span = t.traces(name, cfg, span.spanContext, psc)
  28. }
  29. return ctx, span
  30. }
  31. // Expected to be implemented in eBPF.
  32. //
  33. //go:noinline
  34. func (t *tracer) start(
  35. ctx context.Context,
  36. spanPtr *span,
  37. psc *trace.SpanContext,
  38. sampled *bool,
  39. sc *trace.SpanContext,
  40. ) {
  41. start(ctx, spanPtr, psc, sampled, sc)
  42. }
  43. // start is used for testing.
  44. var start = func(context.Context, *span, *trace.SpanContext, *bool, *trace.SpanContext) {}
  45. func (t tracer) traces(name string, cfg trace.SpanConfig, sc, psc trace.SpanContext) (*telemetry.Traces, *telemetry.Span) {
  46. span := &telemetry.Span{
  47. TraceID: telemetry.TraceID(sc.TraceID()),
  48. SpanID: telemetry.SpanID(sc.SpanID()),
  49. Flags: uint32(sc.TraceFlags()),
  50. TraceState: sc.TraceState().String(),
  51. ParentSpanID: telemetry.SpanID(psc.SpanID()),
  52. Name: name,
  53. Kind: spanKind(cfg.SpanKind()),
  54. }
  55. span.Attrs, span.DroppedAttrs = convCappedAttrs(maxSpan.Attrs, cfg.Attributes())
  56. links := cfg.Links()
  57. if limit := maxSpan.Links; limit == 0 {
  58. span.DroppedLinks = uint32(len(links))
  59. } else {
  60. if limit > 0 {
  61. n := max(len(links)-limit, 0)
  62. span.DroppedLinks = uint32(n)
  63. links = links[n:]
  64. }
  65. span.Links = convLinks(links)
  66. }
  67. if t := cfg.Timestamp(); !t.IsZero() {
  68. span.StartTime = cfg.Timestamp()
  69. } else {
  70. span.StartTime = time.Now()
  71. }
  72. return &telemetry.Traces{
  73. ResourceSpans: []*telemetry.ResourceSpans{
  74. {
  75. ScopeSpans: []*telemetry.ScopeSpans{
  76. {
  77. Scope: &telemetry.Scope{
  78. Name: t.name,
  79. Version: t.version,
  80. },
  81. Spans: []*telemetry.Span{span},
  82. SchemaURL: t.schemaURL,
  83. },
  84. },
  85. },
  86. },
  87. }, span
  88. }
  89. func spanKind(kind trace.SpanKind) telemetry.SpanKind {
  90. switch kind {
  91. case trace.SpanKindInternal:
  92. return telemetry.SpanKindInternal
  93. case trace.SpanKindServer:
  94. return telemetry.SpanKindServer
  95. case trace.SpanKindClient:
  96. return telemetry.SpanKindClient
  97. case trace.SpanKindProducer:
  98. return telemetry.SpanKindProducer
  99. case trace.SpanKindConsumer:
  100. return telemetry.SpanKindConsumer
  101. }
  102. return telemetry.SpanKind(0) // undefined.
  103. }