diff options
Diffstat (limited to 'src/Debug.vala')
-rw-r--r-- | src/Debug.vala | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/src/Debug.vala b/src/Debug.vala new file mode 100644 index 0000000..ad626f4 --- /dev/null +++ b/src/Debug.vala @@ -0,0 +1,146 @@ +/* Copyright 2009-2014 Yorba Foundation + * + * This software is licensed under the GNU LGPL (version 2.1 or later). + * See the COPYING file in this distribution. + */ + +namespace Debug { + private const LogLevelFlags DEFAULT_LOG_MASK = + LogLevelFlags.LEVEL_CRITICAL | + LogLevelFlags.LEVEL_WARNING | + LogLevelFlags.LEVEL_MESSAGE; + + public const string VIEWER_PREFIX = "V"; + public const string LIBRARY_PREFIX = "L"; + + // Ideally, there would be a LogLevelFlags.NONE constant to use as + // empty value but failing that, 0 works as well + private LogLevelFlags log_mask = 0; + private string log_app_version_prefix; + // log_file_stream is the canonical reference to the file stream (and owns + // it), while log_out and log_err are indirections that can point to + // log_file_stream or stdout and stderr respectively + private unowned FileStream log_out = null; + private unowned FileStream log_err = null; + private FileStream log_file_stream = null; + + public static void init(string app_version_prefix) { + log_app_version_prefix = app_version_prefix; + + // default to stdout/stderr if file cannot be opened or console is specified + log_out = stdout; + log_err = stderr; + + string log_file_error_msg = null; + + // logging to disk is currently off for viewer more; see http://trac.yorba.org/ticket/2078 + File? log_file = (log_app_version_prefix == LIBRARY_PREFIX) ? AppDirs.get_log_file() : null; + if(log_file != null) { + File log_dir = log_file.get_parent(); + try { + if (log_dir.query_exists(null) == false) { + if (!log_dir.make_directory_with_parents(null)) { + log_file_error_msg = "Unable to create data directory %s".printf(log_dir.get_path()); + } + } + } catch (Error err) { + log_file_error_msg = err.message; + } + // overwrite the log file every time the application is started + // to ensure it doesn't grow too large; if there is a need for + // keeping the log, the 'w' should be replaced by 'a' and some sort + // of log rotation implemented + log_file_stream = FileStream.open(log_file.get_path(), "w"); + if(log_file_stream != null) { + log_out = log_file_stream; + log_err = log_file_stream; + } else { + log_file_error_msg = "Unable to open or create log file %s".printf(log_file.get_path()); + } + } + + if (Environment.get_variable("SHOTWELL_LOG") != null) { + log_mask = LogLevelFlags.LEVEL_MASK; + } else { + log_mask = ((Environment.get_variable("SHOTWELL_INFO") != null) ? + log_mask | LogLevelFlags.LEVEL_INFO : + log_mask); + log_mask = ((Environment.get_variable("SHOTWELL_DEBUG") != null) ? + log_mask | LogLevelFlags.LEVEL_DEBUG : + log_mask); + log_mask = ((Environment.get_variable("SHOTWELL_MESSAGE") != null) ? + log_mask | LogLevelFlags.LEVEL_MESSAGE : + log_mask); + log_mask = ((Environment.get_variable("SHOTWELL_WARNING") != null) ? + log_mask | LogLevelFlags.LEVEL_WARNING : + log_mask); + log_mask = ((Environment.get_variable("SHOTWELL_CRITICAL") != null) ? + log_mask | LogLevelFlags.LEVEL_CRITICAL : + log_mask); + } + + Log.set_handler(null, LogLevelFlags.LEVEL_INFO, info_handler); + Log.set_handler(null, LogLevelFlags.LEVEL_DEBUG, debug_handler); + Log.set_handler(null, LogLevelFlags.LEVEL_MESSAGE, message_handler); + Log.set_handler(null, LogLevelFlags.LEVEL_WARNING, warning_handler); + Log.set_handler(null, LogLevelFlags.LEVEL_CRITICAL, critical_handler); + + if(log_mask == 0 && log_file != null) { + // if the log mask is still 0 and we have a log file, set the + // mask to the default + log_mask = DEFAULT_LOG_MASK; + } + + if(log_file_error_msg != null) { + warning("%s", log_file_error_msg); + } + } + + public static void terminate() { + } + + private bool is_enabled(LogLevelFlags flag) { + return ((log_mask & flag) > 0); + } + + private void log(FileStream stream, string prefix, string message) { + time_t now = time_t(); + stream.printf("%s %d %s [%s] %s\n", + log_app_version_prefix, + Posix.getpid(), + Time.local(now).to_string(), + prefix, + message + ); + stream.flush(); + } + + private void info_handler(string? domain, LogLevelFlags flags, string message) { + if (is_enabled(LogLevelFlags.LEVEL_INFO)) + log(log_out, "INF", message); + } + + private void debug_handler(string? domain, LogLevelFlags flags, string message) { + if (is_enabled(LogLevelFlags.LEVEL_DEBUG)) + log(log_out, "DBG", message); + } + + private void message_handler(string? domain, LogLevelFlags flags, string message) { + if (is_enabled(LogLevelFlags.LEVEL_MESSAGE)) + log(log_err, "MSG", message); + } + + private void warning_handler(string? domain, LogLevelFlags flags, string message) { + if (is_enabled(LogLevelFlags.LEVEL_WARNING)) + log(log_err, "WRN", message); + } + + private void critical_handler(string? domain, LogLevelFlags flags, string message) { + if (is_enabled(LogLevelFlags.LEVEL_CRITICAL)) { + log(log_err, "CRT", message); + if (log_file_stream != null) + log(stderr, "CRT", message); // also log to console + } + } +} + |