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;
}