Skip to main content

Monitoring and Analytics Setup

Complete guide for setting up monitoring, error tracking, and analytics for Dashtray.

Overview

This guide covers:
  1. Error tracking with Sentry
  2. Uptime monitoring
  3. Performance monitoring
  4. Usage analytics
  5. Alert configuration

1. Error Tracking (Sentry)

1.1 Create Sentry Account

  1. Sign up at sentry.io
  2. Create a new organization: “Dashtray”
  3. Create a new project:
    • Platform: SvelteKit
    • Name: “dashtray-production”

1.2 Install Sentry SDK

pnpm add @sentry/sveltekit

1.3 Configure Sentry

Create src/hooks.client.ts:
import * as Sentry from '@sentry/sveltekit';

Sentry.init({
  dsn: 'https://your-dsn@sentry.io/your-project-id',
  environment: import.meta.env.MODE,

  // Performance monitoring
  tracesSampleRate: 0.1, // 10% of transactions

  // Session replay (optional)
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,

  // Filter sensitive data
  beforeSend(event) {
    // Remove sensitive data
    if (event.request) {
      delete event.request.cookies;
      delete event.request.headers;
    }
    return event;
  },

  // Ignore certain errors
  ignoreErrors: [
    'ResizeObserver loop limit exceeded',
    'Non-Error promise rejection captured'
  ]
});
Create src/hooks.server.ts:
import * as Sentry from '@sentry/sveltekit';

Sentry.init({
  dsn: 'https://your-dsn@sentry.io/your-project-id',
  environment: import.meta.env.MODE,
  tracesSampleRate: 0.1
});

export const handleError = Sentry.handleErrorWithSentry();

1.4 Add Sentry to Convex

In Convex functions, log errors to Sentry:
// src/convex/lib/errorTracking.ts
export async function logError(
  error: Error,
  context: {
    userId?: string;
    projectId?: string;
    action?: string;
  }
) {
  // Log to console
  console.error('Error:', error.message, context);

  // In production, send to Sentry via HTTP
  if (process.env.NODE_ENV === 'production') {
    try {
      await fetch('https://sentry.io/api/your-project/store/', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-Sentry-Auth': `Sentry sentry_key=your-key`
        },
        body: JSON.stringify({
          message: error.message,
          level: 'error',
          extra: context
        })
      });
    } catch (e) {
      // Fail silently
    }
  }
}

1.5 Configure Alerts

In Sentry dashboard:
  1. Go to Alerts → Create Alert
  2. Configure alert rules:
    • High error rate: > 10 errors in 5 minutes
    • New error: First occurrence of an error
    • Regression: Error that was resolved returns
  3. Set notification channels:
    • Email
    • Slack
    • PagerDuty (for critical alerts)

1.6 Set Up Releases

Track deployments in Sentry:
# Install Sentry CLI
pnpm add -D @sentry/cli

# Create release
npx sentry-cli releases new $(git rev-parse HEAD)
npx sentry-cli releases set-commits $(git rev-parse HEAD) --auto
npx sentry-cli releases finalize $(git rev-parse HEAD)
Add to CI/CD pipeline:
# .github/workflows/deploy.yml
- name: Create Sentry release
  run: |
    npx sentry-cli releases new ${{ github.sha }}
    npx sentry-cli releases set-commits ${{ github.sha }} --auto
    npx sentry-cli releases finalize ${{ github.sha }}
  env:
    SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
    SENTRY_ORG: dashtray
    SENTRY_PROJECT: dashtray-production

2. Uptime Monitoring

2.1 UptimeRobot (Free)

  1. Sign up at uptimerobot.com
  2. Create monitors:
Main Site:
  • Type: HTTPS
  • URL: https://dashtray.com
  • Interval: 5 minutes
  • Alert contacts: Email, Slack
API Health Check:
  • Type: HTTPS
  • URL: https://dashtray.com/api/health
  • Interval: 5 minutes
  • Alert contacts: Email, Slack
Convex Backend:
  • Type: HTTPS
  • URL: https://your-deployment.convex.site/api/health
  • Interval: 5 minutes
  • Alert contacts: Email, Slack

2.2 Create Health Check Endpoint

// src/routes/api/health/+server.ts
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';

export const GET: RequestHandler = async () => {
  try {
    // Check Convex connection
    // Check database
    // Check critical services

    return json({
      status: 'healthy',
      timestamp: new Date().toISOString(),
      version: process.env.VERSION || 'unknown'
    });
  } catch (error) {
    return json(
      {
        status: 'unhealthy',
        error: error instanceof Error ? error.message : 'Unknown error'
      },
      { status: 503 }
    );
  }
};

2.3 Configure Alerts

In UptimeRobot:
  1. Go to Alert Contacts
  2. Add contacts:
  3. Set alert thresholds:
    • Alert after: 2 failed checks
    • Alert frequency: Every 5 minutes until resolved

3. Performance Monitoring

3.1 Convex Dashboard

  1. Go to Convex Dashboard
  2. Select your production deployment
  3. Monitor:
    • Function execution times
    • Database query performance
    • Cron job status
    • Error rates

3.2 Set Up Convex Alerts

In Convex dashboard:
  1. Go to Settings → Alerts
  2. Configure alerts:
    • Function duration > 5s
    • Database query time > 1s
    • Error rate > 1%
    • Cron job failures

3.3 Cloudflare Analytics

  1. Go to Cloudflare Pages dashboard
  2. View analytics:
    • Page views
    • Unique visitors
    • Bandwidth usage
    • Response times
    • Error rates (4xx, 5xx)

3.4 Web Vitals Monitoring

Add Web Vitals tracking:
// src/lib/analytics/webVitals.ts
import { onCLS, onFID, onLCP, onFCP, onTTFB } from 'web-vitals';

function sendToAnalytics(metric: any) {
  // Send to your analytics service
  if (import.meta.env.PROD) {
    fetch('/api/analytics/vitals', {
      method: 'POST',
      body: JSON.stringify(metric),
      headers: { 'Content-Type': 'application/json' }
    });
  }
}

export function initWebVitals() {
  onCLS(sendToAnalytics);
  onFID(sendToAnalytics);
  onLCP(sendToAnalytics);
  onFCP(sendToAnalytics);
  onTTFB(sendToAnalytics);
}
Use in src/routes/+layout.svelte:
<script lang="ts">
  import { onMount } from 'svelte';
  import { initWebVitals } from '$lib/analytics/webVitals';

  onMount(() => {
    initWebVitals();
  });
</script>

4. Usage Analytics

4.1 Plausible Analytics (Privacy-Friendly)

  1. Sign up at plausible.io
  2. Add your domain: dashtray.com
  3. Get tracking script
Add to src/app.html:
<script defer data-domain="dashtray.com" src="https://plausible.io/js/script.js"></script>

4.2 Track Custom Events

// src/lib/analytics/plausible.ts
export function trackEvent(eventName: string, props?: Record<string, any>) {
  if (typeof window !== 'undefined' && (window as any).plausible) {
    (window as any).plausible(eventName, { props });
  }
}
Track important events:
// User signs up
trackEvent('signup', { method: 'email' });

// User connects integration
trackEvent('integration_connected', { service: 'stripe' });

// User upgrades
trackEvent('subscription_upgrade', { tier: 'pro' });

// User creates dashboard
trackEvent('dashboard_created', { type: 'custom' });

4.3 Convex Usage Tracking

Track usage in Convex:
// src/convex/analytics.ts
import { mutation } from './_generated/server';
import { v } from 'convex/values';

export const trackEvent = mutation({
  args: {
    event: v.string(),
    properties: v.optional(v.any())
  },
  handler: async (ctx, args) => {
    const userId = await getCurrentUserId(ctx);

    await ctx.db.insert('analyticsEvents', {
      userId,
      event: args.event,
      properties: args.properties,
      timestamp: Date.now()
    });
  }
});

5. Business Metrics Dashboard

5.1 Key Metrics to Track

User Metrics:
  • Total users
  • Active users (DAU, WAU, MAU)
  • New signups per day
  • Churn rate
  • User retention
Revenue Metrics:
  • MRR (Monthly Recurring Revenue)
  • ARR (Annual Recurring Revenue)
  • ARPU (Average Revenue Per User)
  • Conversion rate (Free → Paid)
  • Churn rate
Product Metrics:
  • Integrations connected per user
  • Dashboards created per user
  • Alerts created per user
  • API usage (Scale+ users)
  • Feature adoption rates
Technical Metrics:
  • Error rate
  • Response time (p50, p95, p99)
  • Uptime percentage
  • Database query performance
  • Function execution time

5.2 Create Analytics Dashboard

Use Convex queries to aggregate metrics:
// src/convex/analytics.ts
export const getMetrics = query({
  handler: async (ctx) => {
    const now = Date.now();
    const thirtyDaysAgo = now - 30 * 24 * 60 * 60 * 1000;

    // Total users
    const totalUsers = await ctx.db.query('users').collect();

    // Active users (last 30 days)
    const activeUsers = totalUsers.filter(
      user => user.lastActiveAt && user.lastActiveAt > thirtyDaysAgo
    );

    // New signups (last 30 days)
    const newSignups = totalUsers.filter(
      user => user.createdAt > thirtyDaysAgo
    );

    // Total projects
    const projects = await ctx.db.query('projects').collect();

    // Active subscriptions
    const activeSubscriptions = projects.filter(
      p => p.subscriptionStatus === 'active' && p.subscriptionTier !== 'free'
    );

    // Calculate MRR
    const mrr = activeSubscriptions.reduce((sum, project) => {
      const tierPrices = { pro: 69, scale: 199, agency: 599 };
      return sum + (tierPrices[project.subscriptionTier] || 0);
    }, 0);

    return {
      users: {
        total: totalUsers.length,
        active: activeUsers.length,
        new: newSignups.length
      },
      revenue: {
        mrr,
        arr: mrr * 12,
        activeSubscriptions: activeSubscriptions.length
      },
      projects: {
        total: projects.length,
        free: projects.filter(p => p.subscriptionTier === 'free').length,
        paid: activeSubscriptions.length
      }
    };
  }
});

5.3 Visualize Metrics

Create an internal admin dashboard:
<!-- src/routes/(admin)/admin/metrics/+page.svelte -->
<script lang="ts">
  import { useQuery } from 'convex-svelte';
  import { api } from '$convex/_generated/api';

  const metrics = useQuery(api.analytics.getMetrics);
</script>

{#if $metrics}
  <div class="grid grid-cols-3 gap-4">
    <div class="card">
      <h3>Total Users</h3>
      <p class="text-4xl">{$metrics.users.total}</p>
      <p class="text-sm text-gray-600">
        {$metrics.users.new} new this month
      </p>
    </div>

    <div class="card">
      <h3>MRR</h3>
      <p class="text-4xl">${$metrics.revenue.mrr.toLocaleString()}</p>
      <p class="text-sm text-gray-600">
        {$metrics.revenue.activeSubscriptions} active subscriptions
      </p>
    </div>

    <div class="card">
      <h3>Projects</h3>
      <p class="text-4xl">{$metrics.projects.total}</p>
      <p class="text-sm text-gray-600">
        {$metrics.projects.paid} paid
      </p>
    </div>
  </div>
{/if}

6. Log Aggregation

6.1 Convex Logs

View logs in real-time:
# Tail production logs
npx convex logs --prod --tail

# Filter by function
npx convex logs --prod --function=projects:create

# Filter by level
npx convex logs --prod --level=error

6.2 Structured Logging

Use structured logging in Convex:
// src/convex/lib/logger.ts
export function log(
  level: 'info' | 'warn' | 'error',
  message: string,
  context?: Record<string, any>
) {
  const logEntry = {
    level,
    message,
    timestamp: new Date().toISOString(),
    ...context
  };

  console.log(JSON.stringify(logEntry));
}

// Usage
log('info', 'User signed up', { userId: 'user_123', method: 'email' });
log('error', 'Failed to sync metrics', { connectionId: 'conn_456', error: 'API timeout' });

7. Alert Configuration

7.1 Critical Alerts (PagerDuty)

For critical issues that require immediate attention:
  1. Sign up at pagerduty.com
  2. Create service: “Dashtray Production”
  3. Set up escalation policy
  4. Integrate with Sentry and UptimeRobot
Critical alerts:
  • Site down (> 5 minutes)
  • Error rate > 5%
  • Payment processing failures
  • Database connection failures

7.2 Warning Alerts (Slack)

For issues that need attention but aren’t critical:
  1. Create Slack channel: #dashtray-alerts
  2. Add incoming webhook
  3. Configure integrations to post to Slack
Warning alerts:
  • Error rate > 1%
  • Response time > 2s
  • Webhook failures
  • Sync failures
  • Low disk space

7.3 Info Alerts (Email)

For informational notifications: Info alerts:
  • Daily metrics summary
  • Weekly usage report
  • Monthly revenue report
  • New user signups (digest)

8. Status Page

8.1 Create Status Page

Use statuspage.io or self-host:
  1. Create status page: status.dashtray.com
  2. Add components:
    • Website
    • API
    • Integrations
    • Payments
  3. Configure automated updates from UptimeRobot

8.2 Incident Management

When incidents occur:
  1. Detect: Monitoring alerts
  2. Acknowledge: Team member acknowledges
  3. Investigate: Diagnose the issue
  4. Update status page: Keep users informed
  5. Resolve: Fix the issue
  6. Post-mortem: Document and learn

9. Monitoring Checklist

Daily

  • Check error rates in Sentry
  • Review Convex logs for errors
  • Check uptime status
  • Monitor response times
  • Review user feedback

Weekly

  • Review performance trends
  • Check for slow queries
  • Review security alerts
  • Analyze usage patterns
  • Check for dependency updates

Monthly

  • Review all metrics
  • Analyze user growth
  • Review revenue metrics
  • Check infrastructure costs
  • Plan optimizations

10. Dashboards

10.1 Operations Dashboard

Create a dashboard with:
  • Current error rate
  • Response times (p50, p95, p99)
  • Active users
  • Recent errors
  • System health

10.2 Business Dashboard

Create a dashboard with:
  • MRR/ARR
  • User growth
  • Conversion rates
  • Churn rate
  • Feature adoption

10.3 Technical Dashboard

Create a dashboard with:
  • Function execution times
  • Database query performance
  • API usage
  • Webhook success rates
  • Integration health

Need Help?