X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Futils%2Fmono-logger.c;h=5cc59c77fbe6dd87bf56d097df56dc7380e9baf9;hb=30d60224a85b2e36406bf58e9ab7bfe7ffa6509f;hp=7d0c9ce12a4f811d33e6d5a3bca405b2f564da03;hpb=565c6ac0802eedf68755bd5776c80b00ab388415;p=mono.git diff --git a/mono/utils/mono-logger.c b/mono/utils/mono-logger.c index 7d0c9ce12a4..5cc59c77fbe 100644 --- a/mono/utils/mono-logger.c +++ b/mono/utils/mono-logger.c @@ -11,13 +11,26 @@ typedef struct { MonoTraceMask mask; } MonoLogLevelEntry; -GLogLevelFlags mono_internal_current_level = INT_MAX; -MonoTraceMask mono_internal_current_mask = MONO_TRACE_ALL; +GLogLevelFlags mono_internal_current_level = INT_MAX; +MonoTraceMask mono_internal_current_mask = MONO_TRACE_ALL; +gboolean mono_trace_log_header = FALSE; static GQueue *level_stack = NULL; static const char *mono_log_domain = "Mono"; static MonoPrintCallback print_callback, printerr_callback; +static MonoLogCallParm logCallback = { + .opener = NULL, + .writer = NULL, + .closer = NULL, + .header = FALSE +}; + +typedef struct { + MonoLogCallback legacy_callback; + gpointer user_data; +} UserSuppliedLoggerUserData; + /** * mono_trace_init: * @@ -32,6 +45,8 @@ mono_trace_init (void) mono_trace_set_mask_string(g_getenv("MONO_LOG_MASK")); mono_trace_set_level_string(g_getenv("MONO_LOG_LEVEL")); + mono_trace_set_logheader_string(g_getenv("MONO_LOG_HEADER")); + mono_trace_set_logdest_string(g_getenv("MONO_LOG_DEST")); } } @@ -48,6 +63,7 @@ mono_trace_cleanup (void) g_free (g_queue_pop_head (level_stack)); } + logCallback.closer(); g_queue_free (level_stack); level_stack = NULL; } @@ -65,13 +81,19 @@ mono_trace_cleanup (void) void mono_tracev_inner (GLogLevelFlags level, MonoTraceMask mask, const char *format, va_list args) { + char *log_message; if (level_stack == NULL) { mono_trace_init (); if(level > mono_internal_current_level || !(mask & mono_internal_current_mask)) return; } - g_logv (mono_log_domain, level, format, args); + g_assert (logCallback.opener); // mono_trace_init should have provided us with one! + + if (g_vasprintf (&log_message, format, args) < 0) + return; + logCallback.writer (mono_log_domain, level, logCallback.header, log_message); + g_free (log_message); } /** @@ -107,7 +129,66 @@ mono_trace_set_mask (MonoTraceMask mask) if(level_stack == NULL) mono_trace_init(); - mono_internal_current_mask = mask; + mono_internal_current_mask = mask; +} + +/** + * mono_trace_set_logdest: + * + * @dest: Destination for logging + * + * Sets the current logging destination. This can be a file or, if supported, + * syslog. + */ +void +mono_trace_set_logdest_string (const char *dest) +{ + MonoLogCallParm logger; + + if(level_stack == NULL) + mono_trace_init(); + +#if PLATFORM_ANDROID + logger.opener = mono_log_open_logcat; + logger.writer = mono_log_write_logcat; + logger.closer = mono_log_close_logcat; + logger.dest = (char*) dest; +#elif defined (HOST_IOS) + logger.opener = mono_log_open_asl; + logger.writer = mono_log_write_asl; + logger.closer = mono_log_close_asl; + logger.dest = (char*) dest; +#else + if ((dest == NULL) || (strcmp("syslog", dest) != 0)) { + logger.opener = mono_log_open_logfile; + logger.writer = mono_log_write_logfile; + logger.closer = mono_log_close_logfile; + logger.dest = (char *) dest; + } else { + logger.opener = mono_log_open_syslog; + logger.writer = mono_log_write_syslog; + logger.closer = mono_log_close_syslog; + logger.dest = (char *) dest; + } +#endif + mono_trace_set_log_handler_internal(&logger, NULL); +} + +/** + * mono_trace_set_logheader: + * + * @head: Whether we want pid/date/time header on log messages + * + * Sets the current logging header option. + */ +void +mono_trace_set_logheader_string(const char *head) +{ + if (head == NULL) { + mono_trace_log_header = FALSE; + } else { + mono_trace_log_header = TRUE; + } } /** @@ -193,10 +274,11 @@ mono_trace_set_mask_string (const char *value) const char *tok; guint32 flags = 0; - const char *valid_flags[] = {"asm", "type", "dll", "gc", "cfg", "aot", "security", "threadpool", "io-threadpool", "io-layer", "all", NULL}; + const char *valid_flags[] = {"asm", "type", "dll", "gc", "cfg", "aot", "security", "threadpool", "io-threadpool", "io-layer", "w32handle", "all", NULL}; const MonoTraceMask valid_masks[] = {MONO_TRACE_ASSEMBLY, MONO_TRACE_TYPE, MONO_TRACE_DLLIMPORT, MONO_TRACE_GC, MONO_TRACE_CONFIG, MONO_TRACE_AOT, MONO_TRACE_SECURITY, - MONO_TRACE_THREADPOOL, MONO_TRACE_IO_THREADPOOL, MONO_TRACE_IO_LAYER, MONO_TRACE_ALL }; + MONO_TRACE_THREADPOOL, MONO_TRACE_IO_THREADPOOL, MONO_TRACE_IO_LAYER, + MONO_TRACE_W32HANDLE, MONO_TRACE_ALL }; if(!value) return; @@ -209,7 +291,7 @@ mono_trace_set_mask_string (const char *value) continue; } for (i = 0; valid_flags[i]; i++) { - int len = strlen (valid_flags[i]); + size_t len = strlen (valid_flags[i]); if (strncmp (tok, valid_flags[i], len) == 0 && (tok[len] == 0 || tok[len] == ',')) { flags |= valid_masks[i]; tok += len; @@ -236,30 +318,120 @@ mono_trace_is_traced (GLogLevelFlags level, MonoTraceMask mask) return (level <= mono_internal_current_level && mask & mono_internal_current_mask); } -static MonoLogCallback log_callback; - -static const char* +/** + * log_level_get_name + * @log_level severity level + * + * Convert log level into a string for legacy log handlers + */ +static const char * log_level_get_name (GLogLevelFlags log_level) { - switch (log_level & G_LOG_LEVEL_MASK) { - case G_LOG_LEVEL_ERROR: return "error"; - case G_LOG_LEVEL_CRITICAL: return "critical"; - case G_LOG_LEVEL_WARNING: return "warning"; - case G_LOG_LEVEL_MESSAGE: return "message"; - case G_LOG_LEVEL_INFO: return "info"; - case G_LOG_LEVEL_DEBUG: return "debug"; - default: return "unknown"; + switch (log_level & G_LOG_LEVEL_MASK) { + case G_LOG_LEVEL_ERROR: return "error"; + case G_LOG_LEVEL_CRITICAL: return "critical"; + case G_LOG_LEVEL_WARNING: return "warning"; + case G_LOG_LEVEL_MESSAGE: return "message"; + case G_LOG_LEVEL_INFO: return "info"; + case G_LOG_LEVEL_DEBUG: return "debug"; + default: return "unknown"; + } +} + +/** + * callback_adapter + * + * @log_domain Message prefix + * @log_level Severity + * @message Message to be written + * @fatal Fatal flag - write then abort + * @user_data Argument passed to @callback + * + * This adapts the old callback writer exposed by MonoCallback to the newer method of + * logging. We ignore the header request as legacy handlers never had headers. + */ +static void +callback_adapter (const char *domain, GLogLevelFlags level, mono_bool fatal, const char *message) +{ + UserSuppliedLoggerUserData *ll =logCallback.user_data; + + ll->legacy_callback (domain, log_level_get_name(level), message, fatal, ll->user_data); +} + +static void +eglib_log_adapter (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) +{ + UserSuppliedLoggerUserData *ll = logCallback.user_data; + + ll->legacy_callback (log_domain, log_level_get_name (log_level), message, log_level & G_LOG_LEVEL_ERROR, ll->user_data); +} + +/** + * legacy_opener + * + * Dummy routine for older style loggers + */ +static void +legacy_opener(const char *path, void *user_data) +{ + /* nothing to do */ +} + +/** + * legacy_closer + * + * Cleanup routine for older style loggers + */ +static void +legacy_closer(void) +{ + if (logCallback.user_data != NULL) { + g_free (logCallback.user_data); /* This is a UserSuppliedLoggerUserData struct */ + logCallback.opener = NULL; + logCallback.writer = NULL; + logCallback.closer = NULL; + logCallback.user_data = NULL; + logCallback.header = FALSE; } } +/** + * mono_trace_set_log_handler: + * + * @callback The callback that will replace the default logging handler + * @user_data Argument passed to @callback + * + * The log handler replaces the default runtime logger. All logging requests with be routed to it. + * If the fatal argument in the callback is true, the callback must abort the current process. The runtime expects that + * execution will not resume after a fatal error. + */ +void +mono_trace_set_log_handler (MonoLogCallback callback, void *user_data) +{ + g_assert (callback); + + if (logCallback.closer != NULL) + logCallback.closer(); + UserSuppliedLoggerUserData *ll = g_malloc (sizeof (UserSuppliedLoggerUserData)); + ll->legacy_callback = callback; + ll->user_data = user_data; + logCallback.opener = legacy_opener; + logCallback.writer = callback_adapter; + logCallback.closer = legacy_closer; + logCallback.user_data = ll; + logCallback.dest = NULL; + + g_log_set_default_handler (eglib_log_adapter, user_data); +} + static void -log_adapter (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) +structured_log_adapter (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { - log_callback (log_domain, log_level_get_name (log_level), message, log_level & G_LOG_LEVEL_ERROR, user_data); + logCallback.writer (log_domain, log_level, logCallback.header, message); } /** - * mono_trace_set_log_handler: + * mono_trace_set_log_handler_internal: * * @callback The callback that will replace the default logging handler * @user_data Argument passed to @callback @@ -269,11 +441,19 @@ log_adapter (const gchar *log_domain, GLogLevelFlags log_level, const gchar *mes * execution will not resume after a fatal error. */ void -mono_trace_set_log_handler (MonoLogCallback callback, void *user_data) +mono_trace_set_log_handler_internal (MonoLogCallParm *callback, void *user_data) { g_assert (callback); - log_callback = callback; - g_log_set_default_handler (log_adapter, user_data); + if (logCallback.closer != NULL) + logCallback.closer(); + logCallback.opener = callback->opener; + logCallback.writer = callback->writer; + logCallback.closer = callback->closer; + logCallback.header = mono_trace_log_header; + logCallback.dest = callback->dest; + logCallback.opener (logCallback.dest, user_data); + + g_log_set_default_handler (structured_log_adapter, user_data); } static void