1
#pragma once
2

            
3
#include <cstdint>
4

            
5
#include "envoy/api/api.h"
6
#include "envoy/common/optref.h"
7
#include "envoy/config/trace/v3/opentelemetry.pb.h"
8
#include "envoy/runtime/runtime.h"
9
#include "envoy/thread_local/thread_local.h"
10
#include "envoy/tracing/trace_driver.h"
11

            
12
#include "source/common/common/logger.h"
13
#include "source/extensions/tracers/common/factory_base.h"
14
#include "source/extensions/tracers/opentelemetry/grpc_trace_exporter.h"
15
#include "source/extensions/tracers/opentelemetry/resource_detectors/resource_detector.h"
16
#include "source/extensions/tracers/opentelemetry/samplers/sampler.h"
17
#include "source/extensions/tracers/opentelemetry/span_context.h"
18

            
19
#include "absl/strings/escaping.h"
20

            
21
namespace Envoy {
22
namespace Extensions {
23
namespace Tracers {
24
namespace OpenTelemetry {
25

            
26
#define OPENTELEMETRY_TRACER_STATS(COUNTER)                                                        \
27
57
  COUNTER(spans_sent)                                                                              \
28
57
  COUNTER(timer_flushed)                                                                           \
29
57
  COUNTER(spans_dropped)
30

            
31
struct OpenTelemetryTracerStats {
32
  OPENTELEMETRY_TRACER_STATS(GENERATE_COUNTER_STRUCT)
33
};
34

            
35
/**
36
 * OpenTelemetry Tracer. It is stored in TLS and contains the exporter.
37
 */
38
class Tracer : Logger::Loggable<Logger::Id::tracing> {
39
public:
40
  Tracer(OpenTelemetryTraceExporterPtr exporter, Envoy::TimeSource& time_source,
41
         Random::RandomGenerator& random, Runtime::Loader& runtime, Event::Dispatcher& dispatcher,
42
         OpenTelemetryTracerStats tracing_stats, const ResourceConstSharedPtr resource,
43
         SamplerSharedPtr sampler, uint64_t max_cache_size);
44

            
45
  void sendSpan(::opentelemetry::proto::trace::v1::Span& span);
46

            
47
  Tracing::SpanPtr startSpan(const std::string& operation_name,
48
                             const StreamInfo::StreamInfo& stream_info, SystemTime start_time,
49
                             Tracing::Decision tracing_decision,
50
                             OptRef<const Tracing::TraceContext> trace_context,
51
                             OTelSpanKind span_kind);
52

            
53
  Tracing::SpanPtr startSpan(const std::string& operation_name,
54
                             const StreamInfo::StreamInfo& stream_info, SystemTime start_time,
55
                             const SpanContext& previous_span_context,
56
                             OptRef<const Tracing::TraceContext> trace_context,
57
                             OTelSpanKind span_kind);
58

            
59
private:
60
  /**
61
   * Enables the span-flushing timer.
62
   */
63
  void enableTimer();
64
  /*
65
   * Removes all spans from the span buffer and sends them to the collector.
66
   */
67
  void flushSpans();
68

            
69
  OpenTelemetryTraceExporterPtr exporter_;
70
  Envoy::TimeSource& time_source_;
71
  Random::RandomGenerator& random_;
72
  std::vector<::opentelemetry::proto::trace::v1::Span> span_buffer_;
73
  Runtime::Loader& runtime_;
74
  Event::TimerPtr flush_timer_;
75
  OpenTelemetryTracerStats tracing_stats_;
76
  const ResourceConstSharedPtr resource_;
77
  SamplerSharedPtr sampler_;
78
  uint64_t max_cache_size_;
79
};
80

            
81
/**
82
 * OpenTelemetry tracing implementation of the Envoy Span object.
83
 * Note that it has a pointer to its parent Tracer to access the shared Exporter.
84
 */
85
class Span : Logger::Loggable<Logger::Id::tracing>, public Tracing::Span {
86
public:
87
  Span(const std::string& name, const StreamInfo::StreamInfo& stream_info, SystemTime start_time,
88
       Envoy::TimeSource& time_source, Tracer& parent_tracer, OTelSpanKind span_kind,
89
       bool use_local_decision = false);
90

            
91
  // Tracing::Span functions
92
  void setOperation(absl::string_view /*operation*/) override;
93
  void setTag(absl::string_view /*name*/, absl::string_view /*value*/) override;
94
  void log(SystemTime /*timestamp*/, const std::string& /*event*/) override;
95
  void finishSpan() override;
96
  void injectContext(Envoy::Tracing::TraceContext& /*trace_context*/,
97
                     const Tracing::UpstreamContext&) override;
98
  Tracing::SpanPtr spawnChild(const Tracing::Config& config, const std::string& name,
99
                              SystemTime start_time) override;
100

            
101
  /**
102
   * Set the span's sampled flag.
103
   */
104
80
  void setSampled(bool sampled) override { sampled_ = sampled; };
105

            
106
  /**
107
   * @return whether the local tracing decision is used by the span.
108
   */
109
2
  bool useLocalDecision() const override { return use_local_decision_; }
110

            
111
  /**
112
   * @return whether or not the sampled attribute is set
113
   */
114
121
  bool sampled() const { return sampled_; }
115

            
116
1
  std::string getBaggage(absl::string_view /*key*/) override { return EMPTY_STRING; };
117
1
  void setBaggage(absl::string_view /*key*/, absl::string_view /*value*/) override{};
118

            
119
  // Additional methods
120

            
121
  /**
122
   * Sets the span's trace id attribute.
123
   */
124
79
  void setTraceId(absl::string_view trace_id_hex) {
125
79
    span_.set_trace_id(absl::HexStringToBytes(trace_id_hex));
126
79
  }
127

            
128
38
  std::string getTraceId() const override { return absl::BytesToHexString(span_.trace_id()); };
129

            
130
  std::string getSpanId() const override { return absl::BytesToHexString(span_.span_id()); };
131

            
132
19
  OTelSpanKind spankind() const { return span_.kind(); }
133

            
134
  /**
135
   * @return the operation name set on the span
136
   */
137
2
  absl::string_view name() const { return span_.name(); }
138

            
139
  /**
140
   * Sets the span's id.
141
   */
142
79
  void setId(absl::string_view span_id_hex) {
143
79
    span_.set_span_id(absl::HexStringToBytes(span_id_hex));
144
79
  }
145

            
146
18
  std::string spanId() { return absl::BytesToHexString(span_.span_id()); }
147

            
148
  /**
149
   * Sets the span's parent id.
150
   */
151
31
  void setParentId(absl::string_view parent_span_id_hex) {
152
31
    span_.set_parent_span_id(absl::HexStringToBytes(parent_span_id_hex));
153
31
  }
154

            
155
20
  absl::string_view tracestate() const { return span_.trace_state(); }
156

            
157
  /**
158
   * Sets the span's tracestate.
159
   */
160
11
  void setTracestate(absl::string_view tracestate) {
161
11
    span_.set_trace_state(std::string{tracestate});
162
11
  }
163

            
164
  /**
165
   * Sets a span attribute.
166
   */
167
  void setAttribute(absl::string_view name, const OTelAttribute& value);
168

            
169
  /**
170
   * Method to access the span for testing.
171
   */
172
8
  const ::opentelemetry::proto::trace::v1::Span& spanForTest() const { return span_; }
173

            
174
private:
175
  ::opentelemetry::proto::trace::v1::Span span_;
176
  const StreamInfo::StreamInfo& stream_info_;
177
  Tracer& parent_tracer_;
178
  Envoy::TimeSource& time_source_;
179
  bool sampled_;
180
  const bool use_local_decision_{false};
181
};
182

            
183
using TracerPtr = std::unique_ptr<Tracer>;
184

            
185
} // namespace OpenTelemetry
186
} // namespace Tracers
187
} // namespace Extensions
188
} // namespace Envoy