fix: Better logging and revie system of debug
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -37,6 +37,7 @@ next-env.d.ts
|
|||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
.cache
|
.cache
|
||||||
|
debug-logs
|
||||||
|
|
||||||
# Environment variables
|
# Environment variables
|
||||||
.env
|
.env
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user