6 #include "mono-compiler.h"
7 #include "mono-logger-internals.h"
14 GLogLevelFlags mono_internal_current_level = INT_MAX;
15 MonoTraceMask mono_internal_current_mask = MONO_TRACE_ALL;
16 gboolean mono_trace_log_header = FALSE;
18 static GQueue *level_stack = NULL;
19 static const char *mono_log_domain = "Mono";
20 static MonoPrintCallback print_callback, printerr_callback;
22 static MonoLogCallback logCallback = {
32 * Initializes the mono tracer.
35 mono_trace_init (void)
37 if(level_stack == NULL) {
38 mono_internal_current_level = G_LOG_LEVEL_ERROR;
39 level_stack = g_queue_new();
41 mono_trace_set_mask_string(g_getenv("MONO_LOG_MASK"));
42 mono_trace_set_level_string(g_getenv("MONO_LOG_LEVEL"));
43 mono_trace_set_logheader_string(g_getenv("MONO_LOG_HEADER"));
44 mono_trace_set_logdest_string(g_getenv("MONO_LOG_DEST"));
51 * Releases the mono tracer.
54 mono_trace_cleanup (void)
56 if(level_stack != NULL) {
57 while(!g_queue_is_empty (level_stack)) {
58 g_free (g_queue_pop_head (level_stack));
61 g_queue_free (level_stack);
69 * @level: Verbose level of the specified message
70 * @mask: Type of the specified message
72 * Traces a new message, depending on the current logging level
76 mono_tracev_inner (GLogLevelFlags level, MonoTraceMask mask, const char *format, va_list args)
78 if (level_stack == NULL) {
80 if(level > mono_internal_current_level || !(mask & mono_internal_current_mask))
84 if (logCallback.opener == NULL) {
85 logCallback.opener = mono_log_open_logfile;
86 logCallback.writer = mono_log_write_logfile;
87 logCallback.closer = mono_log_close_logfile;
88 logCallback.opener(NULL, NULL);
90 logCallback.writer(mono_log_domain, level, logCallback.header, format, args);
94 * mono_trace_set_level:
96 * @level: Verbose level to set
98 * Sets the current logging level. Every subsequent call to
99 * mono_trace will check the visibility of a message against this
103 mono_trace_set_level (GLogLevelFlags level)
105 if(level_stack == NULL)
108 mono_internal_current_level = level;
112 * mono_trace_set_mask:
114 * @mask: Mask of visible message types.
116 * Sets the current logging level. Every subsequent call to
117 * mono_trace will check the visibility of a message against this
121 mono_trace_set_mask (MonoTraceMask mask)
123 if(level_stack == NULL)
126 mono_internal_current_mask = mask;
130 * mono_trace_set_logdest:
132 * @dest: Destination for logging
134 * Sets the current logging destination. This can be a file or, if supported,
138 mono_trace_set_logdest_string (const char *dest)
140 MonoLogCallback logger;
142 if(level_stack == NULL)
145 if ((dest == NULL) || (strcmp("syslog", dest) != 0)) {
146 logger.opener = mono_log_open_logfile;
147 logger.writer = mono_log_write_logfile;
148 logger.closer = mono_log_close_logfile;
149 mono_trace_set_log_handler(&logger, dest, NULL);
151 logger.opener = mono_log_open_syslog;
152 logger.writer = mono_log_write_syslog;
153 logger.closer = mono_log_close_syslog;
154 mono_trace_set_log_handler(&logger, mono_log_domain, NULL);
159 * mono_trace_set_logheader:
161 * @head: Whether we want pid/date/time header on log messages
163 * Sets the current logging header option.
166 mono_trace_set_logheader_string(const char *head)
168 MonoLogCallback logger;
171 mono_trace_log_header = FALSE;
173 mono_trace_log_header = TRUE;
180 * @level: Verbose level to set
181 * @mask: Mask of visible message types.
183 * Saves the current values of level and mask then calls mono_trace_set
184 * with the specified new values.
187 mono_trace_push (GLogLevelFlags level, MonoTraceMask mask)
189 if(level_stack == NULL)
190 g_error("%s: cannot use mono_trace_push without calling mono_trace_init first.", __func__);
192 MonoLogLevelEntry *entry = (MonoLogLevelEntry *) g_malloc(sizeof(MonoLogLevelEntry));
193 entry->level = mono_internal_current_level;
194 entry->mask = mono_internal_current_mask;
196 g_queue_push_head (level_stack, (gpointer)entry);
198 /* Set the new level and mask
200 mono_internal_current_level = level;
201 mono_internal_current_mask = mask;
208 * Restores level and mask values saved from a previous call to mono_trace_push.
211 mono_trace_pop (void)
213 if(level_stack == NULL)
214 g_error("%s: cannot use mono_trace_pop without calling mono_trace_init first.", __func__);
216 if(!g_queue_is_empty (level_stack)) {
217 MonoLogLevelEntry *entry = (MonoLogLevelEntry*)g_queue_pop_head (level_stack);
219 /* Restore previous level and mask
221 mono_internal_current_level = entry->level;
222 mono_internal_current_mask = entry->mask;
231 mono_trace_set_level_string (const char *value)
234 const char *valid_vals[] = {"error", "critical", "warning", "message", "info", "debug", NULL};
235 const GLogLevelFlags valid_ids[] = {G_LOG_LEVEL_ERROR, G_LOG_LEVEL_CRITICAL, G_LOG_LEVEL_WARNING,
236 G_LOG_LEVEL_MESSAGE, G_LOG_LEVEL_INFO, G_LOG_LEVEL_DEBUG };
241 while(valid_vals[i]) {
242 if(!strcmp(valid_vals[i], value)){
243 mono_trace_set_level(valid_ids[i]);
250 g_print("Unknown trace loglevel: %s\n", value);
254 mono_trace_set_mask_string (const char *value)
260 const char *valid_flags[] = {"asm", "type", "dll", "gc", "cfg", "aot", "security", "threadpool", "io-threadpool", "io-layer", "all", NULL};
261 const MonoTraceMask valid_masks[] = {MONO_TRACE_ASSEMBLY, MONO_TRACE_TYPE, MONO_TRACE_DLLIMPORT,
262 MONO_TRACE_GC, MONO_TRACE_CONFIG, MONO_TRACE_AOT, MONO_TRACE_SECURITY,
263 MONO_TRACE_THREADPOOL, MONO_TRACE_IO_THREADPOOL, MONO_TRACE_IO_LAYER, MONO_TRACE_ALL };
275 for (i = 0; valid_flags[i]; i++) {
276 int len = strlen (valid_flags[i]);
277 if (strncmp (tok, valid_flags[i], len) == 0 && (tok[len] == 0 || tok[len] == ',')) {
278 flags |= valid_masks[i];
283 if (!valid_flags[i]) {
284 g_print("Unknown trace flag: %s\n", tok);
289 mono_trace_set_mask ((MonoTraceMask) flags);
293 * mono_trace_is_traced:
295 * Returns whenever a message with @level and @mask will be printed or not.
298 mono_trace_is_traced (GLogLevelFlags level, MonoTraceMask mask)
300 return (level <= mono_internal_current_level && mask & mono_internal_current_mask);
304 * mono_trace_set_log_handler:
306 * @callback The callback that will replace the default logging handler
307 * @user_data Argument passed to @callback
309 * The log handler replaces the default runtime logger. All logging requests with be routed to it.
310 * If the fatal argument in the callback is true, the callback must abort the current process. The runtime expects that
311 * execution will not resume after a fatal error.
314 mono_trace_set_log_handler (MonoLogCallback *callback, const char *dest, void *user_data)
317 logCallback.opener = callback->opener;
318 logCallback.writer = callback->writer;
319 logCallback.closer = callback->closer;
320 logCallback.header = mono_trace_log_header;
321 logCallback.opener(dest, user_data);
325 print_handler (const char *string)
327 print_callback (string, TRUE);
331 printerr_handler (const char *string)
333 printerr_callback (string, FALSE);
337 * mono_trace_set_print_handler:
339 * @callback The callback that will replace the default runtime behavior for stdout output.
341 * The print handler replaces the default runtime stdout output handler. This is used by free form output done by the runtime.
345 mono_trace_set_print_handler (MonoPrintCallback callback)
348 print_callback = callback;
349 g_set_print_handler (print_handler);
353 * mono_trace_set_printerr_handler:
355 * @callback The callback that will replace the default runtime behavior for stderr output.
357 * The print handler replaces the default runtime stderr output handler. This is used by free form output done by the runtime.
361 mono_trace_set_printerr_handler (MonoPrintCallback callback)
364 printerr_callback = callback;
365 g_set_printerr_handler (printerr_handler);