From 98a1e93dca3b34630d607bc15d95f6dfe39d778d Mon Sep 17 00:00:00 2001 From: Stefan Fritsch Date: Sun, 6 Jun 2010 16:54:51 +0000 Subject: [PATCH] - Introduce log levels trace1/.../trace8 - Add macro wrappers for ap_log_*error. On C99, this will save argument preparation and function call overhead when a message is not logged because of the configured loglevel. - Introduce per-module loglevel configuration. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@951893 13f79535-47bb-0310-9956-ffa450edef68 --- configure.in | 3 + include/ap_mmn.h | 7 +- include/http_config.h | 50 ++++++++++ include/http_log.h | 210 ++++++++++++++++++++++++++++++++++-------- include/httpd.h | 2 + server/config.c | 36 ++++++++ server/core.c | 54 +++++++++-- server/log.c | 73 +++++++++------ server/util_debug.c | 16 ++++ 9 files changed, 374 insertions(+), 77 deletions(-) diff --git a/configure.in b/configure.in index 4501857bb2..9ee5b5b58b 100644 --- a/configure.in +++ b/configure.in @@ -170,6 +170,9 @@ dnl PCRE and for our config tests will be whatever PCRE determines. AC_PROG_CC AC_PROG_CPP +dnl Try to get c99 support for variadic macros +AC_PROG_CC_C99 + if test "x${cache_file}" = "x/dev/null"; then # Likewise, ensure that CC and CPP are passed through to the pcre # configure script iff caching is disabled (the autoconf 2.5x default). diff --git a/include/ap_mmn.h b/include/ap_mmn.h index ac40e9def1..e708bc3c07 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -221,12 +221,17 @@ * 20100223.1 (2.3.6-dev) Added ap_process_fnmatch_configs(). * 20100504.0 (2.3.6-dev) Added name arg to ap_{proc,global}_mutex_create(). * 20100604.0 (2.3.6-dev) Remove unused core_dir_config::loglevel + * 20100606.0 (2.3.6-dev) Make ap_log_*error macro wrappers around + * ap_log_*error_ to save argument preparation and + * function call overhead. + * Introduce per-module loglevels + * */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ #ifndef MODULE_MAGIC_NUMBER_MAJOR -#define MODULE_MAGIC_NUMBER_MAJOR 20100604 +#define MODULE_MAGIC_NUMBER_MAJOR 20100606 #endif #define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */ diff --git a/include/http_config.h b/include/http_config.h index 33a3e54a62..c5bbd48298 100644 --- a/include/http_config.h +++ b/include/http_config.h @@ -28,6 +28,7 @@ #include "apr_hooks.h" #include "util_cfgtree.h" +#include "ap_config.h" #ifdef __cplusplus extern "C" { @@ -394,6 +395,17 @@ struct module_struct { void (*register_hooks) (apr_pool_t *p); }; +/* + * Macro to choose which module a file belongs to, for logging. + */ +#define APLOG_USE_MODULE(foo) \ + extern module AP_MODULE_DECLARE_DATA foo##_module; \ + static int * const aplog_module_index = &(foo##_module.module_index) + +#define AP_DECLARE_MODULE(foo) \ + APLOG_USE_MODULE(foo); \ + module AP_MODULE_DECLARE_DATA foo##_module + /** * @defgroup ModuleInit Module structure initializers * @@ -469,6 +481,44 @@ AP_DECLARE(void) ap_set_module_config(ap_conf_vector_t *cv, const module *m, #endif /* AP_DEBUG */ +/** + * Generic accessor for modules to get the module-specific loglevel + * @param s The server from which to get the loglevel. + * @param index The module_index of the module to get the loglevel for. + * @return The module-specific loglevel + */ +AP_DECLARE(int) ap_get_module_loglevel(const server_rec *s, int index); + +/** + * Accessor to set module-specific loglevel + * @param p A pool + * @param s The server for which to set the loglevel. + * @param index The module_index of the module to set the loglevel for. + * @param level The new log level + * @return The module-specific loglevel + */ +AP_DECLARE(void) ap_set_module_loglevel(apr_pool_t *p, server_rec *s, + int index, int level); + +#if !defined(AP_DEBUG) + +#define ap_get_module_loglevel(s,i) \ + (i < 0 || (s)->module_loglevels == NULL || (((s)->module_loglevels)[i]) < 0 ? \ + (s)->loglevel : \ + ((s)->module_loglevels)[i]) + +#endif /* AP_DEBUG */ + +/** + * Reset all module-specific loglevels to server default + * @param p A pool + * @param s The server for which to set the loglevel. + * @param index The module_index of the module to set the loglevel for. + * @param level The new log level + * @return The module-specific loglevel + */ +AP_DECLARE(void) ap_reset_module_loglevels(server_rec *s); + /** * Generic command handling function for strings * @param cmd The command parameters for this directive diff --git a/include/http_log.h b/include/http_log.h index 80e8b9fa67..183be0aa8e 100644 --- a/include/http_log.h +++ b/include/http_log.h @@ -35,33 +35,51 @@ extern "C" { #ifdef HAVE_SYSLOG #include +#include "http_config.h" + #ifndef LOG_PRIMASK #define LOG_PRIMASK 7 #endif -#define APLOG_EMERG LOG_EMERG /* system is unusable */ -#define APLOG_ALERT LOG_ALERT /* action must be taken immediately */ -#define APLOG_CRIT LOG_CRIT /* critical conditions */ -#define APLOG_ERR LOG_ERR /* error conditions */ -#define APLOG_WARNING LOG_WARNING /* warning conditions */ -#define APLOG_NOTICE LOG_NOTICE /* normal but significant condition */ -#define APLOG_INFO LOG_INFO /* informational */ -#define APLOG_DEBUG LOG_DEBUG /* debug-level messages */ - -#define APLOG_LEVELMASK LOG_PRIMASK /* mask off the level value */ +#define APLOG_EMERG LOG_EMERG /* system is unusable */ +#define APLOG_ALERT LOG_ALERT /* action must be taken immediately */ +#define APLOG_CRIT LOG_CRIT /* critical conditions */ +#define APLOG_ERR LOG_ERR /* error conditions */ +#define APLOG_WARNING LOG_WARNING /* warning conditions */ +#define APLOG_NOTICE LOG_NOTICE /* normal but significant condition */ +#define APLOG_INFO LOG_INFO /* informational */ +#define APLOG_DEBUG LOG_DEBUG /* debug-level messages */ +#define APLOG_TRACE1 (LOG_DEBUG + 1) /* trace-level 1 messages */ +#define APLOG_TRACE2 (LOG_DEBUG + 2) /* trace-level 2 messages */ +#define APLOG_TRACE3 (LOG_DEBUG + 3) /* trace-level 3 messages */ +#define APLOG_TRACE4 (LOG_DEBUG + 4) /* trace-level 4 messages */ +#define APLOG_TRACE5 (LOG_DEBUG + 5) /* trace-level 5 messages */ +#define APLOG_TRACE6 (LOG_DEBUG + 6) /* trace-level 6 messages */ +#define APLOG_TRACE7 (LOG_DEBUG + 7) /* trace-level 7 messages */ +#define APLOG_TRACE8 (LOG_DEBUG + 8) /* trace-level 8 messages */ + +#define APLOG_LEVELMASK 15 /* mask off the level value */ #else -#define APLOG_EMERG 0 /* system is unusable */ -#define APLOG_ALERT 1 /* action must be taken immediately */ -#define APLOG_CRIT 2 /* critical conditions */ -#define APLOG_ERR 3 /* error conditions */ -#define APLOG_WARNING 4 /* warning conditions */ -#define APLOG_NOTICE 5 /* normal but significant condition */ -#define APLOG_INFO 6 /* informational */ -#define APLOG_DEBUG 7 /* debug-level messages */ - -#define APLOG_LEVELMASK 7 /* mask off the level value */ +#define APLOG_EMERG 0 /* system is unusable */ +#define APLOG_ALERT 1 /* action must be taken immediately */ +#define APLOG_CRIT 2 /* critical conditions */ +#define APLOG_ERR 3 /* error conditions */ +#define APLOG_WARNING 4 /* warning conditions */ +#define APLOG_NOTICE 5 /* normal but significant condition */ +#define APLOG_INFO 6 /* informational */ +#define APLOG_DEBUG 7 /* debug-level messages */ +#define APLOG_TRACE1 8 /* trace-level 1 messages */ +#define APLOG_TRACE2 9 /* trace-level 2 messages */ +#define APLOG_TRACE3 10 /* trace-level 3 messages */ +#define APLOG_TRACE4 11 /* trace-level 4 messages */ +#define APLOG_TRACE5 12 /* trace-level 5 messages */ +#define APLOG_TRACE6 13 /* trace-level 6 messages */ +#define APLOG_TRACE7 14 /* trace-level 7 messages */ +#define APLOG_TRACE8 15 /* trace-level 8 messages */ + +#define APLOG_LEVELMASK 15 /* mask off the level value */ #endif @@ -91,9 +109,79 @@ extern "C" { #define DEFAULT_LOGLEVEL APLOG_WARNING #endif +#define APLOG_NO_MODULE -1 + +/* + * Objects with static storage duration are set to NULL if not + * initialized explicitly. This means if aplog_module_index + * is not initalized using the APLOG_USE_MODULE or the + * AP_DECLARE_MODULE macro, we can safely fall back to + * use APLOG_NO_MODULE. + */ +static int * const aplog_module_index; +#define APLOG_MODULE_INDEX \ + (aplog_module_index ? *aplog_module_index : APLOG_NO_MODULE) + +/* + * APLOG_MAX_LOGLEVEL can be used to remove logging above some + * specified level at compile time. + */ +#ifndef APLOG_MAX_LOGLEVEL +#define APLOG_MODULE_IS_LEVEL(s,module_index,level) \ + ( (((level)&APLOG_LEVELMASK) <= APLOG_NOTICE) || \ + (s == NULL) || \ + (ap_get_module_loglevel(s, module_index) \ + >= ((level)&APLOG_LEVELMASK) ) ) +#else +#define APLOG_MODULE_IS_LEVEL(s,module_index,level) \ + ( (((level)&APLOG_LEVELMASK) <= APLOG_MAX_LOGLEVEL) && \ + ( (((level)&APLOG_LEVELMASK) <= APLOG_NOTICE) || \ + (s == NULL) || \ + (ap_get_module_loglevel(s, module_index) \ + >= ((level)&APLOG_LEVELMASK) ) ) ) +#endif + +#define APLOG_IS_LEVEL(s,level) \ + APLOG_MODULE_IS_LEVEL(s,APLOG_MODULE_INDEX,level) + +#define APLOGinfo(s) APLOG_IS_LEVEL(s,APLOG_INFO) +#define APLOGdebug(s) APLOG_IS_LEVEL(s,APLOG_DEBUG) +#define APLOGtrace1(s) APLOG_IS_LEVEL(s,APLOG_TRACE1) +#define APLOGtrace2(s) APLOG_IS_LEVEL(s,APLOG_TRACE2) +#define APLOGtrace3(s) APLOG_IS_LEVEL(s,APLOG_TRACE3) +#define APLOGtrace4(s) APLOG_IS_LEVEL(s,APLOG_TRACE4) +#define APLOGtrace5(s) APLOG_IS_LEVEL(s,APLOG_TRACE5) +#define APLOGtrace6(s) APLOG_IS_LEVEL(s,APLOG_TRACE6) +#define APLOGtrace7(s) APLOG_IS_LEVEL(s,APLOG_TRACE7) +#define APLOGtrace8(s) APLOG_IS_LEVEL(s,APLOG_TRACE8) + +#define APLOG_R_IS_LEVEL(r,level) APLOG_IS_LEVEL(r->server,level) +#define APLOGrinfo(r) APLOG_R_IS_LEVEL(r,APLOG_INFO) +#define APLOGrdebug(r) APLOG_R_IS_LEVEL(r,APLOG_DEBUG) +#define APLOGrtrace1(r) APLOG_R_IS_LEVEL(r,APLOG_TRACE1) +#define APLOGrtrace2(r) APLOG_R_IS_LEVEL(r,APLOG_TRACE2) +#define APLOGrtrace3(r) APLOG_R_IS_LEVEL(r,APLOG_TRACE3) +#define APLOGrtrace4(r) APLOG_R_IS_LEVEL(r,APLOG_TRACE4) +#define APLOGrtrace5(r) APLOG_R_IS_LEVEL(r,APLOG_TRACE5) +#define APLOGrtrace6(r) APLOG_R_IS_LEVEL(r,APLOG_TRACE6) +#define APLOGrtrace7(r) APLOG_R_IS_LEVEL(r,APLOG_TRACE7) +#define APLOGrtrace8(r) APLOG_R_IS_LEVEL(r,APLOG_TRACE8) + +#define APLOG_C_IS_LEVEL(c,level) APLOG_IS_LEVEL(c->base_server,level) +#define APLOGcinfo(c) APLOG_C_IS_LEVEL(c,APLOG_INFO) +#define APLOGcdebug(c) APLOG_C_IS_LEVEL(c,APLOG_DEBUG) +#define APLOGctrace1(r) APLOG_C_IS_LEVEL(c,APLOG_TRACE1) +#define APLOGctrace2(r) APLOG_C_IS_LEVEL(c,APLOG_TRACE2) +#define APLOGctrace3(r) APLOG_C_IS_LEVEL(c,APLOG_TRACE3) +#define APLOGctrace4(r) APLOG_C_IS_LEVEL(c,APLOG_TRACE4) +#define APLOGctrace5(r) APLOG_C_IS_LEVEL(c,APLOG_TRACE5) +#define APLOGctrace6(r) APLOG_C_IS_LEVEL(c,APLOG_TRACE6) +#define APLOGctrace7(r) APLOG_C_IS_LEVEL(c,APLOG_TRACE7) +#define APLOGctrace8(r) APLOG_C_IS_LEVEL(c,APLOG_TRACE8) + extern int AP_DECLARE_DATA ap_default_loglevel; -#define APLOG_MARK __FILE__,__LINE__ +#define APLOG_MARK __FILE__,__LINE__,APLOG_MODULE_INDEX /** * Set up for logging to stderr. @@ -147,6 +235,7 @@ void ap_logs_child_init(apr_pool_t *p, server_rec *s); * to the error_log. * @param file The file in which this function is called * @param line The line number on which this function is called + * @param module_index The module_index of the module generating this message * @param level The level of this error message * @param status The status code from the previous command * @param s The server on which we are logging @@ -164,10 +253,20 @@ void ap_logs_child_init(apr_pool_t *p, server_rec *s); * simple format string like "%s", followed by the string containing the * untrusted data. */ -AP_DECLARE(void) ap_log_error(const char *file, int line, int level, - apr_status_t status, const server_rec *s, - const char *fmt, ...) - __attribute__((format(printf,6,7))); +#if __STDC_VERSION__ >= 199901L +/* need additional step to expand APLOG_MARK first */ +#define ap_log_error(...) ap_log_error__(__VA_ARGS__) +#define ap_log_error__(file, line, mi, level, status, s, ...) \ + do { server_rec *sr = s; if (APLOG_MODULE_IS_LEVEL(sr, mi, level)) \ + ap_log_error_(file, line, mi, level, status, sr, __VA_ARGS__); \ + } while(0) +#else +#define ap_log_error ap_log_error_ +#endif +AP_DECLARE(void) ap_log_error_(const char *file, int line, int module_index, + int level, apr_status_t status, + const server_rec *s, const char *fmt, ...) + __attribute__((format(printf,7,8))); /** * ap_log_perror() - log messages which are not related to a particular @@ -175,6 +274,7 @@ AP_DECLARE(void) ap_log_error(const char *file, int line, int level, * format to log messages to the error_log. * @param file The file in which this function is called * @param line The line number on which this function is called + * @param module_index ignored dummy value for use by APLOG_MARK * @param level The level of this error message * @param status The status code from the previous command * @param p The pool which we are logging for @@ -188,10 +288,20 @@ AP_DECLARE(void) ap_log_error(const char *file, int line, int level, * simple format string like "%s", followed by the string containing the * untrusted data. */ -AP_DECLARE(void) ap_log_perror(const char *file, int line, int level, - apr_status_t status, apr_pool_t *p, - const char *fmt, ...) - __attribute__((format(printf,6,7))); +#if __STDC_VERSION__ >= 199901L && defined(APLOG_MAX_LOGLEVEL) +/* need additional step to expand APLOG_MARK first */ +#define ap_log_perror(...) ap_log_perror__(__VA_ARGS__) +#define ap_log_perror__(file, line, mi, level, status, p, ...) \ + do { if ((level) <= APLOG_MAX_LOGLEVEL ) \ + ap_do_log_perror(file, line, mi, level, status, p, \ + __VA_ARGS__); } while(0) +#else +#define ap_log_perror ap_log_perror_ +#endif +AP_DECLARE(void) ap_log_perror_(const char *file, int line, int module_index, + int level, apr_status_t status, apr_pool_t *p, + const char *fmt, ...) + __attribute__((format(printf,7,8))); /** * ap_log_rerror() - log messages which are related to a particular @@ -199,6 +309,7 @@ AP_DECLARE(void) ap_log_perror(const char *file, int line, int level, * error_log. * @param file The file in which this function is called * @param line The line number on which this function is called + * @param module_index The module_index of the module generating this message * @param level The level of this error message * @param status The status code from the previous command * @param r The request which we are logging for @@ -212,10 +323,20 @@ AP_DECLARE(void) ap_log_perror(const char *file, int line, int level, * simple format string like "%s", followed by the string containing the * untrusted data. */ -AP_DECLARE(void) ap_log_rerror(const char *file, int line, int level, - apr_status_t status, const request_rec *r, - const char *fmt, ...) - __attribute__((format(printf,6,7))); +#if __STDC_VERSION__ >= 199901L +/* need additional step to expand APLOG_MARK first */ +#define ap_log_rerror(...) ap_log_rerror__(__VA_ARGS__) +#define ap_log_rerror__(file, line, mi, level, status, r, ...) \ + do { if (APLOG_MODULE_IS_LEVEL(r->server, mi, level)) \ + ap_log_rerror_(file, line, mi, level, status, r, __VA_ARGS__); \ + } while(0) +#else +#define ap_log_rerror ap_log_rerror_ +#endif +AP_DECLARE(void) ap_log_rerror_(const char *file, int line, int module_index, + int level, apr_status_t status, + const request_rec *r, const char *fmt, ...) + __attribute__((format(printf,7,8))); /** * ap_log_cerror() - log messages which are related to a particular @@ -224,6 +345,7 @@ AP_DECLARE(void) ap_log_rerror(const char *file, int line, int level, * @param file The file in which this function is called * @param line The line number on which this function is called * @param level The level of this error message + * @param module_index The module_index of the module generating this message * @param status The status code from the previous command * @param c The connection which we are logging for * @param fmt The format string @@ -238,10 +360,20 @@ AP_DECLARE(void) ap_log_rerror(const char *file, int line, int level, * simple format string like "%s", followed by the string containing the * untrusted data. */ -AP_DECLARE(void) ap_log_cerror(const char *file, int line, int level, - apr_status_t status, const conn_rec *c, - const char *fmt, ...) - __attribute__((format(printf,6,7))); +#if __STDC_VERSION__ >= 199901L +/* need additional step to expand APLOG_MARK first */ +#define ap_log_cerror(...) ap_log_cerror__(__VA_ARGS__) +#define ap_log_cerror__(file, line, mi, level, status, c, ...) \ + do { if (APLOG_MODULE_IS_LEVEL(c->base_server, mi, level)) \ + ap_log_cerror_(file, line, mi, level, status, c, __VA_ARGS__); \ + } while(0) +#else +#define ap_log_cerror ap_log_cerror_ +#endif +AP_DECLARE(void) ap_log_cerror_(const char *file, int line, int module_level, + int level, apr_status_t status, + const conn_rec *c, const char *fmt, ...) + __attribute__((format(printf,7,8))); /** * Convert stderr to the error log @@ -321,6 +453,7 @@ AP_DECLARE(apr_file_t *) ap_piped_log_write_fd(piped_log *pl); * @ingroup hooks * @param file The file in which this function is called * @param line The line number on which this function is called + * @param module_index The module_index of the module generating this message * @param level The level of this error message * @param status The status code from the previous command * @param s The server which we are logging for @@ -328,7 +461,8 @@ AP_DECLARE(apr_file_t *) ap_piped_log_write_fd(piped_log *pl); * @param pool Memory pool to allocate from * @param errstr message to log */ -AP_DECLARE_HOOK(void, error_log, (const char *file, int line, int level, +AP_DECLARE_HOOK(void, error_log, (const char *file, int line, + int module_index, int level, apr_status_t status, const server_rec *s, const request_rec *r, apr_pool_t *pool, const char *errstr)) diff --git a/include/httpd.h b/include/httpd.h index 5c52148ee7..9d1ccda5a6 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -1186,6 +1186,8 @@ struct server_rec { /* Log files --- note that transfer log is now in the modules... */ + /** The per-module log levels */ + int *module_loglevels; /** The name of the error log */ char *error_fname; /** A file descriptor that references the error log */ diff --git a/server/config.c b/server/config.c index 9d468f07fb..1cd97e9aef 100644 --- a/server/config.c +++ b/server/config.c @@ -50,6 +50,8 @@ #include "http_vhost.h" #include "util_cfgtree.h" +APLOG_USE_MODULE(core); + AP_DECLARE_DATA const char *ap_server_argv0 = NULL; AP_DECLARE_DATA const char *ap_server_root = NULL; AP_DECLARE_DATA server_rec *ap_server_conf = NULL; @@ -1353,6 +1355,26 @@ AP_DECLARE_NONSTD(const char *) ap_set_deprecated(cmd_parms *cmd, return cmd->cmd->errmsg; } +AP_DECLARE(void) ap_reset_module_loglevels(server_rec *s) +{ + if (s->module_loglevels) { + memset(s->module_loglevels, -1, + sizeof(int) * (total_modules + DYNAMIC_MODULE_LIMIT)); + } +} + +AP_DECLARE(void) ap_set_module_loglevel(apr_pool_t *pool, server_rec *s, + int index, int level) +{ + if (!s->module_loglevels) { + s->module_loglevels = apr_palloc(pool, + sizeof(int) * (total_modules + DYNAMIC_MODULE_LIMIT)); + ap_reset_module_loglevels(s); + } + + s->module_loglevels[index] = level; +} + /***************************************************************** * * Reading whole config files... @@ -1960,6 +1982,7 @@ AP_CORE_DECLARE(const char *) ap_init_virtual_host(apr_pool_t *p, s->keep_alive_max = -1; s->error_log = main_server->error_log; s->loglevel = main_server->loglevel; + s->module_loglevels = NULL; /* useful default, otherwise we get a port of 0 on redirects */ s->port = main_server->port; s->next = NULL; @@ -2008,6 +2031,18 @@ AP_DECLARE(void) ap_fixup_virtual_hosts(apr_pool_t *p, server_rec *main_server) if (virt->keep_alive_max == -1) virt->keep_alive_max = main_server->keep_alive_max; + if (virt->module_loglevels == NULL) { + virt->module_loglevels = main_server->module_loglevels; + } + else if (main_server->module_loglevels != NULL) { + int i; + for (i = 0; i < total_modules + DYNAMIC_MODULE_LIMIT; i++) { + if (virt->module_loglevels[i] < 0) + virt->module_loglevels[i] = + main_server->module_loglevels[i]; + } + } + /* XXX: this is really something that should be dealt with by a * post-config api phase */ @@ -2041,6 +2076,7 @@ static server_rec *init_server_config(process_rec *process, apr_pool_t *p) s->server_scheme = NULL; s->error_fname = DEFAULT_ERRORLOG; s->loglevel = DEFAULT_LOGLEVEL; + s->module_loglevels = NULL; s->limit_req_line = DEFAULT_LIMIT_REQUEST_LINE; s->limit_req_fieldsize = DEFAULT_LIMIT_REQUEST_FIELDSIZE; s->limit_req_fields = DEFAULT_LIMIT_REQUEST_FIELDS; diff --git a/server/core.c b/server/core.c index 63e4b1cb62..9f29d562cf 100644 --- a/server/core.c +++ b/server/core.c @@ -2625,24 +2625,60 @@ static const char *include_config (cmd_parms *cmd, void *dummy, return NULL; } -static const char *set_loglevel(cmd_parms *cmd, void *dummy, const char *arg) +static const char *set_loglevel(cmd_parms *cmd, void *dummy, const char *arg_) { - char *str; + char *level_str; + int level; + module *module; + char *arg = apr_pstrdup(cmd->temp_pool, arg_); const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); if (err != NULL) { return err; } - if ((str = ap_getword_conf(cmd->pool, &arg))) { - err = ap_parse_log_level(str, &cmd->server->loglevel); + if (arg == NULL) + return "LogLevel requires level keyword or module loglevel specifier"; + + level_str = ap_strchr(arg, ':'); + + if (level_str == NULL) { + err = ap_parse_log_level(arg, &cmd->server->loglevel); if (err != NULL) - return apr_psprintf(cmd->pool, "LogLevel: %s", err); + return err; + ap_reset_module_loglevels(cmd->server); + ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, cmd->server, + "Setting LogLevel for all modules to %s", arg); + return NULL; } - else { - return "LogLevel requires level keyword"; + + *level_str++ = '\0'; + if (!*level_str) { + return apr_psprintf(cmd->temp_pool, "Module specifier '%s' must be " + "followed by a log level keyword", arg); } + err = ap_parse_log_level(level_str, &level); + if (err != NULL) + return apr_psprintf(cmd->temp_pool, "%s:%s: %s", arg, level_str, err); + + if ((module = find_module(cmd->server, arg)) == NULL) { + char *name = apr_psprintf(cmd->temp_pool, "%s_module", arg); + ap_log_error(APLOG_MARK, APLOG_TRACE6, 0, cmd->server, + "Cannot find module '%s', trying '%s'", arg, name); + module = find_module(cmd->server, name); + } + + if (module == NULL) { + return apr_psprintf(cmd->temp_pool, "Cannot find module %s", arg); + } + + ap_set_module_loglevel(cmd->pool, cmd->server, module->module_index, + level); + ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, cmd->server, + "Setting LogLevel for module %s to %s", module->name, + level_str); + return NULL; } @@ -3319,7 +3355,7 @@ AP_INIT_TAKE1("IncludeOptional", include_config, (void*)1, (RSRC_CONF | ACCESS_CONF | EXEC_ON_READ), "Name or pattern of the config file(s) to be included; ignored if the file " "does not exist or the pattern does not match any files"), -AP_INIT_TAKE1("LogLevel", set_loglevel, NULL, RSRC_CONF, +AP_INIT_ITERATE("LogLevel", set_loglevel, NULL, RSRC_CONF, "Level of verbosity in error logging"), AP_INIT_TAKE1("NameVirtualHost", ap_set_name_virtual_host, NULL, RSRC_CONF, "A numeric IP address:port, or the name of a host"), @@ -3990,7 +4026,7 @@ static void register_hooks(apr_pool_t *p) NULL, AP_FTYPE_RESOURCE - 10); } -AP_DECLARE_DATA module core_module = { +AP_DECLARE_MODULE(core) = { MPM20_MODULE_STUFF, AP_PLATFORM_REWRITE_ARGS_HOOK, /* hook to run before apache parses args */ create_core_dir_config, /* create per-directory config structure */ diff --git a/server/log.c b/server/log.c index 9d9e24f4d5..49ab7ad77b 100644 --- a/server/log.c +++ b/server/log.c @@ -49,6 +49,8 @@ #include "util_time.h" #include "ap_mpm.h" +APLOG_USE_MODULE(core); + typedef struct { const char *t_name; int t_val; @@ -134,6 +136,14 @@ static const TRANS priorities[] = { {"notice", APLOG_NOTICE}, {"info", APLOG_INFO}, {"debug", APLOG_DEBUG}, + {"trace1", APLOG_TRACE1}, + {"trace2", APLOG_TRACE2}, + {"trace3", APLOG_TRACE3}, + {"trace4", APLOG_TRACE4}, + {"trace5", APLOG_TRACE5}, + {"trace6", APLOG_TRACE6}, + {"trace7", APLOG_TRACE7}, + {"trace8", APLOG_TRACE8}, {NULL, -1}, }; @@ -535,7 +545,8 @@ AP_DECLARE(void) ap_error_log2stderr(server_rec *s) { } } -static void log_error_core(const char *file, int line, int level, +static void log_error_core(const char *file, int line, int module_index, + int level, apr_status_t status, const server_rec *s, const conn_rec *c, const request_rec *r, apr_pool_t *pool, @@ -572,10 +583,10 @@ static void log_error_core(const char *file, int line, int level, else if (s->error_log) { /* * If we are doing normal logging, don't log messages that are - * above the server log level unless it is a startup/shutdown notice + * above the module's log level unless it is a startup/shutdown notice */ if ((level_and_mask != APLOG_NOTICE) - && (level_and_mask > s->loglevel)) { + && (level_and_mask > ap_get_module_loglevel(s, module_index))) { return; } @@ -584,9 +595,9 @@ static void log_error_core(const char *file, int line, int level, else { /* * If we are doing syslog logging, don't log messages that are - * above the server log level (including a startup/shutdown notice) + * above the module's log level (including a startup/shutdown notice) */ - if (level_and_mask > s->loglevel) { + if (level_and_mask > ap_get_module_loglevel(s, module_index)) { return; } } @@ -606,7 +617,7 @@ static void log_error_core(const char *file, int line, int level, "[%s] ", priorities[level_and_mask].t_name); } - if (file && level_and_mask == APLOG_DEBUG) { + if (file && level_and_mask >= APLOG_DEBUG) { #if defined(_OSD_POSIX) || defined(WIN32) || defined(__MVS__) char tmp[256]; char *e = strrchr(file, '/'); @@ -719,44 +730,48 @@ static void log_error_core(const char *file, int line, int level, } #ifdef HAVE_SYSLOG else { - syslog(level_and_mask, "%s", errstr); + syslog(level_and_mask < LOG_PRIMASK ? level_and_mask : APLOG_DEBUG, + "%s", errstr); } #endif - ap_run_error_log(file, line, level, status, s, r, pool, errstr + errstrlen); + ap_run_error_log(file, line, module_index, level, status, s, r, pool, + errstr + errstrlen); } -AP_DECLARE(void) ap_log_error(const char *file, int line, int level, - apr_status_t status, const server_rec *s, - const char *fmt, ...) +AP_DECLARE(void) ap_log_error_(const char *file, int line, int module_index, + int level, apr_status_t status, + const server_rec *s, const char *fmt, ...) { va_list args; va_start(args, fmt); - log_error_core(file, line, level, status, s, NULL, NULL, NULL, fmt, args); + log_error_core(file, line, module_index, level, status, s, NULL, NULL, + NULL, fmt, args); va_end(args); } -AP_DECLARE(void) ap_log_perror(const char *file, int line, int level, - apr_status_t status, apr_pool_t *p, - const char *fmt, ...) +AP_DECLARE(void) ap_log_perror_(const char *file, int line, int module_index, + int level, apr_status_t status, apr_pool_t *p, + const char *fmt, ...) { va_list args; va_start(args, fmt); - log_error_core(file, line, level, status, NULL, NULL, NULL, p, fmt, args); + log_error_core(file, line, module_index, level, status, NULL, NULL, NULL, + p, fmt, args); va_end(args); } -AP_DECLARE(void) ap_log_rerror(const char *file, int line, int level, - apr_status_t status, const request_rec *r, - const char *fmt, ...) +AP_DECLARE(void) ap_log_rerror_(const char *file, int line, int module_index, + int level, apr_status_t status, + const request_rec *r, const char *fmt, ...) { va_list args; va_start(args, fmt); - log_error_core(file, line, level, status, r->server, NULL, r, NULL, fmt, - args); + log_error_core(file, line, module_index, level, status, r->server, NULL, r, + NULL, fmt, args); /* * IF APLOG_TOCLIENT is set, @@ -777,15 +792,15 @@ AP_DECLARE(void) ap_log_rerror(const char *file, int line, int level, va_end(args); } -AP_DECLARE(void) ap_log_cerror(const char *file, int line, int level, - apr_status_t status, const conn_rec *c, - const char *fmt, ...) +AP_DECLARE(void) ap_log_cerror_(const char *file, int line, int module_index, + int level, apr_status_t status, + const conn_rec *c, const char *fmt, ...) { va_list args; va_start(args, fmt); - log_error_core(file, line, level, status, c->base_server, c, NULL, NULL, - fmt, args); + log_error_core(file, line, module_index, level, status, c->base_server, c, + NULL, NULL, fmt, args); va_end(args); } @@ -1162,7 +1177,7 @@ AP_DECLARE(void) ap_close_piped_log(piped_log *pl) AP_DECLARE(const char *) ap_parse_log_level(const char *str, int *val) { char *err = "Log level keyword must be one of emerg/alert/crit/error/warn/" - "notice/info/debug"; + "notice/info/debug/trace1/.../trace8"; int i = 0; if (str == NULL) @@ -1179,8 +1194,8 @@ AP_DECLARE(const char *) ap_parse_log_level(const char *str, int *val) } AP_IMPLEMENT_HOOK_VOID(error_log, - (const char *file, int line, int level, + (const char *file, int line, int module_index, int level, apr_status_t status, const server_rec *s, const request_rec *r, apr_pool_t *pool, - const char *errstr), (file, line, level, + const char *errstr), (file, line, module_index, level, status, s, r, pool, errstr)) diff --git a/server/util_debug.c b/server/util_debug.c index 0387c724b8..0230038b0e 100644 --- a/server/util_debug.c +++ b/server/util_debug.c @@ -106,6 +106,22 @@ AP_DECLARE(void *) ap_get_module_config(const ap_conf_vector_t *cv, return ((void **)cv)[m->module_index]; } +#if defined(ap_get_module_loglevel) +#undef ap_get_module_loglevel +AP_DECLARE(int) ap_get_module_loglevel(const server_rec *s, int module_index); +#endif + +AP_DECLARE(int) ap_get_module_loglevel(const server_rec *s, int module_index) +{ + if (module_index < 0 || s->module_loglevels == NULL || + s->module_loglevels[module_index] < 0) + { + return s->loglevel; + } + + return s->module_loglevels[module_index]; +} + /** * Generic accessors for other modules to set at their own module-specific * data -- 2.40.0