#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 // #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 // #include "probes.h" // class TMyMonSrvc: public NKiwi::TMonService { // TMyMonSrvc(TProbeRegistry& probes) // { // THolder 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