diff options
-rw-r--r-- | Makefile.in | 4 | ||||
-rw-r--r-- | docs/log-message-tags/README | 53 | ||||
-rw-r--r-- | docs/log-message-tags/find-messages.cocci | 18 | ||||
-rw-r--r-- | docs/log-message-tags/macros.h | 23 | ||||
-rw-r--r-- | docs/log-message-tags/next-number | 1 | ||||
-rw-r--r-- | docs/log-message-tags/update-log-msg-tags | 155 | ||||
-rw-r--r-- | include/ap_mmn.h | 1 | ||||
-rw-r--r-- | include/http_log.h | 8 |
8 files changed, 263 insertions, 0 deletions
diff --git a/Makefile.in b/Makefile.in index e5d75c8ac2..9311dff592 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 index 0000000000..1b4803f814 --- /dev/null +++ b/docs/log-message-tags/README @@ -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 index 0000000000..f3e6a9acbe --- /dev/null +++ b/docs/log-message-tags/find-messages.cocci @@ -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 index 0000000000..f4c120ddbd --- /dev/null +++ b/docs/log-message-tags/macros.h @@ -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 index 0000000000..d00491fd7e --- /dev/null +++ b/docs/log-message-tags/next-number @@ -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 index 0000000000..ddd245dfb8 --- /dev/null +++ b/docs/log-message-tags/update-log-msg-tags @@ -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; +} diff --git a/include/ap_mmn.h b/include/ap_mmn.h index ed6a27b63f..9f2f5543d5 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -372,6 +372,7 @@ * 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" */ diff --git a/include/http_log.h b/include/http_log.h index 68a6c8f20d..66ed59ca7d 100644 --- a/include/http_log.h +++ b/include/http_log.h @@ -109,6 +109,14 @@ extern "C" { #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 * should not be used directly. Use ::APLOG_MARK or ::APLOG_MODULE_INDEX |