summaryrefslogtreecommitdiff
path: root/lib/integration-log/rest-logging.ts
blob: e84d656dcceabd939c0627fa592391950fe7ae50 (plain)
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
"use server";

import { logIntegrationExecution } from "./service";

/**
 * REST API 호출 로깅 래퍼 함수
 * 
 * @description
 * REST API 호출을 자동으로 로깅하는 래퍼 함수입니다. 
 * 요청 시작부터 완료까지의 시간을 측정하고, 성공/실패 여부를 기록합니다.
 * 
 * @param integrationId 인터페이스 ID (추후 매핑 필요)
 * @param url 요청 URL
 * @param method HTTP 메소드
 * @param requestData 요청 데이터
 * @param processor 실제 fetch 함수
 * @returns 처리 결과
 * 
 * @example
 * // 기본 사용법 - 커스텀 처리 함수와 함께
 * const result = await withRestLogging(
 *   1, // 인터페이스 ID
 *   'https://api.example.com/users',
 *   'GET',
 *   undefined,
 *   async () => {
 *     const response = await fetch('https://api.example.com/users');
 *     return response.json();
 *   }
 * );
 * 
 * @example
 * // POST 요청 with 데이터
 * const userData = { name: 'John', email: 'john@example.com' };
 * const createdUser = await withRestLogging(
 *   2,
 *   'https://api.example.com/users',
 *   'POST',
 *   userData,
 *   async () => {
 *     const response = await fetch('https://api.example.com/users', {
 *       method: 'POST',
 *       headers: { 'Content-Type': 'application/json' },
 *       body: JSON.stringify(userData)
 *     });
 *     return response.json();
 *   }
 * );
 * 
 * @example
 * // 에러 처리와 함께
 * try {
 *   const result = await withRestLogging(
 *     3,
 *     'https://api.example.com/data',
 *     'GET',
 *     undefined,
 *     async () => {
 *       const response = await fetch('https://api.example.com/data');
 *       if (!response.ok) {
 *         throw new Error(`API Error: ${response.status}`);
 *       }
 *       return response.json();
 *     }
 *   );
 * } catch (error) {
 *   console.error('API 호출 실패:', error);
 * }
 */
export async function withRestLogging<T>(
  integrationId: number,
  url: string,
  method: string,
  requestData?: unknown,
  processor?: () => Promise<T>
): Promise<T> {
  const start = Date.now();
  
  try {
    let result: T;
    
    if (processor) {
      // 커스텀 처리 함수가 있는 경우
      result = await processor();
    } else {
      // 기본 fetch 처리
      const response = await fetch(url, {
        method,
        headers: {
          'Content-Type': 'application/json',
        },
        body: requestData ? JSON.stringify(requestData) : undefined,
      });
      
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }
      
      result = await response.json() as T;
    }
    
    const duration = Date.now() - start;
    
    // 성공 로그 기록
    await logIntegrationExecution({
      integrationId,
      status: 'success',
      responseTime: duration,
      requestMethod: method,
      requestUrl: url,
      correlationId: `rest_${Date.now()}`,
    });
    
    return result;
    
  } catch (error) {
    const duration = Date.now() - start;
    
    // 실패 로그 기록
    await logIntegrationExecution({
      integrationId,
      status: 'failed',
      responseTime: duration,
      errorMessage: error instanceof Error ? error.message : 'Unknown error',
      requestMethod: method,
      requestUrl: url,
      correlationId: `rest_${Date.now()}`,
    });
    
    throw error;
  }
}

/**
 * 기존 fetch 호출을 로깅 버전으로 래핑하는 헬퍼 함수
 * 
 * @description
 * 표준 fetch API를 사용하면서 자동으로 로깅하고 싶을 때 사용하는 헬퍼 함수입니다.
 * 기존 fetch 호출을 최소한의 변경으로 로깅 기능을 추가할 수 있습니다.
 * 
 * @param integrationId 인터페이스 ID
 * @param url 요청 URL
 * @param options fetch 옵션
 * @returns fetch 결과
 * 
 * @example
 * // 기본 GET 요청
 * const response = await fetchWithLogging(
 *   1,
 *   'https://api.example.com/users'
 * );
 * const users = await response.json();
 * 
 * @example
 * // POST 요청 with 옵션
 * const response = await fetchWithLogging(
 *   2,
 *   'https://api.example.com/users',
 *   {
 *     method: 'POST',
 *     headers: {
 *       'Content-Type': 'application/json',
 *       'Authorization': 'Bearer token'
 *     },
 *     body: JSON.stringify({ name: 'John' })
 *   }
 * );
 * 
 * @example
 * // 기존 fetch 호출 대체
 * // 기존: const response = await fetch('/api/data');
 * // 새로운: const response = await fetchWithLogging(1, '/api/data');
 */
export async function fetchWithLogging(
  integrationId: number,
  url: string,
  options: RequestInit = {}
): Promise<Response> {
  return withRestLogging(
    integrationId,
    url,
    options.method || 'GET',
    options.body,
    async () => {
      return fetch(url, options);
    }
  );
}