1
#include "source/common/tracing/tracer_impl.h"
2

            
3
#include "envoy/upstream/upstream.h"
4

            
5
#include "source/common/stream_info/utility.h"
6

            
7
#include "absl/strings/str_cat.h"
8

            
9
namespace Envoy {
10
namespace Tracing {
11

            
12
namespace {
13

            
14
3
static void annotateVerbose(Span& span, const StreamInfo::StreamInfo& stream_info) {
15
3
  const auto start_time = stream_info.startTime();
16
3
  StreamInfo::TimingUtility timing(stream_info);
17
3
  if (timing.lastDownstreamRxByteReceived()) {
18
3
    span.log(start_time + std::chrono::duration_cast<SystemTime::duration>(
19
3
                              *timing.lastDownstreamRxByteReceived()),
20
3
             Tracing::Logs::get().LastDownstreamRxByteReceived);
21
3
  }
22
3
  if (timing.firstUpstreamTxByteSent()) {
23
3
    span.log(start_time + std::chrono::duration_cast<SystemTime::duration>(
24
3
                              *timing.firstUpstreamTxByteSent()),
25
3
             Tracing::Logs::get().FirstUpstreamTxByteSent);
26
3
  }
27
3
  if (timing.lastUpstreamTxByteSent()) {
28
3
    span.log(start_time +
29
3
                 std::chrono::duration_cast<SystemTime::duration>(*timing.lastUpstreamTxByteSent()),
30
3
             Tracing::Logs::get().LastUpstreamTxByteSent);
31
3
  }
32
3
  if (timing.firstUpstreamRxByteReceived()) {
33
3
    span.log(start_time + std::chrono::duration_cast<SystemTime::duration>(
34
3
                              *timing.firstUpstreamRxByteReceived()),
35
3
             Tracing::Logs::get().FirstUpstreamRxByteReceived);
36
3
  }
37
3
  if (timing.lastUpstreamRxByteReceived()) {
38
3
    span.log(start_time + std::chrono::duration_cast<SystemTime::duration>(
39
3
                              *timing.lastUpstreamRxByteReceived()),
40
3
             Tracing::Logs::get().LastUpstreamRxByteReceived);
41
3
  }
42
3
  if (timing.firstDownstreamTxByteSent()) {
43
3
    span.log(start_time + std::chrono::duration_cast<SystemTime::duration>(
44
3
                              *timing.firstDownstreamTxByteSent()),
45
3
             Tracing::Logs::get().FirstDownstreamTxByteSent);
46
3
  }
47
3
  if (timing.lastDownstreamTxByteSent()) {
48
3
    span.log(start_time + std::chrono::duration_cast<SystemTime::duration>(
49
3
                              *timing.lastDownstreamTxByteSent()),
50
3
             Tracing::Logs::get().LastDownstreamTxByteSent);
51
3
  }
52
3
}
53

            
54
} // namespace
55

            
56
const std::string TracerUtility::IngressOperation = "ingress";
57
const std::string TracerUtility::EgressOperation = "egress";
58

            
59
63
const std::string& TracerUtility::toString(OperationName operation_name) {
60
63
  switch (operation_name) {
61
53
  case OperationName::Ingress:
62
53
    return IngressOperation;
63
10
  case OperationName::Egress:
64
10
    return EgressOperation;
65
63
  }
66

            
67
  return EMPTY_STRING; // Make the compiler happy.
68
63
}
69

            
70
574
Decision TracerUtility::shouldTraceRequest(const StreamInfo::StreamInfo& stream_info) {
71
  // Exclude health check requests immediately.
72
574
  if (stream_info.healthCheck()) {
73
1
    return {Reason::HealthCheck, false};
74
1
  }
75

            
76
573
  const Tracing::Reason trace_reason = stream_info.traceReason();
77
573
  switch (trace_reason) {
78
1
  case Reason::ClientForced:
79
26
  case Reason::ServiceForced:
80
106
  case Reason::Sampling:
81
106
    return {trace_reason, true};
82
467
  default:
83
467
    return {trace_reason, false};
84
573
  }
85
573
}
86

            
87
void TracerUtility::finalizeSpan(Span& span, const StreamInfo::StreamInfo& stream_info,
88
17
                                 const Config& tracing_config, bool upstream_span) {
89
17
  span.setTag(Tracing::Tags::get().Component, Tracing::Tags::get().Proxy);
90

            
91
  // Response flag.
92
17
  span.setTag(Tracing::Tags::get().ResponseFlags,
93
17
              StreamInfo::ResponseFlagUtils::toShortString(stream_info));
94

            
95
  // Downstream info.
96
17
  if (!upstream_span) {
97
3
    const auto& remote_address = stream_info.downstreamAddressProvider().directRemoteAddress();
98
3
    span.setTag(Tracing::Tags::get().PeerAddress, remote_address->asStringView());
99
3
  }
100

            
101
  // Cluster info.
102
17
  if (auto cluster_info = stream_info.upstreamClusterInfo();
103
17
      cluster_info.has_value() && cluster_info.value() != nullptr) {
104
15
    span.setTag(Tracing::Tags::get().UpstreamCluster, cluster_info.value()->name());
105
15
    span.setTag(Tracing::Tags::get().UpstreamClusterName,
106
15
                cluster_info.value()->observabilityName());
107
15
  }
108

            
109
  // Upstream info.
110
17
  if (stream_info.upstreamInfo() && stream_info.upstreamInfo()->upstreamHost()) {
111
15
    auto upstream_address = stream_info.upstreamInfo()->upstreamHost()->address();
112

            
113
15
    span.setTag(Tracing::Tags::get().UpstreamAddress, upstream_address->asStringView());
114

            
115
    // Upstream address would be 'peer.address' in the case of an upstream span.
116
15
    if (upstream_span) {
117
14
      span.setTag(Tracing::Tags::get().PeerAddress, upstream_address->asStringView());
118
14
    }
119
15
  }
120

            
121
  // Verbose timing log.
122
17
  if (tracing_config.verbose()) {
123
3
    annotateVerbose(span, stream_info);
124
3
  }
125
17
  tracing_config.modifySpan(span, upstream_span);
126

            
127
  // Finish the span.
128
17
  span.finishSpan();
129
17
}
130

            
131
TracerImpl::TracerImpl(DriverSharedPtr driver, const LocalInfo::LocalInfo& local_info)
132
44
    : driver_(std::move(driver)), local_info_(local_info) {}
133

            
134
SpanPtr TracerImpl::startSpan(const Config& config, TraceContext& trace_context,
135
                              const StreamInfo::StreamInfo& stream_info,
136
42
                              const Tracing::Decision tracing_decision) {
137
42
  std::string span_name = TracerUtility::toString(config.operationName());
138

            
139
42
  if (config.operationName() == OperationName::Egress) {
140
2
    span_name.append(" ");
141
2
    span_name.append(std::string(trace_context.host()));
142
2
  }
143

            
144
42
  SpanPtr active_span =
145
42
      driver_->startSpan(config, trace_context, stream_info, span_name, tracing_decision);
146

            
147
  // Set tags related to the local environment
148
42
  if (active_span) {
149
41
    active_span->setTag(Tracing::Tags::get().NodeId, local_info_.nodeName());
150
41
    active_span->setTag(Tracing::Tags::get().Zone, local_info_.zoneName());
151
41
  }
152

            
153
42
  return active_span;
154
42
}
155

            
156
} // namespace Tracing
157
} // namespace Envoy