Skip to content

Monitoring ​

Set up observability for your self-hosted Scry instance.

Overview ​

Monitor these components:

ComponentMonitoring
Upload ServiceCloudflare Analytics, Worker Logs
CDN ServiceCloudflare Analytics, Worker Logs
DashboardVercel Analytics, Error tracking
FirebaseFirebase Console, Cloud Monitoring
R2 StorageCloudflare Dashboard

Cloudflare Workers ​

Analytics Dashboard ​

  1. Go to Cloudflare Dashboard → Workers
  2. Select your worker
  3. View Analytics tab

Key metrics:

  • Requests: Total and requests/second
  • Errors: Error rate and types
  • CPU Time: Execution duration
  • Data Transfer: Bytes in/out

Real-time Logs ​

Use wrangler tail for live logs:

bash
# Upload Service
wrangler tail scry-upload-service

# CDN Service
wrangler tail scry-cdn-service

# Filter by status
wrangler tail scry-upload-service --format=json | jq 'select(.outcome == "exception")'

Custom Logging ​

Add structured logging to your workers:

typescript
console.log(JSON.stringify({
  level: 'info',
  message: 'Upload completed',
  projectId: project,
  version: version,
  size: bytes,
  duration: ms
}));

Firebase Monitoring ​

Firestore Usage ​

  1. Go to Firebase Console → Usage and billing
  2. View Firestore usage:
    • Reads/writes per day
    • Storage used
    • Network egress

Authentication Metrics ​

  1. Go to Authentication → Usage
  2. View:
    • Daily active users
    • Sign-in methods
    • Authentication failures

Cloud Monitoring (Advanced) ​

Enable Google Cloud Monitoring:

  1. Go to Google Cloud Console
  2. Navigate to Monitoring
  3. Create dashboard for Firebase metrics

Key metrics:

  • firestore.googleapis.com/document/read_count
  • firestore.googleapis.com/document/write_count
  • identitytoolkit.googleapis.com/request_count

Vercel Dashboard ​

Built-in Analytics ​

Enable in Project Settings → Analytics:

  • Page views: Traffic patterns
  • Web Vitals: Performance metrics
  • Functions: Serverless function usage

Deployment Monitoring ​

View in Deployments tab:

  • Build duration
  • Build size
  • Deployment status

Error Tracking ​

Integrate with error tracking services:

typescript
// lib/error-tracking.ts
export function captureError(error: Error, context?: object) {
  console.error('Application error:', error, context);

  // Send to external service (Sentry, etc.)
  if (process.env.SENTRY_DSN) {
    Sentry.captureException(error, { extra: context });
  }
}

Alerting ​

Cloudflare Alerts ​

  1. Go to Cloudflare Dashboard → Notifications
  2. Create alerts for:
    • Worker error rate > 1%
    • Worker requests spike
    • R2 storage usage

Firebase Alerts ​

  1. Go to Firebase Console → Settings → Integrations
  2. Configure budget alerts
  3. Set up Cloud Monitoring alerts

Uptime Monitoring ​

Use external monitoring services:

bash
# Health check endpoints
# Upload Service
https://your-upload-service.workers.dev/health

# CDN Service
https://view-test.yourdomain.com/health

# Dashboard
https://dashboard.yourdomain.com/api/health

Recommended services:

  • UptimeRobot (free tier available)
  • Better Uptime
  • Pingdom

Custom Health Checks ​

Upload Service Health ​

typescript
// Already included
app.get('/health', (c) => {
  return c.json({
    status: 'ok',
    timestamp: new Date().toISOString(),
    version: '1.0.0'
  });
});

CDN Service Health ​

typescript
// Already included
app.get('/health', (c) => {
  return c.json({
    status: 'healthy',
    service: 'scry-cdn-service',
    platform: 'cloudflare',
    timestamp: new Date().toISOString()
  });
});

Dashboard Health ​

Create app/api/health/route.ts:

typescript
export async function GET() {
  const health = {
    status: 'ok',
    timestamp: new Date().toISOString(),
    checks: {
      firebase: await checkFirebase(),
    }
  };

  return Response.json(health);
}

async function checkFirebase() {
  try {
    // Quick Firestore ping
    const db = getFirestore();
    await db.collection('_health').doc('ping').get();
    return 'ok';
  } catch {
    return 'error';
  }
}

Logging Best Practices ​

Structured Logs ​

Use JSON format for searchability:

typescript
function log(level: string, message: string, data?: object) {
  console.log(JSON.stringify({
    level,
    message,
    timestamp: new Date().toISOString(),
    ...data
  }));
}

// Usage
log('info', 'Upload started', { projectId, version, size });
log('error', 'Upload failed', { projectId, error: err.message });

Log Levels ​

LevelUse Case
debugDetailed debugging info
infoNormal operations
warnUnexpected but handled
errorFailures requiring attention

Sensitive Data ​

Never log:

  • API keys
  • Passwords
  • Personal information
  • Full request bodies

Metrics Dashboard ​

Grafana (Self-hosted) ​

For advanced monitoring, set up Grafana:

yaml
# docker-compose.yml
services:
  grafana:
    image: grafana/grafana
    ports:
      - "3001:3000"
    volumes:
      - grafana-data:/var/lib/grafana

  prometheus:
    image: prom/prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml

volumes:
  grafana-data:

Key Metrics to Track ​

MetricDescriptionAlert Threshold
Request rateRequests per secondSudden spike
Error rate% of 4xx/5xx> 1%
Latency p9999th percentile response time> 1s
Storage usedR2 bucket size> 80% quota
API key usageRequests per keyUnusual patterns

Incident Response ​

Runbook Template ​

markdown
## Incident: [Description]

### Detection
- How was the issue detected?
- What alerts fired?

### Impact
- Which services affected?
- Number of users impacted?

### Timeline
- [Time] Issue detected
- [Time] Investigation started
- [Time] Root cause identified
- [Time] Fix deployed
- [Time] Issue resolved

### Root Cause
[Description of what caused the issue]

### Resolution
[Steps taken to resolve]

### Prevention
[Steps to prevent recurrence]

Common Issues ​

High error rate:

  1. Check Worker logs
  2. Verify R2 connectivity
  3. Check Firebase status
  4. Review recent deployments

Slow responses:

  1. Check Worker CPU time
  2. Review KV cache hit rate
  3. Check R2 latency
  4. Analyze request patterns

Authentication failures:

  1. Check Firebase Auth status
  2. Verify API key validity
  3. Review Firestore rules
  4. Check rate limits

Next Steps ​