diff --git a/base/daemon/BaseDaemon.cpp b/base/daemon/BaseDaemon.cpp index e9f85da3594..91b2351db38 100644 --- a/base/daemon/BaseDaemon.cpp +++ b/base/daemon/BaseDaemon.cpp @@ -53,6 +53,8 @@ #include #include +#include + #if !defined(ARCADIA_BUILD) # include #endif @@ -308,16 +310,12 @@ private: /// Write symbolized stack trace line by line for better grep-ability. stack_trace.toStringEveryLine([&](const std::string & s) { LOG_FATAL(log, s); }); + /// Write crash to system.crash_log table if available. + DB::CrashLog::collect(sig, thread_num, query_id, stack_trace); + /// Send crash report to developers (if configured) - - #if defined(__ELF__) && !defined(__FreeBSD__) - const String & build_id_hex = DB::SymbolIndex::instance().getBuildIDHex(); - #else - String build_id_hex{}; - #endif - if (sig != SanitizerTrap) - SentryWriter::onFault(sig, error_message, stack_trace, build_id_hex); + SentryWriter::onFault(sig, error_message, stack_trace); /// When everything is done, we will try to send these error messages to client. if (thread_ptr) diff --git a/base/daemon/SentryWriter.cpp b/base/daemon/SentryWriter.cpp index be432602f6e..e0ed43207fa 100644 --- a/base/daemon/SentryWriter.cpp +++ b/base/daemon/SentryWriter.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #if !defined(ARCADIA_BUILD) @@ -157,7 +158,7 @@ void SentryWriter::shutdown() sentry_shutdown(); } -void SentryWriter::onFault(int sig, const std::string & error_message, const StackTrace & stack_trace, const std::string & build_id_hex) +void SentryWriter::onFault(int sig, const std::string & error_message, const StackTrace & stack_trace) { auto * logger = &Poco::Logger::get("SentryWriter"); if (initialized) @@ -165,10 +166,12 @@ void SentryWriter::onFault(int sig, const std::string & error_message, const Sta sentry_value_t event = sentry_value_new_message_event(SENTRY_LEVEL_FATAL, "fault", error_message.c_str()); sentry_set_tag("signal", strsignal(sig)); sentry_set_extra("signal_number", sentry_value_new_int32(sig)); - if (!build_id_hex.empty()) - { + + #if defined(__ELF__) && !defined(__FreeBSD__) + const String & build_id_hex = DB::SymbolIndex::instance().getBuildIDHex(); sentry_set_tag("build_id", build_id_hex.c_str()); - } + #endif + setExtras(); /// Prepare data for https://develop.sentry.dev/sdk/event-payloads/stacktrace/ @@ -240,6 +243,6 @@ void SentryWriter::onFault(int sig, const std::string & error_message, const Sta void SentryWriter::initialize(Poco::Util::LayeredConfiguration &) {} void SentryWriter::shutdown() {} -void SentryWriter::onFault(int, const std::string &, const StackTrace &, const std::string &) {} +void SentryWriter::onFault(int, const std::string &, const StackTrace &) {} #endif diff --git a/base/daemon/SentryWriter.h b/base/daemon/SentryWriter.h index a5cc82651a9..0888b2fe9a3 100644 --- a/base/daemon/SentryWriter.h +++ b/base/daemon/SentryWriter.h @@ -23,7 +23,5 @@ namespace SentryWriter void onFault( int sig, const std::string & error_message, - const StackTrace & stack_trace, - const std::string & build_id_hex - ); + const StackTrace & stack_trace); }; diff --git a/src/Common/StackTrace.cpp b/src/Common/StackTrace.cpp index 9c6904b884c..0ffe0f01afc 100644 --- a/src/Common/StackTrace.cpp +++ b/src/Common/StackTrace.cpp @@ -308,7 +308,8 @@ const StackTrace::FramePointers & StackTrace::getFramePointers() const return frame_pointers; } -static void toStringEveryLineImpl(const StackTrace::FramePointers & frame_pointers, size_t offset, size_t size, std::function callback) +static void toStringEveryLineImpl( + const StackTrace::FramePointers & frame_pointers, size_t offset, size_t size, std::function callback) { if (size == 0) return callback(""); diff --git a/src/Common/TraceCollector.cpp b/src/Common/TraceCollector.cpp index eb87f95bd7b..599815680a4 100644 --- a/src/Common/TraceCollector.cpp +++ b/src/Common/TraceCollector.cpp @@ -141,7 +141,8 @@ void TraceCollector::run() if (trace_log) { - TraceLogElement element{std::time(nullptr), clock_gettime_ns(), trace_type, thread_id, query_id, trace, size}; + UInt64 time = clock_gettime_ns(); + TraceLogElement element{time_t(time / 1000000000), time, trace_type, thread_id, query_id, trace, size}; trace_log->add(element); } } diff --git a/src/Interpreters/CrashLog.cpp b/src/Interpreters/CrashLog.cpp index d802a5a927a..69af5ad11cb 100644 --- a/src/Interpreters/CrashLog.cpp +++ b/src/Interpreters/CrashLog.cpp @@ -58,4 +58,26 @@ void CrashLogElement::appendToBlock(MutableColumns & columns) const columns[i++]->insert(build_id_hex); } +void CrashLog::collect(Int32 signal, UInt64 thread_id, const String & query_id, const StackTrace & stack_trace) +{ + UInt64 time = clock_gettime_ns(); + + size_t stack_trace_size = stack_trace.getSize(); + size_t stack_trace_offset = stack_trace.getOffset(); + size_t num_frames = stack_trace_size - stack_trace_offset; + + Array trace; + Array trace_full; + + trace.reserve(num_frames); + trace_full.reserve(num_frames); + + for (size_t i = stack_trace_offset; i < stack_trace_size; ++i) + trace.push_back(reinterpret_cast(stack_trace.getFramePointers()[i])); + + stack_trace.toStringEveryLine([&trace_full](const std::string & line) { trace_full.push_back(line); }); + + CrashLogElement element{time_t(time / 1000000000), time, signal, thread_id, query_id, trace, trace_full}; +} + } diff --git a/src/Interpreters/CrashLog.h b/src/Interpreters/CrashLog.h index 2f6dd79fcec..5f0a3221952 100644 --- a/src/Interpreters/CrashLog.h +++ b/src/Interpreters/CrashLog.h @@ -40,6 +40,8 @@ public: if (auto crash_log_owned = crash_log.lock()) crash_log_owned->add(element); } + + static void collect(Int32 signal, UInt64 thread_id, const String & query_id, const StackTrace & stack_trace); }; }