feat: add logging enhancements by integrating pino and pino-pretty for improved error tracking and debugging across the application
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import NextAuth from "next-auth";
|
||||
import Credentials from "next-auth/providers/credentials";
|
||||
import { AuthServerService } from "@/lib/services/auth-server.service";
|
||||
import logger from "@/lib/logger";
|
||||
|
||||
export const { handlers, auth, signIn, signOut } = NextAuth({
|
||||
providers: [
|
||||
@@ -28,7 +29,7 @@ export const { handlers, auth, signIn, signOut } = NextAuth({
|
||||
roles: userData.roles,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Auth error:", error);
|
||||
logger.error({ err: error }, "Auth error");
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
34
src/lib/logger.ts
Normal file
34
src/lib/logger.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import pino from 'pino';
|
||||
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
|
||||
const logger = pino({
|
||||
level: isProduction ? 'info' : 'debug',
|
||||
...(isProduction
|
||||
? {}
|
||||
: {
|
||||
transport: {
|
||||
target: 'pino-pretty',
|
||||
options: {
|
||||
colorize: true,
|
||||
translateTime: 'SYS:dd/mm/yyyy HH:MM:ss',
|
||||
ignore: 'pid,hostname',
|
||||
singleLine: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
formatters: {
|
||||
level: (label) => {
|
||||
return { level: label.toUpperCase() };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Prevent memory leaks in development (Node.js runtime only)
|
||||
if (!isProduction && typeof process.stdout !== 'undefined') {
|
||||
process.stdout.setMaxListeners?.(20);
|
||||
process.stderr.setMaxListeners?.(20);
|
||||
}
|
||||
|
||||
export default logger;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { NextRequest } from "next/server";
|
||||
import { getToken } from "next-auth/jwt";
|
||||
import logger from "@/lib/logger";
|
||||
|
||||
export async function getAuthSession(request: NextRequest) {
|
||||
try {
|
||||
@@ -20,7 +21,7 @@ export async function getAuthSession(request: NextRequest) {
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Auth error in middleware:", error);
|
||||
logger.error({ err: error }, "Auth error in middleware");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import logger from "@/lib/logger";
|
||||
|
||||
export const registerServiceWorker = async () => {
|
||||
if (typeof window === "undefined" || !("serviceWorker" in navigator)) {
|
||||
return;
|
||||
@@ -5,8 +7,8 @@ export const registerServiceWorker = async () => {
|
||||
|
||||
try {
|
||||
await navigator.serviceWorker.register("/sw.js");
|
||||
// console.log("Service Worker registered with scope:", registration.scope);
|
||||
// logger.info("Service Worker registered with scope:", registration.scope);
|
||||
} catch (error) {
|
||||
console.error("Service Worker registration failed:", error);
|
||||
logger.error({ err: error }, "Service Worker registration failed:");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@ import { RequestMonitorService } from "./request-monitor.service";
|
||||
import { RequestQueueService } from "./request-queue.service";
|
||||
import { CircuitBreakerService } from "./circuit-breaker.service";
|
||||
import { PreferencesService } from "./preferences.service";
|
||||
import logger from "@/lib/logger";
|
||||
|
||||
export type { CacheType };
|
||||
|
||||
@@ -42,14 +43,14 @@ export abstract class BaseApiService {
|
||||
const preferences = await PreferencesService.getPreferences();
|
||||
return preferences.komgaMaxConcurrentRequests;
|
||||
} catch (error) {
|
||||
console.error('Failed to get preferences for request queue:', error);
|
||||
logger.error({ err: error }, 'Failed to get preferences for request queue');
|
||||
return 5; // Valeur par défaut
|
||||
}
|
||||
});
|
||||
|
||||
this.requestQueueInitialized = true;
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize request queue:', error);
|
||||
logger.error({ err: error }, 'Failed to initialize request queue');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +69,7 @@ export abstract class BaseApiService {
|
||||
const preferences = await PreferencesService.getPreferences();
|
||||
return preferences.circuitBreakerConfig;
|
||||
} catch (error) {
|
||||
console.error('Failed to get preferences for circuit breaker:', error);
|
||||
logger.error({ err: error }, 'Failed to get preferences for circuit breaker');
|
||||
return {
|
||||
threshold: 5,
|
||||
timeout: 30000,
|
||||
@@ -79,7 +80,7 @@ export abstract class BaseApiService {
|
||||
|
||||
this.circuitBreakerInitialized = true;
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize circuit breaker:', error);
|
||||
logger.error({ err: error }, 'Failed to initialize circuit breaker');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +104,7 @@ export abstract class BaseApiService {
|
||||
if (error instanceof AppError && error.code === ERROR_CODES.KOMGA.MISSING_CONFIG) {
|
||||
throw error;
|
||||
}
|
||||
console.error("Erreur lors de la récupération de la configuration:", error);
|
||||
logger.error({ err: error }, "Erreur lors de la récupération de la configuration");
|
||||
throw new AppError(ERROR_CODES.KOMGA.MISSING_CONFIG, {}, error);
|
||||
}
|
||||
}
|
||||
@@ -199,7 +200,7 @@ export abstract class BaseApiService {
|
||||
} catch (fetchError: any) {
|
||||
// Gestion spécifique des erreurs DNS
|
||||
if (fetchError?.cause?.code === 'EAI_AGAIN' || fetchError?.code === 'EAI_AGAIN') {
|
||||
console.error(`DNS resolution failed for ${url}. Retrying with different DNS settings...`);
|
||||
logger.error(`DNS resolution failed for ${url}. Retrying with different DNS settings...`);
|
||||
|
||||
// Retry avec des paramètres DNS différents
|
||||
return await fetch(url, {
|
||||
@@ -218,8 +219,7 @@ export abstract class BaseApiService {
|
||||
|
||||
// Retry automatique sur timeout de connexion (cold start)
|
||||
if (fetchError?.cause?.code === 'UND_ERR_CONNECT_TIMEOUT') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`⏱️ Connection timeout for ${url}. Retrying once (cold start)...`);
|
||||
logger.info(`⏱️ Connection timeout for ${url}. Retrying once (cold start)...`);
|
||||
|
||||
return await fetch(url, {
|
||||
headers,
|
||||
|
||||
@@ -8,6 +8,7 @@ import { ERROR_CODES } from "../../constants/errorCodes";
|
||||
import { AppError } from "../../utils/errors";
|
||||
import { SeriesService } from "./series.service";
|
||||
import type { Series } from "@/types/series";
|
||||
import logger from "@/lib/logger";
|
||||
|
||||
export class BookService extends BaseApiService {
|
||||
private static async getImageCacheMaxAge(): Promise<number> {
|
||||
@@ -16,7 +17,7 @@ export class BookService extends BaseApiService {
|
||||
const maxAge = ttlConfig?.imageCacheMaxAge ?? 2592000;
|
||||
return maxAge;
|
||||
} catch (error) {
|
||||
console.error('[ImageCache] Error fetching TTL config:', error);
|
||||
logger.error({ err: error }, '[ImageCache] Error fetching TTL config');
|
||||
return 2592000; // 30 jours par défaut en cas d'erreur
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Évite l'effet avalanche en coupant les requêtes vers un service défaillant
|
||||
*/
|
||||
import type { CircuitBreakerConfig } from "@/types/preferences";
|
||||
import logger from "@/lib/logger";
|
||||
|
||||
interface CircuitBreakerState {
|
||||
state: 'CLOSED' | 'OPEN' | 'HALF_OPEN';
|
||||
@@ -47,7 +48,7 @@ class CircuitBreaker {
|
||||
resetTimeout: prefConfig.resetTimeout ?? 60000,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error getting circuit breaker config from preferences:', error);
|
||||
logger.error({ err: error }, 'Error getting circuit breaker config from preferences');
|
||||
return this.config;
|
||||
}
|
||||
}
|
||||
@@ -78,8 +79,7 @@ class CircuitBreaker {
|
||||
if (this.state.state === 'HALF_OPEN') {
|
||||
this.state.failureCount = 0;
|
||||
this.state.state = 'CLOSED';
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[CIRCUIT-BREAKER] ✅ Circuit closed - Komga recovered');
|
||||
logger.info('[CIRCUIT-BREAKER] ✅ Circuit closed - Komga recovered');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ class CircuitBreaker {
|
||||
if (this.state.failureCount >= config.failureThreshold) {
|
||||
this.state.state = 'OPEN';
|
||||
this.state.nextAttemptTime = Date.now() + config.resetTimeout;
|
||||
console.warn(`[CIRCUIT-BREAKER] 🔴 Circuit OPEN - Komga failing (${this.state.failureCount} failures, reset in ${config.resetTimeout}ms)`);
|
||||
logger.warn(`[CIRCUIT-BREAKER] 🔴 Circuit OPEN - Komga failing (${this.state.failureCount} failures, reset in ${config.resetTimeout}ms)`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,8 +105,7 @@ class CircuitBreaker {
|
||||
lastFailureTime: 0,
|
||||
nextAttemptTime: 0,
|
||||
};
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[CIRCUIT-BREAKER] 🔄 Circuit reset');
|
||||
logger.info('[CIRCUIT-BREAKER] 🔄 Circuit reset');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { getCurrentUser } from "../auth-utils";
|
||||
import { ERROR_CODES } from "../../constants/errorCodes";
|
||||
import { AppError } from "../../utils/errors";
|
||||
import type { User } from "@/types/komga";
|
||||
import logger from "@/lib/logger";
|
||||
|
||||
export class FavoriteService {
|
||||
private static readonly FAVORITES_CHANGE_EVENT = "favoritesChanged";
|
||||
@@ -38,7 +39,7 @@ export class FavoriteService {
|
||||
});
|
||||
return !!favorite;
|
||||
} catch (error) {
|
||||
console.error("Erreur lors de la vérification du favori:", error);
|
||||
logger.error({ err: error, seriesId }, "Erreur lors de la vérification du favori");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { BaseApiService } from "./base-api.service";
|
||||
import { ERROR_CODES } from "../../constants/errorCodes";
|
||||
import { AppError } from "../../utils/errors";
|
||||
import logger from "@/lib/logger";
|
||||
|
||||
export interface ImageResponse {
|
||||
buffer: Buffer;
|
||||
@@ -23,7 +24,7 @@ export class ImageService extends BaseApiService {
|
||||
contentType,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Erreur lors de la récupération de l'image:", error);
|
||||
logger.error({ err: error }, "Erreur lors de la récupération de l'image");
|
||||
throw new AppError(ERROR_CODES.IMAGE.FETCH_ERROR, {}, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
* Service de monitoring des requêtes concurrentes vers Komga
|
||||
* Permet de tracker le nombre de requêtes actives et d'alerter en cas de charge élevée
|
||||
*/
|
||||
import logger from "@/lib/logger";
|
||||
|
||||
class RequestMonitor {
|
||||
private activeRequests = 0;
|
||||
private readonly thresholds = {
|
||||
@@ -29,12 +31,11 @@ class RequestMonitor {
|
||||
const count = this.activeRequests;
|
||||
|
||||
if (count >= this.thresholds.critical) {
|
||||
console.warn(`[REQUEST-MONITOR] 🔴 CRITICAL concurrency: ${count} active requests`);
|
||||
logger.warn(`[REQUEST-MONITOR] 🔴 CRITICAL concurrency: ${count} active requests`);
|
||||
} else if (count >= this.thresholds.high) {
|
||||
console.warn(`[REQUEST-MONITOR] ⚠️ HIGH concurrency: ${count} active requests`);
|
||||
logger.warn(`[REQUEST-MONITOR] ⚠️ HIGH concurrency: ${count} active requests`);
|
||||
} else if (count >= this.thresholds.warning) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`[REQUEST-MONITOR] ⚡ Warning concurrency: ${count} active requests`);
|
||||
logger.info(`[REQUEST-MONITOR] ⚡ Warning concurrency: ${count} active requests`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Service de gestion de queue pour limiter les requêtes concurrentes vers Komga
|
||||
* Évite de surcharger Komga avec trop de requêtes simultanées
|
||||
*/
|
||||
import logger from "@/lib/logger";
|
||||
|
||||
interface QueuedRequest<T> {
|
||||
execute: () => Promise<T>;
|
||||
@@ -35,7 +36,7 @@ class RequestQueue {
|
||||
try {
|
||||
return await this.getMaxConcurrent();
|
||||
} catch (error) {
|
||||
console.error('Error getting maxConcurrent from preferences, using default:', error);
|
||||
logger.error({ err: error }, 'Error getting maxConcurrent from preferences, using default');
|
||||
return this.maxConcurrent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { ERROR_CODES } from "../../constants/errorCodes";
|
||||
import { AppError } from "../../utils/errors";
|
||||
import type { UserPreferences } from "@/types/preferences";
|
||||
import type { ServerCacheService } from "./server-cache.service";
|
||||
import logger from "@/lib/logger";
|
||||
|
||||
export class SeriesService extends BaseApiService {
|
||||
private static async getImageCacheMaxAge(): Promise<number> {
|
||||
@@ -19,7 +20,7 @@ export class SeriesService extends BaseApiService {
|
||||
const maxAge = ttlConfig?.imageCacheMaxAge ?? 2592000;
|
||||
return maxAge;
|
||||
} catch (error) {
|
||||
console.error('[ImageCache] Error fetching TTL config:', error);
|
||||
logger.error({ err: error }, '[ImageCache] Error fetching TTL config');
|
||||
return 2592000; // 30 jours par défaut en cas d'erreur
|
||||
}
|
||||
}
|
||||
@@ -181,7 +182,7 @@ export class SeriesService extends BaseApiService {
|
||||
"SERIES"
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Erreur lors de la récupération du premier livre:", error);
|
||||
logger.error({ err: error }, "Erreur lors de la récupération du premier livre");
|
||||
throw new AppError(ERROR_CODES.SERIES.FETCH_ERROR, {}, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import fs from "fs";
|
||||
import path from "path";
|
||||
import { PreferencesService } from "./preferences.service";
|
||||
import { getCurrentUser } from "../auth-utils";
|
||||
import logger from "@/lib/logger";
|
||||
|
||||
export type CacheMode = "file" | "memory";
|
||||
|
||||
@@ -52,7 +53,7 @@ class ServerCacheService {
|
||||
const preferences = await PreferencesService.getPreferences();
|
||||
this.setCacheMode(preferences.cacheMode);
|
||||
} catch (error) {
|
||||
console.error("Error initializing cache mode from preferences:", error);
|
||||
logger.error({ err: error }, "Error initializing cache mode from preferences");
|
||||
// Keep default memory mode if preferences can't be loaded
|
||||
}
|
||||
}
|
||||
@@ -93,7 +94,7 @@ class ServerCacheService {
|
||||
try {
|
||||
fs.rmdirSync(itemPath);
|
||||
} catch (error) {
|
||||
console.error(`Could not remove directory ${itemPath}:`, error);
|
||||
logger.error({ err: error, path: itemPath }, `Could not remove directory ${itemPath}`);
|
||||
isEmpty = false;
|
||||
}
|
||||
} else {
|
||||
@@ -109,12 +110,12 @@ class ServerCacheService {
|
||||
isEmpty = false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Could not parse file ${itemPath}:`, error);
|
||||
logger.error({ err: error, path: itemPath }, `Could not parse file ${itemPath}`);
|
||||
// Si le fichier est corrompu, on le supprime
|
||||
try {
|
||||
fs.unlinkSync(itemPath);
|
||||
} catch (error) {
|
||||
console.error(`Could not remove file ${itemPath}:`, error);
|
||||
logger.error({ err: error, path: itemPath }, `Could not remove file ${itemPath}`);
|
||||
isEmpty = false;
|
||||
}
|
||||
}
|
||||
@@ -122,7 +123,7 @@ class ServerCacheService {
|
||||
isEmpty = false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Could not access ${itemPath}:`, error);
|
||||
logger.error({ err: error, path: itemPath }, `Could not access ${itemPath}`);
|
||||
// En cas d'erreur sur le fichier/dossier, on continue
|
||||
isEmpty = false;
|
||||
continue;
|
||||
@@ -197,12 +198,12 @@ class ServerCacheService {
|
||||
this.memoryCache.set(key, cached);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Could not parse file ${itemPath}:`, error);
|
||||
logger.error({ err: error, path: itemPath }, `Could not parse file ${itemPath}`);
|
||||
// Ignore les fichiers corrompus
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Could not access ${itemPath}:`, error);
|
||||
logger.error({ err: error, path: itemPath }, `Could not access ${itemPath}`);
|
||||
// Ignore les erreurs d'accès
|
||||
}
|
||||
}
|
||||
@@ -221,7 +222,7 @@ class ServerCacheService {
|
||||
}
|
||||
fs.writeFileSync(filePath, JSON.stringify(value), "utf-8");
|
||||
} catch (error) {
|
||||
console.error(`Could not write cache file ${filePath}:`, error);
|
||||
logger.error({ err: error, path: filePath }, `Could not write cache file ${filePath}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +247,7 @@ class ServerCacheService {
|
||||
}
|
||||
fs.writeFileSync(filePath, JSON.stringify(cacheData), "utf-8");
|
||||
} catch (error) {
|
||||
console.error(`Error writing cache file ${filePath}:`, error);
|
||||
logger.error({ err: error, path: filePath }, `Error writing cache file ${filePath}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -283,7 +284,7 @@ class ServerCacheService {
|
||||
fs.unlinkSync(filePath);
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error(`Error reading cache file ${filePath}:`, error);
|
||||
logger.error({ err: error, path: filePath }, `Error reading cache file ${filePath}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -317,7 +318,7 @@ class ServerCacheService {
|
||||
isStale: cached.expiry <= Date.now(),
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`Error reading cache file ${filePath}:`, error);
|
||||
logger.error({ err: error, path: filePath }, `Error reading cache file ${filePath}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -392,17 +393,17 @@ class ServerCacheService {
|
||||
try {
|
||||
fs.rmdirSync(itemPath);
|
||||
} catch (error) {
|
||||
console.error(`Could not remove directory ${itemPath}:`, error);
|
||||
logger.error({ err: error, path: itemPath }, `Could not remove directory ${itemPath}`);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
fs.unlinkSync(itemPath);
|
||||
} catch (error) {
|
||||
console.error(`Could not remove file ${itemPath}:`, error);
|
||||
logger.error({ err: error, path: itemPath }, `Could not remove file ${itemPath}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error accessing ${itemPath}:`, error);
|
||||
logger.error({ err: error, path: itemPath }, `Error accessing ${itemPath}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -410,7 +411,7 @@ class ServerCacheService {
|
||||
try {
|
||||
removeDirectory(this.cacheDir);
|
||||
} catch (error) {
|
||||
console.error("Error clearing cache:", error);
|
||||
logger.error({ err: error }, "Error clearing cache");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,8 +444,7 @@ class ServerCacheService {
|
||||
if (process.env.CACHE_DEBUG === 'true') {
|
||||
const icon = isStale ? '⚠️' : '✅';
|
||||
const status = isStale ? 'STALE' : 'HIT';
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`${icon} [CACHE ${status}] ${key} | ${type} | ${(endTime - startTime).toFixed(2)}ms`);
|
||||
logger.debug(`${icon} [CACHE ${status}] ${key} | ${type} | ${(endTime - startTime).toFixed(2)}ms`);
|
||||
}
|
||||
|
||||
// Si le cache est expiré, revalider en background sans bloquer la réponse
|
||||
@@ -458,8 +458,7 @@ class ServerCacheService {
|
||||
|
||||
// Pas de cache du tout, fetch normalement
|
||||
if (process.env.CACHE_DEBUG === 'true') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`❌ [CACHE MISS] ${key} | ${type}`);
|
||||
logger.debug(`❌ [CACHE MISS] ${key} | ${type}`);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -468,8 +467,7 @@ class ServerCacheService {
|
||||
|
||||
const endTime = performance.now();
|
||||
if (process.env.CACHE_DEBUG === 'true') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`💾 [CACHE SET] ${key} | ${type} | ${(endTime - startTime).toFixed(2)}ms`);
|
||||
logger.debug(`💾 [CACHE SET] ${key} | ${type} | ${(endTime - startTime).toFixed(2)}ms`);
|
||||
}
|
||||
|
||||
return data;
|
||||
@@ -494,11 +492,10 @@ class ServerCacheService {
|
||||
|
||||
if (process.env.CACHE_DEBUG === 'true') {
|
||||
const endTime = performance.now();
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`🔄 [CACHE REVALIDATE] ${debugKey} | ${type} | ${(endTime - startTime).toFixed(2)}ms`);
|
||||
logger.debug(`🔄 [CACHE REVALIDATE] ${debugKey} | ${type} | ${(endTime - startTime).toFixed(2)}ms`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`🔴 [CACHE REVALIDATE ERROR] ${debugKey}:`, error);
|
||||
logger.error({ err: error, key: debugKey }, `🔴 [CACHE REVALIDATE ERROR] ${debugKey}`);
|
||||
// Ne pas relancer l'erreur car c'est en background
|
||||
}
|
||||
}
|
||||
@@ -582,7 +579,7 @@ class ServerCacheService {
|
||||
itemCount++;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Could not access ${itemPath}:`, error);
|
||||
logger.error({ err: error, path: itemPath }, `Could not access ${itemPath}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -648,11 +645,11 @@ class ServerCacheService {
|
||||
isExpired: cached.expiry <= Date.now(),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`Could not parse file ${itemPath}:`, error);
|
||||
logger.error({ err: error, path: itemPath }, `Could not parse file ${itemPath}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Could not access ${itemPath}:`, error);
|
||||
logger.error({ err: error, path: itemPath }, `Could not access ${itemPath}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { AuthConfig } from "@/types/auth";
|
||||
import { ERROR_CODES } from "../../constants/errorCodes";
|
||||
import { AppError } from "../../utils/errors";
|
||||
import type { KomgaLibrary } from "@/types/komga";
|
||||
import logger from "@/lib/logger";
|
||||
|
||||
export class TestService extends BaseApiService {
|
||||
static async testConnection(config: AuthConfig): Promise<{ libraries: KomgaLibrary[] }> {
|
||||
@@ -20,7 +21,7 @@ export class TestService extends BaseApiService {
|
||||
const libraries = await response.json();
|
||||
return { libraries };
|
||||
} catch (error) {
|
||||
console.error("Erreur lors du test de connexion:", error);
|
||||
logger.error({ err: error }, "Erreur lors du test de connexion");
|
||||
if (error instanceof AppError) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user