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,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&;

View File

@ -174,9 +174,8 @@ private:
{"1s", 1}
};
for (auto &&item : m) {}
return result;
}
return result;
}
void LinkToParent(Slice rel_path, ExposedVarGroup *parent)
{

View File

@ -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(&timestamp, &t);
} else {
gmtime_r(&timestamp, &t);
}
LogMessageTime::LogMessageTime(std::time_t timestamp, WallTime now) : use_localtime_(false)
{
std::tm t;
if (use_localtime_) {
localtime_r(&timestamp, &t);
} else {
gmtime_r(&timestamp, &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(&timestamp, &t);
} else {
gmtime_r(&timestamp, &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(&timestamp, &t);
} else {
gmtime_r(&timestamp, &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(&timestamp_, &gmt_struct);
isDst = gmt_struct.tm_isdst;
gmt_struct = time_struct_;
} else {
isDst = time_struct_.tm_isdst;
gmtime_r(&timestamp_, &gmt_struct);
}
void
LogMessageTime::CalcGmtOffset()
{
std::tm gmt_struct;
int isDst = 0;
if (true) {
localtime_r(&timestamp_, &gmt_struct);
isDst = gmt_struct.tm_isdst;
gmt_struct = time_struct_;
} else {
isDst = time_struct_.tm_isdst;
gmtime_r(&timestamp_, &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

View File

@ -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 &timestamp() 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 &timestamp() 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);

View File

@ -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(&timestamp, &t);
else
localtime_r(&timestamp, &t);
init(t, timestamp, now);
LogMessageTime::LogMessageTime(std::time_t timestamp, WallTime now)
{
std::tm t;
if (FLAGS_log_utc_time)
gmtime_r(&timestamp, &t);
else
localtime_r(&timestamp, &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(&timestamp_, &gmt_struct);
isDst = gmt_struct.tm_isdst;
gmt_struct = time_struct_;
} else {
isDst = time_struct_.tm_isdst;
gmtime_r(&timestamp_, &gmt_struct);
}
void
LogMessageTime::CalcGmtOffset()
{
std::tm gmt_struct;
int isDst = 0;
if (FLAGS_log_utc_time) {
localtime_r(&timestamp_, &gmt_struct);
isDst = gmt_struct.tm_isdst;
gmt_struct = time_struct_;
} else {
isDst = time_struct_.tm_isdst;
gmtime_r(&timestamp_, &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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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