From c07e0ef581b8a3a9ee43c1cd3f369e03aee5a2db Mon Sep 17 00:00:00 2001 From: "roberto@oneiric64" Date: Mon, 6 Feb 2012 16:00:51 +0100 Subject: [PATCH] --touch-logreopen and --touch-logrotate --- logging.c | 174 ++++++++++++++++++++++++++++++++++++++---------------- master.c | 83 +++++--------------------- utils.c | 23 ++++++++ uwsgi.c | 2 + uwsgi.h | 5 ++ 5 files changed, 166 insertions(+), 121 deletions(-) diff --git a/logging.c b/logging.c index e834c53c..8db77ba8 100644 --- a/logging.c +++ b/logging.c @@ -19,6 +19,97 @@ extern struct uwsgi_server uwsgi; +void uwsgi_check_logrotate(void) { + + char message[1024]; + int need_rotation = 0; + int need_reopen = 0; + + if (uwsgi.log_master) { + uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR); + } + else { + uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR); + } + + if (uwsgi.log_maxsize > 0 && uwsgi.shared->logsize > uwsgi.log_maxsize) { + need_rotation = 1; + } + + if (uwsgi_check_touches(uwsgi.touch_logrotate)) { + need_rotation = 1; + } + + if (uwsgi_check_touches(uwsgi.touch_logreopen)) { + need_reopen = 1; + } + + if (need_rotation) { + + char *rot_name = uwsgi.log_backupname; + int need_free = 0; + if (rot_name == NULL) { + char *ts_str = uwsgi_num2str((int) time(NULL)); + rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str); + free(ts_str); + need_free = 1; + } + int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) time(NULL), (unsigned long long) uwsgi.shared->logsize, rot_name); + if (ret > 0) { + if (write(uwsgi.original_log_fd, message, ret) != ret) { + // very probably this will never be printed + uwsgi_error("write()"); + } + } + if (rename(uwsgi.logfile, rot_name) == 0) { + // reopen logfile dup'it and eventually gracefully reload workers; + int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP); + if (fd < 0) { + uwsgi_error_open(uwsgi.logfile); + grace_them_all(0); + } + if (dup2(fd, uwsgi.original_log_fd) < 0) { + uwsgi_error("dup2()"); + grace_them_all(0); + } + + close(fd); + + } + else { + uwsgi_error("unable to rotate log: rename()"); + } + if (need_free) + free(rot_name); + } + else if (need_reopen) { + int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) time(NULL), (unsigned long long) uwsgi.shared->logsize); + if (ret > 0) { + 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); + } + ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) time(NULL), uwsgi.logfile); + if (ret > 0) { + 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); + } +} + + void log_request(struct wsgi_request *wsgi_req) { // optimize this (please) @@ -48,7 +139,8 @@ void log_request(struct wsgi_request *wsgi_req) { struct uwsgi_app *wi; - if (wsgi_req->do_not_log) return ; + if (wsgi_req->do_not_log) + return; if (wsgi_req->app_id >= 0) { wi = &uwsgi_apps[wsgi_req->app_id]; @@ -58,7 +150,7 @@ void log_request(struct wsgi_request *wsgi_req) { } #ifdef UWSGI_SENDFILE - if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) { + if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) { via = msg1; } #endif @@ -93,12 +185,9 @@ void log_request(struct wsgi_request *wsgi_req) { if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) { #ifndef UNBIT - rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", - (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024, - (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024); + rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024); #else - rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ", - (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024); + rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024); #endif logvec[logvecpos].iov_base = mempkt; @@ -107,35 +196,16 @@ void log_request(struct wsgi_request *wsgi_req) { } - rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n", - (int) uwsgi.mypid, - wsgi_req->app_id, - app_req, - (unsigned long long ) uwsgi.workers[0].requests, - wsgi_req->remote_addr_len, wsgi_req->remote_addr, - wsgi_req->remote_user_len, wsgi_req->remote_user, - wsgi_req->var_cnt, - wsgi_req->uh.pktsize, - 24, time_request, - wsgi_req->method_len, wsgi_req->method, - wsgi_req->uri_len, wsgi_req->uri, - (unsigned long long) wsgi_req->response_size, - rt, tsize, - via, - wsgi_req->protocol_len, wsgi_req->protocol, - wsgi_req->status, - wsgi_req->header_cnt, - (unsigned long long) wsgi_req->headers_size, - wsgi_req->switches, wsgi_req->async_id); + rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->remote_user_len, wsgi_req->remote_user, wsgi_req->var_cnt, wsgi_req->uh.pktsize, 24, time_request, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) wsgi_req->response_size, rt, tsize, via, wsgi_req->protocol_len, wsgi_req->protocol, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id); logvec[logvecpos].iov_base = logpkt; logvec[logvecpos].iov_len = rlen; // do not check for errors - rlen = writev(2, logvec, logvecpos+1); + rlen = writev(2, logvec, logvecpos + 1); } -void get_memusage(uint64_t *rss, uint64_t *vsz) { +void get_memusage(uint64_t * rss, uint64_t * vsz) { #ifdef UNBIT *vsz = syscall(356); @@ -146,7 +216,7 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) { if (procfile) { i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss); if (i != 2) { - uwsgi_log( "warning: invalid record in /proc/self/stat\n"); + uwsgi_log("warning: invalid record in /proc/self/stat\n"); } fclose(procfile); } @@ -157,7 +227,7 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) { procfd = open("/proc/self/psinfo", O_RDONLY); if (procfd >= 0) { - if ( read(procfd, (char *) &info, sizeof(info)) > 0) { + if (read(procfd, (char *) &info, sizeof(info)) > 0) { *rss = (uint64_t) info.pr_rssize * 1024; *vsz = (uint64_t) info.pr_size * 1024; } @@ -215,9 +285,9 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) { *vsz = 0; *rss = 0; - while(get_next_area_info(0, &cookie, &ai) == B_OK) { + while (get_next_area_info(0, &cookie, &ai) == B_OK) { *vsz += ai.ram_size; - if ( (ai.protection & B_WRITE_AREA) != 0) { + if ((ai.protection & B_WRITE_AREA) != 0) { *rss += ai.ram_size; } } @@ -225,27 +295,27 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) { } -void uwsgi_register_logger(char *name, ssize_t (*func)(struct uwsgi_logger *, char *, size_t)) { +void uwsgi_register_logger(char *name, ssize_t(*func) (struct uwsgi_logger *, char *, size_t)) { - struct uwsgi_logger *ul = uwsgi.loggers, *old_ul; + struct uwsgi_logger *ul = uwsgi.loggers, *old_ul; - if (!ul) { - uwsgi.loggers = uwsgi_malloc(sizeof(struct uwsgi_logger)); - ul = uwsgi.loggers; - } - else { - while(ul) { - old_ul = ul; - ul = ul->next; - } + if (!ul) { + uwsgi.loggers = uwsgi_malloc(sizeof(struct uwsgi_logger)); + ul = uwsgi.loggers; + } + else { + while (ul) { + old_ul = ul; + ul = ul->next; + } - ul = uwsgi_malloc(sizeof(struct uwsgi_logger)); - old_ul->next = ul; - } + ul = uwsgi_malloc(sizeof(struct uwsgi_logger)); + old_ul->next = ul; + } - ul->name = name; - ul->func = func; - ul->next = NULL; + ul->name = name; + ul->func = func; + ul->next = NULL; ul->configured = 0; ul->fd = -1; ul->data = NULL; @@ -259,11 +329,11 @@ void uwsgi_register_logger(char *name, ssize_t (*func)(struct uwsgi_logger *, ch struct uwsgi_logger *uwsgi_get_logger(char *name) { struct uwsgi_logger *ul = uwsgi.loggers; - while(ul) { + while (ul) { if (!strcmp(ul->name, name)) { return ul; } - ul = ul->next; + ul = ul->next; } return NULL; diff --git a/master.c b/master.c index 53a235d9..6ec0b203 100644 --- a/master.c +++ b/master.c @@ -534,19 +534,10 @@ int master_loop(char **argv, char **environ) { } } - struct uwsgi_string_list *touch_reload = uwsgi.touch_reload; - while (touch_reload) { - struct stat tr_st; - if (stat(touch_reload->value, &tr_st)) { - uwsgi_log("unable to stat() %s, reload will be triggered as soon as the file is created\n", touch_reload->value); - touch_reload->custom = 0; - } - else { - touch_reload->custom = (uint64_t) tr_st.st_mtime; - } - touch_reload = touch_reload->next; - - } + // update touches timestamps + uwsgi_check_touches(uwsgi.touch_reload); + uwsgi_check_touches(uwsgi.touch_logrotate); + uwsgi_check_touches(uwsgi.touch_logreopen); for (;;) { //uwsgi_log("ready_to_reload %d %d\n", ready_to_reload, uwsgi.numproc); @@ -1251,51 +1242,12 @@ int master_loop(char **argv, char **environ) { continue; } uwsgi.current_time = now; + // checking logsize if (uwsgi.logfile) { - if (uwsgi.log_master) { - uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR); - } - else { - uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR); - } - if (uwsgi.log_maxsize > 0 && uwsgi.shared->logsize > uwsgi.log_maxsize) { - char *rot_name = uwsgi.log_backupname; - int need_free = 0; - if (rot_name == NULL) { - char *ts_str = uwsgi_num2str((int) time(NULL)); - rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str); - free(ts_str); - need_free = 1; - } - char message[1024]; - int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) time(NULL), (unsigned long long) uwsgi.shared->logsize, rot_name); - if (ret > 0) { - rlen = write(uwsgi.original_log_fd, message, ret); - - } - if (rename(uwsgi.logfile, rot_name) == 0) { - // close 2, reopen logfile dup'it and gracefully reload workers; - int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP); - if (fd < 0) { - uwsgi_error_open(uwsgi.logfile); - grace_them_all(0); - } - if (dup2(fd, uwsgi.original_log_fd) < 0) { - uwsgi_error("dup2()"); - grace_them_all(0); - } - - } - else { - uwsgi_error("unable to rotate log: rename()"); - } - if (need_free) - free(rot_name); - } + uwsgi_check_logrotate(); } - // this will be incremented at (more or less) regular intervals uwsgi.master_cycles++; @@ -1522,24 +1474,15 @@ int master_loop(char **argv, char **environ) { } // check touch_reload - struct uwsgi_string_list *touch_reload = uwsgi.touch_reload; - while (touch_reload && !uwsgi.to_heaven && !uwsgi.to_hell) { - struct stat tr_st; - if (stat(touch_reload->value, &tr_st)) { - touch_reload->custom = 0; + if (!uwsgi.to_heaven && !uwsgi.to_hell) { + char *touched = uwsgi_check_touches(uwsgi.touch_reload); + if (touched) { + uwsgi_log("*** %s has been touched... grace them all !!! ***\n", touched); + grace_them_all(0); + break; } - else { - if ((uint64_t) tr_st.st_mtime > touch_reload->custom) { - uwsgi_log("*** %s has been touched... grace them all !!! ***\n", touch_reload->value); - grace_them_all(0); - break; - } - } - touch_reload = touch_reload->next; } - - // now check for lb pool continue; } @@ -1759,4 +1702,6 @@ int master_loop(char **argv, char **environ) { } } + // never here + return -1; } diff --git a/utils.c b/utils.c index 8faba342..93176e3e 100644 --- a/utils.c +++ b/utils.c @@ -3765,6 +3765,29 @@ void uwsgi_add_app(int id, uint8_t modifier1, char *mountpoint, int mountpoint_l } +char *uwsgi_check_touches(struct uwsgi_string_list *touch_list) { + + struct uwsgi_string_list *touch = touch_list; + while (touch) { + struct stat tr_st; + if (stat(touch->value, &tr_st)) { + uwsgi_log("unable to stat() %s, events will be triggered as soon as the file is created\n", touch->value); + touch->custom = 0; + } + else { + if ((uint64_t) tr_st.st_mtime > touch->custom) { + touch->custom = (uint64_t) tr_st.st_mtime; + return touch->value; + } + touch->custom = (uint64_t) tr_st.st_mtime; + } + touch = touch->next; + } + + return NULL; +} + + char *uwsgi_tmpname(char *base, char *id) { char *template = uwsgi_concat3(base, "/", id); if (mkstemp(template) < 0) { diff --git a/uwsgi.c b/uwsgi.c index c1753ebb..de3b053c 100644 --- a/uwsgi.c +++ b/uwsgi.c @@ -203,6 +203,8 @@ static struct uwsgi_option uwsgi_base_options[] = { #endif {"never-swap", no_argument, 0, "lock all memory pages avoiding swapping", uwsgi_opt_true, &uwsgi.never_swap, 0}, {"touch-reload", required_argument, 0, "reload uWSGI if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_reload, UWSGI_OPT_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}, {"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal mamagement", uwsgi_opt_true, &uwsgi.propagate_touch, 0}, {"limit-post", required_argument, 0, "limit request body", uwsgi_opt_set_64bit, &uwsgi.limit_post, 0}, {"no-orphans", no_argument, 0, "automatically kill workers if master dies (can be dangerous for availability)", uwsgi_opt_true, &uwsgi.no_orphans, 0}, diff --git a/uwsgi.h b/uwsgi.h index 694b1498..7bd8301e 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -1183,7 +1183,10 @@ struct uwsgi_server { rlim_t reload_on_rss; rlim_t evil_reload_on_as; rlim_t evil_reload_on_rss; + struct uwsgi_string_list *touch_reload; + struct uwsgi_string_list *touch_logrotate; + struct uwsgi_string_list *touch_logreopen; int propagate_touch; @@ -2565,6 +2568,8 @@ int uwsgi_apply_routes(struct wsgi_request *); #endif void uwsgi_backtrace(int); +void uwsgi_check_logrotate(void); +char *uwsgi_check_touches(struct uwsgi_string_list *); #ifdef UWSGI_AS_SHARED_LIBRARY int uwsgi_init(int, char **, char **);