@wutiange/log-listener-plugin 1.3.0-alpha.3 → 1.3.1
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.
- package/LICENSE +201 -201
- package/README.md +10 -2
- package/dist/src/HTTPInterceptor.d.ts +3 -2
- package/dist/src/HTTPInterceptor.js +29 -8
- package/dist/src/HTTPInterceptor.js.map +1 -1
- package/dist/src/{server.d.ts → Server.d.ts} +1 -0
- package/dist/src/{server.js → Server.js} +5 -2
- package/dist/src/Server.js.map +1 -0
- package/dist/src/__mocks__/react-native/Libraries/Blob/FileReader.d.ts +14 -0
- package/dist/src/__mocks__/react-native/Libraries/Blob/FileReader.js +42 -0
- package/dist/src/__mocks__/react-native/Libraries/Blob/FileReader.js.map +1 -0
- package/dist/src/__mocks__/react-native/Libraries/Network/XHRInterceptor.d.ts +17 -0
- package/dist/src/__mocks__/react-native/Libraries/Network/XHRInterceptor.js +35 -0
- package/dist/src/__mocks__/react-native/Libraries/Network/XHRInterceptor.js.map +1 -0
- package/dist/src/__tests__/HTTPInterceptor.test.d.ts +9 -0
- package/dist/src/__tests__/HTTPInterceptor.test.js +281 -0
- package/dist/src/__tests__/HTTPInterceptor.test.js.map +1 -0
- package/dist/src/__tests__/Server.test.d.ts +1 -0
- package/dist/src/__tests__/Server.test.js +155 -0
- package/dist/src/__tests__/Server.test.js.map +1 -0
- package/dist/src/__tests__/utils.test.d.ts +1 -0
- package/dist/src/__tests__/utils.test.js +108 -0
- package/dist/src/__tests__/utils.test.js.map +1 -0
- package/dist/src/logPlugin.d.ts +2 -1
- package/dist/src/logPlugin.js +13 -8
- package/dist/src/logPlugin.js.map +1 -1
- package/dist/src/utils.d.ts +4 -1
- package/dist/src/utils.js +75 -12
- package/dist/src/utils.js.map +1 -1
- package/package.json +53 -49
- package/console.ts +0 -21
- package/dist/src/__tests__/console.test.d.ts +0 -1
- package/dist/src/__tests__/console.test.js +0 -29
- package/dist/src/__tests__/console.test.js.map +0 -1
- package/dist/src/server.js.map +0 -1
- package/fetch.ts +0 -39
- package/index.ts +0 -3
- package/src/HTTPInterceptor.ts +0 -319
- package/src/__tests__/console.test.ts +0 -26
- package/src/common.ts +0 -4
- package/src/logPlugin.ts +0 -238
- package/src/server.ts +0 -66
- package/src/utils.ts +0 -47
package/src/HTTPInterceptor.ts
DELETED
@@ -1,319 +0,0 @@
|
|
1
|
-
// @ts-ignore
|
2
|
-
import XHRInterceptor from 'react-native/Libraries/Network/XHRInterceptor';
|
3
|
-
// @ts-ignore
|
4
|
-
import BlobFileReader from 'react-native/Libraries/Blob/FileReader';
|
5
|
-
|
6
|
-
type StartNetworkLoggingOptions = {
|
7
|
-
/** List of hosts to ignore, e.g. `services.test.com` */
|
8
|
-
ignoredHosts?: string[];
|
9
|
-
/** List of urls to ignore, e.g. `https://services.test.com/test` */
|
10
|
-
ignoredUrls?: string[];
|
11
|
-
/**
|
12
|
-
* List of url patterns to ignore, e.g. `/^GET https://test.com\/pages\/.*$/`
|
13
|
-
*
|
14
|
-
* Url to match with is in the format: `${method} ${url}`, e.g. `GET https://test.com/pages/123`
|
15
|
-
*/
|
16
|
-
ignoredPatterns?: RegExp[];
|
17
|
-
/**
|
18
|
-
* Force the network logger to start even if another program is using the network interceptor
|
19
|
-
* e.g. a dev/debuging program
|
20
|
-
*/
|
21
|
-
forceEnable?: boolean;
|
22
|
-
};
|
23
|
-
|
24
|
-
interface HttpRequestInfo {
|
25
|
-
id: string;
|
26
|
-
method: RequestMethod;
|
27
|
-
url: string;
|
28
|
-
timeout: number;
|
29
|
-
requestHeaders: Record<string, string>;
|
30
|
-
requestData: string;
|
31
|
-
startTime: number;
|
32
|
-
endTime: number;
|
33
|
-
responseHeaders: Headers;
|
34
|
-
responseData: string;
|
35
|
-
status: number;
|
36
|
-
duration: number;
|
37
|
-
responseContentType: string;
|
38
|
-
responseSize: number;
|
39
|
-
responseURL: string;
|
40
|
-
responseType: string;
|
41
|
-
}
|
42
|
-
|
43
|
-
type RequestMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
44
|
-
|
45
|
-
type XHR = {
|
46
|
-
uniqueId: string;
|
47
|
-
responseHeaders?: Headers;
|
48
|
-
};
|
49
|
-
|
50
|
-
type EventName =
|
51
|
-
| 'open'
|
52
|
-
| 'requestHeader'
|
53
|
-
| 'headerReceived'
|
54
|
-
| 'send'
|
55
|
-
| 'response';
|
56
|
-
|
57
|
-
const extractHost = (url: string) => {
|
58
|
-
const host = url.split('//')[1]?.split(':')[0]?.split('/')[0] || undefined;
|
59
|
-
|
60
|
-
return host;
|
61
|
-
};
|
62
|
-
|
63
|
-
const generateUniqueId = () => {
|
64
|
-
return Date.now().toString(36) + Math.random().toString(36).substr(2);
|
65
|
-
};
|
66
|
-
|
67
|
-
const parseResponseBlob = async (response: string) => {
|
68
|
-
const blobReader = new BlobFileReader();
|
69
|
-
blobReader.readAsText(response);
|
70
|
-
|
71
|
-
return await new Promise<string>((resolve, reject) => {
|
72
|
-
const handleError = () => reject(blobReader.error);
|
73
|
-
|
74
|
-
blobReader.addEventListener('load', () => {
|
75
|
-
resolve(blobReader.result);
|
76
|
-
});
|
77
|
-
blobReader.addEventListener('error', handleError);
|
78
|
-
blobReader.addEventListener('abort', handleError);
|
79
|
-
});
|
80
|
-
}
|
81
|
-
|
82
|
-
const getResponseBody = async (responseType: string, response: string) => {
|
83
|
-
try {
|
84
|
-
const body = await (responseType !== 'blob'
|
85
|
-
? response
|
86
|
-
: parseResponseBlob(response));
|
87
|
-
return JSON.parse(body)
|
88
|
-
} catch (error) {
|
89
|
-
return null
|
90
|
-
}
|
91
|
-
}
|
92
|
-
|
93
|
-
class HTTPInterceptor {
|
94
|
-
private static _index = 0;
|
95
|
-
private ignoredHosts: Set<string> | undefined;
|
96
|
-
private ignoredUrls: Set<string> | undefined;
|
97
|
-
private ignoredPatterns: RegExp[] | undefined;
|
98
|
-
// 只保存正在请求中的
|
99
|
-
private allRequests = new Map<string, Partial<HttpRequestInfo>>();
|
100
|
-
|
101
|
-
private userListeners: [
|
102
|
-
EventName,
|
103
|
-
(data: Partial<HttpRequestInfo>) => Promise<void> | void,
|
104
|
-
][] = [];
|
105
|
-
|
106
|
-
private enabled = false;
|
107
|
-
|
108
|
-
addListener = (
|
109
|
-
eventName: EventName,
|
110
|
-
listener: (data: Partial<HttpRequestInfo>) => Promise<void> | void,
|
111
|
-
) => {
|
112
|
-
// 如果之前已经订阅过了就过滤掉
|
113
|
-
if (
|
114
|
-
this.userListeners.find(
|
115
|
-
([name, tempListener]) =>
|
116
|
-
name === eventName && tempListener === listener,
|
117
|
-
)
|
118
|
-
) {
|
119
|
-
return;
|
120
|
-
}
|
121
|
-
this.userListeners.push([eventName, listener]);
|
122
|
-
|
123
|
-
return () => {
|
124
|
-
this.userListeners = this.userListeners.filter(
|
125
|
-
([name, tempListener]) =>
|
126
|
-
name !== eventName || tempListener !== listener,
|
127
|
-
);
|
128
|
-
};
|
129
|
-
};
|
130
|
-
|
131
|
-
removeListener = (
|
132
|
-
eventName: EventName,
|
133
|
-
listener: (data: Partial<HttpRequestInfo>) => Promise<void> | void,
|
134
|
-
) => {
|
135
|
-
this.userListeners = this.userListeners.filter(
|
136
|
-
([name, tempListener]) => name !== eventName || tempListener !== listener,
|
137
|
-
);
|
138
|
-
};
|
139
|
-
|
140
|
-
removeAllListener() {
|
141
|
-
this.userListeners = [];
|
142
|
-
}
|
143
|
-
|
144
|
-
private listenerHandle = (
|
145
|
-
eventName: EventName,
|
146
|
-
data: Partial<HttpRequestInfo>,
|
147
|
-
) => {
|
148
|
-
this.userListeners.forEach(async ([name, listener]) => {
|
149
|
-
if (name === eventName) {
|
150
|
-
await listener(data);
|
151
|
-
}
|
152
|
-
});
|
153
|
-
};
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
private openHandle = (method: RequestMethod, url: string, xhr: XHR) => {
|
158
|
-
if (this.ignoredHosts) {
|
159
|
-
const host = extractHost(url);
|
160
|
-
if (host && this.ignoredHosts.has(host)) {
|
161
|
-
return;
|
162
|
-
}
|
163
|
-
}
|
164
|
-
if (this.ignoredUrls && this.ignoredUrls.has(url)) {
|
165
|
-
return;
|
166
|
-
}
|
167
|
-
|
168
|
-
if (this.ignoredPatterns) {
|
169
|
-
if (
|
170
|
-
this.ignoredPatterns.some(pattern => pattern.test(`${method} ${url}`))
|
171
|
-
) {
|
172
|
-
return;
|
173
|
-
}
|
174
|
-
}
|
175
|
-
xhr.uniqueId = HTTPInterceptor._index + generateUniqueId();
|
176
|
-
const newRequest = {
|
177
|
-
id: xhr.uniqueId,
|
178
|
-
method,
|
179
|
-
url,
|
180
|
-
};
|
181
|
-
this.allRequests.set(xhr.uniqueId, newRequest);
|
182
|
-
this.listenerHandle('open', newRequest);
|
183
|
-
};
|
184
|
-
|
185
|
-
private requestHeaderHandle = (header: string, value: string, xhr: XHR) => {
|
186
|
-
const currentRequest = this.allRequests.get(xhr.uniqueId);
|
187
|
-
if (!currentRequest) {
|
188
|
-
return;
|
189
|
-
}
|
190
|
-
if (!currentRequest.requestHeaders) {
|
191
|
-
currentRequest.requestHeaders = {};
|
192
|
-
}
|
193
|
-
currentRequest.requestHeaders[header] = value;
|
194
|
-
this.listenerHandle('requestHeader', currentRequest);
|
195
|
-
};
|
196
|
-
|
197
|
-
private headerReceivedHandle = (
|
198
|
-
responseContentType: string,
|
199
|
-
responseSize: number,
|
200
|
-
responseHeaders: Headers,
|
201
|
-
xhr: XHR,
|
202
|
-
) => {
|
203
|
-
const currentRequest = this.allRequests.get(xhr.uniqueId);
|
204
|
-
if (!currentRequest) {
|
205
|
-
return;
|
206
|
-
}
|
207
|
-
currentRequest.responseContentType = responseContentType;
|
208
|
-
currentRequest.responseSize = responseSize;
|
209
|
-
currentRequest.responseHeaders = xhr.responseHeaders;
|
210
|
-
this.listenerHandle('headerReceived', currentRequest);
|
211
|
-
};
|
212
|
-
|
213
|
-
private responseHandle = async (
|
214
|
-
status: number,
|
215
|
-
timeout: number,
|
216
|
-
response: string,
|
217
|
-
responseURL: string,
|
218
|
-
responseType: string,
|
219
|
-
xhr: XHR,
|
220
|
-
) => {
|
221
|
-
const currentRequest = this.allRequests.get(xhr.uniqueId);
|
222
|
-
if (!currentRequest) {
|
223
|
-
return;
|
224
|
-
}
|
225
|
-
currentRequest.endTime = Date.now();
|
226
|
-
currentRequest.status = status;
|
227
|
-
currentRequest.timeout = timeout;
|
228
|
-
currentRequest.responseData = await getResponseBody(responseType, response);
|
229
|
-
currentRequest.responseURL = responseURL;
|
230
|
-
currentRequest.responseType = responseType;
|
231
|
-
currentRequest.duration =
|
232
|
-
currentRequest.endTime - (currentRequest.startTime ?? 0);
|
233
|
-
this.listenerHandle('response', currentRequest);
|
234
|
-
this.allRequests.delete(xhr.uniqueId);
|
235
|
-
};
|
236
|
-
|
237
|
-
private sendHandle = (data: string, xhr: XHR) => {
|
238
|
-
const currentRequest = this.allRequests.get(xhr.uniqueId);
|
239
|
-
if (!currentRequest) {
|
240
|
-
return;
|
241
|
-
}
|
242
|
-
try {
|
243
|
-
currentRequest.requestData = JSON.parse(data);
|
244
|
-
} catch (error) {
|
245
|
-
currentRequest.requestData = null;
|
246
|
-
}
|
247
|
-
currentRequest.startTime = Date.now();
|
248
|
-
this.listenerHandle('send', currentRequest);
|
249
|
-
};
|
250
|
-
|
251
|
-
enable = (options?: StartNetworkLoggingOptions) => {
|
252
|
-
try {
|
253
|
-
if (
|
254
|
-
this.enabled ||
|
255
|
-
(XHRInterceptor.isInterceptorEnabled() && !options?.forceEnable)
|
256
|
-
) {
|
257
|
-
if (!this.enabled) {
|
258
|
-
console.warn(
|
259
|
-
'network interceptor has not been enabled as another interceptor is already running (e.g. another debugging program). Use option `forceEnable: true` to override this behaviour.',
|
260
|
-
);
|
261
|
-
}
|
262
|
-
return;
|
263
|
-
}
|
264
|
-
|
265
|
-
if (options?.ignoredHosts) {
|
266
|
-
if (
|
267
|
-
!Array.isArray(options.ignoredHosts) ||
|
268
|
-
typeof options.ignoredHosts[0] !== 'string'
|
269
|
-
) {
|
270
|
-
console.warn(
|
271
|
-
'ignoredHosts must be an array of strings. The logger has not been started.',
|
272
|
-
);
|
273
|
-
return;
|
274
|
-
}
|
275
|
-
this.ignoredHosts = new Set(options.ignoredHosts);
|
276
|
-
}
|
277
|
-
|
278
|
-
if (options?.ignoredPatterns) {
|
279
|
-
this.ignoredPatterns = options.ignoredPatterns;
|
280
|
-
}
|
281
|
-
|
282
|
-
if (options?.ignoredUrls) {
|
283
|
-
if (
|
284
|
-
!Array.isArray(options.ignoredUrls) ||
|
285
|
-
typeof options.ignoredUrls[0] !== 'string'
|
286
|
-
) {
|
287
|
-
console.warn(
|
288
|
-
'ignoredUrls must be an array of strings. The logger has not been started.',
|
289
|
-
);
|
290
|
-
return;
|
291
|
-
}
|
292
|
-
this.ignoredUrls = new Set(options.ignoredUrls);
|
293
|
-
}
|
294
|
-
XHRInterceptor.setOpenCallback(this.openHandle);
|
295
|
-
XHRInterceptor.setRequestHeaderCallback(this.requestHeaderHandle);
|
296
|
-
XHRInterceptor.setHeaderReceivedCallback(this.headerReceivedHandle);
|
297
|
-
XHRInterceptor.setSendCallback(this.sendHandle);
|
298
|
-
XHRInterceptor.setResponseCallback(this.responseHandle);
|
299
|
-
XHRInterceptor.enableInterception();
|
300
|
-
this.enabled = true;
|
301
|
-
} catch (error) {}
|
302
|
-
};
|
303
|
-
|
304
|
-
disable = () => {
|
305
|
-
if (!this.enabled) {
|
306
|
-
return;
|
307
|
-
}
|
308
|
-
XHRInterceptor.disableInterception();
|
309
|
-
this.enabled = false;
|
310
|
-
}
|
311
|
-
}
|
312
|
-
|
313
|
-
const httpInterceptor = new HTTPInterceptor();
|
314
|
-
export {
|
315
|
-
type StartNetworkLoggingOptions,
|
316
|
-
httpInterceptor,
|
317
|
-
type EventName,
|
318
|
-
type RequestMethod,
|
319
|
-
};
|
@@ -1,26 +0,0 @@
|
|
1
|
-
import '../../console'
|
2
|
-
import logger from '../../index'
|
3
|
-
describe("重写日志", () => {
|
4
|
-
it("log 没有提前设置 url", () => {
|
5
|
-
console.log("log 是否正常打印")
|
6
|
-
expect(1).toBe(1)
|
7
|
-
})
|
8
|
-
|
9
|
-
it("log 提前设置了 url", () => {
|
10
|
-
logger.setBaseUrl("http://192.168.118.103")
|
11
|
-
console.log("log 是否正常打印")
|
12
|
-
expect(1).toBe(1)
|
13
|
-
})
|
14
|
-
|
15
|
-
it('warn', () => {
|
16
|
-
logger.setBaseUrl("http://192.168.118.103")
|
17
|
-
console.warn("warn 是否正常打印")
|
18
|
-
expect(1).toBe(1)
|
19
|
-
})
|
20
|
-
|
21
|
-
it('error', () => {
|
22
|
-
logger.setBaseUrl("http://192.168.118.103")
|
23
|
-
console.error("error 是否正常打印")
|
24
|
-
expect(1).toBe(1)
|
25
|
-
})
|
26
|
-
})
|
package/src/common.ts
DELETED
package/src/logPlugin.ts
DELETED
@@ -1,238 +0,0 @@
|
|
1
|
-
import Server from './server';
|
2
|
-
import { extractDomain } from './utils';
|
3
|
-
import { httpInterceptor } from './HTTPInterceptor';
|
4
|
-
|
5
|
-
class LogPlugin {
|
6
|
-
private server: Server | null = null;
|
7
|
-
private baseData: Record<string, any> = {};
|
8
|
-
private timeout: number | null = null;
|
9
|
-
private host = '';
|
10
|
-
private isAuto = false
|
11
|
-
|
12
|
-
auto = () => {
|
13
|
-
if (this.host) {
|
14
|
-
this.startRecordNetwork();
|
15
|
-
this.startRecordLog();
|
16
|
-
}
|
17
|
-
this.isAuto = true
|
18
|
-
}
|
19
|
-
|
20
|
-
unAuto = () => {
|
21
|
-
this.stopRecordLog()
|
22
|
-
httpInterceptor.disable()
|
23
|
-
httpInterceptor.removeAllListener()
|
24
|
-
this.isAuto = false
|
25
|
-
}
|
26
|
-
|
27
|
-
startRecordLog = () => {
|
28
|
-
const common = require('./common')
|
29
|
-
console.log = (...data: any[]) => {
|
30
|
-
this.log(...data);
|
31
|
-
common.log(...data);
|
32
|
-
};
|
33
|
-
|
34
|
-
console.warn = (...data: any[]) => {
|
35
|
-
this.warn(...data);
|
36
|
-
common.warn(...data);
|
37
|
-
};
|
38
|
-
|
39
|
-
console.error = (...data: any[]) => {
|
40
|
-
this.error(...data);
|
41
|
-
common.error(...data);
|
42
|
-
};
|
43
|
-
}
|
44
|
-
|
45
|
-
stopRecordLog = () => {
|
46
|
-
const common = require('./common')
|
47
|
-
console.log = common.log
|
48
|
-
console.warn = common.warn
|
49
|
-
console.error = common.error
|
50
|
-
}
|
51
|
-
|
52
|
-
startRecordNetwork = () => {
|
53
|
-
httpInterceptor.addListener("send", (data) => {
|
54
|
-
this.server?.network({
|
55
|
-
...this.baseData,
|
56
|
-
url: data.url,
|
57
|
-
id: data.id,
|
58
|
-
method: data.method,
|
59
|
-
headers: data.requestHeaders,
|
60
|
-
body: data.requestData,
|
61
|
-
createTime: data.startTime
|
62
|
-
})
|
63
|
-
})
|
64
|
-
httpInterceptor.addListener("response", (data) => {
|
65
|
-
this.server?.network({
|
66
|
-
...this.baseData,
|
67
|
-
headers: data.responseHeaders,
|
68
|
-
body: data.responseData,
|
69
|
-
requestId: data.id,
|
70
|
-
statusCode: data.status,
|
71
|
-
endTime: data.endTime
|
72
|
-
})
|
73
|
-
})
|
74
|
-
httpInterceptor.enable({
|
75
|
-
ignoredHosts: [extractDomain(this.host)]
|
76
|
-
})
|
77
|
-
}
|
78
|
-
|
79
|
-
setBaseUrl = (url: string) => {
|
80
|
-
if (!url?.trim()) {
|
81
|
-
httpInterceptor.disable()
|
82
|
-
this.stopRecordLog()
|
83
|
-
return
|
84
|
-
}
|
85
|
-
this.host = url.includes("http") ? url : `http://${url}`;
|
86
|
-
if (this.server) {
|
87
|
-
this.server.updateUrl(url);
|
88
|
-
} else {
|
89
|
-
this.server = new Server(url);
|
90
|
-
}
|
91
|
-
if (this.isAuto) {
|
92
|
-
this.startRecordNetwork();
|
93
|
-
this.startRecordLog()
|
94
|
-
}
|
95
|
-
}
|
96
|
-
|
97
|
-
/**
|
98
|
-
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
99
|
-
*/
|
100
|
-
setTimeout = (timeout: number) => {
|
101
|
-
if (typeof timeout === 'number') {
|
102
|
-
this.timeout = timeout;
|
103
|
-
this.server?.updateTimeout(this.timeout);
|
104
|
-
}
|
105
|
-
}
|
106
|
-
|
107
|
-
/**
|
108
|
-
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
109
|
-
*/
|
110
|
-
getTimeout = () => {
|
111
|
-
if (typeof this.timeout === 'number') {
|
112
|
-
return this.timeout;
|
113
|
-
}
|
114
|
-
return null;
|
115
|
-
}
|
116
|
-
|
117
|
-
setBaseData = (data: Record<string, any> = {}) => {
|
118
|
-
this.baseData = data;
|
119
|
-
}
|
120
|
-
|
121
|
-
private _log = (level: string, tag: string, ...data: any[]) => {
|
122
|
-
const sendData = {
|
123
|
-
...this.baseData,
|
124
|
-
message: data,
|
125
|
-
tag,
|
126
|
-
level: level ?? 'log',
|
127
|
-
createTime: Date.now(),
|
128
|
-
};
|
129
|
-
this.server?.log(sendData);
|
130
|
-
}
|
131
|
-
|
132
|
-
tag = (tag: string, ...data: any[]) => {
|
133
|
-
this._log('log', tag, ...data);
|
134
|
-
}
|
135
|
-
|
136
|
-
log = (...data: any[]) => {
|
137
|
-
this._log('log', 'default', ...data);
|
138
|
-
}
|
139
|
-
|
140
|
-
warn = (...data: any[]) => {
|
141
|
-
this._log('warn', 'default', ...data);
|
142
|
-
}
|
143
|
-
|
144
|
-
error = (...data: any[]) => {
|
145
|
-
this._log('error', 'default', ...data);
|
146
|
-
}
|
147
|
-
|
148
|
-
/**
|
149
|
-
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
150
|
-
*/
|
151
|
-
uniqueReq = async (
|
152
|
-
uniqueId: string | undefined,
|
153
|
-
input: RequestInfo | URL,
|
154
|
-
init?: RequestInit
|
155
|
-
) => {
|
156
|
-
let url: string | null = null;
|
157
|
-
let method = init?.method ?? 'get';
|
158
|
-
let headers = init?.headers;
|
159
|
-
let body = init?.body;
|
160
|
-
if (input instanceof Request) {
|
161
|
-
url = input.url;
|
162
|
-
method = input.method ?? 'get';
|
163
|
-
headers = (input.headers as Record<string, any>).map;
|
164
|
-
body = input.body;
|
165
|
-
} else if (input instanceof URL) {
|
166
|
-
url = input.href;
|
167
|
-
} else {
|
168
|
-
url = input;
|
169
|
-
}
|
170
|
-
return this.server?.network({
|
171
|
-
...this.baseData,
|
172
|
-
url,
|
173
|
-
id: uniqueId,
|
174
|
-
method,
|
175
|
-
headers,
|
176
|
-
body,
|
177
|
-
createTime: Date.now(),
|
178
|
-
});
|
179
|
-
}
|
180
|
-
|
181
|
-
private _res = async (uniqueId?: string, id?: number, response?: Response) => {
|
182
|
-
const body = await response?.text();
|
183
|
-
return this.server?.network({
|
184
|
-
...this.baseData,
|
185
|
-
headers: (response?.headers as Record<string, any>).map,
|
186
|
-
body,
|
187
|
-
requestId: uniqueId ?? Number(id),
|
188
|
-
statusCode: response?.status,
|
189
|
-
endTime: Date.now(),
|
190
|
-
});
|
191
|
-
}
|
192
|
-
|
193
|
-
/**
|
194
|
-
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
195
|
-
*/
|
196
|
-
resTimeout = async (uniqueId: string) => {
|
197
|
-
return this.server?.network({
|
198
|
-
...this.baseData,
|
199
|
-
isTimeout: true,
|
200
|
-
requestId: uniqueId,
|
201
|
-
});
|
202
|
-
}
|
203
|
-
|
204
|
-
/**
|
205
|
-
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
206
|
-
*/
|
207
|
-
resResponseError = async (uniqueId: string) => {
|
208
|
-
return this.server?.network({
|
209
|
-
...this.baseData,
|
210
|
-
isResponseError: true,
|
211
|
-
requestId: uniqueId,
|
212
|
-
});
|
213
|
-
}
|
214
|
-
|
215
|
-
/**
|
216
|
-
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
217
|
-
*/
|
218
|
-
uniqueRes = async (uniqueId: string, response?: Response) => {
|
219
|
-
return this._res(uniqueId, undefined, response);
|
220
|
-
}
|
221
|
-
|
222
|
-
/**
|
223
|
-
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
224
|
-
*/
|
225
|
-
req = async (input: RequestInfo | URL, init?: RequestInit) => {
|
226
|
-
return this.uniqueReq(undefined, input, init);
|
227
|
-
}
|
228
|
-
|
229
|
-
/**
|
230
|
-
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
231
|
-
*/
|
232
|
-
res = async (id: number, response?: Response) => {
|
233
|
-
return this._res(undefined, id, response);
|
234
|
-
}
|
235
|
-
}
|
236
|
-
const logPlugin = new LogPlugin();
|
237
|
-
export { LogPlugin };
|
238
|
-
export default logPlugin;
|
package/src/server.ts
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
import {hasPort, sleep} from './utils';
|
2
|
-
const DEFAULT_PORT = 27751
|
3
|
-
class Server {
|
4
|
-
private baseUrl = '';
|
5
|
-
private timeout: number;
|
6
|
-
|
7
|
-
constructor(url: string, timeout: number = 3000) {
|
8
|
-
this.updateUrl(url);
|
9
|
-
this.timeout = timeout;
|
10
|
-
}
|
11
|
-
|
12
|
-
updateTimeout(timeout = 3000) {
|
13
|
-
this.timeout = timeout;
|
14
|
-
}
|
15
|
-
|
16
|
-
private getPort() {
|
17
|
-
if (hasPort(this.baseUrl)) {
|
18
|
-
return ''
|
19
|
-
}
|
20
|
-
return DEFAULT_PORT;
|
21
|
-
}
|
22
|
-
|
23
|
-
private async send(path: string, data: Record<string, any>) {
|
24
|
-
try {
|
25
|
-
if (!this.baseUrl) {
|
26
|
-
return null;
|
27
|
-
}
|
28
|
-
const common = require('./common');
|
29
|
-
const result = await Promise.race([
|
30
|
-
common.tempFetch(`${this.baseUrl}:${this.getPort()}/${path}`, {
|
31
|
-
method: 'POST',
|
32
|
-
headers: {
|
33
|
-
'Content-Type': 'application/json;charset=utf-8',
|
34
|
-
},
|
35
|
-
body: JSON.stringify(data, (_, val) => {
|
36
|
-
if (val instanceof Error) {
|
37
|
-
return val.toString();
|
38
|
-
}
|
39
|
-
return val;
|
40
|
-
}),
|
41
|
-
}),
|
42
|
-
sleep(this.timeout, true),
|
43
|
-
]);
|
44
|
-
if (result instanceof Response) {
|
45
|
-
return result.text();
|
46
|
-
}
|
47
|
-
return null;
|
48
|
-
} catch (error) {
|
49
|
-
return null;
|
50
|
-
}
|
51
|
-
}
|
52
|
-
|
53
|
-
updateUrl(url: string) {
|
54
|
-
this.baseUrl = url;
|
55
|
-
}
|
56
|
-
|
57
|
-
async log(data: Record<string, any>) {
|
58
|
-
return this.send('log', data);
|
59
|
-
}
|
60
|
-
|
61
|
-
async network(data: Record<string, any>) {
|
62
|
-
return this.send('network', data);
|
63
|
-
}
|
64
|
-
}
|
65
|
-
|
66
|
-
export default Server;
|
package/src/utils.ts
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
export function sleep(ms: number, isReject: boolean = false) {
|
2
|
-
return new Promise((resolve, reject) => {
|
3
|
-
setTimeout(isReject ? () => reject({
|
4
|
-
code: 11001,
|
5
|
-
key: '@wutiange/log-listener-plugin%%timeout',
|
6
|
-
msg: 'Timeout'
|
7
|
-
}) : resolve, ms)
|
8
|
-
})
|
9
|
-
}
|
10
|
-
|
11
|
-
export function extractDomain(url: string) {
|
12
|
-
// 如果 url 是空的或不是字符串,直接返回
|
13
|
-
if (!url || typeof url !== 'string') {
|
14
|
-
return url;
|
15
|
-
}
|
16
|
-
|
17
|
-
// 使用正则表达式匹配 URL
|
18
|
-
const match = url.match(/^(https?:\/\/)?([^/:]+)/i);
|
19
|
-
|
20
|
-
// 如果没有匹配到,返回原始输入
|
21
|
-
if (!match) {
|
22
|
-
return url;
|
23
|
-
}
|
24
|
-
|
25
|
-
// 返回匹配到的域名部分
|
26
|
-
return match[2];
|
27
|
-
}
|
28
|
-
|
29
|
-
|
30
|
-
export function hasPort(url: string) {
|
31
|
-
// 如果 url 是空的或不是字符串,返回 false
|
32
|
-
if (!url || typeof url !== 'string') {
|
33
|
-
return false;
|
34
|
-
}
|
35
|
-
|
36
|
-
try {
|
37
|
-
// 使用 URL 构造函数解析 URL
|
38
|
-
const parsedUrl = new URL(url);
|
39
|
-
|
40
|
-
// 检查 port 属性是否为空
|
41
|
-
// 注意:如果使用默认端口(如 HTTP 的 80 或 HTTPS 的 443),port 会是空字符串
|
42
|
-
return parsedUrl.port !== '';
|
43
|
-
} catch (error) {
|
44
|
-
// 如果 URL 无效,捕获错误并返回 false
|
45
|
-
return false;
|
46
|
-
}
|
47
|
-
}
|