Skip to content

Traffic Log Format

The appliance writes a second access log in a structured format that the console reads. Your ordinary access.log is left in Squid's native format and untouched, so existing tooling pointed at it keeps working.

Path /var/log/squid/cloudinfra-events.log
Format name cloudinfra
Separator Tab
Fields 18
Ownership squid:squid, mode 0640

Why a second log

Squid's native format is designed to be human-readable, which makes it ambiguous to parse: fields are space-separated, and URLs, user agents and usernames can all contain spaces. Anything parsing it has to guess.

The structured log removes the guessing. It is tab-separated with a fixed field count, and every free-text field is percent-encoded by Squid itself.

The fields

# Squid token Contents
1 %ts.%03tu Timestamp, epoch seconds with milliseconds
2 %tr Response time, milliseconds
3 %>a Client address
4 %>p Client port
5 %[un Authenticated username, - if none
6 %Ss Squid result code, e.g. TCP_MISS, TCP_DENIED
7 %03>Hs HTTP status sent to the client
8 %<st Bytes received from the destination
9 %>st Bytes received from the client
10 %rm Request method
11 %[ru Request URL
12 %[mt MIME type
13 %Sh Hierarchy code — how the request was forwarded
14 %<a Destination address
15 %err_code Squid error code, if any
16 %err_detail Error detail, if any
17 %{ci_rule}note The rule that decided this request
18 %[{User-Agent}>h Client user agent

The %[ modifier

Fields 5, 11, 12 and 18 use Squid's %[ prefix, which percent-encodes the value.

This is what makes tab framing safe. A URL containing a tab or a newline arrives as %09 or %0A and cannot break the record — so a hostile request cannot forge a log entry or split one into two.

Any consumer must percent-decode these fields before displaying them, and must not decode before parsing structure. Decoding first destroys the framing the encoding exists to protect.

Field 17: rule attribution

Squid has no native field recording which http_access line decided a request. This one is created by the configuration generator.

Each generated rule declares an annotation ACL that always matches and exists only for its side effect, placed last on its http_access line:

acl ci_src_7 src 10.20.0.0/16
acl ci_dst_7 dstdomain .facebook.com
acl ci_mark_7 annotate_transaction ci_rule=7
http_access deny ci_src_7 ci_dst_7 ci_mark_7

Because it is last, it only stamps the transaction when every preceding ACL on that line matched — that is, when this rule is the one that decided. Placed first, it would stamp every request the line merely considered, and attribution would be meaningless.

Value Means
A number The rule with that identifier decided the request
0 The appliance's own built-in policy decided it
- No annotation — an allow that matched no managed rule

This works only because the appliance owns both the configuration generator and the log reader.

A sample record

Shown with tabs as for readability, and wrapped:

1755600123.456→142→10.20.1.55→51234→-→TCP_DENIED→403→3521→412→GET→
http%3A%2F%2Fwww.facebook.com%2F→text%2Fhtml→HIER_NONE→-→
ERR_ACCESS_DENIED→-→7→Mozilla%2F5.0%20(Windows%20NT%2010.0)

Read as: a request from 10.20.1.55 to www.facebook.com was denied with 403 by rule 7, taking 142 ms.

Reading it yourself

The format is deliberately easy to consume.

# Every denied request, with the rule that denied it
awk -F'\t' '$6 ~ /DENIED/ { print $3, $11, "rule=" $17 }' \
    /var/log/squid/cloudinfra-events.log
# Bandwidth by client
awk -F'\t' '{ b[$3] += $8 } END { for (c in b) print b[c], c }' \
    /var/log/squid/cloudinfra-events.log | sort -rn | head

Remember to percent-decode field 11 before displaying URLs.

The field order is a contract

The format string and the console's parser are two halves of one agreement. If you change the logformat line, the console stops being able to read its own traffic log.

If you need a different format for your own tooling, add a third access_log line in /etc/squid/local.conf rather than altering this one.

Rotation

The log rotates daily and is kept for 14 days, with squid -k rotate issued so Squid reopens its files rather than continuing to write to a renamed one. The Health page warns if rotation stops running.

The console's log viewer reads rotated and compressed archives as well as the current file.