@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
- export declare function patchCreate(): void;
13
- export declare function initAxiosConfig(axiosInstance?: AxiosInstance): void;
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;
@@ -1,4 +1,4 @@
1
- import axios, { Axios } from "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
- let isPrototypeInjected = false;
133
- function injectAxiosPrototype() {
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('Failed to start axios trace span in prototype:', e);
157
+ console.error('[ProxyTrace] Start axios trace span failed:', e);
162
158
  }
163
- const promise = originalRequest.apply(this, arguments);
159
+ const promise = originalInstance.request.call(originalInstance, finalConfig);
164
160
  return promise.then((response)=>{
165
- try {
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
- try {
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
- function patchCreate() {
222
- const originalCreate = axios.create;
223
- axios.create = function(config) {
224
- injectAxiosPrototype();
225
- const instance = originalCreate.call(axios, config);
226
- initAxiosConfig(instance);
227
- return instance;
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
- if (!axiosInstance) axiosInstance = axios;
232
- axiosInstance.interceptors.request.use((config)=>{
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 && axiosInstance.interceptors.response.use((response)=>{
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, patchCreate };
232
+ export { initAxiosConfig, wrapAxiosWithTrace };
@@ -1,5 +1,5 @@
1
1
  import axios from "axios";
2
- import { initAxiosConfig, patchCreate } from "./axiosConfig.js";
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 || '/'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/client-toolkit",
3
- "version": "1.2.1-alpha.18",
3
+ "version": "1.2.1-alpha.19",
4
4
  "types": "./lib/index.d.ts",
5
5
  "main": "./lib/index.js",
6
6
  "files": [