1
#include "source/extensions/tracers/skywalking/tracer.h"
2

            
3
#include <string>
4

            
5
namespace Envoy {
6
namespace Extensions {
7
namespace Tracers {
8
namespace SkyWalking {
9

            
10
namespace {
11
static constexpr absl::string_view StatusCodeTag = "status_code";
12
static constexpr absl::string_view UrlTag = "url";
13
} // namespace
14

            
15
10
const Tracing::TraceContextHandler& skywalkingPropagationHeaderKey() {
16
10
  CONSTRUCT_ON_FIRST_USE(Tracing::TraceContextHandler, "sw8");
17
10
}
18

            
19
7
void Span::setTag(absl::string_view name, absl::string_view value) {
20
7
  if (name == Tracing::Tags::get().HttpUrl) {
21
1
    span_entity_->addTag(UrlTag.data(), std::string(value));
22
6
  } else if (name == Tracing::Tags::get().HttpStatusCode) {
23
1
    span_entity_->addTag(StatusCodeTag.data(), std::string(value));
24
5
  } else if (name == Tracing::Tags::get().Error) {
25
1
    span_entity_->setErrorStatus();
26
1
    span_entity_->addTag(std::string(name), std::string(value));
27
4
  } else if (name == Tracing::Tags::get().PeerAddress) {
28
1
    span_entity_->setPeer(std::string(value));
29
3
  } else {
30
3
    span_entity_->addTag(std::string(name), std::string(value));
31
3
  }
32
7
}
33

            
34
1
void Span::setSampled(bool do_sample) {
35
  // Sampling status is always true on SkyWalking. But with disabling skip_analysis,
36
  // this span can't be analyzed.
37
1
  if (!do_sample) {
38
1
    span_entity_->setSkipAnalysis();
39
1
  }
40
1
}
41

            
42
1
void Span::log(SystemTime, const std::string& event) { span_entity_->addLog(EMPTY_STRING, event); }
43

            
44
8
void Span::finishSpan() {
45
8
  span_entity_->setSpanLayer(skywalking::v3::SpanLayer::Http);
46
8
  span_entity_->endSpan();
47
8
  parent_tracer_.sendSegment(tracing_context_);
48
8
}
49

            
50
void Span::injectContext(Tracing::TraceContext& trace_context,
51
2
                         const Tracing::UpstreamContext& upstream) {
52
2
  absl::string_view remote_address =
53
2
      upstream.host_.has_value() ? upstream.host_->address()->asStringView() : trace_context.host();
54

            
55
2
  auto sw8_header =
56
2
      tracing_context_->createSW8HeaderValue({remote_address.data(), remote_address.size()});
57
2
  if (sw8_header.has_value()) {
58
2
    skywalkingPropagationHeaderKey().setRefKey(trace_context, sw8_header.value());
59

            
60
    // Rewrite operation name with latest upstream request path for the EXIT span.
61
2
    absl::string_view upstream_request_path = trace_context.path();
62
2
    span_entity_->setOperationName({upstream_request_path.data(), upstream_request_path.size()});
63
2
  }
64
2
}
65

            
66
3
Tracing::SpanPtr Span::spawnChild(const Tracing::Config&, const std::string&, SystemTime) {
67
  // Reuse operation name of parent span by default.
68
3
  return std::make_unique<Span>(span_entity_->operationName(), span_entity_->spanLayer(), *this,
69
3
                                tracing_context_, parent_tracer_);
70
3
}
71

            
72
5
Tracer::Tracer(TraceSegmentReporterPtr reporter) : reporter_(std::move(reporter)) {}
73

            
74
8
void Tracer::sendSegment(TracingContextSharedPtr segment_context) {
75
8
  ASSERT(reporter_);
76
8
  if (segment_context->readyToSend()) {
77
5
    reporter_->report(std::move(segment_context));
78
5
  }
79
8
}
80

            
81
Tracing::SpanPtr Tracer::startSpan(absl::string_view name, absl::string_view protocol,
82
8
                                   TracingContextSharedPtr tracing_context) {
83
8
  return std::make_unique<Span>(name, protocol, tracing_context, *this);
84
8
}
85
} // namespace SkyWalking
86
} // namespace Tracers
87
} // namespace Extensions
88
} // namespace Envoy