File size: 1,799 Bytes
e8c33fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
const { env } = require('../configs/env');
const logger = require('./logger');

const MAX_ENTRIES = 500;
const memoryLog = [];

const logError = (error, context = {}) => {
  try {
    const err = error instanceof Error ? error : new Error(String(error ?? 'Unknown error'));
    const entry = {
      timestamp: new Date().toISOString(),
      type: err.name || 'Error',
      message: err.message || 'Unknown error',
      stack: err.stack || '',
      code: context.code || 'INTERNAL_SERVER_ERROR',
      statusCode: context.statusCode || 500,
      request: {
        url: context.req?.originalUrl || '',
        method: context.req?.method || '',
        ip: context.req?.ip || '',
        userAgent: context.req?.headers?.['user-agent'] || '',
        // Log field names only — not values, to protect sensitive data
        bodyFields: context.req?.body && typeof context.req.body === 'object' && !Array.isArray(context.req.body)
          ? Object.keys(context.req.body)
          : [],
      },
      userId: context.req?.user?.id || context.userId || '',
      env: env.nodeEnv,
    };

    logger.error("Request error", { type: entry.type, message: entry.message, code: entry.code, status: entry.statusCode });

    memoryLog.unshift(entry);
    if (memoryLog.length > MAX_ENTRIES) {
      memoryLog.length = MAX_ENTRIES;
    }

    if (env.isProduction) {
      // Lazy require to avoid loading Mongoose at startup if DB is not yet connected
      const ErrorLog = require('../models/ErrorLog');
      ErrorLog.create(entry).catch(() => {});
    }
  } catch {
    // logError must never throw — swallow all errors
  }
};

const getMemoryLog = () => [...memoryLog];

const clearMemoryLog = () => {
  memoryLog.length = 0;
};

module.exports = { logError, getMemoryLog, clearMemoryLog };