feat: Sentry monitoring a kompletnější sledování stavů Bolt Food
- integrace Sentry na serveru (@sentry/node) i klientu (@sentry/react): chyby 5xx, pády a console logy se hlásí do self-hosted Sentry - nový veřejný endpoint GET /api/config — klient si z něj za běhu vyzvedne Sentry DSN (SENTRY_DSN / SENTRY_CLIENT_DSN v env) - ErrorBoundary na klientu a sourcemapy pro čitelné stack traces - oprava mapování stavu waiting_acceptance (zobrazoval se jako Příprava) - mapování stavů kurýra matched/accepted, logování přechodů stavů Bolt objednávek pro postupné zmapování nedokumentovaného API - simulátor Bolt ve vývoji nově prochází celou reálnou sekvenci stavů - vypnuté logování connect/disconnect websocket klientů
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
"@fortawesome/free-regular-svg-icons": "^7.1.0",
|
||||
"@fortawesome/free-solid-svg-icons": "^7.1.0",
|
||||
"@fortawesome/react-fontawesome": "^3.1.0",
|
||||
"@sentry/react": "^10.65.0",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@types/node": "^24.10.0",
|
||||
"@types/react": "^19.2.2",
|
||||
|
||||
@@ -14,6 +14,7 @@ const STEPS = ['Přijato', 'Příprava', 'Vyzvedávání', 'Na cestě', 'Doruče
|
||||
const ORDER_STATE_TO_STEP: Record<string, number> = {
|
||||
created: 0,
|
||||
pending: 0,
|
||||
waiting_acceptance: 0,
|
||||
accepted: 0,
|
||||
waiting_preparation: 0,
|
||||
preparing: 1,
|
||||
@@ -31,6 +32,8 @@ const ORDER_STATE_TO_STEP: Record<string, number> = {
|
||||
|
||||
/** Stavy kurýra z Bolt API → index kroku. Kurýr u podniku ještě neznamená "na cestě". */
|
||||
const COURIER_STATE_TO_STEP: Record<string, number> = {
|
||||
matched: 0,
|
||||
accepted: 0,
|
||||
heading_to_provider: 1,
|
||||
arrived_to_provider: 1,
|
||||
picked_up: 3,
|
||||
@@ -49,6 +52,7 @@ function stepForOrderState(state: string): number | 'cancelled' {
|
||||
if (s in ORDER_STATE_TO_STEP) return ORDER_STATE_TO_STEP[s];
|
||||
if (/cancel|reject|fail/.test(s)) return 'cancelled';
|
||||
if (/delivered|finished/.test(s)) return 4;
|
||||
if (/accept|pending|created/.test(s)) return 0;
|
||||
if (/^waiting|prepar|ready|cook/.test(s)) return 1;
|
||||
if (/picked|delivering|heading_to_client|transport/.test(s)) return 3;
|
||||
return 0;
|
||||
|
||||
+31
-5
@@ -6,20 +6,38 @@ import './index.css';
|
||||
import AppRoutes from './AppRoutes';
|
||||
import { BrowserRouter } from 'react-router';
|
||||
import { client } from '../../types/gen/client.gen';
|
||||
import { getConfig } from '../../types/gen/sdk.gen';
|
||||
import { getToken } from './Utils';
|
||||
import { toast } from 'react-toastify';
|
||||
import * as Sentry from '@sentry/react';
|
||||
|
||||
client.setConfig({
|
||||
auth: () => getToken(),
|
||||
baseUrl: '/api', // openapi-ts si to z nějakého důvodu neumí převzít z api.yml
|
||||
});
|
||||
|
||||
// Sentry se inicializuje až podle runtime konfigurace ze serveru (bez DSN zůstává vypnuté).
|
||||
// Klient je statický build, takže DSN nejde zapéct při buildu — server ho zná z env.
|
||||
getConfig().then(({ data }) => {
|
||||
if (data?.sentry.dsn) {
|
||||
Sentry.init({
|
||||
dsn: data.sentry.dsn,
|
||||
environment: data.sentry.environment,
|
||||
enableLogs: true,
|
||||
});
|
||||
}
|
||||
}).catch(() => { /* config endpoint nedostupný — běžíme bez Sentry */ });
|
||||
|
||||
// Interceptor na vyhození toasteru při chybě
|
||||
client.interceptors.response.use(async response => {
|
||||
// TODO opravit - login je zatím výjimka, voláme ho "naprázdno" abychom zjistili, zda nás nepřihlásily trusted headers
|
||||
if (!response.ok && !response.url.includes("/login")) {
|
||||
const json = await response.json();
|
||||
toast.error(json.error, { theme: "colored" });
|
||||
// Serverové chyby hlásíme do Sentry; 4xx jsou očekávané (chyby uživatele)
|
||||
if (response.status >= 500) {
|
||||
Sentry.captureMessage(`API ${response.status}: ${new URL(response.url).pathname} — ${json.error}`, 'error');
|
||||
}
|
||||
}
|
||||
return response;
|
||||
});
|
||||
@@ -29,10 +47,18 @@ const root = ReactDOM.createRoot(
|
||||
);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<ProvideAuth>
|
||||
<AppRoutes />
|
||||
</ProvideAuth>
|
||||
</BrowserRouter>
|
||||
<Sentry.ErrorBoundary fallback={
|
||||
<div className="text-center p-5">
|
||||
<h4>Něco se pokazilo 😕</h4>
|
||||
<p>Chyba byla nahlášena. Zkuste stránku načíst znovu.</p>
|
||||
<button className="btn btn-primary" onClick={() => window.location.reload()}>Načíst znovu</button>
|
||||
</div>
|
||||
}>
|
||||
<BrowserRouter>
|
||||
<ProvideAuth>
|
||||
<AppRoutes />
|
||||
</ProvideAuth>
|
||||
</BrowserRouter>
|
||||
</Sentry.ErrorBoundary>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
@@ -6,6 +6,10 @@ export default defineConfig({
|
||||
// depending on your application, base can also be "/"
|
||||
base: '',
|
||||
plugins: [react(), viteTsconfigPaths()],
|
||||
build: {
|
||||
// Veřejné sourcemapy, aby Sentry umělo přeložit minifikované stack traces
|
||||
sourcemap: true,
|
||||
},
|
||||
server: {
|
||||
open: true,
|
||||
host: '0.0.0.0',
|
||||
|
||||
@@ -854,6 +854,70 @@
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz#f79437939020b83057faf07e98365b1fa51c458b"
|
||||
integrity sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==
|
||||
|
||||
"@sentry/browser-utils@10.65.0":
|
||||
version "10.65.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/browser-utils/-/browser-utils-10.65.0.tgz#e3b67c6b9dd05dad2ad7eee82ad873bfc9f8ab12"
|
||||
integrity sha512-4J0mkfNJAGUOkpg1ZggizyftFTn9N20b+Jl87UnWsDUkNG0Ic1l/FIzMPTVxXrAnhBGu0ULO0TFWMoQ5s3QtZw==
|
||||
dependencies:
|
||||
"@sentry/conventions" "^0.15.1"
|
||||
"@sentry/core" "10.65.0"
|
||||
|
||||
"@sentry/browser@10.65.0":
|
||||
version "10.65.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-10.65.0.tgz#e2734a2effe051a9005afdd914fc07c68262f627"
|
||||
integrity sha512-XUDDsx0qxzeIlcOu1fDEqTcDl0eiOqghsgV+ReuuNP4jYjZ9kUQxE3rXWM5mlT1pBi4VaQ4FHqvQZZrRXy+oDw==
|
||||
dependencies:
|
||||
"@sentry/browser-utils" "10.65.0"
|
||||
"@sentry/conventions" "^0.15.1"
|
||||
"@sentry/core" "10.65.0"
|
||||
"@sentry/feedback" "10.65.0"
|
||||
"@sentry/replay" "10.65.0"
|
||||
"@sentry/replay-canvas" "10.65.0"
|
||||
|
||||
"@sentry/conventions@^0.15.1":
|
||||
version "0.15.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/conventions/-/conventions-0.15.1.tgz#5b8888862d1e444678938f5afdd7842bca42f7cc"
|
||||
integrity sha512-ZLP8bRdMON3prWE2tJyImuYscCxdcJeIPIhrOs/rgyFm3C1nCh1B6gdvPj3AZ5zW08oSFFCsq7T+tYEW3h8MNA==
|
||||
|
||||
"@sentry/core@10.65.0":
|
||||
version "10.65.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-10.65.0.tgz#a98cfd6e138d9658dd42d050902837ff591452e8"
|
||||
integrity sha512-3aqtmM5NgNGo45BNaaBzi0LPQZAw//NEL4HKS5fXm12pJMa4KEkze8DEKnkTEIrGnWaOJKamecHKlnNg/Mqf/Q==
|
||||
dependencies:
|
||||
"@sentry/conventions" "^0.15.1"
|
||||
|
||||
"@sentry/feedback@10.65.0":
|
||||
version "10.65.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/feedback/-/feedback-10.65.0.tgz#a9418cc77c835e3a74cdc3fad2fb1098ecbc3887"
|
||||
integrity sha512-ck8h7wgd3F3bYNk0v1OgohmyLBeXcKxqlfBJRtQq4k6KZUq+pXimOG7ckNguVMYjCo3PEfuG+ckKc21yqotKug==
|
||||
dependencies:
|
||||
"@sentry/core" "10.65.0"
|
||||
|
||||
"@sentry/react@^10.65.0":
|
||||
version "10.65.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/react/-/react-10.65.0.tgz#83552b6e136d827782915bf4002ff5916dc11ccc"
|
||||
integrity sha512-fvHxpuvid0wt9/1N3itcKDyKOjqmYHw3MBSt5Pki3Iz4CL2CmgQp9ZFv/CA7UhMnEvn2Gd+Qc2UKxujZWd8FLg==
|
||||
dependencies:
|
||||
"@sentry/browser" "10.65.0"
|
||||
"@sentry/conventions" "^0.15.1"
|
||||
"@sentry/core" "10.65.0"
|
||||
|
||||
"@sentry/replay-canvas@10.65.0":
|
||||
version "10.65.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/replay-canvas/-/replay-canvas-10.65.0.tgz#5ff20832ae8acacd38fe7f154dd7ac6c6cad1af2"
|
||||
integrity sha512-A7X3RVk1Gk+knK8Ip/2EjejckNCLgCfRZo6eGlsy6qyz904KBpYmys1a0o7QkzFRjhIndjHAfcVxwt6jSLJlrQ==
|
||||
dependencies:
|
||||
"@sentry/core" "10.65.0"
|
||||
"@sentry/replay" "10.65.0"
|
||||
|
||||
"@sentry/replay@10.65.0":
|
||||
version "10.65.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-10.65.0.tgz#8ed1255349e32faeac786e4ca2f4c2f56b98e64e"
|
||||
integrity sha512-aW988CcQBNArbOMzOFOziipHz6uQyXSa4i5CPWsu+nhVPTJHafosi5Lv9n6NM/icDX5e23VdnX6mZd8SyJuo8A==
|
||||
dependencies:
|
||||
"@sentry/browser-utils" "10.65.0"
|
||||
"@sentry/core" "10.65.0"
|
||||
|
||||
"@sinclair/typebox@^0.34.0":
|
||||
version "0.34.41"
|
||||
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.34.41.tgz#aa51a6c1946df2c5a11494a2cdb9318e026db16c"
|
||||
|
||||
Reference in New Issue
Block a user