1
#pragma once
2

            
3
#include <string>
4

            
5
#include "envoy/common/platform.h"
6
#include "envoy/config/core/v3/base.pb.h"
7
#include "envoy/local_info/local_info.h"
8
#include "envoy/runtime/runtime.h"
9
#include "envoy/tracing/tracer.h"
10

            
11
#include "source/common/formatter/substitution_formatter.h"
12
#include "source/common/http/header_map_impl.h"
13
#include "source/common/tracing/common_values.h"
14
#include "source/common/tracing/null_span_impl.h"
15
#include "source/common/tracing/tracer_impl.h"
16

            
17
namespace Envoy {
18
namespace Tracing {
19

            
20
template <class T> class HttpTraceContextBase : public TraceContext {
21
public:
22
  static_assert(std::is_same<typename std::remove_const<T>::type, Http::RequestHeaderMap>::value,
23
                "T must be Http::RequestHeaderMap or const Http::RequestHeaderMap");
24

            
25
52320
  HttpTraceContextBase(T& request_headers) : request_headers_(request_headers) {}
26

            
27
2
  absl::string_view protocol() const override { return request_headers_.getProtocolValue(); }
28
4
  absl::string_view host() const override { return request_headers_.getHostValue(); }
29
6
  absl::string_view path() const override { return request_headers_.getPathValue(); }
30
6
  absl::string_view method() const override { return request_headers_.getMethodValue(); }
31
2
  void forEach(IterateCallback callback) const override {
32
4
    request_headers_.iterate([cb = std::move(callback)](const Http::HeaderEntry& entry) {
33
4
      if (cb(entry.key().getStringView(), entry.value().getStringView())) {
34
3
        return Http::HeaderMap::Iterate::Continue;
35
3
      }
36
1
      return Http::HeaderMap::Iterate::Break;
37
4
    });
38
2
  }
39
2
  absl::optional<absl::string_view> get(absl::string_view key) const override {
40
2
    Http::LowerCaseString lower_key{std::string(key)};
41
2
    const auto entry = request_headers_.get(lower_key);
42
2
    if (!entry.empty()) {
43
1
      return entry[0]->value().getStringView();
44
1
    }
45
1
    return absl::nullopt;
46
2
  }
47
1
  void set(absl::string_view, absl::string_view) override {}
48
1
  void remove(absl::string_view) override {}
49
1
  OptRef<const Http::RequestHeaderMap> requestHeaders() const override { return request_headers_; };
50
1
  OptRef<Http::RequestHeaderMap> requestHeaders() override { return {}; };
51

            
52
protected:
53
  T& request_headers_;
54
};
55

            
56
// Read only http trace context that could be constructed from const Http::RequestHeaderMap.
57
// This is mainly used for custom tag extraction.
58
using ReadOnlyHttpTraceContext = HttpTraceContextBase<const Http::RequestHeaderMap>;
59

            
60
class HttpTraceContext : public HttpTraceContextBase<Http::RequestHeaderMap> {
61
public:
62
  using HttpTraceContextBase::HttpTraceContextBase;
63

            
64
1
  void set(absl::string_view key, absl::string_view value) override {
65
1
    request_headers_.setCopy(Http::LowerCaseString(std::string(key)), value);
66
1
  }
67
1
  void remove(absl::string_view key) override {
68
1
    request_headers_.remove(Http::LowerCaseString(std::string(key)));
69
1
  }
70
75
  OptRef<const Http::RequestHeaderMap> requestHeaders() const override { return request_headers_; };
71
82
  OptRef<Http::RequestHeaderMap> requestHeaders() override { return request_headers_; };
72
};
73

            
74
class HttpTracerUtility {
75
public:
76
  /**
77
   * Adds information obtained from the downstream request headers as tags to the active span.
78
   * Then finishes the span.
79
   */
80
  static void finalizeDownstreamSpan(Span& span, const Http::RequestHeaderMap* request_headers,
81
                                     const Http::ResponseHeaderMap* response_headers,
82
                                     const Http::ResponseTrailerMap* response_trailers,
83
                                     const StreamInfo::StreamInfo& stream_info,
84
                                     const Config& tracing_config);
85

            
86
  /**
87
   * Adds information obtained from the upstream request headers as tags to the active span.
88
   * Then finishes the span.
89
   */
90
  static void finalizeUpstreamSpan(Span& span, const StreamInfo::StreamInfo& stream_info,
91
                                   const Config& tracing_config);
92

            
93
  /**
94
   * Adds tags to the current "unfinished" span when processing upstream response headers.
95
   * NOOP if headers are nullptr.
96
   */
97
  static void onUpstreamResponseHeaders(Span& span,
98
                                        const Http::ResponseHeaderMap* response_headers);
99

            
100
  /**
101
   * Adds tags to the current "unfinished" span when processing upstream response trailers.
102
   * NOOP if trailers are nullptr.
103
   */
104
  static void onUpstreamResponseTrailers(Span& span,
105
                                         const Http::ResponseTrailerMap* response_trailers);
106

            
107
private:
108
  static void setCommonTags(Span& span, const StreamInfo::StreamInfo& stream_info,
109
                            const Config& tracing_config, bool upstream_span);
110
};
111

            
112
} // namespace Tracing
113
} // namespace Envoy