ADR 0001: Log-level voor HTTP-fouten
- Status: geaccepteerd
- Datum: 2026-04-30
- Beslissers: Roy Milder
Context
De centrale errorhandler in apps/api/src/common/middleware/errorHandler/errorHandler.ts logde elke afgehandelde fout op error-niveau, ongeacht de HTTP-statuscode. Verwachte clientfouten (een gebruiker zonder auth-header op een beschermd endpoint, een mislukte Zod-validatie, een ontbrekend document) kwamen daarmee als ERROR met volledige stacktrace in de logs terecht.
Daardoor:
- Werd het signaal van echte serverfouten (5xx) overschaduwd door normaal verkeer.
- Triggerden monitoring- en alertintegraties die op error-niveau luisteren op events die geen actie vereisen.
- Was lastig te onderscheiden of een spike in errors een productieprobleem was, of gewoon meer ongeauthenticeerd verkeer.
4xx-statuscodes geven per definitie aan dat de client iets fout doet, niet de server. Voor de meeste 4xx-gevallen hoeft niemand te kijken; de toegangslog bevat de statuscode al.
Beslissing
We loggen HTTP-fouten in de centrale errorhandler op een niveau dat past bij de statuscode:
errorvoor 5xx (serverfouten die actie vereisen).infovoor 4xx (clientfouten, normaal verkeer).
De keuze is gebaseerd op de vraag “moet hier iemand naar kijken?”. Bij 5xx is het antwoord ja, bij 4xx in de regel nee. Daarom gebruiken we info voor 4xx en niet warn: een warn-stream die volloopt met routine-clientfouten verliest betekenis, net als de error-stream nu.
Gevolgen
- Positief:
- De error-stream bevat alleen nog daadwerkelijke serverfouten, waardoor alerts en dashboards betrouwbaarder worden.
- Minder ruis in productielogs; routine-401’s en validatiefouten blijven traceerbaar via
infomaar triggeren niets. - De drempel voor “is er iets mis?” wordt hoger en daardoor zinvoller.
- Negatief:
- Wie eerder grepde op
level=errorom alle afgehandelde excepties te zien, moet nu ookinfomeenemen, of beter: filteren op statuscode in de toegangslog. - De errorhandler beslist het log-level op basis van responsestatus; afwijkingen vereisen aanpassing op één centrale plek.
- Wie eerder grepde op
- Risico’s:
- Een echte fout die per ongeluk als 4xx wordt gemapt, valt voortaan onder
infoen triggert geen alert. Mitigatie: bij twijfel mappen we onbekende fouten al naar 500 (zie de catch-all op regel 88 inerrorHandler.ts), en de toegangslog blijft beschikbaar voor forensisch onderzoek. - Specifieke 4xx-codes (429, herhaalde 401’s met geldig ogend maar afgewezen token) kunnen wel degelijk een signaal zijn. Als dat in de praktijk voorkomt, voegen we een gerichte
warn-tak toe; we doen dat niet preventief.
- Een echte fout die per ongeluk als 4xx wordt gemapt, valt voortaan onder
Alternatieven
Alles op error blijven loggen. Status quo. Afgewezen omdat de error-stream daardoor onbruikbaar wordt voor alerting: je kunt geen onderscheid maken tussen “site stuk” en “iemand zonder token”.
4xx op warn. Een tussenoptie. Afgewezen omdat warn dan dezelfde overload krijgt als error nu. Een logniveau is alleen nuttig als er iets aan vastzit (een dashboardregel, een alert); voor routine-401’s geldt dat niet. Wanneer er wel een signaal in zit (rate limiting, gerichte aanvalspatronen) kunnen we die specifieke gevallen alsnog op warn zetten.
Per fouttype een vast log-level configureren. Flexibeler, maar complexer en duplicaat met de mapping van fouttype naar statuscode die al in de errorhandler zit. De statuscode is de enige bron van waarheid voor “hoe ernstig is dit voor de server”.