summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.in4
-rw-r--r--docs/log-message-tags/README53
-rw-r--r--docs/log-message-tags/find-messages.cocci18
-rw-r--r--docs/log-message-tags/macros.h23
-rw-r--r--docs/log-message-tags/next-number1
-rw-r--r--docs/log-message-tags/update-log-msg-tags155
-rw-r--r--include/ap_mmn.h1
-rw-r--r--include/http_log.h8
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