1
#pragma once
2

            
3
#include "envoy/extensions/request_id/uuid/v3/uuid.pb.h"
4
#include "envoy/extensions/request_id/uuid/v3/uuid.pb.validate.h"
5
#include "envoy/http/request_id_extension.h"
6
#include "envoy/server/request_id_extension_config.h"
7

            
8
namespace Envoy {
9
namespace Extensions {
10
namespace RequestId {
11

            
12
// UUIDRequestIDExtension is the default implementation if no other extension is explicitly
13
// configured.
14
class UUIDRequestIDExtension : public Envoy::Http::RequestIDExtension {
15
public:
16
  UUIDRequestIDExtension(const envoy::extensions::request_id::uuid::v3::UuidRequestIdConfig& config,
17
                         Random::RandomGenerator& random)
18
21128
      : random_(random),
19
21128
        pack_trace_reason_(PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, pack_trace_reason, true)),
20
        use_request_id_for_trace_sampling_(
21
21128
            PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, use_request_id_for_trace_sampling, true)) {}
22

            
23
11104
  static Envoy::Http::RequestIDExtensionSharedPtr defaultInstance(Random::RandomGenerator& random) {
24
11104
    return std::make_shared<UUIDRequestIDExtension>(
25
11104
        envoy::extensions::request_id::uuid::v3::UuidRequestIdConfig(), random);
26
11104
  }
27

            
28
2
  bool packTraceReason() { return pack_trace_reason_; }
29

            
30
  // Envoy::Http::RequestIDExtension
31
  void set(Envoy::Http::RequestHeaderMap& request_headers, bool edge_request,
32
           bool keep_external_id) override;
33
  void setInResponse(Envoy::Http::ResponseHeaderMap& response_headers,
34
                     const Envoy::Http::RequestHeaderMap& request_headers) override;
35
  absl::optional<absl::string_view>
36
  get(const Envoy::Http::RequestHeaderMap& request_headers) const override;
37
  absl::optional<uint64_t>
38
  getInteger(const Envoy::Http::RequestHeaderMap& request_headers) const override;
39
  Tracing::Reason getTraceReason(const Envoy::Http::RequestHeaderMap& request_headers) override;
40
  void setTraceReason(Envoy::Http::RequestHeaderMap& request_headers,
41
                      Tracing::Reason status) override;
42
1000301
  bool useRequestIdForTraceSampling() const override { return use_request_id_for_trace_sampling_; }
43

            
44
private:
45
  Envoy::Random::RandomGenerator& random_;
46
  const bool pack_trace_reason_;
47
  const bool use_request_id_for_trace_sampling_;
48

            
49
  // Byte on this position has predefined value of 4 for UUID4.
50
  static const int TRACE_BYTE_POSITION = 14;
51

            
52
  // Value of '9' is chosen randomly to distinguish between freshly generated uuid4 and the
53
  // one modified because we sample trace.
54
  static const char TRACE_SAMPLED = '9';
55

            
56
  // Value of 'a' is chosen randomly to distinguish between freshly generated uuid4 and the
57
  // one modified because we force trace.
58
  static const char TRACE_FORCED = 'a';
59

            
60
  // Value of 'b' is chosen randomly to distinguish between freshly generated uuid4 and the
61
  // one modified because of client trace.
62
  static const char TRACE_CLIENT = 'b';
63

            
64
  // Initial value for freshly generated uuid4.
65
  static const char NO_TRACE = '4';
66
};
67

            
68
// Factory for the UUID request ID extension.
69
class UUIDRequestIDExtensionFactory : public Server::Configuration::RequestIDExtensionFactory {
70
public:
71
11223
  std::string name() const override { return "envoy.request_id.uuid"; }
72
10496
  ProtobufTypes::MessagePtr createEmptyConfigProto() override {
73
10496
    return std::make_unique<envoy::extensions::request_id::uuid::v3::UuidRequestIdConfig>();
74
10496
  }
75
  Envoy::Http::RequestIDExtensionSharedPtr
76
  createExtensionInstance(const Protobuf::Message& config,
77
10016
                          Server::Configuration::FactoryContext& context) override {
78
10016
    return std::make_shared<UUIDRequestIDExtension>(
79
10016
        MessageUtil::downcastAndValidate<
80
10016
            const envoy::extensions::request_id::uuid::v3::UuidRequestIdConfig&>(
81
10016
            config, context.messageValidationVisitor()),
82
10016
        context.serverFactoryContext().api().randomGenerator());
83
10016
  }
84
};
85

            
86
DECLARE_FACTORY(UUIDRequestIDExtensionFactory);
87

            
88
} // namespace RequestId
89
} // namespace Extensions
90
} // namespace Envoy