28 #include <boost/algorithm/string.hpp>
29 #include <boost/iostreams/stream.hpp>
30 #include <boost/iostreams/tee.hpp>
40 #define ERR_LS LOG_STREAM(err, log_setup)
41 #define WRN_LS LOG_STREAM(warn, log_setup)
42 #define LOG_LS LOG_STREAM(info, log_setup)
43 #define DBG_LS LOG_STREAM(debug, log_setup)
47 class null_streambuf :
public std::streambuf
49 virtual int overflow(
int c) {
return std::char_traits< char >::not_eof(
c); }
77 static std::unique_ptr<std::ostream, void(*)(std::ostream*)>
output_file_(
nullptr, [](std::ostream*){
78 std::cerr.rdbuf(
nullptr);
79 std::cout.rdbuf(
nullptr);
102 std::vector<std::string> files;
105 files.erase(std::remove_if(files.begin(), files.end(),
is_not_log_file), files.end());
115 std::sort(files.begin(), files.end());
117 for(std::size_t j = 0; j < files.size() -
lg::max_logs; ++j) {
118 const std::string
path = log_dir +
'/' + files[j];
121 ERR_LS <<
"rotate_logs(): failed to delete " <<
path <<
"!";
131 std::ostringstream o;
132 const std::time_t cur = std::time(
nullptr);
136 << std::put_time(std::localtime(&cur),
"%Y%m%d-%H%M%S-")
185 static std::ostream cerr_stream{std::cerr.rdbuf()};
187 auto cerr_tee { boost::iostreams::tee(*logfile, cerr_stream) };
188 output_file_.reset(
new boost::iostreams::stream<decltype(cerr_tee)>{cerr_tee, 4096, 0});
268 std::string::size_type
s = name.size();
273 }
else if (
s > 2 && name.compare(
s - 2, 2,
"/*") == 0) {
275 if (l.first.compare(0,
s - 1, name, 0,
s - 1) == 0)
301 std::ostringstream res;
303 if(l.first.find(filter) != std::string::npos)
304 res << l.first <<
"\n";
324 std::ostringstream ss;
326 ss << std::put_time(std::localtime(&
t),
format.c_str());
331 std::ostringstream sout;
333 const std::time_t minutes =
t / 60;
334 const std::time_t days = minutes / 60 / 24;
337 }
else if(minutes == 0) {
338 sout <<
t <<
" seconds";
339 }
else if(days == 0) {
340 sout << minutes / 60 <<
" hours, " << minutes % 60 <<
" minutes";
342 sout << days <<
" days, " << (minutes / 60) % 24 <<
" hours, " << minutes % 60 <<
" minutes";
350 int64_t micros = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
351 std::time_t seconds = micros/1'000'000;
352 int fractional = micros-(seconds*1'000'000);
353 char c = out.fill(
'0');
354 out << std::put_time(std::localtime(&seconds),
"%Y%m%d %H:%M:%S") <<
"." << std::setw(6) << fractional <<
' ';
361 std::string str = logstr;
364 const char* user_name = getenv(
"USERNAME");
366 const char* user_name = getenv(
"USER");
369 if(user_name !=
nullptr) {
370 boost::replace_all(str, std::string(
"/") + user_name +
"/",
"/USER/");
371 boost::replace_all(str, std::string(
"\\") + user_name +
"\\",
"\\USER\\");
381 bool show_timestamps,
383 bool auto_newline)
const
399 stream |
formatter() <<
"Error (strict mode, strict_level = " <<
strict_level_ <<
"): wesnoth reported on channel " <<
name_ <<
" " << domain.
domain_->first << std::endl;
449 ticks_ = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
451 debug()(domain_,
false,
true) |
formatter() <<
"{ BEGIN: " << str_;
459 ticks = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count() -
ticks_;
470 static std::stringstream
lg;
log_domain(char const *name, int severity=1)
void operator|(formatter &&message)
void set_auto_newline(bool enabled)
void set_prefix(const std::string &prefix)
void set_indent(int level)
log_in_progress(std::ostream &stream)
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
~redirect_output_setter()
std::ostream * old_stream_
The previously set redirection.
redirect_output_setter(std::ostream &stream)
Constructor.
const log_domain & domain_
void do_log_entry(const std::string &str) noexcept
void do_log_exit() noexcept
uint32_t get_next_random()
Get a new random number.
Declarations for File-IO.
static bool precise_timestamp
static std::string output_file_path_
static std::ostream null_ostream(new null_streambuf)
static std::mutex log_mutex
static std::optional< bool > is_log_dir_writable_
static std::ostream & output()
static std::ostream * output_stream_
static std::unique_ptr< std::ostream, void(*)(std::ostream *)> output_file_(nullptr, [](std::ostream *){ std::cerr.rdbuf(nullptr);std::cout.rdbuf(nullptr);})
static lg::log_domain log_setup("logsetup")
Standard logging facilities (interface).
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.
bool delete_file(const std::string &filename)
static bool file_exists(const bfs::path &fpath)
filesystem::scoped_ostream ostream_file(const std::string &fname, std::ios_base::openmode mode, bool create_directory)
int file_size(const std::string &fname)
Returns the size of a file, or -1 if the file doesn't exist.
void write_file(const std::string &fname, const std::string &data, std::ios_base::openmode mode)
Throws io_exception if an error occurs.
std::string get_logs_dir()
bool make_directory(const std::string &dirname)
std::string get_timespan(const std::time_t &t)
void set_strict_severity(int severity)
void rotate_logs(const std::string &log_dir)
Deletes old log files from the log directory.
std::string unique_log_filename()
Generates a unique log file name.
static log_domain dom("general")
void set_log_file_path(const std::string &path)
std::string list_logdomains(const std::string &filter)
bool is_not_log_file(const std::string &fn)
Helper function for rotate_logs.
bool set_log_domain_severity(const std::string &name, int severity)
std::string sanitize_log(const std::string &logstr)
std::map< std::string, int > domain_map
void check_log_dir_writable()
std::stringstream & log_to_chat()
Use this to show WML errors in the ingame chat.
const std::string log_file_prefix
std::string & get_log_file_path()
std::pair< const std::string, int > logd
static domain_map * domains
static bool strict_threw_
std::string get_timestamp(const std::time_t &t, const std::string &format)
void precise_timestamps(bool pt)
std::optional< bool > log_dir_writable()
bool get_log_domain_severity(const std::string &name, int &severity)
static void print_precise_timestamp(std::ostream &out) noexcept
const std::string log_file_suffix
std::string::const_iterator iterator
An exception object used when an IO error occurs.
static map_location::DIRECTION s