nginx
GeoMetrikks reads a keyed JSON access log. Add this log_format to the
http block in your nginx.conf (nginx 1.11.8 or later for escape=json):
log_format geometrikks_json escape=json '{' '"client_ip":"$remote_addr",' '"timestamp":"$time_iso8601",' '"method":"$request_method",' '"path":"$request_uri",' '"protocol":"$server_protocol",' '"status":"$status",' '"bytes":"$body_bytes_sent",' '"host":"$host",' '"referrer":"$http_referer",' '"user_agent":"$http_user_agent",' '"remote_user":"$remote_user",' '"request_time":"$request_time",' '"upstream_time":"$upstream_response_time",' '"request_raw":"$request"' '}';Then use it on the access log you want GeoMetrikks to tail:
access_log /config/log/nginx/access.log geometrikks_json;Keep every value quoted, including the numbers: nginx has no typed output,
and an unquoted empty variable breaks the line. escape=json is required;
without it a quote inside a user agent produces invalid JSON, and the line
is skipped and counted as unparseable. escape=json leaves bytes above
0x7f raw, so a probe line can carry undecodable bytes; GeoMetrikks
replaces them with U+FFFD and still classifies the line. client_ip and
timestamp are the only required keys. Drop any other key and the feature
it feeds goes empty (host feeds the host filter, request_time and
upstream_time feed the response-time analytics). Add your own keys
freely; GeoMetrikks ignores the ones it does not know.
LOGPARSER_LOG_FORMATS=geometrikks-json pins the parser to this format
instead of detecting it per file.
$remote_addr is only the visitor’s address if nginx sees the visitor
directly. Behind a CDN, tunnel, or another proxy, see
docs/proxy-setup.md for the realip config that logs
the visitor instead of that hop.
Legacy nginx format
Section titled “Legacy nginx format”Earlier versions documented this positional format. It keeps working for
both live tailing and import-logs, so an existing install needs no
change, and archives already written in it import as before. Use the JSON
format above for new setups.
log_format custom '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" $host "$http_user_agent" ' '"$request_time" "$upstream_response_time"';The parser matches this format on position and quoting rather than on field names, so a rearranged format can land values in the wrong columns instead of failing outright. Four rules:
- Use
$time_local.$time_iso8601does not match at all, and a file that uses it produces no rows. - Keep
$hostunquoted and between"$http_referer"and"$http_user_agent". Writing"$host"still parses, but the hostname ends up in the user-agent column andhostcomes out empty. - Keep
$request_timeand$upstream_response_timequoted. Unquoted, both are dropped and read as 0. - Append extra fields only after both timing fields. The parser fills the
two timing slots by quoting alone, so on a format without them an extra
quoted field lands in
$request_time. A non-numeric value such as"$http_x_forwarded_for"is discarded, but a numeric one is recorded and charted as a response time.
LOGPARSER_LOG_FORMATS=nginx pins the parser to this format.
Backfilling logs written in another format
Section titled “Backfilling logs written in another format”Lines in nginx’s built-in combined format also parse, so you can import
archives you have on disk without having changed your nginx config first.
Three fields are absent from those lines and cannot be recovered after the
fact:
| Missing field | What it costs you |
|---|---|
$host |
The host filter on the access-log and analytics pages has nothing to list |
$request_time |
Response-time cards show n/a for those rows; rows imported by earlier versions carry a placeholder 0.0 that backfill-timings clears |
$upstream_response_time |
Upstream timing stays empty in the access-log detail view |
The map, geo analytics, status codes, URLs, referrers, user agents and bytes are unaffected.
Multiple log files
Section titled “Multiple log files”LOGPARSER_LOG_PATHS accepts a single path or a JSON list, so nginx can log
to more than one file and GeoMetrikks tails all of them:
access_log /config/log/nginx/somepage/access.log geometrikks_json;access_log /config/log/nginx/access.log geometrikks_json;LOGPARSER_LOG_PATHS=["/var/log/access/access.log", "/var/log/access/somepage/access.log"]