Author: Nathan Hoad Author: Alex Rousskov Bug 3389: Auto-reconnect for tcp access_log. Major changes: 1. Squid reconnects to TCP logger as needed. Squid keeps trying to connect forever, using a hard-coded 0.5 second delay between attempts. 2. Squid buffers log records while there is no connectivity. The buffering limit is configurable. 3. On buffer overflows, Squid worker either dies or starts dropping log records. The choice is configurable. 4. The tcp logging module honors buffered_logs setting. Old code was flushing each record. 5. Squid reports changes in logging state to cache.log. Routine connection retries are not reported at level 1, to reduce noise level. 6. A new access_log configuration format/style has been added. It allows us to easily add named options such as buffer-size or on-error. The same format can be used to add module-specific options in the future, but doing so would require changes to the high-level logging code. All old configuration formats/styles are still supported. 7. squid.conf buffered_log option documentation now reflects reality. It used to talk about cache.log but I do not think Squid uses that option for cache.log maintenance. Known minor side-effects of these changes: i) All access_log logs can now be configured to bypass errors because the old "fatal" flag is now configurable via log-specific on-error option in squid.conf. The default is still "die". I have not checked whether modules other than TCP logger honor that flag. ii) All access_log logs now use 8*MAX_URL (64KB) instead of a 4*MAX_URL (32KB) or smaller buffer size by default. The ICAP logger was using 2*MAX_URL buffer size. The TCP logger was using 64KB buffer size before so no change for TCP. I decided that it is better to raise the default buffering level for some logs rather than decrease it for other logs, but it is not clear what the best default is. The buffer size is now configurable via buffer-size so admins can control it on individual log basis. iii) Some access_log configuration styles overlap. To resolve ambiguities, Squid may need to assume that the first logging ACL name (if any) does not contain '=' and is not equal to an existing logformat name. It is possible to use 'all' as the first ACL name if these heuristics cause problems. TODO: We have attempted to solve more TCP logging problems, but it turns out that correct solutions would require fixing higher-level logging code, not specific to TCP logger or Bug 3389 scope. Those unsolved problems include: A. During reconfiguration, all logs are closed and reopened, even if there have been no changes to their configuration that necessitate such a drastic action (or no changes at all!). For TCP logger, this means that the old connection is used to flush remaining buffered records (if any), and the new connection is used to log new records, possibly at the same time. Nathan wrote clever code that keeps logging going using the same job/connection. However, we had to yank that code out because it clashed with higher-level logging state in subtle ways. B. During shutdown, all connections are put in the closing state before logs are told to flush remaining records. For TCP logger, this means that the remaining buffered records (if any) are lost. The correct fix would probably require rearranging shutdown sequence AND letting EventLoop run during shutdown (probably among other things). C. When logger connectivity is lost, Squid does not notice the problem until the second TCP socket write (or later). This results in lost records. This is due to TCP-level buffering. I suspect the only cure for this is adding logger-to-Squid "I got your records" feedback, which requires changes in the logging protocol (currently there is no logger-to-Squid communication at all). # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: rousskov@measurement-factory.com-20130429185049-\ # 65dujc1f0p0e4ikj # target_branch: http://www.squid-cache.org/bzr/squid3/trunk # testament_sha1: 6eae957142f725213d92d9cc703f15a6090d6636 # timestamp: 2013-04-29 13:00:37 -0600 # base_revision_id: rousskov@measurement-factory.com-20130326220843-\ # e8yzu2sprsfmlfee # # Begin patch === modified file 'CONTRIBUTORS' --- CONTRIBUTORS 2013-03-11 00:30:26 +0000 +++ CONTRIBUTORS 2013-04-18 21:43:22 +0000 @@ -39,6 +39,7 @@ Cord Beermann Daniel O'Callaghan David Luyer + Dhaval Varia Diego Woitasen Dmitry Kurochkin Don Hopkins === modified file 'src/Makefile.am' --- src/Makefile.am 2013-03-18 04:55:51 +0000 +++ src/Makefile.am 2013-04-12 15:45:24 +0000 @@ -1487,6 +1487,7 @@ multicast.h \ multicast.cc \ mem_node.cc \ + MemBlob.cc \ MemBuf.cc \ MemObject.cc \ mime.h \ @@ -1901,6 +1902,7 @@ Mem.h \ mem.cc \ mem_node.cc \ + MemBlob.cc \ MemBuf.cc \ MemObject.cc \ mime.h \ @@ -2144,6 +2146,7 @@ internal.cc \ SquidList.h \ SquidList.cc \ + MemBlob.cc \ MemBuf.cc \ MemObject.cc \ Mem.h \ @@ -2387,6 +2390,7 @@ ipcache.cc \ SquidList.h \ SquidList.cc \ + MemBlob.cc \ MemBuf.cc \ MemObject.cc \ Mem.h \ @@ -2677,6 +2681,7 @@ multicast.h \ multicast.cc \ mem_node.cc \ + MemBlob.cc \ MemBuf.cc \ MemObject.cc \ mime.h \ @@ -3647,6 +3652,7 @@ Mem.h \ mem.cc \ mem_node.cc \ + MemBlob.cc \ MemBuf.cc \ MemObject.cc \ mime.h \ === modified file 'src/acl/Gadgets.cc' --- src/acl/Gadgets.cc 2012-09-05 14:49:29 +0000 +++ src/acl/Gadgets.cc 2013-04-16 04:46:27 +0000 @@ -209,7 +209,7 @@ /* next expect a list of ACL names, possibly preceeded * by '!' for negation */ - while ((t = strtok(NULL, w_space))) { + while ((t = parser.strtokFile())) { ACLList *L = new ACLList; if (*t == '!') { === modified file 'src/adaptation/icap/icap_log.cc' --- src/adaptation/icap/icap_log.cc 2012-09-06 13:29:14 +0000 +++ src/adaptation/icap/icap_log.cc 2013-04-05 23:50:25 +0000 @@ -17,7 +17,7 @@ if (log->type == Log::Format::CLF_NONE) continue; - log->logfile = logfileOpen(log->filename, MAX_URL << 1, 1); + log->logfile = logfileOpen(log->filename, log->bufferSize, log->fatal); IcapLogfileStatus = LOG_ENABLE; } === modified file 'src/cache_cf.cc' --- src/cache_cf.cc 2013-03-26 22:08:43 +0000 +++ src/cache_cf.cc 2013-04-29 18:50:49 +0000 @@ -180,6 +180,7 @@ static int check_null_access_log(CustomLog *customlog_definitions); static void dump_access_log(StoreEntry * entry, const char *name, CustomLog * definitions); static void free_access_log(CustomLog ** definitions); +static bool setLogformat(CustomLog *cl, const char *name, const bool dieWhenMissing); static void update_maxobjsize(void); static void configDoConfigure(void); @@ -1224,7 +1225,6 @@ } #endif -#if USE_SSL /** * Parse bytes from a string. * Similar to the parseBytesLine function but parses the string value instead of @@ -1260,7 +1260,6 @@ if (static_cast(*bptr) * 2 != (m * d / u) * 2) self_destruct(); } -#endif static size_t parseBytesUnits(const char *unit) @@ -4024,14 +4023,39 @@ #include "AccessLogEntry.h" +/** + We support several access_log configuration styles: + + #1: Deprecated ancient style without an explicit logging module: + access_log /var/log/access.log + + #2: The "none" logging module (i.e., no logging [of matching transactions]): + access_log none [acl ...] + + #3: Configurable logging module without named options: + Logformat or the first ACL name, whichever comes first, may not contain '='. + If no explicit logformat name is given, the first ACL name, if any, + should not be an existing logformat name or it will be treated as such. + access_log module:place [[logformat_name] acl ...] + + #4: Configurable logging module with name=value options such as logformat=x: + The first ACL name may not contain '='. + access_log module:place [option ...] [acl ...] + +*/ static void parse_access_log(CustomLog ** logs) { - const char *filename, *logdef_name; - CustomLog *cl = (CustomLog *)xcalloc(1, sizeof(*cl)); - if ((filename = strtok(NULL, w_space)) == NULL) { + // default buffer size and fatal settings + cl->bufferSize = 8*MAX_URL; + cl->fatal = true; + + /* determine configuration style */ + + const char *filename = strtok(NULL, w_space); + if (!filename) { self_destruct(); return; } @@ -4045,12 +4069,72 @@ return; } - if ((logdef_name = strtok(NULL, w_space)) == NULL) - logdef_name = "squid"; - - debugs(3, 9, "Log definition name '" << logdef_name << "' file '" << filename << "'"); - cl->filename = xstrdup(filename); + cl->type = Log::Format::CLF_UNKNOWN; + + const char *token = ConfigParser::strtokFile(); + if (!token) { // style #1 + // no options to deal with + } else if (!strchr(token, '=')) { // style #3 + // if logformat name is not recognized, + // put back the token; it must be an ACL name + if (!setLogformat(cl, token, false)) + ConfigParser::strtokFileUndo(); + } else { // style #4 + do { + if (strncasecmp(token, "on-error=", 9) == 0) { + if (strncasecmp(token+9, "die", 3) == 0) { + cl->fatal = true; + } else if (strncasecmp(token+9, "drop", 4) == 0) { + cl->fatal = false; + } else { + debugs(3, DBG_CRITICAL, "Unknown value for on-error '" << + token << "' expected 'drop' or 'die'"); + self_destruct(); + } + } else if (strncasecmp(token, "buffer-size=", 12) == 0) { + parseBytesOptionValue(&cl->bufferSize, B_BYTES_STR, token+12); + } else if (strncasecmp(token, "logformat=", 10) == 0) { + setLogformat(cl, token+10, true); + } else if (!strchr(token, '=')) { + // put back the token; it must be an ACL name + ConfigParser::strtokFileUndo(); + break; // done with name=value options, now to ACLs + } else { + debugs(3, DBG_CRITICAL, "Unknown access_log option " << token); + self_destruct(); + } + } while ((token = ConfigParser::strtokFile()) != NULL); + } + + // set format if it has not been specified explicitly + if (cl->type == Log::Format::CLF_UNKNOWN) + setLogformat(cl, "squid", true); + + aclParseAclList(LegacyParser, &cl->aclList); + + while (*logs) + logs = &(*logs)->next; + + *logs = cl; +} + +/// sets CustomLog::type and, if needed, CustomLog::lf +/// returns false iff there is no named log format +static bool +setLogformat(CustomLog *cl, const char *logdef_name, const bool dieWhenMissing) +{ + assert(cl); + assert(logdef_name); + + debugs(3, 9, "possible " << cl->filename << " logformat: " << logdef_name); + + if (cl->type != Log::Format::CLF_UNKNOWN) { + debugs(3, DBG_CRITICAL, "Second logformat name in one access_log: " << + logdef_name << " " << cl->type << " ? " << Log::Format::CLF_NONE); + self_destruct(); + return false; + } /* look for the definition pointer corresponding to this name */ Format::Format *lf = Log::TheConfig.logformats; @@ -4084,18 +4168,15 @@ cl->type = Log::Format::CLF_USERAGENT; } else if (strcmp(logdef_name, "referrer") == 0) { cl->type = Log::Format::CLF_REFERER; - } else { + } else if (dieWhenMissing) { debugs(3, DBG_CRITICAL, "Log format '" << logdef_name << "' is not defined"); self_destruct(); - return; + return false; + } else { + return false; } - aclParseAclList(LegacyParser, &cl->aclList); - - while (*logs) - logs = &(*logs)->next; - - *logs = cl; + return true; } static int === modified file 'src/cf.data.pre' --- src/cf.data.pre 2013-03-18 10:10:13 +0000 +++ src/cf.data.pre 2013-04-29 18:50:49 +0000 @@ -3692,16 +3692,47 @@ LOC: Config.Log.accesslogs DEFAULT_IF_NONE: daemon:@DEFAULT_ACCESS_LOG@ squid DOC_START - These files log client request activities. Has a line every HTTP or - ICP request. The format is: + Configures whether and how Squid logs HTTP and ICP transactions. + If access logging is enabled, a single line is logged for every + matching HTTP or ICP request. The recommended directive formats are: + + access_log : [option ...] [acl acl ...] + access_log none [acl acl ...]] + + The following directive format is accepted but may be deprecated: access_log : [ [acl acl ...]] - access_log none [acl acl ...]] + + In most cases, the first ACL name must not contain the '=' character + and should not be equal to an existing logformat name. You can always + start with an 'all' ACL to work around those restrictions. Will log to the specified module:place using the specified format (which must be defined in a logformat directive) those entries which match ALL the acl's specified (which must be defined in acl clauses). If no acl is specified, all requests will be logged to this destination. + ===== Available options for the recommended directive format ===== + + logformat=name Names log line format (either built-in or + defined by a logformat directive). Defaults + to 'squid'. + + buffer-size=64KB Defines approximate buffering limit for log + records (see buffered_logs). Squid should not + keep more than the specified size and, hence, + should flush records before the buffer becomes + full to avoid overflows under normal + conditions (the exact flushing algorithm is + module-dependent though). The on-error option + controls overflow handling. + + on-error=die|drop Defines action on unrecoverable errors. The + 'drop' action ignores (i.e., does not log) + affected log records. The default 'die' action + kills the affected worker. The drop action + support has not been tested for modules other + than tcp. + ===== Modules Currently available ===== none Do not log any requests matching these ACL. @@ -3732,6 +3763,7 @@ Place Format: //host:port tcp To send each log line as text data to a TCP receiver. + Lines may be accumulated before sending (see buffered_logs). Place: The destination host name or IP and port. Place Format: //host:port @@ -4041,11 +4073,18 @@ DEFAULT: off LOC: Config.onoff.buffered_logs DOC_START - cache.log log file is written with stdio functions, and as such - it can be buffered or unbuffered. By default it will be unbuffered. - Buffering it can speed up the writing slightly (though you are - unlikely to need to worry unless you run with tons of debugging - enabled in which case performance will suffer badly anyway..). + Whether to write/send access_log records ASAP or accumulate them and + then write/send them in larger chunks. Buffering may improve + performance because it decreases the number of I/Os. However, + buffering increases the delay before log records become available to + the final recipient (e.g., a disk file or logging daemon) and, + hence, increases the risk of log records loss. + + Note that even when buffered_logs are off, Squid may have to buffer + records if it cannot write/send them immediately due to pending I/Os + (e.g., the I/O writing the previous log record) or connectivity loss. + + Currently honored by 'daemon' and 'tcp' access_log modules only. DOC_END NAME: netdb_filename === modified file 'src/log/CustomLog.h' --- src/log/CustomLog.h 2012-10-04 00:23:44 +0000 +++ src/log/CustomLog.h 2013-04-12 00:15:02 +0000 @@ -48,6 +48,10 @@ Logfile *logfile; CustomLog *next; Log::Format::log_type type; + /// how much to buffer before dropping or dying (access_log buffer-size) + size_t bufferSize; + /// whether unrecoverable errors (e.g., dropping a log record) kill worker + bool fatal; }; #endif /* SQUID_CUSTOMLOG_H_ */ === modified file 'src/log/File.cc' --- src/log/File.cc 2012-09-01 14:38:36 +0000 +++ src/log/File.cc 2013-04-18 21:43:22 +0000 @@ -37,7 +37,7 @@ #include "log/ModStdio.h" #include "log/ModSyslog.h" #include "log/ModUdp.h" -#include "log/ModTcp.h" +#include "log/TcpLogger.h" CBDATA_TYPE(Logfile); @@ -62,7 +62,7 @@ ret = logfile_mod_daemon_open(lf, patharg, bufsz, fatal_flag); } else if (strncmp(path, "tcp:", 4) == 0) { patharg = path + 4; - ret = logfile_mod_tcp_open(lf, patharg, bufsz, fatal_flag); + ret = Log::TcpLogger::Open(lf, patharg, bufsz, fatal_flag); } else if (strncmp(path, "udp:", 4) == 0) { patharg = path + 4; ret = logfile_mod_udp_open(lf, patharg, bufsz, fatal_flag); @@ -72,7 +72,7 @@ ret = logfile_mod_syslog_open(lf, patharg, bufsz, fatal_flag); #endif } else { - debugs(50, DBG_IMPORTANT, "WARNING: log parameters now start with a module name. Use 'stdio:" << patharg << "'"); + debugs(50, DBG_IMPORTANT, "WARNING: log name now starts with a module name. Use 'stdio:" << patharg << "'"); snprintf(lf->path, MAXPATHLEN, "stdio:%s", patharg); ret = logfile_mod_stdio_open(lf, patharg, bufsz, fatal_flag); } === modified file 'src/log/Makefile.am' --- src/log/Makefile.am 2012-09-06 12:47:15 +0000 +++ src/log/Makefile.am 2013-04-18 21:43:22 +0000 @@ -24,10 +24,10 @@ ModStdio.h \ ModSyslog.cc \ ModSyslog.h \ - ModTcp.cc \ - ModTcp.h \ ModUdp.cc \ ModUdp.h \ CustomLog.h \ - CustomLog.cc + CustomLog.cc \ + TcpLogger.cc \ + TcpLogger.h === removed file 'src/log/ModTcp.cc' --- src/log/ModTcp.cc 2012-09-23 09:04:21 +0000 +++ src/log/ModTcp.cc 1970-01-01 00:00:00 +0000 @@ -1,237 +0,0 @@ -/* - * DEBUG: section 50 Log file handling - * AUTHOR: Dhaval Varia - * Developed based on ModUdp.* by Adrian Chadd - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "comm.h" -#include "comm/Connection.h" -#include "disk.h" -#include "fd.h" -#include "log/File.h" -#include "log/ModTcp.h" -#include "Parsing.h" -#include "SquidConfig.h" - -#if HAVE_ERRNO_H -#include -#endif -/* - * This logfile TCP module is mostly inspired by a patch by Tim Starling - * from Wikimedia. - * - * It doesn't do any TCP buffering - it'd be quite a bit of work for - * something which the kernel could be doing for you! - */ - -typedef struct { - int fd; - char *buf; - size_t bufsz; - int offset; -} l_tcp_t; - -static void -logfile_mod_tcp_write(Logfile * lf, const char *buf, size_t len) -{ - l_tcp_t *ll = (l_tcp_t *) lf->data; - ssize_t s; - s = write(ll->fd, (char const *) buf, len); - - fd_bytes(ll->fd, s, FD_WRITE); -#if 0 - if (s < 0) { - debugs(1, DBG_IMPORTANT, "logfile (tcp): got errno (" << errno << "):" << xstrerror()); - } - if (s != len) { - debugs(1, DBG_IMPORTANT, "logfile (tcp): len=" << len << ", wrote=" << s); - } -#endif - - /* We don't worry about network errors for now */ -} - -static void -logfile_mod_tcp_flush(Logfile * lf) -{ - l_tcp_t *ll = (l_tcp_t *) lf->data; - if (0 == ll->offset) - return; - logfile_mod_tcp_write(lf, ll->buf, (size_t) ll->offset); - ll->offset = 0; -} - -static void -logfile_mod_tcp_writeline(Logfile * lf, const char *buf, size_t len) -{ - l_tcp_t *ll = (l_tcp_t *) lf->data; - - if (0 == ll->bufsz) { - /* buffering disabled */ - logfile_mod_tcp_write(lf, buf, len); - return; - } - if (ll->offset > 0 && (ll->offset + len + 4) > ll->bufsz) - logfile_mod_tcp_flush(lf); - - if (len > ll->bufsz) { - /* too big to fit in buffer */ - logfile_mod_tcp_write(lf, buf, len); - return; - } - /* buffer it */ - memcpy(ll->buf + ll->offset, buf, len); - - ll->offset += len; - - assert(ll->offset >= 0); - - assert((size_t) ll->offset <= ll->bufsz); -} - -static void -logfile_mod_tcp_linestart(Logfile * lf) -{ -} - -static void -logfile_mod_tcp_lineend(Logfile * lf) -{ - logfile_mod_tcp_flush(lf); -} - -static void -logfile_mod_tcp_rotate(Logfile * lf) -{ - return; -} - -static void -logfile_mod_tcp_close(Logfile * lf) -{ - l_tcp_t *ll = (l_tcp_t *) lf->data; - lf->f_flush(lf); - - if (ll->fd >= 0) - file_close(ll->fd); - - if (ll->buf) - xfree(ll->buf); - - xfree(lf->data); - lf->data = NULL; -} - -/* - * This code expects the path to be //host:port - */ -int -logfile_mod_tcp_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag) -{ - debugs(5, 3, "Tcp Open called"); - Ip::Address addr; - - char *strAddr; - - lf->f_close = logfile_mod_tcp_close; - lf->f_linewrite = logfile_mod_tcp_writeline; - lf->f_linestart = logfile_mod_tcp_linestart; - lf->f_lineend = logfile_mod_tcp_lineend; - lf->f_flush = logfile_mod_tcp_flush; - lf->f_rotate = logfile_mod_tcp_rotate; - - l_tcp_t *ll = static_cast(xcalloc(1, sizeof(*ll))); - lf->data = ll; - - if (strncmp(path, "//", 2) == 0) { - path += 2; - } - strAddr = xstrdup(path); - - if (!GetHostWithPort(strAddr, &addr)) { - if (lf->flags.fatal) { - fatalf("Invalid TCP logging address '%s'\n", lf->path); - } else { - debugs(50, DBG_IMPORTANT, "Invalid TCP logging address '" << lf->path << "'"); - safe_free(strAddr); - return FALSE; - } - } - - safe_free(strAddr); - - Ip::Address any_addr; - any_addr.SetAnyAddr(); - - // require the sending TCP port to be of the right family for the destination address. - if (addr.IsIPv4()) - any_addr.SetIPv4(); - - ll->fd = comm_open(SOCK_STREAM, IPPROTO_TCP, any_addr, COMM_NONBLOCKING, "TCP log socket"); - if (ll->fd < 0) { - if (lf->flags.fatal) { - fatalf("Unable to open TCP socket for logging\n"); - } else { - debugs(50, DBG_IMPORTANT, "Unable to open TCP socket for logging"); - return FALSE; - } - } else if (!comm_connect_addr(ll->fd, &addr)) { - if (lf->flags.fatal) { - fatalf("Unable to connect to %s for TCP log: %s\n", lf->path, xstrerror()); - } else { - debugs(50, DBG_IMPORTANT, "Unable to connect to " << lf->path << " for TCP log: " << xstrerror()); - return FALSE; - } - } - if (ll->fd == -1) { - if (ENOENT == errno && fatal_flag) { - fatalf("Cannot open '%s' because\n" - "\tthe parent directory does not exist.\n" - "\tPlease create the directory.\n", path); - } else if (EACCES == errno && fatal_flag) { - fatalf("Cannot open '%s' for writing.\n" - "\tThe parent directory must be writeable by the\n" - "\tuser '%s', which is the cache_effective_user\n" - "\tset in squid.conf.", path, Config.effectiveUser); - } else { - debugs(50, DBG_IMPORTANT, "logfileOpen (TCP): " << lf->path << ": " << xstrerror()); - return 0; - } - } - - bufsz = 65536; - if (bufsz > 0) { - ll->buf = static_cast(xmalloc(bufsz)); - ll->bufsz = bufsz; - } - - return 1; -} === removed file 'src/log/ModTcp.h' --- src/log/ModTcp.h 2012-10-04 09:14:06 +0000 +++ src/log/ModTcp.h 1970-01-01 00:00:00 +0000 @@ -1,40 +0,0 @@ -/* - * DEBUG: section 50 Log file handling - * AUTHOR: Dhaval Varia - * Developed based on ModUdp.* by Adrian Chadd - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ -#ifndef _SQUID_SRC_LOG_MODTCP_H -#define _SQUID_SRC_LOG_MODTCP_H - -class Logfile; - -int logfile_mod_tcp_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag); - -#endif /* _SQUID_SRC_LOG_MODTCP_H */ === added file 'src/log/TcpLogger.cc' --- src/log/TcpLogger.cc 1970-01-01 00:00:00 +0000 +++ src/log/TcpLogger.cc 2013-04-18 21:43:22 +0000 @@ -0,0 +1,471 @@ +#include "squid.h" +#include "comm.h" +#include "comm/ConnOpener.h" +#include "comm/Connection.h" +#include "comm/Loops.h" +#include "comm/Write.h" +#include "fde.h" +#include "globals.h" // for shutting_down +#include "log/CustomLog.h" +#include "log/File.h" +#include "log/TcpLogger.h" +#include "MemBlob.h" +#include "Parsing.h" +#include "SquidConfig.h" +#include "SquidTime.h" + +// a single I/O buffer should be large enough to store any access.log record +const size_t Log::TcpLogger::IoBufSize = 2*MAX_URL; +// We need at least two buffers because when we write the first buffer, +// we have to use the second buffer to accumulate new entries. +const size_t Log::TcpLogger::BufferCapacityMin = 2*Log::TcpLogger::IoBufSize; + +#define MY_DEBUG_SECTION 50 /* Log file handling */ + + +CBDATA_NAMESPACED_CLASS_INIT(Log, TcpLogger); + +Log::TcpLogger::TcpLogger(size_t bufCap, bool dieOnErr, Ip::Address them): + AsyncJob("TcpLogger"), + dieOnError(dieOnErr), + bufferCapacity(bufCap), + bufferedSize(0), + flushDebt(0), + quitOnEmpty(false), + reconnectScheduled(false), + writeScheduled(false), + conn(NULL), + remote(them), + connectFailures(0), + drops(0) +{ + if (bufferCapacity < BufferCapacityMin) { + debugs(MY_DEBUG_SECTION, DBG_IMPORTANT, + "WARNING: tcp:" << remote << " logger configured buffer " << + "size " << bufferCapacity << " is smaller than the " << + BufferCapacityMin << "-byte" << " minimum. " << + "Using the minimum instead."); + bufferCapacity = BufferCapacityMin; + } +} + +Log::TcpLogger::~TcpLogger() +{ + // make sure Comm::Write does not have our buffer pointer + assert(!writeScheduled); +} + +void +Log::TcpLogger::start() +{ + connect(); +} + +bool +Log::TcpLogger::doneAll() const +{ + debugs(MY_DEBUG_SECTION, 5, "quitOnEmpty: " << quitOnEmpty << + " buffered: " << bufferedSize << + " conn: " << conn << ' ' << connectFailures); + + // we do not quit unless we are told that we may + if (!quitOnEmpty) + return false; + + /* We were asked to quit after we are done writing buffers. Are we done? */ + + // If we have records but are failing to connect, quit. Otherwise, we may + // be trying to connect forever due to a [since fixed] misconfiguration! + const bool failingToConnect = !conn && connectFailures; + if (bufferedSize && !failingToConnect) + return false; + + return AsyncJob::doneAll(); +} + +void +Log::TcpLogger::swanSong() +{ + disconnect(); // optional: refcounting should close/delete conn eventually + AsyncJob::swanSong(); +} + +void +Log::TcpLogger::endGracefully() +{ + // job call protection must end our job if we are done logging current bufs + assert(inCall != NULL); + quitOnEmpty = true; + flush(); +} + +void +Log::TcpLogger::flush() +{ + flushDebt = bufferedSize; + writeIfNeeded(); +} + +void +Log::TcpLogger::logRecord(const char *buf, const size_t len) +{ + appendRecord(buf, len); + writeIfNeeded(); +} + +/// starts writing if and only if it is time to write accumulated records +void +Log::TcpLogger::writeIfNeeded() +{ + // write if an earlier flush command forces us to write or + // if we have filled at least one I/O buffer + if (flushDebt > 0 || buffers.size() > 1) + writeIfPossible(); +} + +/// starts writing if possible +void Log::TcpLogger::writeIfPossible() +{ + debugs(MY_DEBUG_SECTION, 7, "guards: " << (!writeScheduled) << + (bufferedSize > 0) << (conn != NULL) << + (conn != NULL && !fd_table[conn->fd].closing()) << " buffered: " << + bufferedSize << '/' << buffers.size()); + + // XXX: Squid shutdown sequence starts closing our connection before + // calling LogfileClose, leading to loss of log records during shutdown. + if (!writeScheduled && bufferedSize > 0 && conn != NULL && + !fd_table[conn->fd].closing()) { + debugs(MY_DEBUG_SECTION, 5, "writing first buffer"); + + typedef CommCbMemFunT WriteDialer; + AsyncCall::Pointer callback = JobCallback(MY_DEBUG_SECTION, 5, WriteDialer, this, Log::TcpLogger::writeDone); + const MemBlob::Pointer &buffer = buffers.front(); + Comm::Write(conn, buffer->mem, buffer->size, callback, NULL); + writeScheduled = true; + } +} + +/// whether len more bytes can be buffered +bool +Log::TcpLogger::canFit(const size_t len) const +{ + // TODO: limit reporting frequency in addition to reporting only changes + + if (bufferedSize+len <= bufferCapacity) { + if (drops) { + // We can get here if a shorter record accidentally fits after we + // started dropping records. When that happens, the following + // DBG_IMPORTANT message will mislead admin into thinking that + // the problem was resolved (for a brief period of time, until + // another record comes in and overflows the buffer). It is + // difficult to prevent this without also creating the opposite + // problem: A huge record that does not fit and is dropped blocks + // subsequent regular records from being buffered until we write. + debugs(MY_DEBUG_SECTION, DBG_IMPORTANT, "tcp:" << remote << + " logger stops dropping records after " << drops << " drops" << + "; current buffer use: " << (bufferedSize+len) << + " out of " << bufferCapacity << " bytes"); + } + return true; + } + + if (!drops || dieOnError) { + debugs(MY_DEBUG_SECTION, + dieOnError ? DBG_CRITICAL : DBG_IMPORTANT, + "tcp:" << remote << " logger " << bufferCapacity << "-byte " << + "buffer overflowed; cannot fit " << + (bufferedSize+len-bufferCapacity) << " bytes"); + } + + if (dieOnError) + fatal("tcp logger buffer overflowed"); + + if (!drops) { + debugs(MY_DEBUG_SECTION, DBG_IMPORTANT, "tcp:" << remote << + " logger starts dropping records."); + } + + return false; +} + +/// buffer a record that might exceed IoBufSize +void +Log::TcpLogger::appendRecord(const char *record, const size_t len) +{ + // they should not happen, but to be safe, let's protect drop start/stop + // monitoring algorithm from empty records (which can never be dropped) + if (!len) + return; + + if (!canFit(len)) { + ++drops; + return; + } + + drops = 0; + // append without spliting buf, unless it exceeds IoBufSize + for (size_t off = 0; off < len; off += IoBufSize) + appendChunk(record + off, min(len - off, IoBufSize)); +} + +/// buffer a record chunk without splitting it across buffers +void +Log::TcpLogger::appendChunk(const char *chunk, const size_t len) +{ + Must(len <= IoBufSize); + // add a buffer if there is not one that can accomodate len bytes + bool addBuffer = buffers.empty() || + (buffers.back()->size+len > IoBufSize); + // also add a buffer if there is only one and that one is being written + addBuffer = addBuffer || (writeScheduled && buffers.size() == 1); + + if (addBuffer) { + buffers.push_back(new MemBlob(IoBufSize)); + debugs(MY_DEBUG_SECTION, 7, "added buffer #" << buffers.size()); + } + + Must(!buffers.empty()); + buffers.back()->append(chunk, len); + bufferedSize += len; +} + +/// starts [re]connecting to the remote logger +void +Log::TcpLogger::connect() +{ + if (shutting_down) + return; + + debugs(MY_DEBUG_SECTION, 3, "connecting"); + Must(!conn); + + Comm::ConnectionPointer futureConn = new Comm::Connection; + futureConn->remote = remote; + futureConn->local.SetAnyAddr(); + if (futureConn->remote.IsIPv4()) + futureConn->local.SetIPv4(); + + typedef CommCbMemFunT Dialer; + AsyncCall::Pointer call = JobCallback(MY_DEBUG_SECTION, 5, Dialer, this, Log::TcpLogger::connectDone); + AsyncJob::Start(new Comm::ConnOpener(futureConn, call, 2)); +} + +/// Comm::ConnOpener callback +void +Log::TcpLogger::connectDone(const CommConnectCbParams ¶ms) +{ + if (params.flag != COMM_OK) { + const double delay = 0.5; // seconds + if (connectFailures++ % 100 == 0) { + debugs(MY_DEBUG_SECTION, DBG_IMPORTANT, "tcp:" << remote << + " logger connection attempt #" << connectFailures << + " failed. Will keep trying every " << delay << " seconds."); + } + + if (!reconnectScheduled) { + reconnectScheduled = true; + eventAdd("Log::TcpLogger::DelayedReconnect", + Log::TcpLogger::DelayedReconnect, + new Pointer(this), 0.5, 0, false); + } + } else { + if (connectFailures > 0) { + debugs(MY_DEBUG_SECTION, DBG_IMPORTANT, "tcp:" << remote << + " logger connectivity restored after " << + (connectFailures+1) << " attempts."); + connectFailures = 0; + } + + Must(!conn); + conn = params.conn; + + Must(!closer); + typedef CommCbMemFunT Closer; + closer = JobCallback(MY_DEBUG_SECTION, 4, Closer, this, Log::TcpLogger::handleClosure); + comm_add_close_handler(conn->fd, closer); + + writeIfNeeded(); + } +} + +// XXX: Needed until eventAdd() starts accepting Async calls directly. +/// Log::TcpLogger::delayedReconnect() wrapper. +void +Log::TcpLogger::DelayedReconnect(void *data) +{ + Pointer *ptr = static_cast(data); + assert(ptr); + if (TcpLogger *logger = ptr->valid()) { + // Get back inside AsyncJob protections by scheduling another call. + typedef NullaryMemFunT Dialer; + AsyncCall::Pointer call = JobCallback(MY_DEBUG_SECTION, 5, Dialer, + logger, + Log::TcpLogger::delayedReconnect); + ScheduleCallHere(call); + } + delete ptr; +} + +/// "sleep a little before trying to connect again" event callback +void +Log::TcpLogger::delayedReconnect() { + Must(reconnectScheduled); + Must(!conn); + reconnectScheduled = false; + connect(); +} + +/// Comm::Write callback +void +Log::TcpLogger::writeDone(const CommIoCbParams &io) +{ + writeScheduled = false; + if (io.flag == COMM_ERR_CLOSING) { + debugs(MY_DEBUG_SECTION, 7, "closing"); + // do nothing here -- our comm_close_handler will be called to clean up + } else + if (io.flag != COMM_OK) { + debugs(MY_DEBUG_SECTION, 2, "write failure: " << xstrerr(io.xerrno)); + // keep the first buffer (the one we failed to write) + disconnect(); + connect(); + } else { + debugs(MY_DEBUG_SECTION, 5, "write successful"); + + Must(!buffers.empty()); // we had a buffer to write + const MemBlob::Pointer &written = buffers.front(); + const size_t writtenSize = static_cast(written->size); + // and we wrote the whole buffer + Must(io.size >= 0 && writtenSize >= 0 && io.size == writtenSize); + Must(bufferedSize >= writtenSize); + bufferedSize -= writtenSize; + + buffers.pop_front(); + + if (flushDebt > io.size) + flushDebt -= io.size; + else + flushDebt = 0; // wrote everything we owed (or more) + + writeIfNeeded(); + } +} + +/// This is our comm_close_handler. It is called when some external force +/// (e.g., reconfigure or shutdown) is closing the connection (rather than us). +void +Log::TcpLogger::handleClosure(const CommCloseCbParams &io) +{ + assert(inCall != NULL); + closer = NULL; + conn = NULL; + // in all current use cases, we should not try to reconnect + mustStop("Log::TcpLogger::handleClosure"); +} + +/// close our connection now, without flushing +void +Log::TcpLogger::disconnect() +{ + if (conn != NULL) { + if (closer != NULL) { + comm_remove_close_handler(conn->fd, closer); + closer = NULL; + } + conn->close(); + conn = NULL; + } +} + +/// Converts Logfile into a pointer to a valid TcpLogger job or, +/// if the logger job has quit, into a nill pointer +Log::TcpLogger * +Log::TcpLogger::StillLogging(Logfile *lf) +{ + if (Pointer *pptr = static_cast(lf->data)) + return pptr->get(); // may be nil + return NULL; +} + +void +Log::TcpLogger::Flush(Logfile * lf) +{ + if (TcpLogger *logger = StillLogging(lf)) + logger->flush(); +} + +void +Log::TcpLogger::WriteLine(Logfile * lf, const char *buf, size_t len) +{ + if (TcpLogger *logger = StillLogging(lf)) + logger->logRecord(buf, len); +} + +void +Log::TcpLogger::StartLine(Logfile * lf) +{ +} + +void +Log::TcpLogger::EndLine(Logfile * lf) +{ + if (!Config.onoff.buffered_logs) + Flush(lf); +} + +void +Log::TcpLogger::Rotate(Logfile * lf) +{ +} + +void +Log::TcpLogger::Close(Logfile * lf) +{ + if (TcpLogger *logger = StillLogging(lf)) { + debugs(50, 3, "Closing " << logger); + typedef NullaryMemFunT Dialer; + Dialer dialer(logger, &Log::TcpLogger::endGracefully); + AsyncCall::Pointer call = asyncCall(50, 3, "Log::TcpLogger::endGracefully", dialer); + ScheduleCallHere(call); + } + delete static_cast(lf->data); + lf->data = NULL; +} + +/* + * This code expects the path to be //host:port + */ +int +Log::TcpLogger::Open(Logfile * lf, const char *path, size_t bufsz, int fatalFlag) +{ + assert(!StillLogging(lf)); + debugs(5, 3, "Tcp Open called"); + + Ip::Address addr; + + if (strncmp(path, "//", 2) == 0) + path += 2; + char *strAddr = xstrdup(path); + if (!GetHostWithPort(strAddr, &addr)) { + if (lf->flags.fatal) { + fatalf("Invalid TCP logging address '%s'\n", lf->path); + } else { + debugs(50, DBG_IMPORTANT, "Invalid TCP logging address '" << lf->path << "'"); + safe_free(strAddr); + return FALSE; + } + } + safe_free(strAddr); + + TcpLogger *logger = new TcpLogger(bufsz, fatalFlag, addr); + lf->data = new Pointer(logger); + lf->f_close = &Close; + lf->f_linewrite = &WriteLine; + lf->f_linestart = &StartLine; + lf->f_lineend = &EndLine; + lf->f_flush = &Flush; + lf->f_rotate = &Rotate; + AsyncJob::Start(logger); + + return 1; +} === added file 'src/log/TcpLogger.h' --- src/log/TcpLogger.h 1970-01-01 00:00:00 +0000 +++ src/log/TcpLogger.h 2013-04-18 21:43:22 +0000 @@ -0,0 +1,106 @@ +#ifndef _SQUID_SRC_LOG_TCPLOGGER_H +#define _SQUID_SRC_LOG_TCPLOGGER_H + +#include "squid.h" +#include "base/AsyncJob.h" +#include "ip/Address.h" + +#ifdef HAVE_LIST +#include +#endif + +class MemBlob; +typedef RefCount MemBlobPointer; + +namespace Log { + +/** + * Sends log records to a remote TCP logger at the configured IP:port address. + * Handles loss of connectivity, record buffering, and buffer overflows. + */ +class TcpLogger : public AsyncJob +{ +public: + typedef CbcPointer Pointer; + + // Logfile API. XXX: The only method general logging code needs to know. + static int Open(Logfile *lf, const char *path, size_t bufSz, int fatalFlag); + +protected: + TcpLogger(size_t, bool, Ip::Address); + virtual ~TcpLogger(); + + /// Called when Squid is reconfiguring (or exiting) to give us a chance to + /// flush remaining buffers and end this job w/o loss of data. No new log + /// records are expected. Must be used as (or inside) an async job call and + /// will result in [eventual] job termination. + void endGracefully(); + + /// buffers record and possibly writes it to the remote logger + void logRecord(const char *buf, size_t len); + /// write all currently buffered records ASAP + void flush(); + + /* AsyncJob API */ + virtual void start(); + virtual bool doneAll() const; + virtual void swanSong(); + +private: + /* Logfile API. Map c-style Logfile calls to TcpLogger method calls. */ + static void Flush(Logfile *lf); + static void WriteLine(Logfile *lf, const char *buf, size_t len); + static void StartLine(Logfile *lf); + static void EndLine(Logfile *lf); + static void Rotate(Logfile *lf); + static void Close(Logfile *lf); + + static TcpLogger *StillLogging(Logfile *lf); + + static void DelayedReconnect(void *data); + void delayedReconnect(); + + bool canFit(const size_t len) const; + void appendRecord(const char *buf, size_t len); + void appendChunk(const char *chunk, const size_t len); + void writeIfNeeded(); + void writeIfPossible(); + void connect(); + void disconnect(); + + /* comm callbacks */ + void connectDone(const CommConnectCbParams &conn); + void writeDone(const CommIoCbParams &io); + void handleClosure(const CommCloseCbParams &io); + + static const size_t IoBufSize; ///< fixed I/O buffer size + static const size_t BufferCapacityMin; ///< minimum bufferCapacity value + + /// Whether this job must kill Squid on the first unrecoverable error. + /// Note that we may be able to recover from a failure to connect, but we + /// cannot recover from forgetting (dropping) a record while connecting. + bool dieOnError; + + std::list buffers; ///< I/O buffers + size_t bufferCapacity; ///< bufferedSize limit + size_t bufferedSize; ///< number of log record bytes stored in RAM now + size_t flushDebt; ///< how many record bytes we still need to write ASAP + + bool quitOnEmpty; ///< whether this job should quit when buffers are empty + bool reconnectScheduled; ///< we are sleeping before the next connection attempt + bool writeScheduled; ///< we are waiting for the latest write() results + + Comm::ConnectionPointer conn; ///< opened connection to the remote logger + Ip::Address remote; ///< where the remote logger expects our records + AsyncCall::Pointer closer; ///< handles unpexted/external conn closures + + uint64_t connectFailures; ///< number of sequential connection failures + uint64_t drops; ///< number of records dropped during the current outage + + CBDATA_CLASS2(TcpLogger); +}; + +} // namespace Log + + +#endif /* _SQUID_SRC_LOG_TCPLOGGER_H */ === modified file 'src/log/access_log.cc' --- src/log/access_log.cc 2013-03-18 04:55:51 +0000 +++ src/log/access_log.cc 2013-04-05 23:50:25 +0000 @@ -320,7 +320,7 @@ if (log->type == Log::Format::CLF_NONE) continue; - log->logfile = logfileOpen(log->filename, MAX_URL << 2, 1); + log->logfile = logfileOpen(log->filename, log->bufferSize, log->fatal); LogfileStatus = LOG_ENABLE; # Begin bundle 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 qadWUUmYTAFoQxMsd8+6Of/i7kinChIGTsejQA==