diff options
| author | Dan Engelbrecht <[email protected]> | 2024-08-14 09:23:19 +0200 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2024-08-14 09:23:19 +0200 |
| commit | 501d5e3b0be37ebceda96240af1e4d8df927d68f (patch) | |
| tree | 1279228466433e992ec1dd2635c317d1ce78dcc3 /src | |
| parent | don't try to memcache the empty buffer if invalid format (#110) (diff) | |
| download | zen-501d5e3b0be37ebceda96240af1e4d8df927d68f.tar.xz zen-501d5e3b0be37ebceda96240af1e4d8df927d68f.zip | |
improve logging on main failure (#111)
* add support for indenting callstack output
* Explicitly catch option-parse error and reduce log spam on bad parameters
* add command line to sentry error reports
* log command line at startup
Diffstat (limited to 'src')
| -rw-r--r-- | src/zencore/callstack.cpp | 10 | ||||
| -rw-r--r-- | src/zencore/include/zencore/callstack.h | 4 | ||||
| -rw-r--r-- | src/zencore/zencore.cpp | 4 | ||||
| -rw-r--r-- | src/zenserver/config.cpp | 2 | ||||
| -rw-r--r-- | src/zenserver/config.h | 1 | ||||
| -rw-r--r-- | src/zenserver/main.cpp | 12 | ||||
| -rw-r--r-- | src/zenserver/sentryintegration.cpp | 36 | ||||
| -rw-r--r-- | src/zenserver/sentryintegration.h | 4 |
8 files changed, 39 insertions, 34 deletions
diff --git a/src/zencore/callstack.cpp b/src/zencore/callstack.cpp index 905ab3d9e..d16605fb9 100644 --- a/src/zencore/callstack.cpp +++ b/src/zencore/callstack.cpp @@ -172,7 +172,7 @@ GetFrameSymbols(uint32_t FrameCount, void** Frames) } void -FormatCallstack(const CallstackFrames* Callstack, StringBuilderBase& SB) +FormatCallstack(const CallstackFrames* Callstack, StringBuilderBase& SB, std::string_view Prefix) { bool First = true; for (const std::string& Symbol : GetFrameSymbols(Callstack)) @@ -185,15 +185,19 @@ FormatCallstack(const CallstackFrames* Callstack, StringBuilderBase& SB) { First = false; } + if (!Prefix.empty()) + { + SB.Append(Prefix); + } SB.Append(Symbol); } } std::string -CallstackToString(const CallstackFrames* Callstack) +CallstackToString(const CallstackFrames* Callstack, std::string_view Prefix) { StringBuilder<2048> SB; - FormatCallstack(Callstack, SB); + FormatCallstack(Callstack, SB, Prefix); return SB.ToString(); } diff --git a/src/zencore/include/zencore/callstack.h b/src/zencore/include/zencore/callstack.h index 02ba8b3c3..ef4ba0e91 100644 --- a/src/zencore/include/zencore/callstack.h +++ b/src/zencore/include/zencore/callstack.h @@ -29,8 +29,8 @@ GetFrameSymbols(const CallstackFrames* Callstack) return GetFrameSymbols(Callstack ? Callstack->FrameCount : 0, Callstack ? Callstack->Frames : nullptr); } -void FormatCallstack(const CallstackFrames* Callstack, StringBuilderBase& SB); -std::string CallstackToString(const CallstackFrames* Callstack); +void FormatCallstack(const CallstackFrames* Callstack, StringBuilderBase& SB, std::string_view Prefix); +std::string CallstackToString(const CallstackFrames* Callstack, std::string_view Prefix = {}); void callstack_forcelink(); // internal diff --git a/src/zencore/zencore.cpp b/src/zencore/zencore.cpp index 9c48b355b..6a963110b 100644 --- a/src/zencore/zencore.cpp +++ b/src/zencore/zencore.cpp @@ -82,7 +82,7 @@ AssertException::FullDescription() const noexcept { if (_Callstack) { - return fmt::format("'{}'\n{}", what(), CallstackToString(_Callstack)); + return fmt::format("'{}'\n{}", what(), CallstackToString(_Callstack, " ")); } return what(); } @@ -131,7 +131,7 @@ AssertImpl::OnAssert(const char* Filename, int LineNumber, const char* FunctionN fmt::basic_memory_buffer<char, 2048> Message; auto Appender = fmt::appender(Message); - fmt::format_to(Appender, "{}({}): ZEN_ASSERT({})\n{}", Filename, LineNumber, Msg, CallstackToString(Callstack)); + fmt::format_to(Appender, "{}({}): ZEN_ASSERT({})\n{}", Filename, LineNumber, Msg, CallstackToString(Callstack, " ")); Message.push_back('\0'); // We use direct ZEN_LOG here instead of ZEN_ERROR as we don't care about *this* code location in the log diff --git a/src/zenserver/config.cpp b/src/zenserver/config.cpp index 55c90cbe1..867089ded 100644 --- a/src/zenserver/config.cpp +++ b/src/zenserver/config.cpp @@ -565,6 +565,8 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) } #endif + ServerOptions.CommandLine = fmt::format("{}", fmt::join(std::span<const char*>((const char**)argv, size_t(argc)), " ")); + // Note to those adding future options; std::filesystem::path-type options // must be read into a std::string first. As of cxxopts-3.0.0 it uses a >> // stream operator to convert argv value into the options type. std::fs::path diff --git a/src/zenserver/config.h b/src/zenserver/config.h index 41e05c7ea..46fdd6fdf 100644 --- a/src/zenserver/config.h +++ b/src/zenserver/config.h @@ -165,6 +165,7 @@ struct ZenServerOptions std::string TraceHost; // Host name or IP address to send trace data to std::string TraceFile; // Path of a file to write a trace #endif + std::string CommandLine; }; void ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions); diff --git a/src/zenserver/main.cpp b/src/zenserver/main.cpp index 023abc8a3..c27d4eb04 100644 --- a/src/zenserver/main.cpp +++ b/src/zenserver/main.cpp @@ -5,6 +5,7 @@ #include <zencore/compactbinarybuilder.h> #include <zencore/compactbinaryvalidation.h> #include <zencore/config.h> +#include <zencore/except.h> #include <zencore/filesystem.h> #include <zencore/fmtutils.h> #include <zencore/logging.h> @@ -92,10 +93,9 @@ ZenEntryPoint::Run() std::string SentryDatabasePath = (m_ServerOptions.DataDir / ".sentry-native").string(); std::string SentryAttachmentPath = m_ServerOptions.AbsLogFile.string(); - Sentry.Initialize(SentryDatabasePath, SentryAttachmentPath, m_ServerOptions.SentryAllowPII); + Sentry.Initialize(SentryDatabasePath, SentryAttachmentPath, m_ServerOptions.SentryAllowPII, m_ServerOptions.CommandLine); } #endif - try { // Mutual exclusion and synchronization @@ -179,6 +179,8 @@ ZenEntryPoint::Run() InitializeServerLogging(m_ServerOptions); + ZEN_INFO("Command line: {}", m_ServerOptions.CommandLine); + #if ZEN_USE_SENTRY Sentry.LogStartupInformation(); #endif @@ -437,6 +439,12 @@ main(int argc, char* argv[]) return App.Run(); #endif } + catch (const OptionParseException& ParseEx) + { + // The parsing error already outputs all the details so no need to output the command line here + fprintf(stderr, "ERROR: %s\n", ParseEx.what()); + return 1; + } catch (const AssertException& AssertEx) { fprintf(stderr, "ERROR: Caught assert exception in main: '%s'", AssertEx.FullDescription().c_str()); diff --git a/src/zenserver/sentryintegration.cpp b/src/zenserver/sentryintegration.cpp index 2f68a269b..5d2b851d1 100644 --- a/src/zenserver/sentryintegration.cpp +++ b/src/zenserver/sentryintegration.cpp @@ -190,7 +190,10 @@ SentryIntegration::~SentryIntegration() } void -SentryIntegration::Initialize(std::string SentryDatabasePath, std::string SentryAttachmentPath, bool AllowPII) +SentryIntegration::Initialize(std::string SentryDatabasePath, + std::string SentryAttachmentsPath, + bool AllowPII, + const std::string& CommandLine) { m_AllowPII = AllowPII; @@ -202,11 +205,11 @@ SentryIntegration::Initialize(std::string SentryDatabasePath, std::string Sentry sentry_options_set_dsn(SentryOptions, "https://[email protected]/5919284"); sentry_options_set_database_path(SentryOptions, SentryDatabasePath.c_str()); sentry_options_set_logger(SentryOptions, SentryLogFunction, this); - if (SentryAttachmentPath.starts_with("\\\\?\\")) + if (SentryAttachmentsPath.starts_with("\\\\?\\")) { - SentryAttachmentPath = SentryAttachmentPath.substr(4); + SentryAttachmentsPath = SentryAttachmentsPath.substr(4); } - sentry_options_add_attachment(SentryOptions, SentryAttachmentPath.c_str()); + sentry_options_add_attachment(SentryOptions, SentryAttachmentsPath.c_str()); sentry_options_set_release(SentryOptions, ZEN_CFG_VERSION); // sentry_options_set_debug(SentryOptions, 1); @@ -215,6 +218,8 @@ SentryIntegration::Initialize(std::string SentryDatabasePath, std::string Sentry if (m_SentryErrorCode == 0) { + sentry_value_t SentryUserObject = sentry_value_new_object(); + if (m_AllowPII) { # if ZEN_PLATFORM_WINDOWS @@ -259,14 +264,15 @@ SentryIntegration::Initialize(std::string SentryDatabasePath, std::string Sentry m_SentryHostName = "unknown"; } # endif - m_SentryId = fmt::format("{}@{}", m_SentryUserName, m_SentryHostName); - sentry_value_t SentryUserObject = sentry_value_new_object(); + m_SentryId = fmt::format("{}@{}", m_SentryUserName, m_SentryHostName); sentry_value_set_by_key(SentryUserObject, "id", sentry_value_new_string(m_SentryId.c_str())); sentry_value_set_by_key(SentryUserObject, "username", sentry_value_new_string(m_SentryUserName.c_str())); sentry_value_set_by_key(SentryUserObject, "ip_address", sentry_value_new_string("{{auto}}")); - sentry_set_user(SentryUserObject); } + sentry_value_set_by_key(SentryUserObject, "cmd", sentry_value_new_string(CommandLine.c_str())); + sentry_set_user(SentryUserObject); + m_SentryLogger = spdlog::create<sentry::sentry_sink>("sentry"); logging::SetErrorLog("sentry"); @@ -279,22 +285,6 @@ SentryIntegration::Initialize(std::string SentryDatabasePath, std::string Sentry void SentryIntegration::LogStartupInformation() { -# if (ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC) - uid_t uid = geteuid(); - struct passwd* pw = getpwuid(uid); - if (pw) - { - m_SentryUserName = std::string(pw->pw_name); - } - ZEN_INFO("Username: '{}'", m_SentryUserName); - - char HostNameBuffer[1023 + 1]; - int err = gethostname(HostNameBuffer, sizeof(HostNameBuffer)); - if (err == 0) - { - ZEN_INFO("Hostname: '{}'", HostNameBuffer); - } -# endif if (m_IsInitialized) { if (m_SentryErrorCode == 0) diff --git a/src/zenserver/sentryintegration.h b/src/zenserver/sentryintegration.h index dd8b87ab7..29f526714 100644 --- a/src/zenserver/sentryintegration.h +++ b/src/zenserver/sentryintegration.h @@ -36,8 +36,8 @@ public: SentryIntegration(); ~SentryIntegration(); - void Initialize(std::string SentryDatabasePath, std::string SentryAttachmentsPath, bool AllowPII); - void LogStartupInformation(); + void Initialize(std::string SentryDatabasePath, std::string SentryAttachmentsPath, bool AllowPII, const std::string& CommandLine); + void LogStartupInformation(); static void ClearCaches(); private: |