1
#pragma once
2

            
3
#include <cstdint>
4
#include <string>
5
#include <vector>
6

            
7
#include "envoy/access_log/access_log.h"
8
#include "envoy/access_log/access_log_config.h"
9
#include "envoy/common/random_generator.h"
10
#include "envoy/config/accesslog/v3/accesslog.pb.h"
11
#include "envoy/config/typed_config.h"
12
#include "envoy/runtime/runtime.h"
13
#include "envoy/type/v3/percent.pb.h"
14

            
15
#include "source/common/common/matchers.h"
16
#include "source/common/common/utility.h"
17
#include "source/common/config/utility.h"
18
#include "source/common/grpc/status.h"
19
#include "source/common/http/header_utility.h"
20
#include "source/common/protobuf/protobuf.h"
21

            
22
#include "absl/container/node_hash_set.h"
23
#include "absl/hash/hash.h"
24

            
25
namespace Envoy {
26
namespace AccessLog {
27

            
28
/**
29
 * Access log filter factory that reads from proto.
30
 */
31
class FilterFactory {
32
public:
33
  /**
34
   * Read a filter definition from proto and instantiate a concrete filter class.
35
   */
36
  static FilterPtr fromProto(const envoy::config::accesslog::v3::AccessLogFilter& config,
37
                             Server::Configuration::GenericFactoryContext& context);
38
};
39

            
40
/**
41
 * Base implementation of an access log filter that performs comparisons.
42
 */
43
class ComparisonFilter : public Filter {
44
protected:
45
  ComparisonFilter(const envoy::config::accesslog::v3::ComparisonFilter& config,
46
                   Runtime::Loader& runtime);
47

            
48
  bool compareAgainstValue(uint64_t lhs) const;
49

            
50
  envoy::config::accesslog::v3::ComparisonFilter config_;
51
  Runtime::Loader& runtime_;
52
};
53

            
54
/**
55
 * Filter on response status code.
56
 */
57
class StatusCodeFilter : public ComparisonFilter {
58
public:
59
  StatusCodeFilter(const envoy::config::accesslog::v3::StatusCodeFilter& config,
60
                   Runtime::Loader& runtime)
61
59
      : ComparisonFilter(config.comparison(), runtime) {}
62

            
63
  // AccessLog::Filter
64
  bool evaluate(const Formatter::Context& context,
65
                const StreamInfo::StreamInfo& info) const override;
66
};
67

            
68
/**
69
 * Filter on total request/response duration.
70
 */
71
class DurationFilter : public ComparisonFilter {
72
public:
73
  DurationFilter(const envoy::config::accesslog::v3::DurationFilter& config,
74
                 Runtime::Loader& runtime)
75
17
      : ComparisonFilter(config.comparison(), runtime) {}
76

            
77
  // AccessLog::Filter
78
  bool evaluate(const Formatter::Context& context,
79
                const StreamInfo::StreamInfo& info) const override;
80
};
81

            
82
/**
83
 * Base operator filter, compose other filters with operation
84
 */
85
class OperatorFilter : public Filter {
86
public:
87
  OperatorFilter(
88
      const Protobuf::RepeatedPtrField<envoy::config::accesslog::v3::AccessLogFilter>& configs,
89
      Server::Configuration::GenericFactoryContext& context);
90

            
91
protected:
92
  std::vector<FilterPtr> filters_;
93
};
94

            
95
/**
96
 * *And* operator filter, apply logical *and* operation to all of the sub filters.
97
 */
98
class AndFilter : public OperatorFilter {
99
public:
100
  AndFilter(const envoy::config::accesslog::v3::AndFilter& config,
101
            Server::Configuration::GenericFactoryContext& context);
102

            
103
  // AccessLog::Filter
104
  bool evaluate(const Formatter::Context& context,
105
                const StreamInfo::StreamInfo& info) const override;
106
};
107

            
108
/**
109
 * *Or* operator filter, apply logical *or* operation to all of the sub filters.
110
 */
111
class OrFilter : public OperatorFilter {
112
public:
113
  OrFilter(const envoy::config::accesslog::v3::OrFilter& config,
114
           Server::Configuration::GenericFactoryContext& context);
115

            
116
  // AccessLog::Filter
117
  bool evaluate(const Formatter::Context& context,
118
                const StreamInfo::StreamInfo& info) const override;
119
};
120

            
121
/**
122
 * Filter out health check requests.
123
 */
124
class NotHealthCheckFilter : public Filter {
125
public:
126
9189
  NotHealthCheckFilter() = default;
127

            
128
  // AccessLog::Filter
129
  bool evaluate(const Formatter::Context& context,
130
                const StreamInfo::StreamInfo& info) const override;
131
};
132

            
133
/**
134
 * Filter traceable requests.
135
 */
136
class TraceableRequestFilter : public Filter {
137
public:
138
  // AccessLog::Filter
139
  bool evaluate(const Formatter::Context& context,
140
                const StreamInfo::StreamInfo& info) const override;
141
};
142

            
143
/**
144
 * Filter that uses a runtime feature key to check if the log should be written.
145
 */
146
class RuntimeFilter : public Filter {
147
public:
148
  RuntimeFilter(const envoy::config::accesslog::v3::RuntimeFilter& config, Runtime::Loader& runtime,
149
                Random::RandomGenerator& random);
150

            
151
  // AccessLog::Filter
152
  bool evaluate(const Formatter::Context& context,
153
                const StreamInfo::StreamInfo& info) const override;
154

            
155
private:
156
  Runtime::Loader& runtime_;
157
  Random::RandomGenerator& random_;
158
  const std::string runtime_key_;
159
  const envoy::type::v3::FractionalPercent percent_;
160
  const bool use_independent_randomness_;
161
};
162

            
163
/**
164
 * Filter based on headers.
165
 */
166
class HeaderFilter : public Filter {
167
public:
168
  HeaderFilter(const envoy::config::accesslog::v3::HeaderFilter& config,
169
               Server::Configuration::CommonFactoryContext& context);
170

            
171
  // AccessLog::Filter
172
  bool evaluate(const Formatter::Context& context,
173
                const StreamInfo::StreamInfo& info) const override;
174

            
175
private:
176
  const Http::HeaderUtility::HeaderDataPtr header_data_;
177
};
178

            
179
/**
180
 * Filter requests that had a response with an Envoy response flag set.
181
 */
182
class ResponseFlagFilter : public Filter {
183
public:
184
  ResponseFlagFilter(const envoy::config::accesslog::v3::ResponseFlagFilter& config);
185

            
186
  // AccessLog::Filter
187
  bool evaluate(const Formatter::Context& context,
188
                const StreamInfo::StreamInfo& info) const override;
189

            
190
private:
191
  std::vector<bool> configured_flags_{};
192
};
193

            
194
/**
195
 * Filters requests that have a response with a gRPC status. Because the gRPC protocol does not
196
 * guarantee a gRPC status code, if a gRPC status code is not available, then the filter will infer
197
 * the gRPC status code from an HTTP status code if available.
198
 */
199
class GrpcStatusFilter : public Filter {
200
public:
201
  using GrpcStatusHashSet =
202
      absl::node_hash_set<Grpc::Status::GrpcStatus, absl::Hash<Grpc::Status::GrpcStatus>>;
203

            
204
  GrpcStatusFilter(const envoy::config::accesslog::v3::GrpcStatusFilter& config);
205

            
206
  // AccessLog::Filter
207
  bool evaluate(const Formatter::Context& context,
208
                const StreamInfo::StreamInfo& info) const override;
209

            
210
private:
211
  GrpcStatusHashSet statuses_;
212
  bool exclude_;
213

            
214
  /**
215
   * Converts a Protobuf representation of a gRPC status into the equivalent code version of a gRPC
216
   * status.
217
   */
218
  Grpc::Status::GrpcStatus
219
  protoToGrpcStatus(envoy::config::accesslog::v3::GrpcStatusFilter::Status status) const;
220
};
221

            
222
/**
223
 * Filters requests based on access log type
224
 */
225
class LogTypeFilter : public Filter {
226
public:
227
  using LogTypeHashSet = absl::flat_hash_set<AccessLogType>;
228

            
229
  LogTypeFilter(const envoy::config::accesslog::v3::LogTypeFilter& filter_config);
230

            
231
  bool evaluate(const Formatter::Context& context,
232
                const StreamInfo::StreamInfo& info) const override;
233

            
234
private:
235
  LogTypeHashSet types_;
236
  bool exclude_;
237
};
238

            
239
/**
240
 * Filters requests based on dynamic metadata
241
 */
242
class MetadataFilter : public Filter {
243
public:
244
  MetadataFilter(const envoy::config::accesslog::v3::MetadataFilter& filter_config,
245
                 Server::Configuration::CommonFactoryContext& context);
246

            
247
  bool evaluate(const Formatter::Context& context,
248
                const StreamInfo::StreamInfo& info) const override;
249

            
250
private:
251
  Matchers::PresentMatcher present_matcher_;
252
  Matchers::ValueMatcherConstSharedPtr value_matcher_;
253

            
254
  std::vector<std::string> path_;
255

            
256
  const bool default_match_;
257
  const std::string filter_;
258
};
259

            
260
/**
261
 * Access log factory that reads the configuration from proto.
262
 */
263
class AccessLogFactory {
264
public:
265
  /**
266
   * Read a filter definition from proto and instantiate an Instance. This method is used
267
   * to create access log instances that need access to listener properties.
268
   */
269
  static InstanceSharedPtr
270
  fromProto(const envoy::config::accesslog::v3::AccessLog& config,
271
            Server::Configuration::GenericFactoryContext& context,
272
            std::vector<Formatter::CommandParserPtr>&& command_parsers = {});
273
};
274

            
275
} // namespace AccessLog
276
} // namespace Envoy