#include "base/include/debug/lynx_error.h"
#include "base/include/compiler_specific.h"
#include "base/include/log/logging.h"
#include "base/include/string/string_utils.h"
#if !defined(OS_WIN)
#include "base/include/debug/backtrace.h"
#endif
#include <cstdarg>
namespace lynx {
namespace base {
static constexpr const char* kLynxErrorKeyPrefixContext = "lynx_context_";
static constexpr const char* kLynxErrorKeyErrorStack = "error_stack";
namespace {
std::string AddBackTrace(std::string& error_message) {
#if OS_IOS
return lynx::base::debug::GetBacktraceInfo(error_message);
#else
return error_message;
#endif
}
}
bool StoreError(int32_t error_code, std::string error_msg,
std::string fix_suggestion, LynxErrorLevel level) {
LynxError error{error_code, std::move(error_msg), std::move(fix_suggestion),
level};
return ErrorStorage::GetInstance().SetError(std::move(error));
}
bool StoreErrorIfNot(bool expression, int32_t error_code, std::string error_msg,
std::string fix_suggestion, base::LynxErrorLevel level) {
if (!expression) {
LynxError error{error_code, std::move(error_msg), std::move(fix_suggestion),
level};
return ErrorStorage::GetInstance().SetError(std::move(error));
}
return false;
}
LynxError::LynxError(int error_code, const char* format, ...)
: error_code_(error_code), is_logbox_only_(false) {
va_list args;
va_start(args, format);
error_message_ = FormatStringWithVaList(format, args);
va_end(args);
error_message_ = AddBackTrace(error_message_);
error_level_ = LynxErrorLevel::Error;
LOGI("LynxError occurs error_code:" << error_code
<< " error_message:" << error_message_);
}
LynxError::LynxError(int error_code, std::string error_msg,
std::string fix_suggestion, LynxErrorLevel level,
bool is_logbox_only)
: error_level_(level),
error_code_(error_code),
error_message_(std::move(error_msg)),
fix_suggestion_(std::move(fix_suggestion)),
is_logbox_only_(is_logbox_only) {
LOGI("LynxError occurs error_code:" << error_code_
<< " error_message:" << error_message_);
}
void LynxError::AddCallStack(const std::string& stack) {
custom_info_[kLynxErrorKeyErrorStack] = stack;
}
void LynxError::AddContextInfo(const std::string& key,
const std::string& value) {
std::string context_key(kLynxErrorKeyPrefixContext);
context_key.append(key);
custom_info_[context_key] = value;
}
std::string LynxError::GetLevelString(int32_t level) {
LynxErrorLevel l_enum = LynxErrorLevel::Error;
if (level >= static_cast<int32_t>(LynxErrorLevel::Fatal) &&
level <= static_cast<int32_t>(LynxErrorLevel::Warn)) {
l_enum = static_cast<LynxErrorLevel>(level);
}
switch (l_enum) {
case LynxErrorLevel::Fatal:
return "fatal";
case LynxErrorLevel::Warn:
return "warn";
case LynxErrorLevel::Error:
default:
return "error";
}
}
ErrorStorage& ErrorStorage::GetInstance() {
#if defined(OS_IOS) && defined(__i386__)
static ThreadLocal<ErrorStorage> instance([] { return new ErrorStorage; });
#else
static thread_local ErrorStorage instance;
#endif
return instance;
}
void ErrorStorage::AddCustomInfoToError(
const std::unordered_map<std::string, std::string>& custom_info) {
if (!error_) {
return;
}
for (const auto& [key, value] : custom_info) {
error_->custom_info_[key] = value;
}
}
void ErrorStorage::AddCustomInfoToError(const std::string& key,
const std::string& value) {
if (error_) {
error_->custom_info_[key] = value;
}
}
}
}