diff --git a/src/components/admin/ErrorAnalytics.tsx b/src/components/admin/ErrorAnalytics.tsx index 74f1bc22..8532961a 100644 --- a/src/components/admin/ErrorAnalytics.tsx +++ b/src/components/admin/ErrorAnalytics.tsx @@ -2,8 +2,15 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts'; import { AlertCircle, TrendingUp, Users, Zap } from 'lucide-react'; +interface ErrorSummary { + error_type: string | null; + occurrence_count: number | null; + affected_users: number | null; + avg_duration_ms: number | null; +} + interface ErrorAnalyticsProps { - errorSummary: any[] | undefined; + errorSummary: ErrorSummary[] | undefined; } export function ErrorAnalytics({ errorSummary }: ErrorAnalyticsProps) { @@ -11,8 +18,8 @@ export function ErrorAnalytics({ errorSummary }: ErrorAnalyticsProps) { return null; } - const totalErrors = errorSummary.reduce((sum, item) => sum + item.occurrence_count, 0); - const totalAffectedUsers = errorSummary.reduce((sum, item) => sum + item.affected_users, 0); + const totalErrors = errorSummary.reduce((sum, item) => sum + (item.occurrence_count || 0), 0); + const totalAffectedUsers = errorSummary.reduce((sum, item) => sum + (item.affected_users || 0), 0); const avgDuration = errorSummary.reduce((sum, item) => sum + (item.avg_duration_ms || 0), 0) / errorSummary.length; const topErrors = errorSummary.slice(0, 5); diff --git a/src/components/admin/ErrorDetailsModal.tsx b/src/components/admin/ErrorDetailsModal.tsx index 570d8c16..e6cfb519 100644 --- a/src/components/admin/ErrorDetailsModal.tsx +++ b/src/components/admin/ErrorDetailsModal.tsx @@ -6,8 +6,31 @@ import { Copy, ExternalLink } from 'lucide-react'; import { format } from 'date-fns'; import { toast } from 'sonner'; +interface Breadcrumb { + timestamp: string; + category: string; + message: string; + level: string; + data?: Record; +} + +interface ErrorDetails { + request_id: string; + created_at: string; + error_type: string; + error_message: string; + error_stack?: string; + endpoint: string; + method: string; + status_code: number; + duration_ms: number; + user_id?: string; + breadcrumbs?: Breadcrumb[]; + environment_context?: Record; +} + interface ErrorDetailsModalProps { - error: any; + error: ErrorDetails; onClose: () => void; } @@ -125,7 +148,7 @@ ${error.error_stack ? `Stack Trace:\n${error.error_stack}` : ''} {error.breadcrumbs && error.breadcrumbs.length > 0 ? (
- {error.breadcrumbs.map((crumb: any, index: number) => ( + {error.breadcrumbs.map((crumb, index) => (
diff --git a/src/components/error/EntityErrorBoundary.tsx b/src/components/error/EntityErrorBoundary.tsx index cccd50da..db33ae57 100644 --- a/src/components/error/EntityErrorBoundary.tsx +++ b/src/components/error/EntityErrorBoundary.tsx @@ -18,19 +18,8 @@ interface EntityErrorBoundaryState { errorInfo: ErrorInfo | null; } -/** - * Entity Error Boundary Component (P0 #5) - * - * Specialized error boundary for entity detail pages. - * Prevents entity rendering errors from crashing the app. - * - * Usage: - * ```tsx - * - * - * - * ``` - */ +type ErrorWithId = Error & { errorId: string }; + export class EntityErrorBoundary extends Component { constructor(props: EntityErrorBoundaryProps) { super(props); @@ -61,7 +50,7 @@ export class EntityErrorBoundary extends Component { @@ -131,9 +120,9 @@ export class EntityErrorBoundary extends Component {this.state.error?.message || `An unexpected error occurred while loading this ${entityLabel.toLowerCase()}`}

- {(this.state.error as any)?.errorId && ( + {(this.state.error as ErrorWithId)?.errorId && (

- Reference ID: {((this.state.error as any).errorId as string).slice(0, 8)} + Reference ID: {(this.state.error as ErrorWithId).errorId.slice(0, 8)}

)}

diff --git a/src/components/error/ErrorBoundary.tsx b/src/components/error/ErrorBoundary.tsx index 5b06e73d..ae43fce3 100644 --- a/src/components/error/ErrorBoundary.tsx +++ b/src/components/error/ErrorBoundary.tsx @@ -18,19 +18,8 @@ interface ErrorBoundaryState { errorInfo: ErrorInfo | null; } -/** - * Generic Error Boundary Component (P0 #5) - * - * Prevents component errors from crashing the entire application. - * Shows user-friendly error UI with recovery options. - * - * Usage: - * ```tsx - * - * - * - * ``` - */ +type ErrorWithId = Error & { errorId: string }; + export class ErrorBoundary extends Component { constructor(props: ErrorBoundaryProps) { super(props); @@ -61,7 +50,7 @@ export class ErrorBoundary extends Component {this.state.error?.message || 'An unexpected error occurred'}

- {(this.state.error as any)?.errorId && ( + {(this.state.error as ErrorWithId)?.errorId && (

- Reference ID: {((this.state.error as any).errorId as string).slice(0, 8)} + Reference ID: {(this.state.error as ErrorWithId).errorId.slice(0, 8)}

)} diff --git a/src/components/error/RouteErrorBoundary.tsx b/src/components/error/RouteErrorBoundary.tsx index 98107d26..74da7676 100644 --- a/src/components/error/RouteErrorBoundary.tsx +++ b/src/components/error/RouteErrorBoundary.tsx @@ -13,19 +13,8 @@ interface RouteErrorBoundaryState { error: Error | null; } -/** - * Route Error Boundary Component (P0 #5) - * - * Top-level error boundary that wraps all routes. - * Last line of defense to prevent complete app crashes. - * - * Usage: Wrap Routes component in App.tsx - * ```tsx - * - * ... - * - * ``` - */ +type ErrorWithId = Error & { errorId: string }; + export class RouteErrorBoundary extends Component { constructor(props: RouteErrorBoundaryProps) { super(props); @@ -56,7 +45,7 @@ export class RouteErrorBoundary extends Component { @@ -91,9 +80,9 @@ export class RouteErrorBoundary extends Component )} - {(this.state.error as any)?.errorId && ( + {(this.state.error as ErrorWithId)?.errorId && (

- Reference ID: {((this.state.error as any).errorId as string).slice(0, 8)} + Reference ID: {(this.state.error as ErrorWithId).errorId.slice(0, 8)}

)}
diff --git a/supabase/functions/request-account-deletion/index.ts b/supabase/functions/request-account-deletion/index.ts index c0a465cf..76b8efe4 100644 --- a/supabase/functions/request-account-deletion/index.ts +++ b/supabase/functions/request-account-deletion/index.ts @@ -164,9 +164,12 @@ serve(async (req) => { html: emailPayload.html, }), }); - console.log('Deletion confirmation email sent'); + edgeLogger.info('Deletion confirmation email sent', { requestId: tracking.requestId }); } catch (emailError) { - console.error('Failed to send email:', emailError); + edgeLogger.error('Failed to send email', { + requestId: tracking.requestId, + error: emailError.message + }); } } diff --git a/supabase/functions/resend-deletion-code/index.ts b/supabase/functions/resend-deletion-code/index.ts index 0daff935..fe6140f8 100644 --- a/supabase/functions/resend-deletion-code/index.ts +++ b/supabase/functions/resend-deletion-code/index.ts @@ -126,9 +126,12 @@ serve(async (req) => { `, }), }); - console.log('New confirmation code email sent'); + edgeLogger.info('New confirmation code email sent', { requestId: tracking.requestId }); } catch (emailError) { - console.error('Failed to send email:', emailError); + edgeLogger.error('Failed to send email', { + requestId: tracking.requestId, + error: emailError.message + }); } } diff --git a/supabase/functions/seed-test-data/index.ts b/supabase/functions/seed-test-data/index.ts index ef543cd2..7b2d8022 100644 --- a/supabase/functions/seed-test-data/index.ts +++ b/supabase/functions/seed-test-data/index.ts @@ -1,4 +1,5 @@ import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.57.4'; +import { edgeLogger, startRequest, endRequest } from '../_shared/logger.ts'; const corsHeaders = { 'Access-Control-Allow-Origin': '*', @@ -89,7 +90,7 @@ async function registerTestEntity( }); if (error && error.code !== '23505') { // Ignore unique constraint violations - console.error(`Error registering ${entityType} ${slug}:`, error); + edgeLogger.error(`Error registering ${entityType} ${slug}`, { error: error.message, entityType, slug }); } } @@ -103,7 +104,7 @@ async function getExistingTestEntities( .eq('entity_type', entityType); if (error) { - console.error(`Error fetching existing ${entityType}:`, error); + edgeLogger.error(`Error fetching existing ${entityType}`, { error: error.message, entityType }); return []; } @@ -121,7 +122,7 @@ async function getPendingSubmissionItems( .eq('status', 'pending'); if (error) { - console.error(`Error fetching pending ${itemType} items:`, error); + edgeLogger.error(`Error fetching pending ${itemType} items`, { error: error.message, itemType }); return []; } @@ -129,6 +130,8 @@ async function getPendingSubmissionItems( } Deno.serve(async (req) => { + const tracking = startRequest(); + if (req.method === 'OPTIONS') { return new Response(null, { headers: corsHeaders }); } @@ -176,12 +179,17 @@ Deno.serve(async (req) => { stage }: SeedOptions = await req.json(); - console.info('=== SEED DATA GENERATION DEBUG ==='); - console.info('Received entityTypes:', JSON.stringify(entityTypes)); - console.info('entityTypes is array:', Array.isArray(entityTypes)); - console.info('entityTypes length:', entityTypes?.length); - console.info('Preset:', preset); - console.info('==================================='); + edgeLogger.info('Seed data generation started', { + requestId: tracking.requestId, + entityTypes, + preset, + fieldDensity, + includeDependencies, + includeConflicts, + includeVersionChains, + includeEscalated, + includeExpiredLocks + }); const plan = PRESETS[preset]; if (!plan) { @@ -212,7 +220,7 @@ Deno.serve(async (req) => { // Load existing test entities from registry if includeDependencies is true if (includeDependencies) { - console.log('Loading existing test entities from registry...'); + edgeLogger.info('Loading existing test entities from registry', { requestId: tracking.requestId }); const existingOperators = await getExistingTestEntities(supabase, 'operator'); const existingOwners = await getExistingTestEntities(supabase, 'property_owner'); @@ -260,8 +268,19 @@ Deno.serve(async (req) => { pendingParks.forEach(item => createdSubmissionItems.park.push(item.id)); pendingRideModels.forEach(item => createdSubmissionItems.ride_model.push(item.id)); - console.log(`Loaded ${existingOperators.length} operators, ${existingOwners.length} owners, ${existingManufacturers.length} manufacturers, ${existingDesigners.length} designers, ${existingParks.length} parks`); - console.log(`Loaded ${pendingOperators.length} pending operators, ${pendingOwners.length} pending owners, ${pendingManufacturers.length} pending manufacturers, ${pendingDesigners.length} pending designers, ${pendingParks.length} pending parks`); + edgeLogger.info('Loaded existing entities', { + requestId: tracking.requestId, + operators: existingOperators.length, + owners: existingOwners.length, + manufacturers: existingManufacturers.length, + designers: existingDesigners.length, + parks: existingParks.length, + pendingOperators: pendingOperators.length, + pendingOwners: pendingOwners.length, + pendingManufacturers: pendingManufacturers.length, + pendingDesigners: pendingDesigners.length, + pendingParks: pendingParks.length + }); // Add pending parks' slugs to createdParks for ride generation pendingParks.forEach(item => { @@ -271,7 +290,7 @@ Deno.serve(async (req) => { } }); - console.log(`Total parks available for rides: ${createdParks.length}`); + edgeLogger.info('Parks available for rides', { requestId: tracking.requestId, count: createdParks.length }); } // Helper to create submission @@ -316,7 +335,7 @@ Deno.serve(async (req) => { const { error: subError } = await supabase.from('content_submissions').insert(submissionData); if (subError) { - console.error(`Error inserting content_submission for type ${type}:`, subError); + edgeLogger.error('Error inserting content_submission', { type, error: subError.message }); throw subError; } @@ -350,8 +369,7 @@ Deno.serve(async (req) => { const { data: insertedData, error: typeError } = await supabase.from(table).insert(typeData).select('id').single(); if (typeError) { - console.error(`Error inserting into ${table} for type ${type}:`, typeError); - console.error('Data being inserted:', JSON.stringify(typeData, null, 2)); + edgeLogger.error('Error inserting into type table', { table, type, error: typeError.message, data: typeData }); throw typeError; } return { submissionId, itemId, typeId: insertedData?.id }; @@ -373,10 +391,6 @@ Deno.serve(async (req) => { // Create companies FIRST so parks can reference operators/owners if (!stage || stage === 'companies') { - console.info('=== COMPANY GENERATION CHECK ==='); - console.info('Entity types array:', JSON.stringify(entityTypes)); - console.info('Plan calls for companies:', plan.companies); - const companyTypes = ['manufacturer', 'operator', 'designer', 'property_owner']; // First, determine which company types are selected @@ -384,14 +398,17 @@ Deno.serve(async (req) => { entityTypes.includes(pluralizeCompanyType(compType)) ); - console.info(`✓ Selected company types (${selectedCompanyTypes.length}):`, selectedCompanyTypes); + edgeLogger.info('Company generation started', { + requestId: tracking.requestId, + entityTypes, + planCompanies: plan.companies, + selectedCompanyTypes + }); // Calculate fair distribution: base amount per type + extras const basePerType = Math.floor(plan.companies / selectedCompanyTypes.length); const extras = plan.companies % selectedCompanyTypes.length; - console.info(`Distribution plan: ${basePerType} base per type, ${extras} extra(s) to first types`); - let companiesCreatedTotal = 0; for (let typeIndex = 0; typeIndex < selectedCompanyTypes.length; typeIndex++) { @@ -401,10 +418,9 @@ Deno.serve(async (req) => { // Each type gets base amount, first N types get +1 extra const count = basePerType + (typeIndex < extras ? 1 : 0); - console.info(`✓ Generating ${count} companies of type ${compType}`); + edgeLogger.info('Creating companies', { requestId: tracking.requestId, compType, count }); for (let i = 0; i < count; i++) { - console.info(` Creating company ${i + 1}/${count} (type: ${compType})`); const level = getPopulationLevel(fieldDensity, i); const companyData: any = { name: `Test ${compType.replace('_', ' ')} ${i + 1}`, @@ -461,8 +477,8 @@ Deno.serve(async (req) => { // Create parks if ((!stage || stage === 'parks') && entityTypes.includes('parks')) { + edgeLogger.info('Creating parks', { requestId: tracking.requestId, count: plan.parks }); for (let i = 0; i < plan.parks; i++) { - console.log(` Creating park ${i + 1}/${plan.parks}`); const level = getPopulationLevel(fieldDensity, i); const shouldConflict = includeConflicts && createdParkSlugs.length > 0 && Math.random() < 0.15; const shouldVersionChain = includeVersionChains && createdParkSlugs.length > 0 && Math.random() < 0.15; @@ -824,20 +840,33 @@ Deno.serve(async (req) => { const executionTime = Date.now() - startTime; + edgeLogger.info('Seed data generation completed', { + requestId: tracking.requestId, + duration: executionTime, + summary, + stage: stage || 'all' + }); + return new Response( JSON.stringify({ success: true, summary, time: (executionTime / 1000).toFixed(2), - stage: stage || 'all' + stage: stage || 'all', + requestId: tracking.requestId }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ); } catch (error) { - console.error('Seed error:', error); + const duration = endRequest(tracking); + edgeLogger.error('Seed error', { + requestId: tracking.requestId, + duration, + error: error.message + }); return new Response( - JSON.stringify({ error: error.message }), + JSON.stringify({ error: error.message, requestId: tracking.requestId }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ); } diff --git a/supabase/functions/send-escalation-notification/index.ts b/supabase/functions/send-escalation-notification/index.ts index 1db0a3e1..0a350220 100644 --- a/supabase/functions/send-escalation-notification/index.ts +++ b/supabase/functions/send-escalation-notification/index.ts @@ -1,5 +1,6 @@ import { serve } from "https://deno.land/std@0.190.0/http/server.ts"; import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4"; +import { edgeLogger, startRequest, endRequest } from '../_shared/logger.ts'; const corsHeaders = { 'Access-Control-Allow-Origin': '*', @@ -12,10 +13,6 @@ interface EscalationRequest { escalatedBy: string; } -// Simple request tracking -const startRequest = () => ({ requestId: crypto.randomUUID(), start: Date.now() }); -const endRequest = (tracking: { start: number }) => Date.now() - tracking.start; - serve(async (req) => { const tracking = startRequest(); @@ -31,7 +28,12 @@ serve(async (req) => { const { submissionId, escalationReason, escalatedBy }: EscalationRequest = await req.json(); - console.log('Processing escalation notification:', { submissionId, escalationReason, escalatedBy }); + edgeLogger.info('Processing escalation notification', { + requestId: tracking.requestId, + submissionId, + escalatedBy, + action: 'send_escalation' + }); // Fetch submission details const { data: submission, error: submissionError } = await supabase @@ -52,7 +54,11 @@ serve(async (req) => { .single(); if (escalatorError) { - console.error('Failed to fetch escalator profile:', escalatorError); + edgeLogger.error('Failed to fetch escalator profile', { + requestId: tracking.requestId, + error: escalatorError.message, + escalatedBy + }); } // Fetch submission items count @@ -62,7 +68,11 @@ serve(async (req) => { .eq('submission_id', submissionId); if (countError) { - console.error('Failed to fetch items count:', countError); + edgeLogger.error('Failed to fetch items count', { + requestId: tracking.requestId, + error: countError.message, + submissionId + }); } // Prepare email content @@ -185,7 +195,10 @@ serve(async (req) => { }), }); } catch (fetchError) { - console.error('Network error sending email:', fetchError); + edgeLogger.error('Network error sending email', { + requestId: tracking.requestId, + error: fetchError.message + }); throw new Error('Network error: Unable to reach email service'); } @@ -196,7 +209,11 @@ serve(async (req) => { } catch (parseError) { errorText = 'Unable to parse error response'; } - console.error('ForwardEmail API error:', errorText); + edgeLogger.error('ForwardEmail API error', { + requestId: tracking.requestId, + status: emailResponse.status, + errorText + }); throw new Error(`Failed to send email: ${emailResponse.status} - ${errorText}`); } @@ -204,10 +221,16 @@ serve(async (req) => { try { emailResult = await emailResponse.json(); } catch (parseError) { - console.error('Failed to parse email API response:', parseError); + edgeLogger.error('Failed to parse email API response', { + requestId: tracking.requestId, + error: parseError.message + }); throw new Error('Invalid response from email service'); } - console.log('Email sent successfully:', emailResult); + edgeLogger.info('Email sent successfully', { + requestId: tracking.requestId, + emailId: emailResult.id + }); // Update submission with notification status const { error: updateError } = await supabase @@ -221,11 +244,20 @@ serve(async (req) => { .eq('id', submissionId); if (updateError) { - console.error('Failed to update submission escalation status:', updateError); + edgeLogger.error('Failed to update submission escalation status', { + requestId: tracking.requestId, + error: updateError.message, + submissionId + }); } const duration = endRequest(tracking); - console.log('Escalation notification sent', { requestId: tracking.requestId, duration, emailId: emailResult.id }); + edgeLogger.info('Escalation notification sent', { + requestId: tracking.requestId, + duration, + emailId: emailResult.id, + submissionId + }); return new Response( JSON.stringify({ @@ -242,7 +274,11 @@ serve(async (req) => { ); } catch (error) { const duration = endRequest(tracking); - console.error('Error in send-escalation-notification:', error, { requestId: tracking.requestId, duration }); + edgeLogger.error('Error in send-escalation-notification', { + requestId: tracking.requestId, + duration, + error: error instanceof Error ? error.message : 'Unknown error' + }); return new Response( JSON.stringify({ error: error instanceof Error ? error.message : 'Unknown error occurred', diff --git a/supabase/functions/send-password-added-email/index.ts b/supabase/functions/send-password-added-email/index.ts index 27c93e82..1a2c42eb 100644 --- a/supabase/functions/send-password-added-email/index.ts +++ b/supabase/functions/send-password-added-email/index.ts @@ -138,7 +138,7 @@ serve(async (req) => { const fromEmail = Deno.env.get('FROM_EMAIL_ADDRESS') || 'noreply@thrillwiki.com'; if (!forwardEmailKey) { - console.error('FORWARDEMAIL_API_KEY not configured'); + edgeLogger.error('FORWARDEMAIL_API_KEY not configured', { requestId: tracking.requestId }); throw new Error('Email service not configured'); } @@ -158,7 +158,11 @@ serve(async (req) => { if (!emailResponse.ok) { const errorText = await emailResponse.text(); - console.error('ForwardEmail API error:', errorText); + edgeLogger.error('ForwardEmail API error', { + requestId: tracking.requestId, + status: emailResponse.status, + errorText + }); throw new Error(`Failed to send email: ${emailResponse.statusText}`); } diff --git a/supabase/functions/sync-all-moderators-to-topic/index.ts b/supabase/functions/sync-all-moderators-to-topic/index.ts index 3a5a7f7c..ca7f352c 100644 --- a/supabase/functions/sync-all-moderators-to-topic/index.ts +++ b/supabase/functions/sync-all-moderators-to-topic/index.ts @@ -1,6 +1,7 @@ import { serve } from "https://deno.land/std@0.168.0/http/server.ts"; import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4"; import { Novu } from "npm:@novu/api@1.6.0"; +import { edgeLogger, startRequest, endRequest } from '../_shared/logger.ts'; const corsHeaders = { 'Access-Control-Allow-Origin': '*', @@ -12,10 +13,6 @@ const TOPICS = { MODERATION_REPORTS: 'moderation-reports', } as const; -// Simple request tracking -const startRequest = () => ({ requestId: crypto.randomUUID(), start: Date.now() }); -const endRequest = (tracking: { start: number }) => Date.now() - tracking.start; - serve(async (req) => { const tracking = startRequest(); @@ -35,7 +32,10 @@ serve(async (req) => { const novu = new Novu({ secretKey: novuApiKey }); const supabase = createClient(supabaseUrl, supabaseServiceKey); - console.log('Starting moderator sync to Novu topics...'); + edgeLogger.info('Starting moderator sync to Novu topics', { + requestId: tracking.requestId, + action: 'sync_moderators' + }); // Get all moderators, admins, and superusers const { data: moderatorRoles, error: rolesError } = await supabase @@ -50,7 +50,10 @@ serve(async (req) => { // Get unique user IDs (a user might have multiple moderator-level roles) const uniqueUserIds = [...new Set(moderatorRoles.map(r => r.user_id))]; - console.log(`Found ${uniqueUserIds.length} unique moderators to sync`); + edgeLogger.info('Found unique moderators to sync', { + requestId: tracking.requestId, + count: uniqueUserIds.length + }); const topics = [TOPICS.MODERATION_SUBMISSIONS, TOPICS.MODERATION_REPORTS]; const results = { @@ -62,11 +65,15 @@ serve(async (req) => { try { // Ensure topic exists (Novu will create it if it doesn't) await novu.topics.create({ key: topicKey, name: topicKey }); - console.log(`Topic ${topicKey} ready`); + edgeLogger.info('Topic ready', { requestId: tracking.requestId, topicKey }); } catch (error: any) { // Topic might already exist, which is fine if (!error.message?.includes('already exists')) { - console.warn(`Note about topic ${topicKey}:`, error.message); + edgeLogger.warn('Note about topic', { + requestId: tracking.requestId, + topicKey, + error: error.message + }); } } @@ -83,10 +90,19 @@ serve(async (req) => { subscribers: batch, }); successCount += batch.length; - console.log(`Added batch of ${batch.length} users to ${topicKey}`); + edgeLogger.info('Added batch of users to topic', { + requestId: tracking.requestId, + topicKey, + batchSize: batch.length + }); } catch (error: any) { errorCount += batch.length; - console.error(`Error adding batch to ${topicKey}:`, error.message); + edgeLogger.error('Error adding batch to topic', { + requestId: tracking.requestId, + topicKey, + batchSize: batch.length, + error: error.message + }); } } @@ -98,7 +114,11 @@ serve(async (req) => { } const duration = endRequest(tracking); - console.log('Sync completed:', results, { requestId: tracking.requestId, duration }); + edgeLogger.info('Sync completed', { + requestId: tracking.requestId, + duration, + results + }); return new Response( JSON.stringify({ @@ -118,7 +138,11 @@ serve(async (req) => { ); } catch (error: any) { const duration = endRequest(tracking); - console.error('Error syncing moderators to topics:', error, { requestId: tracking.requestId, duration }); + edgeLogger.error('Error syncing moderators to topics', { + requestId: tracking.requestId, + duration, + error: error.message + }); return new Response( JSON.stringify({ diff --git a/supabase/functions/trigger-notification/index.ts b/supabase/functions/trigger-notification/index.ts index 275fde1e..42023f9a 100644 --- a/supabase/functions/trigger-notification/index.ts +++ b/supabase/functions/trigger-notification/index.ts @@ -1,6 +1,6 @@ import { serve } from "https://deno.land/std@0.168.0/http/server.ts"; import { Novu } from "npm:@novu/api@1.6.0"; -import { startRequest, endRequest } from "../_shared/logger.ts"; +import { edgeLogger, startRequest, endRequest } from "../_shared/logger.ts"; const corsHeaders = { 'Access-Control-Allow-Origin': '*', @@ -42,7 +42,12 @@ serve(async (req) => { ? { subscriberId } : { topicKey: topicKey! }; - console.log('Triggering notification:', { workflowId, recipient, requestId: tracking.requestId }); + edgeLogger.info('Triggering notification', { + workflowId, + recipient, + requestId: tracking.requestId, + action: 'trigger_notification' + }); const result = await novu.trigger({ to: recipient, @@ -51,7 +56,10 @@ serve(async (req) => { overrides, }); - console.log('Notification triggered successfully:', result.data); + edgeLogger.info('Notification triggered successfully', { + requestId: tracking.requestId, + transactionId: result.data.transactionId + }); endRequest(tracking, 200); @@ -72,7 +80,10 @@ serve(async (req) => { ); } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; - console.error('Error triggering notification:', errorMessage); + edgeLogger.error('Error triggering notification', { + requestId: tracking.requestId, + error: errorMessage + }); endRequest(tracking, 500, errorMessage);