int jk_log()

in native/common/jk_util.c [695:836]


int jk_log(jk_log_context_t *log_ctx,
           const char *file, int line, const char *funcname, int level,
           const char *fmt, ...)
{
    int rc = 0;
    jk_logger_t *l;

    /*
     * Need to reserve space for terminating zero byte
     * and platform specific line endings added during the call
     * to the output routing.
     */
    static int usable_size = LOG_BUFFER_SIZE - 3;
    if (!log_ctx || !(l = log_ctx->logger) || !file || !fmt) {
        return -1;
    }

    if ((l->level <= level) || (level == JK_LOG_REQUEST_LEVEL)) {
        char buf[LOG_BUFFER_SIZE];
        char *f = (char *)(file + strlen(file) - 1);
        va_list args;
        int used = 0;

        while (f != file && '\\' != *f && '/' != *f) {
            f--;
        }
        if (f != file) {
            f++;
        }

        used = set_time_str(buf, usable_size, l);

        if (line) { /* line==0 only used for request log item */
            /* Log [requestid] for all levels except REQUEST.
             */
            const char *context_id;
            if (log_ctx == NULL) {
                context_id = "-";
                rc = 1;
            } else if (log_ctx->id == NULL) {
                context_id = "NO-ID";
                rc = 5;
            }
            else {
                context_id = log_ctx->id;
                rc = (int)strlen(context_id);
            }
            if (usable_size - used >= rc + 3) {
                strncpy(buf + used, "[", 1);
                used += 1;
                strncpy(buf + used, context_id, rc);
                used += rc;
                strncpy(buf + used, "] ", 2);
                used += 2;
            }
            else {
                strcpy(buf, "Logging failed in context_id formatting");
                l->log(l, level, (int)strlen(buf), buf);
                return 0;
            }

            /* Log [pid:threadid] for all levels except REQUEST.
             * This information helps to correlate lines from different logs.
             * Performance is no issue, because with production log levels
             * we only call it often, if we have a lot of errors
             */
            rc = snprintf(buf + used, usable_size - used,
                          "[%" JK_PID_T_FMT ":%" JK_PTHREAD_T_FMT "] ", getpid(), jk_gettid());
            used += rc;
            if (rc < 0) {
                strcpy(buf, "Logging failed in pid/tid formatting");
                l->log(l, level, (int)strlen(buf), buf);
                return 0;
            }

            rc = (int)strlen(jk_level_verbs[level]);
            if (usable_size - used >= rc) {
                strncpy(buf + used, jk_level_verbs[level], rc);
                used += rc;
            }
            else {
                strcpy(buf, "Logging failed in log level formatting");
                l->log(l, level, (int)strlen(buf), buf);
                return 0;           /* [V] not sure what to return... */
            }

            if (funcname) {
                rc = (int)strlen(funcname);
                if (usable_size - used >= rc + 2) {
                    strncpy(buf + used, funcname, rc);
                    used += rc;
                    strncpy(buf + used, "::", 2);
                    used += 2;
                }
                else {
                    strcpy(buf, "Logging failed in function name formatting");
                    l->log(l, level, (int)strlen(buf), buf);
                    return 0;           /* [V] not sure what to return... */
                }
            }

            rc = (int)strlen(f);
            if (usable_size - used >= rc) {
                strncpy(buf + used, f, rc);
                used += rc;
            }
            else {
                strcpy(buf, "Logging failed in source file name formatting");
                l->log(l, level, (int)strlen(buf), buf);
                return 0;           /* [V] not sure what to return... */
            }

            rc = snprintf(buf + used, usable_size - used,
                          " (%d): ", line);
            used += rc;
            if (rc < 0 || usable_size - used < 0) {
                strcpy(buf, "Logging failed in line number formatting");
                l->log(l, level, (int)strlen(buf), buf);
                return 0;           /* [V] not sure what to return... */
            }
        }

        va_start(args, fmt);
        rc = vsnprintf(buf + used, usable_size - used, fmt, args);
        va_end(args);
        /* Depending on the snprintf implementation used,
         * "rc == usable_size - used" can indicate not enough space in buffer */
        if (rc < usable_size - used) {
            used += rc;
        }
        else {
            used = usable_size;
            buf[used - 1] = '.';
            buf[used - 2] = '.';
            buf[used - 3] = '.';
        }
        l->log(l, level, used, buf);

    }

    return rc;
}