From 3d2e4f8e7078259d05b9aedc20fc73102eb396c1 Mon Sep 17 00:00:00 2001 From: Jacquin Antoine Date: Sun, 1 Mar 2026 02:31:16 +0100 Subject: [PATCH] feature: add JsonSockLogLevel directive for configurable log levels - New directive: JsonSockLogLevel (DEBUG, INFO, WARNING, ERROR, EMERG) - Default level: WARNING - Controls verbosity of module logs in Apache error_log - DEBUG: Log header skipping, buffer truncation, size limits - Updates conf/mod_reqin_log.conf with example configuration Co-authored-by: Qwen-Coder --- conf/mod_reqin_log.conf | 8 +++++ mod_reqin_log.spec | 1 + src/mod_reqin_log.c | 66 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 67 insertions(+), 8 deletions(-) diff --git a/conf/mod_reqin_log.conf b/conf/mod_reqin_log.conf index 5b914b1..1721976 100644 --- a/conf/mod_reqin_log.conf +++ b/conf/mod_reqin_log.conf @@ -27,3 +27,11 @@ JsonSockLogReconnectInterval 10 # Minimum delay between error messages to Apache error_log (seconds) JsonSockLogErrorReportInterval 10 + +# Log level for module messages: DEBUG, INFO, WARNING, ERROR, EMERG (default: WARNING) +# DEBUG: Log all messages including header skipping and buffer truncation +# INFO: Log informational messages +# WARNING: Log warnings (default) +# ERROR: Log only errors +# EMERG: Log only emergency messages +JsonSockLogLevel WARNING diff --git a/mod_reqin_log.spec b/mod_reqin_log.spec index 9d19da4..7a2186a 100644 --- a/mod_reqin_log.spec +++ b/mod_reqin_log.spec @@ -40,6 +40,7 @@ install -m 644 %{_pkgroot}/%{_sysconfdir}/httpd/conf.d/mod_reqin_log.conf %{buil * Sun Mar 01 2026 Developer - 1.0.6 - CONF: Change default socket path to /var/run/logcorrelator/http.socket - BUILD: Allow Docker cache for RPM builds (remove --no-cache flag) +- FEATURE: Add JsonSockLogLevel directive (DEBUG, INFO, WARNING, ERROR, EMERG) * Sun Mar 01 2026 Developer - 1.0.4 - BUILD: Fix RPM package paths in Dockerfile.package (el8, el9, el10 directories) diff --git a/src/mod_reqin_log.c b/src/mod_reqin_log.c index 2daf63b..27ce1f4 100644 --- a/src/mod_reqin_log.c +++ b/src/mod_reqin_log.c @@ -54,6 +54,9 @@ } \ } while(0) +/* Helper macro to check if a log level should be emitted */ +#define SHOULD_LOG(srv_conf, level) ((srv_conf) && (srv_conf)->log_level <= (level)) + /* Default sensitive headers blacklist - prevents accidental logging of credentials */ static const char *const DEFAULT_SENSITIVE_HEADERS[] = { "Authorization", @@ -84,10 +87,20 @@ typedef struct { int connect_failed; } reqin_log_child_state_t; +/* Log levels */ +typedef enum { + REQIN_LOG_LEVEL_DEBUG = 0, + REQIN_LOG_LEVEL_INFO = 1, + REQIN_LOG_LEVEL_WARNING = 2, + REQIN_LOG_LEVEL_ERROR = 3, + REQIN_LOG_LEVEL_EMERG = 4 +} reqin_log_level_t; + /* Module server configuration structure */ typedef struct { reqin_log_config_t *config; reqin_log_child_state_t child_state; + reqin_log_level_t log_level; } reqin_log_server_conf_t; /* Forward declarations for helper functions */ @@ -107,6 +120,7 @@ static const char *cmd_set_max_headers(cmd_parms *cmd, void *dummy, const char * static const char *cmd_set_max_header_value_len(cmd_parms *cmd, void *dummy, const char *arg); static const char *cmd_set_reconnect_interval(cmd_parms *cmd, void *dummy, const char *arg); static const char *cmd_set_error_report_interval(cmd_parms *cmd, void *dummy, const char *arg); +static const char *cmd_set_log_level(cmd_parms *cmd, void *dummy, const char *arg); /* Forward declarations for hooks */ static int reqin_log_post_read_request(request_rec *r); @@ -130,6 +144,8 @@ static const command_rec reqin_log_cmds[] = { "Reconnect interval in seconds (default: 10)"), AP_INIT_TAKE1("JsonSockLogErrorReportInterval", cmd_set_error_report_interval, NULL, RSRC_CONF, "Error report interval in seconds (default: 10)"), + AP_INIT_TAKE1("JsonSockLogLevel", cmd_set_log_level, NULL, RSRC_CONF, + "Log level: DEBUG, INFO, WARNING, ERROR, EMERG (default: WARNING)"), { NULL } }; @@ -170,6 +186,8 @@ static void *reqin_log_create_server_conf(apr_pool_t *pool, server_rec *s) srv_conf->child_state.last_error_report = 0; srv_conf->child_state.connect_failed = 0; + srv_conf->log_level = REQIN_LOG_LEVEL_WARNING; + return srv_conf; } @@ -413,6 +431,32 @@ static const char *cmd_set_error_report_interval(cmd_parms *cmd, void *dummy, co return NULL; } +static const char *cmd_set_log_level(cmd_parms *cmd, void *dummy, const char *arg) +{ + (void)dummy; + reqin_log_server_conf_t *srv_conf = get_server_conf(cmd->server); + if (srv_conf == NULL) { + return "Internal error: server configuration not available"; + } + if (arg == NULL || arg[0] == '\0') { + return "JsonSockLogLevel must be a non-empty string"; + } + if (strcasecmp(arg, "DEBUG") == 0) { + srv_conf->log_level = REQIN_LOG_LEVEL_DEBUG; + } else if (strcasecmp(arg, "INFO") == 0) { + srv_conf->log_level = REQIN_LOG_LEVEL_INFO; + } else if (strcasecmp(arg, "WARNING") == 0) { + srv_conf->log_level = REQIN_LOG_LEVEL_WARNING; + } else if (strcasecmp(arg, "ERROR") == 0) { + srv_conf->log_level = REQIN_LOG_LEVEL_ERROR; + } else if (strcasecmp(arg, "EMERG") == 0) { + srv_conf->log_level = REQIN_LOG_LEVEL_EMERG; + } else { + return "JsonSockLogLevel must be one of: DEBUG, INFO, WARNING, ERROR, EMERG"; + } + return NULL; +} + /* ============== Socket Functions ============== */ /** @@ -612,7 +656,7 @@ static const char *get_header(request_rec *r, const char *name) return NULL; } -static void log_request(request_rec *r, reqin_log_config_t *cfg, reqin_log_child_state_t *state) +static void log_request(request_rec *r, reqin_log_config_t *cfg, reqin_log_child_state_t *state, reqin_log_server_conf_t *srv_conf) { apr_pool_t *pool; server_rec *s; @@ -736,8 +780,10 @@ static void log_request(request_rec *r, reqin_log_config_t *cfg, reqin_log_child /* Check buffer size before adding headers to prevent memory exhaustion */ if (buf.len >= MAX_JSON_SIZE) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - MOD_REQIN_LOG_NAME ": JSON buffer size limit reached before headers"); + if (SHOULD_LOG(srv_conf, REQIN_LOG_LEVEL_DEBUG)) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + MOD_REQIN_LOG_NAME ": JSON buffer size limit reached before headers"); + } return; } @@ -753,8 +799,10 @@ static void log_request(request_rec *r, reqin_log_config_t *cfg, reqin_log_child /* Skip sensitive headers to prevent credential leakage */ if (is_sensitive_header(header_name)) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - MOD_REQIN_LOG_NAME ": Skipping sensitive header: %s", header_name); + if (SHOULD_LOG(srv_conf, REQIN_LOG_LEVEL_DEBUG)) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + MOD_REQIN_LOG_NAME ": Skipping sensitive header: %s", header_name); + } continue; } @@ -766,8 +814,10 @@ static void log_request(request_rec *r, reqin_log_config_t *cfg, reqin_log_child char *truncated; if (buf.len + header_contrib >= MAX_JSON_SIZE) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - MOD_REQIN_LOG_NAME ": JSON size limit reached, truncating headers"); + if (SHOULD_LOG(srv_conf, REQIN_LOG_LEVEL_DEBUG)) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + MOD_REQIN_LOG_NAME ": JSON size limit reached, truncating headers"); + } break; } @@ -824,7 +874,7 @@ static int reqin_log_post_read_request(request_rec *r) return DECLINED; } - log_request(r, srv_conf->config, &srv_conf->child_state); + log_request(r, srv_conf->config, &srv_conf->child_state, srv_conf); return DECLINED; }