提交 06ea9ff8 编写于 作者: D Dmitry Kozlov

log: implemented log_tcp logging target which sends logs to specified host over tcp/ip

上级 b85986e5
......@@ -29,6 +29,9 @@ containes list of modules to load
.BI log_file
This is logging target which logs messages to files. It support per-session/per-user features.
.TP
.BI log_tcp
This is logging target which logs messages over TCP/IP.
.TP
.BI log_pgsql
This is logging target which logs messages to PostgreSQL.
.TP
......@@ -248,6 +251,9 @@ Path to file to write general log.
.BI "log-emerg=" file
Path to file to write emergency messages.
.TP
.BI "log-tcp=" x.x.x.x:port
Send logs to specified host.
.TP
.BI "copy=" n
If this options is given and greater then zero logging engine will duplicate session log in general log.
(Useful when per-session/per-user logs are not used)
......
......@@ -87,7 +87,7 @@ static void do_log(int level, const char *fmt, va_list ap, struct ppp_t *ppp)
m = clone_msg(cur_msg);
if (!m)
break;
t->log(m, ppp);
t->log(t, m, ppp);
}
out:
......
......@@ -39,7 +39,7 @@ struct log_target_t
{
struct list_head entry;
void (*log)(struct log_msg_t *, struct ppp_t *ppp);
void (*log)(struct log_target_t *, struct log_msg_t *, struct ppp_t *ppp);
void (*reopen)(void);
};
......
ADD_LIBRARY(log_file SHARED log_file.c)
TARGET_LINK_LIBRARIES(log_file rt)
INSTALL(TARGETS log_file
ADD_LIBRARY(log_tcp SHARED log_tcp.c)
INSTALL(TARGETS log_file log_tcp
LIBRARY DESTINATION usr/lib/accel-pptp
)
......
......@@ -261,7 +261,7 @@ static void set_hdr(struct log_msg_t *msg, struct ppp_t *ppp)
msg->hdr->len = strlen(msg->hdr->msg);
}
static void general_log(struct log_msg_t *msg, struct ppp_t *ppp)
static void general_log(struct log_target_t *t, struct log_msg_t *msg, struct ppp_t *ppp)
{
if (ppp && !conf_copy) {
log_free_msg(msg);
......@@ -286,7 +286,7 @@ static struct log_file_pd_t *find_pd(struct ppp_t *ppp, void *pd_key)
return NULL;
}
static void per_user_log(struct log_msg_t *msg, struct ppp_t *ppp)
static void per_user_log(struct log_target_t *t, struct log_msg_t *msg, struct ppp_t *ppp)
{
struct log_file_pd_t *lpd;
......@@ -306,7 +306,7 @@ static void per_user_log(struct log_msg_t *msg, struct ppp_t *ppp)
queue_log(&lpd->lf, msg);
}
static void per_session_log(struct log_msg_t *msg, struct ppp_t *ppp)
static void per_session_log(struct log_target_t *t, struct log_msg_t *msg, struct ppp_t *ppp)
{
struct log_file_pd_t *lpd;
......
......@@ -193,7 +193,7 @@ static void queue_log(struct log_msg_t *msg)
}
static void general_log(struct log_msg_t *msg, struct ppp_t *ppp)
static void general_log(struct log_target_t *t, struct log_msg_t *msg, struct ppp_t *ppp)
{
set_hdr(msg, ppp);
queue_log(msg);
......
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "log.h"
#include "triton.h"
#include "events.h"
#include "ppp.h"
#include "spinlock.h"
#include "mempool.h"
#include "memdebug.h"
struct tcp_target_t
{
struct log_target_t target;
struct list_head entry;
struct triton_md_handler_t hnd;
struct triton_timer_t conn_timer;
struct sockaddr_in addr;
char *buf;
int buf_size;
int buf_pos;
spinlock_t lock;
struct list_head queue;
int queue_len;
int connected:1;
int wait:1;
};
static int conf_connect_interval = 5;
static int conf_queue_len = 1000;
static struct triton_context_t tcp_ctx;
static const char* level_name[]={" msg", "error", " warn", " info", "debug"};
static void start_connect(struct tcp_target_t *t);
static void disconnect(struct tcp_target_t *t)
{
triton_md_unregister_handler(&t->hnd);
close(t->hnd.fd);
start_connect(t);
}
static void unpack_msg(struct tcp_target_t *t, struct log_msg_t *msg)
{
struct log_chunk_t *chunk;
int pos = strlen(msg->hdr->msg);
strcpy(t->buf, msg->hdr->msg);
list_for_each_entry(chunk, msg->chunks, entry) {
memcpy(t->buf + pos, chunk->msg, chunk->len);
pos += chunk->len;
}
t->buf_size = pos;
t->buf_pos = 0;
}
static int send_log(struct tcp_target_t *t)
{
struct log_msg_t *msg;
int n;
while (1) {
spin_lock(&t->lock);
if (!t->queue_len) {
t->wait = 0;
spin_unlock(&t->lock);
return 0;
}
msg = list_entry(t->queue.next, typeof(*msg), entry);
list_del(&msg->entry);
t->queue_len--;
spin_unlock(&t->lock);
unpack_msg(t, msg);
log_free_msg(msg);
while (t->buf_pos != t->buf_size) {
n = write(t->hnd.fd, t->buf + t->buf_pos, t->buf_size - t->buf_pos);
if (n < 0) {
if (errno == EAGAIN)
return 1;
if (errno != EPIPE)
log_emerg("log-tcp: write: %s\n", strerror(errno));
disconnect(t);
return 0;
}
t->buf_pos += n;
}
}
}
static void queue_log(struct tcp_target_t *t, struct log_msg_t *msg)
{
int r;
spin_lock(&t->lock);
if (t->queue_len == conf_queue_len) {
spin_unlock(&t->lock);
log_free_msg(msg);
}
list_add_tail(&msg->entry, &t->queue);
t->queue_len++;
if (t->connected) {
r = t->wait;
t->wait = 1;
} else
r = 1;
spin_unlock(&t->lock);
if (!r) {
if (send_log(t))
triton_md_enable_handler(&t->hnd, MD_MODE_WRITE);
}
}
static void set_hdr(struct log_msg_t *msg, struct ppp_t *ppp)
{
struct tm tm;
char timestamp[32];
localtime_r(&msg->timestamp.tv_sec, &tm);
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", &tm);
sprintf(msg->hdr->msg, "[%s]: %s: %s: ", timestamp, level_name[msg->level], ppp ? ppp->ifname : "");
msg->hdr->len = strlen(msg->hdr->msg);
}
static void general_log(struct log_target_t *lt, struct log_msg_t *msg, struct ppp_t *ppp)
{
struct tcp_target_t *t = container_of(lt, typeof(*t), target);
set_hdr(msg, ppp);
queue_log(t, msg);
}
static int log_tcp_write(struct triton_md_handler_t *h)
{
struct tcp_target_t *t = container_of(h, typeof(*t), hnd);
if (!send_log(t))
triton_md_disable_handler(h, MD_MODE_WRITE);
return 0;
}
static int log_tcp_connect(struct triton_md_handler_t *h)
{
struct tcp_target_t *t = container_of(h, typeof(*t), hnd);
if (connect(t->hnd.fd, &t->addr, sizeof(t->addr))) {
if (errno == EAGAIN)
return 0;
if (errno == EINPROGRESS)
return 0;
log_emerg("log-tcp: connect: %s\n", strerror(errno));
triton_md_unregister_handler(&t->hnd);
close(t->hnd.fd);
triton_timer_add(&tcp_ctx, &t->conn_timer, 0);
return 0;
}
t->hnd.write = log_tcp_write;
triton_md_disable_handler(&t->hnd, MD_MODE_WRITE);
spin_lock(&t->lock);
t->connected = 1;
t->wait = 1;
spin_unlock(&t->lock);
send_log(t);
return 0;
}
static void connect_timer(struct triton_timer_t *timer)
{
struct tcp_target_t *t = container_of(timer, typeof(*t), conn_timer);
triton_timer_del(timer);
start_connect(t);
}
static void start_connect(struct tcp_target_t *t)
{
t->hnd.write = log_tcp_connect;
t->hnd.fd = socket(PF_INET, SOCK_STREAM, 0);
if (!t->hnd.fd) {
log_emerg("log-tcp: socket: %s\n", strerror(errno));
return;
}
if (fcntl(t->hnd.fd, F_SETFL, O_NONBLOCK)) {
log_emerg("log-tcp: failed to set nonblocking mode: %s\n", strerror(errno));
close(t->hnd.fd);
return;
}
if (connect(t->hnd.fd, &t->addr, sizeof(t->addr))) {
if (errno != EINPROGRESS) {
log_emerg("log-tcp: connect: %s\n", strerror(errno));
close(t->hnd.fd);
return;
}
}
triton_md_register_handler(&tcp_ctx, &t->hnd);
triton_md_enable_handler(&t->hnd, MD_MODE_WRITE);
}
static int start_log(const char *_opt)
{
struct tcp_target_t *t;
char *opt = strdup(_opt);
int port;
char *d;
d = strchr(opt, ':');
if (!d)
goto err;
*d = 0;
port = atoi(d + 1);
if (port <= 0)
goto err;
t = _malloc(sizeof(*t));
memset(t, 0, sizeof(*t));
t->buf = _malloc(LOG_MAX_SIZE + 64);
t->conn_timer.expire_tv.tv_sec = conf_connect_interval;
t->conn_timer.expire = connect_timer;
t->target.log = general_log;
memset(&t->addr, 0, sizeof(t->addr));
t->addr.sin_family = AF_INET;
t->addr.sin_port = htons(port);
t->addr.sin_addr.s_addr = inet_addr(opt);
INIT_LIST_HEAD(&t->queue);
start_connect(t);
log_register_target(&t->target);
return 0;
err:
free(opt);
return -1;
}
static void __init init(void)
{
struct conf_sect_t *s = conf_get_section("log");
struct conf_option_t *opt;
if (!s)
return;
triton_context_register(&tcp_ctx, NULL);
list_for_each_entry(opt, &s->items, entry) {
if (strcmp(opt->name, "log-tcp"))
continue;
if (!opt->val || start_log(opt->val))
log_emerg("log: log-tcp: invalid format: '%s'\n", opt->val);
}
triton_context_wakeup(&tcp_ctx);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册