I am trying to deploy my application right now, which uses Boost Log (Boost 1.58). It is a simple console app, being run in Windows 7. Logging works perfectly fine on my personal desktop.
However, when I deploy the application to a Win7 virtual machine, it crashes upon my first log statement:
boost::log::sources::severity_logger<SeverityLevel> slg;
BOOST_LOG_SEV(slg, SeverityLevel::Notification) << L"Application loaded"; // <-- Crash here
The log directory gets created, but the log file never gets created and the application crashes.
I have tried a logfile directory in my %APPDATA% directory, and also in my My Documents directory.
The odd thing is: When I run the app as Administrator, it works!
So this must be a permissions thing, but I have permissions to these folders, so...
Any ideas?
* MORE *
Here is the code to set up my logger:
wstring appData = GetMyAppDataPath();
boost::shared_ptr< boost::log::sinks::synchronous_sink< boost::log::sinks::text_file_backend > > textFileSink(new boost::log::sinks::synchronous_sink< boost::log::sinks::text_file_backend >(to store rotated files
boost::log::keywords::file_name = "log_%7N.log", // file name pattern
boost::log::keywords::rotation_size = 16384 // rotation size, in characters
));
// Set up where the rotated files will be stored
textFileSink->locked_backend()->set_file_collector(boost::log::sinks::file::make_collector(
boost::log::keywords::target = appData + L"\\logs", // where to store rotated files
boost::log::keywords::max_size = 64 * 1024 * 1024, // maximum total size of the stored files, in bytes (64 MiB)
boost::log::keywords::min_free_space = 100 * 1024 * 1024 // minimum free space on the drive, in bytes
));
// Upon restart, scan the target directory for files matching the file_name pattern
textFileSink->locked_backend()->scan_for_files();
// Set up the format for output to the text file.
textFileSink->set_formatter(boost::log::expressions::stream
<< "[" << boost::log::expressions::attr< boost::posix_time::ptime >("TimeStamp")
<< " " << boost::log::expressions::attr< SeverityLevel, severity_tag >("Severity") << "] "
<< boost::log::expressions::message
);
// Add it to the core
boost::log::core::get()->add_sink(textFileSink);
which is mostly taken from here: http://www.boost.org/doc/libs/1_58_0/libs/log/example/rotating_file/main.cpp .
* ALSO *
I added an exception handler to the Boost Logger by adding:
boost::log::core::get()->set_exception_handler(boost::log::make_exception_handler<
std::runtime_error,
std::logic_error,
std::exception
>(pbb_boost_log_exception_handler()));
And then adding the handler. When I then run, I am able to catch the following exception before the crash:
std::exception: Failed to open file for writing: Input/output error: "C:\Program Files\My App\log_0000000.log"
WTF? I am definitely setting the log file location to the appData
value, which I have verified is correct. Furthermore, if I run this app as administrator, the log file ends up in the place where I expect it (appdata folder). So it must just be creating a temporary file at the executable's location. Is this normal behavior? I can't imagine it is... so what did I do??
Okay, I figured it out.
The issue was this line here, setting up the text backend:
boost::shared_ptr< boost::log::sinks::synchronous_sink< boost::log::sinks::text_file_backend > > textFileSink(new boost::log::sinks::synchronous_sink< boost::log::sinks::text_file_backend >
boost::log::keywords::file_name = "log_%7N.log", // file name pattern
boost::log::keywords::rotation_size = 16384 // rotation size, in characters
));
There was definitely a temporary log file being written to the local directory (a Program Files directory, which is bad). Based on the documentation here, I saw that there is a temporary file written, and then passed to the file collector.
So for the solution, I changed the code to this:
boost::shared_ptr< boost::log::sinks::synchronous_sink< boost::log::sinks::text_file_backend > > textFileSink(new boost::log::sinks::synchronous_sink< boost::log::sinks::text_file_backend >(
boost::log::keywords::file_name = appData + L"\\log_%7N.log", // file name pattern
boost::log::keywords::rotation_size = 16384 // rotation size, in characters
));
Notice that I am now specifying the file_name
as being in the AppData directory instead.
This solved the problem.
I have a hard time believing that I am the first one to run into this issue, but I could not find this anywhere on the web. This would be a commonly recurring problem for windows developers, so hopefully this is helpful to someone else.