28 #include <boost/algorithm/string.hpp> 38 #define ERR_LS LOG_STREAM(err, log_setup) 39 #define WRN_LS LOG_STREAM(warn, log_setup) 40 #define LOG_LS LOG_STREAM(info, log_setup) 41 #define DBG_LS LOG_STREAM(debug, log_setup) 45 class null_streambuf :
public std::streambuf
47 virtual int overflow(
int c) {
return std::char_traits< char >::not_eof(c); }
75 static std::unique_ptr<std::ostream, void(*)(std::ostream*)>
output_file_(
nullptr, [](std::ostream*){
76 std::cerr.rdbuf(
nullptr);
77 std::cout.rdbuf(
nullptr);
96 if(output_file_path_.empty()) {
100 std::vector<std::string> files;
103 files.erase(std::remove_if(files.begin(), files.end(),
is_not_log_file), files.end());
113 std::sort(files.begin(), files.end());
115 for(std::size_t j = 0; j < files.size() -
lg::max_logs; ++j) {
116 const std::string
path = log_dir +
'/' + files[j];
119 ERR_LS <<
"rotate_logs(): failed to delete " << path <<
"!";
129 std::ostringstream o;
130 const std::time_t cur = std::time(
nullptr);
134 << std::put_time(std::localtime(&cur),
"%Y%m%d-%H%M%S-")
196 output_file_path_ =
path;
199 redirect_output_setter::redirect_output_setter(std::ostream& stream)
252 domain_ = &*domains->insert(
logd(name, severity)).first;
258 std::string::size_type
s = name.size();
260 for(
logd &l : *domains) {
263 }
else if (s > 2 && name.compare(s - 2, 2,
"/*") == 0) {
264 for(
logd &l : *domains) {
265 if (l.first.compare(0, s - 1, name, 0, s - 1) == 0)
270 if (it == domains->end())
283 if (it == domains->end())
285 severity = it->second;
291 std::ostringstream res;
292 for(
logd &l : *domains) {
293 if(l.first.find(filter) != std::string::npos)
294 res << l.first <<
"\n";
314 std::ostringstream ss;
316 ss << std::put_time(std::localtime(&t), format.c_str());
321 std::ostringstream sout;
323 const std::time_t minutes = t / 60;
324 const std::time_t days = minutes / 60 / 24;
327 }
else if(minutes == 0) {
328 sout << t <<
" seconds";
329 }
else if(days == 0) {
330 sout << minutes / 60 <<
" hours, " << minutes % 60 <<
" minutes";
332 sout << days <<
" days, " << (minutes / 60) % 24 <<
" hours, " << minutes % 60 <<
" minutes";
340 int64_t micros = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
341 std::time_t seconds = micros/1
'000'000;
342 int fractional = micros-(seconds*1
'000'000);
343 char c = out.fill(
'0');
344 out << std::put_time(std::localtime(&seconds),
"%Y%m%d %H:%M:%S") <<
"." << std::setw(6) << fractional <<
' ';
351 std::string str = logstr;
354 const char* user_name = getenv(
"USERNAME");
356 const char* user_name = getenv(
"USER");
359 if(user_name !=
nullptr) {
360 boost::replace_all(str, std::string(
"/") + user_name +
"/",
"/USER/");
361 boost::replace_all(str, std::string(
"\\") + user_name +
"\\",
"\\USER\\");
371 bool show_timestamps,
373 bool auto_newline)
const 375 if (severity_ > domain.
domain_->second) {
388 if (!strict_threw_ && severity_ <= strict_level_ && break_strict) {
389 stream |
formatter() <<
"Error (strict mode, strict_level = " << strict_level_ <<
"): wesnoth reported on channel " << name_ <<
" " << domain.
domain_->first << std::endl;
390 strict_threw_ =
true;
439 ticks_ = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
441 debug()(domain_,
false,
true) |
formatter() <<
"{ BEGIN: " << str_;
449 ticks = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count() - ticks_;
455 output |
formatter() <<
"} END: " << str_ <<
" (took " << ticks <<
"us)";
460 static std::stringstream
lg;
static log_domain dom("general")
std::string get_timestamp(const std::time_t &t, const std::string &format)
static std::mutex log_mutex
static domain_map * domains
std::string get_timespan(const std::time_t &t)
bool delete_file(const std::string &filename)
void do_log_exit() noexcept
static bool file_exists(const bfs::path &fpath)
static std::unique_ptr< std::ostream, void(*)(std::ostream *)> output_file_(nullptr, [](std::ostream *){ std::cerr.rdbuf(nullptr);std::cout.rdbuf(nullptr);})
uint32_t get_next_random()
Get a new random number.
std::string get_logs_dir()
log_in_progress(std::ostream &stream)
static lg::log_domain log_setup("logsetup")
log_domain(char const *name, int severity=1)
const std::string log_file_suffix
filesystem::scoped_ostream ostream_file(const std::string &fname, std::ios_base::openmode mode, bool create_directory)
log_in_progress operator()(const log_domain &domain, bool show_names=true, bool do_indent=false, bool show_timestamps=true, bool break_strict=true, bool auto_newline=true) const
std::pair< const std::string, int > logd
bool is_not_log_file(const std::string &fn)
Helper function for rotate_logs.
void set_auto_newline(bool enabled)
static bool is_log_dir_writable_
static std::ostream & output()
std::string & get_log_file_path()
bool get_log_domain_severity(const std::string &name, int &severity)
std::string sanitize_log(const std::string &logstr)
void get_files_in_dir(const std::string &dir, std::vector< std::string > *files, std::vector< std::string > *dirs, name_mode mode, filter_mode filter, reorder_mode reorder, file_tree_checksum *checksum)
Get a list of all files and/or directories in a given directory.
void rotate_logs(const std::string &log_dir)
Deletes old log files from the log directory.
static bool precise_timestamp
void do_log_entry(const std::string &str) noexcept
std::string unique_log_filename()
Generates a unique log file name.
std::map< std::string, int > domain_map
void check_log_dir_writable()
~redirect_output_setter()
void write_file(const std::string &fname, const std::string &data, std::ios_base::openmode mode)
Throws io_exception if an error occurs.
std::ostream * old_stream_
The previously set redirection.
static void print_precise_timestamp(std::ostream &out) noexcept
void set_strict_severity(int severity)
An exception object used when an IO error occurs.
static map_location::DIRECTION s
bool make_directory(const std::string &dirname)
static std::ostream * output_stream_
static std::string output_file_path_
Declarations for File-IO.
bool set_log_domain_severity(const std::string &name, int severity)
int file_size(const std::string &fname)
Returns the size of a file, or -1 if the file doesn't exist.
void operator|(formatter &&message)
static bool strict_threw_
std::string list_logdomains(const std::string &filter)
Standard logging facilities (interface).
static std::ostream null_ostream(new null_streambuf)
void set_prefix(const std::string &prefix)
void set_indent(int level)
void set_log_file_path(const std::string &path)
int get_severity() const
Returns following values depending on the logger: error: 0 warn: 1 info: 2 debug: 3 See also the lg::...
std::string::const_iterator iterator
const std::string log_file_prefix
void precise_timestamps(bool pt)
std::stringstream & log_to_chat()
Use this to show WML errors in the ingame chat.