/** * 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 information. 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, unsigned int flags, const char *fmt, ...) { static bool logVersionStderr = true; char *str = NULL; char *msg = NULL; char timestamp[VIR_TIME_STRING_BUFLEN]; int fprio, i, ret; int saved_errno = errno; int emit = 1; va_list ap; if (!virLogInitialized) virLogStartup(); if (fmt == NULL) goto cleanup; /* * check against list of specific logging patterns */ fprio = virLogFiltersCheck(category); if (fprio == 0) { if (priority < virLogDefaultPriority) emit = 0; } else if (priority < fprio) { emit = 0; } if ((emit == 0) && ((virLogBuffer == NULL) || (virLogSize <= 0))) goto cleanup; /* * serialize the error message, add level and timestamp */ va_start(ap, fmt); if (virVasprintf(&str, fmt, ap) < 0) { va_end(ap); goto cleanup; } va_end(ap); ret = virLogFormatString(&msg, funcname, linenr, priority, str); VIR_FREE(str); if (ret < 0) goto cleanup; if (virTimeStringNowRaw(timestamp) < 0) timestamp[0] = '\0'; /* * Log based on defaults, first store in the history buffer, * then if emit 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. */ virLogLock(); virLogStr(timestamp); virLogStr(msg); virLogUnlock(); if (emit == 0) goto cleanup; virLogLock(); for (i = 0; i < virLogNbOutputs; i++) { if (priority >= virLogOutputs[i].priority) { if (virLogOutputs[i].logVersion) { char *ver = NULL; if (virLogVersionString(&ver) >= 0) virLogOutputs[i].f(category, VIR_LOG_INFO, __func__, __LINE__, timestamp, ver, virLogOutputs[i].data); VIR_FREE(ver); virLogOutputs[i].logVersion = false; } virLogOutputs[i].f(category, priority, funcname, linenr, timestamp, msg, virLogOutputs[i].data); } } if ((virLogNbOutputs == 0) && (flags != 1)) { if (logVersionStderr) { char *ver = NULL; if (virLogVersionString(&ver) >= 0) virLogOutputToFd(category, VIR_LOG_INFO, __func__, __LINE__, timestamp, ver, (void *) STDERR_FILENO); VIR_FREE(ver); logVersionStderr = false; } virLogOutputToFd(category, priority, funcname, linenr, timestamp, msg, (void *) STDERR_FILENO); } virLogUnlock(); cleanup: VIR_FREE(msg); errno = saved_errno; }
/** * virLogVMessage: * @source: where is that message coming from * @priority: the priority level * @filename: file where the message was emitted * @linenr: line where the message was emitted * @funcname: the function emitting the (debug) message * @metadata: NULL or metadata array, terminated by an item with NULL key * @fmt: the string format * @vargs: format args * * Call the libvirt logger with some information. Based on the configuration * the message may be stored, sent to output or just discarded */ void virLogVMessage(virLogSourcePtr source, virLogPriority priority, const char *filename, int linenr, const char *funcname, virLogMetadataPtr metadata, const char *fmt, va_list vargs) { static bool logVersionStderr = true; char *str = NULL; char *msg = NULL; char timestamp[VIR_TIME_STRING_BUFLEN]; int ret; size_t i; int saved_errno = errno; unsigned int filterflags = 0; if (virLogInitialize() < 0) return; if (fmt == NULL) return; /* * 3 intentionally non-thread safe variable reads. * Since writes to the variable are serialized on * virLogLock, worst case result is a log message * is accidentally dropped or emitted, if another * thread is updating log filter list concurrently * with a log message emission. */ if (source->serial < virLogFiltersSerial) virLogSourceUpdate(source); if (priority < source->priority) goto cleanup; filterflags = source->flags; /* * serialize the error message, add level and timestamp */ if (virVasprintfQuiet(&str, fmt, vargs) < 0) { goto cleanup; } ret = virLogFormatString(&msg, linenr, funcname, priority, str); if (ret < 0) goto cleanup; if (virTimeStringNowRaw(timestamp) < 0) timestamp[0] = '\0'; virLogLock(); /* * Push the message to the outputs defined, if none exist then * use stderr. */ for (i = 0; i < virLogNbOutputs; i++) { if (priority >= virLogOutputs[i].priority) { if (virLogOutputs[i].logVersion) { const char *rawver; char *ver = NULL; if (virLogVersionString(&rawver, &ver) >= 0) virLogOutputs[i].f(&virLogSelf, VIR_LOG_INFO, __FILE__, __LINE__, __func__, timestamp, NULL, 0, rawver, ver, virLogOutputs[i].data); VIR_FREE(ver); virLogOutputs[i].logVersion = false; } virLogOutputs[i].f(source, priority, filename, linenr, funcname, timestamp, metadata, filterflags, str, msg, virLogOutputs[i].data); } } if (virLogNbOutputs == 0) { if (logVersionStderr) { const char *rawver; char *ver = NULL; if (virLogVersionString(&rawver, &ver) >= 0) virLogOutputToFd(&virLogSelf, VIR_LOG_INFO, __FILE__, __LINE__, __func__, timestamp, NULL, 0, rawver, ver, (void *) STDERR_FILENO); VIR_FREE(ver); logVersionStderr = false; } virLogOutputToFd(source, priority, filename, linenr, funcname, timestamp, metadata, filterflags, str, msg, (void *) STDERR_FILENO); } virLogUnlock(); cleanup: VIR_FREE(str); VIR_FREE(msg); errno = saved_errno; }
/** * virLogVMessage: * @source: where is that message coming from * @priority: the priority level * @filename: file where the message was emitted * @linenr: line where the message was emitted * @funcname: the function emitting the (debug) message * @metadata: NULL or metadata array, terminated by an item with NULL key * @fmt: the string format * @vargs: format args * * Call the libvirt logger with some information. Based on the configuration * the message may be stored, sent to output or just discarded */ void virLogVMessage(virLogSource source, virLogPriority priority, const char *filename, int linenr, const char *funcname, virLogMetadataPtr metadata, const char *fmt, va_list vargs) { static bool logVersionStderr = true; char *str = NULL; char *msg = NULL; char timestamp[VIR_TIME_STRING_BUFLEN]; int fprio, ret; size_t i; int saved_errno = errno; bool emit = true; unsigned int filterflags = 0; if (virLogInitialize() < 0) return; if (fmt == NULL) goto cleanup; /* * check against list of specific logging patterns */ fprio = virLogFiltersCheck(filename, &filterflags); if (fprio == 0) { if (priority < virLogDefaultPriority) emit = false; } else if (priority < fprio) { emit = false; } if (!emit && ((virLogBuffer == NULL) || (virLogSize <= 0))) goto cleanup; /* * serialize the error message, add level and timestamp */ if (virVasprintfQuiet(&str, fmt, vargs) < 0) { goto cleanup; } ret = virLogFormatString(&msg, linenr, funcname, priority, str); if (ret < 0) goto cleanup; if (virTimeStringNowRaw(timestamp) < 0) timestamp[0] = '\0'; /* * Log based on defaults, first store in the history buffer, * then if emit 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. */ virLogLock(); virLogStr(timestamp); virLogStr(": "); virLogStr(msg); virLogUnlock(); if (!emit) goto cleanup; virLogLock(); for (i = 0; i < virLogNbOutputs; i++) { if (priority >= virLogOutputs[i].priority) { if (virLogOutputs[i].logVersion) { const char *rawver; char *ver = NULL; if (virLogVersionString(&rawver, &ver) >= 0) virLogOutputs[i].f(VIR_LOG_FROM_FILE, VIR_LOG_INFO, __FILE__, __LINE__, __func__, timestamp, NULL, 0, rawver, ver, virLogOutputs[i].data); VIR_FREE(ver); virLogOutputs[i].logVersion = false; } virLogOutputs[i].f(source, priority, filename, linenr, funcname, timestamp, metadata, filterflags, str, msg, virLogOutputs[i].data); } } if ((virLogNbOutputs == 0) && (source != VIR_LOG_FROM_ERROR)) { if (logVersionStderr) { const char *rawver; char *ver = NULL; if (virLogVersionString(&rawver, &ver) >= 0) virLogOutputToFd(VIR_LOG_FROM_FILE, VIR_LOG_INFO, __FILE__, __LINE__, __func__, timestamp, NULL, 0, rawver, ver, (void *) STDERR_FILENO); VIR_FREE(ver); logVersionStderr = false; } virLogOutputToFd(source, priority, filename, linenr, funcname, timestamp, metadata, filterflags, str, msg, (void *) STDERR_FILENO); } virLogUnlock(); cleanup: VIR_FREE(str); VIR_FREE(msg); errno = saved_errno; }