]> granicus.if.org Git - apache/commitdiff
Add APLOGNO() macro for unique tags for every log message.
authorStefan Fritsch <sf@apache.org>
Fri, 2 Dec 2011 22:26:54 +0000 (22:26 +0000)
committerStefan Fritsch <sf@apache.org>
Fri, 2 Dec 2011 22:26:54 +0000 (22:26 +0000)
Add some scripts to make adding these tags easier.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1209743 13f79535-47bb-0310-9956-ffa450edef68

Makefile.in
docs/log-message-tags/README [new file with mode: 0644]
docs/log-message-tags/find-messages.cocci [new file with mode: 0644]
docs/log-message-tags/macros.h [new file with mode: 0644]
docs/log-message-tags/next-number [new file with mode: 0644]
docs/log-message-tags/update-log-msg-tags [new file with mode: 0644]
include/ap_mmn.h
include/http_log.h

index e5d75c8ac272c248270a309a7e3e59f28d9d272a..9311dff592b8ced5f32d0197d3fa3b7a8b1f2b2d 100644 (file)
@@ -242,5 +242,9 @@ suexec:
 x-local-distclean:
        @rm -rf autom4te.cache
 
+update-log-tags update-log-msg-tags:
+       find server modules os -name \*.c|xargs perl \
+               docs/log-message-tags/update-log-msg-tags
+
 # XXX: This looks awfully platform-specific [read: bad form and style]
 include $(top_srcdir)/os/os2/core.mk
diff --git a/docs/log-message-tags/README b/docs/log-message-tags/README
new file mode 100644 (file)
index 0000000..1b4803f
--- /dev/null
@@ -0,0 +1,53 @@
+This directory contains the infrastructure to create unique tags for error log
+messages. In the source, the tags use the APLOGNO(02182) macro where the argument
+is a 5 digit decimal number. The macro expands to "AH02182: ".
+
+The idea is that these tags help users finding useful information with search
+engines. The use of the macro is intended to prevent search engine hits at
+svn.apache.org or the svn commit mailing list.
+
+Basic rules:
+
+- Only messages of level debug and higher should get tags.
+- If the same message is logged at two different places in httpd, assign two
+  different tags.
+- If the context changes, where a message is generated, assign a new tag.
+- If only the text of the message changes (e.g. making it more verbose), keep
+  the tag.
+- Never reuse tags that have been removed, numbers are cheap.
+- Use the same tags in different branches.
+- The tag AH02182 is reserved for examples.
+- Currently only modules included in the httpd distribution should do this.
+
+TODO: Define what third-party modules should do.
+
+How to add a few new tags:
+==========================
+
+When adding new error messages, it is easiest to just add empty APLOGNO() tags
+and then run the update-log-msg-tags perl script on the source file. This will
+look into docs/log-message-tags/next-number to determine the next tag to be
+used, fill in all empty APLOGNO() tags, and update
+docs/log-message-tags/next-number accordingly.
+
+The toplevel Makefile has a target update-log-msg-tags to run run the script
+over all *.c files in the source tree.
+
+The script also puts a list of all messages in docs/log-message-tags/list.
+This list should not be committed to svn.
+
+
+How to add lots of new tags:
+============================
+
+In order to find candidate calls to ap_log_*error, coccinelle's spatch command
+can be used.  It will add empty APLOGNO() tags where the loglevel is a
+constant and is of level debug or above. Then, update-log-msg-tags can be used
+to add numbers to the APLOGNO() tags. The invocation for spatch is:
+
+DIR=docs/log-message-tags
+spatch -sp_file $DIR/find-messages.cocci -in_place -macro_file $DIR/macros.h <file1> ...
+
+After the initial addition of tags, calling spatch on the same file again may
+be a bad idea. But it may still be useful when adding larger pieces of code to
+httpd.
diff --git a/docs/log-message-tags/find-messages.cocci b/docs/log-message-tags/find-messages.cocci
new file mode 100644 (file)
index 0000000..f3e6a9a
--- /dev/null
@@ -0,0 +1,18 @@
+@r@
+expression rv, s;
+constant char [] format;
+identifier level ~= "^APLOG_\(EMERG\|ALERT\|CRIT\|ERR\|WARNING\|NOTICE\|INFO\|STARTUP\|DEBUG\)$";
+identifier fn ~= "^ap_log_\(\|r\|c\|p\)error$";
+
+@@
+        fn( APLOG_MARK ,
+(
+        level
+|
+        level|APLOG_NOERROR
+|
+        level|APLOG_STARTUP
+)
+        ,rv, s
++       , APLOGNO()
+        ,format, ...)
diff --git a/docs/log-message-tags/macros.h b/docs/log-message-tags/macros.h
new file mode 100644 (file)
index 0000000..f4c120d
--- /dev/null
@@ -0,0 +1,23 @@
+#define AP_DECLARE(x)             x
+#define AP_DECLARE_NONSTD(x)      x
+#define AP_CORE_DECLARE(x)        x
+#define AP_CORE_DECLARE_NONSTD(x) x
+#define AP_LUA_DECLARE(x)         x
+#define APR_DECLARE(x)            x
+#define APR_DECLARE_NONSTD(x)     x
+#define APU_DECLARE(x)            x
+#define APU_DECLARE_NONSTD(x)     x
+#define PROXY_DECLARE(x)          x
+#define DAV_DECLARE(x)            x
+#define APREQ_DECLARE(x)          x
+#define APREQ_DECLARE_PARSER(x)   x
+
+#define AP_DECLARE_DATA
+#define AP_MODULE_DECLARE_DATA
+#define APR_DECLARE_DATA
+#define APR_MODULE_DECLARE_DATA
+#define APU_DECLARE_DATA
+#define DAV_DECLARE_DATA
+#define PROXY_DECLARE_DATA
+
+#define AP_DECLARE_MODULE(foo)  module foo##_module
diff --git a/docs/log-message-tags/next-number b/docs/log-message-tags/next-number
new file mode 100644 (file)
index 0000000..d00491f
--- /dev/null
@@ -0,0 +1 @@
+1
diff --git a/docs/log-message-tags/update-log-msg-tags b/docs/log-message-tags/update-log-msg-tags
new file mode 100644 (file)
index 0000000..ddd245d
--- /dev/null
@@ -0,0 +1,155 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+my $basedir = "docs/log-message-tags";
+my $serial_file = "$basedir/next-number";
+my $serial = read_serial($serial_file);
+my $orig_serial = $serial;
+my %tags;
+
+foreach my $file (@ARGV) {
+    if ($file !~ /\.c$/) {
+        print STDERR "Skipping non-C file $file\n";
+        next;
+    }
+    process($file);
+}
+write_file($serial_file, "$serial\n") if $serial != $orig_serial;
+
+my $list = "";
+foreach my $tag (sort keys %tags) {
+    my $d = $tags{$tag};
+    $list .= "$tag: $d->{file}:$d->{line}: $d->{msg}\n";
+}
+write_file("$basedir/list", $list);
+
+exit 0;
+
+sub process
+{
+    my $file = shift;
+
+    open(my $fh, "<", $file) or die "open $file: $!";
+    #print STDERR "processing $file\n";
+    my $line = <$fh>;
+    my $modified;
+    my $result = "";
+    while (defined $line) {
+        if ($line =~ s{APLOGNO\(\),?}{gen_tag($file)}e) {
+            $modified = 1;
+        }
+        if ($line =~ /APLOGNO\(\s*(\d{5})\s*\)/ ) {
+            my $lineno = $.;
+            my $tag = $1;
+            while (1) {
+                if ($line =~ s/.*?
+                               APLOGNO\(\s*
+                               (\d+)
+                               \s*\)
+                               (
+                                (?: [\s\n]*
+                                    (?:"
+                                       (?:\\"|[^"])+    # a string constant
+                                       "
+                                      |
+                                       \w+              # things like APR_SIZE_T_FMT
+                                    )
+                                )*                      # zero or more string fragments. We allow
+                                                        # zero because some logging constructs may
+                                                        # use things like:
+                                                        #     logno=APLOGNO(...);
+                                                        #     ap_log_...(..., "%s...", logno, ...)
+                               )
+                               [\s\n]*
+                               [,);:\\]                 # the "," before the next argument,
+                                                        # or the closing brace of ap_log...(),
+                                                        # or the end of a statement (if used
+                                                        # outside of ap_log_...),
+                                                        # or ":" in things like:
+                                                        #     cond ? "msg1" : "msg2",
+                                                        # or "\" at the end of a macro line
+                              //xs) {
+                    my $match = $&;
+                    note_tag($file, $lineno, $1, $2);
+                    $result .= $match;
+                    last;
+                }
+                else {
+                    my $next = <$fh>;
+                    defined $next or die "can't find end of format string in $file:$lineno";
+                    $line .= $next;
+                    if ($next =~ /^#/) {
+                        # log format inside preprocessor #if, that's too complicated
+                        note_tag($file, $lineno, $tag, "");
+                        $result .= $line;
+                        $line = "";
+                        last;
+                    }
+                }
+            };
+        }
+        else {
+            $result .= $line;
+            $line = <$fh>;
+        }
+    }
+    close $fh;
+    write_file($file, $result) if $modified;
+}
+
+sub gen_tag
+{
+    my $file = shift;
+    my $msg = shift;
+    my $tag = sprintf('%05d', $serial++);
+    return "APLOGNO($tag)";
+}
+
+sub note_tag
+{
+    my $file = shift;
+    my $lineno = shift;
+    my $tag = shift;
+    my $msg = shift;
+
+    my $oneline = "";
+    while (length $msg) {
+        $msg =~ s/^[\s\n]+//s;
+        if ($msg =~ s{^"((?:\\"|[^"])+)"}{}) {
+            $oneline .= $1;
+        }
+        if ($msg =~ s{^(\w+)}{}) {
+            $oneline .= $1;
+        }
+    }
+    if (exists $tags{$tag}) {
+        print STDERR "WARNING: Duplicate tag $tag at $tags{$tag}->{file}:$tags{$tag}->{line} and $file:$lineno\n";
+    }
+    $tags{$tag} = { file => $file, line => $lineno, msg => $oneline };
+}
+
+sub write_file
+{
+    my $file = shift;
+    my $data = shift;
+
+    my $tmpname = "$file.$$.tmp";
+
+    open(my $fh, ">", $tmpname) or die "open $tmpname: $!";
+    print $fh $data or die "write $tmpname: $!";
+    close($fh) or die "close $tmpname: $!";
+    rename($tmpname, $file) or die "rename $tmpname -> $file: $!";
+    print STDERR "Updated $file\n";
+}
+
+sub read_serial
+{
+    my $name = shift;
+    open(my $fh, "<", $name) or die "can't open $name, need to be started in the top source dir";
+    my $num = <$fh>;
+    chomp $num;
+    $num =~ /^\d+$/ or die "invalid serial in $name: $num";
+    return $num;
+}
index ed6a27b63f480a7b8aea2965c5ebda838dfb0a3a..9f2f5543d551ebff335bb1bbe3e952a3b719a179 100644 (file)
  *                         add pool to ap_errorlog_info.
  * 20111201.0 (2.5.0-dev)  Add invalidate_entity() to the cache provider.
  * 20111202.0 (2.5.0-dev)  Use apr_status_t across mod_session API.
+ * 20111202.1 (2.5.0-dev)  add APLOGNO()
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
index 68a6c8f20dd8bc4a72b47abdea100ebd408743ab..66ed59ca7d95fbc8206c90991fa23fea05e98f1a 100644 (file)
@@ -108,6 +108,14 @@ extern "C" {
 #define DEFAULT_LOGLEVEL        APLOG_WARNING
 #endif
 
+/**
+ * APLOGNO() should be used at the start of the format string passed
+ * to ap_log_error() and friends. The argument must be a 5 digit decimal
+ * number. It creates a tag of the form "AH02182: "
+ * See docs/log-message-tags/README for details.
+ */
+#define APLOGNO(n)              "AH" #n ": "
+
 /**
  * APLOG_NO_MODULE may be passed as module_index to ap_log_error() and related
  * functions if the module causing the log message is not known. Normally this