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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
#pragma once
#include "unistat.h"
#include <util/datetime/base.h>
#include <util/generic/noncopyable.h>
#include <util/generic/va_args.h>
#include <util/generic/yexception.h>
#include <util/system/defaults.h>
class TUnistatTimer: public TNonCopyable {
public:
template <typename T>
TUnistatTimer(TUnistat& unistat, T&& holename)
: Started_(Now())
, HoleName_(ToString(holename))
, Aggregator_(unistat)
{
}
~TUnistatTimer() {
if (!Dismiss_) {
Aggregator_.PushSignalUnsafe(HoleName_, (Now() - Started_).MillisecondsFloat());
}
}
void Dismiss() noexcept {
Dismiss_ = true;
}
void Accept() noexcept {
Dismiss_ = false;
}
private:
bool Dismiss_{false};
const TInstant Started_;
const TString HoleName_;
TUnistat& Aggregator_;
};
class TUnistatExceptionCounter: public TNonCopyable {
public:
template <typename T, typename U>
TUnistatExceptionCounter(TUnistat& unistat, T&& hasExceptionHolename, U&& noExceptionHolename)
: HasExceptionHoleName_(ToString(hasExceptionHolename))
, NoExceptionHoleName_(ToString(noExceptionHolename))
, Aggregator_(unistat)
{
}
template <typename T>
TUnistatExceptionCounter(TUnistat& unistat, T&& hasExceptionHolename)
: HasExceptionHoleName_(ToString(hasExceptionHolename))
, Aggregator_(unistat)
{
}
~TUnistatExceptionCounter() {
if (!Dismiss_) {
if (UncaughtException()) {
Aggregator_.PushSignalUnsafe(HasExceptionHoleName_, 1.);
} else if (NoExceptionHoleName_) {
Aggregator_.PushSignalUnsafe(NoExceptionHoleName_, 1.);
}
}
}
void Dismiss() noexcept {
Dismiss_ = true;
}
void Accept() noexcept {
Dismiss_ = false;
}
private:
bool Dismiss_{false};
const TString HasExceptionHoleName_;
const TString NoExceptionHoleName_;
TUnistat& Aggregator_;
};
/**
* @def Y_UNISTAT_TIMER
*
* Macro is needed to time scope and push time into aggregator.
*
* @code
* void DoSomethingImportant() {
* Y_UNISTAT_TIMER(TUnistat::Instance(), "doing-important-stuff")
* // doing something here
* }
* @endcode
*/
#define Y_UNISTAT_TIMER(unistat, holeName) \
::TUnistatTimer Y_GENERATE_UNIQUE_ID(timer){unistat, holeName};
#define Y_UNISTAT_EXCEPTION_COUNTER_IMPL_2(unistat, hasExceptionHoleName) \
::TUnistatExceptionCounter Y_GENERATE_UNIQUE_ID(exceptionCounter){unistat, hasExceptionHoleName};
#define Y_UNISTAT_EXCEPTION_COUNTER_IMPL_3(unistat, hasExceptionHolename, noExceptionHolename) \
::TUnistatExceptionCounter Y_GENERATE_UNIQUE_ID(exceptionCounter){unistat, hasExceptionHolename, noExceptionHolename};
#define Y_UNISTAT_EXCEPTION_COUNTER_IMPL_DISPATCHER(_1, _2, _3, NAME, ...) NAME
/**
* @def Y_UNISTAT_EXCEPTION_COUNTER
*
* Macro is needed to check if there was an exception on scope exit or not.
*
* @code
* void DoSomethingThatMayThrowException() {
* Y_UNISTAT_EXCEPTION_COUNTER(TUnistat::Instance(), "exception_occured", "no_exception")
* Y_UNISTAT_EXCEPTION_COUNTER(TUnistat::Instance(), "wow_exception_occured")
* // doing something here
* }
* @endcode
*/
#define Y_UNISTAT_EXCEPTION_COUNTER(...) Y_PASS_VA_ARGS(Y_UNISTAT_EXCEPTION_COUNTER_IMPL_DISPATCHER(__VA_ARGS__, Y_UNISTAT_EXCEPTION_COUNTER_IMPL_3, Y_UNISTAT_EXCEPTION_COUNTER_IMPL_2)(__VA_ARGS__))
|