@lark-apaas/client-toolkit 1.2.1-alpha.18 → 1.2.1-alpha.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -9,5 +9,9 @@ declare module 'axios' {
|
|
|
9
9
|
_requestUUID?: string;
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* 使用 Proxy 包装 Axios 实例,实现全链路 Trace 注入
|
|
14
|
+
* @param originalInstance 原始的 axios 实例
|
|
15
|
+
*/
|
|
16
|
+
export declare function wrapAxiosWithTrace(originalInstance: AxiosInstance): AxiosInstance;
|
|
17
|
+
export declare function initAxiosConfig(axiosInstance?: AxiosInstance): AxiosInstance;
|
package/lib/utils/axiosConfig.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import axios
|
|
1
|
+
import axios from "axios";
|
|
2
2
|
import { observable } from "@lark-apaas/observable-web";
|
|
3
3
|
import { logger } from "../apis/logger.js";
|
|
4
4
|
import { getStacktrace } from "../logger/selected-logs.js";
|
|
@@ -129,12 +129,8 @@ async function logResponse(ok, responseOrError) {
|
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
131
|
const requestStacktraceMap = new Map();
|
|
132
|
-
|
|
133
|
-
function
|
|
134
|
-
if (isPrototypeInjected) return;
|
|
135
|
-
isPrototypeInjected = true;
|
|
136
|
-
const originalRequest = Axios.prototype.request;
|
|
137
|
-
Axios.prototype.request = function(configOrUrl, config) {
|
|
132
|
+
function wrapAxiosWithTrace(originalInstance) {
|
|
133
|
+
const tracedRequest = function(configOrUrl, config) {
|
|
138
134
|
let finalConfig;
|
|
139
135
|
if ('string' == typeof configOrUrl) {
|
|
140
136
|
finalConfig = config || {};
|
|
@@ -158,78 +154,61 @@ function injectAxiosPrototype() {
|
|
|
158
154
|
}
|
|
159
155
|
}
|
|
160
156
|
} catch (e) {
|
|
161
|
-
console.error('
|
|
157
|
+
console.error('[ProxyTrace] Start axios trace span failed:', e);
|
|
162
158
|
}
|
|
163
|
-
const promise =
|
|
159
|
+
const promise = originalInstance.request.call(originalInstance, finalConfig);
|
|
164
160
|
return promise.then((response)=>{
|
|
165
|
-
|
|
166
|
-
const currentSpan = response.config?.__span;
|
|
167
|
-
if (currentSpan) {
|
|
168
|
-
const startTime = response.config._startTime;
|
|
169
|
-
const url = response.config.url || "";
|
|
170
|
-
const method = (response.config.method || 'GET').toUpperCase();
|
|
171
|
-
const path = url.split('?')[0] || '/';
|
|
172
|
-
const logData = {
|
|
173
|
-
method,
|
|
174
|
-
path,
|
|
175
|
-
url: response.request?.responseURL || url || "",
|
|
176
|
-
duration_ms: startTime ? Date.now() - startTime : void 0,
|
|
177
|
-
status: response.status
|
|
178
|
-
};
|
|
179
|
-
if ('undefined' != typeof navigator) logData.user_agent = navigator.userAgent;
|
|
180
|
-
if (response.config.data) logData.request_body = response.config.data;
|
|
181
|
-
if (response.data) logData.response = response.data || {};
|
|
182
|
-
observable.log('INFO', safeStringify(logData), {}, currentSpan);
|
|
183
|
-
'function' == typeof currentSpan.end && currentSpan.end();
|
|
184
|
-
}
|
|
185
|
-
} catch (e) {
|
|
186
|
-
console.error('Failed to log success span:', e);
|
|
187
|
-
}
|
|
161
|
+
handleSpanEnd(response.config, response, null);
|
|
188
162
|
return response;
|
|
189
163
|
}, (error)=>{
|
|
190
|
-
|
|
191
|
-
const errorConfig = error.config || {};
|
|
192
|
-
const currentSpan = errorConfig.__span;
|
|
193
|
-
if (currentSpan) {
|
|
194
|
-
const errorResponse = error.response || {};
|
|
195
|
-
const startTime = errorConfig._startTime;
|
|
196
|
-
const url = errorConfig.url || "";
|
|
197
|
-
const method = (errorConfig.method || 'GET').toUpperCase();
|
|
198
|
-
const path = url.split('?')[0] || '/';
|
|
199
|
-
const errorMessage = error.message || '未知错误';
|
|
200
|
-
const logData = {
|
|
201
|
-
method,
|
|
202
|
-
path,
|
|
203
|
-
url: errorResponse.request?.responseURL || errorConfig.url || "",
|
|
204
|
-
duration_ms: startTime ? Date.now() - startTime : void 0,
|
|
205
|
-
status: errorResponse.status || 200,
|
|
206
|
-
error_message: errorMessage
|
|
207
|
-
};
|
|
208
|
-
if ('undefined' != typeof navigator) logData.user_agent = navigator.userAgent;
|
|
209
|
-
if (errorConfig.data) logData.request_body = errorConfig.data;
|
|
210
|
-
if (errorResponse.data) logData.response = errorResponse.data || {};
|
|
211
|
-
observable.log('ERROR', safeStringify(logData), {}, currentSpan);
|
|
212
|
-
'function' == typeof currentSpan.end && currentSpan.end();
|
|
213
|
-
}
|
|
214
|
-
} catch (e) {
|
|
215
|
-
console.error('Failed to log error span:', e);
|
|
216
|
-
}
|
|
164
|
+
handleSpanEnd(error.config || finalConfig, null, error);
|
|
217
165
|
return Promise.reject(error);
|
|
218
166
|
});
|
|
219
167
|
};
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
168
|
+
function handleSpanEnd(cfg, response, error) {
|
|
169
|
+
try {
|
|
170
|
+
const currentSpan = cfg?.__span;
|
|
171
|
+
if (!currentSpan) return;
|
|
172
|
+
const startTime = cfg._startTime;
|
|
173
|
+
const url = cfg.url || "";
|
|
174
|
+
const method = (cfg.method || 'GET').toUpperCase();
|
|
175
|
+
const path = url.split('?')[0] || '/';
|
|
176
|
+
const errorResponse = error?.response || {};
|
|
177
|
+
const errorMessage = error?.message || '未知错误';
|
|
178
|
+
const logData = {
|
|
179
|
+
method,
|
|
180
|
+
path,
|
|
181
|
+
url: response?.request?.responseURL || errorResponse?.request?.responseURL || url || "",
|
|
182
|
+
duration_ms: startTime ? Date.now() - startTime : void 0,
|
|
183
|
+
status: response ? response.status : errorResponse.status || 0
|
|
184
|
+
};
|
|
185
|
+
if (error) logData.error_message = errorMessage;
|
|
186
|
+
if ('undefined' != typeof navigator) logData.user_agent = navigator.userAgent;
|
|
187
|
+
if (cfg.data) logData.request_body = cfg.data;
|
|
188
|
+
const responseData = response?.data || errorResponse?.data;
|
|
189
|
+
if (responseData) logData.response = responseData;
|
|
190
|
+
const level = error ? 'ERROR' : 'INFO';
|
|
191
|
+
observable.log(level, safeStringify(logData), {}, currentSpan);
|
|
192
|
+
'function' == typeof currentSpan.end && currentSpan.end();
|
|
193
|
+
} catch (e) {
|
|
194
|
+
console.error('[ProxyTrace] Log span failed:', e);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return new Proxy(originalInstance, {
|
|
198
|
+
apply (target, thisArg, args) {
|
|
199
|
+
return tracedRequest(...args);
|
|
200
|
+
},
|
|
201
|
+
get (target, prop, receiver) {
|
|
202
|
+
if ('request' === prop) return tracedRequest;
|
|
203
|
+
const value = Reflect.get(target, prop, receiver);
|
|
204
|
+
if ('function' == typeof value && 'create' !== prop) return value.bind(receiver);
|
|
205
|
+
return value;
|
|
206
|
+
}
|
|
207
|
+
});
|
|
229
208
|
}
|
|
230
209
|
function initAxiosConfig(axiosInstance) {
|
|
231
|
-
|
|
232
|
-
|
|
210
|
+
const instance = axiosInstance || axios;
|
|
211
|
+
instance.interceptors.request.use((config)=>{
|
|
233
212
|
const requestUUID = crypto.randomUUID();
|
|
234
213
|
if ('production' !== process.env.NODE_ENV) {
|
|
235
214
|
const stacktrace = getStacktrace();
|
|
@@ -241,12 +220,13 @@ function initAxiosConfig(axiosInstance) {
|
|
|
241
220
|
if (csrfToken) config.headers['X-Suda-Csrf-Token'] = csrfToken;
|
|
242
221
|
return config;
|
|
243
222
|
}, (error)=>Promise.reject(error));
|
|
244
|
-
'production' !== process.env.NODE_ENV &&
|
|
223
|
+
'production' !== process.env.NODE_ENV && instance.interceptors.response.use((response)=>{
|
|
245
224
|
logResponse('success', response);
|
|
246
225
|
return response;
|
|
247
226
|
}, (error)=>{
|
|
248
227
|
logResponse('error', error.response || error);
|
|
249
228
|
return Promise.reject(error);
|
|
250
229
|
});
|
|
230
|
+
return wrapAxiosWithTrace(instance);
|
|
251
231
|
}
|
|
252
|
-
export { initAxiosConfig,
|
|
232
|
+
export { initAxiosConfig, wrapAxiosWithTrace };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
|
-
import { initAxiosConfig
|
|
2
|
+
import { initAxiosConfig } from "./axiosConfig.js";
|
|
3
3
|
let axiosInstance;
|
|
4
4
|
function showToast(message, duration = 3000) {
|
|
5
5
|
return new Promise((resolve)=>{
|
|
@@ -54,7 +54,6 @@ function showToast(message, duration = 3000) {
|
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
function getAxiosForBackend() {
|
|
57
|
-
patchCreate();
|
|
58
57
|
if (!axiosInstance) {
|
|
59
58
|
axiosInstance = axios.create({
|
|
60
59
|
baseURL: process.env.CLIENT_BASE_PATH || '/'
|