Skip to content

Commit

Permalink
add "strict" logging option, to treat e.g. wml warnings as errors
Browse files Browse the repository at this point in the history
When the game is run using e.g. "--log-strict=warning", then
writing anything to a log channel of severity warning or higher
will result in a game::game_error exception being thrown.

This will only happen the first time that such a write is
attempted, subsequent attempts to get the logging object will
pass without exception and such messages will be reported.
  • Loading branch information
cbeck88 committed May 15, 2014
1 parent a9274bd commit f7ce184
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 2 deletions.
15 changes: 15 additions & 0 deletions src/commandline_options.cpp
Expand Up @@ -196,6 +196,7 @@ commandline_options::commandline_options ( int argc, char** argv ) :
("log-info", po::value<std::string>(), "sets the severity level of the specified log domain(s) to 'info'. Similar to --log-error.")
("log-debug", po::value<std::string>(), "sets the severity level of the specified log domain(s) to 'debug'. Similar to --log-error.")
("log-precise", "shows the timestamps in the logfile with more precision")
("log-strict", po::value<std::string>(), "sets the strict level of the logger. messages to log domains of this level or more severe generate an in-game exception.")
;

po::options_description multiplayer_opts("Multiplayer options");
Expand Down Expand Up @@ -332,6 +333,8 @@ commandline_options::commandline_options ( int argc, char** argv ) :
logdomains = vm["logdomains"].as<std::string>();
if (vm.count("log-precise"))
log_precise_timestamps = true;
if (vm.count("log-strict"))
parse_log_strictness(vm["log-strict"].as<std::string>());
if (vm.count("max-fps"))
max_fps = vm["max-fps"].as<int>();
if (vm.count("multiplayer"))
Expand Down Expand Up @@ -444,6 +447,18 @@ void commandline_options::parse_log_domains_(const std::string &domains_string,
}
}

void commandline_options::parse_log_strictness (const std::string & severity ) {
static lg::logger const *loggers[] = { &lg::err, &lg::warn, &lg::info, &lg::debug };
BOOST_FOREACH (const lg::logger * l, loggers ) {
if (severity == l->get_name()) {
lg::set_strict_severity(*l);
return ;
}
}
std::cerr << "Unrecognized argument to --log-strict : " << severity << " . \nDisabling strict mode logging." << std::endl;
lg::set_strict_severity(-1);
}

void commandline_options::parse_resolution_ ( const std::string& resolution_string )
{
const std::vector<std::string> tokens = utils::split(resolution_string, 'x');
Expand Down
3 changes: 3 additions & 0 deletions src/commandline_options.hpp
Expand Up @@ -75,6 +75,8 @@ friend std::ostream& operator<<(std::ostream &os, const commandline_options& cmd
/// Contains parsed arguments of --log-* (e.g. --log-debug).
/// Vector of pairs (severity, log domain).
boost::optional<std::vector<boost::tuple<int, std::string> > > log;
/// Non-empty if --log-strict was given
boost::optional<int> log_strict_level;
/// Non-empty if --load was given on the command line. Savegame specified to load after start.
boost::optional<std::string> load;
/// Non-empty if --logdomains was given on the command line. Prints possible logdomains filtered by given string and exits.
Expand Down Expand Up @@ -191,6 +193,7 @@ friend std::ostream& operator<<(std::ostream &os, const commandline_options& cmd
bool with_replay;
private:
void parse_log_domains_(const std::string &domains_string, const int severity);
void parse_log_strictness (const std::string &severity);
void parse_resolution_ (const std::string &resolution_string);
/// A helper function splitting vector of strings of format unsigned int:string to vector of tuples (unsigned int,string)
std::vector<boost::tuple<unsigned int,std::string> > parse_to_uint_string_tuples_(const std::vector<std::string> &strings, char separator = ':');
Expand Down
26 changes: 24 additions & 2 deletions src/log.cpp
Expand Up @@ -19,6 +19,7 @@
* See also the command line switches --logdomains and --log-@<level@>="domain".
*/

#include "game_errors.hpp"
#include "global.hpp"

#include "SDL.h"
Expand Down Expand Up @@ -74,6 +75,8 @@ tredirect_output_setter::~tredirect_output_setter()

typedef std::map<std::string, int> domain_map;
static domain_map *domains;
static int strict_level_ = -1;
static bool strict_threw_ = false;
void timestamps(bool t) { timestamp = t; }
void precise_timestamps(bool pt) { precise_timestamp = pt; }

Expand Down Expand Up @@ -122,6 +125,14 @@ std::string list_logdomains(const std::string& filter)
return res.str();
}

void set_strict_severity(int severity) {
strict_level_ = severity;
}

void set_strict_severity(const logger &lg) {
set_strict_severity(lg.get_severity());
}

std::string get_timestamp(const time_t& t, const std::string& format) {
char buf[100] = {0};
tm* lt = localtime(&t);
Expand Down Expand Up @@ -158,9 +169,20 @@ static void print_precise_timestamp(std::ostream & out)

std::ostream &logger::operator()(log_domain const &domain, bool show_names, bool do_indent) const
{
if (severity_ > domain.domain_->second)
if (severity_ > domain.domain_->second) {
return null_ostream;
else {
} else if (!strict_threw_ && (severity_ <= strict_level_)) {
std::stringstream ss;
ss << "Error (strict mode, strict_level = " << strict_level_ << "): wesnoth reported on channel " << name_ << " " << domain.domain_->first;
std::cerr << ss.str() << std::endl;
//TODO: Would be nice to actually get whatever message they were going to log...
//perhaps could pass back a & to a stringstream with a custom destructor that
//throws this game::error when it goes out of scope, after capturing their message?
//TODO: The flag strict_threw_ makes sure that we only do this once, and don't block
//subsequent error logging. Does this need to be more robust?
strict_threw_ = true;
throw game::game_error(ss.str());
} else {
std::ostream& stream = output();
if(do_indent) {
for(int i = 0; i != indent; ++i)
Expand Down
8 changes: 8 additions & 0 deletions src/log.hpp
Expand Up @@ -78,6 +78,9 @@ bool set_log_domain_severity(std::string const &name, int severity);
bool set_log_domain_severity(std::string const &name, const logger &lg);
std::string list_logdomains(const std::string& filter);

void set_strict_severity(int severity);
void set_strict_severity(const logger &lg);

class logger {
char const *name_;
int severity_;
Expand All @@ -95,6 +98,11 @@ class logger {
{
return severity_;
}

std::string get_name() const
{
return name_;
}
};

void timestamps(bool);
Expand Down

0 comments on commit f7ce184

Please sign in to comment.