mirror of https://github.com/yandex/odyssey.git
244 lines
6.0 KiB
C
244 lines
6.0 KiB
C
|
|
/*
|
|
* Odissey.
|
|
*
|
|
* Advanced PostgreSQL connection pooler.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <inttypes.h>
|
|
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include <sys/fcntl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/time.h>
|
|
|
|
#include <machinarium.h>
|
|
#include <shapito.h>
|
|
|
|
#include "sources/macro.h"
|
|
#include "sources/pid.h"
|
|
#include "sources/id.h"
|
|
#include "sources/log_file.h"
|
|
#include "sources/log_system.h"
|
|
#include "sources/logger.h"
|
|
|
|
typedef struct {
|
|
od_logsystem_prio_t syslog_prio;
|
|
char *ident;
|
|
char *ident_short;
|
|
} od_logger_ident_t;
|
|
|
|
static od_logger_ident_t od_logger_ident_tab[] =
|
|
{
|
|
[OD_LOG] = { OD_LOGSYSTEM_INFO, "info", NULL },
|
|
[OD_LOG_ERROR] = { OD_LOGSYSTEM_ERROR, "error", "error" },
|
|
[OD_LOG_CLIENT] = { OD_LOGSYSTEM_INFO, "client_info", NULL },
|
|
[OD_LOG_CLIENT_ERROR] = { OD_LOGSYSTEM_ERROR, "client_error", "error" },
|
|
[OD_LOG_CLIENT_DEBUG] = { OD_LOGSYSTEM_DEBUG, "client_debug", "debug" },
|
|
[OD_LOG_SERVER] = { OD_LOGSYSTEM_INFO, "server_info", NULL },
|
|
[OD_LOG_SERVER_ERROR] = { OD_LOGSYSTEM_ERROR, "server_error", "error" },
|
|
[OD_LOG_SERVER_DEBUG] = { OD_LOGSYSTEM_DEBUG, "server_debug", "debug" }
|
|
};
|
|
|
|
static inline void
|
|
od_logger_write(od_logger_t *logger, od_logger_ident_t *ident,
|
|
char *buf, int buf_len)
|
|
{
|
|
od_logfile_write(&logger->log, buf, buf_len);
|
|
od_logsystem(&logger->log_system, ident->syslog_prio, buf, buf_len);
|
|
if (logger->log_stdout) {
|
|
write(0, buf, buf_len);
|
|
}
|
|
}
|
|
|
|
static void
|
|
od_logger_text(od_logger_t *logger,
|
|
od_logger_event_t event,
|
|
od_id_t *id,
|
|
char *context,
|
|
char *fmt, va_list args)
|
|
{
|
|
char buf[512];
|
|
int buf_len;
|
|
|
|
/* pid */
|
|
buf_len = snprintf(buf, sizeof(buf), "%s ", logger->pid->pid_sz);
|
|
|
|
/* timestamp */
|
|
struct timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
buf_len += strftime(buf + buf_len, sizeof(buf) - buf_len, "%d %b %H:%M:%S.",
|
|
localtime(&tv.tv_sec));
|
|
buf_len += snprintf(buf + buf_len, sizeof(buf) - buf_len, "%03d ",
|
|
(signed)tv.tv_usec / 1000);
|
|
|
|
/* ident */
|
|
od_logger_ident_t *ident;
|
|
ident = &od_logger_ident_tab[event];
|
|
if (ident->ident_short) {
|
|
buf_len += snprintf(buf + buf_len, sizeof(buf) - buf_len, "%s: ",
|
|
ident->ident_short);
|
|
}
|
|
|
|
/* id */
|
|
if (id) {
|
|
buf_len += snprintf(buf + buf_len, sizeof(buf) - buf_len, "%s%.*s: ",
|
|
id->id_prefix,
|
|
(signed)sizeof(id->id), id->id);
|
|
}
|
|
|
|
/* context */
|
|
if (context) {
|
|
buf_len += snprintf(buf + buf_len, sizeof(buf) - buf_len, "(%s) ",
|
|
context);
|
|
}
|
|
|
|
/* message */
|
|
buf_len += vsnprintf(buf + buf_len, sizeof(buf) - buf_len, fmt, args);
|
|
buf_len += snprintf(buf + buf_len, sizeof(buf) - buf_len, "\n");
|
|
|
|
/* write log message */
|
|
od_logger_write(logger, ident, buf, buf_len);
|
|
}
|
|
|
|
static char od_logger_tskv_escape_tab[256] =
|
|
{
|
|
['\0'] = '0',
|
|
['\t'] = 't',
|
|
['\n'] = 'n',
|
|
['\r'] = 'r',
|
|
['\\'] = '\\',
|
|
['='] = '='
|
|
};
|
|
|
|
__attribute__((hot)) static inline int
|
|
od_logger_tskv_escape(char *dest, int size, char *fmt, va_list args)
|
|
{
|
|
char prefmt[512];
|
|
int prefmt_len;
|
|
prefmt_len = vsnprintf(prefmt, sizeof(prefmt), fmt, args);
|
|
|
|
char *dst_pos = dest;
|
|
char *dst_end = dest + size;
|
|
char *msg_pos = prefmt;
|
|
char *msg_end = prefmt + prefmt_len;
|
|
|
|
while (msg_pos < msg_end) {
|
|
char escaped_char;
|
|
escaped_char = od_logger_tskv_escape_tab[(int)*msg_pos];
|
|
if (od_unlikely(escaped_char)) {
|
|
if (od_unlikely((dst_end - dst_pos) < 2))
|
|
break;
|
|
dst_pos[0] = '\\';
|
|
dst_pos[1] = escaped_char;
|
|
dst_pos += 2;
|
|
} else {
|
|
if (od_unlikely((dst_end - dst_pos) < 1))
|
|
break;
|
|
dst_pos[0] = *msg_pos;
|
|
dst_pos += 1;
|
|
}
|
|
msg_pos++;
|
|
}
|
|
return dst_pos - dest;
|
|
}
|
|
|
|
static void
|
|
od_logger_tskv(od_logger_t *logger,
|
|
od_logger_event_t event,
|
|
od_id_t *id,
|
|
char *context,
|
|
char *fmt, va_list args)
|
|
{
|
|
char buf[512];
|
|
int buf_len;
|
|
|
|
/* begin */
|
|
buf_len = snprintf(buf, sizeof(buf), "tskv\t");
|
|
|
|
/* ident */
|
|
od_logger_ident_t *ident;
|
|
ident = &od_logger_ident_tab[event];
|
|
buf_len += snprintf(buf + buf_len, sizeof(buf) - buf_len, "event=%s\t",
|
|
ident->ident);
|
|
|
|
/* timestamp */
|
|
struct timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
buf_len += strftime(buf + buf_len, sizeof(buf) - buf_len, "timestamp=%Y-%m-%d %H:%M:%S\t",
|
|
localtime(&tv.tv_sec));
|
|
|
|
/* pid */
|
|
buf_len += snprintf(buf + buf_len, sizeof(buf) - buf_len, "pid=%s\t",
|
|
logger->pid->pid_sz);
|
|
|
|
/* id */
|
|
if (id) {
|
|
buf_len += snprintf(buf + buf_len, sizeof(buf) - buf_len, "id=%s%.*s\t",
|
|
id->id_prefix,
|
|
(signed)sizeof(id->id), id->id);
|
|
}
|
|
|
|
/* context */
|
|
if (context) {
|
|
buf_len += snprintf(buf + buf_len, sizeof(buf) - buf_len, "context=%s\t",
|
|
context);
|
|
}
|
|
|
|
/* message */
|
|
buf_len += snprintf(buf + buf_len, sizeof(buf) - buf_len, "msg=");
|
|
buf_len += od_logger_tskv_escape(buf + buf_len, sizeof(buf) - buf_len, fmt, args);
|
|
buf_len += snprintf(buf + buf_len, sizeof(buf) - buf_len, "\t\n");
|
|
|
|
/* write log message */
|
|
od_logger_write(logger, ident, buf, buf_len);
|
|
}
|
|
|
|
void od_logger_init(od_logger_t *logger, od_pid_t *pid)
|
|
{
|
|
logger->pid = pid;
|
|
logger->log_debug = 0;
|
|
logger->log_stdout = 1;
|
|
logger->function = od_logger_text;
|
|
od_logfile_init(&logger->log);
|
|
od_logsystem_init(&logger->log_system);
|
|
}
|
|
|
|
void od_logger_set_debug(od_logger_t *logger, int enable)
|
|
{
|
|
logger->log_debug = enable;
|
|
}
|
|
|
|
void od_logger_set_stdout(od_logger_t *logger, int enable)
|
|
{
|
|
logger->log_stdout = enable;
|
|
}
|
|
|
|
int od_logger_open(od_logger_t *logger, char *path)
|
|
{
|
|
return od_logfile_open(&logger->log, path);
|
|
}
|
|
|
|
int od_logger_open_syslog(od_logger_t *logger, char *ident, char *facility)
|
|
{
|
|
return od_logsystem_open(&logger->log_system, ident, facility);
|
|
}
|
|
|
|
void od_logger_set_tskv(od_logger_t *logger)
|
|
{
|
|
logger->function = od_logger_tskv;
|
|
}
|
|
|
|
void od_logger_close(od_logger_t *logger)
|
|
{
|
|
od_logfile_close(&logger->log);
|
|
od_logsystem_close(&logger->log_system);
|
|
}
|