# Log dostępu witryny: format wiersza, zakres zapisu, retencja i limity

> Jak powstaje plik logu witryny tenanta: Combined Log Format i znaczenie każdego pola, co nie wchodzi do zapisu, strefa czasowa i granica doby, limit rozmiaru, retencja, bramka planu oraz przykłady analizy w GoAccess i awk.

Opublikowano: 2026-09-17 · Aktualizacja: 2026-10-07
Źródło: https://kompasfirm.pl/dokumentacja/log-dostepu-witryny

---
## Gdzie powstaje plik

Zapis wykonuje ta sama warstwa, która zasila Kompas Lead Analytics: middleware żądań witryn tenantów, w fazie `terminate()`, czyli po odesłaniu odpowiedzi do przeglądarki. Obie ścieżki (baza analityki i plik logu) mają osobne zabezpieczenie na wyjątki, więc awaria jednej nie zabiera drugiej, a żaden błąd tej warstwy nie wywraca strony klienta.

Każda witryna ma własny zestaw plików, trzymany w katalogu nazwanym jej numerem, a nie subdomeną: zmiana adresu czy podpięcie własnej domeny nie rozcina historii. Nazwa pliku to `access-RRRR-MM-DD.log`, czyli jeden plik na dobę.

Doba jest liczona w strefie **Europe/Warsaw**, mimo że aplikacja pracuje w UTC. Log czyta polski klient i porównuje go z własnym zegarem, więc granica doby i znaczniki czasu idą za nim, a nie za serwerem. Ma to jedną konsekwencję przy korelowaniu źródeł: godzina w logu i godzina w surowych danych analityki mogą się różnić o przesunięcie strefy, więc porównując oba, trzeba to uwzględnić.

Plik nowej doby powstaje leniwie, przy pierwszym żądaniu po północy. Dopisywanie idzie w trybie append z blokadą pliku, więc równoległe żądania nie mieszają sobie wierszy. Gdy katalogu nie da się utworzyć albo zapis się nie powiedzie, żądanie kończy się normalnie, a wiersz po prostu przepada: log nie ma prawa zaszkodzić stronie.

Zapis nie zależy od planu. Plan bramkuje wyłącznie sięganie po gotowy plik, bo to on zawiera adresy IP.

## Format wiersza

```
%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"
```

| Pole | Zawartość |
| --- | --- |
| `%h` | adres klienta ustalony zza proxy (nagłówek `X-Forwarded-For` od Caddy'ego); `-`, gdy nie da się go ustalić |
| `%l` | zawsze `-` (identd, relikt formatu) |
| `%u` | numer zalogowanego konta, gdy żądanie idzie do panelu pod domeną klienta; poza tym `-` |
| `%t` | `d/M/Y:H:i:s O` w strefie z konfiguracji |
| `%r` | metoda, pełny adres z query stringiem i wersja protokołu |
| `%>s` | kod odpowiedzi HTTP |
| `%b` | `Content-Length`, a gdy nagłówka nie ma, długość treści odpowiedzi |
| Referer, User-Agent | nagłówki żądania; `-`, gdy puste |

Wersja protokołu jest tą, którą widzi aplikacja za Caddym (zwykle `HTTP/1.1`), nie tą, której użył klient. Pole zostaje dla zgodności z parserami.

Wartości w cudzysłowach są czyszczone przed zapisem: znaki sterujące wycinamy (inaczej dałoby się dopisać do logu spreparowany wiersz), cudzysłów i ukośnik dostają ucieczkę, a pole jest przycinane do 1024 znaków. Referer i User-Agent są w pełni pod kontrolą klienta, więc traktujemy je jak dane wrogie.

## Co nie trafia do pliku

- **Pliki z `public/`** (grafiki, `/build`, favicona). Serwer WWW oddaje je przed PHP-FPM, żądanie nie wchodzi w kernel aplikacji. Komplet takich wierszy ma wyłącznie log brzegu (Caddy).
- **Ścieżki techniczne pomiaru** (beacon analityki), żeby nie dublować w logu tego, co ma własną warstwę zapisu. Porównanie idzie po ścieżce bez query stringa.
- **Żądania bez rozpoznanej witryny tenanta**: platforma, panel na `kompasfirm.pl`, panel administratora.
- **Ruch zatrzymany na brzegu**, czyli to, co nigdy nie doszło do aplikacji.

Przekierowanie kanoniczne (www na wersję wybraną w panelu) następuje już po rozpoznaniu witryny, więc zostawia normalny wiersz z kodem 301.

## Limit doby i retencja

Jedna doba jednej witryny może zająć najwyżej 50 MB. Po przekroczeniu limitu dopisujemy wiersz-znacznik z godziną i wartością limitu, a dalsze żądania tej doby nie są logowane; następna doba startuje czysto. To bezpiecznik na dysk: ponad 83% ruchu platformy to automaty, więc jedna strona pod skanerem potrafi puchnąć w tempie, którego nikt nie pilnuje. Znacznik w pliku jest jedynym sygnałem, że doba jest niekompletna, więc przy analizie transferu warto go najpierw poszukać.

Retencję stosuje nocne zadanie: pliki starsze niż 30 dni są kasowane bezpowrotnie, codziennie, bez wyjątków i bez możliwości odtworzenia. Retencja jest krótsza niż w analityce, bo tu leży pełne IP. Jeśli potrzebujesz dłuższej historii, pobieraj pliki regularnie i archiwizuj je u siebie, pamiętając, że wtedy to Ty jesteś administratorem tych danych.

## Dostęp i pobieranie

- Bramka: flaga planu `site_logs` (plan Standard i wyższe). Administrator platformy wchodzi bez flagi, bo log bywa narzędziem wsparcia.
- Role udostępnienia pojedynczej strony (redaktor, handlowiec, klient) nie mają tej trasy w allowliście, więc dostają 403. Copywriter w zespole nie widzi pozycji w menu.
- Pobranie oddaje plik jako `text/plain; charset=UTF-8` pod nazwą `<subdomena>-access-RRRR-MM-DD.log`. Data w adresie jest walidowana wzorcem `\d{4}-\d{2}-\d{2}`, a nieistniejąca doba kończy się kodem 404.
- Podgląd w panelu czyta 100 ostatnich wierszy od końca pliku, blokami po 8 kB, bez wczytywania całości do pamięci.

## Parametry

| Parametr | Wartość |
| --- | --- |
| dostępność | plan Standard i wyższe (flaga planu `site_logs`) |
| zakres zapisu | wszystkie witryny, niezależnie od planu |
| plik | jeden na dobę, doba w strefie Europe/Warsaw |
| retencja | 30 dni, potem kasowanie bezpowrotne |
| limit jednej doby | 50 MB, po przekroczeniu doba jest domykana |
| podgląd w panelu | 100 ostatnich wierszy najnowszej doby |
| maskowanie adresów IP | opcja platformy, domyślnie wyłączona |
| format pobieranego pliku | `text/plain; charset=UTF-8` |

Maskowanie, gdy jest włączone, zeruje końcówkę adresu na postaci binarnej, więc wynik dalej jest poprawnym adresem i GoAccess czy AWStats czytają plik bez zmian; tracą jedynie rozróżnienie pojedynczych hostów. Panel informuje o włączonym maskowaniu, bo zmienia ono status pliku wobec danych osobowych. Ustawienie działa globalnie, nie per witryna, i nie zmienia plików już zapisanych.

## Jak czytać dane z logu bez błędnych wniosków

- **Jeden wiersz to jedno żądanie**, nie jedna wizyta i nie jeden użytkownik. Log nie skleja żądań w sesje; nie ma tu identyfikatora wizyty, bo nie ma cookies.
- **Adres IP nie jest tożsamością.** Jedno biuro wychodzi do internetu jednym adresem, a operatorzy komórkowi i sieci za CGNAT dzielą adres między wielu abonentów. Liczba unikalnych adresów jest więc górnym ograniczeniem, a nie liczbą osób.
- **User-Agent jest deklaracją klienta**, którą można dowolnie podrobić, i skanery masowo to robią. Deklarację Googlebota weryfikuje się odwrotnym DNS-em na adresie IP (`host <ip>` powinien zwrócić nazwę w domenie `googlebot.com`, a nazwa po ponownym rozwiązaniu ten sam adres) albo porównaniem z publikowanymi przez Google zakresami adresów.
- **Kod 200 opisuje odpowiedź serwera**, nie to, co zobaczył człowiek. O renderowaniu, błędach JavaScriptu i zachowaniu odwiedzającego log nie wie nic.
- **Brak wierszy dla zasobów statycznych** zmienia arytmetykę znaną z klasycznego hostingu: liczba wierszy odpowiada mniej więcej liczbie odsłon, a suma pola `%b` nie jest pełnym transferem strony.

## Analiza pliku

```bash
goaccess twoja-strona-access-2026-09-16.log --log-format=COMBINED -o raport.html
```

```bash
# dziesięć najczęstszych adresów kończących się kodem 404
awk '$9 == 404 {print $7}' access.log | sort | uniq -c | sort -rn | head

# co i kiedy odwiedził Googlebot
grep Googlebot access.log | awk '{print $4, $7}'

# transfer w megabajtach
awk '{sum += $10} END {print sum/1024/1024 " MB"}' access.log
```

## Log a Kompas Lead Analytics

| | Log dostępu | Kompas Lead Analytics |
| --- | --- | --- |
| Postać | plik tekstowy, wiersz na żądanie | tabele w bazie plus agregaty |
| Adres IP | pełny (albo maskowany globalnie) | nie jest zapisywany |
| User-Agent | pełny | rodzina klienta |
| Automaty | wszystkie, bez filtrowania | odfiltrowane z wizyt, pokazane osobno |
| Zgoda w banerze | bez znaczenia, to zapis serwera | warstwa przeglądarkowa dopiero po zgodzie |
| Retencja | 30 dni | od dwóch tygodni do dwóch lat, zależnie od warstwy |

Szczegóły przetwarzania po stronie analityki opisuje [Analityka w panelu](/pomoc/analityka-w-panelu). Log jest osobnym przetwarzaniem, z własną retencją i własną bramką dostępu.
