diff --git a/supabase/functions/collect-metrics/index.ts b/supabase/functions/collect-metrics/index.ts index c9228f5c..d66322e5 100644 --- a/supabase/functions/collect-metrics/index.ts +++ b/supabase/functions/collect-metrics/index.ts @@ -1,9 +1,6 @@ import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.57.4'; - -const corsHeaders = { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', -}; +import { createEdgeFunction } from '../_shared/edgeFunctionWrapper.ts'; +import { edgeLogger } from '../_shared/logger.ts'; interface MetricRecord { metric_name: string; @@ -12,17 +9,13 @@ interface MetricRecord { timestamp: string; } -Deno.serve(async (req) => { - if (req.method === 'OPTIONS') { - return new Response(null, { headers: corsHeaders }); - } - - try { - const supabaseUrl = Deno.env.get('SUPABASE_URL')!; - const supabaseKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!; - const supabase = createClient(supabaseUrl, supabaseKey); - - console.log('Starting metrics collection...'); +export default createEdgeFunction( + { + name: 'collect-metrics', + requireAuth: false, + }, + async (req, context, supabase) => { + edgeLogger.info('Starting metrics collection', { requestId: context.requestId }); const metrics: MetricRecord[] = []; const timestamp = new Date().toISOString(); @@ -159,11 +152,17 @@ Deno.serve(async (req) => { .insert(metrics); if (insertError) { - console.error('Error inserting metrics:', insertError); + edgeLogger.error('Error inserting metrics', { + error: insertError, + requestId: context.requestId + }); throw insertError; } - console.log(`Successfully recorded ${metrics.length} metrics`); + edgeLogger.info('Successfully recorded metrics', { + count: metrics.length, + requestId: context.requestId + }); } return new Response( @@ -172,16 +171,7 @@ Deno.serve(async (req) => { metrics_collected: metrics.length, metrics: metrics.map(m => ({ name: m.metric_name, value: m.metric_value })), }), - { headers: { ...corsHeaders, 'Content-Type': 'application/json' } } - ); - } catch (error) { - console.error('Error in collect-metrics function:', error); - return new Response( - JSON.stringify({ error: error.message }), - { - status: 500, - headers: { ...corsHeaders, 'Content-Type': 'application/json' }, - } + { headers: { 'Content-Type': 'application/json' } } ); } -}); +); diff --git a/supabase/functions/detect-anomalies/index.ts b/supabase/functions/detect-anomalies/index.ts index d4bbd2b6..57388bed 100644 --- a/supabase/functions/detect-anomalies/index.ts +++ b/supabase/functions/detect-anomalies/index.ts @@ -1,9 +1,6 @@ import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.57.4'; - -const corsHeaders = { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', -}; +import { createEdgeFunction } from '../_shared/edgeFunctionWrapper.ts'; +import { edgeLogger } from '../_shared/logger.ts'; interface MetricData { timestamp: string; @@ -291,17 +288,13 @@ class AnomalyDetector { } } -Deno.serve(async (req) => { - if (req.method === 'OPTIONS') { - return new Response(null, { headers: corsHeaders }); - } - - try { - const supabaseUrl = Deno.env.get('SUPABASE_URL')!; - const supabaseKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!; - const supabase = createClient(supabaseUrl, supabaseKey); - - console.log('Starting anomaly detection run...'); +export default createEdgeFunction( + { + name: 'detect-anomalies', + requireAuth: false, + }, + async (req, context, supabase) => { + edgeLogger.info('Starting anomaly detection run', { requestId: context.requestId }); // Get all enabled anomaly detection configurations const { data: configs, error: configError } = await supabase @@ -314,7 +307,10 @@ Deno.serve(async (req) => { throw configError; } - console.log(`Processing ${configs?.length || 0} metric configurations`); + edgeLogger.info('Processing metric configurations', { + count: configs?.length || 0, + requestId: context.requestId + }); const anomaliesDetected: any[] = []; @@ -338,7 +334,11 @@ Deno.serve(async (req) => { const data = metricData as MetricData[]; if (!data || data.length < config.min_data_points) { - console.log(`Insufficient data for ${config.metric_name}: ${data?.length || 0} points`); + edgeLogger.info('Insufficient data for metric', { + metric: config.metric_name, + points: data?.length || 0, + requestId: context.requestId + }); continue; } @@ -464,7 +464,10 @@ Deno.serve(async (req) => { } } - console.log(`Anomaly detection complete. Detected ${anomaliesDetected.length} anomalies`); + edgeLogger.info('Anomaly detection complete', { + detected: anomaliesDetected.length, + requestId: context.requestId + }); return new Response( JSON.stringify({ @@ -472,16 +475,7 @@ Deno.serve(async (req) => { anomalies_detected: anomaliesDetected.length, anomalies: anomaliesDetected, }), - { headers: { ...corsHeaders, 'Content-Type': 'application/json' } } - ); - } catch (error) { - console.error('Error in detect-anomalies function:', error); - return new Response( - JSON.stringify({ error: error.message }), - { - status: 500, - headers: { ...corsHeaders, 'Content-Type': 'application/json' }, - } + { headers: { 'Content-Type': 'application/json' } } ); } -}); +); diff --git a/supabase/functions/monitor-rate-limits/index.ts b/supabase/functions/monitor-rate-limits/index.ts index 0943ad27..e383748d 100644 --- a/supabase/functions/monitor-rate-limits/index.ts +++ b/supabase/functions/monitor-rate-limits/index.ts @@ -8,13 +8,10 @@ */ import { createClient } from 'jsr:@supabase/supabase-js@2'; +import { createEdgeFunction } from '../_shared/edgeFunctionWrapper.ts'; +import { edgeLogger } from '../_shared/logger.ts'; import { getMetricsStats } from '../_shared/rateLimitMetrics.ts'; -const corsHeaders = { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', -}; - interface AlertConfig { id: string; metric_type: 'block_rate' | 'total_requests' | 'unique_ips' | 'function_specific'; @@ -159,19 +156,14 @@ async function sendNotification( } } -async function handler(req: Request): Promise { - // Handle CORS preflight - if (req.method === 'OPTIONS') { - return new Response(null, { headers: corsHeaders }); - } - - const startTime = Date.now(); - console.log('Rate limit monitor starting...'); - - try { - const supabaseUrl = Deno.env.get('SUPABASE_URL')!; - const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!; - const supabase = createClient(supabaseUrl, supabaseServiceKey); +export default createEdgeFunction( + { + name: 'monitor-rate-limits', + requireAuth: false, + }, + async (req, context, supabase) => { + const startTime = Date.now(); + edgeLogger.info('Rate limit monitor starting', { requestId: context.requestId }); // Fetch enabled alert configurations const { data: configs, error: configError } = await supabase @@ -180,41 +172,48 @@ async function handler(req: Request): Promise { .eq('enabled', true); if (configError) { - console.error('Failed to fetch alert configs:', configError); - return new Response( - JSON.stringify({ - success: false, - error: 'Failed to fetch alert configurations', - details: configError.message - }), - { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } - ); + edgeLogger.error('Failed to fetch alert configs', { + error: configError, + requestId: context.requestId + }); + throw configError; } if (!configs || configs.length === 0) { - console.log('No enabled alert configurations found'); + edgeLogger.info('No enabled alert configurations found', { + requestId: context.requestId + }); return new Response( JSON.stringify({ success: true, message: 'No enabled alert configurations', checked: 0 }), - { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } + { headers: { 'Content-Type': 'application/json' } } ); } - console.log(`Checking ${configs.length} alert configurations...`); + edgeLogger.info('Checking alert configurations', { + count: configs.length, + requestId: context.requestId + }); // Check all alert conditions const checks = await checkAlertConditions(configs); const exceededChecks = checks.filter(c => c.exceeded); - console.log(`Found ${exceededChecks.length} threshold violations`); + edgeLogger.info('Threshold violations found', { + count: exceededChecks.length, + requestId: context.requestId + }); // Process exceeded thresholds const alertResults = []; for (const check of exceededChecks) { - console.log(`Processing alert: ${check.message}`); + edgeLogger.info('Processing alert', { + message: check.message, + requestId: context.requestId + }); // Check if we've already sent a recent alert for this config const { data: recentAlerts } = await supabase @@ -227,7 +226,10 @@ async function handler(req: Request): Promise { .limit(1); if (recentAlerts && recentAlerts.length > 0) { - console.log(`Skipping alert - recent unresolved alert exists for config ${check.configId}`); + edgeLogger.info('Skipping alert - recent unresolved alert exists', { + configId: check.configId, + requestId: context.requestId + }); alertResults.push({ configId: check.configId, skipped: true, @@ -253,7 +255,10 @@ async function handler(req: Request): Promise { } const duration = Date.now() - startTime; - console.log(`Monitor completed in ${duration}ms`); + edgeLogger.info('Monitor completed', { + duration, + requestId: context.requestId + }); return new Response( JSON.stringify({ @@ -263,20 +268,7 @@ async function handler(req: Request): Promise { alerts: alertResults, duration_ms: duration, }), - { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } - ); - - } catch (error) { - console.error('Error in rate limit monitor:', error); - return new Response( - JSON.stringify({ - success: false, - error: 'Internal server error', - message: error instanceof Error ? error.message : 'Unknown error', - }), - { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } + { headers: { 'Content-Type': 'application/json' } } ); } -} - -Deno.serve(handler); +);