From: Christos Tsantilas Date: Fri, 2 May 2014 07:51:33 +0000 (-0700) Subject: Logformat annotation fixes X-Git-Tag: SQUID_3_4_5~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d01ea2048517315c3446b780dc1dc0f00abf3b61;p=thirdparty%2Fsquid.git Logformat annotation fixes Currently note values printed with "%note" formating code, which contain non alphanumeric characters, were quoted and quotes were then escaped, resulting in bizarre logged rendition of empty or simple values (often received from various helpers): %22-%22 %22Default_Google%22 %22pg13,US%22 This patch: - does not use quotes to print annotations - allow system admin to define a separator to use for logged annotations. The %note logformat accepts the following argument: [name][:separator] The separator can be one of the ',' ';' or ':'. By default, multiple note values are separated with "," and multiple notes are separated with "\r\n". When logging named notes with %{name}note, the explicitly configured separator is used between note values. When logging all notes with %note, the explicitly configured separator is used between individual notes. There is currently no way to specify both value and notes separators when logging all notes with %note. - makes the Format::Token::data a struct (now is a union) and initialize Format::Token::data data members in Format::Token::Token constructor. This is a Measurement Factory project --- diff --git a/src/Notes.cc b/src/Notes.cc index a981ad2fee..00039565f6 100644 --- a/src/Notes.cc +++ b/src/Notes.cc @@ -144,15 +144,15 @@ NotePairs::~NotePairs() } const char * -NotePairs::find(const char *noteKey) const +NotePairs::find(const char *noteKey, const char *sep) const { static String value; value.clean(); for (Vector::const_iterator i = entries.begin(); i != entries.end(); ++i) { if ((*i)->name.cmp(noteKey) == 0) { if (value.size()) - value.append(", "); - value.append(ConfigParser::QuoteString((*i)->value)); + value.append(sep); + value.append((*i)->value); } } return value.size() ? value.termedBuf() : NULL; @@ -166,7 +166,7 @@ NotePairs::toString(const char *sep) const for (Vector::const_iterator i = entries.begin(); i != entries.end(); ++i) { value.append((*i)->name); value.append(": "); - value.append(ConfigParser::QuoteString((*i)->value)); + value.append((*i)->value); value.append(sep); } return value.size() ? value.termedBuf() : NULL; diff --git a/src/Notes.h b/src/Notes.h index 341b482716..47950d4c88 100644 --- a/src/Notes.h +++ b/src/Notes.h @@ -140,7 +140,7 @@ public: * Returns a comma separated list of notes with key 'noteKey'. * Use findFirst instead when a unique kv-pair is needed. */ - const char *find(const char *noteKey) const; + const char *find(const char *noteKey, const char *sep = ",") const; /** * Returns the first note value for this key or an empty string. diff --git a/src/cf.data.pre b/src/cf.data.pre index 88f4c0c6e0..777d73c24a 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -3700,10 +3700,22 @@ DOC_START err_code The ID of an error response served by Squid or a similar internal error identifier. err_detail Additional err_code-dependent error information. - note The meta header specified by the argument. Also + note The annotation specified by the argument. Also logs the adaptation meta headers set by the adaptation_meta configuration parameter. - If no argument given all meta headers logged. + If no argument given all annotations logged. + The argument may include a separator to use with + annotation values: + name[:separator] + By default, multiple note values are separated with "," + and multiple notes are separated with "\r\n". + When logging named notes with %{name}note, the + explicitly configured separator is used between note + values. When logging all notes with %note, the + explicitly configured separator is used between + individual notes. There is currently no way to + specify both value and notes separators when logging + all notes with %note. Connection related format codes: diff --git a/src/format/Format.cc b/src/format/Format.cc index e737280e8e..10d1f67625 100644 --- a/src/format/Format.cc +++ b/src/format/Format.cc @@ -1076,31 +1076,36 @@ Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logS #endif case LFT_NOTE: - if (fmt->data.string) { + tmp[0] = fmt->data.header.separator; + tmp[1] = '\0'; + if (fmt->data.header.header && *fmt->data.header.header) { + const char *separator = tmp; #if USE_ADAPTATION Adaptation::History::Pointer ah = al->request ? al->request->adaptHistory() : Adaptation::History::Pointer(); if (ah != NULL && ah->metaHeaders != NULL) { - if (const char *meta = ah->metaHeaders->find(fmt->data.string)) + if (const char *meta = ah->metaHeaders->find(fmt->data.header.header, separator)) sb.append(meta); } #endif if (al->notes != NULL) { - if (const char *note = al->notes->find(fmt->data.string)) { + if (const char *note = al->notes->find(fmt->data.header.header, separator)) { if (sb.size()) - sb.append(", "); + sb.append(separator); sb.append(note); } } out = sb.termedBuf(); quote = 1; } else { + // if no argument given use default "\r\n" as notes separator + const char *separator = fmt->data.string ? tmp : "\r\n"; #if USE_ADAPTATION Adaptation::History::Pointer ah = al->request ? al->request->adaptHistory() : Adaptation::History::Pointer(); if (ah != NULL && ah->metaHeaders != NULL && !ah->metaHeaders->empty()) - sb.append(ah->metaHeaders->toString()); + sb.append(ah->metaHeaders->toString(separator)); #endif if (al->notes != NULL && !al->notes->empty()) - sb.append(al->notes->toString()); + sb.append(al->notes->toString(separator)); out = sb.termedBuf(); quote = 1; diff --git a/src/format/Token.cc b/src/format/Token.cc index 1dd60e6c50..6f67b144e7 100644 --- a/src/format/Token.cc +++ b/src/format/Token.cc @@ -404,6 +404,8 @@ done: case LFT_REPLY_HEADER: + case LFT_NOTE: + if (data.string) { char *header = data.string; char *cp = strchr(header, ':'); @@ -538,6 +540,25 @@ done: return (cur - def); } +Format::Token::Token() : type(LFT_NONE), + label(NULL), + widthMin(-1), + widthMax(-1), + quote(LOG_QUOTE_NONE), + left(false), + space(false), + zero(false), + divisor(1), + next(NULL) +{ + data.string = NULL; + data.header.header = NULL; + data.header.element = NULL; + data.header.separator = ','; +} + + + Format::Token::~Token() { label = NULL; // drop reference to global static. diff --git a/src/format/Token.h b/src/format/Token.h index f8b3c62264..a50c38a722 100644 --- a/src/format/Token.h +++ b/src/format/Token.h @@ -27,18 +27,7 @@ class TokenTableEntry; class Token { public: - Token() : type(LFT_NONE), - label(NULL), - widthMin(-1), - widthMax(-1), - quote(LOG_QUOTE_NONE), - left(false), - space(false), - zero(false), - divisor(1), - next(NULL) - { data.string = NULL; } - + Token(); ~Token(); /// Initialize the format token registrations @@ -52,7 +41,7 @@ public: ByteCode_t type; const char *label; - union { + struct { char *string; struct {