feat/update_config #10

Merged
tqcq merged 26 commits from feat/update_config into master 2024-10-14 10:15:01 +08:00
15 changed files with 958 additions and 729 deletions
Showing only changes of commit fa04f9c23a - Show all commits

View File

@ -2128,7 +2128,7 @@ nsel_DISABLE_MSVC_WARNINGS(26409)
: make_unexpected(detail::invoke(std::forward<F>(f), std::move(error()))); : make_unexpected(detail::invoke(std::forward<F>(f), std::move(error())));
} }
#endif #endif
#endif// nsel_P2505R >= 3 #endif// nsel_P2505R >= 3 \
// unwrap() // unwrap()
// template <class U, class E> // template <class U, class E>

View File

@ -174,7 +174,6 @@ private:
{"1s", 1} {"1s", 1}
}; };
for (auto &&item : m) {} for (auto &&item : m) {}
}
return result; return result;
} }

View File

@ -16,7 +16,7 @@ GetProviers()
static std::vector<PrefixAppender *> providers; static std::vector<PrefixAppender *> providers;
return &providers; return &providers;
} }
} // namespace }// namespace
namespace details { namespace details {
std::string std::string
@ -24,9 +24,11 @@ DescribeFormatArguments(const std::vector<std::string> &args)
{ {
return fmt::format("{}", fmt::join(args.begin(), args.end(), ", ")); return fmt::format("{}", fmt::join(args.begin(), args.end(), ", "));
} }
} // namespace details }// namespace details
void InstallPrefixProvider(PrefixAppender *writer) { void
InstallPrefixProvider(PrefixAppender *writer)
{
GetProviers()->push_back(writer); GetProviers()->push_back(writer);
} }
@ -39,9 +41,9 @@ WritePrefixTo(std::string *to)
if (to->size() != was) { to->push_back(' '); } if (to->size() != was) { to->push_back(' '); }
} }
} }
} // namespace logging }// namespace logging
} // namespace internal }// namespace internal
} // namespace tile }// namespace tile
namespace tile { namespace tile {
static std::mutex g_sink_mutex; static std::mutex g_sink_mutex;
@ -61,32 +63,39 @@ private:
std::ostream &ostream_; std::ostream &ostream_;
}; };
bool VLogIsOn(int n) { return true; } bool
VLogIsOn(int n)
{
return true;
}
class LogMessage::Impl { class LogMessage::Impl {
public: public:
Impl(const char *file, int line) Impl(const char *file, int line) : stream_(message_text_, LogMessage::kMaxLogMessageLen, 0)
: stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) { {
Init(file, line, TILE_INFO, &LogMessage::Impl::SendToLog); Init(file, line, TILE_INFO, &LogMessage::Impl::SendToLog);
} }
Impl(const char *file, int line, LogSeverity severity)
: stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) { Impl(const char *file, int line, LogSeverity severity) : stream_(message_text_, LogMessage::kMaxLogMessageLen, 0)
{
Init(file, line, severity, &LogMessage::Impl::SendToLog); Init(file, line, severity, &LogMessage::Impl::SendToLog);
} }
Impl(const char *file, int line, LogSeverity severity, LogSink *sink,
bool also_send_to_log) Impl(const char *file, int line, LogSeverity severity, LogSink *sink, bool also_send_to_log)
: stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) { : stream_(message_text_, LogMessage::kMaxLogMessageLen, 0)
{
Init(file, line, severity, Init(file, line, severity,
also_send_to_log ? &LogMessage::Impl::SendToSinkAndLog also_send_to_log ? &LogMessage::Impl::SendToSinkAndLog : &LogMessage::Impl::SendToSink);
: &LogMessage::Impl::SendToSink);
sink_ = sink; sink_ = sink;
} }
~Impl() { Flush(); } ~Impl() { Flush(); }
std::ostream &stream() { return stream_; } std::ostream &stream() { return stream_; }
void Flush() {
if (has_been_flushed_) { void Flush()
return; {
} if (has_been_flushed_) { return; }
num_chars_to_log_ = stream_.pcount(); num_chars_to_log_ = stream_.pcount();
const bool append_newline = message_text_[num_chars_to_log_ - 1] != '\n'; const bool append_newline = message_text_[num_chars_to_log_ - 1] != '\n';
@ -103,35 +112,32 @@ public:
(this->*(send_method_))(); (this->*(send_method_))();
++g_num_messages[severity_]; ++g_num_messages[severity_];
WaitForSinks(); WaitForSinks();
if (sink_) { if (sink_) { sink_->Flush(); }
sink_->Flush();
}
} }
if (append_newline) { if (append_newline) { message_text_[num_chars_to_log_ - 1] = original_final_char; }
message_text_[num_chars_to_log_ - 1] = original_final_char;
}
if (preserved_errno_ != 0) { if (preserved_errno_ != 0) { errno = preserved_errno_; }
errno = preserved_errno_;
}
has_been_flushed_ = true; has_been_flushed_ = true;
if (severity_ == TILE_FATAL) { if (severity_ == TILE_FATAL) { assert(false); }
assert(false);
}
} }
LogSeverity severity() const noexcept { return severity_; } LogSeverity severity() const noexcept { return severity_; }
int line() const noexcept { return line_; } int line() const noexcept { return line_; }
const char *fullname() const noexcept { return file_; } const char *fullname() const noexcept { return file_; }
const char *basename() const noexcept { return file_; } const char *basename() const noexcept { return file_; }
const LogMessageTime &time() const noexcept { return time_; } const LogMessageTime &time() const noexcept { return time_; }
int preserved_errno() const { return preserved_errno_; } int preserved_errno() const { return preserved_errno_; }
private: private:
void Init(const char *file, int line, LogSeverity severity, void Init(const char *file, int line, LogSeverity severity, void (LogMessage::Impl::*send_method)())
void (LogMessage::Impl::*send_method)()) { {
has_been_flushed_ = false; has_been_flushed_ = false;
file_ = file; file_ = file;
line_ = line; line_ = line;
@ -144,23 +150,25 @@ private:
preserved_errno_ = errno; preserved_errno_ = errno;
} }
void SendToSink() { void SendToSink()
{
if (sink_) { if (sink_) {
sink_->Send(severity_, fullname(), basename(), line(), time(), sink_->Send(severity_, fullname(), basename(), line(), time(), message_text_ + num_prefix_chars_,
message_text_ + num_prefix_chars_, num_chars_to_log_ - num_prefix_chars_ - 1);
num_chars_to_log_ - num_prefix_chars_);
} }
} }
void SendToLog() {
void SendToLog()
{
if (g_sink_count.load(std::memory_order_relaxed) == 0) { if (g_sink_count.load(std::memory_order_relaxed) == 0) {
ColoredWriteToStdout(severity_, message_text_ + num_prefix_chars_, ColoredWriteToStdout(severity_, message_text_ + num_prefix_chars_, num_chars_to_log_ - num_chars_to_log_);
num_chars_to_log_ - num_chars_to_log_);
} }
LogToSinks(severity_, fullname(), basename(), line(), time(), LogToSinks(severity_, fullname(), basename(), line(), time(), message_text_ + num_prefix_chars_,
message_text_ + num_prefix_chars_, num_chars_to_log_ - num_prefix_chars_ - 1);
num_chars_to_log_ - num_prefix_chars_);
} }
void SendToSinkAndLog() {
void SendToSinkAndLog()
{
SendToSink(); SendToSink();
SendToLog(); SendToLog();
} }
@ -185,44 +193,84 @@ private:
size_t num_chars_to_log_; size_t num_chars_to_log_;
}; };
LogMessage::LogMessage(const char *file, int line) LogMessage::LogMessage(const char *file, int line) : impl_(new Impl(file, line)) {}
: impl_(new Impl(file, line)) {}
LogMessage::LogMessage(const char *file, int line, LogSeverity severity) LogMessage::LogMessage(const char *file, int line, LogSeverity severity) : impl_(new Impl(file, line, severity)) {}
: impl_(new Impl(file, line, severity)) {}
LogMessage::LogMessage(const char *file, int line, LogSeverity severity, LogMessage::LogMessage(const char *file, int line, LogSeverity severity, LogSink *sink, bool also_send_to_log)
LogSink *sink, bool also_send_to_log) : impl_(new Impl(file, line, severity, sink, also_send_to_log))
: impl_(new Impl(file, line, severity, sink, also_send_to_log)) {} {}
LogMessage::~LogMessage() {} LogMessage::~LogMessage() {}
std::ostream &LogMessage::stream() { return impl_->stream(); } std::ostream &
void LogMessage::Flush() { impl_->Flush(); } LogMessage::stream()
{
return impl_->stream();
}
LogSeverity LogMessage::severity() const noexcept { return impl_->severity(); } void
int LogMessage::line() const noexcept { return impl_->line(); } LogMessage::Flush()
const char *LogMessage::fullname() const noexcept { return impl_->fullname(); } {
const char *LogMessage::basename() const noexcept { return impl_->basename(); } impl_->Flush();
const LogMessageTime &LogMessage::time() const noexcept { }
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(); return impl_->time();
} }
int LogMessage::preserved_errno() const { return impl_->preserved_errno(); }
LogMessageFatal::LogMessageFatal(const char *file, int line) int
: LogMessage(file, line, TILE_FATAL) {} LogMessage::preserved_errno() const
{
return impl_->preserved_errno();
}
LogMessageFatal::LogMessageFatal(const char *file, int line) : LogMessage(file, line, TILE_FATAL) {}
LogMessageFatal::~LogMessageFatal() {} 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() : time_struct_(), timestamp_(0), usecs_(0), gmtoffset_(0) {}
LogMessageTime::LogMessageTime(std::tm t) : use_localtime_(true) { LogMessageTime::LogMessageTime(std::tm t) : use_localtime_(true)
{
std::time_t timestamp = std::mktime(&t); std::time_t timestamp = std::mktime(&t);
init(t, timestamp, 0); init(t, timestamp, 0);
} }
LogMessageTime::LogMessageTime(std::time_t timestamp, WallTime now) LogMessageTime::LogMessageTime(std::time_t timestamp, WallTime now) : use_localtime_(false)
: use_localtime_(false) { {
std::tm t; std::tm t;
if (use_localtime_) { if (use_localtime_) {
localtime_r(&timestamp, &t); localtime_r(&timestamp, &t);
@ -232,8 +280,9 @@ LogMessageTime::LogMessageTime(std::time_t timestamp, WallTime now)
init(t, timestamp, now); init(t, timestamp, now);
} }
LogMessageTime::LogMessageTime(std::chrono::system_clock::time_point tp)
: use_localtime_(false) { 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::time_t timestamp = std::chrono::system_clock::to_time_t(tp);
std::tm t; std::tm t;
if (use_localtime_) { if (use_localtime_) {
@ -243,14 +292,12 @@ LogMessageTime::LogMessageTime(std::chrono::system_clock::time_point tp)
} }
init(t, timestamp, 0); init(t, timestamp, 0);
usecs_ = std::chrono::duration_cast<std::chrono::microseconds>( usecs_ = std::chrono::duration_cast<std::chrono::microseconds>(tp.time_since_epoch()).count() % 1000000;
tp.time_since_epoch())
.count() %
1000000;
} }
void LogMessageTime::init(const std::tm &t, std::time_t timestamp, void
WallTime now) { LogMessageTime::init(const std::tm &t, std::time_t timestamp, WallTime now)
{
time_struct_ = t; time_struct_ = t;
timestamp_ = timestamp; timestamp_ = timestamp;
if (now < timestamp) { if (now < timestamp) {
@ -262,7 +309,9 @@ void LogMessageTime::init(const std::tm &t, std::time_t timestamp,
CalcGmtOffset(); CalcGmtOffset();
} }
void LogMessageTime::CalcGmtOffset() { void
LogMessageTime::CalcGmtOffset()
{
std::tm gmt_struct; std::tm gmt_struct;
int isDst = 0; int isDst = 0;
if (true) { if (true) {
@ -282,14 +331,15 @@ void LogMessageTime::CalcGmtOffset() {
} }
LogSink::~LogSink() {} LogSink::~LogSink() {}
bool LogSink::ShouldLog(LogSeverity severity) { return true; }
void LogSink::Send(LogSeverity severity, const char *full_filename, bool
const char *base_filename, int line, LogSink::ShouldLog(LogSeverity severity)
const LogMessageTime &logmsgtime, const char *message, {
size_t message_len) { return true;
}
void void
LogSink::send(LogSeverity severity, LogSink::Send(LogSeverity severity,
const char *full_filename, const char *full_filename,
const char *base_filename, const char *base_filename,
int line, int line,
@ -300,18 +350,24 @@ LogSink::send(LogSeverity severity,
// do nothing // do nothing
} }
void LogSink::Flush() {}
std::string LogSink::ToString(LogSeverity severity, const char *file, void
const char *base_filename, int line, LogSink::Flush()
{}
std::string
LogSink::ToString(LogSeverity severity,
const char *file,
const char *base_filename,
int line,
const LogMessageTime &logmsgtime, const LogMessageTime &logmsgtime,
const char *message, size_t message_len) { const char *message,
size_t message_len)
{
std::stringstream ss; std::stringstream ss;
char date_time[64]; char date_time[64];
sprintf(date_time, "%4d-%02d-%02dT%02d:%02d:%02d.%06d", sprintf(date_time, "%4d-%02d-%02dT%02d:%02d:%02d.%06d", logmsgtime.year() + 1900, logmsgtime.month(),
logmsgtime.year() + 1900, logmsgtime.month(), logmsgtime.day(), logmsgtime.day(), logmsgtime.hour(), logmsgtime.min(), logmsgtime.sec(), logmsgtime.usec());
logmsgtime.hour(), logmsgtime.min(), logmsgtime.sec(),
logmsgtime.usec());
ss << date_time; ss << date_time;
@ -333,63 +389,83 @@ std::string LogSink::ToString(LogSeverity severity, const char *file,
return ss.str(); return ss.str();
} }
static void ColoredWriteToStderrOrStdout(FILE *output, LogSeverity severity, static void
const char *message, size_t len) { ColoredWriteToStderrOrStdout(FILE *output, LogSeverity severity, const char *message, size_t len)
{
fwrite(message, len, 1, output); fwrite(message, len, 1, output);
fflush(output); fflush(output);
} }
void ColoredWriteToStdout(LogSeverity severity, const char *message, void
size_t len) { ColoredWriteToStdout(LogSeverity severity, const char *message, size_t len)
{
FILE *output = stdout; FILE *output = stdout;
if (severity >= TILE_FATAL) { if (severity >= TILE_FATAL) { output = stderr; }
output = stderr;
}
ColoredWriteToStderrOrStdout(output, severity, message, len); ColoredWriteToStderrOrStdout(output, severity, message, len);
} }
void ColoredWriteToStderr(LogSeverity severity, const char *message,
size_t len) { void
ColoredWriteToStderr(LogSeverity severity, const char *message, size_t len)
{
ColoredWriteToStderrOrStdout(stderr, severity, message, len); ColoredWriteToStderrOrStdout(stderr, severity, message, len);
} }
void AddLogSink(LogSink::Ptr dest) { void
AddLogSink(LogSink::Ptr dest)
{
std::lock_guard<std::mutex> _(g_sink_mutex); std::lock_guard<std::mutex> _(g_sink_mutex);
g_sinks.insert(dest); g_sinks.insert(dest);
g_sink_count.fetch_add(1); g_sink_count.fetch_add(1);
} }
void RemoveLogSink(LogSink::Ptr dest) { void
RemoveLogSink(LogSink::Ptr dest)
{
std::lock_guard<std::mutex> _(g_sink_mutex); std::lock_guard<std::mutex> _(g_sink_mutex);
g_sinks.erase(dest); g_sinks.erase(dest);
g_sink_count.fetch_sub(1); g_sink_count.fetch_sub(1);
} }
void SetStderrLogging(LogSeverity min_severity) {} void
void LogToStderr() {} SetStderrLogging(LogSeverity min_severity)
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
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); std::lock_guard<std::mutex> _(g_sink_mutex);
for (auto &&sink : g_sinks) { for (auto &&sink : g_sinks) {
if (sink->ShouldLog(severity)) { if (sink->ShouldLog(severity)) {
sink->Send(severity, full_filename, base_filename, line, time, message, sink->Send(severity, full_filename, base_filename, line, time, message, message_len);
message_len);
} }
} }
} }
void WaitForSinks() {
std::lock_guard<std::mutex> _(g_sink_mutex);
for (auto &&sink : g_sinks) {
sink->Flush();
}
}
const char *GetLogSeverityName(LogSeverity severity) { 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 = { const static std::map<LogSeverity, const char *> severity_names = {
{TILE_INFO, "INFO"}, {TILE_INFO, "INFO" },
{TILE_WARNING, "WARNING"}, {TILE_WARNING, "WARNING"},
{TILE_ERROR, "ERROR"}, {TILE_ERROR, "ERROR" },
{TILE_FATAL, "FATAL"}, {TILE_FATAL, "FATAL" },
}; };
auto iter = severity_names.find(severity); auto iter = severity_names.find(severity);
@ -400,4 +476,4 @@ const char *GetLogSeverityName(LogSeverity severity) {
} }
} }
} // namespace tile }// namespace tile

View File

@ -35,28 +35,35 @@ 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; } int_type overflow(int_type ch) { return ch; }
size_t pcount() const { return static_cast<size_t>(pptr() - pbase()); } size_t pcount() const { return static_cast<size_t>(pptr() - pbase()); }
char *pbase() const { return std::streambuf::pbase(); } char *pbase() const { return std::streambuf::pbase(); }
}; };
class LogSink; class LogSink;
class LogMessageTime; class LogMessageTime;
class LogMessage { class LogMessage {
public: public:
class LogStream : public std::ostream { class LogStream : public std::ostream {
public: public:
LogStream(char *buf, int len, int64_t ctr) LogStream(char *buf, int len, int64_t ctr) : std::ostream(nullptr), streambuf_(buf, len), ctr_(ctr), self_(this)
: std::ostream(nullptr), streambuf_(buf, len), ctr_(ctr), self_(this) { {
rdbuf(&streambuf_); rdbuf(&streambuf_);
} }
LogStream(LogStream &other) noexcept LogStream(LogStream &other) noexcept
: std::ostream(nullptr), streambuf_(std::move(other.streambuf_)), : std::ostream(nullptr),
ctr_(internal::Exchange(other.ctr_, 0)), self_(this) { streambuf_(std::move(other.streambuf_)),
ctr_(internal::Exchange(other.ctr_, 0)),
self_(this)
{
rdbuf(&streambuf_); rdbuf(&streambuf_);
} }
LogStream &operator=(LogStream &&other) noexcept { LogStream &operator=(LogStream &&other) noexcept
{
streambuf_ = std::move(other.streambuf_); streambuf_ = std::move(other.streambuf_);
ctr_ = internal::Exchange(other.ctr_, 0); ctr_ = internal::Exchange(other.ctr_, 0);
self_ = this; self_ = this;
@ -65,12 +72,15 @@ public:
} }
int64_t ctr() const { return ctr_; } int64_t ctr() const { return ctr_; }
void set_ctr(int64_t ctr) { ctr_ = ctr; } void set_ctr(int64_t ctr) { ctr_ = ctr; }
LogStream *self() { return self_; } LogStream *self() { return self_; }
size_t pcount() const { return streambuf_.pcount(); } size_t pcount() const { return streambuf_.pcount(); }
char *pbase() const { return streambuf_.pbase(); } char *pbase() const { return streambuf_.pbase(); }
char *str() const { return pbase(); } char *str() const { return pbase(); }
LogStream(const LogStream &) = delete; LogStream(const LogStream &) = delete;
@ -86,8 +96,7 @@ public:
static const size_t kMaxLogMessageLen = 30000; static const size_t kMaxLogMessageLen = 30000;
LogMessage(const char *file, int line); LogMessage(const char *file, int line);
LogMessage(const char *file, int line, LogSeverity severity); LogMessage(const char *file, int line, LogSeverity severity);
LogMessage(const char *file, int line, LogSeverity severity, LogSink *sink, LogMessage(const char *file, int line, LogSeverity severity, LogSink *sink, bool also_send_to_log = true);
bool also_send_to_log = true);
~LogMessage(); ~LogMessage();
std::ostream &stream(); std::ostream &stream();
@ -550,6 +559,7 @@ FormatLog(const char *file, int line, Ts &&...args) noexcept
namespace tile { namespace tile {
typedef double WallTime; typedef double WallTime;
struct LogMessageTime { struct LogMessageTime {
LogMessageTime(); LogMessageTime();
LogMessageTime(std::tm t); LogMessageTime(std::tm t);
@ -557,23 +567,36 @@ struct LogMessageTime {
LogMessageTime(std::chrono::system_clock::time_point tp); LogMessageTime(std::chrono::system_clock::time_point tp);
const time_t &timestamp() const { return timestamp_; } const time_t &timestamp() const { return timestamp_; }
const int &sec() const { return time_struct_.tm_sec; } const int &sec() const { return time_struct_.tm_sec; }
const int32_t &usec() const { return usecs_; } const int32_t &usec() const { return usecs_; }
const int &(min)() const { return time_struct_.tm_min; }
const int &(min) () const { return time_struct_.tm_min; }
const int &hour() const { return time_struct_.tm_hour; } const int &hour() const { return time_struct_.tm_hour; }
const int &day() const { return time_struct_.tm_mday; } const int &day() const { return time_struct_.tm_mday; }
const int &month() const { return time_struct_.tm_mon; } const int &month() const { return time_struct_.tm_mon; }
const int &year() const { return time_struct_.tm_year; } const int &year() const { return time_struct_.tm_year; }
const int &dayOfWeek() const { return time_struct_.tm_wday; } const int &dayOfWeek() const { return time_struct_.tm_wday; }
const int &dayInYear() const { return time_struct_.tm_yday; } const int &dayInYear() const { return time_struct_.tm_yday; }
const int &dst() const { return time_struct_.tm_isdst; } const int &dst() const { return time_struct_.tm_isdst; }
const long int &gmtoff() const { return gmtoffset_; } const long int &gmtoff() const { return gmtoffset_; }
const std::tm &tm() const { return time_struct_; } const std::tm &tm() const { return time_struct_; }
const bool use_localtime() const { return use_localtime_; } const bool use_localtime() const { return use_localtime_; }
private: private:
void init(const std::tm &t, std::time_t timestamp, WallTime now); void init(const std::tm &t, std::time_t timestamp, WallTime now);
std::tm time_struct_; // Time of creation of LogMessage std::tm time_struct_;// Time of creation of LogMessage
time_t timestamp_; // Time of creation of LogMessage in seconds time_t timestamp_; // Time of creation of LogMessage in seconds
int32_t usecs_; // Time of creation of LogMessage - microseconds part int32_t usecs_; // Time of creation of LogMessage - microseconds part
long int gmtoffset_; long int gmtoffset_;
@ -588,28 +611,36 @@ public:
virtual ~LogSink(); virtual ~LogSink();
virtual bool ShouldLog(LogSeverity severity); virtual bool ShouldLog(LogSeverity severity);
virtual void Send(LogSeverity severity, const char *full_filename, virtual void Send(LogSeverity severity,
const char *base_filename, int line, const char *full_filename,
const LogMessageTime &logmsgtime, const char *message, const char *base_filename,
int line,
const LogMessageTime &logmsgtime,
const char *message,
size_t message_len); size_t message_len);
virtual void Flush(); virtual void Flush();
std::string ToString(LogSeverity severity, const char *file, std::string ToString(LogSeverity severity,
const char *base_file, int line, const char *file,
const LogMessageTime &logmsgtime, const char *message, const char *base_file,
int line,
const LogMessageTime &logmsgtime,
const char *message,
size_t message_len); size_t message_len);
}; };
void ColoredWriteToStdout(LogSeverity severity, const char *message, void ColoredWriteToStdout(LogSeverity severity, const char *message, size_t len);
size_t len); void ColoredWriteToStderr(LogSeverity severity, const char *message, size_t len);
void ColoredWriteToStderr(LogSeverity severity, const char *message,
size_t len);
void AddLogSink(LogSink::Ptr dest); void AddLogSink(LogSink::Ptr dest);
void RemoveLogSink(LogSink::Ptr dest); void RemoveLogSink(LogSink::Ptr dest);
void SetStderrLogging(LogSeverity min_severity); void SetStderrLogging(LogSeverity min_severity);
void LogToStderr(); void LogToStderr();
void LogToSinks(LogSeverity severity, const char *full_filename, void LogToSinks(LogSeverity severity,
const char *base_filename, int line, const LogMessageTime &time, const char *full_filename,
const char *message, size_t message_len); const char *base_filename,
int line,
const LogMessageTime &time,
const char *message,
size_t message_len);
void WaitForSinks(); void WaitForSinks();
const char *GetLogSeverityName(LogSeverity severity); const char *GetLogSeverityName(LogSeverity severity);

View File

@ -6,10 +6,16 @@
#include <mutex> #include <mutex>
namespace tile { namespace tile {
bool VLogIsOn(int n) { return true; } bool
VLogIsOn(int n)
{
return true;
}
class LogMessage::Impl { class LogMessage::Impl {
public: public:
Impl(const char *file, int line, int severity) : lm_(file, line, severity) {} Impl(const char *file, int line, int severity) : lm_(file, line, severity) {}
std::ostream &stream() { return lm_.stream(); } std::ostream &stream() { return lm_.stream(); }
private: private:
@ -19,65 +25,87 @@ private:
class LogMessageFatal::Impl { class LogMessageFatal::Impl {
public: public:
Impl(const char *file, int line) : lm_(file, line) {} Impl(const char *file, int line) : lm_(file, line) {}
std::ostream &stream() { return lm_.stream(); } std::ostream &stream() { return lm_.stream(); }
private: private:
google::LogMessageFatal lm_; google::LogMessageFatal lm_;
}; };
LogMessage::LogMessage(const char *file, int line, int severity) LogMessage::LogMessage(const char *file, int line, int severity) : impl_(new Impl(file, line, severity)) {}
: impl_(new Impl(file, line, severity)) {}
LogMessage::~LogMessage() = default; LogMessage::~LogMessage() = default;
std::ostream &LogMessage::stream() { return impl_->stream(); }
LogMessageFatal::LogMessageFatal(const char *file, int line) std::ostream &
: impl_(new Impl(file, line)) {} LogMessage::stream()
{
return impl_->stream();
}
LogMessageFatal::LogMessageFatal(const char *file, int line) : impl_(new Impl(file, line)) {}
LogMessageFatal::~LogMessageFatal() = default; LogMessageFatal::~LogMessageFatal() = default;
std::ostream &LogMessageFatal::stream() { return impl_->stream(); }
} // namespace tile std::ostream &
LogMessageFatal::stream()
{
return impl_->stream();
}
}// namespace tile
namespace tile { namespace tile {
namespace internal { namespace internal {
namespace logging { namespace logging {
namespace { namespace {
std::vector<PrefixAppender *> *GetProviers() { std::vector<PrefixAppender *> *
GetProviers()
{
static std::vector<PrefixAppender *> providers; static std::vector<PrefixAppender *> providers;
return &providers; return &providers;
} }
} // namespace }// namespace
namespace details { namespace details {
std::string DescribeFormatArguments(const std::vector<std::string> &args) { std::string
DescribeFormatArguments(const std::vector<std::string> &args)
{
return fmt::format("{}", fmt::join(args.begin(), args.end(), ", ")); return fmt::format("{}", fmt::join(args.begin(), args.end(), ", "));
} }
} // namespace details }// namespace details
void InstallPrefixProvider(PrefixAppender *writer) {
void
InstallPrefixProvider(PrefixAppender *writer)
{
GetProviers()->push_back(writer); GetProviers()->push_back(writer);
} }
void WritePrefixTo(std::string *to) {
void
WritePrefixTo(std::string *to)
{
for (auto &&appender : *GetProviers()) { for (auto &&appender : *GetProviers()) {
auto was = to->size(); auto was = to->size();
appender(to); appender(to);
if (to->size() != was) { if (to->size() != was) { to->push_back(' '); }
to->push_back(' ');
}
} }
} }
} // namespace logging }// namespace logging
} // namespace internal }// namespace internal
} // namespace tile }// namespace tile
namespace tile { namespace tile {
LogMessageTime::LogMessageTime() LogMessageTime::LogMessageTime() : time_struct_(), timestamp_(0), usecs_(0), gmtoffset_(0) {}
: time_struct_(), timestamp_(0), usecs_(0), gmtoffset_(0) {}
LogMessageTime::LogMessageTime(std::tm t) { LogMessageTime::LogMessageTime(std::tm t)
{
std::time_t timestamp = std::mktime(&t); std::time_t timestamp = std::mktime(&t);
init(t, timestamp, 0); init(t, timestamp, 0);
} }
LogMessageTime::LogMessageTime(std::time_t timestamp, WallTime now) { LogMessageTime::LogMessageTime(std::time_t timestamp, WallTime now)
{
std::tm t; std::tm t;
if (FLAGS_log_utc_time) if (FLAGS_log_utc_time)
gmtime_r(&timestamp, &t); gmtime_r(&timestamp, &t);
@ -86,8 +114,9 @@ LogMessageTime::LogMessageTime(std::time_t timestamp, WallTime now) {
init(t, timestamp, now); init(t, timestamp, now);
} }
void LogMessageTime::init(const std::tm &t, std::time_t timestamp, void
WallTime now) { LogMessageTime::init(const std::tm &t, std::time_t timestamp, WallTime now)
{
time_struct_ = t; time_struct_ = t;
timestamp_ = timestamp; timestamp_ = timestamp;
usecs_ = static_cast<std::int32_t>((now - timestamp) * 1000000); usecs_ = static_cast<std::int32_t>((now - timestamp) * 1000000);
@ -95,7 +124,9 @@ void LogMessageTime::init(const std::tm &t, std::time_t timestamp,
CalcGmtOffset(); CalcGmtOffset();
} }
void LogMessageTime::CalcGmtOffset() { void
LogMessageTime::CalcGmtOffset()
{
std::tm gmt_struct; std::tm gmt_struct;
int isDst = 0; int isDst = 0;
if (FLAGS_log_utc_time) { if (FLAGS_log_utc_time) {
@ -111,36 +142,54 @@ void LogMessageTime::CalcGmtOffset() {
const long hour_secs = 3600; const long hour_secs = 3600;
// If the Daylight Saving Time(isDst) is active subtract an hour from the // If the Daylight Saving Time(isDst) is active subtract an hour from the
// current timestamp. // current timestamp.
gmtoffset_ = gmtoffset_ = static_cast<long int>(timestamp_ - gmt_sec + (isDst ? hour_secs : 0));
static_cast<long int>(timestamp_ - gmt_sec + (isDst ? hour_secs : 0));
} }
LogSink::~LogSink() {} LogSink::~LogSink() {}
void LogSink::send(LogSeverity severity, const char *full_filename,
const char *base_filename, int line, void
const LogMessageTime &logmsgtime, const char *message, LogSink::send(LogSeverity severity,
size_t message_len) { const char *full_filename,
const char *base_filename,
int line,
const LogMessageTime &logmsgtime,
const char *message,
size_t message_len)
{
// do nothing // do nothing
} }
void LogSink::WaitTillSent() {}
std::string LogSink::ToString(LogSeverity severity, const char *file, int line, void
LogSink::WaitTillSent()
{}
std::string
LogSink::ToString(LogSeverity severity,
const char *file,
int line,
const LogMessageTime &logmsgtime, const LogMessageTime &logmsgtime,
const char *message, size_t message_len) { const char *message,
return google::LogSink::ToString(severity, file, line, logmsgtime.tm(), size_t message_len)
message, message_len); {
return google::LogSink::ToString(severity, file, line, logmsgtime.tm(), message, message_len);
} }
class LogSinkWrapper : public google::LogSink { class LogSinkWrapper : public google::LogSink {
public: public:
LogSinkWrapper(tile::LogSink *dest) : dest_(dest) {} LogSinkWrapper(tile::LogSink *dest) : dest_(dest) {}
~LogSinkWrapper() override {} ~LogSinkWrapper() override {}
void send(LogSeverity severity, const char *full_filename,
const char *base_filename, int line, void send(LogSeverity severity,
const google::LogMessageTime &logmsgtime, const char *message, const char *full_filename,
size_t message_len) override { const char *base_filename,
dest_->send(severity, full_filename, base_filename, line, logmsgtime.tm(), int line,
message, message_len); 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(); } void WaitTillSent() override { dest_->WaitTillSent(); }
@ -157,18 +206,20 @@ struct LogSinkPair {
static std::map<LogSink *, LogSinkWrapper *> sink_registry; static std::map<LogSink *, LogSinkWrapper *> sink_registry;
static std::mutex sink_registry_mutex; static std::mutex sink_registry_mutex;
void AddLogSink(LogSink *dest) { void
AddLogSink(LogSink *dest)
{
std::lock_guard<std::mutex> lock(sink_registry_mutex); std::lock_guard<std::mutex> lock(sink_registry_mutex);
if (sink_registry.find(dest) != sink_registry.end()) { if (sink_registry.find(dest) != sink_registry.end()) { return; }
return;
}
auto wrapper = new LogSinkWrapper(dest); auto wrapper = new LogSinkWrapper(dest);
sink_registry[dest] = wrapper; sink_registry[dest] = wrapper;
google::AddLogSink(wrapper); google::AddLogSink(wrapper);
} }
void RemoveLogSink(LogSink *dest) { void
RemoveLogSink(LogSink *dest)
{
std::lock_guard<std::mutex> lock(sink_registry_mutex); std::lock_guard<std::mutex> lock(sink_registry_mutex);
auto iter = sink_registry.find(dest); auto iter = sink_registry.find(dest);
if (iter != sink_registry.end()) { if (iter != sink_registry.end()) {
@ -177,11 +228,22 @@ void RemoveLogSink(LogSink *dest) {
delete iter->second; delete iter->second;
} }
} }
void SetStderrLogging(LogSeverity min_severity) {
void
SetStderrLogging(LogSeverity min_severity)
{
google::SetStderrLogging(min_severity); google::SetStderrLogging(min_severity);
} }
void LogToStderr() { google::LogToStderr(); }
const char *GetLogSeverityName(LogSeverity severity) { void
LogToStderr()
{
google::LogToStderr();
}
const char *
GetLogSeverityName(LogSeverity severity)
{
return google::GetLogSeverityName(severity); return google::GetLogSeverityName(severity);
} }
} // namespace tile }// namespace tile

View File

@ -9,17 +9,31 @@
#include <thread> #include <thread>
struct AwesomeLogSink : public tile::LogSink { struct AwesomeLogSink : public tile::LogSink {
virtual void Send(tile::LogSeverity severity, const char *full_filename, static std::shared_ptr<AwesomeLogSink> Create() { return std::make_shared<AwesomeLogSink>(); }
const char *base_filename, int line,
const tile::LogMessageTime &logmsgtime, const char *message, virtual void Send(tile::LogSeverity severity,
size_t message_len) override { 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)); msgs.emplace_back(std::string(message, message_len));
} }
std::vector<std::string> msgs; std::vector<std::string> msgs;
}; };
std::string my_prefix, my_prefix2; std::string my_prefix, my_prefix2;
void
ResetLogPrefix()
{
my_prefix.clear();
my_prefix2.clear();
}
void void
WriteLoggingPrefix(std::string *s) WriteLoggingPrefix(std::string *s)
{ {
@ -32,7 +46,8 @@ WriteLoggingPrefix2(std::string *s)
*s += my_prefix2; *s += my_prefix2;
} }
TEST(Logging, Prefix) { TEST(Logging, Prefix)
{
auto sink = std::make_shared<AwesomeLogSink>(); auto sink = std::make_shared<AwesomeLogSink>();
tile::AddLogSink(sink); tile::AddLogSink(sink);
tile::ScopedDeferred defered([&] { tile::RemoveLogSink(sink); }); tile::ScopedDeferred defered([&] { tile::RemoveLogSink(sink); });
@ -49,9 +64,8 @@ TEST(Logging, Prefix) {
TILE_LOG_INFO("something"); TILE_LOG_INFO("something");
ASSERT_THAT(sink->msgs, ASSERT_THAT(sink->msgs,
::testing::ElementsAre("something", "[prefix] something", ::testing::ElementsAre(
"[prefix1] something", "something", "[prefix] something", "[prefix1] something", "[prefix1] [prefix2] something"));
"[prefix1] [prefix2] something"));
} }
TEST(Logging, CHECK) TEST(Logging, CHECK)
@ -65,13 +79,13 @@ TEST(Logging, CHECK)
ASSERT_DEATH(([] { TILE_CHECK_NE(1, 1, "CHECK_NE"); }()), "CHECK_NE"); ASSERT_DEATH(([] { TILE_CHECK_NE(1, 1, "CHECK_NE"); }()), "CHECK_NE");
} }
TEST(Logging, Prefix) TEST(Logging, DontPanicOnFormatFailure) { TILE_LOG_INFO("Don't panic!{}{}", 1); }
{
AwesomeLogSink sink;
tile::AddLogSink(&sink);
tile::ScopedDeferred defered([&] { tile::RemoveLogSink(&sink); });
auto sink = std::make_shared<AwesomeLogSink>(); TEST(Logging, EverySecond)
{
ResetLogPrefix();
auto sink = AwesomeLogSink::Create();
tile::AddLogSink(sink); tile::AddLogSink(sink);
tile::ScopedDeferred defered([&] { tile::RemoveLogSink(sink); }); tile::ScopedDeferred defered([&] { tile::RemoveLogSink(sink); });
for (int i = 0; i < 30; i++) { for (int i = 0; i < 30; i++) {
@ -79,25 +93,7 @@ TEST(Logging, Prefix)
std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::this_thread::sleep_for(std::chrono::milliseconds(100));
} }
ASSERT_THAT(sink->msgs, ASSERT_THAT(sink->msgs, ::testing::ElementsAre("something", "something", "something"));
::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); });
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, Enum) TEST(Logging, Enum)

View File

@ -1,24 +1,47 @@
#include "tile/base/logging/basic_file_sink.h" #include "tile/base/logging/basic_file_sink.h"
namespace tile { namespace tile {
BasicFileSink::Ptr BasicFileSink::Create(const std::string &filepath) { BasicFileSink::Ptr
BasicFileSink::Create(const std::string &filepath)
{
auto sink = std::shared_ptr<BasicFileSink>(new BasicFileSink()); auto sink = std::shared_ptr<BasicFileSink>(new BasicFileSink());
sink->set_filepath(filepath); sink->set_filepath(filepath);
return sink; return sink;
} }
BasicFileSink::BasicFileSink() {} BasicFileSink::BasicFileSink() {}
BasicFileSink::~BasicFileSink() {} BasicFileSink::~BasicFileSink() {}
void BasicFileSink::Send(LogSeverity severity, const char *full_filename,
const char *base_filename, int line, void
const LogMessageTime &logmsgtime, const char *message, BasicFileSink::Send(LogSeverity severity,
size_t message_len) { 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"); TILE_CHECK(!filepath_.empty(), "filepath is empty");
ofs_ << std::string(message, message_len) << std::endl; ofs_ << std::string(message, message_len) << std::endl;
} }
std::string BasicFileSink::filepath() const { return filepath_; }
void BasicFileSink::set_filepath(const std::string &filepath) { std::string
BasicFileSink::filepath() const
{
return filepath_;
}
void
BasicFileSink::set_filepath(const std::string &filepath)
{
filepath_ = filepath; filepath_ = filepath;
ofs_.open(filepath, std::ios::out | std::ios::app); ofs_.open(filepath, std::ios::out | std::ios::app);
} }
void BasicFileSink::Flush() { ofs_.flush(); }
} // namespace tile void
BasicFileSink::Flush()
{
ofs_.flush();
}
}// namespace tile

View File

@ -14,9 +14,12 @@ public:
static Ptr Create(const std::string &filepath); static Ptr Create(const std::string &filepath);
~BasicFileSink() override; ~BasicFileSink() override;
void Send(LogSeverity severity, const char *full_filename, void Send(LogSeverity severity,
const char *base_filename, int line, const char *full_filename,
const LogMessageTime &logmsgtime, const char *message, const char *base_filename,
int line,
const LogMessageTime &logmsgtime,
const char *message,
size_t message_len) override; size_t message_len) override;
void Flush() override; void Flush() override;
@ -31,6 +34,6 @@ private:
std::ofstream ofs_; std::ofstream ofs_;
}; };
} // namespace tile }// namespace tile
#endif // TILE_BASE_LOGGING_BASIC_FILE_SINK_H #endif// TILE_BASE_LOGGING_BASIC_FILE_SINK_H

View File

@ -1,23 +1,28 @@
#include "tile/base/logging/console_sink.h" #include "tile/base/logging/console_sink.h"
#include <stdio.h> #include <stdio.h>
namespace tile { namespace tile {
ConsoleSink::Ptr ConsoleSink::Create() { ConsoleSink::Ptr
ConsoleSink::Create()
{
return std::shared_ptr<ConsoleSink>(new ConsoleSink()); return std::shared_ptr<ConsoleSink>(new ConsoleSink());
} }
ConsoleSink::~ConsoleSink() {} ConsoleSink::~ConsoleSink() {}
void ConsoleSink::Send(LogSeverity severity, const char *full_filename, void
const char *base_filename, int line, ConsoleSink::Send(LogSeverity severity,
const LogMessageTime &logmsgtime, const char *message, const char *full_filename,
size_t message_len) { const char *base_filename,
auto msg = ToString(severity, full_filename, base_filename, line, logmsgtime, int line,
message, message_len); const LogMessageTime &logmsgtime,
while (!msg.empty() && msg.back() == '\n') { const char *message,
msg.pop_back(); 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) { if (severity >= TILE_FATAL) {
fprintf(stderr, "%s\n", msg.c_str()); fprintf(stderr, "%s\n", msg.c_str());
} else { } else {
@ -25,8 +30,10 @@ void ConsoleSink::Send(LogSeverity severity, const char *full_filename,
} }
} }
void ConsoleSink::Flush() {} void
ConsoleSink::Flush()
{}
ConsoleSink::ConsoleSink() {} ConsoleSink::ConsoleSink() {}
} // namespace tile }// namespace tile

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include "tile/base/internal/logging.h" #include "tile/base/internal/logging.h"
namespace tile { namespace tile {
class ConsoleSink : public LogSink { class ConsoleSink : public LogSink {
public: public:
@ -11,15 +12,18 @@ public:
static Ptr Create(); static Ptr Create();
~ConsoleSink() override; ~ConsoleSink() override;
void Send(LogSeverity severity, const char *full_filename, void Send(LogSeverity severity,
const char *base_filename, int line, const char *full_filename,
const LogMessageTime &logmsgtime, const char *message, const char *base_filename,
int line,
const LogMessageTime &logmsgtime,
const char *message,
size_t message_len) override; size_t message_len) override;
void Flush() override; void Flush() override;
protected: protected:
ConsoleSink(); ConsoleSink();
}; };
} // namespace tile }// namespace tile
#endif // TILE_BASE_LOGGING_CONSOLE_SINK_H #endif// TILE_BASE_LOGGING_CONSOLE_SINK_H

View File

@ -2,62 +2,78 @@
#include <cassert> #include <cassert>
namespace tile { namespace tile {
std::shared_ptr<SplitterSink> SplitterSink::Create() { std::shared_ptr<SplitterSink>
SplitterSink::Create()
{
return std::shared_ptr<SplitterSink>(new SplitterSink()); return std::shared_ptr<SplitterSink>(new SplitterSink());
} }
std::shared_ptr<SplitterSink> SplitterSink::Create( std::shared_ptr<SplitterSink>
std::initializer_list<std::shared_ptr<LogSink>> init_list) { SplitterSink::Create(std::initializer_list<std::shared_ptr<LogSink>> init_list)
{
auto sink = Create(); auto sink = Create();
for (auto &s : init_list) { for (auto &s : init_list) { sink->AddSink(s); }
sink->AddSink(s);
}
return sink; return sink;
} }
SplitterSink::SplitterSink() {} SplitterSink::SplitterSink() {}
SplitterSink::~SplitterSink() {} SplitterSink::~SplitterSink() {}
void SplitterSink::Send(LogSeverity severity, const char *full_filename,
const char *base_filename, int line, void
const LogMessageTime &logmsgtime, const char *message, SplitterSink::Send(LogSeverity severity,
size_t message_len) { 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"); assert(!doing_ && "SplitterSink::send() should not be called recursively");
std::lock_guard<std::mutex> _(sinks_mutex_); std::lock_guard<std::mutex> _(sinks_mutex_);
doing_ = true; doing_ = true;
for (auto &sink : sinks_) { for (auto &sink : sinks_) {
sink->Send(severity, full_filename, base_filename, line, logmsgtime, sink->Send(severity, full_filename, base_filename, line, logmsgtime, message, message_len);
message, message_len);
} }
doing_ = false; doing_ = false;
} }
void SplitterSink::Flush() { void
SplitterSink::Flush()
{
assert(!doing_ && "SplitterSink::send() should not be called recursively"); assert(!doing_ && "SplitterSink::send() should not be called recursively");
std::lock_guard<std::mutex> _(sinks_mutex_); std::lock_guard<std::mutex> _(sinks_mutex_);
doing_ = true; doing_ = true;
for (auto &sink : sinks_) { for (auto &sink : sinks_) { sink->Flush(); }
sink->Flush();
}
doing_ = false; doing_ = false;
} }
void SplitterSink::AddSink(std::shared_ptr<LogSink> sink) { void
SplitterSink::AddSink(std::shared_ptr<LogSink> sink)
{
std::lock_guard<std::mutex> _(sinks_mutex_); std::lock_guard<std::mutex> _(sinks_mutex_);
sinks_.insert(sink); sinks_.insert(sink);
} }
void SplitterSink::RemoveSink(std::shared_ptr<LogSink> sink) { void
SplitterSink::RemoveSink(std::shared_ptr<LogSink> sink)
{
std::lock_guard<std::mutex> _(sinks_mutex_); std::lock_guard<std::mutex> _(sinks_mutex_);
sinks_.erase(sink); sinks_.erase(sink);
} }
void SplitterSink::ClearSinks() { void
SplitterSink::ClearSinks()
{
std::lock_guard<std::mutex> _(sinks_mutex_); std::lock_guard<std::mutex> _(sinks_mutex_);
sinks_.clear(); sinks_.clear();
} }
std::set<LogSink::Ptr> SplitterSink::sinks() {
std::set<LogSink::Ptr>
SplitterSink::sinks()
{
std::lock_guard<std::mutex> _(sinks_mutex_); std::lock_guard<std::mutex> _(sinks_mutex_);
return sinks_; return sinks_;
} }
} // namespace tile }// namespace tile

View File

@ -16,9 +16,12 @@ public:
~SplitterSink() override; ~SplitterSink() override;
void Send(LogSeverity severity, const char *full_filename, void Send(LogSeverity severity,
const char *base_filename, int line, const char *full_filename,
const LogMessageTime &logmsgtime, const char *message, const char *base_filename,
int line,
const LogMessageTime &logmsgtime,
const char *message,
size_t message_len) override; size_t message_len) override;
void Flush() override; void Flush() override;
@ -35,6 +38,6 @@ private:
std::mutex sinks_mutex_; std::mutex sinks_mutex_;
bool doing_ = false; bool doing_ = false;
}; };
} // namespace tile }// namespace tile
#endif // TILE_BASE_LOGGING_SPLITTER_SINK_H #endif// TILE_BASE_LOGGING_SPLITTER_SINK_H

View File

@ -5,52 +5,56 @@ namespace tile {
class SimpleSink : public LogSink { class SimpleSink : public LogSink {
public: public:
using Ptr = std::shared_ptr<SimpleSink>; using Ptr = std::shared_ptr<SimpleSink>;
static Ptr Create() { return std::shared_ptr<SimpleSink>(new 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, void Send(LogSeverity severity,
const LogMessageTime &logmsgtime, const char *message, const char *full_filename,
size_t message_len) override { const char *base_filename,
int line,
const LogMessageTime &logmsgtime,
const char *message,
size_t message_len) override
{
message_ = std::string(message, message_len); message_ = std::string(message, message_len);
} }
void Flush() override {} void Flush() override {}
std::string message_; std::string message_;
}; };
TEST(SplitterSink, One) { TEST(SplitterSink, One)
{
auto sink = SimpleSink::Create(); auto sink = SimpleSink::Create();
auto splitter = SplitterSink::Create({sink}); auto splitter = SplitterSink::Create({sink});
splitter->Send(LogSeverity::TILE_INFO, nullptr, nullptr, 0, LogMessageTime(), splitter->Send(LogSeverity::TILE_INFO, nullptr, nullptr, 0, LogMessageTime(), "message", 7);
"message", 7);
ASSERT_EQ(sink->message_, "message"); ASSERT_EQ(sink->message_, "message");
} }
TEST(SplitterSink, Two) { TEST(SplitterSink, Two)
{
auto sink1 = SimpleSink::Create(); auto sink1 = SimpleSink::Create();
auto sink2 = SimpleSink::Create(); auto sink2 = SimpleSink::Create();
auto splitter = SplitterSink::Create({sink1, sink2}); auto splitter = SplitterSink::Create({sink1, sink2});
splitter->Send(LogSeverity::TILE_INFO, nullptr, nullptr, 0, LogMessageTime(), splitter->Send(LogSeverity::TILE_INFO, nullptr, nullptr, 0, LogMessageTime(), "message", 7);
"message", 7);
ASSERT_EQ(sink1->message_, "message"); ASSERT_EQ(sink1->message_, "message");
ASSERT_EQ(sink2->message_, "message"); ASSERT_EQ(sink2->message_, "message");
} }
TEST(SplitterSink, Multi) { TEST(SplitterSink, Multi)
{
auto splitter = SplitterSink::Create(); auto splitter = SplitterSink::Create();
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) { splitter->AddSink(SimpleSink::Create()); }
splitter->AddSink(SimpleSink::Create());
}
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
std::stringstream ss; std::stringstream ss;
ss << "message" << i; ss << "message" << i;
auto msg = ss.str(); auto msg = ss.str();
splitter->Send(LogSeverity::TILE_INFO, nullptr, nullptr, 0, splitter->Send(LogSeverity::TILE_INFO, nullptr, nullptr, 0, LogMessageTime(), msg.data(), msg.size());
LogMessageTime(), msg.data(), msg.size());
for (auto &sink : splitter->sinks()) { for (auto &sink : splitter->sinks()) { ASSERT_EQ(std::static_pointer_cast<SimpleSink>(sink)->message_, msg); }
ASSERT_EQ(std::static_pointer_cast<SimpleSink>(sink)->message_, msg);
}
} }
} }
} // namespace tile }// namespace tile

View File

@ -32,7 +32,9 @@ namespace {
std::atomic<bool> g_quit_siganl{false}; std::atomic<bool> g_quit_siganl{false};
void QuitSignalHandler(int sig) { void
QuitSignalHandler(int sig)
{
auto old = g_quit_siganl.exchange(true, std::memory_order_relaxed); auto old = g_quit_siganl.exchange(true, std::memory_order_relaxed);
if (old && FLAGS_tile_abort_on_double_quit_signal) { if (old && FLAGS_tile_abort_on_double_quit_signal) {
// TODO: Add TILE_RAW_LOG // TODO: Add TILE_RAW_LOG
@ -52,8 +54,9 @@ InstallQuitSignalHandler()
} }
}// namespace }// namespace
int Start(int argc, char **argv, std::function<int(int, char **)> cb, int
bool single_thread, bool enable_crash_catch) { Start(int argc, char **argv, std::function<int(int, char **)> cb, bool single_thread, bool enable_crash_catch)
{
if (enable_crash_catch) { if (enable_crash_catch) {
// TODO: Add InstallFailureSignalHandler // TODO: Add InstallFailureSignalHandler
// google::InstallFailureSignalHandler(); // google::InstallFailureSignalHandler();

View File

@ -10,18 +10,20 @@ namespace tile {
namespace testing { namespace testing {
namespace { namespace {
int StartBenchmark(int argc, char **argv) { int
StartBenchmark(int argc, char **argv)
{
::benchmark::Initialize(&argc, argv); ::benchmark::Initialize(&argc, argv);
if (::benchmark::ReportUnrecognizedArguments(argc, argv)) { if (::benchmark::ReportUnrecognizedArguments(argc, argv)) { return 1; }
return 1;
}
::benchmark::RunSpecifiedBenchmarks(); ::benchmark::RunSpecifiedBenchmarks();
::benchmark::Shutdown(); ::benchmark::Shutdown();
return 0; return 0;
} }
} // namespace }// namespace
int InitAndRunAllBenchmarks(int *argc, char **argv) { int
InitAndRunAllBenchmarks(int *argc, char **argv)
{
// if (gflags::GetCommandLineFlagInfoOrDie("logtostderr").is_default) { // if (gflags::GetCommandLineFlagInfoOrDie("logtostderr").is_default) {
// FLAGS_logtostderr = true; // FLAGS_logtostderr = true;
@ -30,7 +32,7 @@ int InitAndRunAllBenchmarks(int *argc, char **argv) {
return Start(*argc, argv, StartBenchmark, true); return Start(*argc, argv, StartBenchmark, true);
} }
} // namespace testing }// namespace testing
} // namespace tile }// namespace tile
TILE_BENCHMARK_MAIN TILE_BENCHMARK_MAIN