Execution Logging System Documentation
Overview
The Execution Logging System provides granular, step-by-step monitoring of background job processing with beautiful UI visualization. This system captures detailed execution flow, timing, and error context - offering superior debugging capabilities compared to standard Cloudflare Worker logs.
Architecture
High-Level Flow
Background Worker (ai-consulting-main-worker)
↓ Stores execution logs
KV Namespace (EXECUTION_LOGS)
↓ Retrieved by
Pages Functions (strategic-intelligence-onboarding)
↓ Displayed in
Admin UI Modal (Process Log Viewer)Key Components
- Background Job Processor - Captures execution steps
- KV Storage - Stores structured log data
- Pages Function API - Retrieves logs with authentication
- Admin UI Modal - Beautiful step-by-step visualization
Backend Implementation
1. Log Structure
Each execution creates a comprehensive log entry:
const executionLog = {
tracking_id: "60B3RNTB",
execution_id: "exec_1703123456789_xyz123abc",
started_at: "2024-01-15T10:30:00.000Z",
completed_at: "2024-01-15T10:32:30.000Z",
duration_ms: 150000,
tier: "comprehensive",
company: "Acme Corp",
steps: [
{
step: "initialization",
timestamp: "2024-01-15T10:30:00.000Z",
status: "completed",
message: "Started processing for Acme Corp (comprehensive tier)"
},
{
step: "status_update",
timestamp: "2024-01-15T10:30:01.000Z",
status: "completed",
message: "Updated status to processing"
},
{
step: "orchestrator_execution",
timestamp: "2024-01-15T10:30:02.000Z",
status: "in_progress",
message: "Starting orchestrator execution..."
},
{
step: "error_handling",
timestamp: "2024-01-15T10:32:30.000Z",
status: "failed",
message: "Processing failed: AI generation timeout after 480000ms",
error_details: "Error: AI generation timeout after 480000ms\n at AIService.generateContent (worker.js:1234:56)"
}
]
};2. Background Job Integration
BackgroundJobProcessor.js
// Create fresh execution log for each processing attempt
async processProfile(profile) {
const executionLog = {
tracking_id: trackingId,
execution_id: `exec_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
started_at: new Date().toISOString(),
tier: profile.tier_level,
company: profile.company_name,
steps: []
};
try {
// Log initialization
executionLog.steps.push({
step: 'initialization',
timestamp: new Date().toISOString(),
status: 'completed',
message: `Started processing for ${profile.company_name} (${profile.tier_level} tier)`
});
// Log status updates
await this.updateProfileStatus(trackingId, 'processing', {
processed_at: new Date().toISOString(),
processing_mode: 'background'
});
executionLog.steps.push({
step: 'status_update',
timestamp: new Date().toISOString(),
status: 'completed',
message: 'Updated status to processing'
});
// Log orchestrator execution
executionLog.steps.push({
step: 'orchestrator_execution',
timestamp: new Date().toISOString(),
status: 'in_progress',
message: 'Starting orchestrator execution...'
});
const response = await this.orchestratorService.executeOrchestrator(mockRequest);
if (response.success) {
executionLog.steps.push({
step: 'orchestrator_execution',
timestamp: new Date().toISOString(),
status: 'completed',
message: `Orchestrator completed successfully. Response: ${responseData.message || 'Analysis complete'}`
});
}
} catch (error) {
// Log errors with full context
executionLog.steps.push({
step: 'error_handling',
timestamp: new Date().toISOString(),
status: 'failed',
message: `Processing failed: ${error.message}`,
error_details: error.stack
});
} finally {
// Always store execution log
executionLog.completed_at = new Date().toISOString();
executionLog.duration_ms = Date.now() - startTime;
await this.storeExecutionLog(executionLog);
}
}3. KV Storage Implementation
/**
* Store detailed execution log for admin monitoring
*/
async storeExecutionLog(executionLog) {
try {
// Store in KV for quick admin access
const key = `execution_log:${executionLog.tracking_id}`;
await this.env.EXECUTION_LOGS.put(key, JSON.stringify(executionLog), {
expirationTtl: 7 * 24 * 60 * 60 // 7 days retention
});
// Log storage confirmation
this.logger.info(`Execution Log Stored: ${executionLog.tracking_id} (${executionLog.duration_ms}ms)`, {
tracking_id: executionLog.tracking_id,
duration: executionLog.duration_ms,
steps_count: executionLog.steps.length,
final_status: executionLog.steps[executionLog.steps.length - 1]?.status || 'unknown'
});
} catch (error) {
this.logger.error('Failed to store execution log:', error);
}
}
/**
* Retrieve execution log for a specific tracking ID
*/
async getExecutionLog(trackingId) {
try {
const key = `execution_log:${trackingId}`;
const logData = await this.env.EXECUTION_LOGS.get(key);
return logData ? JSON.parse(logData) : null;
} catch (error) {
this.logger.error(`Failed to retrieve execution log for ${trackingId}:`, error);
return null;
}
}4. KV Namespace Configuration
wrangler.jsonc
{
"kv_namespaces": [
{
"binding": "EXECUTION_LOGS",
"id": "89bc42b35fa848498eb44de24367029c",
"preview_id": "89bc42b35fa848498eb44de24367029c"
}
]
}Frontend Implementation
1. Pages Function API
functions/api/execution-logs/[trackingId].ts
export const onRequestGet: typeof onRequest = async (context) => {
const { request, env, params } = context;
const trackingId = params.trackingId as string;
try {
// Access the background worker's KV store
const typedEnv = env as unknown as Env;
const key = `execution_log:${trackingId}`;
const logData = await typedEnv.EXECUTION_LOGS.get(key);
if (!logData) {
return new Response(JSON.stringify({
success: false,
error: 'No execution log found for this tracking ID',
tracking_id: trackingId
}), {
status: 404,
headers: { 'Content-Type': 'application/json' }
});
}
const executionLog: ExecutionLog = JSON.parse(logData);
// Format for admin display
const formattedLog = {
tracking_id: executionLog.tracking_id,
execution_id: executionLog.execution_id,
company: executionLog.company,
tier: executionLog.tier,
started_at: executionLog.started_at,
completed_at: executionLog.completed_at,
duration_ms: executionLog.duration_ms,
duration_readable: formatDuration(executionLog.duration_ms),
total_steps: executionLog.steps.length,
final_status: getFinalStatus(executionLog.steps),
steps: executionLog.steps.map(step => ({
step: step.step,
status: step.status,
timestamp: step.timestamp,
message: step.message,
time_from_start: getTimeFromStart(executionLog.started_at, step.timestamp),
error_details: step.error_details || null
}))
};
return new Response(JSON.stringify({
success: true,
data: formattedLog
}), {
headers: { 'Content-Type': 'application/json' }
});
} catch (error) {
console.error('Execution log retrieval error:', error);
return new Response(JSON.stringify({
success: false,
error: 'Failed to retrieve execution log',
details: error instanceof Error ? error.message : 'Unknown error'
}), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
};2. React Component Integration
AnalysisQueuedSection.tsx
const fetchExecutionLog = async () => {
if (!trackingId) return;
setLoadingLog(true);
setLogError(null);
try {
const response = await fetch(`/api/execution-logs/${trackingId}`);
const data = await response.json();
if (data.success) {
setExecutionLog(data.data);
} else {
setLogError(data.error || 'Failed to load execution log');
}
} catch (error) {
console.error('Failed to fetch execution log:', error);
setLogError('Failed to connect to execution log service');
} finally {
setLoadingLog(false);
}
};
const handleProcessLogClick = () => {
setShowProcessLog(true);
fetchExecutionLog();
};UI Design System
Color Palette & Status Mapping
Step Status Indicators
/* Completed Steps */
.step-completed {
border-left: 4px solid #10b981; /* Green-400 */
background-color: #f0fdf4; /* Green-50 */
}
/* Failed Steps */
.step-failed {
border-left: 4px solid #ef4444; /* Red-400 */
background-color: #fef2f2; /* Red-50 */
}
/* In Progress Steps */
.step-in-progress {
border-left: 4px solid #3b82f6; /* Blue-400 */
background-color: #eff6ff; /* Blue-50 */
}Final Status Badges
/* Completed Analysis */
.status-completed {
background-color: #dcfce7; /* Green-100 */
color: #166534; /* Green-800 */
}
/* Failed Analysis */
.status-failed {
background-color: #fee2e2; /* Red-100 */
color: #991b1b; /* Red-800 */
}
/* In Progress Analysis */
.status-in-progress {
background-color: #fef3c7; /* Yellow-100 */
color: #92400e; /* Yellow-800 */
}Typography & Layout
Font Specifications
/* Modal Header */
.log-header {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto';
font-size: 1.125rem; /* 18px */
font-weight: 600; /* Semibold */
color: #1f2937; /* Gray-800 */
}
/* Metadata Grid */
.log-metadata {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto';
font-size: 0.75rem; /* 12px */
font-weight: 500; /* Medium */
}
/* Execution Steps */
.log-steps {
font-family: 'SF Mono', Monaco, Inconsolata, 'Roboto Mono', monospace;
font-size: 0.875rem; /* 14px */
line-height: 1.5;
}
/* Step Messages */
.step-message {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto';
font-size: 0.75rem; /* 12px */
line-height: 1.4;
}
/* Error Details */
.error-details {
font-family: 'SF Mono', Monaco, Inconsolata, 'Roboto Mono', monospace;
font-size: 0.625rem; /* 10px */
background-color: #fef2f2; /* Red-50 */
color: #dc2626; /* Red-600 */
padding: 4px 8px;
border-radius: 4px;
white-space: pre-wrap;
}Usage Patterns
1. Fresh Execution Logs
Each re-process creates a fresh execution log:
- Clean slate for each attempt
- Focused on current execution
- No historical clutter
- Unique
execution_idper attempt - Consistent KV key for easy lookup
2. Error Debugging Workflow
1. User clicks "Re-process" on failed analysis
2. Background job starts with fresh execution log
3. Each step is logged with precise timing
4. Error occurs and is captured with full stack trace
5. Admin clicks "Process Log" to see detailed failure context
6. Admin identifies exact failure point and timing
7. Admin can fix issue and re-process again3. Performance Monitoring
1. Admin opens "Process Log" for completed analysis
2. Reviews step-by-step timing breakdown
3. Identifies bottlenecks (e.g., "orchestrator_execution: +2m 30s")
4. Optimizes slow components based on granular timing dataBenefits Over Standard Cloudflare Logs
Granular Execution Logging System
- Step-by-step visibility: See exactly where processing succeeds/fails
- Precise timing: Know how long each step takes
- Rich context: Company, tier, tracking ID metadata
- Beautiful UI: Professional modal with color-coded steps
- Error context: Full stack traces and error details
- Self-contained: No external log aggregation needed
- User-friendly: Accessible to non-technical users
- Real-time: Available immediately after execution
Standard Cloudflare Worker Logs
- Still valuable for: Infrastructure debugging, broader context
- Best for: Worker deployment issues, environment problems
- Limited for: Application-level step-by-step debugging
Configuration
Environment Variables
{
"AI_GENERATION_TIMEOUT": "300000", // 5 minutes
"LLAMA4_SCOUT_TIMEOUT": "480000", // 8 minutes
"LOG_LEVEL": "info"
}KV Namespace Settings
{
"binding": "EXECUTION_LOGS",
"id": "89bc42b35fa848498eb44de24367029c",
"expirationTtl": 604800 // 7 days retention
}Extensibility
Adding New Step Types
// In BackgroundJobProcessor.js
executionLog.steps.push({
step: 'pdf_generation', // New step type
timestamp: new Date().toISOString(),
status: 'in_progress',
message: 'Generating PDF report...'
});
// After PDF generation
executionLog.steps.push({
step: 'pdf_generation',
timestamp: new Date().toISOString(),
status: 'completed',
message: `PDF generated successfully (${pdfSize} bytes)`
});Custom Error Handling
try {
await complexOperation();
} catch (error) {
executionLog.steps.push({
step: 'complex_operation',
timestamp: new Date().toISOString(),
status: 'failed',
message: `Complex operation failed: ${error.message}`,
error_details: error.stack,
retry_attempt: retryCount, // Custom metadata
operation_params: operationConfig // Custom context
});
}Best Practices
1. Meaningful Step Names
// Good
step: 'ai_model_inference'
step: 'pdf_generation'
step: 'data_validation'
// Avoid
step: 'step1'
step: 'process'
step: 'thing'2. Descriptive Messages
// Good
message: 'AI inference completed for comprehensive tier analysis (1,247 tokens)'
message: 'PDF generation failed: Template not found for tier level'
// Avoid
message: 'Done'
message: 'Error occurred'3. Consistent Status Values
// Standard status values
'completed' // Step finished successfully
'failed' // Step failed with error
'in_progress' // Step currently executing
'skipped' // Step skipped due to conditions4. Error Context
// Always include error details for failed steps
executionLog.steps.push({
step: 'operation_name',
status: 'failed',
message: `Clear description: ${error.message}`,
error_details: error.stack, // Full stack trace
error_code: error.code, // Error classification
retry_possible: true // Retry indication
});Future Enhancements
1. Log Aggregation
- Collect logs across multiple executions
- Identify patterns in failures
- Performance trending over time
2. Alert Integration
- Notify on repeated failures
- Performance degradation alerts
- Custom webhook integrations
3. Export Capabilities
- CSV export for analysis
- Integration with external monitoring
- Automated reporting
4. Enhanced UI Features
- Log search and filtering
- Step duration visualizations
- Error pattern analysis
Conclusion
The Execution Logging System provides comprehensive, granular visibility into background job processing with a beautiful, professional UI. This system offers superior debugging capabilities compared to standard infrastructure logs while maintaining clean architecture and excellent user experience.
The fresh execution log approach ensures focused, actionable information for each processing attempt, making it perfect for both development debugging and production monitoring.