Client-Error-Endpoint POST /api/vitec/client-error (0072-FE / 0077-BE)
Neue PSR-15-Middleware ClientErrorMiddleware: nimmt Browser-Fehler des
React-Frontends als JSON {url, message, stack, release, userAgent}
entgegen und antwortet 204 ohne Body. Schutz: 30 Meldungen pro Minute
und IP (Sliding Window ueber TYPO3-RateLimiter, 429 + Retry-After),
8-KB-Body-Limit (413, Content-Length und tatsaechliche Bytes), kein
JSON-Objekt oder leere message = 400, GET = 405. Keine Session, keine
Cookies; der /_json-Praefix funktioniert ebenfalls.
Speicherung in der neuen Tabelle tx_vitec_clienterrorlog mit
anonymisierter IP (IPv4 letztes Oktett 0, IPv6 /48). Sichtbar als
Tabelle "Client errors (last 24 h)" im Modul VITEC SSR (mit Stack als
Aufklapper) und als Zeile "Client errors reported (24 h / 7 d)" in der
Dashboard-Kachel VITEC: SSR statistics.
CLI vitec:client-error-cleanup [--days=30] loescht Eintraege aelter als
30 Tage (taeglich per Cron).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
ff6f86b829
commit
5121eaa000
7 files changed
+360
No files matched your search
@@ -140,4 +140,42 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3>Client errors <small>(last 24 h — {clientErrorCount24h} report<f:if condition="{clientErrorCount24h} != 1">s</f:if>, newest 50 shown)</small></h3>
|
||||
<p class="text-muted" style="font-size:11px">
|
||||
Browser-side failures reported by the React frontend via <code>POST /api/vitec/client-error</code>
|
||||
(JS errors, unhandled promise rejections, element error boundaries and "chunk reload" after a deploy).
|
||||
Limited to 30 reports per minute and IP, 8 KB per report; IPs are stored anonymized.
|
||||
Kept for 30 days (cron <code>vitec:client-error-cleanup</code>).
|
||||
</p>
|
||||
<table class="table table-striped table-sm">
|
||||
<thead><tr><th>Time</th><th>Release</th><th>Message</th><th>Page</th><th>Browser</th><th>IP</th></tr></thead>
|
||||
<tbody>
|
||||
<f:for each="{clientErrors}" as="row">
|
||||
<tr>
|
||||
<td style="white-space:nowrap"><f:format.date format="Y-m-d H:i:s">@{row.crdate}</f:format.date></td>
|
||||
<td><code>{row.release}</code></td>
|
||||
<td>
|
||||
<f:if condition="{row.is_chunk_reload}">
|
||||
<f:then><span class="badge badge-warning">chunk reload</span> </f:then>
|
||||
<f:else><span class="badge badge-danger">error</span> </f:else>
|
||||
</f:if>
|
||||
{row.message}
|
||||
<f:if condition="{row.stack}">
|
||||
<details style="margin-top:4px">
|
||||
<summary style="cursor:pointer" class="text-muted">stack</summary>
|
||||
<pre style="font-size:11px;white-space:pre-wrap;max-height:240px;overflow:auto">{row.stack}</pre>
|
||||
</details>
|
||||
</f:if>
|
||||
</td>
|
||||
<td><a href="{row.url}" target="_blank" rel="noopener" title="{row.url}">{row.path}</a></td>
|
||||
<td title="{row.user_agent}"><small>{row.ua_short}</small></td>
|
||||
<td><small>{row.ip}</small></td>
|
||||
</tr>
|
||||
</f:for>
|
||||
<f:if condition="!{clientErrors}">
|
||||
<tr><td colspan="6" class="text-muted">No client errors reported in the last 24 hours.</td></tr>
|
||||
</f:if>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</html>
|
||||
Reference in new issue
Block a user