Blog · usługi programistyczne

Debugowanie integracji na produkcji, gdy nie masz dostępu do logów

2026-08-31

Problem

Integracja z zewnętrznym systemem „niby działa”: formularz się wysyła, użytkownik widzi podziękowanie, a mimo to dane nie docierają na drugi koniec. Kod wygląda dobrze. Zewnętrzny system odpowiada „200 OK”. A leada jak nie było, tak nie ma.

Na własnej maszynie dorzuciłabyś kilka linijek logu i po sprawcy. Ale problem jest tylko na produkcji – bo to produkcja łączy się na zewnątrz, a localhost nie wychodzi w świat. I tu zaczyna się gimnastyka: hosting współdzielony, log błędów PHP przekierowany w miejsce, którego nie sposób znaleźć w panelu, a dostępu do serwera przez konsolę brak.

Dlaczego „200 OK” potrafi kłamać

Najważniejsza lekcja z takiej sytuacji: kod odpowiedzi HTTP mówi tylko, że serwer odebrał żądanie – nie że je zaakceptował. Zewnętrzny Form Handler potrafi zwrócić „200 OK”, a w treści odpowiedzi grzecznie napisać „to pole jest wymagane” i nic nie zapisać. Jeśli patrzysz tylko na kod odpowiedzi, widzisz sukces. Prawda siedzi w treści (body), którą trzeba osobno wyciągnąć i zobaczyć.

Rozwiązanie: przełącznik + plik podglądu

Zamiast walczyć z logami hostingu, robię dwie rzeczy. Pierwsza: własny log sterowany stałą, domyślnie wyłączony. Pisze do pliku obok modułu, więc wiem gdzie go szukać.

// Domyślnie wyłączony - włączam tylko na czas testów.
if (!defined('MOJ_DEBUG')) {
    define('MOJ_DEBUG', false);
}

private function debug_log($msg) {
    if (!MOJ_DEBUG) return;                       // cisza, gdy wyłączone
    $file = __DIR__ . '/_debug.log';
    @file_put_contents($file, '[' . date('Y-m-d H:i:s') . "] $msg\n", FILE_APPEND);
}

Loguję to, co naprawdę chcę wiedzieć: dokąd poszło, co poszło, i – co kluczowe – treść odpowiedzi, nie tylko jej kod:

$this->debug_log('URL: ' . $url);
$this->debug_log('POLA: ' . wp_json_encode($fields, JSON_UNESCAPED_UNICODE));
$this->debug_log('Odpowiedź: ' . wp_remote_retrieve_response_code($response)
    . ' | treść: ' . substr(wp_remote_retrieve_body($response), 0, 300));

Druga rzecz: mały plik, który po wejściu w przeglądarce wypisuje ostatnie linie tego logu na ekran. Dzięki temu nie muszę w ogóle szukać logów w panelu hostingu – otwieram adres, czytam, koniec.

<?php
// _podglad.php - kasuję z serwera razem z logiem po testach.

$klucz  = 'wpisz-tutaj-cos-losowego';
$podany = is_string($_GET['k'] ?? null) ? $_GET['k'] : '';
if (!hash_equals($klucz, $podany)) {
    http_response_code(404);   // 404, nie 403 - nie potwierdzam, że plik istnieje
    exit;
}

$plik = __DIR__ . '/_debug.log';
if (!is_readable($plik)) {
    exit('Brak logu - akcja jeszcze się nie wykonała?');
}

// Czytam tylko ogon pliku, nie całość - log potrafi urosnąć.
$f = new SplFileObject($plik);
$f->seek(PHP_INT_MAX);
$od = max(0, $f->key() - 100);

header('Content-Type: text/plain; charset=utf-8');
foreach (new LimitIterator($f, $od) as $linia) {
    echo $linia;
}

Klucz w adresie to nie jest twarde zabezpieczenie – to bariera na te dziesięć minut, żeby nikt nie trafił na plik przypadkiem ani nie zgadł adresu. To dlatego 404 zamiast 403: bez klucza plik udaje, że go nie ma. Ale skoro w logu lądują cudze maile i telefony, sam klucz nie wystarcza za usprawiedliwienie – realną ochroną jest to, że plik żyje krótko i znika z serwera od razu po testach (o tym niżej). Przy text/plain celowo nie escapuję treści: przeglądarka i tak niczego nie renderuje, a htmlspecialchars() zamieniłoby znaki w odpowiedzi API na encje i log zrobiłby się nieczytelny.

1. Włącz przełącznik (stała na true), wgraj plik na serwer.
2. Wywołaj akcję, którą testujesz (np. wyślij formularz).
3. Otwórz plik podglądu w przeglądarce - czytasz, co poszło.
4. Po wszystkim: przełącznik z powrotem na false, usuń z serwera
   plik podglądu ORAZ plik logu.

To właśnie ta pętla – włącz, wywołaj, podejrzyj, wyłącz – pozwoliła namierzyć całą serię drobnych przyczyn, których z zewnątrz nie było widać: że system odrzuca dane mimo „200”, że rozpoznanie działało nie tak, jak zakładałam, że nazwy pól się nie zgadzają. Bez tego zgadywałabym w ciemno, wgrywając poprawkę po poprawce.

Uwaga, która jest ważniejsza niż cały trik

Taki log zapisuje prawdziwe dane z formularzy – maile, telefony, nazwiska. To jest tymczasowe narzędzie diagnostyczne, nie element strony. Po skończonych testach trzeba wyłączyć przełącznik i skasować z serwera i plik podglądu, i plik logu. Zostawiony na produkcji byłby wyciekiem danych osobowych na życzenie.

Czego się nauczyłam

Nie każdy problem widać z zewnątrz, a „200 OK” bywa mylące. Czasem najszybszą drogą do rozwiązania nie jest kolejna poprawka na wyczucie, tylko dziesięć minut na zbudowanie sobie okna, przez które w końcu widać, co się naprawdę dzieje. To okno warto potem zamknąć.

Wróć do wszystkich wpisów

Masz projekt do omówienia?

Napisz, o co chodzi - nie musi być technicznie, od tego jestem ja. Odezwę się i powiem wprost, czy i jak mogę pomóc.