aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/neh/stat.h
blob: 803e8d2974c614c261a8ea4a11536dcf2df92a64 (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
87
88
89
90
91
92
93
94
95
96
#pragma once

#include <util/generic/ptr.h>
#include <util/stream/output.h>
#include <library/cpp/deprecated/atomic/atomic.h>
#include <library/cpp/deprecated/atomic/atomic_ops.h>

namespace NNeh {
    class TStatCollector;

    /// NEH service workability statistics collector.
    ///
    /// Disabled by default, use `TServiceStat::ConfigureValidator` to set `maxContinuousErrors`
    /// different from zero.
    class TServiceStat: public TThrRefBase {
    public:
        static void ConfigureValidator(unsigned maxContinuousErrors, unsigned reSendValidatorPeriod) noexcept {
            AtomicSet(MaxContinuousErrors_, maxContinuousErrors);
            AtomicSet(ReSendValidatorPeriod_, reSendValidatorPeriod);
        }
        static bool Disabled() noexcept {
            return !AtomicGet(MaxContinuousErrors_);
        }

        enum EStatus {
            Ok,
            Fail,
            ReTry //time for sending request-validator to service
        };

        EStatus GetStatus();

        void DbgOut(IOutputStream&) const;

    protected:
        friend class TStatCollector;

        virtual void OnBegin();
        virtual void OnSuccess();
        virtual void OnCancel();
        virtual void OnFail();

        static TAtomic MaxContinuousErrors_;
        static TAtomic ReSendValidatorPeriod_;
        TAtomicCounter RequestsInProcess_;
        TAtomic LastContinuousErrors_ = 0;
        TAtomic SendValidatorCounter_ = 0;
    };

    using TServiceStatRef = TIntrusivePtr<TServiceStat>;

    //thread safe (race protected) service stat updater
    class TStatCollector {
    public:
        TStatCollector(TServiceStatRef& ss)
            : SS_(ss)
        {
            ss->OnBegin();
        }

        ~TStatCollector() {
            if (CanInformSS()) {
                SS_->OnFail();
            }
        }

        void OnCancel() noexcept {
            if (CanInformSS()) {
                SS_->OnCancel();
            }
        }

        void OnFail() noexcept {
            if (CanInformSS()) {
                SS_->OnFail();
            }
        }

        void OnSuccess() noexcept {
            if (CanInformSS()) {
                SS_->OnSuccess();
            }
        }

    private:
        inline bool CanInformSS() noexcept {
            return AtomicGet(CanInformSS_) && AtomicCas(&CanInformSS_, 0, 1);
        }

        TServiceStatRef SS_;
        TAtomic CanInformSS_ = 1;
    };

    TServiceStatRef GetServiceStat(TStringBuf addr);

}