feat/update_config #10
@ -2128,8 +2128,8 @@ nsel_DISABLE_MSVC_WARNINGS(26409)
|
||||
: make_unexpected(detail::invoke(std::forward<F>(f), std::move(error())));
|
||||
}
|
||||
#endif
|
||||
#endif// nsel_P2505R >= 3
|
||||
// unwrap()
|
||||
#endif// nsel_P2505R >= 3 \
|
||||
// unwrap()
|
||||
|
||||
// template <class U, class E>
|
||||
// constexpr expected<U,E> expected<expected<U,E>,E>::unwrap() const&;
|
||||
|
@ -174,9 +174,8 @@ private:
|
||||
{"1s", 1}
|
||||
};
|
||||
for (auto &&item : m) {}
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void LinkToParent(Slice rel_path, ExposedVarGroup *parent)
|
||||
{
|
||||
|
@ -16,7 +16,7 @@ GetProviers()
|
||||
static std::vector<PrefixAppender *> providers;
|
||||
return &providers;
|
||||
}
|
||||
} // namespace
|
||||
}// namespace
|
||||
|
||||
namespace details {
|
||||
std::string
|
||||
@ -24,10 +24,12 @@ DescribeFormatArguments(const std::vector<std::string> &args)
|
||||
{
|
||||
return fmt::format("{}", fmt::join(args.begin(), args.end(), ", "));
|
||||
}
|
||||
} // namespace details
|
||||
}// namespace details
|
||||
|
||||
void InstallPrefixProvider(PrefixAppender *writer) {
|
||||
GetProviers()->push_back(writer);
|
||||
void
|
||||
InstallPrefixProvider(PrefixAppender *writer)
|
||||
{
|
||||
GetProviers()->push_back(writer);
|
||||
}
|
||||
|
||||
void
|
||||
@ -39,9 +41,9 @@ WritePrefixTo(std::string *to)
|
||||
if (to->size() != was) { to->push_back(' '); }
|
||||
}
|
||||
}
|
||||
} // namespace logging
|
||||
} // namespace internal
|
||||
} // namespace tile
|
||||
}// namespace logging
|
||||
}// namespace internal
|
||||
}// namespace tile
|
||||
|
||||
namespace tile {
|
||||
static std::mutex g_sink_mutex;
|
||||
@ -53,226 +55,273 @@ std::mutex g_log_mutex;
|
||||
|
||||
class OStreamWrapper : public std::streambuf {
|
||||
public:
|
||||
OStreamWrapper(std::ostream &ostream) : ostream_(ostream) {}
|
||||
OStreamWrapper(std::ostream &ostream) : ostream_(ostream) {}
|
||||
|
||||
int_type overflow(int_type c) override { return c; }
|
||||
int_type overflow(int_type c) override { return c; }
|
||||
|
||||
private:
|
||||
std::ostream &ostream_;
|
||||
std::ostream &ostream_;
|
||||
};
|
||||
|
||||
bool VLogIsOn(int n) { return true; }
|
||||
bool
|
||||
VLogIsOn(int n)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
class LogMessage::Impl {
|
||||
public:
|
||||
Impl(const char *file, int line)
|
||||
: stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) {
|
||||
Init(file, line, TILE_INFO, &LogMessage::Impl::SendToLog);
|
||||
}
|
||||
Impl(const char *file, int line, LogSeverity severity)
|
||||
: stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) {
|
||||
Init(file, line, severity, &LogMessage::Impl::SendToLog);
|
||||
}
|
||||
Impl(const char *file, int line, LogSeverity severity, LogSink *sink,
|
||||
bool also_send_to_log)
|
||||
: stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) {
|
||||
Init(file, line, severity,
|
||||
also_send_to_log ? &LogMessage::Impl::SendToSinkAndLog
|
||||
: &LogMessage::Impl::SendToSink);
|
||||
sink_ = sink;
|
||||
}
|
||||
~Impl() { Flush(); }
|
||||
std::ostream &stream() { return stream_; }
|
||||
void Flush() {
|
||||
if (has_been_flushed_) {
|
||||
return;
|
||||
}
|
||||
|
||||
num_chars_to_log_ = stream_.pcount();
|
||||
const bool append_newline = message_text_[num_chars_to_log_ - 1] != '\n';
|
||||
char original_final_char = '\0';
|
||||
|
||||
if (append_newline) {
|
||||
original_final_char = message_text_[num_chars_to_log_];
|
||||
message_text_[num_chars_to_log_++] = '\n';
|
||||
}
|
||||
message_text_[num_chars_to_log_] = '\0';
|
||||
|
||||
Impl(const char *file, int line) : stream_(message_text_, LogMessage::kMaxLogMessageLen, 0)
|
||||
{
|
||||
std::lock_guard<std::mutex> _{g_log_mutex};
|
||||
(this->*(send_method_))();
|
||||
++g_num_messages[severity_];
|
||||
WaitForSinks();
|
||||
if (sink_) {
|
||||
sink_->Flush();
|
||||
}
|
||||
Init(file, line, TILE_INFO, &LogMessage::Impl::SendToLog);
|
||||
}
|
||||
|
||||
if (append_newline) {
|
||||
message_text_[num_chars_to_log_ - 1] = original_final_char;
|
||||
Impl(const char *file, int line, LogSeverity severity) : stream_(message_text_, LogMessage::kMaxLogMessageLen, 0)
|
||||
{
|
||||
Init(file, line, severity, &LogMessage::Impl::SendToLog);
|
||||
}
|
||||
|
||||
if (preserved_errno_ != 0) {
|
||||
errno = preserved_errno_;
|
||||
Impl(const char *file, int line, LogSeverity severity, LogSink *sink, bool also_send_to_log)
|
||||
: stream_(message_text_, LogMessage::kMaxLogMessageLen, 0)
|
||||
{
|
||||
Init(file, line, severity,
|
||||
also_send_to_log ? &LogMessage::Impl::SendToSinkAndLog : &LogMessage::Impl::SendToSink);
|
||||
sink_ = sink;
|
||||
}
|
||||
has_been_flushed_ = true;
|
||||
|
||||
if (severity_ == TILE_FATAL) {
|
||||
assert(false);
|
||||
~Impl() { Flush(); }
|
||||
|
||||
std::ostream &stream() { return stream_; }
|
||||
|
||||
void Flush()
|
||||
{
|
||||
if (has_been_flushed_) { return; }
|
||||
|
||||
num_chars_to_log_ = stream_.pcount();
|
||||
const bool append_newline = message_text_[num_chars_to_log_ - 1] != '\n';
|
||||
char original_final_char = '\0';
|
||||
|
||||
if (append_newline) {
|
||||
original_final_char = message_text_[num_chars_to_log_];
|
||||
message_text_[num_chars_to_log_++] = '\n';
|
||||
}
|
||||
message_text_[num_chars_to_log_] = '\0';
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> _{g_log_mutex};
|
||||
(this->*(send_method_))();
|
||||
++g_num_messages[severity_];
|
||||
WaitForSinks();
|
||||
if (sink_) { sink_->Flush(); }
|
||||
}
|
||||
|
||||
if (append_newline) { message_text_[num_chars_to_log_ - 1] = original_final_char; }
|
||||
|
||||
if (preserved_errno_ != 0) { errno = preserved_errno_; }
|
||||
has_been_flushed_ = true;
|
||||
|
||||
if (severity_ == TILE_FATAL) { assert(false); }
|
||||
}
|
||||
}
|
||||
|
||||
LogSeverity severity() const noexcept { return severity_; }
|
||||
int line() const noexcept { return line_; }
|
||||
const char *fullname() const noexcept { return file_; }
|
||||
const char *basename() const noexcept { return file_; }
|
||||
const LogMessageTime &time() const noexcept { return time_; }
|
||||
int preserved_errno() const { return preserved_errno_; }
|
||||
LogSeverity severity() const noexcept { return severity_; }
|
||||
|
||||
int line() const noexcept { return line_; }
|
||||
|
||||
const char *fullname() const noexcept { return file_; }
|
||||
|
||||
const char *basename() const noexcept { return file_; }
|
||||
|
||||
const LogMessageTime &time() const noexcept { return time_; }
|
||||
|
||||
int preserved_errno() const { return preserved_errno_; }
|
||||
|
||||
private:
|
||||
void Init(const char *file, int line, LogSeverity severity,
|
||||
void (LogMessage::Impl::*send_method)()) {
|
||||
has_been_flushed_ = false;
|
||||
file_ = file;
|
||||
line_ = line;
|
||||
severity_ = severity;
|
||||
send_method_ = send_method;
|
||||
sink_ = nullptr;
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
time_ = LogMessageTime(now);
|
||||
thread_id_ = std::this_thread::get_id();
|
||||
preserved_errno_ = errno;
|
||||
}
|
||||
void Init(const char *file, int line, LogSeverity severity, void (LogMessage::Impl::*send_method)())
|
||||
{
|
||||
has_been_flushed_ = false;
|
||||
file_ = file;
|
||||
line_ = line;
|
||||
severity_ = severity;
|
||||
send_method_ = send_method;
|
||||
sink_ = nullptr;
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
time_ = LogMessageTime(now);
|
||||
thread_id_ = std::this_thread::get_id();
|
||||
preserved_errno_ = errno;
|
||||
}
|
||||
|
||||
void SendToSink() {
|
||||
if (sink_) {
|
||||
sink_->Send(severity_, fullname(), basename(), line(), time(),
|
||||
message_text_ + num_prefix_chars_,
|
||||
num_chars_to_log_ - num_prefix_chars_);
|
||||
void SendToSink()
|
||||
{
|
||||
if (sink_) {
|
||||
sink_->Send(severity_, fullname(), basename(), line(), time(), message_text_ + num_prefix_chars_,
|
||||
num_chars_to_log_ - num_prefix_chars_ - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
void SendToLog() {
|
||||
if (g_sink_count.load(std::memory_order_relaxed) == 0) {
|
||||
ColoredWriteToStdout(severity_, message_text_ + num_prefix_chars_,
|
||||
num_chars_to_log_ - num_chars_to_log_);
|
||||
|
||||
void SendToLog()
|
||||
{
|
||||
if (g_sink_count.load(std::memory_order_relaxed) == 0) {
|
||||
ColoredWriteToStdout(severity_, message_text_ + num_prefix_chars_, num_chars_to_log_ - num_chars_to_log_);
|
||||
}
|
||||
LogToSinks(severity_, fullname(), basename(), line(), time(), message_text_ + num_prefix_chars_,
|
||||
num_chars_to_log_ - num_prefix_chars_ - 1);
|
||||
}
|
||||
|
||||
void SendToSinkAndLog()
|
||||
{
|
||||
SendToSink();
|
||||
SendToLog();
|
||||
}
|
||||
LogToSinks(severity_, fullname(), basename(), line(), time(),
|
||||
message_text_ + num_prefix_chars_,
|
||||
num_chars_to_log_ - num_prefix_chars_);
|
||||
}
|
||||
void SendToSinkAndLog() {
|
||||
SendToSink();
|
||||
SendToLog();
|
||||
}
|
||||
|
||||
private:
|
||||
char message_text_[LogMessage::kMaxLogMessageLen + 1];
|
||||
LogMessage::LogStream stream_;
|
||||
char message_text_[LogMessage::kMaxLogMessageLen + 1];
|
||||
LogMessage::LogStream stream_;
|
||||
|
||||
bool has_been_flushed_;
|
||||
bool has_been_flushed_;
|
||||
|
||||
const char *file_;
|
||||
int line_;
|
||||
LogSeverity severity_;
|
||||
void (LogMessage::Impl::*send_method_)();
|
||||
const char *file_;
|
||||
int line_;
|
||||
LogSeverity severity_;
|
||||
void (LogMessage::Impl::*send_method_)();
|
||||
|
||||
LogSink *sink_;
|
||||
LogMessageTime time_;
|
||||
std::thread::id thread_id_;
|
||||
int preserved_errno_;
|
||||
LogSink *sink_;
|
||||
LogMessageTime time_;
|
||||
std::thread::id thread_id_;
|
||||
int preserved_errno_;
|
||||
|
||||
size_t num_prefix_chars_;
|
||||
size_t num_chars_to_log_;
|
||||
size_t num_prefix_chars_;
|
||||
size_t num_chars_to_log_;
|
||||
};
|
||||
|
||||
LogMessage::LogMessage(const char *file, int line)
|
||||
: impl_(new Impl(file, line)) {}
|
||||
LogMessage::LogMessage(const char *file, int line, LogSeverity severity)
|
||||
: impl_(new Impl(file, line, severity)) {}
|
||||
LogMessage::LogMessage(const char *file, int line, LogSeverity severity,
|
||||
LogSink *sink, bool also_send_to_log)
|
||||
: impl_(new Impl(file, line, severity, sink, also_send_to_log)) {}
|
||||
LogMessage::LogMessage(const char *file, int line) : impl_(new Impl(file, line)) {}
|
||||
|
||||
LogMessage::LogMessage(const char *file, int line, LogSeverity severity) : impl_(new Impl(file, line, severity)) {}
|
||||
|
||||
LogMessage::LogMessage(const char *file, int line, LogSeverity severity, LogSink *sink, bool also_send_to_log)
|
||||
: impl_(new Impl(file, line, severity, sink, also_send_to_log))
|
||||
{}
|
||||
|
||||
LogMessage::~LogMessage() {}
|
||||
|
||||
std::ostream &LogMessage::stream() { return impl_->stream(); }
|
||||
void LogMessage::Flush() { impl_->Flush(); }
|
||||
|
||||
LogSeverity LogMessage::severity() const noexcept { return impl_->severity(); }
|
||||
int LogMessage::line() const noexcept { return impl_->line(); }
|
||||
const char *LogMessage::fullname() const noexcept { return impl_->fullname(); }
|
||||
const char *LogMessage::basename() const noexcept { return impl_->basename(); }
|
||||
const LogMessageTime &LogMessage::time() const noexcept {
|
||||
return impl_->time();
|
||||
std::ostream &
|
||||
LogMessage::stream()
|
||||
{
|
||||
return impl_->stream();
|
||||
}
|
||||
int LogMessage::preserved_errno() const { return impl_->preserved_errno(); }
|
||||
|
||||
LogMessageFatal::LogMessageFatal(const char *file, int line)
|
||||
: LogMessage(file, line, TILE_FATAL) {}
|
||||
void
|
||||
LogMessage::Flush()
|
||||
{
|
||||
impl_->Flush();
|
||||
}
|
||||
|
||||
LogSeverity
|
||||
LogMessage::severity() const noexcept
|
||||
{
|
||||
return impl_->severity();
|
||||
}
|
||||
|
||||
int
|
||||
LogMessage::line() const noexcept
|
||||
{
|
||||
return impl_->line();
|
||||
}
|
||||
|
||||
const char *
|
||||
LogMessage::fullname() const noexcept
|
||||
{
|
||||
return impl_->fullname();
|
||||
}
|
||||
|
||||
const char *
|
||||
LogMessage::basename() const noexcept
|
||||
{
|
||||
return impl_->basename();
|
||||
}
|
||||
|
||||
const LogMessageTime &
|
||||
LogMessage::time() const noexcept
|
||||
{
|
||||
return impl_->time();
|
||||
}
|
||||
|
||||
int
|
||||
LogMessage::preserved_errno() const
|
||||
{
|
||||
return impl_->preserved_errno();
|
||||
}
|
||||
|
||||
LogMessageFatal::LogMessageFatal(const char *file, int line) : LogMessage(file, line, TILE_FATAL) {}
|
||||
|
||||
LogMessageFatal::~LogMessageFatal() {}
|
||||
|
||||
std::ostream &LogMessageFatal::stream() { return LogMessage::stream(); }
|
||||
std::ostream &
|
||||
LogMessageFatal::stream()
|
||||
{
|
||||
return LogMessage::stream();
|
||||
}
|
||||
|
||||
LogMessageTime::LogMessageTime() : time_struct_(), timestamp_(0), usecs_(0), gmtoffset_(0) {}
|
||||
|
||||
LogMessageTime::LogMessageTime(std::tm t) : use_localtime_(true) {
|
||||
std::time_t timestamp = std::mktime(&t);
|
||||
init(t, timestamp, 0);
|
||||
LogMessageTime::LogMessageTime(std::tm t) : use_localtime_(true)
|
||||
{
|
||||
std::time_t timestamp = std::mktime(&t);
|
||||
init(t, timestamp, 0);
|
||||
}
|
||||
|
||||
LogMessageTime::LogMessageTime(std::time_t timestamp, WallTime now)
|
||||
: use_localtime_(false) {
|
||||
std::tm t;
|
||||
if (use_localtime_) {
|
||||
localtime_r(×tamp, &t);
|
||||
} else {
|
||||
gmtime_r(×tamp, &t);
|
||||
}
|
||||
LogMessageTime::LogMessageTime(std::time_t timestamp, WallTime now) : use_localtime_(false)
|
||||
{
|
||||
std::tm t;
|
||||
if (use_localtime_) {
|
||||
localtime_r(×tamp, &t);
|
||||
} else {
|
||||
gmtime_r(×tamp, &t);
|
||||
}
|
||||
|
||||
init(t, timestamp, now);
|
||||
}
|
||||
LogMessageTime::LogMessageTime(std::chrono::system_clock::time_point tp)
|
||||
: use_localtime_(false) {
|
||||
std::time_t timestamp = std::chrono::system_clock::to_time_t(tp);
|
||||
std::tm t;
|
||||
if (use_localtime_) {
|
||||
localtime_r(×tamp, &t);
|
||||
} else {
|
||||
gmtime_r(×tamp, &t);
|
||||
}
|
||||
|
||||
init(t, timestamp, 0);
|
||||
usecs_ = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
tp.time_since_epoch())
|
||||
.count() %
|
||||
1000000;
|
||||
init(t, timestamp, now);
|
||||
}
|
||||
|
||||
void LogMessageTime::init(const std::tm &t, std::time_t timestamp,
|
||||
WallTime now) {
|
||||
time_struct_ = t;
|
||||
timestamp_ = timestamp;
|
||||
if (now < timestamp) {
|
||||
usecs_ = 0;
|
||||
} else {
|
||||
usecs_ = static_cast<std::int32_t>((now - timestamp) * 1000000) % 1000000;
|
||||
}
|
||||
LogMessageTime::LogMessageTime(std::chrono::system_clock::time_point tp) : use_localtime_(false)
|
||||
{
|
||||
std::time_t timestamp = std::chrono::system_clock::to_time_t(tp);
|
||||
std::tm t;
|
||||
if (use_localtime_) {
|
||||
localtime_r(×tamp, &t);
|
||||
} else {
|
||||
gmtime_r(×tamp, &t);
|
||||
}
|
||||
|
||||
init(t, timestamp, 0);
|
||||
usecs_ = std::chrono::duration_cast<std::chrono::microseconds>(tp.time_since_epoch()).count() % 1000000;
|
||||
}
|
||||
|
||||
void
|
||||
LogMessageTime::init(const std::tm &t, std::time_t timestamp, WallTime now)
|
||||
{
|
||||
time_struct_ = t;
|
||||
timestamp_ = timestamp;
|
||||
if (now < timestamp) {
|
||||
usecs_ = 0;
|
||||
} else {
|
||||
usecs_ = static_cast<std::int32_t>((now - timestamp) * 1000000) % 1000000;
|
||||
}
|
||||
|
||||
CalcGmtOffset();
|
||||
}
|
||||
|
||||
void LogMessageTime::CalcGmtOffset() {
|
||||
std::tm gmt_struct;
|
||||
int isDst = 0;
|
||||
if (true) {
|
||||
localtime_r(×tamp_, &gmt_struct);
|
||||
isDst = gmt_struct.tm_isdst;
|
||||
gmt_struct = time_struct_;
|
||||
} else {
|
||||
isDst = time_struct_.tm_isdst;
|
||||
gmtime_r(×tamp_, &gmt_struct);
|
||||
}
|
||||
void
|
||||
LogMessageTime::CalcGmtOffset()
|
||||
{
|
||||
std::tm gmt_struct;
|
||||
int isDst = 0;
|
||||
if (true) {
|
||||
localtime_r(×tamp_, &gmt_struct);
|
||||
isDst = gmt_struct.tm_isdst;
|
||||
gmt_struct = time_struct_;
|
||||
} else {
|
||||
isDst = time_struct_.tm_isdst;
|
||||
gmtime_r(×tamp_, &gmt_struct);
|
||||
}
|
||||
|
||||
time_t gmt_sec = mktime(&gmt_struct);
|
||||
const long hour_secs = 3600;
|
||||
@ -282,14 +331,15 @@ void LogMessageTime::CalcGmtOffset() {
|
||||
}
|
||||
|
||||
LogSink::~LogSink() {}
|
||||
bool LogSink::ShouldLog(LogSeverity severity) { return true; }
|
||||
void LogSink::Send(LogSeverity severity, const char *full_filename,
|
||||
const char *base_filename, int line,
|
||||
const LogMessageTime &logmsgtime, const char *message,
|
||||
size_t message_len) {
|
||||
|
||||
bool
|
||||
LogSink::ShouldLog(LogSeverity severity)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
LogSink::send(LogSeverity severity,
|
||||
LogSink::Send(LogSeverity severity,
|
||||
const char *full_filename,
|
||||
const char *base_filename,
|
||||
int line,
|
||||
@ -300,104 +350,130 @@ LogSink::send(LogSeverity severity,
|
||||
|
||||
// do nothing
|
||||
}
|
||||
void LogSink::Flush() {}
|
||||
|
||||
std::string LogSink::ToString(LogSeverity severity, const char *file,
|
||||
const char *base_filename, int line,
|
||||
const LogMessageTime &logmsgtime,
|
||||
const char *message, size_t message_len) {
|
||||
std::stringstream ss;
|
||||
char date_time[64];
|
||||
sprintf(date_time, "%4d-%02d-%02dT%02d:%02d:%02d.%06d",
|
||||
logmsgtime.year() + 1900, logmsgtime.month(), logmsgtime.day(),
|
||||
logmsgtime.hour(), logmsgtime.min(), logmsgtime.sec(),
|
||||
logmsgtime.usec());
|
||||
void
|
||||
LogSink::Flush()
|
||||
{}
|
||||
|
||||
ss << date_time;
|
||||
std::string
|
||||
LogSink::ToString(LogSeverity severity,
|
||||
const char *file,
|
||||
const char *base_filename,
|
||||
int line,
|
||||
const LogMessageTime &logmsgtime,
|
||||
const char *message,
|
||||
size_t message_len)
|
||||
{
|
||||
std::stringstream ss;
|
||||
char date_time[64];
|
||||
sprintf(date_time, "%4d-%02d-%02dT%02d:%02d:%02d.%06d", logmsgtime.year() + 1900, logmsgtime.month(),
|
||||
logmsgtime.day(), logmsgtime.hour(), logmsgtime.min(), logmsgtime.sec(), logmsgtime.usec());
|
||||
|
||||
if (logmsgtime.gmtoff() != 0) {
|
||||
auto hour = logmsgtime.gmtoff() / 3600;
|
||||
auto min = std::abs(logmsgtime.gmtoff() % 3600) / 60;
|
||||
sprintf(date_time, "%+03ld:%02ld", hour, min);
|
||||
ss << date_time;
|
||||
} else if (!logmsgtime.use_localtime()) {
|
||||
ss << "Z";
|
||||
}
|
||||
ss << " " << GetLogSeverityName(severity)[0] << " ";
|
||||
ss << base_filename << ":" << line << " ";
|
||||
|
||||
// return google::LogSink::ToString(severity, file, line, logmsgtime.tm(),
|
||||
// message, message_len);
|
||||
|
||||
ss.write(message, message_len);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static void ColoredWriteToStderrOrStdout(FILE *output, LogSeverity severity,
|
||||
const char *message, size_t len) {
|
||||
fwrite(message, len, 1, output);
|
||||
fflush(output);
|
||||
}
|
||||
|
||||
void ColoredWriteToStdout(LogSeverity severity, const char *message,
|
||||
size_t len) {
|
||||
FILE *output = stdout;
|
||||
if (severity >= TILE_FATAL) {
|
||||
output = stderr;
|
||||
}
|
||||
ColoredWriteToStderrOrStdout(output, severity, message, len);
|
||||
}
|
||||
void ColoredWriteToStderr(LogSeverity severity, const char *message,
|
||||
size_t len) {
|
||||
ColoredWriteToStderrOrStdout(stderr, severity, message, len);
|
||||
}
|
||||
|
||||
void AddLogSink(LogSink::Ptr dest) {
|
||||
std::lock_guard<std::mutex> _(g_sink_mutex);
|
||||
g_sinks.insert(dest);
|
||||
g_sink_count.fetch_add(1);
|
||||
}
|
||||
|
||||
void RemoveLogSink(LogSink::Ptr dest) {
|
||||
std::lock_guard<std::mutex> _(g_sink_mutex);
|
||||
g_sinks.erase(dest);
|
||||
g_sink_count.fetch_sub(1);
|
||||
}
|
||||
|
||||
void SetStderrLogging(LogSeverity min_severity) {}
|
||||
void LogToStderr() {}
|
||||
void LogToSinks(LogSeverity severity, const char *full_filename,
|
||||
const char *base_filename, int line, const LogMessageTime &time,
|
||||
const char *message, size_t message_len) {
|
||||
std::lock_guard<std::mutex> _(g_sink_mutex);
|
||||
for (auto &&sink : g_sinks) {
|
||||
if (sink->ShouldLog(severity)) {
|
||||
sink->Send(severity, full_filename, base_filename, line, time, message,
|
||||
message_len);
|
||||
if (logmsgtime.gmtoff() != 0) {
|
||||
auto hour = logmsgtime.gmtoff() / 3600;
|
||||
auto min = std::abs(logmsgtime.gmtoff() % 3600) / 60;
|
||||
sprintf(date_time, "%+03ld:%02ld", hour, min);
|
||||
ss << date_time;
|
||||
} else if (!logmsgtime.use_localtime()) {
|
||||
ss << "Z";
|
||||
}
|
||||
}
|
||||
}
|
||||
void WaitForSinks() {
|
||||
std::lock_guard<std::mutex> _(g_sink_mutex);
|
||||
for (auto &&sink : g_sinks) {
|
||||
sink->Flush();
|
||||
}
|
||||
ss << " " << GetLogSeverityName(severity)[0] << " ";
|
||||
ss << base_filename << ":" << line << " ";
|
||||
|
||||
// return google::LogSink::ToString(severity, file, line, logmsgtime.tm(),
|
||||
// message, message_len);
|
||||
|
||||
ss.write(message, message_len);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
const char *GetLogSeverityName(LogSeverity severity) {
|
||||
const static std::map<LogSeverity, const char *> severity_names = {
|
||||
{TILE_INFO, "INFO"},
|
||||
{TILE_WARNING, "WARNING"},
|
||||
{TILE_ERROR, "ERROR"},
|
||||
{TILE_FATAL, "FATAL"},
|
||||
};
|
||||
|
||||
auto iter = severity_names.find(severity);
|
||||
if (iter != severity_names.end()) {
|
||||
return iter->second;
|
||||
} else {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
static void
|
||||
ColoredWriteToStderrOrStdout(FILE *output, LogSeverity severity, const char *message, size_t len)
|
||||
{
|
||||
fwrite(message, len, 1, output);
|
||||
fflush(output);
|
||||
}
|
||||
|
||||
} // namespace tile
|
||||
void
|
||||
ColoredWriteToStdout(LogSeverity severity, const char *message, size_t len)
|
||||
{
|
||||
FILE *output = stdout;
|
||||
if (severity >= TILE_FATAL) { output = stderr; }
|
||||
ColoredWriteToStderrOrStdout(output, severity, message, len);
|
||||
}
|
||||
|
||||
void
|
||||
ColoredWriteToStderr(LogSeverity severity, const char *message, size_t len)
|
||||
{
|
||||
ColoredWriteToStderrOrStdout(stderr, severity, message, len);
|
||||
}
|
||||
|
||||
void
|
||||
AddLogSink(LogSink::Ptr dest)
|
||||
{
|
||||
std::lock_guard<std::mutex> _(g_sink_mutex);
|
||||
g_sinks.insert(dest);
|
||||
g_sink_count.fetch_add(1);
|
||||
}
|
||||
|
||||
void
|
||||
RemoveLogSink(LogSink::Ptr dest)
|
||||
{
|
||||
std::lock_guard<std::mutex> _(g_sink_mutex);
|
||||
g_sinks.erase(dest);
|
||||
g_sink_count.fetch_sub(1);
|
||||
}
|
||||
|
||||
void
|
||||
SetStderrLogging(LogSeverity min_severity)
|
||||
{}
|
||||
|
||||
void
|
||||
LogToStderr()
|
||||
{}
|
||||
|
||||
void
|
||||
LogToSinks(LogSeverity severity,
|
||||
const char *full_filename,
|
||||
const char *base_filename,
|
||||
int line,
|
||||
const LogMessageTime &time,
|
||||
const char *message,
|
||||
size_t message_len)
|
||||
{
|
||||
std::lock_guard<std::mutex> _(g_sink_mutex);
|
||||
for (auto &&sink : g_sinks) {
|
||||
if (sink->ShouldLog(severity)) {
|
||||
sink->Send(severity, full_filename, base_filename, line, time, message, message_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WaitForSinks()
|
||||
{
|
||||
std::lock_guard<std::mutex> _(g_sink_mutex);
|
||||
for (auto &&sink : g_sinks) { sink->Flush(); }
|
||||
}
|
||||
|
||||
const char *
|
||||
GetLogSeverityName(LogSeverity severity)
|
||||
{
|
||||
const static std::map<LogSeverity, const char *> severity_names = {
|
||||
{TILE_INFO, "INFO" },
|
||||
{TILE_WARNING, "WARNING"},
|
||||
{TILE_ERROR, "ERROR" },
|
||||
{TILE_FATAL, "FATAL" },
|
||||
};
|
||||
|
||||
auto iter = severity_names.find(severity);
|
||||
if (iter != severity_names.end()) {
|
||||
return iter->second;
|
||||
} else {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
}// namespace tile
|
||||
|
@ -21,84 +21,93 @@ namespace tile {
|
||||
// typedef int LogSeverity;
|
||||
// const int TILE_INFO = 0, TILE_WARNING = 1, TILE_ERROR = 2, TILE_FATAL = 3;
|
||||
enum LogSeverity {
|
||||
TILE_INFO = 0,
|
||||
TILE_WARNING = 1,
|
||||
TILE_ERROR = 2,
|
||||
TILE_FATAL = 3,
|
||||
TILE_MAX_LOG_SEVERITY = TILE_FATAL
|
||||
TILE_INFO = 0,
|
||||
TILE_WARNING = 1,
|
||||
TILE_ERROR = 2,
|
||||
TILE_FATAL = 3,
|
||||
TILE_MAX_LOG_SEVERITY = TILE_FATAL
|
||||
};
|
||||
|
||||
bool VLogIsOn(int n);
|
||||
|
||||
class LogStreamBuf : public std::streambuf {
|
||||
public:
|
||||
LogStreamBuf(char *buf, int len) { setp(buf, buf + len - 2); }
|
||||
LogStreamBuf(char *buf, int len) { setp(buf, buf + len - 2); }
|
||||
|
||||
int_type overflow(int_type ch) { return ch; }
|
||||
size_t pcount() const { return static_cast<size_t>(pptr() - pbase()); }
|
||||
char *pbase() const { return std::streambuf::pbase(); }
|
||||
int_type overflow(int_type ch) { return ch; }
|
||||
|
||||
size_t pcount() const { return static_cast<size_t>(pptr() - pbase()); }
|
||||
|
||||
char *pbase() const { return std::streambuf::pbase(); }
|
||||
};
|
||||
|
||||
class LogSink;
|
||||
class LogMessageTime;
|
||||
|
||||
class LogMessage {
|
||||
public:
|
||||
class LogStream : public std::ostream {
|
||||
public:
|
||||
LogStream(char *buf, int len, int64_t ctr)
|
||||
: std::ostream(nullptr), streambuf_(buf, len), ctr_(ctr), self_(this) {
|
||||
rdbuf(&streambuf_);
|
||||
}
|
||||
class LogStream : public std::ostream {
|
||||
public:
|
||||
LogStream(char *buf, int len, int64_t ctr) : std::ostream(nullptr), streambuf_(buf, len), ctr_(ctr), self_(this)
|
||||
{
|
||||
rdbuf(&streambuf_);
|
||||
}
|
||||
|
||||
LogStream(LogStream &other) noexcept
|
||||
: std::ostream(nullptr), streambuf_(std::move(other.streambuf_)),
|
||||
ctr_(internal::Exchange(other.ctr_, 0)), self_(this) {
|
||||
rdbuf(&streambuf_);
|
||||
}
|
||||
LogStream(LogStream &other) noexcept
|
||||
: std::ostream(nullptr),
|
||||
streambuf_(std::move(other.streambuf_)),
|
||||
ctr_(internal::Exchange(other.ctr_, 0)),
|
||||
self_(this)
|
||||
{
|
||||
rdbuf(&streambuf_);
|
||||
}
|
||||
|
||||
LogStream &operator=(LogStream &&other) noexcept {
|
||||
streambuf_ = std::move(other.streambuf_);
|
||||
ctr_ = internal::Exchange(other.ctr_, 0);
|
||||
self_ = this;
|
||||
rdbuf(&streambuf_);
|
||||
return *this;
|
||||
}
|
||||
LogStream &operator=(LogStream &&other) noexcept
|
||||
{
|
||||
streambuf_ = std::move(other.streambuf_);
|
||||
ctr_ = internal::Exchange(other.ctr_, 0);
|
||||
self_ = this;
|
||||
rdbuf(&streambuf_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
int64_t ctr() const { return ctr_; }
|
||||
void set_ctr(int64_t ctr) { ctr_ = ctr; }
|
||||
int64_t ctr() const { return ctr_; }
|
||||
|
||||
LogStream *self() { return self_; }
|
||||
void set_ctr(int64_t ctr) { ctr_ = ctr; }
|
||||
|
||||
size_t pcount() const { return streambuf_.pcount(); }
|
||||
char *pbase() const { return streambuf_.pbase(); }
|
||||
char *str() const { return pbase(); }
|
||||
LogStream *self() { return self_; }
|
||||
|
||||
LogStream(const LogStream &) = delete;
|
||||
LogStream &operator=(const LogStream &) = delete;
|
||||
size_t pcount() const { return streambuf_.pcount(); }
|
||||
|
||||
private:
|
||||
LogStreamBuf streambuf_;
|
||||
int64_t ctr_;
|
||||
LogStream *self_;
|
||||
};
|
||||
char *pbase() const { return streambuf_.pbase(); }
|
||||
|
||||
char *str() const { return pbase(); }
|
||||
|
||||
LogStream(const LogStream &) = delete;
|
||||
LogStream &operator=(const LogStream &) = delete;
|
||||
|
||||
private:
|
||||
LogStreamBuf streambuf_;
|
||||
int64_t ctr_;
|
||||
LogStream *self_;
|
||||
};
|
||||
|
||||
public:
|
||||
static const size_t kMaxLogMessageLen = 30000;
|
||||
LogMessage(const char *file, int line);
|
||||
LogMessage(const char *file, int line, LogSeverity severity);
|
||||
LogMessage(const char *file, int line, LogSeverity severity, LogSink *sink,
|
||||
bool also_send_to_log = true);
|
||||
static const size_t kMaxLogMessageLen = 30000;
|
||||
LogMessage(const char *file, int line);
|
||||
LogMessage(const char *file, int line, LogSeverity severity);
|
||||
LogMessage(const char *file, int line, LogSeverity severity, LogSink *sink, bool also_send_to_log = true);
|
||||
|
||||
~LogMessage();
|
||||
std::ostream &stream();
|
||||
void Flush();
|
||||
~LogMessage();
|
||||
std::ostream &stream();
|
||||
void Flush();
|
||||
|
||||
LogSeverity severity() const noexcept;
|
||||
int line() const noexcept;
|
||||
const char *fullname() const noexcept;
|
||||
const char *basename() const noexcept;
|
||||
const LogMessageTime &time() const noexcept;
|
||||
int preserved_errno() const;
|
||||
LogSeverity severity() const noexcept;
|
||||
int line() const noexcept;
|
||||
const char *fullname() const noexcept;
|
||||
const char *basename() const noexcept;
|
||||
const LogMessageTime &time() const noexcept;
|
||||
int preserved_errno() const;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
@ -107,9 +116,9 @@ private:
|
||||
|
||||
class LogMessageFatal : public LogMessage {
|
||||
public:
|
||||
LogMessageFatal(const char *file, int line);
|
||||
~LogMessageFatal();
|
||||
std::ostream &stream();
|
||||
LogMessageFatal(const char *file, int line);
|
||||
~LogMessageFatal();
|
||||
std::ostream &stream();
|
||||
};
|
||||
|
||||
class LogMessageVoidify {
|
||||
@ -550,66 +559,88 @@ FormatLog(const char *file, int line, Ts &&...args) noexcept
|
||||
|
||||
namespace tile {
|
||||
typedef double WallTime;
|
||||
struct LogMessageTime {
|
||||
LogMessageTime();
|
||||
LogMessageTime(std::tm t);
|
||||
LogMessageTime(std::time_t timestamp, WallTime now);
|
||||
LogMessageTime(std::chrono::system_clock::time_point tp);
|
||||
|
||||
const time_t ×tamp() const { return timestamp_; }
|
||||
const int &sec() const { return time_struct_.tm_sec; }
|
||||
const int32_t &usec() const { return usecs_; }
|
||||
const int &(min)() const { return time_struct_.tm_min; }
|
||||
const int &hour() const { return time_struct_.tm_hour; }
|
||||
const int &day() const { return time_struct_.tm_mday; }
|
||||
const int &month() const { return time_struct_.tm_mon; }
|
||||
const int &year() const { return time_struct_.tm_year; }
|
||||
const int &dayOfWeek() const { return time_struct_.tm_wday; }
|
||||
const int &dayInYear() const { return time_struct_.tm_yday; }
|
||||
const int &dst() const { return time_struct_.tm_isdst; }
|
||||
const long int &gmtoff() const { return gmtoffset_; }
|
||||
const std::tm &tm() const { return time_struct_; }
|
||||
const bool use_localtime() const { return use_localtime_; }
|
||||
struct LogMessageTime {
|
||||
LogMessageTime();
|
||||
LogMessageTime(std::tm t);
|
||||
LogMessageTime(std::time_t timestamp, WallTime now);
|
||||
LogMessageTime(std::chrono::system_clock::time_point tp);
|
||||
|
||||
const time_t ×tamp() const { return timestamp_; }
|
||||
|
||||
const int &sec() const { return time_struct_.tm_sec; }
|
||||
|
||||
const int32_t &usec() const { return usecs_; }
|
||||
|
||||
const int &(min) () const { return time_struct_.tm_min; }
|
||||
|
||||
const int &hour() const { return time_struct_.tm_hour; }
|
||||
|
||||
const int &day() const { return time_struct_.tm_mday; }
|
||||
|
||||
const int &month() const { return time_struct_.tm_mon; }
|
||||
|
||||
const int &year() const { return time_struct_.tm_year; }
|
||||
|
||||
const int &dayOfWeek() const { return time_struct_.tm_wday; }
|
||||
|
||||
const int &dayInYear() const { return time_struct_.tm_yday; }
|
||||
|
||||
const int &dst() const { return time_struct_.tm_isdst; }
|
||||
|
||||
const long int &gmtoff() const { return gmtoffset_; }
|
||||
|
||||
const std::tm &tm() const { return time_struct_; }
|
||||
|
||||
const bool use_localtime() const { return use_localtime_; }
|
||||
|
||||
private:
|
||||
void init(const std::tm &t, std::time_t timestamp, WallTime now);
|
||||
std::tm time_struct_; // Time of creation of LogMessage
|
||||
time_t timestamp_; // Time of creation of LogMessage in seconds
|
||||
int32_t usecs_; // Time of creation of LogMessage - microseconds part
|
||||
long int gmtoffset_;
|
||||
bool use_localtime_;
|
||||
void init(const std::tm &t, std::time_t timestamp, WallTime now);
|
||||
std::tm time_struct_;// Time of creation of LogMessage
|
||||
time_t timestamp_; // Time of creation of LogMessage in seconds
|
||||
int32_t usecs_; // Time of creation of LogMessage - microseconds part
|
||||
long int gmtoffset_;
|
||||
bool use_localtime_;
|
||||
|
||||
void CalcGmtOffset();
|
||||
};
|
||||
|
||||
class LogSink {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<LogSink>;
|
||||
using Ptr = std::shared_ptr<LogSink>;
|
||||
|
||||
virtual ~LogSink();
|
||||
virtual bool ShouldLog(LogSeverity severity);
|
||||
virtual void Send(LogSeverity severity, const char *full_filename,
|
||||
const char *base_filename, int line,
|
||||
const LogMessageTime &logmsgtime, const char *message,
|
||||
size_t message_len);
|
||||
virtual void Flush();
|
||||
std::string ToString(LogSeverity severity, const char *file,
|
||||
const char *base_file, int line,
|
||||
const LogMessageTime &logmsgtime, const char *message,
|
||||
size_t message_len);
|
||||
virtual ~LogSink();
|
||||
virtual bool ShouldLog(LogSeverity severity);
|
||||
virtual void Send(LogSeverity severity,
|
||||
const char *full_filename,
|
||||
const char *base_filename,
|
||||
int line,
|
||||
const LogMessageTime &logmsgtime,
|
||||
const char *message,
|
||||
size_t message_len);
|
||||
virtual void Flush();
|
||||
std::string ToString(LogSeverity severity,
|
||||
const char *file,
|
||||
const char *base_file,
|
||||
int line,
|
||||
const LogMessageTime &logmsgtime,
|
||||
const char *message,
|
||||
size_t message_len);
|
||||
};
|
||||
|
||||
void ColoredWriteToStdout(LogSeverity severity, const char *message,
|
||||
size_t len);
|
||||
void ColoredWriteToStderr(LogSeverity severity, const char *message,
|
||||
size_t len);
|
||||
void ColoredWriteToStdout(LogSeverity severity, const char *message, size_t len);
|
||||
void ColoredWriteToStderr(LogSeverity severity, const char *message, size_t len);
|
||||
void AddLogSink(LogSink::Ptr dest);
|
||||
void RemoveLogSink(LogSink::Ptr dest);
|
||||
void SetStderrLogging(LogSeverity min_severity);
|
||||
void LogToStderr();
|
||||
void LogToSinks(LogSeverity severity, const char *full_filename,
|
||||
const char *base_filename, int line, const LogMessageTime &time,
|
||||
const char *message, size_t message_len);
|
||||
void LogToSinks(LogSeverity severity,
|
||||
const char *full_filename,
|
||||
const char *base_filename,
|
||||
int line,
|
||||
const LogMessageTime &time,
|
||||
const char *message,
|
||||
size_t message_len);
|
||||
void WaitForSinks();
|
||||
const char *GetLogSeverityName(LogSeverity severity);
|
||||
|
||||
|
@ -6,182 +6,244 @@
|
||||
#include <mutex>
|
||||
|
||||
namespace tile {
|
||||
bool VLogIsOn(int n) { return true; }
|
||||
bool
|
||||
VLogIsOn(int n)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
class LogMessage::Impl {
|
||||
public:
|
||||
Impl(const char *file, int line, int severity) : lm_(file, line, severity) {}
|
||||
std::ostream &stream() { return lm_.stream(); }
|
||||
Impl(const char *file, int line, int severity) : lm_(file, line, severity) {}
|
||||
|
||||
std::ostream &stream() { return lm_.stream(); }
|
||||
|
||||
private:
|
||||
google::LogMessage lm_;
|
||||
google::LogMessage lm_;
|
||||
};
|
||||
|
||||
class LogMessageFatal::Impl {
|
||||
public:
|
||||
Impl(const char *file, int line) : lm_(file, line) {}
|
||||
std::ostream &stream() { return lm_.stream(); }
|
||||
Impl(const char *file, int line) : lm_(file, line) {}
|
||||
|
||||
std::ostream &stream() { return lm_.stream(); }
|
||||
|
||||
private:
|
||||
google::LogMessageFatal lm_;
|
||||
google::LogMessageFatal lm_;
|
||||
};
|
||||
|
||||
LogMessage::LogMessage(const char *file, int line, int severity)
|
||||
: impl_(new Impl(file, line, severity)) {}
|
||||
LogMessage::LogMessage(const char *file, int line, int severity) : impl_(new Impl(file, line, severity)) {}
|
||||
|
||||
LogMessage::~LogMessage() = default;
|
||||
std::ostream &LogMessage::stream() { return impl_->stream(); }
|
||||
|
||||
LogMessageFatal::LogMessageFatal(const char *file, int line)
|
||||
: impl_(new Impl(file, line)) {}
|
||||
std::ostream &
|
||||
LogMessage::stream()
|
||||
{
|
||||
return impl_->stream();
|
||||
}
|
||||
|
||||
LogMessageFatal::LogMessageFatal(const char *file, int line) : impl_(new Impl(file, line)) {}
|
||||
|
||||
LogMessageFatal::~LogMessageFatal() = default;
|
||||
std::ostream &LogMessageFatal::stream() { return impl_->stream(); }
|
||||
|
||||
} // namespace tile
|
||||
std::ostream &
|
||||
LogMessageFatal::stream()
|
||||
{
|
||||
return impl_->stream();
|
||||
}
|
||||
|
||||
}// namespace tile
|
||||
|
||||
namespace tile {
|
||||
namespace internal {
|
||||
namespace logging {
|
||||
namespace {
|
||||
std::vector<PrefixAppender *> *GetProviers() {
|
||||
static std::vector<PrefixAppender *> providers;
|
||||
return &providers;
|
||||
std::vector<PrefixAppender *> *
|
||||
GetProviers()
|
||||
{
|
||||
static std::vector<PrefixAppender *> providers;
|
||||
return &providers;
|
||||
}
|
||||
} // namespace
|
||||
}// namespace
|
||||
|
||||
namespace details {
|
||||
std::string DescribeFormatArguments(const std::vector<std::string> &args) {
|
||||
return fmt::format("{}", fmt::join(args.begin(), args.end(), ", "));
|
||||
std::string
|
||||
DescribeFormatArguments(const std::vector<std::string> &args)
|
||||
{
|
||||
return fmt::format("{}", fmt::join(args.begin(), args.end(), ", "));
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
void InstallPrefixProvider(PrefixAppender *writer) {
|
||||
GetProviers()->push_back(writer);
|
||||
}// namespace details
|
||||
|
||||
void
|
||||
InstallPrefixProvider(PrefixAppender *writer)
|
||||
{
|
||||
GetProviers()->push_back(writer);
|
||||
}
|
||||
void WritePrefixTo(std::string *to) {
|
||||
for (auto &&appender : *GetProviers()) {
|
||||
auto was = to->size();
|
||||
appender(to);
|
||||
if (to->size() != was) {
|
||||
to->push_back(' ');
|
||||
|
||||
void
|
||||
WritePrefixTo(std::string *to)
|
||||
{
|
||||
for (auto &&appender : *GetProviers()) {
|
||||
auto was = to->size();
|
||||
appender(to);
|
||||
if (to->size() != was) { to->push_back(' '); }
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace logging
|
||||
} // namespace internal
|
||||
} // namespace tile
|
||||
}// namespace logging
|
||||
}// namespace internal
|
||||
}// namespace tile
|
||||
|
||||
namespace tile {
|
||||
|
||||
LogMessageTime::LogMessageTime()
|
||||
: time_struct_(), timestamp_(0), usecs_(0), gmtoffset_(0) {}
|
||||
LogMessageTime::LogMessageTime() : time_struct_(), timestamp_(0), usecs_(0), gmtoffset_(0) {}
|
||||
|
||||
LogMessageTime::LogMessageTime(std::tm t) {
|
||||
std::time_t timestamp = std::mktime(&t);
|
||||
init(t, timestamp, 0);
|
||||
LogMessageTime::LogMessageTime(std::tm t)
|
||||
{
|
||||
std::time_t timestamp = std::mktime(&t);
|
||||
init(t, timestamp, 0);
|
||||
}
|
||||
|
||||
LogMessageTime::LogMessageTime(std::time_t timestamp, WallTime now) {
|
||||
std::tm t;
|
||||
if (FLAGS_log_utc_time)
|
||||
gmtime_r(×tamp, &t);
|
||||
else
|
||||
localtime_r(×tamp, &t);
|
||||
init(t, timestamp, now);
|
||||
LogMessageTime::LogMessageTime(std::time_t timestamp, WallTime now)
|
||||
{
|
||||
std::tm t;
|
||||
if (FLAGS_log_utc_time)
|
||||
gmtime_r(×tamp, &t);
|
||||
else
|
||||
localtime_r(×tamp, &t);
|
||||
init(t, timestamp, now);
|
||||
}
|
||||
|
||||
void LogMessageTime::init(const std::tm &t, std::time_t timestamp,
|
||||
WallTime now) {
|
||||
time_struct_ = t;
|
||||
timestamp_ = timestamp;
|
||||
usecs_ = static_cast<std::int32_t>((now - timestamp) * 1000000);
|
||||
void
|
||||
LogMessageTime::init(const std::tm &t, std::time_t timestamp, WallTime now)
|
||||
{
|
||||
time_struct_ = t;
|
||||
timestamp_ = timestamp;
|
||||
usecs_ = static_cast<std::int32_t>((now - timestamp) * 1000000);
|
||||
|
||||
CalcGmtOffset();
|
||||
CalcGmtOffset();
|
||||
}
|
||||
|
||||
void LogMessageTime::CalcGmtOffset() {
|
||||
std::tm gmt_struct;
|
||||
int isDst = 0;
|
||||
if (FLAGS_log_utc_time) {
|
||||
localtime_r(×tamp_, &gmt_struct);
|
||||
isDst = gmt_struct.tm_isdst;
|
||||
gmt_struct = time_struct_;
|
||||
} else {
|
||||
isDst = time_struct_.tm_isdst;
|
||||
gmtime_r(×tamp_, &gmt_struct);
|
||||
}
|
||||
void
|
||||
LogMessageTime::CalcGmtOffset()
|
||||
{
|
||||
std::tm gmt_struct;
|
||||
int isDst = 0;
|
||||
if (FLAGS_log_utc_time) {
|
||||
localtime_r(×tamp_, &gmt_struct);
|
||||
isDst = gmt_struct.tm_isdst;
|
||||
gmt_struct = time_struct_;
|
||||
} else {
|
||||
isDst = time_struct_.tm_isdst;
|
||||
gmtime_r(×tamp_, &gmt_struct);
|
||||
}
|
||||
|
||||
time_t gmt_sec = mktime(&gmt_struct);
|
||||
const long hour_secs = 3600;
|
||||
// If the Daylight Saving Time(isDst) is active subtract an hour from the
|
||||
// current timestamp.
|
||||
gmtoffset_ =
|
||||
static_cast<long int>(timestamp_ - gmt_sec + (isDst ? hour_secs : 0));
|
||||
time_t gmt_sec = mktime(&gmt_struct);
|
||||
const long hour_secs = 3600;
|
||||
// If the Daylight Saving Time(isDst) is active subtract an hour from the
|
||||
// current timestamp.
|
||||
gmtoffset_ = static_cast<long int>(timestamp_ - gmt_sec + (isDst ? hour_secs : 0));
|
||||
}
|
||||
|
||||
LogSink::~LogSink() {}
|
||||
void LogSink::send(LogSeverity severity, const char *full_filename,
|
||||
const char *base_filename, int line,
|
||||
const LogMessageTime &logmsgtime, const char *message,
|
||||
size_t message_len) {
|
||||
|
||||
// do nothing
|
||||
void
|
||||
LogSink::send(LogSeverity severity,
|
||||
const char *full_filename,
|
||||
const char *base_filename,
|
||||
int line,
|
||||
const LogMessageTime &logmsgtime,
|
||||
const char *message,
|
||||
size_t message_len)
|
||||
{
|
||||
|
||||
// do nothing
|
||||
}
|
||||
void LogSink::WaitTillSent() {}
|
||||
std::string LogSink::ToString(LogSeverity severity, const char *file, int line,
|
||||
const LogMessageTime &logmsgtime,
|
||||
const char *message, size_t message_len) {
|
||||
return google::LogSink::ToString(severity, file, line, logmsgtime.tm(),
|
||||
message, message_len);
|
||||
|
||||
void
|
||||
LogSink::WaitTillSent()
|
||||
{}
|
||||
|
||||
std::string
|
||||
LogSink::ToString(LogSeverity severity,
|
||||
const char *file,
|
||||
int line,
|
||||
const LogMessageTime &logmsgtime,
|
||||
const char *message,
|
||||
size_t message_len)
|
||||
{
|
||||
return google::LogSink::ToString(severity, file, line, logmsgtime.tm(), message, message_len);
|
||||
}
|
||||
|
||||
class LogSinkWrapper : public google::LogSink {
|
||||
public:
|
||||
LogSinkWrapper(tile::LogSink *dest) : dest_(dest) {}
|
||||
~LogSinkWrapper() override {}
|
||||
void send(LogSeverity severity, const char *full_filename,
|
||||
const char *base_filename, int line,
|
||||
const google::LogMessageTime &logmsgtime, const char *message,
|
||||
size_t message_len) override {
|
||||
dest_->send(severity, full_filename, base_filename, line, logmsgtime.tm(),
|
||||
message, message_len);
|
||||
}
|
||||
LogSinkWrapper(tile::LogSink *dest) : dest_(dest) {}
|
||||
|
||||
void WaitTillSent() override { dest_->WaitTillSent(); }
|
||||
~LogSinkWrapper() override {}
|
||||
|
||||
void send(LogSeverity severity,
|
||||
const char *full_filename,
|
||||
const char *base_filename,
|
||||
int line,
|
||||
const google::LogMessageTime &logmsgtime,
|
||||
const char *message,
|
||||
size_t message_len) override
|
||||
{
|
||||
dest_->send(severity, full_filename, base_filename, line, logmsgtime.tm(), message, message_len);
|
||||
}
|
||||
|
||||
void WaitTillSent() override { dest_->WaitTillSent(); }
|
||||
|
||||
private:
|
||||
tile::LogSink *dest_;
|
||||
tile::LogSink *dest_;
|
||||
};
|
||||
|
||||
struct LogSinkPair {
|
||||
struct LogSinWrapper *wrapper;
|
||||
LogSink *sink;
|
||||
struct LogSinWrapper *wrapper;
|
||||
LogSink *sink;
|
||||
};
|
||||
|
||||
static std::map<LogSink *, LogSinkWrapper *> sink_registry;
|
||||
static std::mutex sink_registry_mutex;
|
||||
|
||||
void AddLogSink(LogSink *dest) {
|
||||
std::lock_guard<std::mutex> lock(sink_registry_mutex);
|
||||
if (sink_registry.find(dest) != sink_registry.end()) {
|
||||
return;
|
||||
}
|
||||
void
|
||||
AddLogSink(LogSink *dest)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(sink_registry_mutex);
|
||||
if (sink_registry.find(dest) != sink_registry.end()) { return; }
|
||||
|
||||
auto wrapper = new LogSinkWrapper(dest);
|
||||
sink_registry[dest] = wrapper;
|
||||
google::AddLogSink(wrapper);
|
||||
auto wrapper = new LogSinkWrapper(dest);
|
||||
sink_registry[dest] = wrapper;
|
||||
google::AddLogSink(wrapper);
|
||||
}
|
||||
|
||||
void RemoveLogSink(LogSink *dest) {
|
||||
std::lock_guard<std::mutex> lock(sink_registry_mutex);
|
||||
auto iter = sink_registry.find(dest);
|
||||
if (iter != sink_registry.end()) {
|
||||
google::RemoveLogSink(iter->second);
|
||||
sink_registry.erase(iter);
|
||||
delete iter->second;
|
||||
}
|
||||
void
|
||||
RemoveLogSink(LogSink *dest)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(sink_registry_mutex);
|
||||
auto iter = sink_registry.find(dest);
|
||||
if (iter != sink_registry.end()) {
|
||||
google::RemoveLogSink(iter->second);
|
||||
sink_registry.erase(iter);
|
||||
delete iter->second;
|
||||
}
|
||||
}
|
||||
void SetStderrLogging(LogSeverity min_severity) {
|
||||
google::SetStderrLogging(min_severity);
|
||||
|
||||
void
|
||||
SetStderrLogging(LogSeverity min_severity)
|
||||
{
|
||||
google::SetStderrLogging(min_severity);
|
||||
}
|
||||
void LogToStderr() { google::LogToStderr(); }
|
||||
const char *GetLogSeverityName(LogSeverity severity) {
|
||||
return google::GetLogSeverityName(severity);
|
||||
|
||||
void
|
||||
LogToStderr()
|
||||
{
|
||||
google::LogToStderr();
|
||||
}
|
||||
} // namespace tile
|
||||
|
||||
const char *
|
||||
GetLogSeverityName(LogSeverity severity)
|
||||
{
|
||||
return google::GetLogSeverityName(severity);
|
||||
}
|
||||
}// namespace tile
|
||||
|
@ -9,17 +9,31 @@
|
||||
#include <thread>
|
||||
|
||||
struct AwesomeLogSink : public tile::LogSink {
|
||||
virtual void Send(tile::LogSeverity severity, const char *full_filename,
|
||||
const char *base_filename, int line,
|
||||
const tile::LogMessageTime &logmsgtime, const char *message,
|
||||
size_t message_len) override {
|
||||
msgs.emplace_back(std::string(message, message_len));
|
||||
}
|
||||
std::vector<std::string> msgs;
|
||||
static std::shared_ptr<AwesomeLogSink> Create() { return std::make_shared<AwesomeLogSink>(); }
|
||||
|
||||
virtual void Send(tile::LogSeverity severity,
|
||||
const char *full_filename,
|
||||
const char *base_filename,
|
||||
int line,
|
||||
const tile::LogMessageTime &logmsgtime,
|
||||
const char *message,
|
||||
size_t message_len) override
|
||||
{
|
||||
msgs.emplace_back(std::string(message, message_len));
|
||||
}
|
||||
|
||||
std::vector<std::string> msgs;
|
||||
};
|
||||
|
||||
std::string my_prefix, my_prefix2;
|
||||
|
||||
void
|
||||
ResetLogPrefix()
|
||||
{
|
||||
my_prefix.clear();
|
||||
my_prefix2.clear();
|
||||
}
|
||||
|
||||
void
|
||||
WriteLoggingPrefix(std::string *s)
|
||||
{
|
||||
@ -32,26 +46,26 @@ WriteLoggingPrefix2(std::string *s)
|
||||
*s += my_prefix2;
|
||||
}
|
||||
|
||||
TEST(Logging, Prefix) {
|
||||
auto sink = std::make_shared<AwesomeLogSink>();
|
||||
tile::AddLogSink(sink);
|
||||
tile::ScopedDeferred defered([&] { tile::RemoveLogSink(sink); });
|
||||
TEST(Logging, Prefix)
|
||||
{
|
||||
auto sink = std::make_shared<AwesomeLogSink>();
|
||||
tile::AddLogSink(sink);
|
||||
tile::ScopedDeferred defered([&] { tile::RemoveLogSink(sink); });
|
||||
|
||||
TILE_LOG_INFO("something");
|
||||
TILE_LOG_INFO("something");
|
||||
|
||||
my_prefix = "[prefix]";
|
||||
TILE_LOG_INFO("something");
|
||||
my_prefix = "[prefix]";
|
||||
TILE_LOG_INFO("something");
|
||||
|
||||
my_prefix = "[prefix1]";
|
||||
TILE_LOG_INFO("something");
|
||||
my_prefix = "[prefix1]";
|
||||
TILE_LOG_INFO("something");
|
||||
|
||||
my_prefix2 = "[prefix2]";
|
||||
TILE_LOG_INFO("something");
|
||||
my_prefix2 = "[prefix2]";
|
||||
TILE_LOG_INFO("something");
|
||||
|
||||
ASSERT_THAT(sink->msgs,
|
||||
::testing::ElementsAre("something", "[prefix] something",
|
||||
"[prefix1] something",
|
||||
"[prefix1] [prefix2] something"));
|
||||
ASSERT_THAT(sink->msgs,
|
||||
::testing::ElementsAre(
|
||||
"something", "[prefix] something", "[prefix1] something", "[prefix1] [prefix2] something"));
|
||||
}
|
||||
|
||||
TEST(Logging, CHECK)
|
||||
@ -65,39 +79,21 @@ TEST(Logging, CHECK)
|
||||
ASSERT_DEATH(([] { TILE_CHECK_NE(1, 1, "CHECK_NE"); }()), "CHECK_NE");
|
||||
}
|
||||
|
||||
TEST(Logging, Prefix)
|
||||
{
|
||||
AwesomeLogSink sink;
|
||||
tile::AddLogSink(&sink);
|
||||
tile::ScopedDeferred defered([&] { tile::RemoveLogSink(&sink); });
|
||||
|
||||
auto sink = std::make_shared<AwesomeLogSink>();
|
||||
tile::AddLogSink(sink);
|
||||
tile::ScopedDeferred defered([&] { tile::RemoveLogSink(sink); });
|
||||
for (int i = 0; i < 30; i++) {
|
||||
TILE_LOG_INFO_EVERY_SECOND("something");
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
ASSERT_THAT(sink->msgs,
|
||||
::testing::ElementsAre("something", "something", "something"));
|
||||
}
|
||||
|
||||
TEST(Logging, DontPanicOnFormatFailure) { TILE_LOG_INFO("Don't panic!{}{}", 1); }
|
||||
|
||||
TEST(Logging, EverySecond)
|
||||
{
|
||||
ResetLogPrefix();
|
||||
|
||||
AwesomeLogSink sink;
|
||||
tile::AddLogSink(&sink);
|
||||
tile::ScopedDeferred defered([&] { tile::RemoveLogSink(&sink); });
|
||||
auto sink = AwesomeLogSink::Create();
|
||||
tile::AddLogSink(sink);
|
||||
tile::ScopedDeferred defered([&] { tile::RemoveLogSink(sink); });
|
||||
for (int i = 0; i < 30; i++) {
|
||||
TILE_LOG_INFO_EVERY_SECOND("something");
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
ASSERT_THAT(sink.msgs, ::testing::ElementsAre("something", "something", "something"));
|
||||
ASSERT_THAT(sink->msgs, ::testing::ElementsAre("something", "something", "something"));
|
||||
}
|
||||
|
||||
TEST(Logging, Enum)
|
||||
|
@ -1,24 +1,47 @@
|
||||
#include "tile/base/logging/basic_file_sink.h"
|
||||
|
||||
namespace tile {
|
||||
BasicFileSink::Ptr BasicFileSink::Create(const std::string &filepath) {
|
||||
auto sink = std::shared_ptr<BasicFileSink>(new BasicFileSink());
|
||||
sink->set_filepath(filepath);
|
||||
return sink;
|
||||
BasicFileSink::Ptr
|
||||
BasicFileSink::Create(const std::string &filepath)
|
||||
{
|
||||
auto sink = std::shared_ptr<BasicFileSink>(new BasicFileSink());
|
||||
sink->set_filepath(filepath);
|
||||
return sink;
|
||||
}
|
||||
|
||||
BasicFileSink::BasicFileSink() {}
|
||||
|
||||
BasicFileSink::~BasicFileSink() {}
|
||||
void BasicFileSink::Send(LogSeverity severity, const char *full_filename,
|
||||
const char *base_filename, int line,
|
||||
const LogMessageTime &logmsgtime, const char *message,
|
||||
size_t message_len) {
|
||||
TILE_CHECK(!filepath_.empty(), "filepath is empty");
|
||||
ofs_ << std::string(message, message_len) << std::endl;
|
||||
|
||||
void
|
||||
BasicFileSink::Send(LogSeverity severity,
|
||||
const char *full_filename,
|
||||
const char *base_filename,
|
||||
int line,
|
||||
const LogMessageTime &logmsgtime,
|
||||
const char *message,
|
||||
size_t message_len)
|
||||
{
|
||||
TILE_CHECK(!filepath_.empty(), "filepath is empty");
|
||||
ofs_ << std::string(message, message_len) << std::endl;
|
||||
}
|
||||
std::string BasicFileSink::filepath() const { return filepath_; }
|
||||
void BasicFileSink::set_filepath(const std::string &filepath) {
|
||||
filepath_ = filepath;
|
||||
ofs_.open(filepath, std::ios::out | std::ios::app);
|
||||
|
||||
std::string
|
||||
BasicFileSink::filepath() const
|
||||
{
|
||||
return filepath_;
|
||||
}
|
||||
void BasicFileSink::Flush() { ofs_.flush(); }
|
||||
} // namespace tile
|
||||
|
||||
void
|
||||
BasicFileSink::set_filepath(const std::string &filepath)
|
||||
{
|
||||
filepath_ = filepath;
|
||||
ofs_.open(filepath, std::ios::out | std::ios::app);
|
||||
}
|
||||
|
||||
void
|
||||
BasicFileSink::Flush()
|
||||
{
|
||||
ofs_.flush();
|
||||
}
|
||||
}// namespace tile
|
||||
|
@ -10,27 +10,30 @@
|
||||
namespace tile {
|
||||
class BasicFileSink : public LogSink {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<BasicFileSink>;
|
||||
static Ptr Create(const std::string &filepath);
|
||||
using Ptr = std::shared_ptr<BasicFileSink>;
|
||||
static Ptr Create(const std::string &filepath);
|
||||
|
||||
~BasicFileSink() override;
|
||||
void Send(LogSeverity severity, const char *full_filename,
|
||||
const char *base_filename, int line,
|
||||
const LogMessageTime &logmsgtime, const char *message,
|
||||
size_t message_len) override;
|
||||
void Flush() override;
|
||||
~BasicFileSink() override;
|
||||
void Send(LogSeverity severity,
|
||||
const char *full_filename,
|
||||
const char *base_filename,
|
||||
int line,
|
||||
const LogMessageTime &logmsgtime,
|
||||
const char *message,
|
||||
size_t message_len) override;
|
||||
void Flush() override;
|
||||
|
||||
std::string filepath() const;
|
||||
void set_filepath(const std::string &filepath);
|
||||
std::string filepath() const;
|
||||
void set_filepath(const std::string &filepath);
|
||||
|
||||
protected:
|
||||
BasicFileSink();
|
||||
BasicFileSink();
|
||||
|
||||
private:
|
||||
std::string filepath_;
|
||||
std::ofstream ofs_;
|
||||
std::string filepath_;
|
||||
std::ofstream ofs_;
|
||||
};
|
||||
|
||||
} // namespace tile
|
||||
}// namespace tile
|
||||
|
||||
#endif // TILE_BASE_LOGGING_BASIC_FILE_SINK_H
|
||||
#endif// TILE_BASE_LOGGING_BASIC_FILE_SINK_H
|
||||
|
@ -1,32 +1,39 @@
|
||||
#include "tile/base/logging/console_sink.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace tile {
|
||||
|
||||
ConsoleSink::Ptr ConsoleSink::Create() {
|
||||
return std::shared_ptr<ConsoleSink>(new ConsoleSink());
|
||||
ConsoleSink::Ptr
|
||||
ConsoleSink::Create()
|
||||
{
|
||||
return std::shared_ptr<ConsoleSink>(new ConsoleSink());
|
||||
}
|
||||
|
||||
ConsoleSink::~ConsoleSink() {}
|
||||
|
||||
void ConsoleSink::Send(LogSeverity severity, const char *full_filename,
|
||||
const char *base_filename, int line,
|
||||
const LogMessageTime &logmsgtime, const char *message,
|
||||
size_t message_len) {
|
||||
auto msg = ToString(severity, full_filename, base_filename, line, logmsgtime,
|
||||
message, message_len);
|
||||
while (!msg.empty() && msg.back() == '\n') {
|
||||
msg.pop_back();
|
||||
}
|
||||
if (severity >= TILE_FATAL) {
|
||||
fprintf(stderr, "%s\n", msg.c_str());
|
||||
} else {
|
||||
fprintf(stdout, "%s\n", msg.c_str());
|
||||
}
|
||||
void
|
||||
ConsoleSink::Send(LogSeverity severity,
|
||||
const char *full_filename,
|
||||
const char *base_filename,
|
||||
int line,
|
||||
const LogMessageTime &logmsgtime,
|
||||
const char *message,
|
||||
size_t message_len)
|
||||
{
|
||||
auto msg = ToString(severity, full_filename, base_filename, line, logmsgtime, message, message_len);
|
||||
while (!msg.empty() && msg.back() == '\n') { msg.pop_back(); }
|
||||
if (severity >= TILE_FATAL) {
|
||||
fprintf(stderr, "%s\n", msg.c_str());
|
||||
} else {
|
||||
fprintf(stdout, "%s\n", msg.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleSink::Flush() {}
|
||||
void
|
||||
ConsoleSink::Flush()
|
||||
{}
|
||||
|
||||
ConsoleSink::ConsoleSink() {}
|
||||
|
||||
} // namespace tile
|
||||
}// namespace tile
|
||||
|
@ -4,22 +4,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "tile/base/internal/logging.h"
|
||||
|
||||
namespace tile {
|
||||
class ConsoleSink : public LogSink {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<ConsoleSink>;
|
||||
static Ptr Create();
|
||||
using Ptr = std::shared_ptr<ConsoleSink>;
|
||||
static Ptr Create();
|
||||
|
||||
~ConsoleSink() override;
|
||||
void Send(LogSeverity severity, const char *full_filename,
|
||||
const char *base_filename, int line,
|
||||
const LogMessageTime &logmsgtime, const char *message,
|
||||
size_t message_len) override;
|
||||
void Flush() override;
|
||||
~ConsoleSink() override;
|
||||
void Send(LogSeverity severity,
|
||||
const char *full_filename,
|
||||
const char *base_filename,
|
||||
int line,
|
||||
const LogMessageTime &logmsgtime,
|
||||
const char *message,
|
||||
size_t message_len) override;
|
||||
void Flush() override;
|
||||
|
||||
protected:
|
||||
ConsoleSink();
|
||||
ConsoleSink();
|
||||
};
|
||||
} // namespace tile
|
||||
}// namespace tile
|
||||
|
||||
#endif // TILE_BASE_LOGGING_CONSOLE_SINK_H
|
||||
#endif// TILE_BASE_LOGGING_CONSOLE_SINK_H
|
||||
|
@ -2,62 +2,78 @@
|
||||
#include <cassert>
|
||||
|
||||
namespace tile {
|
||||
std::shared_ptr<SplitterSink> SplitterSink::Create() {
|
||||
return std::shared_ptr<SplitterSink>(new SplitterSink());
|
||||
std::shared_ptr<SplitterSink>
|
||||
SplitterSink::Create()
|
||||
{
|
||||
return std::shared_ptr<SplitterSink>(new SplitterSink());
|
||||
}
|
||||
|
||||
std::shared_ptr<SplitterSink> SplitterSink::Create(
|
||||
std::initializer_list<std::shared_ptr<LogSink>> init_list) {
|
||||
auto sink = Create();
|
||||
for (auto &s : init_list) {
|
||||
sink->AddSink(s);
|
||||
}
|
||||
return sink;
|
||||
std::shared_ptr<SplitterSink>
|
||||
SplitterSink::Create(std::initializer_list<std::shared_ptr<LogSink>> init_list)
|
||||
{
|
||||
auto sink = Create();
|
||||
for (auto &s : init_list) { sink->AddSink(s); }
|
||||
return sink;
|
||||
}
|
||||
|
||||
SplitterSink::SplitterSink() {}
|
||||
|
||||
SplitterSink::~SplitterSink() {}
|
||||
void SplitterSink::Send(LogSeverity severity, const char *full_filename,
|
||||
const char *base_filename, int line,
|
||||
const LogMessageTime &logmsgtime, const char *message,
|
||||
size_t message_len) {
|
||||
assert(!doing_ && "SplitterSink::send() should not be called recursively");
|
||||
std::lock_guard<std::mutex> _(sinks_mutex_);
|
||||
doing_ = true;
|
||||
for (auto &sink : sinks_) {
|
||||
sink->Send(severity, full_filename, base_filename, line, logmsgtime,
|
||||
message, message_len);
|
||||
}
|
||||
doing_ = false;
|
||||
|
||||
void
|
||||
SplitterSink::Send(LogSeverity severity,
|
||||
const char *full_filename,
|
||||
const char *base_filename,
|
||||
int line,
|
||||
const LogMessageTime &logmsgtime,
|
||||
const char *message,
|
||||
size_t message_len)
|
||||
{
|
||||
assert(!doing_ && "SplitterSink::send() should not be called recursively");
|
||||
std::lock_guard<std::mutex> _(sinks_mutex_);
|
||||
doing_ = true;
|
||||
for (auto &sink : sinks_) {
|
||||
sink->Send(severity, full_filename, base_filename, line, logmsgtime, message, message_len);
|
||||
}
|
||||
doing_ = false;
|
||||
}
|
||||
|
||||
void SplitterSink::Flush() {
|
||||
assert(!doing_ && "SplitterSink::send() should not be called recursively");
|
||||
std::lock_guard<std::mutex> _(sinks_mutex_);
|
||||
doing_ = true;
|
||||
for (auto &sink : sinks_) {
|
||||
sink->Flush();
|
||||
}
|
||||
doing_ = false;
|
||||
void
|
||||
SplitterSink::Flush()
|
||||
{
|
||||
assert(!doing_ && "SplitterSink::send() should not be called recursively");
|
||||
std::lock_guard<std::mutex> _(sinks_mutex_);
|
||||
doing_ = true;
|
||||
for (auto &sink : sinks_) { sink->Flush(); }
|
||||
doing_ = false;
|
||||
}
|
||||
|
||||
void SplitterSink::AddSink(std::shared_ptr<LogSink> sink) {
|
||||
std::lock_guard<std::mutex> _(sinks_mutex_);
|
||||
sinks_.insert(sink);
|
||||
void
|
||||
SplitterSink::AddSink(std::shared_ptr<LogSink> sink)
|
||||
{
|
||||
std::lock_guard<std::mutex> _(sinks_mutex_);
|
||||
sinks_.insert(sink);
|
||||
}
|
||||
|
||||
void SplitterSink::RemoveSink(std::shared_ptr<LogSink> sink) {
|
||||
std::lock_guard<std::mutex> _(sinks_mutex_);
|
||||
sinks_.erase(sink);
|
||||
void
|
||||
SplitterSink::RemoveSink(std::shared_ptr<LogSink> sink)
|
||||
{
|
||||
std::lock_guard<std::mutex> _(sinks_mutex_);
|
||||
sinks_.erase(sink);
|
||||
}
|
||||
|
||||
void SplitterSink::ClearSinks() {
|
||||
std::lock_guard<std::mutex> _(sinks_mutex_);
|
||||
sinks_.clear();
|
||||
}
|
||||
std::set<LogSink::Ptr> SplitterSink::sinks() {
|
||||
std::lock_guard<std::mutex> _(sinks_mutex_);
|
||||
return sinks_;
|
||||
void
|
||||
SplitterSink::ClearSinks()
|
||||
{
|
||||
std::lock_guard<std::mutex> _(sinks_mutex_);
|
||||
sinks_.clear();
|
||||
}
|
||||
|
||||
} // namespace tile
|
||||
std::set<LogSink::Ptr>
|
||||
SplitterSink::sinks()
|
||||
{
|
||||
std::lock_guard<std::mutex> _(sinks_mutex_);
|
||||
return sinks_;
|
||||
}
|
||||
|
||||
}// namespace tile
|
||||
|
@ -10,31 +10,34 @@
|
||||
namespace tile {
|
||||
class SplitterSink : public LogSink {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<SplitterSink>;
|
||||
static Ptr Create();
|
||||
static Ptr Create(std::initializer_list<std::shared_ptr<LogSink>> init_list);
|
||||
using Ptr = std::shared_ptr<SplitterSink>;
|
||||
static Ptr Create();
|
||||
static Ptr Create(std::initializer_list<std::shared_ptr<LogSink>> init_list);
|
||||
|
||||
~SplitterSink() override;
|
||||
~SplitterSink() override;
|
||||
|
||||
void Send(LogSeverity severity, const char *full_filename,
|
||||
const char *base_filename, int line,
|
||||
const LogMessageTime &logmsgtime, const char *message,
|
||||
size_t message_len) override;
|
||||
void Flush() override;
|
||||
void Send(LogSeverity severity,
|
||||
const char *full_filename,
|
||||
const char *base_filename,
|
||||
int line,
|
||||
const LogMessageTime &logmsgtime,
|
||||
const char *message,
|
||||
size_t message_len) override;
|
||||
void Flush() override;
|
||||
|
||||
void AddSink(std::shared_ptr<LogSink> sink);
|
||||
void RemoveSink(std::shared_ptr<LogSink> sink);
|
||||
void ClearSinks();
|
||||
std::set<LogSink::Ptr> sinks();
|
||||
void AddSink(std::shared_ptr<LogSink> sink);
|
||||
void RemoveSink(std::shared_ptr<LogSink> sink);
|
||||
void ClearSinks();
|
||||
std::set<LogSink::Ptr> sinks();
|
||||
|
||||
protected:
|
||||
SplitterSink();
|
||||
SplitterSink();
|
||||
|
||||
private:
|
||||
std::set<std::shared_ptr<LogSink>> sinks_;
|
||||
std::mutex sinks_mutex_;
|
||||
bool doing_ = false;
|
||||
std::set<std::shared_ptr<LogSink>> sinks_;
|
||||
std::mutex sinks_mutex_;
|
||||
bool doing_ = false;
|
||||
};
|
||||
} // namespace tile
|
||||
}// namespace tile
|
||||
|
||||
#endif // TILE_BASE_LOGGING_SPLITTER_SINK_H
|
||||
#endif// TILE_BASE_LOGGING_SPLITTER_SINK_H
|
||||
|
@ -4,53 +4,57 @@
|
||||
namespace tile {
|
||||
class SimpleSink : public LogSink {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<SimpleSink>;
|
||||
static Ptr Create() { return std::shared_ptr<SimpleSink>(new SimpleSink()); }
|
||||
void Send(LogSeverity severity, const char *full_filename,
|
||||
const char *base_filename, int line,
|
||||
const LogMessageTime &logmsgtime, const char *message,
|
||||
size_t message_len) override {
|
||||
message_ = std::string(message, message_len);
|
||||
}
|
||||
void Flush() override {}
|
||||
std::string message_;
|
||||
using Ptr = std::shared_ptr<SimpleSink>;
|
||||
|
||||
static Ptr Create() { return std::shared_ptr<SimpleSink>(new SimpleSink()); }
|
||||
|
||||
void Send(LogSeverity severity,
|
||||
const char *full_filename,
|
||||
const char *base_filename,
|
||||
int line,
|
||||
const LogMessageTime &logmsgtime,
|
||||
const char *message,
|
||||
size_t message_len) override
|
||||
{
|
||||
message_ = std::string(message, message_len);
|
||||
}
|
||||
|
||||
void Flush() override {}
|
||||
|
||||
std::string message_;
|
||||
};
|
||||
|
||||
TEST(SplitterSink, One) {
|
||||
auto sink = SimpleSink::Create();
|
||||
auto splitter = SplitterSink::Create({sink});
|
||||
splitter->Send(LogSeverity::TILE_INFO, nullptr, nullptr, 0, LogMessageTime(),
|
||||
"message", 7);
|
||||
ASSERT_EQ(sink->message_, "message");
|
||||
TEST(SplitterSink, One)
|
||||
{
|
||||
auto sink = SimpleSink::Create();
|
||||
auto splitter = SplitterSink::Create({sink});
|
||||
splitter->Send(LogSeverity::TILE_INFO, nullptr, nullptr, 0, LogMessageTime(), "message", 7);
|
||||
ASSERT_EQ(sink->message_, "message");
|
||||
}
|
||||
|
||||
TEST(SplitterSink, Two) {
|
||||
auto sink1 = SimpleSink::Create();
|
||||
auto sink2 = SimpleSink::Create();
|
||||
auto splitter = SplitterSink::Create({sink1, sink2});
|
||||
splitter->Send(LogSeverity::TILE_INFO, nullptr, nullptr, 0, LogMessageTime(),
|
||||
"message", 7);
|
||||
ASSERT_EQ(sink1->message_, "message");
|
||||
ASSERT_EQ(sink2->message_, "message");
|
||||
TEST(SplitterSink, Two)
|
||||
{
|
||||
auto sink1 = SimpleSink::Create();
|
||||
auto sink2 = SimpleSink::Create();
|
||||
auto splitter = SplitterSink::Create({sink1, sink2});
|
||||
splitter->Send(LogSeverity::TILE_INFO, nullptr, nullptr, 0, LogMessageTime(), "message", 7);
|
||||
ASSERT_EQ(sink1->message_, "message");
|
||||
ASSERT_EQ(sink2->message_, "message");
|
||||
}
|
||||
|
||||
TEST(SplitterSink, Multi) {
|
||||
auto splitter = SplitterSink::Create();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
splitter->AddSink(SimpleSink::Create());
|
||||
}
|
||||
TEST(SplitterSink, Multi)
|
||||
{
|
||||
auto splitter = SplitterSink::Create();
|
||||
for (int i = 0; i < 100; i++) { splitter->AddSink(SimpleSink::Create()); }
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
std::stringstream ss;
|
||||
ss << "message" << i;
|
||||
auto msg = ss.str();
|
||||
splitter->Send(LogSeverity::TILE_INFO, nullptr, nullptr, 0,
|
||||
LogMessageTime(), msg.data(), msg.size());
|
||||
for (int i = 0; i < 100; i++) {
|
||||
std::stringstream ss;
|
||||
ss << "message" << i;
|
||||
auto msg = ss.str();
|
||||
splitter->Send(LogSeverity::TILE_INFO, nullptr, nullptr, 0, LogMessageTime(), msg.data(), msg.size());
|
||||
|
||||
for (auto &sink : splitter->sinks()) {
|
||||
ASSERT_EQ(std::static_pointer_cast<SimpleSink>(sink)->message_, msg);
|
||||
for (auto &sink : splitter->sinks()) { ASSERT_EQ(std::static_pointer_cast<SimpleSink>(sink)->message_, msg); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace tile
|
||||
}// namespace tile
|
||||
|
33
tile/init.cc
33
tile/init.cc
@ -32,12 +32,14 @@ namespace {
|
||||
|
||||
std::atomic<bool> g_quit_siganl{false};
|
||||
|
||||
void QuitSignalHandler(int sig) {
|
||||
auto old = g_quit_siganl.exchange(true, std::memory_order_relaxed);
|
||||
if (old && FLAGS_tile_abort_on_double_quit_signal) {
|
||||
// TODO: Add TILE_RAW_LOG
|
||||
// RAW_LOG(FATAL, "Double quit signal received. Crashing the program");
|
||||
}
|
||||
void
|
||||
QuitSignalHandler(int sig)
|
||||
{
|
||||
auto old = g_quit_siganl.exchange(true, std::memory_order_relaxed);
|
||||
if (old && FLAGS_tile_abort_on_double_quit_signal) {
|
||||
// TODO: Add TILE_RAW_LOG
|
||||
// RAW_LOG(FATAL, "Double quit signal received. Crashing the program");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -52,22 +54,23 @@ InstallQuitSignalHandler()
|
||||
}
|
||||
}// namespace
|
||||
|
||||
int Start(int argc, char **argv, std::function<int(int, char **)> cb,
|
||||
bool single_thread, bool enable_crash_catch) {
|
||||
if (enable_crash_catch) {
|
||||
// TODO: Add InstallFailureSignalHandler
|
||||
// google::InstallFailureSignalHandler();
|
||||
}
|
||||
int
|
||||
Start(int argc, char **argv, std::function<int(int, char **)> cb, bool single_thread, bool enable_crash_catch)
|
||||
{
|
||||
if (enable_crash_catch) {
|
||||
// TODO: Add InstallFailureSignalHandler
|
||||
// google::InstallFailureSignalHandler();
|
||||
}
|
||||
|
||||
// Init gflags
|
||||
gflags::SetVersionString(TILE_VERSION);
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
detail::ApplyFlagOverrider();
|
||||
|
||||
AddLogSink(ConsoleSink::Create());
|
||||
AddLogSink(ConsoleSink::Create());
|
||||
|
||||
// TODO: Add Init log level
|
||||
// google::InitGoogleLogging(argv[0]);
|
||||
// TODO: Add Init log level
|
||||
// google::InitGoogleLogging(argv[0]);
|
||||
|
||||
TILE_LOG_INFO("Tile started. version: {}", TILE_VERSION);
|
||||
|
||||
|
@ -10,27 +10,29 @@ namespace tile {
|
||||
namespace testing {
|
||||
|
||||
namespace {
|
||||
int StartBenchmark(int argc, char **argv) {
|
||||
::benchmark::Initialize(&argc, argv);
|
||||
if (::benchmark::ReportUnrecognizedArguments(argc, argv)) {
|
||||
return 1;
|
||||
}
|
||||
::benchmark::RunSpecifiedBenchmarks();
|
||||
::benchmark::Shutdown();
|
||||
return 0;
|
||||
int
|
||||
StartBenchmark(int argc, char **argv)
|
||||
{
|
||||
::benchmark::Initialize(&argc, argv);
|
||||
if (::benchmark::ReportUnrecognizedArguments(argc, argv)) { return 1; }
|
||||
::benchmark::RunSpecifiedBenchmarks();
|
||||
::benchmark::Shutdown();
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
}// namespace
|
||||
|
||||
int InitAndRunAllBenchmarks(int *argc, char **argv) {
|
||||
int
|
||||
InitAndRunAllBenchmarks(int *argc, char **argv)
|
||||
{
|
||||
|
||||
// if (gflags::GetCommandLineFlagInfoOrDie("logtostderr").is_default) {
|
||||
// FLAGS_logtostderr = true;
|
||||
// }
|
||||
// if (gflags::GetCommandLineFlagInfoOrDie("logtostderr").is_default) {
|
||||
// FLAGS_logtostderr = true;
|
||||
// }
|
||||
|
||||
return Start(*argc, argv, StartBenchmark, true);
|
||||
return Start(*argc, argv, StartBenchmark, true);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace tile
|
||||
}// namespace testing
|
||||
}// namespace tile
|
||||
|
||||
TILE_BENCHMARK_MAIN
|
||||
|
Loading…
Reference in New Issue
Block a user