static int virLogFormatString(char **msg, int linenr, const char *funcname, virLogPriority priority, const char *str) { int ret; /* * Be careful when changing the following log message formatting, we rely * on it when stripping libvirt debug messages from qemu log files. So when * changing this, you might also need to change the code there. * virLogFormatString() function name is mentioned there so it's sufficient * to just grep for it to find the right place. */ if ((funcname != NULL)) { ret = virAsprintfQuiet(msg, "%llu: %s : %s:%d : %s\n", virThreadSelfID(), virLogPriorityString(priority), funcname, linenr, str); } else { ret = virAsprintfQuiet(msg, "%llu: %s : %s\n", virThreadSelfID(), virLogPriorityString(priority), str); } return ret; }
/** * virLogMessage: * @category: where is that message coming from * @priority: the priority level * @funcname: the function emitting the (debug) message * @linenr: line where the message was emitted * @flags: extra flags, 1 if coming from the error handler * @fmt: the string format * @...: the arguments * * Call the libvirt logger with some informations. Based on the configuration * the message may be stored, sent to output or just discarded */ void virLogMessage(const char *category, int priority, const char *funcname, long long linenr, int flags, const char *fmt, ...) { char *str = NULL; char *msg; struct timeval cur_time; struct tm time_info; int len, fprio, i, ret; if (!virLogInitialized) virLogStartup(); if (fmt == NULL) return; /* * check against list of specific logging patterns */ fprio = virLogFiltersCheck(category); if (fprio == 0) { if (priority < virLogDefaultPriority) return; } else if (priority < fprio) return; /* * serialize the error message, add level and timestamp */ VIR_GET_VAR_STR(fmt, str); if (str == NULL) return; gettimeofday(&cur_time, NULL); localtime_r(&cur_time.tv_sec, &time_info); if ((funcname != NULL)) { ret = virAsprintf(&msg, "%02d:%02d:%02d.%03d: %s : %s:%lld : %s\n", time_info.tm_hour, time_info.tm_min, time_info.tm_sec, (int) cur_time.tv_usec / 1000, virLogPriorityString(priority), funcname, linenr, str); } else { ret = virAsprintf(&msg, "%02d:%02d:%02d.%03d: %s : %s\n", time_info.tm_hour, time_info.tm_min, time_info.tm_sec, (int) cur_time.tv_usec / 1000, virLogPriorityString(priority), str); } VIR_FREE(str); if (ret < 0) { /* apparently we're running out of memory */ return; } /* * Log based on defaults, first store in the history buffer * then push the message on the outputs defined, if none * use stderr. * NOTE: the locking is a single point of contention for multiple * threads, but avoid intermixing. Maybe set up locks per output * to improve paralellism. */ len = strlen(msg); virLogStr(msg, len); virLogLock(); for (i = 0; i < virLogNbOutputs;i++) { if (priority >= virLogOutputs[i].priority) virLogOutputs[i].f(category, priority, funcname, linenr, msg, len, virLogOutputs[i].data); } if ((virLogNbOutputs == 0) && (flags != 1)) ignore_value (safewrite(STDERR_FILENO, msg, len)); virLogUnlock(); VIR_FREE(msg); }