Preskočiť na obsah

Logovanie ​

Keď má DI kontajner službu implementujúcu Tomaj\NetteApi\Logger\ApiLoggerInterface, ApiPresenter ju zavolá po behu handlera.

Otvoriť diagram v plnej veľkosti

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 ​

php
public function log(
    int $responseCode,
    string $requestMethod,
    string $requestHeader,
    string $requestUri,
    string $requestIp,
    string $requestAgent,
    int $responseTime
): bool;
ArgumentHodnota
$responseCodeodoslaný stavový kód
$requestHeadervšetky hlavičky požiadavky, jedna Name: value na riadok
$requestUriREQUEST_URI aj s query stringom
$requestIpzo služby IpDetectorInterface, ktorá musí existovať
$responseTimemilisekundy

Príklad ​

Príklad logovania zapisuje JSON riadky:

php
<?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;
    }
}
yaml
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í.

yaml
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“.

VolanieMaskované 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 ***:

text
Authorization: ***
X-Trace: abc-123

Maskujú 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.

Vydané pod licenciou MIT.