1
#pragma once
2

            
3
#include "envoy/config/trace/v3/zipkin.pb.h"
4

            
5
#include "source/common/protobuf/protobuf.h"
6
#include "source/extensions/tracers/zipkin/zipkin_core_types.h"
7

            
8
#include "zipkin.pb.h"
9

            
10
namespace Envoy {
11
namespace Extensions {
12
namespace Tracers {
13
namespace Zipkin {
14

            
15
/**
16
 * This class implements a simple buffer to store Zipkin tracing spans
17
 * prior to flushing them.
18
 */
19
class SpanBuffer {
20
public:
21
  /**
22
   * Constructor that creates an empty buffer. Space needs to be allocated by invoking
23
   * the method allocateBuffer(size).
24
   *
25
   * @param version The selected Zipkin collector version. @see
26
   * api/envoy/config/trace/v3/trace.proto.
27
   * @param shared_span_context To determine whether client and server spans will share the same
28
   * span context.
29
   */
30
  SpanBuffer(const envoy::config::trace::v3::ZipkinConfig::CollectorEndpointVersion& version,
31
             bool shared_span_context);
32

            
33
  /**
34
   * Constructor that initializes a buffer with the given size.
35
   *
36
   * @param version The selected Zipkin collector version. @see
37
   * api/envoy/config/trace/v3/trace.proto.
38
   * @param shared_span_context To determine whether client and server spans will share the same
39
   * span context.
40
   * @param size The desired buffer size.
41
   */
42
  SpanBuffer(const envoy::config::trace::v3::ZipkinConfig::CollectorEndpointVersion& version,
43
             bool shared_span_context, uint64_t size);
44

            
45
  /**
46
   * Allocates space for an empty buffer or resizes a previously-allocated one.
47
   *
48
   * @param size The desired buffer size.
49
   */
50
55
  void allocateBuffer(uint64_t size) { span_buffer_.reserve(size); }
51

            
52
  /**
53
   * Adds the given Zipkin span to the buffer.
54
   *
55
   * @param span The span to be added to the buffer.
56
   *
57
   * @return true if the span was successfully added, or false if the buffer was full.
58
   */
59
  bool addSpan(Span&& span);
60

            
61
  /**
62
   * Empties the buffer. This method is supposed to be called when all buffered spans
63
   * have been sent to the Zipkin service.
64
   */
65
17
  void clear() { span_buffer_.clear(); }
66

            
67
  /**
68
   * @return the number of spans currently buffered.
69
   */
70
54
  uint64_t pendingSpans() { return span_buffer_.size(); }
71

            
72
  /**
73
   * Serializes std::vector<Span> span_buffer_ to std::string as payload for the reporter when the
74
   * reporter does spans flushing. This function does only serialization and does not clear
75
   * span_buffer_.
76
   *
77
   * @return std::string the contents of the buffer, a collection of serialized pending Zipkin
78
   * spans.
79
   */
80
37
  std::string serialize() const { return serializer_->serialize(span_buffer_); }
81

            
82
private:
83
  SerializerPtr
84
  makeSerializer(const envoy::config::trace::v3::ZipkinConfig::CollectorEndpointVersion& version,
85
                 bool shared_span_context);
86

            
87
  // We use a pre-allocated vector to improve performance
88
  std::vector<Span> span_buffer_;
89
  SerializerPtr serializer_;
90
};
91

            
92
using SpanBufferPtr = std::unique_ptr<SpanBuffer>;
93

            
94
/**
95
 * JsonV2Serializer implements Zipkin::Serializer that serializes list of Zipkin spans into JSON
96
 * Zipkin v2 array.
97
 */
98
class JsonV2Serializer : public Serializer {
99
public:
100
  JsonV2Serializer(bool shared_span_context);
101

            
102
  /**
103
   * Serialize list of Zipkin spans into Zipkin v2 JSON array.
104
   * @return std::string serialized pending spans as Zipkin v2 JSON array.
105
   */
106
  std::string serialize(const std::vector<Span>& pending_spans) override;
107

            
108
private:
109
  const std::vector<Protobuf::Struct> toListOfSpans(const Span& zipkin_span,
110
                                                    Util::Replacements& replacements) const;
111
  const Protobuf::Struct toProtoEndpoint(const Endpoint& zipkin_endpoint) const;
112

            
113
  const bool shared_span_context_;
114
};
115

            
116
/**
117
 * ProtobufSerializer implements Zipkin::Serializer that serializes list of Zipkin spans into
118
 * stringified (SerializeToString) protobuf message.
119
 */
120
class ProtobufSerializer : public Serializer {
121
public:
122
  ProtobufSerializer(bool shared_span_context);
123

            
124
  /**
125
   * Serialize list of Zipkin spans into Zipkin v2 zipkin::proto3::ListOfSpans.
126
   * @return std::string serialized pending spans as Zipkin zipkin::proto3::ListOfSpans.
127
   */
128
  std::string serialize(const std::vector<Span>& pending_spans) override;
129

            
130
private:
131
  const zipkin::proto3::ListOfSpans toListOfSpans(const Span& zipkin_span) const;
132
  const zipkin::proto3::Endpoint toProtoEndpoint(const Endpoint& zipkin_endpoint) const;
133

            
134
  const bool shared_span_context_;
135
};
136

            
137
} // namespace Zipkin
138
} // namespace Tracers
139
} // namespace Extensions
140
} // namespace Envoy