All files / src/app/api/health route.ts

0% Statements 0/53
100% Branches 0/0
0% Functions 0/1
0% Lines 0/53

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54                                                                                                           
export const dynamic = "force-dynamic";

import { NextResponse } from 'next/server';
import { prisma } from '@/lib/prisma';

export async function GET() {
  const checks = {
    status: 'healthy' as 'healthy' | 'degraded' | 'unhealthy',
    timestamp: new Date().toISOString(),
    services: {
      database: 'unknown' as string,
      memory: 'unknown' as string
    },
    metrics: {
      dbLatency: 0,
      heapUsedMB: 0
    }
  };

  try {
    // Database check
    const dbStart = performance.now();
    await prisma.$queryRaw`SELECT 1`;
    const dbLatency = performance.now() - dbStart;

    checks.metrics.dbLatency = Math.round(dbLatency);
    checks.services.database = dbLatency < 100 ? 'healthy' : dbLatency < 500 ? 'degraded' : 'unhealthy';

    // Memory check
    const memUsage = process.memoryUsage();
    const heapUsedMB = Math.round(memUsage.heapUsed / 1024 / 1024);

    checks.metrics.heapUsedMB = heapUsedMB;
    checks.services.memory = heapUsedMB < 500 ? 'healthy' : heapUsedMB < 1000 ? 'degraded' : 'unhealthy';

    // Overall status
    const statuses = Object.values(checks.services);
    if (statuses.includes('unhealthy')) {
      checks.status = 'unhealthy';
    } else if (statuses.includes('degraded')) {
      checks.status = 'degraded';
    }

    return NextResponse.json(checks, {
      status: checks.status === 'unhealthy' ? 503 : 200
    });
  } catch {
    checks.status = 'unhealthy';
    checks.services.database = 'unhealthy';

    return NextResponse.json(checks, { status: 503 });
  }
}