Title: Logging visit stats with NGINX
Slug: logging-visit-stats-with-nginx
Date: 2021-10-02 19:25:00
Author: Kartones
Lang: en
Tags: Development, Systems-IT
og_image:
Description: How to log visit stats with NGINX by filtering by subdomain and using a custom logger with a desired format. The configuration is provided.


I recently migrated my server to a new, newer instance, and decided to do some housekeeping and rethinking of the stuff I had running on it. One of the things that I had was a subdomain to store very basic visits stats, a tiny Python website done using Flask. Other than some small data formatting, it really wasn't doing anything else, so I thought: "If I'm using nginx and really don't need to format the data on save, why using anything else? why not reducing it to the bare minimum?".

After checking the documentation and some basic experiments, indeed for simple logging you don't really need anything else than filtering by the subdomain and an extra logger with a custom format.

I'll first show how to do it, then briefly explain the results:


On the specific `stats.mydomain.test` nginx configuration, inside the `server` block:
```
# server name must match with the one defined at `nginx.conf`
server_name stats.mydomain.test;

location / {
    # allow GETs from Javascript calls
    if ($request_method = 'GET') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET';
    }

    add_header 'Cache-Control' 'no-store';
    # As there's nothing to return, better 204 than 200
    return 204;
}
```

And on the general `nginx.conf` file, inside the `http` block:

```
# desired format, e.g. resembling a double-quoted fields CSV (without headers)
log_format statsformat '"$time_iso8601","$request_uri","$http_referer","$http_user_agent"';

# conditional mapping...
map $server_name $isstats {
    stats.mydomain.test 1;
    default 0;
}

# ... allows to do conditional logging
access_log /some/path/my_stats.log statsformat if=$isstats;
```

With just those lines, what you get is that any `GET` call to `stats.mydomain.test` will append a line to `my_stats.log` in the web server, but won't mess with calls to `mydomain.test`, `somewhere.mydomain.test` or any other subdomain on your server.

Logs allow for different configurations, like different buffer sizes (or no buffer at all) or compression. Check [the official docs](https://docs.nginx.com/nginx/admin-guide/monitoring/logging/) for more info.