Skip to content

Commit c8bcc15

Browse files
aledlieclaude
andcommitted
refactor(logging): migrate console.log calls to structured logger
- Replace console.log/warn/error with logger.info/warn/error across 14 files - API files: visualizationApi, insightsApi, collaborationApi, analyticsApi, predictionsApi - Components: ErrorBoundary, InsightsPage, HeaderExample, MetricCardExample, NavigationExample - Routes: analytics/index - Examples: DashboardLayoutExample, LoadReports.example, Header.stories - Logger provides context-aware structured logging for future Sentry integration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 88592b9 commit c8bcc15

14 files changed

Lines changed: 55 additions & 42 deletions

File tree

‎src/components/ErrorBoundary/ErrorBoundary.tsx‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
AlertTitle,
1010
} from '@mui/material';
1111
import { ErrorOutline, Refresh } from '@mui/icons-material';
12+
import { logger } from '../../features/dashboard/helpers/logger';
1213

1314
/**
1415
* ErrorBoundary Props
@@ -96,10 +97,8 @@ export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundarySt
9697
* Log error details when component catches an error
9798
*/
9899
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
99-
// Log error to console in development
100-
if (import.meta.env.DEV) {
101-
console.error('ErrorBoundary caught an error:', error, errorInfo);
102-
}
100+
// Log error to structured logger
101+
logger.error('ErrorBoundary', 'ErrorBoundary caught an error', error, { errorInfo });
103102

104103
// Update state with error info
105104
this.setState({

‎src/features/dashboard/api/analyticsApi.ts‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import type {
2020
PredictionSummary,
2121
AnalyticsInsight,
2222
} from '../types/analytics';
23+
import { logger } from '../helpers/logger';
2324

2425
// ============================================================================
2526
// Raw Report Types (from Python analyzer)
@@ -527,17 +528,18 @@ export const analyticsApi = {
527528
const rawData = JSON.parse(text) as unknown;
528529

529530
if (!validateAnalyticsReport(rawData)) {
530-
console.warn('[analyticsApi] Analytics report has invalid structure, using mock data');
531+
logger.warn('analyticsApi', 'Analytics report has invalid structure, using mock data');
531532
return generateMockAnalyticsReport();
532533
}
533534

534535
const data = transformAnalyticsReport(rawData);
535-
console.log(
536-
`[analyticsApi] Loaded analytics report: ${data.riskData.length} risk items, ${data.insights.length} insights`
536+
logger.info(
537+
'analyticsApi',
538+
`Loaded analytics report: ${data.riskData.length} risk items, ${data.insights.length} insights`
537539
);
538540
return data;
539541
} catch (error) {
540-
console.warn(`[analyticsApi] Error loading analytics report:`, error);
542+
logger.warn('analyticsApi', 'Error loading analytics report', { error });
541543
return generateMockAnalyticsReport();
542544
}
543545
},
@@ -579,7 +581,7 @@ export const analyticsApi = {
579581
*/
580582
async dismissInsight(insightId: string): Promise<{ success: boolean }> {
581583
// In a real implementation, this would call a backend API
582-
console.log(`[analyticsApi] Dismissing insight: ${insightId}`);
584+
logger.info('analyticsApi', `Dismissing insight: ${insightId}`);
583585
return { success: true };
584586
},
585587
};

‎src/features/dashboard/api/collaborationApi.ts‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type {
1515
IssueStatus,
1616
User,
1717
} from '../types';
18+
import { logger } from '../helpers/logger';
1819

1920
const API_BASE = '/data/collaboration';
2021

@@ -146,7 +147,7 @@ export async function assignIssue(
146147
userId: string
147148
): Promise<Issue> {
148149
// In production, this would be a POST request
149-
console.log(`Assigning issue ${issueId} to user ${userId}`);
150+
logger.info('collaborationApi', `Assigning issue ${issueId} to user ${userId}`);
150151
// Return mock updated issue
151152
const issues = await fetchIssues();
152153
const issue = issues.find((i) => i.id === issueId);
@@ -162,7 +163,7 @@ export async function updateIssueStatus(
162163
status: IssueStatus
163164
): Promise<Issue> {
164165
// In production, this would be a PATCH request
165-
console.log(`Updating issue ${issueId} status to ${status}`);
166+
logger.info('collaborationApi', `Updating issue ${issueId} status to ${status}`);
166167
const issues = await fetchIssues();
167168
const issue = issues.find((i) => i.id === issueId);
168169
if (!issue) throw new Error('Issue not found');
@@ -178,7 +179,7 @@ export async function addComment(
178179
parentId?: string
179180
): Promise<Comment> {
180181
// In production, this would be a POST request
181-
console.log(`Adding comment to issue ${issueId}`, { text, parentId });
182+
logger.info('collaborationApi', `Adding comment to issue ${issueId}`, { text, parentId });
182183
return {
183184
id: `comment-${Date.now()}`,
184185
issueId,
@@ -198,7 +199,7 @@ export async function addComment(
198199
*/
199200
export async function markActivityAsRead(activityId: string): Promise<void> {
200201
// In production, this would be a PATCH request
201-
console.log(`Marking activity ${activityId} as read`);
202+
logger.info('collaborationApi', `Marking activity ${activityId} as read`);
202203
}
203204

204205
// Mock data generators

‎src/features/dashboard/api/examples/LoadReports.example.tsx‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import { useState, useEffect } from 'react';
99
import { dashboardApi } from '../dashboardApi';
1010
import type { PythonAnalyzerData, ReportLoadError } from '../../types';
11+
import { logger } from '../../helpers/logger';
1112

1213
/**
1314
* Simple loading state component
@@ -155,7 +156,7 @@ export function LoadReportsExample() {
155156
setData(result.data);
156157
setErrors(result.errors);
157158
} catch (error) {
158-
console.error('Fatal error loading reports:', error);
159+
logger.error('LoadReportsExample', 'Fatal error loading reports', error instanceof Error ? error : undefined);
159160
// This would be a network error or catastrophic failure
160161
setErrors([
161162
{
@@ -215,7 +216,7 @@ export function LoadReportsWithCustomPath({ outputsPath }: { outputsPath: string
215216
const result = await dashboardApi.loadAllReports(outputsPath);
216217
setData(result.data);
217218
} catch (error) {
218-
console.error('Error loading reports:', error);
219+
logger.error('LoadReportsWithCustomPath', 'Error loading reports', error instanceof Error ? error : undefined);
219220
} finally {
220221
setLoading(false);
221222
}
@@ -253,7 +254,7 @@ export function LoadIndividualReportsExample() {
253254
const report = await dashboardApi.loadQualityReport('./outputs');
254255
setQuality(report);
255256
} catch (error) {
256-
console.error('Error loading quality report:', error);
257+
logger.error('LoadIndividualReportsExample', 'Error loading quality report', error instanceof Error ? error : undefined);
257258
} finally {
258259
setLoading(false);
259260
}

‎src/features/dashboard/api/insightsApi.ts‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type {
1515
RegenerateResponse,
1616
MetricSnapshot,
1717
} from '../types';
18+
import { logger } from '../helpers/logger';
1819

1920
// ============================================================================
2021
// Raw Python Output Types
@@ -213,7 +214,7 @@ export const insightsApi = {
213214
const response = await fetch(path);
214215
if (!response.ok) {
215216
if (response.status === 404) {
216-
console.warn(`[insightsApi] Insights report not found at ${path}`);
217+
logger.warn('insightsApi', `Insights report not found at ${path}`);
217218
return null;
218219
}
219220
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
@@ -226,10 +227,10 @@ export const insightsApi = {
226227
}
227228

228229
const data = transformInsightsReport(rawData);
229-
console.log(`[insightsApi] Loaded insights report: ${data.summary.total} insights`);
230+
logger.info('insightsApi', `Loaded insights report: ${data.summary.total} insights`);
230231
return data;
231232
} catch (error) {
232-
console.error(`[insightsApi] Error loading insights report from ${path}:`, error);
233+
logger.error('insightsApi', `Error loading insights report from ${path}`, error instanceof Error ? error : undefined);
233234
throw error;
234235
}
235236
},
@@ -297,7 +298,7 @@ export const insightsApi = {
297298
userId: string
298299
): Promise<AcknowledgeResponse> {
299300
// Placeholder - in production, this would POST to a backend
300-
console.log(`[insightsApi] Acknowledging insight ${insightId} by user ${userId}`);
301+
logger.info('insightsApi', `Acknowledging insight ${insightId} by user ${userId}`);
301302

302303
return {
303304
success: true,
@@ -328,7 +329,7 @@ export const insightsApi = {
328329
*/
329330
async regenerateInsights(): Promise<RegenerateResponse> {
330331
// Placeholder - in production, this would trigger analysis
331-
console.log('[insightsApi] Regenerating insights...');
332+
logger.info('insightsApi', 'Regenerating insights...');
332333

333334
return {
334335
success: true,

‎src/features/dashboard/api/predictionsApi.ts‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
PredictionFactor,
1717
GoalMarker,
1818
} from '../types';
19+
import { logger } from '../helpers/logger';
1920

2021
// ============================================================================
2122
// Raw Python Output Types
@@ -299,7 +300,7 @@ export const predictionsApi = {
299300
const response = await fetch(path);
300301
if (!response.ok) {
301302
if (response.status === 404) {
302-
console.warn(`[predictionsApi] Predictions report not found at ${path}`);
303+
logger.warn('predictionsApi', `Predictions report not found at ${path}`);
303304
return null;
304305
}
305306
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
@@ -312,10 +313,10 @@ export const predictionsApi = {
312313
}
313314

314315
const data = transformPredictionsReport(rawData);
315-
console.log(`[predictionsApi] Loaded predictions report: ${data.risks.length} risks`);
316+
logger.info('predictionsApi', `Loaded predictions report: ${data.risks.length} risks`);
316317
return data;
317318
} catch (error) {
318-
console.error(`[predictionsApi] Error loading predictions report from ${path}:`, error);
319+
logger.error('predictionsApi', `Error loading predictions report from ${path}`, error instanceof Error ? error : undefined);
319320
throw error;
320321
}
321322
},
@@ -413,7 +414,7 @@ export const predictionsApi = {
413414
scenario: ScenarioConfig
414415
): Promise<ScenarioResult | null> {
415416
// Placeholder - in production, this would call the analyzer
416-
console.log('[predictionsApi] Calculating custom scenario:', scenario);
417+
logger.info('predictionsApi', 'Calculating custom scenario', { scenario });
417418

418419
const report = await this.loadPredictionsReport(dataPath);
419420
if (!report) {

‎src/features/dashboard/api/visualizationApi.ts‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
ChartType,
1313
VisualizationMetric,
1414
} from '../types/visualizations';
15+
import { logger } from '../helpers/logger';
1516

1617
// Storage key for localStorage
1718
const STORAGE_KEY = 'code-inventory-visualizations';
@@ -33,7 +34,7 @@ function getStoredVisualizations(): Map<string, VisualizationConfig> {
3334
const parsed = JSON.parse(stored) as Record<string, VisualizationConfig>;
3435
return new Map(Object.entries(parsed));
3536
} catch {
36-
console.warn('[visualizationApi] Failed to load from localStorage');
37+
logger.warn('visualizationApi', 'Failed to load from localStorage');
3738
return new Map();
3839
}
3940
}
@@ -46,7 +47,7 @@ function saveToStorage(visualizations: Map<string, VisualizationConfig>): void {
4647
const obj = Object.fromEntries(visualizations);
4748
localStorage.setItem(STORAGE_KEY, JSON.stringify(obj));
4849
} catch (error) {
49-
console.error('[visualizationApi] Failed to save to localStorage:', error);
50+
logger.error('visualizationApi', 'Failed to save to localStorage', error instanceof Error ? error : undefined);
5051
}
5152
}
5253

@@ -178,7 +179,7 @@ export const visualizationApi = {
178179

179180
// For image/PDF formats, would need to use html2canvas or similar
180181
// Placeholder implementation
181-
console.log('[visualizationApi] Export requested:', { id, options });
182+
logger.info('visualizationApi', 'Export requested', { id, options });
182183
return null;
183184
},
184185

‎src/features/dashboard/components/HeaderExample.tsx‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import CssBaseline from '@mui/material/CssBaseline';
1111
import { Box, Container, Typography, Paper } from '@mui/material';
1212
import { dashboardTheme } from '../../../theme/dashboardTheme';
1313
import { Header } from './Header';
14+
import { logger } from '../helpers/logger';
1415

1516
/**
1617
* Example dashboard application showing Header integration
@@ -25,7 +26,7 @@ export function HeaderExample() {
2526
*/
2627
useEffect(() => {
2728
const interval = setInterval(() => {
28-
console.log('Auto-refreshing dashboard data...');
29+
logger.info('HeaderExample', 'Auto-refreshing dashboard data...');
2930
setLastGenerated(new Date());
3031
}, 30000); // 30 seconds
3132

@@ -36,15 +37,15 @@ export function HeaderExample() {
3637
* Handle settings button click
3738
*/
3839
const handleSettingsClick = () => {
39-
console.log('Settings button clicked');
40+
logger.info('HeaderExample', 'Settings button clicked');
4041
alert('Settings modal would open here');
4142
};
4243

4344
/**
4445
* Handle export button click
4546
*/
4647
const handleExportClick = async () => {
47-
console.log('Export button clicked');
48+
logger.info('HeaderExample', 'Export button clicked');
4849
setDataRefreshing(true);
4950

5051
// Simulate data export
@@ -69,7 +70,7 @@ export function HeaderExample() {
6970
URL.revokeObjectURL(url);
7071

7172
setDataRefreshing(false);
72-
console.log('Export completed');
73+
logger.info('HeaderExample', 'Export completed');
7374
}, 1000);
7475
};
7576

‎src/features/dashboard/components/InsightsPage.tsx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import {
4141
useRegenerateInsights,
4242
} from '../hooks/useInsights';
4343
import type { AIInsight, InsightsSortConfig } from '../types';
44+
import { logger } from '../helpers/logger';
4445

4546
/**
4647
* Props for InsightsPage
@@ -294,7 +295,7 @@ function InsightsPageContent({ dataPath = '/data' }: InsightsPageProps) {
294295
key={insight.id}
295296
insight={insight}
296297
onAcknowledge={handleAcknowledge}
297-
onViewDetails={(id) => console.log('View details:', id)}
298+
onViewDetails={(id) => logger.info('InsightsPage', 'View details', { id })}
298299
isLoading={isAcknowledging}
299300
/>
300301
))}

‎src/features/dashboard/components/MetricCardExample.tsx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
Error as ErrorIcon,
2121
} from '@mui/icons-material';
2222
import { MetricCard } from './MetricCard';
23+
import { logger } from '../helpers/logger';
2324

2425
/**
2526
* MetricCard Example Showcase
@@ -32,7 +33,7 @@ export function MetricCardExample() {
3233

3334
const handleCardClick = (cardName: string) => {
3435
setClickedCard(cardName);
35-
console.log(`Card clicked: ${cardName}`);
36+
logger.info('MetricCardExample', `Card clicked: ${cardName}`);
3637
// In a real app, this would navigate or show details
3738
};
3839

0 commit comments

Comments
 (0)