Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/extensions/tracers/zipkin/tracer.cc
Line
Count
Source (jump to first uncovered line)
1
#include "source/extensions/tracers/zipkin/tracer.h"
2
3
#include <chrono>
4
5
#include "source/common/common/utility.h"
6
#include "source/common/tracing/http_tracer_impl.h"
7
#include "source/extensions/tracers/zipkin/util.h"
8
#include "source/extensions/tracers/zipkin/zipkin_core_constants.h"
9
10
namespace Envoy {
11
namespace Extensions {
12
namespace Tracers {
13
namespace Zipkin {
14
15
SpanPtr Tracer::startSpan(const Tracing::Config& config, const std::string& span_name,
16
0
                          SystemTime timestamp) {
17
  // Build the endpoint
18
0
  Endpoint ep(service_name_, address_);
19
20
  // Build the CS annotation
21
0
  Annotation cs;
22
0
  cs.setEndpoint(std::move(ep));
23
0
  if (split_spans_for_request_) {
24
    // No previous context then this must be span created for downstream request. Server span will
25
    // be created for downstream request when split_spans_for_request is set to true
26
0
    cs.setValue(SERVER_RECV);
27
0
  } else {
28
0
    cs.setValue(config.operationName() == Tracing::OperationName::Egress ? CLIENT_SEND
29
0
                                                                         : SERVER_RECV);
30
0
  }
31
  // Create an all-new span, with no parent id
32
0
  SpanPtr span_ptr = std::make_unique<Span>(time_source_);
33
0
  span_ptr->setName(span_name);
34
0
  uint64_t random_number = random_generator_.random();
35
0
  span_ptr->setId(random_number);
36
0
  span_ptr->setTraceId(random_number);
37
0
  if (trace_id_128bit_) {
38
0
    span_ptr->setTraceIdHigh(random_generator_.random());
39
0
  }
40
0
  int64_t start_time_micro = std::chrono::duration_cast<std::chrono::microseconds>(
41
0
                                 time_source_.monotonicTime().time_since_epoch())
42
0
                                 .count();
43
0
  span_ptr->setStartTime(start_time_micro);
44
45
  // Set the timestamp globally for the span and also for the CS annotation
46
0
  uint64_t timestamp_micro =
47
0
      std::chrono::duration_cast<std::chrono::microseconds>(timestamp.time_since_epoch()).count();
48
0
  cs.setTimestamp(timestamp_micro);
49
0
  span_ptr->setTimestamp(timestamp_micro);
50
51
  // Add CS annotation to the span
52
0
  span_ptr->addAnnotation(std::move(cs));
53
54
0
  span_ptr->setTracer(this);
55
56
0
  return span_ptr;
57
0
}
58
59
SpanPtr Tracer::startSpan(const Tracing::Config& config, const std::string& span_name,
60
0
                          SystemTime timestamp, const SpanContext& previous_context) {
61
0
  SpanPtr span_ptr = std::make_unique<Span>(time_source_);
62
0
  Annotation annotation;
63
0
  uint64_t timestamp_micro;
64
65
0
  timestamp_micro =
66
0
      std::chrono::duration_cast<std::chrono::microseconds>(timestamp.time_since_epoch()).count();
67
68
0
  span_ptr->setName(span_name);
69
70
  // Set the span's kind (client or server)
71
0
  if (split_spans_for_request_) {
72
    // If the previous context is an inner context then this span must be a span created for an
73
    // upstream request. A client span will be created for an upstream request.
74
0
    if (previous_context.innerContext()) {
75
0
      annotation.setValue(CLIENT_SEND);
76
0
    } else {
77
0
      annotation.setValue(SERVER_RECV);
78
0
    }
79
0
  } else {
80
0
    if (config.operationName() == Tracing::OperationName::Egress) {
81
0
      annotation.setValue(CLIENT_SEND);
82
0
    } else {
83
0
      annotation.setValue(SERVER_RECV);
84
0
    }
85
0
  }
86
87
  // Set the span's id and parent id
88
0
  if (annotation.value() == CLIENT_SEND || !shared_span_context_) {
89
    // We need to create a new span that is a child of the previous span; no shared context
90
91
    // Create a new span id
92
0
    uint64_t random_number = random_generator_.random();
93
0
    span_ptr->setId(random_number);
94
95
    // Set the parent id to the id of the previous span
96
0
    span_ptr->setParentId(previous_context.id());
97
98
    // Set the timestamp globally for the span
99
0
    span_ptr->setTimestamp(timestamp_micro);
100
0
  } else if (annotation.value() == SERVER_RECV) {
101
    // We need to create a new span that will share context with the previous span
102
103
    // Initialize the shared context for the new span
104
0
    span_ptr->setId(previous_context.id());
105
0
    if (previous_context.parentId()) {
106
0
      span_ptr->setParentId(previous_context.parentId());
107
0
    }
108
0
  } else {
109
0
    return span_ptr; // return an empty span
110
0
  }
111
112
  // Build the endpoint
113
0
  Endpoint ep(service_name_, address_);
114
115
  // Add the newly-created annotation to the span
116
0
  annotation.setEndpoint(std::move(ep));
117
0
  annotation.setTimestamp(timestamp_micro);
118
0
  span_ptr->addAnnotation(std::move(annotation));
119
120
  // Keep the same trace id
121
0
  span_ptr->setTraceId(previous_context.traceId());
122
0
  if (previous_context.is128BitTraceId()) {
123
0
    span_ptr->setTraceIdHigh(previous_context.traceIdHigh());
124
0
  }
125
126
  // Keep the same sampled flag
127
0
  span_ptr->setSampled(previous_context.sampled());
128
129
0
  int64_t start_time_micro = std::chrono::duration_cast<std::chrono::microseconds>(
130
0
                                 time_source_.monotonicTime().time_since_epoch())
131
0
                                 .count();
132
0
  span_ptr->setStartTime(start_time_micro);
133
134
0
  span_ptr->setTracer(this);
135
136
0
  return span_ptr;
137
0
}
138
139
0
void Tracer::reportSpan(Span&& span) {
140
0
  if (reporter_ && span.sampled()) {
141
0
    reporter_->reportSpan(std::move(span));
142
0
  }
143
0
}
144
145
0
void Tracer::setReporter(ReporterPtr reporter) { reporter_ = std::move(reporter); }
146
147
} // namespace Zipkin
148
} // namespace Tracers
149
} // namespace Extensions
150
} // namespace Envoy