client.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package tracing
  2. import (
  3. "context"
  4. "encoding/base64"
  5. "errors"
  6. "sync"
  7. coltracepb "go.opentelemetry.io/proto/otlp/collector/trace/v1"
  8. tracepb "go.opentelemetry.io/proto/otlp/trace/v1"
  9. "google.golang.org/protobuf/proto"
  10. )
  11. const (
  12. MaxTraceAmount = 20
  13. )
  14. var (
  15. errNoTraces = errors.New("no traces recorded to be exported")
  16. errNoopTracer = errors.New("noop tracer has no traces")
  17. )
  18. type InMemoryClient interface {
  19. // Spans returns a copy of the list of in-memory stored spans as a base64
  20. // encoded otlp protobuf string.
  21. Spans() (string, error)
  22. // ExportProtoSpans returns a copy of the list of in-memory stored spans as otlp
  23. // protobuf byte array and clears the in-memory spans.
  24. ExportProtoSpans() ([]byte, error)
  25. }
  26. // InMemoryOtlpClient is a client implementation for otlptrace.Client
  27. type InMemoryOtlpClient struct {
  28. mu sync.Mutex
  29. spans []*tracepb.ResourceSpans
  30. }
  31. func (mc *InMemoryOtlpClient) Start(_ context.Context) error {
  32. return nil
  33. }
  34. func (mc *InMemoryOtlpClient) Stop(_ context.Context) error {
  35. return nil
  36. }
  37. // UploadTraces adds the provided list of spans to the in-memory list.
  38. func (mc *InMemoryOtlpClient) UploadTraces(_ context.Context, protoSpans []*tracepb.ResourceSpans) error {
  39. mc.mu.Lock()
  40. defer mc.mu.Unlock()
  41. // Catch to make sure too many traces aren't being added to response header.
  42. // Returning nil makes sure we don't fail to send the traces we already recorded.
  43. if len(mc.spans)+len(protoSpans) > MaxTraceAmount {
  44. return nil
  45. }
  46. mc.spans = append(mc.spans, protoSpans...)
  47. return nil
  48. }
  49. // Spans returns the list of in-memory stored spans as a base64 encoded otlp protobuf string.
  50. func (mc *InMemoryOtlpClient) Spans() (string, error) {
  51. data, err := mc.ExportProtoSpans()
  52. if err != nil {
  53. return "", err
  54. }
  55. return base64.StdEncoding.EncodeToString(data), nil
  56. }
  57. // ProtoSpans returns the list of in-memory stored spans as the protobuf byte array.
  58. func (mc *InMemoryOtlpClient) ExportProtoSpans() ([]byte, error) {
  59. mc.mu.Lock()
  60. defer mc.mu.Unlock()
  61. if len(mc.spans) <= 0 {
  62. return nil, errNoTraces
  63. }
  64. pbRequest := &coltracepb.ExportTraceServiceRequest{
  65. ResourceSpans: mc.spans,
  66. }
  67. serializedSpans, err := proto.Marshal(pbRequest)
  68. if err != nil {
  69. return nil, err
  70. }
  71. mc.spans = make([]*tracepb.ResourceSpans, 0)
  72. return serializedSpans, nil
  73. }
  74. // NoopOtlpClient is a client implementation for otlptrace.Client that does nothing
  75. type NoopOtlpClient struct{}
  76. func (mc *NoopOtlpClient) Start(_ context.Context) error {
  77. return nil
  78. }
  79. func (mc *NoopOtlpClient) Stop(_ context.Context) error {
  80. return nil
  81. }
  82. func (mc *NoopOtlpClient) UploadTraces(_ context.Context, _ []*tracepb.ResourceSpans) error {
  83. return nil
  84. }
  85. // Spans always returns no traces error
  86. func (mc *NoopOtlpClient) Spans() (string, error) {
  87. return "", errNoopTracer
  88. }
  89. // Spans always returns no traces error
  90. func (mc *NoopOtlpClient) ExportProtoSpans() ([]byte, error) {
  91. return nil, errNoopTracer
  92. }
  93. func (mc *NoopOtlpClient) ClearSpans() {}