All files / src/lib prisma.ts

45.97% Statements 40/87
100% Branches 1/1
100% Functions 1/1
45.97% Lines 40/87

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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 881x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x                                                                                       12x 12x 12x 12x     12x 12x 12x 12x     12x 12x 12x 12x 1x 1x 1x 1x 1x 1x  
import { PrismaClient } from "@prisma/client";
 
// PrismaClient is attached to the `global` object in development to prevent
// exhausting your database connection limit.
// Learn more: https://pris.ly/d/help/next-js-best-practices
 
const SLOW_QUERY_THRESHOLD = parseInt(process.env.SLOW_QUERY_THRESHOLD || '100');
const LOG_ALL_QUERIES = process.env.LOG_ALL_QUERIES === 'true';
 
const globalForPrisma = global as unknown as { prisma: PrismaClient };
 
function createPrismaClient() {
  const client = new PrismaClient({
    log: [
      { level: 'query', emit: 'event' },
      { level: 'error', emit: 'event' },
      { level: 'warn', emit: 'event' },
    ]
  });
 
  // Query logging - import logger lazily to avoid circular dependencies
  client.$on('query', async (e) => {
    const duration = e.duration;

    // Track query metrics for monitoring dashboard
    // Import lazily to avoid circular dependencies
    const { trackSlowQuery } = await import('@/lib/database/metrics');
    trackSlowQuery({
      query: e.query,
      duration,
      timestamp: new Date()
    });

    if (duration > SLOW_QUERY_THRESHOLD) {
      // Import logger lazily
      const { monitoringLogger } = await import('@/lib/monitoring/logger');
      monitoringLogger.warn('DATABASE', 'Slow query detected', {
        duration,
        query: e.query.substring(0, 1000), // Include query in error log for debugging
        params: e.params.substring(0, 500), // Include params (truncated)
      });

      // Store slow query metric in production
      if (process.env.NODE_ENV === 'production') {
        client.performanceMetric.create({
          data: {
            type: 'database',
            name: 'slow_query',
            duration,
            metadata: {
              query: e.query.substring(0, 1000),
              params: e.params.substring(0, 500)
            }
          }
        }).catch(() => { });
      }
    } else if (LOG_ALL_QUERIES || process.env.NODE_ENV === 'development') {
      // Import logger lazily
      import('@/lib/logging').then(({ logger }) => {
        logger.debug('Query executed', {
          category: 'DATABASE',
          duration,
        });
      });
    }
  });
 
  // Error logging
  client.$on('error', async (e) => {
    const { monitoringLogger } = await import('@/lib/monitoring/logger');
    monitoringLogger.error('DATABASE', 'Database error', new Error(e.message));
  });
 
  // Warning logging
  client.$on('warn', async (e) => {
    const { monitoringLogger } = await import('@/lib/monitoring/logger');
    monitoringLogger.warn('DATABASE', e.message);
  });
 
  return client;
}
 
export const prisma = globalForPrisma.prisma || createPrismaClient();
 
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
 
export default prisma;