From 107c5573e1521c90a3e735ea72b971e54f87e939 Mon Sep 17 00:00:00 2001
From: Stefan Fritsch <sf@apache.org>
Date: Sun, 26 Sep 2010 07:40:15 +0000
Subject: [PATCH] In ErrorLogFormat, make it possible to log an item only if
 the loglevel of the message is higher than a specified value. This allows to
 achive the old behaviour for the source file name/line number of being only
 logged for debug and higher.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1001381 13f79535-47bb-0310-9956-ffa450edef68
---
 docs/manual/mod/core.xml | 19 ++++++++++++-------
 include/http_core.h      |  9 +++++----
 server/core.c            | 33 +++++++++++++++++++++++++++++----
 server/log.c             |  4 ++++
 4 files changed, 50 insertions(+), 15 deletions(-)

diff --git a/docs/manual/mod/core.xml b/docs/manual/mod/core.xml
index caeecc8874..1a30ea90fa 100644
--- a/docs/manual/mod/core.xml
+++ b/docs/manual/mod/core.xml
@@ -1083,13 +1083,18 @@ in case of an error</description>
     (percent space) is a zero-witdh field delimiter that does not produce any
     output.</p>
 
-    <p>The above behaviour can be changed by adding flags to the format string
-    item. A <code>-</code> (minus) flag causes a minus to be logged if the
+    <p>The above behaviour can be changed by adding modifiers to the format
+    string item. A <code>-</code> (minus) modifier causes a minus to be logged if the
     respective item does not produce any output. In once-per-connection/request
-    formats, it is also possible to use the <code>+</code> (plus) flag. If an
-    item with the plus flag does not produce any output, the whole line is
+    formats, it is also possible to use the <code>+</code> (plus) modifier. If an
+    item with the plus modifier does not produce any output, the whole line is
     ommitted.</p>
 
+    <p>A number as modifier can be used to assign a log severity level to a
+    format item. The item will only be logged if the severity of the log
+    message is not higher than the specified log severity level. The number can
+    range from 1 (alert) over 4 (warn) and 7 (debug) to 15 (trace8).</p>
+
     <p>Some format string items accept additional parameters in braces.</p>
 
     <table border="1" style="zebra">
@@ -1173,17 +1178,17 @@ in case of an error</description>
     with error log lines.</p>
 
     <example><title>Example (somewhat similar to default format)</title>
-        ErrorLogFormat "[%{u}t] [%-m:%l] [pid %P] %F: %E: [client\ %a]
+        ErrorLogFormat "[%{u}t] [%-m:%l] [pid %P] %7F: %E: [client\ %a]
         %M%&nbsp;,\&nbsp;referer\&nbsp;%{Referer}i"
     </example>
 
     <example><title>Example (similar to the 2.2.x format)</title>
-        ErrorLogFormat "[%t] [%l] %F: %E: [client\ %a]
+        ErrorLogFormat "[%t] [%l] %7F: %E: [client\ %a]
         %M%&nbsp;,\&nbsp;referer\&nbsp;%{Referer}i"
     </example>
 
     <example><title>Advanced example with request/connection log IDs</title>
-        ErrorLogFormat "[%{uc}t] [%-m:%-l] [R:%L] [C:%{C}L] %M"<br/>
+        ErrorLogFormat "[%{uc}t] [%-m:%-l] [R:%L] [C:%{C}L] %7F: %E: %M"<br/>
         ErrorLogFormat request "[%{uc}t] [R:%L] Request %k on C:%{c}L pid:%P tid:%T"<br/>
         ErrorLogFormat request "[%{uc}t] [R:%L] UA:'%+{User-Agent}i'"<br/>
         ErrorLogFormat request "[%{uc}t] [R:%L] Referer:'%+{Referer}i'"<br/>
diff --git a/include/http_core.h b/include/http_core.h
index 9c8fa9e1b2..a4a90461ab 100644
--- a/include/http_core.h
+++ b/include/http_core.h
@@ -721,11 +721,12 @@ typedef struct ap_errorlog_handler {
 typedef struct {
     ap_errorlog_handler_fn_t *func;
     const char *arg;
-#define AP_ERRORLOG_FLAG_FIELD_SEP       1
-#define AP_ERRORLOG_FLAG_MESSAGE         2
-#define AP_ERRORLOG_FLAG_REQUIRED        4
-#define AP_ERRORLOG_FLAG_NULL_AS_HYPHEN  8
+#define AP_ERRORLOG_FLAG_FIELD_SEP       1  /* item starts a new field */
+#define AP_ERRORLOG_FLAG_MESSAGE         2  /* item is the actual error message */
+#define AP_ERRORLOG_FLAG_REQUIRED        4  /* skip whole line if item is zero-length */
+#define AP_ERRORLOG_FLAG_NULL_AS_HYPHEN  8  /* log zero-length item as '-' */
     unsigned int flags;
+    unsigned int min_loglevel;              /* only log if level is higher than this */
 } ap_errorlog_format_item;
 
 AP_DECLARE(void) ap_register_builtin_errorlog_handlers(apr_pool_t *p);
diff --git a/server/core.c b/server/core.c
index b395238696..84e37f358c 100644
--- a/server/core.c
+++ b/server/core.c
@@ -3183,6 +3183,7 @@ static char *parse_errorlog_item(apr_pool_t *p, ap_errorlog_format_item *it,
 {
     const char *s = *sa;
     ap_errorlog_handler *handler;
+    int i;
 
     if (*s != '%') {
         if (*s == ' ') {
@@ -3221,6 +3222,21 @@ static char *parse_errorlog_item(apr_pool_t *p, ap_errorlog_format_item *it,
             ++s;
             it->flags |= AP_ERRORLOG_FLAG_NULL_AS_HYPHEN;
             break;
+        case '0':
+        case '1':
+        case '2':
+        case '3':
+        case '4':
+        case '5':
+        case '6':
+        case '7':
+        case '8':
+        case '9':
+            i = *s - '0';
+            while (apr_isdigit(*++s))
+                i = i * 10 + (*s) - '0';
+            it->min_loglevel = i;
+            break;
         case 'M':
             it->func = NULL;
             it->flags |= AP_ERRORLOG_FLAG_MESSAGE;
@@ -3248,7 +3264,7 @@ static char *parse_errorlog_item(apr_pool_t *p, ap_errorlog_format_item *it,
 static apr_array_header_t *parse_errorlog_string(apr_pool_t *p,
                                                  const char *s,
                                                  const char **err,
-                                                 int want_msg_fmt)
+                                                 int is_main_fmt)
 {
     apr_array_header_t *a = apr_array_make(p, 30,
                                            sizeof(ap_errorlog_format_item));
@@ -3265,20 +3281,29 @@ static apr_array_header_t *parse_errorlog_string(apr_pool_t *p,
             return NULL;
         }
         if (item->flags & AP_ERRORLOG_FLAG_MESSAGE) {
-            if (!want_msg_fmt) {
+            if (!is_main_fmt) {
                 *err = "%M cannot be used in once-per-request or "
                        "once-per-connection formats";
                 return NULL;
             }
             seen_msg_fmt = 1;
         }
-        if (want_msg_fmt && item->flags & AP_ERRORLOG_FLAG_REQUIRED) {
+        if (is_main_fmt && item->flags & AP_ERRORLOG_FLAG_REQUIRED) {
             *err = "The '+' flag cannot be used in the main error log format";
             return NULL;
         }
+	if (!is_main_fmt && item->min_loglevel) {
+            *err = "The loglevel cannot be used as a condition in "
+		   "once-per-request or once-per-connection formats";
+            return NULL;
+        }
+	if (item->min_loglevel > APLOG_TRACE8) {
+            *err = "The specified loglevel modifier is out of range";
+            return NULL;
+        }
     }
 
-    if (want_msg_fmt && !seen_msg_fmt) {
+    if (is_main_fmt && !seen_msg_fmt) {
         *err = "main ErrorLogFormat must contain message format string '%M'";
         return NULL;
     }
diff --git a/server/log.c b/server/log.c
index 72ff781d51..3c3f56ce03 100644
--- a/server/log.c
+++ b/server/log.c
@@ -988,6 +988,10 @@ static int do_errorlog_format(apr_array_header_t *fmt, ap_errorlog_info *info,
         else if (skipping) {
             continue;
         }
+        else if (item->min_loglevel > info->level) {
+            len = field_start;
+            skipping = 1;
+        }
         else {
             int item_len = (*item->func)(info, item->arg, buf + len,
                                          buflen - len);
-- 
2.40.0