diff --git a/bazel/ray_deps_setup.bzl b/bazel/ray_deps_setup.bzl index aa05680dfefd4..f9963125ed10c 100644 --- a/bazel/ray_deps_setup.bzl +++ b/bazel/ray_deps_setup.bzl @@ -185,6 +185,7 @@ def ray_deps_setup(): "//thirdparty/patches:glog-log-pid-tid.patch", "//thirdparty/patches:glog-stack-trace.patch", "//thirdparty/patches:glog-suffix-log.patch", + "//thirdparty/patches:glog-dump-stacktrack.patch", ], ) diff --git a/src/ray/util/logging.cc b/src/ray/util/logging.cc index 62dee6bfce407..1f77ed7c077f9 100644 --- a/src/ray/util/logging.cc +++ b/src/ray/util/logging.cc @@ -47,6 +47,14 @@ namespace ray { +std::string GetCallTrace() { + std::string return_message = "Cannot get callstack information."; +#ifdef RAY_USE_GLOG + return google::GetStackTraceToString(); +#endif + return return_message; +} + #ifdef RAY_USE_GLOG struct StdoutLogger : public google::base::Logger { std::ostream &out() { return std::cout; } diff --git a/src/ray/util/logging.h b/src/ray/util/logging.h index 6b1f8b65c6f49..dcbf1c375f3f9 100644 --- a/src/ray/util/logging.h +++ b/src/ray/util/logging.h @@ -43,6 +43,11 @@ enum { ERROR = 0 }; #endif namespace ray { +/// In order to use the get stacktrace method in other non-glog scenarios, we +/// have added a patch to allow glog to return the current call stack information +/// through the internal interface. This function `GetCallTrace` is a wrapper +/// providing a new detection function for debug or something like that. +std::string GetCallTrace(); enum class RayLogLevel { DEBUG = -1, INFO = 0, WARNING = 1, ERROR = 2, FATAL = 3 }; diff --git a/src/ray/util/logging_test.cc b/src/ray/util/logging_test.cc index 340740fdade88..d3db179eb4364 100644 --- a/src/ray/util/logging_test.cc +++ b/src/ray/util/logging_test.cc @@ -97,6 +97,31 @@ TEST(LogPerfTest, PerfTest) { RayLog::ShutDownRayLog(); } +std::string TestFunctionLevel0() { + std::string call_trace = GetCallTrace(); + RAY_LOG(INFO) << "TestFunctionLevel0\n" << call_trace; + return call_trace; +} + +std::string TestFunctionLevel1() { + RAY_LOG(INFO) << "TestFunctionLevel1:"; + return TestFunctionLevel0(); +} + +std::string TestFunctionLevel2() { + RAY_LOG(INFO) << "TestFunctionLevel2:"; + return TestFunctionLevel1(); +} + +TEST(PrintLogTest, CallstackTraceTest) { + auto ret0 = TestFunctionLevel0(); + EXPECT_TRUE(ret0.find("TestFunctionLevel0") != std::string::npos); + auto ret1 = TestFunctionLevel1(); + EXPECT_TRUE(ret1.find("TestFunctionLevel1") != std::string::npos); + auto ret2 = TestFunctionLevel2(); + EXPECT_TRUE(ret2.find("TestFunctionLevel2") != std::string::npos); +} + } // namespace ray int main(int argc, char **argv) { diff --git a/thirdparty/patches/glog-dump-stacktrack.patch b/thirdparty/patches/glog-dump-stacktrack.patch new file mode 100644 index 0000000000000..d9a942343602f --- /dev/null +++ b/thirdparty/patches/glog-dump-stacktrack.patch @@ -0,0 +1,74 @@ +diff --git src/glog/logging.h.in src/glog/logging.h.in +index 64bed1a..0ff073f 100644 +--- src/glog/logging.h.in ++++ src/glog/logging.h.in +@@ -1676,6 +1676,9 @@ class GOOGLE_GLOG_DLL_DECL NullStreamFatal : public NullStream { + // words, stack traces of other threads won't be shown. + GOOGLE_GLOG_DLL_DECL void InstallFailureSignalHandler(); + ++// Providing stack trace function for upper level. ++GOOGLE_GLOG_DLL_DECL std::string GetStackTraceToString(); ++ + // Installs a function that is used for writing the failure dump. "data" + // is the pointer to the beginning of a message to be written, and "size" + // is the size of the message. You should not expect the data is +diff --git src/logging.cc src/logging.cc +index 733ce8c..e988eb9 100644 +--- src/logging.cc ++++ src/logging.cc +@@ -2336,4 +2336,13 @@ void DisableLogCleaner() { + log_cleaner_enabled_ = false; + } + ++std::string GetStackTraceToString() { ++ // Collect stacktrace from utilities. ++ std::string stacktrace; ++ // The second parameter stands for skip count. The top stack frames will be ++ // skipped to dump from stack if it's non-zero. ++ DumpStackTraceToString(&stacktrace, 0); ++ return stacktrace; ++} ++ + _END_GOOGLE_NAMESPACE_ +diff --git src/utilities.cc src/utilities.cc +index 9a1e35d..3808162 100644 +--- src/utilities.cc ++++ src/utilities.cc +@@ -318,8 +318,8 @@ static void MyUserNameInitializer() { + REGISTER_MODULE_INITIALIZER(utilities, MyUserNameInitializer()); + + #ifdef HAVE_STACKTRACE +-void DumpStackTraceToString(string* stacktrace) { +- DumpStackTrace(1, DebugWriteToString, stacktrace); ++void DumpStackTraceToString(string* stacktrace, int depth) { ++ DumpStackTrace(depth, DebugWriteToString, stacktrace); + } + #endif + +diff --git src/utilities.h src/utilities.h +index c66f914..39c48e8 100644 +--- src/utilities.h ++++ src/utilities.h +@@ -209,7 +209,7 @@ inline T sync_val_compare_and_swap(T* ptr, T oldval, T newval) { + #endif + } + +-void DumpStackTraceToString(std::string* stacktrace); ++void DumpStackTraceToString(std::string* stacktrace, int depth = 1); + + struct CrashReason { + CrashReason() : filename(0), line_number(0), message(0), depth(0) {} +diff --git src/windows/glog/logging.h src/windows/glog/logging.h +index 2a739f9..4ff2a79 100755 +--- src/windows/glog/logging.h ++++ src/windows/glog/logging.h +@@ -1677,6 +1677,9 @@ class GOOGLE_GLOG_DLL_DECL NullStreamFatal : public NullStream { + // words, stack traces of other threads won't be shown. + GOOGLE_GLOG_DLL_DECL void InstallFailureSignalHandler(); + ++// Providing stack trace function for upper level. ++GOOGLE_GLOG_DLL_DECL std::string GetStackTraceToString(); ++ + // Installs a function that is used for writing the failure dump. "data" + // is the pointer to the beginning of a message to be written, and "size" + // is the size of the message. You should not expect the data is