23int ParseLevel(std::string value) {
24 std::transform(value.begin(), value.end(), value.begin(),
25 [](
unsigned char c) { return std::toupper(c); });
32 throw std::invalid_argument(
"Invalid logging level: " + value);
41 default:
return "OFF";
44std::tm LocalTime(std::time_t now) {
47 localtime_s(&result, &now);
49 localtime_r(&now, &result);
61Logger::Logger() : legacy_settings(
Settings::Instance()) {
63 for (
const char* key : {
"OPENSHOT_LOG_LEVEL",
"OPENSHOT_LOG_FILE_LEVEL",
64 "OPENSHOT_LOG_CONSOLE_LEVEL",
"LIBOPENSHOT_LOG_LEVEL",
65 "LIBOPENSHOT_LOG_FILE_LEVEL",
"LIBOPENSHOT_LOG_CONSOLE_LEVEL"}) {
66 const char* value = std::getenv(key);
69 int level = ParseLevel(value);
70 std::string name(key);
71 if (name.find(
"CONSOLE") == std::string::npos) file_level = level;
72 if (name.find(
"FILE") == std::string::npos) {
73 console_level = level;
74 console_configured =
true;
76 }
catch (
const std::invalid_argument&) {
77 std::cerr <<
"libopenshot: ignoring invalid " << key <<
"=" << value <<
'\n';
82 if (
const wchar_t*
path = _wgetenv(L
"LIBOPENSHOT_LOG_FILE")) {
83 try {
Path(std::filesystem::path(
path).u8string()); }
84 catch (
const std::exception&) {
85 std::cerr <<
"libopenshot: invalid LIBOPENSHOT_LOG_FILE path\n";
89 if (
const char*
path = std::getenv(
"LIBOPENSHOT_LOG_FILE"))
Path(
path);
92 ResvgRenderer::initLog();
96int Logger::ConsoleLevel()
const {
102 return level !=
LevelOff && ((file_open && level >= file_level) || level >= ConsoleLevel());
106 console_level = ParseLevel(level);
107 console_configured =
true;
112 const std::lock_guard<std::recursive_mutex> lock(loggerMutex);
113 if (
path == file_path && file_open)
return;
115 if (log_file.is_open()) log_file.close();
118 if (
path.empty())
return;
121 log_file.open(std::filesystem::u8path(
path), std::ios::out | std::ios::app);
125 log_file.open(
path, std::ios::out | std::ios::app);
127 }
catch (
const std::exception&) {
128 std::cerr <<
"libopenshot: invalid log file path: " <<
path <<
'\n';
131 file_open = log_file.is_open();
133 std::cerr <<
"libopenshot: unable to open log file: " <<
path <<
'\n';
136 auto now = LocalTime(std::time(
nullptr));
138 log_file <<
"------------------------------------------\n"
139 <<
"libopenshot logging: " << std::put_time(&now,
"%a %b %d %H:%M:%S %Y") <<
'\n'
140 <<
"------------------------------------------" << std::endl;
144 if (log_file.is_open()) log_file << message << std::flush;
148 const std::lock_guard<std::recursive_mutex> lock(loggerMutex);
149 auto now = LocalTime(std::time(
nullptr));
150 std::ostringstream record;
151 record << std::put_time(&now,
"%Y-%m-%d %H:%M:%S") <<
' '
152 << LevelName(level) <<
" [" << std::this_thread::get_id() <<
"] " << message;
153 if (message.empty() || message.back() !=
'\n') record <<
'\n';
154 const auto text = record.str();
155 if (level >= file_level)
LogToFile(text);
156 if (level >= ConsoleLevel()) std::clog << text << std::flush;
159 const std::lock_guard<std::recursive_mutex> lock(loggerMutex);
162 console_configured =
true;
164 if (log_file.is_open()) log_file.close();
169 std::string arg1_name,
float arg1_value,
170 std::string arg2_name,
float arg2_value,
171 std::string arg3_name,
float arg3_value,
172 std::string arg4_name,
float arg4_value,
173 std::string arg5_name,
float arg5_value,
174 std::string arg6_name,
float arg6_value)
182 const std::lock_guard<std::recursive_mutex> lock(loggerMutex);
184 std::stringstream message;
185 message << std::fixed << std::setprecision(4);
188 message << method_name <<
" (";
190 if (arg1_name.length() > 0)
191 message << arg1_name <<
"=" << arg1_value;
193 if (arg2_name.length() > 0)
194 message <<
", " << arg2_name <<
"=" << arg2_value;
196 if (arg3_name.length() > 0)
197 message <<
", " << arg3_name <<
"=" << arg3_value;
199 if (arg4_name.length() > 0)
200 message <<
", " << arg4_name <<
"=" << arg4_value;
202 if (arg5_name.length() > 0)
203 message <<
", " << arg5_name <<
"=" << arg5_value;
205 if (arg6_name.length() > 0)
206 message <<
", " << arg6_name <<
"=" << arg6_value;
208 message <<
")" << std::endl;
Header file for global Settings class.
Independent file and stderr logging. No networking or worker thread.
void AppendDebugMethod(std::string method_name, std::string arg1_name="", float arg1_value=-1.0, std::string arg2_name="", float arg2_value=-1.0, std::string arg3_name="", float arg3_value=-1.0, std::string arg4_name="", float arg4_value=-1.0, std::string arg5_name="", float arg5_value=-1.0, std::string arg6_name="", float arg6_value=-1.0)
void SetFileLevel(std::string level)
Explicit configuration overrides environment defaults. Invalid levels throw.
void SetConsoleLevel(std::string level)
void Path(std::string path)
void Enable(bool enabled)
Compatibility: enable debug file output, or disable ordinary file output.
bool ShouldLog(Level level=LevelDebug) const
void LogToFile(std::string message)
Unfiltered raw output, retained for the existing crash handler.
void Log(std::string message, Level level=LevelDebug)
static Logger * Instance()
This class is contains settings used by libopenshot (and can be safely toggled at any point)
bool DEBUG_TO_STDERR
Legacy native debug-to-stderr switch (explicit Logger levels take precedence)
This namespace is the default namespace for all code in the openshot library.