Squid Web Cache master
Loading...
Searching...
No Matches
access_log.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9/* DEBUG: section 46 Access Log */
10
11#include "squid.h"
12#include "AccessLogEntry.h"
13#include "acl/Checklist.h"
14#include "sbuf/Algorithms.h"
15#if USE_ADAPTATION
16#include "adaptation/Config.h"
17#endif
18#include "base/PackableStream.h"
19#include "CachePeer.h"
20#include "error/Detail.h"
21#include "errorpage.h"
22#include "format/Token.h"
23#include "globals.h"
24#include "hier_code.h"
25#include "HttpReply.h"
26#include "HttpRequest.h"
27#include "log/access_log.h"
28#include "log/Config.h"
29#include "log/CustomLog.h"
30#include "log/File.h"
31#include "log/Formats.h"
32#include "MemBuf.h"
33#include "mgr/Registration.h"
34#include "rfc1738.h"
35#include "sbuf/SBuf.h"
36#include "SquidConfig.h"
37#include "Store.h"
38
39#if USE_SQUID_EUI
40#include "eui/Eui48.h"
41#include "eui/Eui64.h"
42#endif
43
44#include <unordered_map>
45
46#if USE_FORW_VIA_DB
47
48using HeaderValueCountsElement = std::pair<const SBuf, uint64_t>;
50using HeaderValueCounts = std::unordered_map<SBuf, uint64_t, std::hash<SBuf>, std::equal_to<SBuf>, PoolingAllocator<HeaderValueCountsElement> >;
51
53static HeaderValueCounts TheViaCounts;
55static HeaderValueCounts TheForwardedCounts;
56
57static OBJH fvdbDumpVia;
58static OBJH fvdbDumpForwarded;
59static void fvdbClear(void);
60static void fvdbRegisterWithCacheManager();
61#endif
62
64
65void
67{
68
69 if (al->url.isEmpty())
70 al->url = Format::Dash;
71
72 if (!al->http.content_type || *al->http.content_type == '\0')
74
75 if (al->hier.host[0] == '\0')
77
78 for (; log; log = log->next) {
79 if (log->aclList && checklist && !checklist->fastCheck(log->aclList).allowed())
80 continue;
81
82 // The special-case "none" type has no logfile object set
83 if (log->type == Log::Format::CLF_NONE)
84 return;
85
86 if (log->logfile) {
87 logfileLineStart(log->logfile);
88
89 switch (log->type) {
90
92 Log::Format::SquidNative(al, log->logfile);
93 break;
94
96 Log::Format::HttpdCombined(al, log->logfile);
97 break;
98
100 Log::Format::HttpdCommon(al, log->logfile);
101 break;
102
104 Log::Format::SquidReferer(al, log->logfile);
105 break;
106
108 Log::Format::SquidUserAgent(al, log->logfile);
109 break;
110
113 break;
114
115#if ICAP_CLIENT
117 Log::Format::SquidIcap(al, log->logfile);
118 break;
119#endif
120
121 default:
122 fatalf("Unknown log format %d\n", log->type);
123 break;
124 }
125
126 logfileLineEnd(log->logfile);
127 }
128
129 // NP: WTF? if _any_ log line has no checklist ignore the following ones?
130 if (!checklist)
131 break;
132 }
133}
134
135void
137{
139 return;
140
141 accessLogLogTo(Config.Log.accesslogs, al, checklist);
142}
143
144void
146{
147 CustomLog *log;
148#if USE_FORW_VIA_DB
149
150 fvdbClear();
151#endif
152
153 for (log = Config.Log.accesslogs; log; log = log->next) {
154 log->rotate();
155 }
156}
157
158void
160{
161 CustomLog *log;
162
163 for (log = Config.Log.accesslogs; log; log = log->next) {
164 if (log->logfile) {
165 logfileClose(log->logfile);
166 log->logfile = nullptr;
167 }
168 }
169}
170
172 code(HIER_NONE),
173 cd_lookup(LOOKUP_NONE),
174 n_choices(0),
175 n_ichoices(0),
176 peer_reply_status(Http::scNone),
177 tcpServer(nullptr),
178 bodyBytesRead(-1)
179{
180 memset(host, '\0', SQUIDHOSTNAMELEN);
181 memset(cd_host, '\0', SQUIDHOSTNAMELEN);
182
183 peer_select_start.tv_sec =0;
184 peer_select_start.tv_usec =0;
185
186 store_complete_stop.tv_sec =0;
187 store_complete_stop.tv_usec =0;
188
190}
191
192void
194{
196
198 if (tcpServer == nullptr) {
199 code = HIER_NONE;
200 xstrncpy(host, requestedHost, sizeof(host));
201 } else {
203
204 if (tcpServer->getPeer()) {
205 // went to peer, log peer host name
206 xstrncpy(host, tcpServer->getPeer()->name, sizeof(host));
207 } else {
208 xstrncpy(host, requestedHost, sizeof(host));
209 }
210 }
211}
212
214void
216{
217 peer_last_read_.tv_sec = 0;
218 peer_last_read_.tv_usec = 0;
219
220 peer_last_write_.tv_sec = 0;
221 peer_last_write_.tv_usec = 0;
222
223 bodyBytesRead = -1;
224}
225
226void
231
232void
237
238bool
239HierarchyLogEntry::peerResponseTime(struct timeval &responseTime)
240{
241 // no I/O whatsoever
242 if (peer_last_write_.tv_sec <= 0 && peer_last_read_.tv_sec <= 0)
243 return false;
244
245 // accommodate read without (completed) write
246 const auto last_write = peer_last_write_.tv_sec > 0 ?
248
249 // accommodate write without (completed) read
250 const auto last_read = peer_last_read_.tv_sec > 0 ?
252
253 tvSub(responseTime, last_write, last_read);
254 // The peer response time (%<pt) stopwatch is currently defined to start
255 // when we wrote the entire request. Thus, if we wrote something after the
256 // last read, report zero peer response time.
257 if (responseTime.tv_sec < 0) {
258 responseTime.tv_sec = 0;
259 responseTime.tv_usec = 0;
260 }
261
262 return true;
263}
264
265static void
267{
268#if USE_FORW_VIA_DB
269 fvdbRegisterWithCacheManager();
270#endif
271}
272
273void
275{
276 CustomLog *log;
277
279
280#if USE_ADAPTATION
282#endif
283#if ICAP_CLIENT
285#endif
286
287 for (log = Config.Log.accesslogs; log; log = log->next) {
288 if (log->type == Log::Format::CLF_NONE)
289 continue;
290
291 log->logfile = logfileOpen(log->filename, log->bufferSize, log->fatal);
292
294
295#if USE_ADAPTATION
296 for (Format::Token * curr_token = (log->logFormat?log->logFormat->format:nullptr); curr_token; curr_token = curr_token->next) {
297 if (curr_token->type == Format::LFT_ADAPTATION_SUM_XACT_TIMES ||
298 curr_token->type == Format::LFT_ADAPTATION_ALL_XACT_TIMES ||
299 curr_token->type == Format::LFT_ADAPTATION_LAST_HEADER ||
300 curr_token->type == Format::LFT_ADAPTATION_LAST_HEADER_ELEM ||
301 curr_token->type == Format::LFT_ADAPTATION_LAST_ALL_HEADERS||
302 (curr_token->type == Format::LFT_NOTE && !Adaptation::Config::metaHeaders().empty())) {
304 }
305#if ICAP_CLIENT
306 if (curr_token->type == Format::LFT_ICAP_TOTAL_TIME) {
308 }
309#endif
310 }
311#endif
312 }
313}
314
315#if USE_FORW_VIA_DB
316
317static void
318fvdbRegisterWithCacheManager(void)
319{
320 Mgr::RegisterAction("via_headers", "Via Request Headers", fvdbDumpVia, 0, 1);
321 Mgr::RegisterAction("forw_headers", "X-Forwarded-For Request Headers",
322 fvdbDumpForwarded, 0, 1);
323}
324
325void
326fvdbCountVia(const SBuf &headerValue)
327{
328 ++TheViaCounts[headerValue];
329}
330
331void
332fvdbCountForwarded(const SBuf &key)
333{
334 ++TheForwardedCounts[key];
335}
336
337static void
338fvdbDumpCounts(StoreEntry &e, const HeaderValueCounts &counts)
339{
340 PackableStream os(e);
341 for (const auto &i : counts)
342 os << std::setw(9) << i.second << ' ' << i.first << "\n";
343}
344
345static void
346fvdbDumpVia(StoreEntry * e)
347{
348 assert(e);
349 fvdbDumpCounts(*e, TheViaCounts);
350}
351
352static void
353fvdbDumpForwarded(StoreEntry * e)
354{
355 assert(e);
356 fvdbDumpCounts(*e, TheForwardedCounts);
357}
358
359static void
360fvdbClear(void)
361{
362 TheViaCounts.clear();
363 TheForwardedCounts.clear();
364}
365
366#endif
367
class SquidConfig Config
void accessLogInit(void)
void accessLogLog(const AccessLogEntryPointer &al, ACLChecklist *checklist)
void accessLogClose(void)
void accessLogLogTo(CustomLog *log, const AccessLogEntryPointer &al, ACLChecklist *checklist)
Definition access_log.cc:66
static void accessLogRegisterWithCacheManager(void)
int LogfileStatus
Definition access_log.cc:63
void accessLogRotate(void)
void fvdbCountVia(const SBuf &)
void fvdbCountForwarded(const SBuf &)
count occurrences of the given X-Forwarded-For header value
void log(char *format,...)
#define assert(EX)
Definition assert.h:17
static char server[MAXLINE]
Acl::Answer const & fastCheck()
Definition Checklist.cc:298
HierarchyLogEntry hier
class AccessLogEntry::HttpDetails http
bool allowed() const
Definition Acl.h:82
static Notes & metaHeaders()
The list of configured meta headers.
Definition Config.cc:35
char * name
Definition CachePeer.h:61
hier_code peerType
Definition Connection.h:155
CachePeer * getPeer() const
Token * next
Definition Token.h:73
char host[SQUIDHOSTNAMELEN]
struct timeval peer_select_start
void clearPeerNotes()
forget previous notePeerRead() and notePeerWrite() calls (if any)
struct timeval peer_last_write_
time of the last write to the last peer
struct timeval store_complete_stop
int64_t bodyBytesRead
number of body bytes received from the next hop or -1
Comm::ConnectionPointer tcpServer
TCP/IP level details of the last peer/server connection.
char cd_host[SQUIDHOSTNAMELEN]
bool peerResponseTime(struct timeval &responseTime)
struct timeval peer_last_read_
time of the last read from the last peer
void resetPeerNotes(const Comm::ConnectionPointer &server, const char *requestedHost)
bool hasIcapToken
Definition Config.h:54
bool hasAdaptToken
Definition Config.h:50
bool empty() const
Definition Notes.h:145
STL Allocator that uses Squid memory pools for memory management.
Definition SBuf.h:94
bool isEmpty() const
Definition SBuf.h:435
struct SquidConfig::@82 Log
CustomLog * accesslogs
#define LOG_DISABLE
Definition defines.h:61
#define LOG_ENABLE
Definition defines.h:60
void fatalf(const char *fmt,...)
Definition fatal.cc:68
const char * dash_str
@ HIER_NONE
Definition hier_code.h:13
void logfileLineEnd(Logfile *lf)
Definition File.cc:132
void logfileLineStart(Logfile *lf)
Definition File.cc:126
void logfileClose(Logfile *lf)
Definition File.cc:92
Logfile * logfileOpen(const char *path, size_t bufsz, int fatal_flag)
Definition File.cc:40
@ LOOKUP_NONE
Definition lookup_t.h:13
void OBJH(StoreEntry *)
Definition forward.h:44
const SBuf Dash
@ LFT_ICAP_TOTAL_TIME
Definition ByteCode.h:195
@ LFT_NOTE
Definition ByteCode.h:239
@ LFT_ADAPTATION_SUM_XACT_TIMES
Definition ByteCode.h:186
@ LFT_ADAPTATION_LAST_HEADER
Definition ByteCode.h:188
@ LFT_ADAPTATION_LAST_ALL_HEADERS
Definition ByteCode.h:190
@ LFT_ADAPTATION_LAST_HEADER_ELEM
Definition ByteCode.h:189
@ LFT_ADAPTATION_ALL_XACT_TIMES
Definition ByteCode.h:187
Definition forward.h:18
void HttpdCombined(const AccessLogEntryPointer &al, Logfile *logfile)
Log with Apache httpd combined format.
void SquidCustom(const AccessLogEntryPointer &al, CustomLog *log)
Log with a local custom format.
void SquidIcap(const AccessLogEntryPointer &al, Logfile *logfile)
Display log details in Squid ICAP format.
void SquidUserAgent(const AccessLogEntryPointer &al, Logfile *logfile)
Display log details in useragent format.
@ CLF_COMBINED
Definition Formats.h:28
@ CLF_ICAP_SQUID
Definition Formats.h:32
@ CLF_USERAGENT
Definition Formats.h:36
@ CLF_REFERER
Definition Formats.h:34
void HttpdCommon(const AccessLogEntryPointer &al, Logfile *logfile)
Log with Apache httpd common format.
void SquidNative(const AccessLogEntryPointer &al, Logfile *logfile)
Native Squid Format Display.
void SquidReferer(const AccessLogEntryPointer &al, Logfile *logfile)
Display log details in Squid old refererlog format.
LogConfig TheConfig
Definition Config.cc:15
void RegisterAction(char const *action, char const *desc, OBJH *handler, Protected, Atomic, Format)
STL namespace.
#define SQUIDHOSTNAMELEN
Definition rfc2181.h:30
static StoreRebuildData counts
void tvSub(struct timeval &res, struct timeval const &t1, struct timeval const &t2)
Definition gadgets.cc:58
struct timeval current_time
the current UNIX time in timeval {seconds, microseconds} format
Definition gadgets.cc:18
char * xstrncpy(char *dst, const char *src, size_t n)
Definition xstring.cc:37