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.
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-8pod 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 domeniegooglebot.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
%bnie jest pełnym transferem strony.
Analiza pliku
goaccess twoja-strona-access-2026-09-16.log --log-format=COMBINED -o raport.html
# 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. Log jest osobnym przetwarzaniem, z własną retencją i własną bramką dostępu.