aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/actors/helpers/mon_histogram_helper.h
blob: a9a57e38238c9d386e109dfc12179c24b1bd0bdf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#pragma once

#include <library/cpp/monlib/dynamic_counters/counters.h>

#include <util/string/cast.h>

namespace NActors {
    namespace NMon {
        class THistogramCounterHelper {
        public:
            THistogramCounterHelper()
                : FirstBucketVal(0)
                , BucketCount(0)
            {
            }

            THistogramCounterHelper(const THistogramCounterHelper&) = default;

            void Init(NMonitoring::TDynamicCounters* group, const TString& baseName, const TString& unit,
                ui64 firstBucket, ui64 bucketCnt, bool useSensorLabelName = true)
            {
                Y_ASSERT(FirstBucketVal == 0);
                Y_ASSERT(BucketCount == 0);

                FirstBucketVal = firstBucket;
                BucketCount = bucketCnt;
                BucketsHolder.reserve(BucketCount);
                Buckets.reserve(BucketCount);
                for (size_t i = 0; i < BucketCount; ++i) {
                    TString bucketName = GetBucketName(i) + " " + unit;
                    auto labelName = useSensorLabelName ? "sensor" : "name";
                    BucketsHolder.push_back(group->GetSubgroup(labelName, baseName)->GetNamedCounter("range", bucketName, true));
                    Buckets.push_back(BucketsHolder.back().Get());
                }
            }

            void Add(ui64 val) {
                Y_ASSERT(FirstBucketVal != 0);
                Y_ASSERT(BucketCount != 0);
                Y_VERIFY(val <= (1ULL << 63ULL));
                size_t ind = 0;
                if (val > FirstBucketVal) {
                    ind = GetValueBitCount((2 * val - 1) / FirstBucketVal) - 1;
                    if (ind >= BucketCount) {
                        ind = BucketCount - 1;
                    }
                }
                Buckets[ind]->Inc();
            }

            ui64 GetBucketCount() const {
                return BucketCount;
            }

            ui64 GetBucketValue(size_t index) const {
                Y_ASSERT(index < BucketCount);
                return Buckets[index]->Val();
            }

            void SetBucketValue(ui64 index, ui64 value) {
                Y_ASSERT(index < BucketCount);
                *Buckets[index] = value;
            }

        private:
            TString GetBucketName(size_t ind) const {
                Y_ASSERT(FirstBucketVal != 0);
                Y_ASSERT(BucketCount != 0);
                Y_ASSERT(ind < BucketCount);
                if (ind + 1 < BucketCount) {
                    return ToString<ui64>(FirstBucketVal << ind);
                } else {
                    // Last slot is up to +INF
                    return "INF";
                }
            }

        private:
            ui64 FirstBucketVal;
            ui64 BucketCount;
            TVector<NMonitoring::TDynamicCounters::TCounterPtr> BucketsHolder;
            TVector<NMonitoring::TDeprecatedCounter*> Buckets;
        };

    }
}