Implement centralized logging with RMABLogger

Replaces scattered console statements with a unified RMABLogger across backend API routes and services. Adds LOG_LEVEL-based filtering, job-aware database persistence, and context-based logging. Updates documentation to describe the new logging system and usage patterns. Also documents qBittorrent CSRF header fix
This commit is contained in:
kikootwo
2026-01-12 12:45:48 -05:00
parent ba5f5cf7d6
commit 682836237b
118 changed files with 1623 additions and 1079 deletions
+11 -11
View File
@@ -6,7 +6,7 @@
*/
import { prisma } from '../db';
import { createJobLogger } from '../utils/job-logger';
import { RMABLogger } from '../utils/logger';
export interface AudibleRefreshPayload {
jobId?: string;
@@ -15,9 +15,9 @@ export interface AudibleRefreshPayload {
export async function processAudibleRefresh(payload: AudibleRefreshPayload): Promise<any> {
const { jobId, scheduledJobId } = payload;
const logger = jobId ? createJobLogger(jobId, 'AudibleRefresh') : null;
const logger = RMABLogger.forJob(jobId, 'AudibleRefresh');
await logger?.info('Starting Audible data refresh...');
logger.info('Starting Audible data refresh...');
const { getAudibleService } = await import('../integrations/audible.service');
const { getThumbnailCacheService } = await import('../services/thumbnail-cache.service');
@@ -40,13 +40,13 @@ export async function processAudibleRefresh(payload: AudibleRefreshPayload): Pro
newReleaseRank: null,
},
});
await logger?.info('Cleared previous popular/new-release flags in audible_cache');
logger.info('Cleared previous popular/new-release flags in audible_cache');
// Fetch popular and new releases - 200 items each
const popular = await audibleService.getPopularAudiobooks(200);
const newReleases = await audibleService.getNewReleases(200);
await logger?.info(`Fetched ${popular.length} popular, ${newReleases.length} new releases from Audible`);
logger.info(`Fetched ${popular.length} popular, ${newReleases.length} new releases from Audible`);
// Persist to audible_cache
let popularSaved = 0;
@@ -99,7 +99,7 @@ export async function processAudibleRefresh(payload: AudibleRefreshPayload): Pro
popularSaved++;
} catch (error) {
await logger?.error(`Failed to save popular audiobook ${audiobook.title}: ${error instanceof Error ? error.message : 'Unknown error'}`);
logger.error(`Failed to save popular audiobook ${audiobook.title}: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
@@ -149,20 +149,20 @@ export async function processAudibleRefresh(payload: AudibleRefreshPayload): Pro
newReleasesSaved++;
} catch (error) {
await logger?.error(`Failed to save new release ${audiobook.title}: ${error instanceof Error ? error.message : 'Unknown error'}`);
logger.error(`Failed to save new release ${audiobook.title}: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
await logger?.info(`Saved ${popularSaved} popular and ${newReleasesSaved} new releases to audible_cache`);
logger.info(`Saved ${popularSaved} popular and ${newReleasesSaved} new releases to audible_cache`);
// Cleanup unused thumbnails
await logger?.info('Cleaning up unused thumbnails...');
logger.info('Cleaning up unused thumbnails...');
const allActiveAsins = await prisma.audibleCache.findMany({
select: { asin: true },
});
const activeAsinSet = new Set(allActiveAsins.map(item => item.asin));
const deletedCount = await thumbnailCache.cleanupUnusedThumbnails(activeAsinSet);
await logger?.info(`Cleanup complete: ${deletedCount} unused thumbnails removed`);
logger.info(`Cleanup complete: ${deletedCount} unused thumbnails removed`);
return {
success: true,
@@ -172,7 +172,7 @@ export async function processAudibleRefresh(payload: AudibleRefreshPayload): Pro
thumbnailsDeleted: deletedCount,
};
} catch (error) {
await logger?.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
logger.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
throw error;
}
}