~ubuntu-branches/debian/stretch/gnome-builder/stretch

« back to all changes in this revision

Viewing changes to libide/ide-log.c

  • Committer: Package Import Robot
  • Author(s): Andreas Henriksson
  • Date: 2015-10-11 12:38:45 UTC
  • Revision ID: package-import@ubuntu.com-20151011123845-a0hvkz01se0p1p5a
Tags: upstream-3.16.3
ImportĀ upstreamĀ versionĀ 3.16.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ide-log.c
 
2
 *
 
3
 * Copyright (C) 2015 Christian Hergert <christian@hergert.me>
 
4
 *
 
5
 * This program is free software: you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation, either version 3 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
#ifndef _GNU_SOURCE
 
20
# define _GNU_SOURCE
 
21
#endif
 
22
 
 
23
#ifdef __linux__
 
24
# include <sys/types.h>
 
25
# include <sys/syscall.h>
 
26
#endif
 
27
 
 
28
#include <glib.h>
 
29
#include <string.h>
 
30
#include <time.h>
 
31
#include <unistd.h>
 
32
 
 
33
#include "ide-debug.h"
 
34
#include "ide-log.h"
 
35
 
 
36
typedef const gchar *(*IdeLogLevelStrFunc) (GLogLevelFlags log_level);
 
37
 
 
38
static GPtrArray          *channels;
 
39
static GLogFunc            last_handler;
 
40
static int                 log_verbosity;
 
41
static IdeLogLevelStrFunc  log_level_str_func;
 
42
 
 
43
G_LOCK_DEFINE (channels_lock);
 
44
 
 
45
/**
 
46
 * ide_log_get_thread:
 
47
 *
 
48
 * Retrieves task id for the current thread. This is only supported on Linux.
 
49
 * On other platforms, the current current thread pointer is retrieved.
 
50
 *
 
51
 * Returns: The task id.
 
52
 */
 
53
static inline gint
 
54
ide_log_get_thread (void)
 
55
{
 
56
#if __linux__
 
57
  return (gint) syscall (SYS_gettid);
 
58
#else
 
59
  return GPOINTER_TO_INT (g_thread_self ());
 
60
#endif /* __linux__ */
 
61
}
 
62
 
 
63
/**
 
64
 * ide_log_level_str:
 
65
 * @log_level: A #GLogLevelFlags.
 
66
 *
 
67
 * Retrieves the log level as a string.
 
68
 *
 
69
 * Returns: A string which shouldn't be modified or freed.
 
70
 * Side effects: None.
 
71
 */
 
72
static const gchar *
 
73
ide_log_level_str (GLogLevelFlags log_level)
 
74
{
 
75
  switch (((gulong)log_level & G_LOG_LEVEL_MASK))
 
76
    {
 
77
    case G_LOG_LEVEL_ERROR:    return "   ERROR";
 
78
    case G_LOG_LEVEL_CRITICAL: return "CRITICAL";
 
79
    case G_LOG_LEVEL_WARNING:  return " WARNING";
 
80
    case G_LOG_LEVEL_MESSAGE:  return " MESSAGE";
 
81
    case G_LOG_LEVEL_INFO:     return "    INFO";
 
82
    case G_LOG_LEVEL_DEBUG:    return "   DEBUG";
 
83
    case G_LOG_LEVEL_TRACE:    return "   TRACE";
 
84
 
 
85
    default:
 
86
      return " UNKNOWN";
 
87
    }
 
88
}
 
89
 
 
90
static const gchar *
 
91
ide_log_level_str_with_color (GLogLevelFlags log_level)
 
92
{
 
93
  switch (((gulong)log_level & G_LOG_LEVEL_MASK))
 
94
    {
 
95
    case G_LOG_LEVEL_ERROR:    return "   \033[1;31mERROR\033[0m";
 
96
    case G_LOG_LEVEL_CRITICAL: return "\033[1;35mCRITICAL\033[0m";
 
97
    case G_LOG_LEVEL_WARNING:  return " \033[1;33mWARNING\033[0m";
 
98
    case G_LOG_LEVEL_MESSAGE:  return " \033[1;32mMESSAGE\033[0m";
 
99
    case G_LOG_LEVEL_INFO:     return "    \033[1;32mINFO\033[0m";
 
100
    case G_LOG_LEVEL_DEBUG:    return "   \033[1;32mDEBUG\033[0m";
 
101
    case G_LOG_LEVEL_TRACE:    return "   \033[1;36mTRACE\033[0m";
 
102
 
 
103
    default:
 
104
      return " UNKNOWN";
 
105
    }
 
106
}
 
107
 
 
108
/**
 
109
 * ide_log_write_to_channel:
 
110
 * @channel: A #GIOChannel.
 
111
 * @message: A string log message.
 
112
 *
 
113
 * Writes @message to @channel and flushes the channel.
 
114
 */
 
115
static void
 
116
ide_log_write_to_channel (GIOChannel  *channel,
 
117
                          const gchar *message)
 
118
{
 
119
  g_io_channel_write_chars (channel, message, -1, NULL, NULL);
 
120
  g_io_channel_flush (channel, NULL);
 
121
}
 
122
 
 
123
/**
 
124
 * ide_log_handler:
 
125
 * @log_domain: A string containing the log section.
 
126
 * @log_level: A #GLogLevelFlags.
 
127
 * @message: The string message.
 
128
 * @user_data: User data supplied to g_log_set_default_handler().
 
129
 *
 
130
 * Default log handler that will dispatch log messages to configured logging
 
131
 * destinations.
 
132
 *
 
133
 * Returns: None.
 
134
 * Side effects: None.
 
135
 */
 
136
static void
 
137
ide_log_handler (const gchar    *log_domain,
 
138
                 GLogLevelFlags  log_level,
 
139
                 const gchar    *message,
 
140
                 gpointer        user_data)
 
141
{
 
142
  struct timespec ts;
 
143
  struct tm tt;
 
144
  time_t t;
 
145
  const gchar *level;
 
146
  gchar ftime[32];
 
147
  gchar *buffer;
 
148
 
 
149
  if (G_LIKELY (channels->len))
 
150
    {
 
151
      switch ((int)log_level)
 
152
        {
 
153
        case G_LOG_LEVEL_MESSAGE:
 
154
          if (log_verbosity < 1)
 
155
            return;
 
156
          break;
 
157
 
 
158
        case G_LOG_LEVEL_INFO:
 
159
          if (log_verbosity < 2)
 
160
            return;
 
161
          break;
 
162
 
 
163
        case G_LOG_LEVEL_DEBUG:
 
164
          if (log_verbosity < 3)
 
165
            return;
 
166
          break;
 
167
 
 
168
        case G_LOG_LEVEL_TRACE:
 
169
          if (log_verbosity < 4)
 
170
            return;
 
171
          break;
 
172
 
 
173
        default:
 
174
          break;
 
175
        }
 
176
 
 
177
      level = log_level_str_func (log_level);
 
178
      clock_gettime (CLOCK_REALTIME, &ts);
 
179
      t = (time_t) ts.tv_sec;
 
180
      tt = *localtime (&t);
 
181
      strftime (ftime, sizeof (ftime), "%H:%M:%S", &tt);
 
182
      buffer = g_strdup_printf ("%s.%04ld  %30s[%d]: %s: %s\n",
 
183
                                ftime,
 
184
                                ts.tv_nsec / 100000,
 
185
                                log_domain,
 
186
                                ide_log_get_thread (),
 
187
                                level,
 
188
                                message);
 
189
      G_LOCK (channels_lock);
 
190
      g_ptr_array_foreach (channels, (GFunc) ide_log_write_to_channel, buffer);
 
191
      G_UNLOCK (channels_lock);
 
192
      g_free (buffer);
 
193
    }
 
194
}
 
195
 
 
196
/**
 
197
 * ide_log_init:
 
198
 * @stdout_: Indicates logging should be written to stdout.
 
199
 * @filename: An optional file in which to store logs.
 
200
 *
 
201
 * Initializes the logging subsystem.
 
202
 */
 
203
void
 
204
ide_log_init (gboolean     stdout_,
 
205
              const gchar *filename)
 
206
{
 
207
  static gsize initialized = FALSE;
 
208
  GIOChannel *channel;
 
209
 
 
210
  if (g_once_init_enter (&initialized))
 
211
    {
 
212
      log_level_str_func = ide_log_level_str;
 
213
      channels = g_ptr_array_new ();
 
214
      if (filename)
 
215
        {
 
216
          channel = g_io_channel_new_file (filename, "a", NULL);
 
217
          g_ptr_array_add (channels, channel);
 
218
        }
 
219
      if (stdout_)
 
220
        {
 
221
          channel = g_io_channel_unix_new (STDOUT_FILENO);
 
222
          g_ptr_array_add (channels, channel);
 
223
          if ((filename == NULL) && isatty (STDOUT_FILENO))
 
224
            log_level_str_func = ide_log_level_str_with_color;
 
225
        }
 
226
 
 
227
      g_log_set_default_handler (ide_log_handler, NULL);
 
228
      g_once_init_leave (&initialized, TRUE);
 
229
    }
 
230
}
 
231
 
 
232
/**
 
233
 * ide_log_shutdown:
 
234
 *
 
235
 * Cleans up after the logging subsystem.
 
236
 */
 
237
void
 
238
ide_log_shutdown (void)
 
239
{
 
240
  if (last_handler)
 
241
    {
 
242
      g_log_set_default_handler (last_handler, NULL);
 
243
      last_handler = NULL;
 
244
    }
 
245
}
 
246
 
 
247
/**
 
248
 * ide_log_increase_verbosity:
 
249
 *
 
250
 * Increases the amount of logging that will occur. By default, only
 
251
 * warning and above will be displayed.
 
252
 *
 
253
 * Calling this once will cause G_LOG_LEVEL_MESSAGE to be displayed.
 
254
 * Calling this twice will cause G_LOG_LEVEL_INFO to be displayed.
 
255
 * Calling this thrice will cause G_LOG_LEVEL_DEBUG to be displayed.
 
256
 * Calling this four times will cause G_LOG_LEVEL_TRACE to be displayed.
 
257
 *
 
258
 * Note that many DEBUG and TRACE level log messages are only compiled into
 
259
 * debug builds, and therefore will not be available in release builds.
 
260
 *
 
261
 * This method is meant to be called for every -v provided on the command
 
262
 * line.
 
263
 *
 
264
 * Calling this method more than four times is acceptable.
 
265
 */
 
266
void
 
267
ide_log_increase_verbosity (void)
 
268
{
 
269
  log_verbosity++;
 
270
}