1
#include "source/extensions/tracers/datadog/dict_util.h"
2

            
3
#include <cstddef>
4

            
5
#include "envoy/http/header_map.h"
6
#include "envoy/tracing/trace_context.h"
7

            
8
#include "absl/strings/str_join.h"
9

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

            
15
24
RequestHeaderWriter::RequestHeaderWriter(Http::RequestHeaderMap& headers) : headers_(headers) {}
16

            
17
void RequestHeaderWriter::set(datadog::tracing::StringView key,
18
37
                              datadog::tracing::StringView value) {
19
37
  headers_.setCopy(Http::LowerCaseString{key}, value);
20
37
}
21

            
22
ResponseHeaderReader::ResponseHeaderReader(const Http::ResponseHeaderMap& headers)
23
4
    : headers_(headers) {}
24

            
25
datadog::tracing::Optional<datadog::tracing::StringView>
26
3
ResponseHeaderReader::lookup(datadog::tracing::StringView key) const {
27
3
  auto result = headers_.get(Http::LowerCaseString{key});
28
3
  if (result.empty()) {
29
    // `headers_.get` can return multiple header entries. It conveys
30
    // "not found" by returning zero header entries.
31
1
    return datadog::tracing::nullopt;
32
1
  }
33

            
34
2
  if (result.size() == 1) {
35
1
    return result[0]->value().getStringView();
36
1
  }
37

            
38
  // There's more than one matching header entry.
39
  // Per RFC 2616, this is the same as if there were only one entry whose
40
  // value is the comma-separated concatenation of the multiple values.
41
  // I don't expect the Agent to repeat response headers, and we don't even
42
  // examine the Agent's response headers, but here's a solution anyway.
43
1
  std::vector<absl::string_view> values;
44
1
  values.reserve(result.size());
45
3
  for (std::size_t i = 0; i < result.size(); ++i) {
46
2
    values.push_back(result[i]->value().getStringView());
47
2
  }
48
1
  buffer_ = absl::StrJoin(values, ", ");
49
1
  return buffer_;
50
2
}
51

            
52
void ResponseHeaderReader::visit(
53
    const std::function<void(datadog::tracing::StringView key, datadog::tracing::StringView value)>&
54
1
        visitor) const {
55
3
  headers_.iterate([&](const Http::HeaderEntry& entry) {
56
3
    visitor(entry.key().getStringView(), entry.value().getStringView());
57
3
    return Http::ResponseHeaderMap::Iterate::Continue;
58
3
  });
59
1
}
60

            
61
29
TraceContextReader::TraceContextReader(const Tracing::TraceContext& context) : context_(context) {}
62

            
63
datadog::tracing::Optional<datadog::tracing::StringView>
64
116
TraceContextReader::lookup(datadog::tracing::StringView key) const {
65
116
  return context_.get(key);
66
116
}
67

            
68
void TraceContextReader::visit(
69
    const std::function<void(datadog::tracing::StringView key, datadog::tracing::StringView value)>&
70
1
        visitor) const {
71
2
  context_.forEach([&](absl::string_view key, absl::string_view value) {
72
2
    visitor(key, value);
73
2
    return true;
74
2
  });
75
1
}
76

            
77
} // namespace Datadog
78
} // namespace Tracers
79
} // namespace Extensions
80
} // namespace Envoy