Branch data Line data Source code
1 : : #include <hpactor/tracing/sampler.hpp>
2 : :
3 : : #include <algorithm>
4 : : #include <atomic>
5 : : #include <chrono>
6 : :
7 : : namespace hpactor::tracing {
8 : :
9 : : namespace {
10 : :
11 : 10 : uint64_t splitmix64(uint64_t x) noexcept {
12 : 10 : x += 0x9e3779b97f4a7c15ULL;
13 : 10 : x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;
14 : 10 : x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;
15 : 10 : return x ^ (x >> 31);
16 : : }
17 : :
18 : 0 : uint64_t trace_low64(const TraceId& id) noexcept {
19 : 0 : uint64_t value = 0;
20 : 0 : for (size_t i = 8; i < 16; ++i) {
21 : 0 : value = (value << 8) | id.bytes[i];
22 : : }
23 : 0 : return value;
24 : : }
25 : :
26 : : } // namespace
27 : :
28 : : SamplingDecision
29 : 5 : AlwaysOnSampler::should_sample(const SamplingParameters& /*params*/) const noexcept {
30 : 5 : return {true};
31 : : }
32 : :
33 : : SamplingDecision
34 : 1 : AlwaysOffSampler::should_sample(const SamplingParameters& /*params*/) const noexcept {
35 : 1 : return {false};
36 : : }
37 : :
38 : 4 : TraceIdRatioSampler::TraceIdRatioSampler(double ratio)
39 : 4 : : ratio_(std::clamp(ratio, 0.0, 1.0)) {}
40 : :
41 : : SamplingDecision
42 : 2 : TraceIdRatioSampler::should_sample(const SamplingParameters& params) const noexcept {
43 : 2 : if (ratio_ <= 0.0)
44 : 1 : return {false};
45 : 1 : if (ratio_ >= 1.0)
46 : 1 : return {true};
47 : 0 : const uint64_t threshold =
48 : 0 : static_cast<uint64_t>(ratio_ * static_cast<double>(UINT64_MAX));
49 : 0 : return {splitmix64(trace_low64(params.trace_id)) <= threshold};
50 : : }
51 : :
52 : 2 : ParentBasedSampler::ParentBasedSampler(double root_ratio)
53 : 2 : : root_sampler_(root_ratio) {}
54 : :
55 : : SamplingDecision
56 : 2 : ParentBasedSampler::should_sample(const SamplingParameters& params) const noexcept {
57 : 2 : if (params.has_parent) {
58 : 2 : return {params.parent_sampled};
59 : : }
60 : 0 : return root_sampler_.should_sample(params);
61 : : }
62 : :
63 : 3 : TraceId TraceIdGenerator::next_trace_id() noexcept {
64 : 3 : TraceId id;
65 : 3 : const uint64_t n = counter_.fetch_add(1, std::memory_order_relaxed);
66 : 3 : uint64_t hi = splitmix64(n);
67 : 3 : uint64_t lo = splitmix64(n ^ 0xd1b54a32d192ed03ULL);
68 : 27 : for (int i = 7; i >= 0; --i) {
69 : 48 : id.bytes[static_cast<size_t>(7 - i)] =
70 : 24 : static_cast<uint8_t>((hi >> (i * 8)) & 0xFF);
71 : 24 : id.bytes[static_cast<size_t>(15 - i)] =
72 : 24 : static_cast<uint8_t>((lo >> (i * 8)) & 0xFF);
73 : : }
74 : 3 : if (!id.valid()) {
75 : 0 : id.bytes[15] = 1;
76 : : }
77 : 3 : return id;
78 : : }
79 : :
80 : 4 : SpanId TraceIdGenerator::next_span_id() noexcept {
81 : 4 : SpanId id;
82 : 4 : const uint64_t n = counter_.fetch_add(1, std::memory_order_relaxed);
83 : 4 : uint64_t value = splitmix64(n ^ 0x94d049bb133111ebULL);
84 : 36 : for (int i = 7; i >= 0; --i) {
85 : 32 : id.bytes[static_cast<size_t>(7 - i)] =
86 : 32 : static_cast<uint8_t>((value >> (i * 8)) & 0xFF);
87 : : }
88 : 4 : if (!id.valid()) {
89 : 0 : id.bytes[7] = 1;
90 : : }
91 : 4 : return id;
92 : : }
93 : :
94 : : } // namespace hpactor::tracing
|