File: Logger.vala

package info (click to toggle)
granite 6.2.0-7
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,768 kB
  • sloc: python: 10; makefile: 8
file content (211 lines) | stat: -rw-r--r-- 5,795 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/*
 * Copyright 2015–2019 elementary, Inc. (https://elementary.io)
 * Copyright 2015–2017 Rico Tzschichholz
 * Copyright 2011–2013 Robert Dyer
 * SPDX-License-Identifier: LGPL-3.0-or-later
 */

namespace Granite.Services {
    /**
     * LogLevel:
     */
    public enum LogLevel {
        /**
         * This level is for use in debugging.
         */
        DEBUG,

        /**
         * This level should be used for non-error, non-debugging that is not due to any direct event.
         */
        INFO,

        /**
         * This level is used to log events that have happened in the app.
         */
        NOTIFY,

        /**
         * This level should be used for warnings of errors that haven't happened yet.
         */
        WARN,

        /**
         * This level should be used by recoverable errors.
         */
        ERROR,

        /**
         * This level should be used only in cases of unrecoverable errors.
         */
        FATAL
    }

    enum ConsoleColor {
        BLACK,
        RED,
        GREEN,
        YELLOW,
        BLUE,
        MAGENTA,
        CYAN,
        WHITE
    }

    /**
     * This class helps in the use of logs in a Granite application.
     *
     */
    public class Logger : GLib.Object {
        const string[] LOG_LEVEL_TO_STRING = {
            "DEBUG",
            "INFO",
            "NOTIFY",
            "WARNING",
            "ERROR",
            "FATAL"
        };

        /**
         * This is used to determine which level of LogLevelling should be used.
         */
        public static LogLevel DisplayLevel { get; set; default = LogLevel.WARN; } // vala-lint=naming-convention

        static Mutex write_mutex;

        /**
         * This method initializes the Logger
         *
         * @param app_name name of app that is logging
         */
        public static void initialize (string app_name) {
            Log.set_default_handler ((GLib.LogFunc) glib_log_func);
        }

        /**
         * Logs message using Notify level formatting
         *
         * @param msg message to be logged
         */
        public static void notification (string msg) {
            write (LogLevel.NOTIFY, msg);
        }

        static string get_time () {
            var now = new GLib.DateTime.now_local ();
            return "%.2d:%.2d:%.2d.%.6d".printf (
                now.get_hour (),
                now.get_minute (),
                now.get_second (),
                now.get_microsecond ()
            );
        }

        static void write (LogLevel level, owned string msg) {

            if (level < DisplayLevel)
                return;

            write_mutex.lock ();
            set_color_for_level (level);
            stdout.printf ("[%s %s]", LOG_LEVEL_TO_STRING[level], get_time ());

            reset_color ();
            stdout.printf (" %s\n", msg);

            write_mutex.unlock ();
        }

        static void set_color_for_level (LogLevel level) {

            switch (level) {
                case LogLevel.DEBUG:
                    set_foreground (ConsoleColor.GREEN);
                    break;
                case LogLevel.INFO:
                    set_foreground (ConsoleColor.BLUE);
                    break;
                case LogLevel.NOTIFY:
                    set_foreground (ConsoleColor.MAGENTA);
                    break;
                case LogLevel.WARN:
                    set_foreground (ConsoleColor.YELLOW);
                    break;
                case LogLevel.ERROR:
                    set_foreground (ConsoleColor.RED);
                    break;
                case LogLevel.FATAL:
                    set_background (ConsoleColor.RED);
                    set_foreground (ConsoleColor.WHITE);
                    break;
            }
        }

        static void reset_color () {
            stdout.printf ("\x001b[0m");
        }

        static void set_foreground (ConsoleColor color) {
            set_color (color, true);
        }

        static void set_background (ConsoleColor color) {
            set_color (color, false);
        }

        static void set_color (ConsoleColor color, bool is_foreground) {

            var color_code = color + 30 + 60;
            if (!is_foreground)
                color_code += 10;
            stdout.printf ("\x001b[%dm", color_code);
        }

        static void glib_log_func (string? d, LogLevelFlags flags, string msg) {
            string domain;
            if (d != null)
                domain = "[%s] ".printf (d);
            else
                domain = "";

            string message;
            if (msg.contains ("\n") || msg.contains ("\r"))
                message = "%s%s".printf (domain, msg.replace ("\n", "").replace ("\r", ""));
            else
                message = "%s%s".printf (domain, msg);

            LogLevel level;

            // Strip internal flags to make it possible to use a switch statement
            flags = (flags & LogLevelFlags.LEVEL_MASK);

            switch (flags) {
                case LogLevelFlags.LEVEL_CRITICAL:
                    level = LogLevel.FATAL;
                    break;

                case LogLevelFlags.LEVEL_ERROR:
                    level = LogLevel.ERROR;
                    break;

                case LogLevelFlags.LEVEL_INFO:
                case LogLevelFlags.LEVEL_MESSAGE:
                    level = LogLevel.INFO;
                    break;

                case LogLevelFlags.LEVEL_DEBUG:
                    level = LogLevel.DEBUG;
                    break;

                case LogLevelFlags.LEVEL_WARNING:
                default:
                    level = LogLevel.WARN;
                    break;
            }

            write (level, message);
        }

    }

}