Debug.vala 5.75 KB
Newer Older
1
/* Copyright 2016 Software Freedom Conservancy Inc.
2 3
 *
 * This software is licensed under the GNU LGPL (version 2.1 or later).
4
 * See the COPYING file in this distribution.
5
 */
6 7

namespace Debug {
8 9 10 11
    private const LogLevelFlags DEFAULT_LOG_MASK =
        LogLevelFlags.LEVEL_CRITICAL |
        LogLevelFlags.LEVEL_WARNING |
        LogLevelFlags.LEVEL_MESSAGE;
12
    
13 14 15 16 17 18 19 20 21 22 23 24 25
    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;
26
    
27 28
    public static void init(string app_version_prefix) {
        log_app_version_prefix = app_version_prefix;
29 30 31 32 33
        
        // default to stdout/stderr if file cannot be opened or console is specified
        log_out = stdout;
        log_err = stderr;
        
34 35
        string log_file_error_msg = null;
        
36 37
        // 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;
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
        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());
            }
        }
61
        
62
        if (Environment.get_variable("SHOTWELL_LOG") != null) {
63
            log_mask = LogLevelFlags.LEVEL_MASK;
64
        } else {
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
            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);
80 81 82 83 84 85 86
        }

        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);
87 88 89 90 91 92 93 94 95 96
        
        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);
        }
97 98
    }
    
99
    public static void terminate() {
100 101
    }
    
102 103 104 105
    private bool is_enabled(LogLevelFlags flag) {
        return ((log_mask & flag) > 0);
    }
    
106
    private void log(FileStream stream, string prefix, string message) {
107 108 109 110 111 112 113 114
        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
        );
115 116 117 118
        stream.flush();
    }
    
    private void info_handler(string? domain, LogLevelFlags flags, string message) {
119 120
        if (is_enabled(LogLevelFlags.LEVEL_INFO))
            log(log_out, "INF", message);
121 122 123
    }
    
    private void debug_handler(string? domain, LogLevelFlags flags, string message) {
124 125
        if (is_enabled(LogLevelFlags.LEVEL_DEBUG))
            log(log_out, "DBG", message);
126 127 128
    }
    
    private void message_handler(string? domain, LogLevelFlags flags, string message) {
129 130
        if (is_enabled(LogLevelFlags.LEVEL_MESSAGE))
            log(log_err, "MSG", message);
131 132 133
    }

    private void warning_handler(string? domain, LogLevelFlags flags, string message) {
134 135
        if (is_enabled(LogLevelFlags.LEVEL_WARNING))
            log(log_err, "WRN", message);
136 137 138
    }

    private void critical_handler(string? domain, LogLevelFlags flags, string message) {
139
        if (is_enabled(LogLevelFlags.LEVEL_CRITICAL)) {
140
            log(log_err, "CRT", message);
141 142 143
            if (log_file_stream != null)
                log(stderr, "CRT", message);    // also log to console
        }
144 145 146
    }
}