Exemplo n.º 1
0
/**
 * virLogStartup:
 *
 * Initialize the logging module
 *
 * Returns 0 if successful, and -1 in case or error
 */
int virLogStartup(void) {
    const char *pbm = NULL;

    if (virLogInitialized)
        return -1;

    if (virMutexInit(&virLogMutex) < 0)
        return -1;

    virLogInitialized = 1;
    virLogLock();
    if (VIR_ALLOC_N(virLogBuffer, virLogSize + 1) < 0) {
        /*
         * The debug buffer is not a critical component, allow startup
         * even in case of failure to allocate it in case of a
         * configuration mistake.
         */
        virLogSize = 64 * 1024;
        if (VIR_ALLOC_N(virLogBuffer, virLogSize + 1) < 0) {
            pbm = "Failed to allocate debug buffer: deactivating debug log\n";
            virLogSize = 0;
        } else {
            pbm = "Failed to allocate debug buffer: reduced to 64 kB\n";
        }
    }
    virLogLen = 0;
    virLogStart = 0;
    virLogEnd = 0;
    virLogDefaultPriority = VIR_LOG_DEFAULT;
    virLogUnlock();
    if (pbm)
        VIR_WARN("%s", pbm);
    return 0;
}
Exemplo n.º 2
0
/**
 * virLogDefineFilter:
 * @match: the pattern to match
 * @priority: the priority to give to messages matching the pattern
 * @flags: extra flag, currently unused
 *
 * Defines a pattern used for log filtering, it allow to select or
 * reject messages independently of the default priority.
 * The filter defines a rules that will apply only to messages matching
 * the pattern (currently if @match is a substring of the message category)
 *
 * Returns -1 in case of failure or the filter number if successful
 */
int virLogDefineFilter(const char *match, int priority,
                       int flags ATTRIBUTE_UNUSED) {
    int i;
    char *mdup = NULL;

    if ((match == NULL) || (priority < VIR_LOG_DEBUG) ||
        (priority > VIR_LOG_ERROR))
        return(-1);

    virLogLock();
    for (i = 0;i < virLogNbFilters;i++) {
        if (STREQ(virLogFilters[i].match, match)) {
            virLogFilters[i].priority = priority;
            goto cleanup;
        }
    }

    mdup = strdup(match);
    if (mdup == NULL) {
        i = -1;
        goto cleanup;
    }
    i = virLogNbFilters;
    if (VIR_REALLOC_N(virLogFilters, virLogNbFilters + 1)) {
        i = -1;
        VIR_FREE(mdup);
        goto cleanup;
    }
    virLogFilters[i].match = mdup;
    virLogFilters[i].priority = priority;
    virLogNbFilters++;
cleanup:
    virLogUnlock();
    return(i);
}
Exemplo n.º 3
0
/**
 * virLogDefineOutput:
 * @f: the function to call to output a message
 * @c: the function to call to close the output (or NULL)
 * @data: extra data passed as first arg to the function
 * @priority: minimal priority for this filter, use 0 for none
 * @dest: where to send output of this priority
 * @name: optional name data associated with an output
 * @flags: extra flag, currently unused
 *
 * Defines an output function for log messages. Each message once
 * gone though filtering is emitted through each registered output.
 *
 * Returns -1 in case of failure or the output number if successful
 */
int virLogDefineOutput(virLogOutputFunc f, virLogCloseFunc c, void *data,
                       int priority, int dest, const char *name,
                       int flags ATTRIBUTE_UNUSED) {
    int ret = -1;
    char *ndup = NULL;

    if (f == NULL)
        return(-1);

    if (dest == VIR_LOG_TO_SYSLOG || dest == VIR_LOG_TO_FILE) {
        if (name == NULL)
            return(-1);
        ndup = strdup(name);
        if (ndup == NULL)
            return(-1);
    }

    virLogLock();
    if (VIR_REALLOC_N(virLogOutputs, virLogNbOutputs + 1)) {
        VIR_FREE(ndup);
        goto cleanup;
    }
    ret = virLogNbOutputs++;
    virLogOutputs[ret].f = f;
    virLogOutputs[ret].c = c;
    virLogOutputs[ret].data = data;
    virLogOutputs[ret].priority = priority;
    virLogOutputs[ret].dest = dest;
    virLogOutputs[ret].name = ndup;
cleanup:
    virLogUnlock();
    return(ret);
}
Exemplo n.º 4
0
/*
 * Store a string in the ring buffer
 */
static void virLogStr(const char *str, int len) {
    int tmp;

    if (str == NULL)
        return;
    if (len <= 0)
        len = strlen(str);
    if (len > LOG_BUFFER_SIZE)
        return;
    virLogLock();

    /*
     * copy the data and reset the end, we cycle over the end of the buffer
     */
    if (virLogEnd + len >= LOG_BUFFER_SIZE) {
        tmp = LOG_BUFFER_SIZE - virLogEnd;
        memcpy(&virLogBuffer[virLogEnd], str, tmp);
        virLogBuffer[LOG_BUFFER_SIZE] = 0;
        memcpy(&virLogBuffer[0], &str[tmp], len - tmp);
        virLogEnd = len - tmp;
    } else {
        memcpy(&virLogBuffer[virLogEnd], str, len);
        virLogEnd += len;
    }
    /*
     * Update the log length, and if full move the start index
     */
    virLogLen += len;
    if (virLogLen > LOG_BUFFER_SIZE) {
        tmp = virLogLen - LOG_BUFFER_SIZE;
        virLogLen = LOG_BUFFER_SIZE;
        virLogStart += tmp;
    }
    virLogUnlock();
}
Exemplo n.º 5
0
/**
 * virLogShutdown:
 *
 * Shutdown the logging module
 */
void virLogShutdown(void) {
    if (!virLogInitialized)
        return;
    virLogLock();
    virLogResetFilters();
    virLogResetOutputs();
    virLogLen = 0;
    virLogStart = 0;
    virLogEnd = 0;
    virLogUnlock();
    virMutexDestroy(&virLogMutex);
    virLogInitialized = 0;
}
Exemplo n.º 6
0
/**
 * virLogReset:
 *
 * Reset the logging module to its default initial state
 *
 * Returns 0 if successful, and -1 in case or error
 */
int
virLogReset(void)
{
    if (virLogInitialize() < 0)
        return -1;

    virLogLock();
    virLogResetFilters();
    virLogResetOutputs();
    virLogDefaultPriority = VIR_LOG_DEFAULT;
    virLogUnlock();
    return 0;
}
Exemplo n.º 7
0
/**
 * virLogReset:
 *
 * Reset the logging module to its default initial state
 *
 * Returns 0 if successful, and -1 in case or error
 */
int virLogReset(void) {
    if (!virLogInitialized)
        return(virLogStartup());

    virLogLock();
    virLogResetFilters();
    virLogResetOutputs();
    virLogLen = 0;
    virLogStart = 0;
    virLogEnd = 0;
    virLogDefaultPriority = VIR_LOG_DEFAULT;
    virLogUnlock();
    return(0);
}
Exemplo n.º 8
0
/**
 * virLogFiltersCheck:
 * @input: the input string
 *
 * Check the input of the message against the existing filters. Currently
 * the match is just a substring check of the category used as the input
 * string, a more subtle approach could be used instead
 *
 * Returns 0 if not matched or the new priority if found.
 */
static int virLogFiltersCheck(const char *input) {
    int ret = 0;
    int i;

    virLogLock();
    for (i = 0;i < virLogNbFilters;i++) {
        if (strstr(input, virLogFilters[i].match)) {
            ret = virLogFilters[i].priority;
            break;
        }
    }
    virLogUnlock();
    return(ret);
}
Exemplo n.º 9
0
/**
 * virLogStartup:
 *
 * Initialize the logging module
 *
 * Returns 0 if successful, and -1 in case or error
 */
int virLogStartup(void) {
    if (virLogInitialized)
        return(-1);

    if (virMutexInit(&virLogMutex) < 0)
        return -1;

    virLogInitialized = 1;
    virLogLock();
    virLogLen = 0;
    virLogStart = 0;
    virLogEnd = 0;
    virLogDefaultPriority = VIR_LOG_DEFAULT;
    virLogUnlock();
    return(0);
}
Exemplo n.º 10
0
/**
 * virLogSetBufferSize:
 * @size: size of the buffer in kilobytes or <= 0 to deactivate
 *
 * Dynamically set the size or deactivate the logging buffer used to keep
 * a trace of all recent debug output. Note that the content of the buffer
 * is lost if it gets reallocated.
 *
 * Return -1 in case of failure or 0 in case of success
 */
int
virLogSetBufferSize(int size)
{
    int ret = 0;
    int oldsize;
    char *oldLogBuffer;
    const char *pbm = NULL;

    if (size < 0)
        size = 0;

    if (virLogInitialize() < 0)
        return -1;

    if (size * 1024 == virLogSize)
        return ret;

    virLogLock();

    oldsize = virLogSize;
    oldLogBuffer = virLogBuffer;

    if (INT_MAX / 1024 <= size) {
        pbm = "Requested log size of %d kB too large\n";
        ret = -1;
        goto error;
    }

    virLogSize = size * 1024;
    if (VIR_ALLOC_N_QUIET(virLogBuffer, virLogSize + 1) < 0) {
        pbm = "Failed to allocate debug buffer of %d kB\n";
        virLogBuffer = oldLogBuffer;
        virLogSize = oldsize;
        ret = -1;
        goto error;
    }
    VIR_FREE(oldLogBuffer);
    virLogLen = 0;
    virLogStart = 0;
    virLogEnd = 0;

error:
    virLogUnlock();
    if (pbm)
        VIR_ERROR(pbm, size);
    return ret;
}
Exemplo n.º 11
0
/**
 * virLogDefineOutput:
 * @f: the function to call to output a message
 * @c: the function to call to close the output (or NULL)
 * @data: extra data passed as first arg to the function
 * @priority: minimal priority for this filter, use 0 for none
 * @dest: where to send output of this priority
 * @name: optional name data associated with an output
 * @flags: extra flag, currently unused
 *
 * Defines an output function for log messages. Each message once
 * gone though filtering is emitted through each registered output.
 *
 * Returns -1 in case of failure or the output number if successful
 */
int
virLogDefineOutput(virLogOutputFunc f,
                   virLogCloseFunc c,
                   void *data,
                   virLogPriority priority,
                   virLogDestination dest,
                   const char *name,
                   unsigned int flags)
{
    int ret = -1;
    char *ndup = NULL;

    virCheckFlags(0, -1);

    if (virLogInitialize() < 0)
        return -1;

    if (f == NULL)
        return -1;

    if (dest == VIR_LOG_TO_SYSLOG || dest == VIR_LOG_TO_FILE) {
        if (!name) {
            virReportOOMError();
            return -1;
        }
        if (VIR_STRDUP(ndup, name) < 0)
            return -1;
    }

    virLogLock();
    if (VIR_REALLOC_N_QUIET(virLogOutputs, virLogNbOutputs + 1)) {
        VIR_FREE(ndup);
        goto cleanup;
    }
    ret = virLogNbOutputs++;
    virLogOutputs[ret].logVersion = true;
    virLogOutputs[ret].f = f;
    virLogOutputs[ret].c = c;
    virLogOutputs[ret].data = data;
    virLogOutputs[ret].priority = priority;
    virLogOutputs[ret].dest = dest;
    virLogOutputs[ret].name = ndup;
 cleanup:
    virLogUnlock();
    return ret;
}
Exemplo n.º 12
0
static int
virLogOnceInit(void)
{
    if (virMutexInit(&virLogMutex) < 0)
        return -1;

    virLogLock();
    virLogDefaultPriority = VIR_LOG_DEFAULT;

    if (VIR_ALLOC_QUIET(virLogRegex) >= 0) {
        if (regcomp(virLogRegex, VIR_LOG_REGEX, REG_EXTENDED) != 0)
            VIR_FREE(virLogRegex);
    }

    virLogUnlock();
    return 0;
}
Exemplo n.º 13
0
/**
 * virLogDefineFilter:
 * @match: the pattern to match
 * @priority: the priority to give to messages matching the pattern
 * @flags: extra flags, see virLogFilterFlags enum
 *
 * Defines a pattern used for log filtering, it allow to select or
 * reject messages independently of the default priority.
 * The filter defines a rules that will apply only to messages matching
 * the pattern (currently if @match is a substring of the message category)
 *
 * Returns -1 in case of failure or the filter number if successful
 */
int
virLogDefineFilter(const char *match,
                   virLogPriority priority,
                   unsigned int flags)
{
    size_t i;
    int ret = -1;
    char *mdup = NULL;

    virCheckFlags(VIR_LOG_STACK_TRACE, -1);

    if (virLogInitialize() < 0)
        return -1;

    if ((match == NULL) || (priority < VIR_LOG_DEBUG) ||
        (priority > VIR_LOG_ERROR))
        return -1;

    virLogLock();
    for (i = 0; i < virLogNbFilters; i++) {
        if (STREQ(virLogFilters[i].match, match)) {
            virLogFilters[i].priority = priority;
            ret = i;
            goto cleanup;
        }
    }

    if (VIR_STRDUP_QUIET(mdup, match) < 0)
        goto cleanup;
    if (VIR_REALLOC_N_QUIET(virLogFilters, virLogNbFilters + 1)) {
        VIR_FREE(mdup);
        goto cleanup;
    }
    ret = virLogNbFilters;
    virLogFilters[i].match = mdup;
    virLogFilters[i].priority = priority;
    virLogFilters[i].flags = flags;
    virLogNbFilters++;
    virLogFiltersSerial++;
 cleanup:
    virLogUnlock();
    if (ret < 0)
        virReportOOMError();
    return ret;
}
Exemplo n.º 14
0
/**
 * virLogFiltersCheck:
 * @input: the input string
 *
 * Check the input of the message against the existing filters. Currently
 * the match is just a substring check of the category used as the input
 * string, a more subtle approach could be used instead
 *
 * Returns 0 if not matched or the new priority if found.
 */
static int
virLogFiltersCheck(const char *input,
                   unsigned int *flags)
{
    int ret = 0;
    size_t i;

    virLogLock();
    for (i = 0; i < virLogNbFilters; i++) {
        if (strstr(input, virLogFilters[i].match)) {
            ret = virLogFilters[i].priority;
            *flags = virLogFilters[i].flags;
            break;
        }
    }
    virLogUnlock();
    return ret;
}
Exemplo n.º 15
0
/*
 * Output the ring buffer
 */
static int virLogDump(void *data, virLogOutputFunc f) {
    int ret = 0, tmp;

    if ((virLogLen == 0) || (f == NULL))
        return(0);
    virLogLock();
    if (virLogStart + virLogLen < LOG_BUFFER_SIZE) {
push_end:
        virLogBuffer[virLogStart + virLogLen] = 0;
        tmp = f(data, &virLogBuffer[virLogStart], virLogLen);
        if (tmp < 0) {
            ret = -1;
            goto error;
        }
        ret += tmp;
        virLogStart += tmp;
        virLogLen -= tmp;
    } else {
        tmp = LOG_BUFFER_SIZE - virLogStart;
        ret = f(data, &virLogBuffer[virLogStart], tmp);
        if (ret < 0) {
            ret = -1;
            goto error;
        }
        if (ret < tmp) {
            virLogStart += ret;
            virLogLen -= ret;
        } else {
            virLogStart = 0;
            virLogLen -= tmp;
            /* dump the second part */
            if (virLogLen > 0)
                goto push_end;
        }
    }
error:
    virLogUnlock();
    return(ret);
}
Exemplo n.º 16
0
static int
virLogOnceInit(void)
{
    const char *pbm = NULL;

    if (virMutexInit(&virLogMutex) < 0)
        return -1;

    virLogLock();
    if (VIR_ALLOC_N_QUIET(virLogBuffer, virLogSize + 1) < 0) {
        /*
         * The debug buffer is not a critical component, allow startup
         * even in case of failure to allocate it in case of a
         * configuration mistake.
         */
        virLogSize = 64 * 1024;
        if (VIR_ALLOC_N_QUIET(virLogBuffer, virLogSize + 1) < 0) {
            pbm = "Failed to allocate debug buffer: deactivating debug log\n";
            virLogSize = 0;
        } else {
            pbm = "Failed to allocate debug buffer: reduced to 64 kB\n";
        }
    }
    virLogLen = 0;
    virLogStart = 0;
    virLogEnd = 0;
    virLogDefaultPriority = VIR_LOG_DEFAULT;

    if (VIR_ALLOC_QUIET(virLogRegex) >= 0) {
        if (regcomp(virLogRegex, VIR_LOG_REGEX, REG_EXTENDED) != 0)
            VIR_FREE(virLogRegex);
    }

    virLogUnlock();
    if (pbm)
        VIR_WARN("%s", pbm);
    return 0;
}
Exemplo n.º 17
0
static void
virLogSourceUpdate(virLogSourcePtr source)
{
    virLogLock();
    if (source->serial < virLogFiltersSerial) {
        unsigned int priority = virLogDefaultPriority;
        unsigned int flags = 0;
        size_t i;

        for (i = 0; i < virLogNbFilters; i++) {
            if (strstr(source->name, virLogFilters[i].match)) {
                priority = virLogFilters[i].priority;
                flags = virLogFilters[i].flags;
                break;
            }
        }

        source->priority = priority;
        source->flags = flags;
        source->serial = virLogFiltersSerial;
    }
    virLogUnlock();
}
Exemplo n.º 18
0
/**
 * virLogDefineOutput:
 * @f: the function to call to output a message
 * @c: the function to call to close the output (or NULL)
 * @data: extra data passed as first arg to the function
 * @priority: minimal priority for this filter, use 0 for none
 * @dest: where to send output of this priority
 * @name: optional name data associated with an output
 * @flags: extra flag, currently unused
 *
 * Defines an output function for log messages. Each message once
 * gone though filtering is emitted through each registered output.
 *
 * Returns -1 in case of failure or the output number if successful
 */
int virLogDefineOutput(virLogOutputFunc f, virLogCloseFunc c, void *data,
                       int priority, int dest, const char *name,
                       unsigned int flags)
{
    int ret = -1;
    char *ndup = NULL;

    virCheckFlags(0, -1);

    if (f == NULL)
        return -1;

    if (dest == VIR_LOG_TO_SYSLOG || dest == VIR_LOG_TO_FILE) {
        if (name == NULL)
            return -1;
        ndup = strdup(name);
        if (ndup == NULL)
            return -1;
    }

    virLogLock();
    if (VIR_REALLOC_N(virLogOutputs, virLogNbOutputs + 1)) {
        VIR_FREE(ndup);
        goto cleanup;
    }
    ret = virLogNbOutputs++;
    virLogOutputs[ret].logVersion = true;
    virLogOutputs[ret].f = f;
    virLogOutputs[ret].c = c;
    virLogOutputs[ret].data = data;
    virLogOutputs[ret].priority = priority;
    virLogOutputs[ret].dest = dest;
    virLogOutputs[ret].name = ndup;
cleanup:
    virLogUnlock();
    return ret;
}
Exemplo n.º 19
0
/**
 * 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);
}
Exemplo n.º 20
0
/**
 * 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;
}
Exemplo n.º 21
0
/**
 * 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;
}
Exemplo n.º 22
0
/**
 * 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;
}