#pragma once #include #include #include #include #include "config.h" #include namespace Poco { class Logger; } namespace DB { /** * Query profiler implementation for selected thread. * * This class installs timer and signal handler on creation to: * 1. periodically pause given thread * 2. collect thread's current stack trace * 3. write collected stack trace to trace_pipe for TraceCollector * * Destructor tries to unset timer and restore previous signal handler. * Note that signal handler implementation is defined by template parameter. See QueryProfilerReal and QueryProfilerCPU. */ #ifndef __APPLE__ class Timer { public: Timer(); Timer(const Timer &) = delete; Timer & operator = (const Timer &) = delete; ~Timer(); void createIfNecessary(UInt64 thread_id, int clock_type, int pause_signal); void set(UInt32 period); void stop(); void cleanup(); private: LoggerPtr log; std::optional timer_id; }; #endif template class QueryProfilerBase { public: QueryProfilerBase(UInt64 thread_id, int clock_type, UInt32 period, int pause_signal_); ~QueryProfilerBase(); private: void cleanup(); LoggerPtr log; #ifndef __APPLE__ inline static thread_local Timer timer = Timer(); #endif /// Pause signal to interrupt threads to get traces int pause_signal; }; /// Query profiler with timer based on real clock class QueryProfilerReal : public QueryProfilerBase { public: QueryProfilerReal(UInt64 thread_id, UInt32 period); /// NOLINT static void signalHandler(int sig, siginfo_t * info, void * context); }; /// Query profiler with timer based on CPU clock class QueryProfilerCPU : public QueryProfilerBase { public: QueryProfilerCPU(UInt64 thread_id, UInt32 period); /// NOLINT static void signalHandler(int sig, siginfo_t * info, void * context); }; }