Skip to content

Commit d425ecd

Browse files
committed
feat: implement unified logging system with LogRocket integration
MAJOR IMPROVEMENT: Replace all scattered console.log statements with a centralized, professional logging system. New unified logger features: - ✅ Consistent formatting with emojis and colors - ✅ Multiple log levels (debug, info, warn, error, critical) - ✅ Automatic LogRocket integration for production monitoring - ✅ Context-aware logging (PAGE_SAVE, VERSION_SAVE, API, USER, etc.) - ✅ Structured data logging for better debugging - ✅ Works in both client and server environments Applied to critical page saving flow: - API endpoint (/api/pages PUT) - Complete request/response logging - Version saving system - Detailed process tracking - Client-side save function - User action and API call logging - Error handling - Proper error categorization and reporting This provides absolute simplicity while ensuring comprehensive monitoring and debugging capabilities. All logs go to both console (development) and LogRocket (production) automatically.
1 parent 6ffcdf4 commit d425ecd

File tree

4 files changed

+294
-24
lines changed

4 files changed

+294
-24
lines changed

app/api/pages/route.ts

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { NextRequest, NextResponse } from 'next/server';
77
import { getUserIdFromRequest, createApiResponse, createErrorResponse } from '../auth-helper';
88
import { getFirebaseAdmin } from '../../firebase/firebaseAdmin';
99
import { getCollectionName } from '../../utils/environmentConfig';
10+
import logger from '../../utils/unifiedLogger';
1011

1112
interface PageData {
1213
id?: string;
@@ -314,42 +315,81 @@ export async function POST(request: NextRequest) {
314315

315316
// PUT endpoint - Update an existing page
316317
export async function PUT(request: NextRequest) {
318+
logger.apiRequest('PUT', '/api/pages');
319+
317320
try {
321+
logger.debug('Initializing Firebase Admin', undefined, 'PAGE_SAVE');
318322
const admin = getFirebaseAdmin();
319323
const db = admin.firestore();
320324

325+
logger.debug('Getting authenticated user', undefined, 'PAGE_SAVE');
321326
const currentUserId = await getUserIdFromRequest(request);
327+
322328
if (!currentUserId) {
323-
console.error('🔴 Page save failed: No authenticated user found');
324-
console.error('🔴 Request headers:', Object.fromEntries(request.headers.entries()));
325-
console.error('🔴 Request cookies:', request.cookies.getAll());
329+
logger.error('Authentication failed - no user found', {
330+
headers: Object.fromEntries(request.headers.entries()),
331+
cookies: request.cookies.getAll()
332+
}, 'PAGE_SAVE');
326333
return createErrorResponse('UNAUTHORIZED', 'Authentication required. Please log in again.');
327334
}
328335

336+
logger.debug('Parsing request body', undefined, 'PAGE_SAVE');
329337
const body = await request.json();
330338
const { id, title, content, location, groupId, customDate } = body;
331339

340+
logger.info('Page save request', {
341+
pageId: id,
342+
title: title ? `"${title}"` : 'undefined',
343+
hasContent: !!content,
344+
contentLength: content ? JSON.stringify(content).length : 0,
345+
hasLocation: !!location,
346+
groupId,
347+
customDate,
348+
userId: currentUserId
349+
}, 'PAGE_SAVE');
350+
332351
if (!id) {
352+
logger.error('No page ID provided', undefined, 'PAGE_SAVE');
333353
return createErrorResponse('BAD_REQUEST', 'Page ID is required');
334354
}
335355

356+
logger.debug('Loading page document', {
357+
collection: getCollectionName('pages'),
358+
pageId: id
359+
}, 'PAGE_SAVE');
360+
336361
// Get the existing page
337362
const pageRef = db.collection(getCollectionName('pages')).doc(id);
338363
const pageDoc = await pageRef.get();
339364

365+
logger.debug('Page document loaded', { exists: pageDoc.exists }, 'PAGE_SAVE');
366+
340367
if (!pageDoc.exists) {
368+
logger.error('Page not found', { pageId: id }, 'PAGE_SAVE');
341369
return createErrorResponse('NOT_FOUND', 'Page not found');
342370
}
343371

344372
const pageData = pageDoc.data();
373+
logger.debug('Page data loaded', {
374+
userId: pageData.userId,
375+
title: pageData.title,
376+
hasContent: !!pageData.content,
377+
lastModified: pageData.lastModified,
378+
deleted: pageData.deleted
379+
}, 'PAGE_SAVE');
345380

346381
// Check ownership
347382
if (pageData.userId !== currentUserId) {
383+
logger.error('Permission denied - user does not own page', {
384+
pageUserId: pageData.userId,
385+
currentUserId: currentUserId
386+
}, 'PAGE_SAVE');
348387
return createErrorResponse('FORBIDDEN', 'You can only edit your own pages');
349388
}
350389

351390
// Check if page is deleted
352391
if (pageData.deleted) {
392+
logger.error('Cannot edit deleted page', { pageId: id }, 'PAGE_SAVE');
353393
return createErrorResponse('BAD_REQUEST', 'Cannot edit deleted pages');
354394
}
355395

@@ -383,9 +423,10 @@ export async function PUT(request: NextRequest) {
383423

384424
// If content is being updated, use the version saving system to create activity records
385425
if (content !== undefined) {
386-
console.log('🔍 Content update detected, using version saving system for activity tracking');
426+
logger.info('Content update detected - using version saving system', { pageId: id }, 'PAGE_SAVE');
387427

388428
// Get current user data for version saving
429+
logger.debug('Loading user profile for version save', { userId: currentUserId }, 'PAGE_SAVE');
389430
const { getUserProfile } = await import('../../firebase/database/users');
390431
const currentUser = await getUserProfile(currentUserId);
391432

@@ -400,14 +441,30 @@ export async function PUT(request: NextRequest) {
400441
groupId: groupId
401442
};
402443

444+
logger.debug('Calling saveNewVersion', {
445+
pageId: id,
446+
username: versionData.username,
447+
hasContent: !!content,
448+
contentLength: JSON.stringify(content).length
449+
}, 'PAGE_SAVE');
450+
403451
// Save new version (this creates activity records and updates lastDiff)
404452
const versionResult = await saveNewVersion(id, versionData);
405453

406454
if (!versionResult || !versionResult.success) {
407-
console.error('Failed to save version:', versionResult?.error || 'Version save returned null');
455+
logger.error('Version save failed', {
456+
pageId: id,
457+
error: versionResult?.error || 'Version save returned null',
458+
versionResult
459+
}, 'PAGE_SAVE');
408460
return createErrorResponse('INTERNAL_ERROR', 'Failed to save page version');
409461
}
410462

463+
logger.info('Version saved successfully', {
464+
pageId: id,
465+
versionId: versionResult?.versionId
466+
}, 'PAGE_SAVE');
467+
411468
// Update any additional metadata (title, location) that wasn't handled by saveNewVersion
412469
const metadataUpdate: any = {};
413470
if (title !== undefined) {
@@ -483,20 +540,24 @@ export async function PUT(request: NextRequest) {
483540
}
484541
}
485542

543+
logger.info('Page save completed successfully', {
544+
pageId: id,
545+
updateFields: Object.keys(updateData)
546+
}, 'PAGE_SAVE');
547+
486548
return createApiResponse({
487549
id,
488550
...updateData,
489551
message: 'Page updated successfully'
490552
});
491553

492554
} catch (error: any) {
493-
console.error('Error updating page:', error);
494-
console.error('Error details:', {
495-
message: error.message,
555+
logger.critical('Page save failed with error', {
556+
error: error.message,
496557
stack: error.stack,
497558
name: error.name,
498-
pageId: body.id
499-
});
559+
pageId: body?.id
560+
}, 'PAGE_SAVE');
500561

501562
// Don't expose internal errors that might cause session issues
502563
const userMessage = error.message?.includes('permission') || error.message?.includes('auth')

app/components/pages/PageView.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { TextSelectionProvider } from "../../providers/TextSelectionProvider";
1313
import { PageProvider } from "../../contexts/PageContext";
1414
import { useRecentPages } from "../../contexts/RecentPagesContext";
1515
import { useLineSettings } from "../../contexts/LineSettingsContext";
16-
import { createLogger } from '../../utils/logger';
16+
import logger from '../../utils/unifiedLogger';
1717

1818
// UI Components
1919
import PublicLayout from "../layout/PublicLayout";
@@ -620,22 +620,22 @@ export default function PageView({
620620
// No need for handleSetIsEditing - always in edit mode
621621

622622
const handleSave = useCallback(async () => {
623-
console.log('🚨 SAVE DEBUG: handleSave called', { pageId, hasPage: !!page, title });
623+
logger.userAction('Page save initiated', { pageId, hasPage: !!page, title });
624624

625625
if (!page || !pageId) {
626-
console.log('🚨 SAVE DEBUG: Early return - no page or pageId');
626+
logger.warn('Save aborted - no page or pageId', { pageId, hasPage: !!page });
627627
return;
628628
}
629629

630630
// Validate title is not empty
631631
if (!title || title.trim() === '') {
632-
console.log('🚨 SAVE DEBUG: Early return - no title');
632+
logger.warn('Save aborted - no title provided', { pageId });
633633
setTitleError("Title is required");
634634
setError("Please add a title before saving");
635635
return;
636636
}
637637

638-
console.log('🚨 SAVE DEBUG: Starting save process...');
638+
logger.info('Starting page save process', { pageId, title });
639639
setIsSaving(true);
640640
setError(null);
641641
setTitleError(null);
@@ -653,7 +653,12 @@ export default function PageView({
653653
customDate: customDate
654654
};
655655

656-
console.log('🚨 SAVE DEBUG: Calling API route with data:', { ...updateData, content: '(content omitted)' });
656+
logger.apiRequest('PUT', '/api/pages', {
657+
pageId: id,
658+
title,
659+
hasContent: !!content,
660+
contentLength: editorStateJSON.length
661+
});
657662

658663
const response = await fetch('/api/pages', {
659664
method: 'PUT',
@@ -665,7 +670,7 @@ export default function PageView({
665670

666671
if (!response.ok) {
667672
const errorData = await response.json().catch(() => ({}));
668-
console.error('🚨 SAVE DEBUG: API error response:', errorData);
673+
logger.apiResponse('PUT', '/api/pages', response.status, errorData);
669674

670675
// Handle authentication errors specifically
671676
if (response.status === 401) {
@@ -677,7 +682,7 @@ export default function PageView({
677682
}
678683

679684
const result = await response.json();
680-
console.log('🚨 SAVE DEBUG: API response:', result);
685+
logger.apiResponse('PUT', '/api/pages', response.status, result);
681686

682687
if (!result.success) {
683688
throw new Error(result.message || 'Failed to update page');
@@ -710,7 +715,7 @@ export default function PageView({
710715
}
711716

712717
// Clear unsaved changes flag and stay in always-editable mode
713-
console.log('🚨 SAVE DEBUG: Save successful, clearing unsaved changes flag');
718+
logger.pageSave(pageId, true, { title });
714719
setHasUnsavedChanges(false);
715720
setError(null);
716721

@@ -721,7 +726,7 @@ export default function PageView({
721726
// Page data should already be updated after save
722727
// No need to reload since the save operation updates the page state
723728
} catch (error) {
724-
console.error("Error saving page:", error);
729+
logger.pageSave(pageId, false, { error: error.message, title });
725730
setError("Failed to save page. Please try again.");
726731
} finally {
727732
setIsSaving(false);

app/firebase/database/versions.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { extractLinksFromNodes } from "./links";
1717
import { recordUserActivity } from "../streaks";
1818
import { hasContentChangedSync } from "../../utils/diffService";
1919
import { getCollectionName } from "../../utils/environmentConfig";
20+
import logger from "../../utils/unifiedLogger";
2021

2122
import type { PageVersion } from "../../types/database";
2223

@@ -290,13 +291,16 @@ await setDoc(doc(db, getCollectionName("pages"), pageId), {
290291
*/
291292
export const saveNewVersion = async (pageId: string, data: any): Promise<any> => {
292293
try {
293-
console.log('🚨 ACTIVITY DEBUG: saveNewVersion called with pageId:', pageId);
294-
console.log('🚨 ACTIVITY DEBUG: saveNewVersion data:', { ...data, content: '(content omitted)' });
295-
console.log('🚨 ACTIVITY DEBUG: Starting version save process...');
294+
logger.info('Starting version save process', {
295+
pageId,
296+
userId: data.userId,
297+
username: data.username,
298+
hasContent: !!data.content
299+
}, 'VERSION_SAVE');
296300

297301
// Validate content to prevent saving empty versions
298302
if (!data.content) {
299-
console.error("Cannot save empty content");
303+
logger.error("Cannot save empty content", { pageId }, 'VERSION_SAVE');
300304
return null;
301305
}
302306

0 commit comments

Comments
 (0)