Logovanie
Keď má DI kontajner službu implementujúcu Tomaj\NetteApi\Logger\ApiLoggerInterface, ApiPresenter ju zavolá po behu handlera.
Maskujte tajné hlavičky
Predvolene dostane logger hlavičky požiadavky presne tak, ako prišli, vrátane Authorization, cookies a API kľúčov. Od verzie 3.6.0 zavolajte na presenteri setMaskedLogHeaders(). V 3.5.0 ich maskujte vo svojom loggeri.
Rozhranie
public function log(
int $responseCode,
string $requestMethod,
string $requestHeader,
string $requestUri,
string $requestIp,
string $requestAgent,
int $responseTime
): bool;| Argument | Hodnota |
|---|---|
$responseCode | odoslaný stavový kód |
$requestHeader | všetky hlavičky požiadavky, jedna Name: value na riadok |
$requestUri | REQUEST_URI aj s query stringom |
$requestIp | zo služby IpDetectorInterface, ktorá musí existovať |
$responseTime | milisekundy |
Príklad
Príklad logovania zapisuje JSON riadky:
<?php
declare(strict_types=1);
namespace App;
use Tomaj\NetteApi\Logger\ApiLoggerInterface;
/**
* Writes one JSON line per API request.
* The headers arrive as "Name: value" lines; secret values are already *** thanks to setMaskedLogHeaders().
*/
final class FileApiLogger implements ApiLoggerInterface
{
public function __construct(private string $file)
{
}
public function log(
int $responseCode,
string $requestMethod,
string $requestHeader,
string $requestUri,
string $requestIp,
string $requestAgent,
int $responseTime
): bool {
$headers = [];
foreach (explode(PHP_EOL, trim($requestHeader)) as $line) {
[$name, $value] = array_map('trim', explode(':', $line, 2)) + [1 => ''];
$headers[$name] = $value;
}
$line = json_encode([
'code' => $responseCode,
'method' => $requestMethod,
'uri' => $requestUri,
'ip' => $requestIp,
'agent' => $requestAgent,
'time_ms' => $responseTime,
'headers' => $headers,
], JSON_UNESCAPED_SLASHES);
return file_put_contents($this->file, $line . "\n", FILE_APPEND | LOCK_EX) !== false;
}
}services:
- Tomaj\NetteApi\Misc\IpDetector
- App\FileApiLogger(%appDir%/../log/api.log)Maskovanie hlavičiek
Od verzie 3.6.0
ApiPresenter::setMaskedLogHeaders() nahradí hodnoty zvolených hlavičiek požiadavky reťazcom *** skôr, než sa dostanú do log(). Kým ju nezavoláte, je vypnutá, takže logovanie v 3.x sa samo nezmení.
services:
apiPresenter:
factory: Tomaj\NetteApi\Presenters\ApiPresenter
setup:
- setMaskedLogHeaders()Toto je jediná služba apiPresenter zo stránky Začíname: pridajte k nej tieto riadky setup:, alebo dajte blok pod rovnakým názvom do iného konfiguračného súboru a Nette ich zlúči. Druhú službu ApiPresenter neregistrujte; dve skončia chybou „Multiple services of type Tomaj\NetteApi\Presenters\ApiPresenter found“.
| Volanie | Maskované hlavičky |
|---|---|
setMaskedLogHeaders() | Authorization, Proxy-Authorization, Cookie, Set-Cookie, X-Api-Key (ApiPresenter::DEFAULT_MASKED_LOG_HEADERS) |
setMaskedLogHeaders(['X-Session', 'Authorization']) | iba uvedené, zoznam nahradí predvolený |
setMaskedLogHeaders([]) | žiadne |
Názvy sa porovnávajú bez ohľadu na veľkosť písmen, takže x-api-key zodpovedá X-Api-Key. Hlavička v logu ostane aj s názvom, iba hodnota sa zmení na ***:
Authorization: ***
X-Trace: abc-123Maskujú sa iba hlavičky. Token v query stringu, napríklad ?api_key= pre QueryApiKeyAuthentication, ostane v $requestUri; odstráňte ho vo svojom loggeri.
Čo sa loguje
| Odpoveď | Loguje sa v 3.x |
|---|---|
| výsledok handlera, ľubovoľný kód | áno |
500 z výnimky alebo zlyhanej kontroly výstupu | áno |
404 Unknown api endpoint | áno |
400 zlý vstup, 401, 429, 500 z výnimky v authorized() | nie, presenter skončí pred loggerom |
Časté otázky
Prečo v logu chýbajú moje odpovede 401?
V 3.x končia predčasne, pozrite tabuľku. Ak ich potrebujete, logujte ich vo vlastnom error handleri.
Potrebujem na logovanie detektor IP?
Áno, presenter berie IpDetectorInterface z kontajnera. Uprednostnite taký, ktorý číta len REMOTE_ADDR; pozrite si Autorizáciu.
Kam idú výnimky?
Do Tracy, cez Debugger::log() v DefaultErrorHandler. Pozrite si Spracovanie chýb.
Môžem logovať telo odpovede?
Cez toto rozhranie nie, dostane len kód. Ak potrebujete viac, obaľte handler alebo error handler.
Záleží na návratovej hodnote log()?
Nie, presenter ju ignoruje.
Mám maskovanie nechať aj vo vlastnom loggeri?
Pre hlavičky nie, keď voláte setMaskedLogHeaders(). Nechajte ho pre tokeny v query stringu, na ktoré presenter nesiaha.