fix: Better logging and revie system of debug

This commit is contained in:
Julien Froidefond
2025-02-23 22:19:24 +01:00
parent c7b2621946
commit 66e1db7788
11 changed files with 70 additions and 110 deletions

1
.gitignore vendored
View File

@@ -37,6 +37,7 @@ next-env.d.ts
.vscode .vscode
.cache .cache
debug-logs
# Environment variables # Environment variables
.env .env

View File

@@ -1,31 +0,0 @@
[
{
"url": "books/ondeck",
"startTime": 2885483.439666003,
"endTime": 2886906.0345830023,
"fromCache": false,
"duration": 1422.59491699934,
"timestamp": "2025-02-23T14:10:34.889Z"
},
{
"url": "home-on-deck",
"startTime": 2885483.3969579935,
"endTime": 2886915.6758749783,
"fromCache": true,
"cacheType": "HOME",
"duration": 1432.2789169847965,
"timestamp": "2025-02-23T14:10:34.901Z"
},
{
"url": "Page Render: HomePage",
"startTime": 2885485.3594990075,
"endTime": 2886935.9214159846,
"duration": 1450.5619169771671,
"timestamp": "2025-02-23T14:10:34.912Z",
"fromCache": false,
"pageRender": {
"page": "HomePage",
"duration": 1450.5619169771671
}
}
]

View File

@@ -1,23 +0,0 @@
[
{
"url": "series/list",
"startTime": 1555818.8649999797,
"endTime": 1556150.4556659758,
"duration": 331.5906659960747,
"timestamp": "2025-02-23T12:27:42.757Z"
},
{
"url": "libraries",
"startTime": 1556210.246457994,
"endTime": 1556425.7659159899,
"duration": 215.51945799589157,
"timestamp": "2025-02-23T12:27:43.141Z"
},
{
"url": "series/0GNTC1Q53EM9R",
"startTime": 1590829.9988330007,
"endTime": 1591134.537375003,
"duration": 304.5385420024395,
"timestamp": "2025-02-23T12:28:17.719Z"
}
]

View File

@@ -4,7 +4,6 @@ import "@/styles/globals.css";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import ClientLayout from "@/components/layout/ClientLayout"; import ClientLayout from "@/components/layout/ClientLayout";
import { PreferencesProvider } from "@/contexts/PreferencesContext"; import { PreferencesProvider } from "@/contexts/PreferencesContext";
import { DebugWrapper } from "@/components/debug/DebugWrapper";
const inter = Inter({ subsets: ["latin"] }); const inter = Inter({ subsets: ["latin"] });
@@ -117,7 +116,6 @@ export default function RootLayout({ children }: { children: React.ReactNode })
<body className={cn("min-h-screen bg-background font-sans antialiased", inter.className)}> <body className={cn("min-h-screen bg-background font-sans antialiased", inter.className)}>
<PreferencesProvider> <PreferencesProvider>
<ClientLayout>{children}</ClientLayout> <ClientLayout>{children}</ClientLayout>
<DebugWrapper />
</PreferencesProvider> </PreferencesProvider>
</body> </body>
</html> </html>

View File

@@ -2,6 +2,7 @@
import { usePreferences } from "@/contexts/PreferencesContext"; import { usePreferences } from "@/contexts/PreferencesContext";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { usePathname } from "next/navigation";
import { import {
X, X,
Database, Database,
@@ -46,10 +47,10 @@ function formatDuration(duration: number) {
} }
export function DebugInfo() { export function DebugInfo() {
const { preferences } = usePreferences();
const [logs, setLogs] = useState<RequestTiming[]>([]); const [logs, setLogs] = useState<RequestTiming[]>([]);
const [isMinimized, setIsMinimized] = useState(false); const [isMinimized, setIsMinimized] = useState(false);
const [isRefreshing, setIsRefreshing] = useState(false); const [isRefreshing, setIsRefreshing] = useState(false);
const pathname = usePathname();
const fetchLogs = async () => { const fetchLogs = async () => {
try { try {
@@ -66,9 +67,21 @@ export function DebugInfo() {
} }
}; };
// Rafraîchir les logs au montage et à chaque changement de page
useEffect(() => { useEffect(() => {
fetchLogs(); fetchLogs();
}, []); }, [pathname]);
// Rafraîchir les logs périodiquement si la fenêtre n'est pas minimisée
useEffect(() => {
if (isMinimized) return;
const interval = setInterval(() => {
fetchLogs();
}, 5000); // Rafraîchir toutes les 5 secondes
return () => clearInterval(interval);
}, [isMinimized]);
const clearLogs = async () => { const clearLogs = async () => {
try { try {
@@ -83,12 +96,19 @@ export function DebugInfo() {
return ( return (
<div <div
className={`fixed bottom-4 right-4 bg-zinc-900 border border-zinc-700 rounded-lg shadow-lg p-4 text-zinc-100 ${ className={`fixed bottom-4 right-4 bg-zinc-900 border border-zinc-700 rounded-lg shadow-lg p-4 text-zinc-100 z-50 ${
isMinimized ? "w-auto" : "w-[800px] max-h-[50vh] overflow-auto" isMinimized ? "w-auto" : "w-[800px] max-h-[50vh] overflow-auto"
}`} }`}
> >
<div className="flex items-center justify-between mb-4 sticky top-0 bg-zinc-900 pb-2"> <div className="flex items-center justify-between mb-4 sticky top-0 bg-zinc-900 pb-2">
<h2 className="font-bold text-lg">DEBUG !</h2> <div className="flex items-center gap-2">
<h2 className="font-bold text-lg">DEBUG</h2>
{!isMinimized && (
<span className="text-xs text-zinc-400">
{sortedLogs.length} entrée{sortedLogs.length > 1 ? "s" : ""}
</span>
)}
</div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<button <button
onClick={fetchLogs} onClick={fetchLogs}

View File

@@ -5,7 +5,6 @@ import { DebugInfo } from "./DebugInfo";
export function DebugWrapper() { export function DebugWrapper() {
const { preferences } = usePreferences(); const { preferences } = usePreferences();
console.log(preferences);
if (!preferences.debug) { if (!preferences.debug) {
return null; return null;
} }

View File

@@ -11,6 +11,7 @@ import { PreferencesProvider } from "@/contexts/PreferencesContext";
import { registerServiceWorker } from "@/lib/registerSW"; import { registerServiceWorker } from "@/lib/registerSW";
import { NetworkStatus } from "../ui/NetworkStatus"; import { NetworkStatus } from "../ui/NetworkStatus";
import { LoadingBar } from "@/components/ui/loading-bar"; import { LoadingBar } from "@/components/ui/loading-bar";
import { DebugWrapper } from "@/components/debug/DebugWrapper";
// Routes qui ne nécessitent pas d'authentification // Routes qui ne nécessitent pas d'authentification
const publicRoutes = ["/login", "/register"]; const publicRoutes = ["/login", "/register"];
@@ -71,6 +72,7 @@ export default function ClientLayout({ children }: { children: React.ReactNode }
<InstallPWA /> <InstallPWA />
<Toaster /> <Toaster />
<NetworkStatus /> <NetworkStatus />
<DebugWrapper />
</div> </div>
</PreferencesProvider> </PreferencesProvider>
</ThemeProvider> </ThemeProvider>

View File

@@ -28,25 +28,25 @@ export function PreferencesProvider({ children }: { children: React.ReactNode })
const [preferences, setPreferences] = useState<UserPreferences>(defaultPreferences); const [preferences, setPreferences] = useState<UserPreferences>(defaultPreferences);
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
useEffect(() => { const fetchPreferences = async () => {
const fetchPreferences = async () => { try {
try { const response = await fetch("/api/preferences");
const response = await fetch("/api/preferences"); if (!response.ok) throw new Error("Erreur lors de la récupération des préférences");
if (!response.ok) throw new Error("Erreur lors de la récupération des préférences"); const data = await response.json();
const data = await response.json(); setPreferences({
setPreferences({ ...defaultPreferences,
...defaultPreferences, ...data,
...data, });
}); } catch (error) {
} catch (error) { console.error("Erreur lors de la récupération des préférences:", error);
console.error("Erreur lors de la récupération des préférences:", error); // En cas d'erreur, on garde les préférences par défaut
// En cas d'erreur, on garde les préférences par défaut setPreferences(defaultPreferences);
setPreferences(defaultPreferences); } finally {
} finally { setIsLoading(false);
setIsLoading(false); }
} };
};
useEffect(() => {
fetchPreferences(); fetchPreferences();
}, []); }, []);
@@ -64,14 +64,17 @@ export function PreferencesProvider({ children }: { children: React.ReactNode })
const updatedPreferences = await response.json(); const updatedPreferences = await response.json();
setPreferences((prev) => { setPreferences((prev) => ({
const newState = { ...prev,
...prev, ...updatedPreferences,
...updatedPreferences, }));
};
return newState; // Forcer un rafraîchissement des préférences
}); await fetchPreferences();
return updatedPreferences;
} catch (error) { } catch (error) {
console.error("Erreur lors de la mise à jour des préférences:", error);
throw error; throw error;
} }
}; };

View File

@@ -7,9 +7,8 @@ export function withPageTiming(pageName: string, Component: PageComponent) {
const start = performance.now(); const start = performance.now();
const result = await Promise.resolve(Component(props)); const result = await Promise.resolve(Component(props));
const duration = performance.now() - start; const duration = performance.now() - start;
// Log le temps de rendu // Log le temps de rendu
await DebugService.logPageRender(pageName, duration); await DebugService.logPageRender(pageName + JSON.stringify(props.params), duration);
return result; return result;
}; };

View File

@@ -53,34 +53,12 @@ export abstract class BaseApiService {
type: CacheType = "DEFAULT" type: CacheType = "DEFAULT"
): Promise<T> { ): Promise<T> {
const cacheService = await getServerCacheService(); const cacheService = await getServerCacheService();
const startTime = performance.now();
try { try {
const result = await cacheService.getOrSet(key, fetcher, type); const result = await cacheService.getOrSet(key, fetcher, type);
const endTime = performance.now();
// Log la requête avec l'indication du cache
await DebugService.logRequest({
url: key,
startTime,
endTime,
fromCache: true,
cacheType: type,
});
return result; return result;
} catch (error) { } catch (error) {
const endTime = performance.now();
// Log aussi les erreurs
await DebugService.logRequest({
url: key,
startTime,
endTime,
fromCache: true,
cacheType: type,
});
throw error; throw error;
} }
} }

View File

@@ -1,6 +1,7 @@
import fs from "fs"; import fs from "fs";
import path from "path"; import path from "path";
import { PreferencesService } from "./preferences.service"; import { PreferencesService } from "./preferences.service";
import { DebugService } from "./debug.service";
type CacheMode = "file" | "memory"; type CacheMode = "file" | "memory";
@@ -370,13 +371,26 @@ class ServerCacheService {
fetcher: () => Promise<T>, fetcher: () => Promise<T>,
type: keyof typeof ServerCacheService.DEFAULT_TTL = "DEFAULT" type: keyof typeof ServerCacheService.DEFAULT_TTL = "DEFAULT"
): Promise<T> { ): Promise<T> {
const startTime = performance.now();
const cached = this.get(key); const cached = this.get(key);
if (cached !== null) { if (cached !== null) {
const endTime = performance.now();
// Log la requête avec l'indication du cache
await DebugService.logRequest({
url: key,
startTime,
endTime,
fromCache: true,
cacheType: type,
});
return cached as T; return cached as T;
} }
try { try {
const data = await fetcher(); const data = await fetcher();
this.set(key, data, type); this.set(key, data, type);
return data; return data;
} catch (error) { } catch (error) {