1
#include "source/extensions/tracers/opentelemetry/samplers/cel/cel_sampler.h"
2

            
3
#include <memory>
4
#include <sstream>
5
#include <string>
6

            
7
#include "source/common/config/datasource.h"
8
#include "source/extensions/tracers/opentelemetry/span_context.h"
9

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

            
15
CELSampler::CELSampler(const ::Envoy::LocalInfo::LocalInfo& local_info,
16
                       Expr::BuilderInstanceSharedConstPtr builder,
17
                       const xds::type::v3::CelExpression& expr)
18
16
    : local_info_(local_info), compiled_expr_([&]() {
19
16
        auto compiled_expr = Expr::CompiledExpression::Create(builder, expr);
20
16
        if (!compiled_expr.ok()) {
21
1
          throw EnvoyException(
22
1
              absl::StrCat("failed to create an expression: ", compiled_expr.status().message()));
23
1
        }
24
15
        return std::move(compiled_expr.value());
25
16
      }()) {}
26

            
27
SamplingResult CELSampler::shouldSample(const StreamInfo::StreamInfo& stream_info,
28
                                        const absl::optional<SpanContext> parent_context,
29
                                        const std::string& /*trace_id*/,
30
                                        const std::string& /*name*/, OTelSpanKind /*kind*/,
31
                                        OptRef<const Tracing::TraceContext> trace_context,
32
9
                                        const std::vector<SpanContext>& /*links*/) {
33

            
34
9
  Protobuf::Arena arena;
35
9
  const ::Envoy::Http::RequestHeaderMap* request_headers = nullptr;
36
9
  if (trace_context.has_value() && trace_context->requestHeaders().has_value()) {
37
6
    request_headers = trace_context->requestHeaders().ptr();
38
6
  }
39

            
40
9
  auto eval_status = compiled_expr_.evaluate(
41
9
      arena, &local_info_, stream_info, request_headers /* request_headers */,
42
9
      nullptr /* response_headers */, nullptr /* response_trailers */);
43
9
  SamplingResult result;
44
9
  if (!eval_status.has_value() || eval_status.value().IsError()) {
45
1
    result.decision = Decision::Drop;
46
1
    return result;
47
1
  }
48
8
  auto eval_result_val = eval_status.value();
49
8
  auto eval_result = eval_result_val.IsBool() ? eval_result_val.BoolOrDie() : false;
50
8
  if (!eval_result) {
51
2
    result.decision = Decision::Drop;
52
2
    return result;
53
2
  }
54

            
55
6
  result.decision = Decision::RecordAndSample;
56
6
  if (parent_context.has_value()) {
57
4
    result.tracestate = parent_context.value().tracestate();
58
4
  }
59
6
  return result;
60
8
}
61

            
62
} // namespace OpenTelemetry
63
} // namespace Tracers
64
} // namespace Extensions
65
} // namespace Envoy