File size: 2,678 Bytes
cd8bd0a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/**
 * Request Logger Plugin — logs API requests and responses with timing.
 *
 * @module request-logger
 */

const LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };

function shouldLog(configLevel, messageLevel) {
  return (LEVELS[messageLevel] ?? 1) >= (LEVELS[configLevel] ?? 1);
}

function truncate(str, max) {
  if (typeof str !== "string") return str;
  return str.length > max ? str.slice(0, max) + "..." : str;
}

function formatBody(body, maxLen) {
  if (body === undefined || body === null) return undefined;
  try {
    const json = JSON.stringify(body);
    return truncate(json, maxLen);
  } catch {
    return truncate(String(body), maxLen);
  }
}

/**
 * onRequest hook — records request start time and logs request details.
 */
export function onRequest(ctx) {
  const config = ctx?.config || {};
  const level = config.logLevel || "info";

  if (ctx?.metadata) {
    ctx.metadata.__requestStart = Date.now();
  }

  if (shouldLog(level, "info")) {
    const logEntry = {
      timestamp: new Date().toISOString(),
      requestId: ctx.requestId,
      model: ctx.model,
      provider: ctx.provider,
      method: ctx.method || "POST",
    };

    if (config.includeBody) {
      logEntry.body = formatBody(ctx.body, config.maxBodyLength || 500);
    }

    console.log("[request-logger] REQUEST:", JSON.stringify(logEntry));
  }
}

/**
 * onResponse hook — logs response with timing.
 */
export function onResponse(ctx, response) {
  const config = ctx?.config || {};
  const level = config.logLevel || "info";
  const startTime = ctx?.metadata?.__requestStart || Date.now();
  const duration = Date.now() - startTime;

  if (shouldLog(level, "info")) {
    const logEntry = {
      timestamp: new Date().toISOString(),
      requestId: ctx.requestId,
      model: ctx.model,
      durationMs: duration,
      status: response?.status || 200,
    };

    if (config.includeBody && response?.data) {
      logEntry.response = formatBody(response.data, config.maxBodyLength || 500);
    }

    console.log("[request-logger] RESPONSE:", JSON.stringify(logEntry));
  }

  return response;
}

/**
 * onError hook — logs errors with context.
 */
export function onError(ctx, error) {
  const config = ctx?.config || {};
  const level = config.logLevel || "info";
  const startTime = ctx?.metadata?.__requestStart || Date.now();
  const duration = Date.now() - startTime;

  if (shouldLog(level, "error")) {
    console.error("[request-logger] ERROR:", JSON.stringify({
      timestamp: new Date().toISOString(),
      requestId: ctx.requestId,
      model: ctx.model,
      durationMs: duration,
      error: error?.message || String(error),
    }));
  }
}