aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/lwtrace/all.h
blob: d7aa57c49d7d9247867875068ebeaab0eaa48509 (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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#pragma once

#include "control.h"
#include "event.h"
#include "preprocessor.h"
#include "probe.h"
#include "start.h"

//
// Full documentation: https://wiki.yandex-team.ru/development/poisk/arcadia/library/lwtrace/
//
// Short usage instruction:
//
// 1. Declare probes provider in header file 'probes.h':
//       #include <yweb/robot/kiwi/lwtrace/all.h>
//       #define MY_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \   // name of your provider
//           PROBE(MyProbe, GROUPS("MyGroup1", "MyGroup2"), TYPES(), NAMES()) \   // probe specification w/o argiments
//           PROBE(MyAnotherProbe, GROUPS("MyGroup2"), TYPES(int, TString), NAMES("arg1", "arg2")) \   // another probe with arguments
//           PROBE(MyScopedProbe, GROUPS(), TYPES(ui64, int), NAMES("duration", "stage")) \   // scoped probe with argument
//           /**/
//       LWTRACE_DECLARE_PROVIDER(MY_PROVIDER)
//
// 2. Define provider in source file 'provider.cpp':
//       #include "probes.h"
//       LWTRACE_DEFINE_PROVIDER(MY_PROVIDER)
//
// 3. Call probes from provider in your code:
//       #include "probes.h"
//       int main() {
//           GLOBAL_LWPROBE(MY_PROVIDER, MyProbe);
//           GLOBAL_LWPROBE(MY_PROVIDER, MyAnotherProbe, 123, stroka);
//           ... or ...
//           LWTRACE_USING(MY_PROVIDER); // expands into using namespace
//           LWPROBE(MyProbe);
//           LWPROBE(MyAnotherProbe, 123, stroka);
//       }
//
// 4. Attach provider to your monitoring service:
//       #include <yweb/robot/kiwi/util/monservice.h>
//       #include "probes.h"
//       class TMyMonSrvc: public NKiwi::TMonService {
//           TMyMonSrvc(TProbeRegistry& probes)
//           {
//               THolder<NKiwi::TTraceMonPage> tr(new NKiwi::TTraceMonPage());
//               tr->GetProbes().AddProbesList(LWTRACE_GET_PROBES(MY_PROVIDER));
//               Register(tr.Release());
//           }
//       };
//
// 5. Compile and run application
//
// 6. Create file 'mysuper.tr' with trace query:
//        Blocks { # Log all calls to probes from MyGroup1
//            ProbeDesc { Group: "MyGroup1" }
//            Action {
//                LogAction { LogTimestamp: true }
//            }
//        }
//        Blocks { # Log first 10 calls to MyAnother with arg1 > 1000
//            ProbeDesc { Name: "MyAnotherProbe"; Provider: "MY_PROVIDER" }
//            Predicate {
//                Operators { Type: OT_GT; Param: "arg1"; Value: "1000" }
//            }
//            Action {
//                LogAction { MaxRecords: 10 }
//            }
//        }
//        Blocks { # Start following executon of all 4 blocks each time MyAnotherProbe was called with arg2 == "start"
//            ProbeDesc { Name: "MyAnotherProbe"; Provider: "MY_PROVIDER" }
//            Predicate {
//                Operators { Type: OT_EQ; Param: "arg2"; Value: "start" }
//            }
//            Action { StartAction {} }
//        }
//        Blocks { # Stop following executon of all 4 blocks each time MyAnotherProbe was called with arg2 == "stop"
//            ProbeDesc { Name: "MyAnotherProbe"; Provider: "MY_PROVIDER" }
//            Predicate {
//                Operators { Type: OT_EQ; Param: "arg2"; Value: "stop" }
//            }
//            Action { StopAction {} }
//        }
//
// 7. Send trace query to the server with HTTP POST:
//       yweb/robot/kiwi/scripts/trace.sh new uniq-id-for-my-trace hostname:monport < mysuper.tr
//
// 8. With browser go to: http://hostname:monport/trace
//
// 9. Delete query from server:
//       yweb/robot/kiwi/scripts/trace.sh delete uniq-id-for-my-trace hostname:monport
//
//
// CONFIGURATION AND SUPPORT:
// 1. Turning off all calls to probes.
//       Add to project's CMakeLists.txt: add_definitions(-DLWTRACE_DISABLE_PROBES)
//
// 2. Turning off all calls to events.
//       Add to project's CMakeLists.txt: add_definitions(-DLWTRACE_DISABLE_EVENTS)
//
// 3. Increasing maximum number of probe parameters:
//       Add more lines in FOREACH_PARAMNUM macro definition in preprocessor.h
//
//
// ISSUES
// 1. Note that executors for different blocks are attached in order of their declaration in trace script.
//    Executor can be called by a program as soon as it is attached, therefore there is no guarantee that
//    all blocks are started simultaneously
//

#ifndef LWTRACE_DISABLE

// Declare user provider (see USAGE INSTRUCTION)
#define LWTRACE_DECLARE_PROVIDER(provider) LWTRACE_DECLARE_PROVIDER_I(provider)

// Define user provider (see USAGE INSTRUCTION)
#define LWTRACE_DEFINE_PROVIDER(provider) LWTRACE_DEFINE_PROVIDER_I(provider)

// Import names from provider
#define LWTRACE_USING(provider) using namespace LWTRACE_GET_NAMESPACE(provider);

// Probes and events list accessor
#define LWTRACE_GET_PROBES(provider) LWTRACE_GET_PROBES_I(provider)
#define LWTRACE_GET_EVENTS(provider) LWTRACE_GET_EVENTS_I(provider)

#ifndef LWTRACE_DISABLE_PROBES

// Call a probe
// NOTE: LWPROBE() should be used in source files only with previous call to LWTRACE_USING(MY_PROVIDER)
// NOTE: in header files GLOBAL_LWPROBE() should be used instead
// NOTE: if lots of calls needed in header file, it's convenient to define/undef the following macro:
// NOTE: #define MY_PROBE(name, ...) GLOBAL_LWPROBE(MY_PROVIDER, name, ## __VA_ARGS__)
#define GLOBAL_LWPROBE(provider, probe, ...) LWPROBE_I(LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_NAME(probe), ##__VA_ARGS__)
#define LWPROBE(probe, ...) LWPROBE_I(LWTRACE_GET_NAME(probe), ##__VA_ARGS__)
#define GLOBAL_LWPROBE_ENABLED(provider, probe) LWPROBE_ENABLED_I(LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_NAME(probe))
#define LWPROBE_ENABLED(probe) LWPROBE_ENABLED_I(LWTRACE_GET_NAME(probe))
#define LWPROBE_OBJ(probe, ...) LWPROBE_I(probe, ##__VA_ARGS__)

// Calls a probe when scope is beeing left
// NOTE: arguments are passed by value and stored until scope exit
// NOTE: probe should be declared with first params of type ui64, argument for which is automaticaly generated (duration in microseconds)
// NOTE: *_DURATION() macros take through "..." all arguments except the first one
#define GLOBAL_LWPROBE_DURATION(provider, probe, ...) LWPROBE_DURATION_I(LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_TYPE(probe), lwtrace_scoped_##provider##probe, LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_NAME(probe), ##__VA_ARGS__)
#define LWPROBE_DURATION(probe, ...) LWPROBE_DURATION_I(LWTRACE_GET_TYPE(probe), lwtrace_scoped_##probe, LWTRACE_GET_NAME(probe), ##__VA_ARGS__)

// Probe with orbit support
#define GLOBAL_LWTRACK(provider, probe, orbit, ...) LWTRACK_I(LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_NAME(probe), orbit, ##__VA_ARGS__)
#define LWTRACK(probe, orbit, ...) LWTRACK_I(LWTRACE_GET_NAME(probe), orbit, ##__VA_ARGS__)
#define LWTRACK_OBJ(probe, orbit, ...) LWTRACK_I(probe, orbit, ##__VA_ARGS__)

#else
#define GLOBAL_LWPROBE(provider, probe, ...)
#define LWPROBE(probe, ...)
#define GLOBAL_LWPROBE_ENABLED(provider, probe) false
#define LWPROBE_ENABLED(probe) false
#define LWPROBE_OBJ(probe, ...) Y_UNUSED(probe)
#define GLOBAL_LWPROBE_DURATION(provider, probe, ...)
#define LWPROBE_DURATION(probe, ...)
#define GLOBAL_LWTRACK(provider, probe, orbit, ...)
#define LWTRACK(probe, orbit, ...)
#define LWTRACK_OBJ(probe, orbit, ...) Y_UNUSED(probe)
#endif

#ifndef LWTRACE_DISABLE_EVENTS

// Call an event
// NOTE: LWEVENT() should be used in source files only with previous call to LWTRACE_USING(MY_PROVIDER)
// NOTE: in header files GLOBAL_LWEVENT() should be used instead
// NOTE: if lots of calls needed in header file, it's convenient to define/undef the following macro:
// NOTE: #define MY_EVENT(name, ...) GLOBAL_LWEVENT(MY_PROVIDER, name, ## __VA_ARGS__)
#define GLOBAL_LWEVENT(provider, event, ...) LWEVENT_I(LWTRACE_GET_NAMESPACE(provider)::LWTRACE_GET_NAME(event), ##__VA_ARGS__)
#define LWEVENT(event, ...) LWEVENT_I(LWTRACE_GET_NAME(event), ##__VA_ARGS__)

#else
#define GLOBAL_LWEVENT(provider, event, ...)
#define LWEVENT(event, ...)
#endif

#else

#define LWTRACE_DECLARE_PROVIDER(provider)
#define LWTRACE_DEFINE_PROVIDER(provider)
#define LWTRACE_USING(provider)
#define LWTRACE_GET_PROBES(provider) NULL
#define LWTRACE_GET_EVENTS(provider) NULL
#define GLOBAL_LWPROBE(provider, probe, ...)
#define LWPROBE(probe, ...)
#define GLOBAL_LWPROBE_ENABLED(provider, probe) false
#define LWPROBE_ENABLED(probe) false
#define GLOBAL_LWPROBE_DURATION(provider, probe, ...)
#define LWPROBE_DURATION(probe, ...)
#define GLOBAL_LWTRACK(provider, probe, orbit, ...)
#define LWTRACK(probe, orbit, ...)
#define GLOBAL_LWEVENT(provider, event, ...)
#define LWEVENT(event, ...)

#endif