Skip to content
100 changes: 59 additions & 41 deletions core/logging.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,13 @@ void create_logpipe(void) {

}

mode_t uwsgi_get_logfile_chmod_value() {
if (uwsgi.chmod_logfile_value)
return uwsgi.chmod_logfile_value;
else
return S_IRUSR | S_IWUSR | S_IRGRP;
}

// log to the specified file or udp address
void logto(char *logfile) {

Expand Down Expand Up @@ -279,22 +286,16 @@ void logto(char *logfile) {
}
else {
if (uwsgi.log_truncate) {
fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, uwsgi_get_logfile_chmod_value());
}
else {
fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, uwsgi_get_logfile_chmod_value());
}
if (fd < 0) {
uwsgi_error_open(logfile);
exit(1);
}
uwsgi.logfile = logfile;

if (uwsgi.chmod_logfile_value) {
if (fchmod(fd, uwsgi.chmod_logfile_value)) {
uwsgi_error("fchmod()");
}
}
}


Expand Down Expand Up @@ -530,20 +531,30 @@ void uwsgi_check_logrotate(void) {
}

void uwsgi_log_do_rotate(char *logfile, char *rotatedfile, off_t logsize, int log_fd) {
int need_free = 0;
char *rot_name = rotatedfile;
time_t rawtime = uwsgi_now();
struct tm *current = localtime(&rawtime);

if (rot_name == NULL) {
char *ts_str = uwsgi_num2str((int) uwsgi_now());
rot_name = uwsgi_concat3(logfile, ".", ts_str);
free(ts_str);
int need_free = 0;
char *rot_base_name = rotatedfile;
if (rot_base_name == NULL) {
rot_base_name = uwsgi_concat2(logfile, ".%Y-%m-%dT%X");
need_free = 1;
}

size_t rot_name_len = strlen(rot_base_name) + 64;
char *rot_name = uwsgi_malloc(rot_name_len);

if (strftime(rot_name, rot_name_len, rot_base_name, current) == 0) {
uwsgi_error("uwsgi_log_do_rotate()/strftime() (maybe too long)");
}
if (need_free)
free(rot_base_name);

// this will be rawly written to the logfile
uwsgi_logfile_write("logsize: %llu, triggering rotation to %s...\n", (unsigned long long) logsize, rot_name);
if (rename(logfile, rot_name) == 0) {
// reopen logfile and dup'it, on dup2 error, exit(1)
int fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
int fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, uwsgi_get_logfile_chmod_value());
if (fd < 0) {
// this will be written to the original file
uwsgi_error_open(logfile);
Expand All @@ -561,8 +572,8 @@ void uwsgi_log_do_rotate(char *logfile, char *rotatedfile, off_t logsize, int lo
else {
uwsgi_error("unable to rotate log: rename()");
}
if (need_free)
free(rot_name);

free(rot_name);
}

void uwsgi_log_rotate() {
Expand All @@ -571,33 +582,40 @@ void uwsgi_log_rotate() {
uwsgi_log_do_rotate(uwsgi.logfile, uwsgi.log_backupname, uwsgi.shared->logsize, uwsgi.original_log_fd);
}

void uwsgi_opt_add_cron_logrotate(char *opt, char *value, void *foobar) {
struct uwsgi_cron *uc = uwsgi_cron_add(value);
uc->func = uwsgi_log_rotate;
}

void uwsgi_log_reopen() {
char message[1024];
if (!uwsgi.logfile) return;
if (!uwsgi.logfile)
return;
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
if (ret > 0 && ret < 1024) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}

// reopen logfile;
close(uwsgi.original_log_fd);
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (uwsgi.original_log_fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
return;
}
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
if (ret > 0 && ret < 1024) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
if (ret > 0 && ret < 1024) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}

// reopen logfile;
close(uwsgi.original_log_fd);
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, uwsgi_get_logfile_chmod_value());
if (uwsgi.original_log_fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
return;
}

ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
if (ret > 0 && ret < 1024) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
}


Expand Down
1 change: 1 addition & 0 deletions core/uwsgi.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"touch-mules-reload", required_argument, 0, "reload mules if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_mules_reload, UWSGI_OPT_MASTER},
{"touch-spoolers-reload", required_argument, 0, "reload spoolers if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_spoolers_reload, UWSGI_OPT_MASTER},
{"touch-chain-reload", required_argument, 0, "trigger chain reload if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_chain_reload, UWSGI_OPT_MASTER},
{"cron-logrotate", required_argument, 0, "add a cron task to trigger log rotation", uwsgi_opt_add_cron_logrotate, NULL, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"touch-logrotate", required_argument, 0, "trigger logrotation if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logrotate, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"touch-logreopen", required_argument, 0, "trigger log reopen if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logreopen, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"touch-exec", required_argument, 0, "run command when the specified file is modified/touched (syntax: file command)", uwsgi_opt_add_string_list, &uwsgi.touch_exec, UWSGI_OPT_MASTER},
Expand Down
31 changes: 23 additions & 8 deletions plugins/logfile/logfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ struct logfile_data {
uint64_t maxsize;
};

static void uwsgi_cron_trigger_rotate_func(struct uwsgi_cron *uc, time_t now){
struct uwsgi_logger *ul = uc->data;
struct logfile_data *data = ul->data;
off_t logsize = lseek(ul->fd, 0, SEEK_CUR);

uwsgi_log_do_rotate(data->logfile, data->backupname, logsize, ul->fd);
}

static ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t len) {

if (!ul->configured) {
Expand All @@ -15,10 +23,11 @@ static ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t
char *backupname = NULL;
char *maxsize = NULL;
char *logfile = NULL;
char *cron = NULL;

if (strchr(ul->arg, '=')) {
if (uwsgi_kvlist_parse(ul->arg, strlen(ul->arg), ',', '=',
"logfile", &logfile, "backupname", &backupname, "maxsize", &maxsize, NULL)) {
"logfile", &logfile, "backupname", &backupname, "maxsize", &maxsize, "cron", &cron, NULL)) {
uwsgi_log("[uwsgi-logfile] invalid keyval syntax\n");
exit(1);
}
Expand All @@ -29,22 +38,28 @@ static ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t
uwsgi_log("[uwsgi-logfile] missing logfile key\n");
return 0;
}


struct logfile_data *data = uwsgi_malloc(sizeof(struct logfile_data));
data->logfile = logfile;
data->backupname = backupname;
if (maxsize) {
struct logfile_data *data = uwsgi_malloc(sizeof(struct logfile_data));
data->logfile = logfile;
data->backupname = backupname;
data->maxsize = (uint64_t)strtoull(maxsize, NULL, 10);
ul->data = data;

free(maxsize);
maxsize = NULL;
} else {
data->maxsize = (uint64_t) 0;
}
if (cron) {
struct uwsgi_cron *uc = uwsgi_cron_add(cron);
uc->data = ul;
uc->func = uwsgi_cron_trigger_rotate_func;
}
ul->data = data;
} else {
logfile = ul->arg;
}

ul->fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
ul->fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, uwsgi_get_logfile_chmod_value());
if (ul->fd >= 0) {
ul->configured = 1;
}
Expand Down
5 changes: 5 additions & 0 deletions uwsgi.h
Original file line number Diff line number Diff line change
Expand Up @@ -3005,6 +3005,9 @@ struct uwsgi_cron {
char *command;
void (*func)(struct uwsgi_cron *, time_t);

// data to be used with func
void *data;

time_t started_at;

// next harakiri timestamp
Expand Down Expand Up @@ -4899,8 +4902,10 @@ void uwsgi_master_fifo_prepare();
int uwsgi_master_fifo();
int uwsgi_master_fifo_manage(int);

mode_t uwsgi_get_logfile_chmod_value();
void uwsgi_log_do_rotate(char *, char *, off_t, int);
void uwsgi_log_rotate();
void uwsgi_opt_add_cron_logrotate(char *opt, char *value, void *foobar);
void uwsgi_log_reopen();
void uwsgi_reload_workers();
void uwsgi_reload_mules();
Expand Down