@pisell/core 1.0.63 → 1.0.64

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.
@@ -27,6 +27,101 @@ axiosInstance.interceptors.response.use(interceptorsResponse, interceptorsRespon
27
27
 
28
28
  // 请求计数
29
29
  var requestCount = 0;
30
+ var DEFAULT_REQUEST_TIMING_METRICS = {
31
+ duration: 0,
32
+ dnsLookupDuration: 0,
33
+ tcpHandshakeDuration: 0,
34
+ redirectDuration: 0,
35
+ stalledDuration: 0,
36
+ ttfbDuration: 0,
37
+ requestDuration: 0,
38
+ tlsHandshakeDuration: 0
39
+ };
40
+ var requestTimingStore = new Map();
41
+ var hasInitializedRequestObserver = false;
42
+ function getRequestTimingKey(requestUrl) {
43
+ if (typeof window === "undefined") return requestUrl;
44
+ try {
45
+ return new URL(requestUrl, window.location.href).href.split("#")[0];
46
+ } catch (_unused) {
47
+ return requestUrl;
48
+ }
49
+ }
50
+ function pushRequestTimingEntry(entry) {
51
+ var timingKey = getRequestTimingKey(entry.name);
52
+ var existingEntries = requestTimingStore.get(timingKey) || [];
53
+ existingEntries.push(entry);
54
+ if (existingEntries.length > 30) existingEntries.shift();
55
+ requestTimingStore.set(timingKey, existingEntries);
56
+ }
57
+ function initializeRequestPerformanceObserver() {
58
+ if (hasInitializedRequestObserver) return;
59
+ if (typeof window === "undefined") return;
60
+ if (typeof PerformanceObserver === "undefined") return;
61
+ hasInitializedRequestObserver = true;
62
+ try {
63
+ var observer = new PerformanceObserver(function (list) {
64
+ list.getEntries().forEach(function (entry) {
65
+ if (entry.entryType !== "resource") return;
66
+ var resourceEntry = entry;
67
+ if (!["fetch", "xmlhttprequest"].includes(resourceEntry.initiatorType)) return;
68
+ pushRequestTimingEntry(resourceEntry);
69
+ });
70
+ });
71
+ observer.observe({
72
+ entryTypes: ["resource"]
73
+ });
74
+ } catch (error) {
75
+ hasInitializedRequestObserver = false;
76
+ }
77
+ }
78
+ function readAndConsumeRequestTimingEntry(requestUrl) {
79
+ var timingKey = getRequestTimingKey(requestUrl);
80
+ var cachedEntries = requestTimingStore.get(timingKey);
81
+ if (cachedEntries !== null && cachedEntries !== void 0 && cachedEntries.length) {
82
+ var matchedEntry = cachedEntries.shift();
83
+ if (!cachedEntries.length) requestTimingStore.delete(timingKey);
84
+ return matchedEntry;
85
+ }
86
+ if (typeof performance === "undefined") return undefined;
87
+ var fallbackEntries = performance.getEntriesByName(timingKey, "resource");
88
+ for (var index = fallbackEntries.length - 1; index >= 0; index--) {
89
+ var entry = fallbackEntries[index];
90
+ if (["fetch", "xmlhttprequest"].includes(entry.initiatorType)) return entry;
91
+ }
92
+ return undefined;
93
+ }
94
+ function getSafeDuration(start, end) {
95
+ if (start <= 0) return 0;
96
+ if (end <= 0) return 0;
97
+ if (end < start) return 0;
98
+ return end - start;
99
+ }
100
+ function calculateRequestTimingMetrics(entry) {
101
+ if (!entry) return DEFAULT_REQUEST_TIMING_METRICS;
102
+ var redirectDuration = getSafeDuration(entry.redirectStart, entry.redirectEnd);
103
+ var dnsLookupDuration = getSafeDuration(entry.domainLookupStart, entry.domainLookupEnd);
104
+ var tcpHandshakeDuration = getSafeDuration(entry.connectStart, entry.connectEnd);
105
+ var stalledDuration = getSafeDuration(entry.fetchStart, entry.requestStart);
106
+ var ttfbDuration = getSafeDuration(entry.requestStart, entry.responseStart);
107
+ var requestDuration = getSafeDuration(entry.requestStart, entry.responseEnd);
108
+ var tlsHandshakeDuration = entry.secureConnectionStart > 0 ? getSafeDuration(entry.secureConnectionStart, entry.connectEnd) : 0;
109
+ var duration = entry.duration > 0 ? entry.duration : requestDuration;
110
+ return {
111
+ duration: duration,
112
+ dnsLookupDuration: dnsLookupDuration,
113
+ tcpHandshakeDuration: tcpHandshakeDuration,
114
+ redirectDuration: redirectDuration,
115
+ stalledDuration: stalledDuration,
116
+ ttfbDuration: ttfbDuration,
117
+ requestDuration: requestDuration,
118
+ tlsHandshakeDuration: tlsHandshakeDuration
119
+ };
120
+ }
121
+ function formatDurationInMs(duration) {
122
+ return "".concat(duration.toFixed(2), "ms");
123
+ }
124
+ initializeRequestPerformanceObserver();
30
125
  var isFilterUrl = function isFilterUrl(url) {
31
126
  var _logger$filterUrls;
32
127
  var _getConfig = getConfig(),
@@ -43,7 +138,7 @@ export var createRequest = function createRequest(props) {
43
138
  var _getConfig2 = getConfig(),
44
139
  getUrl = _getConfig2.getUrl,
45
140
  logger = _getConfig2.logger;
46
- var startTime = Date.now(); // 记录请求开始时间
141
+ var requestStartTime = typeof performance !== "undefined" ? performance.now() : Date.now();
47
142
  var app = getApp();
48
143
  var requestId = getUniqueId();
49
144
 
@@ -80,8 +175,10 @@ export var createRequest = function createRequest(props) {
80
175
  var isError = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
81
176
  var requestId = arguments.length > 3 ? arguments[3] : undefined;
82
177
  try {
83
- var endTime = Date.now();
84
- var duration = endTime - startTime;
178
+ var performanceEntry = readAndConsumeRequestTimingEntry(url);
179
+ var timingMetrics = calculateRequestTimingMetrics(performanceEntry);
180
+ var fallbackDuration = (typeof performance !== "undefined" ? performance.now() : Date.now()) - requestStartTime;
181
+ var duration = timingMetrics.duration > 0 ? timingMetrics.duration : fallbackDuration;
85
182
  var maxRequestTime = (logger === null || logger === void 0 ? void 0 : logger.maxRequestTime) || 5000;
86
183
 
87
184
  // 如果请求URL在过滤列表中,则不判断超时时间
@@ -98,11 +195,18 @@ export var createRequest = function createRequest(props) {
98
195
  }
99
196
  app.logger.addLog({
100
197
  type: type,
101
- title: "[ Request ]: Complete - ".concat(requestId, " \u8D85\u8FC75s"),
198
+ title: "[ Request ]: Complete - ".concat(requestId).concat(duration > maxRequestTime ? " 超过5s" : ""),
102
199
  metadata: {
103
200
  error: isError ? JSON.stringify(result) : '',
104
201
  duration: "".concat((duration / 1000).toFixed(2), "s"),
105
- url: url
202
+ url: url,
203
+ dnsLookupDuration: formatDurationInMs(timingMetrics.dnsLookupDuration),
204
+ tcpHandshakeDuration: formatDurationInMs(timingMetrics.tcpHandshakeDuration),
205
+ redirectDuration: formatDurationInMs(timingMetrics.redirectDuration),
206
+ stalledDuration: formatDurationInMs(timingMetrics.stalledDuration),
207
+ ttfbDuration: formatDurationInMs(timingMetrics.ttfbDuration),
208
+ requestDuration: formatDurationInMs(timingMetrics.requestDuration),
209
+ tlsHandshakeDuration: formatDurationInMs(timingMetrics.tlsHandshakeDuration)
106
210
  }
107
211
  });
108
212
  } catch (error) {}
@@ -53,6 +53,99 @@ var axiosInstance = import_axios.default.create(import_constants.axiosConfig);
53
53
  axiosInstance.interceptors.request.use(import_utils.interceptorsRequest, import_utils.interceptorsRequestError);
54
54
  axiosInstance.interceptors.response.use(import_utils.interceptorsResponse, import_utils.interceptorsResponseError);
55
55
  var requestCount = 0;
56
+ var DEFAULT_REQUEST_TIMING_METRICS = {
57
+ duration: 0,
58
+ dnsLookupDuration: 0,
59
+ tcpHandshakeDuration: 0,
60
+ redirectDuration: 0,
61
+ stalledDuration: 0,
62
+ ttfbDuration: 0,
63
+ requestDuration: 0,
64
+ tlsHandshakeDuration: 0
65
+ };
66
+ var requestTimingStore = /* @__PURE__ */ new Map();
67
+ var hasInitializedRequestObserver = false;
68
+ function getRequestTimingKey(requestUrl) {
69
+ if (typeof window === "undefined") return requestUrl;
70
+ try {
71
+ return new URL(requestUrl, window.location.href).href.split("#")[0];
72
+ } catch {
73
+ return requestUrl;
74
+ }
75
+ }
76
+ function pushRequestTimingEntry(entry) {
77
+ const timingKey = getRequestTimingKey(entry.name);
78
+ const existingEntries = requestTimingStore.get(timingKey) || [];
79
+ existingEntries.push(entry);
80
+ if (existingEntries.length > 30) existingEntries.shift();
81
+ requestTimingStore.set(timingKey, existingEntries);
82
+ }
83
+ function initializeRequestPerformanceObserver() {
84
+ if (hasInitializedRequestObserver) return;
85
+ if (typeof window === "undefined") return;
86
+ if (typeof PerformanceObserver === "undefined") return;
87
+ hasInitializedRequestObserver = true;
88
+ try {
89
+ const observer = new PerformanceObserver((list) => {
90
+ list.getEntries().forEach((entry) => {
91
+ if (entry.entryType !== "resource") return;
92
+ const resourceEntry = entry;
93
+ if (!["fetch", "xmlhttprequest"].includes(resourceEntry.initiatorType)) return;
94
+ pushRequestTimingEntry(resourceEntry);
95
+ });
96
+ });
97
+ observer.observe({ entryTypes: ["resource"] });
98
+ } catch (error) {
99
+ hasInitializedRequestObserver = false;
100
+ }
101
+ }
102
+ function readAndConsumeRequestTimingEntry(requestUrl) {
103
+ const timingKey = getRequestTimingKey(requestUrl);
104
+ const cachedEntries = requestTimingStore.get(timingKey);
105
+ if (cachedEntries == null ? void 0 : cachedEntries.length) {
106
+ const matchedEntry = cachedEntries.shift();
107
+ if (!cachedEntries.length) requestTimingStore.delete(timingKey);
108
+ return matchedEntry;
109
+ }
110
+ if (typeof performance === "undefined") return void 0;
111
+ const fallbackEntries = performance.getEntriesByName(timingKey, "resource");
112
+ for (let index = fallbackEntries.length - 1; index >= 0; index--) {
113
+ const entry = fallbackEntries[index];
114
+ if (["fetch", "xmlhttprequest"].includes(entry.initiatorType)) return entry;
115
+ }
116
+ return void 0;
117
+ }
118
+ function getSafeDuration(start, end) {
119
+ if (start <= 0) return 0;
120
+ if (end <= 0) return 0;
121
+ if (end < start) return 0;
122
+ return end - start;
123
+ }
124
+ function calculateRequestTimingMetrics(entry) {
125
+ if (!entry) return DEFAULT_REQUEST_TIMING_METRICS;
126
+ const redirectDuration = getSafeDuration(entry.redirectStart, entry.redirectEnd);
127
+ const dnsLookupDuration = getSafeDuration(entry.domainLookupStart, entry.domainLookupEnd);
128
+ const tcpHandshakeDuration = getSafeDuration(entry.connectStart, entry.connectEnd);
129
+ const stalledDuration = getSafeDuration(entry.fetchStart, entry.requestStart);
130
+ const ttfbDuration = getSafeDuration(entry.requestStart, entry.responseStart);
131
+ const requestDuration = getSafeDuration(entry.requestStart, entry.responseEnd);
132
+ const tlsHandshakeDuration = entry.secureConnectionStart > 0 ? getSafeDuration(entry.secureConnectionStart, entry.connectEnd) : 0;
133
+ const duration = entry.duration > 0 ? entry.duration : requestDuration;
134
+ return {
135
+ duration,
136
+ dnsLookupDuration,
137
+ tcpHandshakeDuration,
138
+ redirectDuration,
139
+ stalledDuration,
140
+ ttfbDuration,
141
+ requestDuration,
142
+ tlsHandshakeDuration
143
+ };
144
+ }
145
+ function formatDurationInMs(duration) {
146
+ return `${duration.toFixed(2)}ms`;
147
+ }
148
+ initializeRequestPerformanceObserver();
56
149
  var isFilterUrl = (url) => {
57
150
  var _a;
58
151
  const { logger } = (0, import_config.getConfig)();
@@ -61,7 +154,7 @@ var isFilterUrl = (url) => {
61
154
  var createRequest = (props) => {
62
155
  const { data, config, method, url } = props;
63
156
  const { getUrl, logger } = (0, import_config.getConfig)();
64
- const startTime = Date.now();
157
+ const requestStartTime = typeof performance !== "undefined" ? performance.now() : Date.now();
65
158
  const app = (0, import_app.getApp)();
66
159
  const requestId = (0, import_utils2.getUniqueId)();
67
160
  requestCount++;
@@ -88,8 +181,10 @@ var createRequest = (props) => {
88
181
  let _url = (getUrl == null ? void 0 : getUrl(props)) || "";
89
182
  const handleRequestComplete = (url2, result, isError = false, requestId2) => {
90
183
  try {
91
- const endTime = Date.now();
92
- const duration = endTime - startTime;
184
+ const performanceEntry = readAndConsumeRequestTimingEntry(url2);
185
+ const timingMetrics = calculateRequestTimingMetrics(performanceEntry);
186
+ const fallbackDuration = (typeof performance !== "undefined" ? performance.now() : Date.now()) - requestStartTime;
187
+ const duration = timingMetrics.duration > 0 ? timingMetrics.duration : fallbackDuration;
93
188
  let maxRequestTime = (logger == null ? void 0 : logger.maxRequestTime) || 5e3;
94
189
  if (isFilterUrl(url2)) {
95
190
  maxRequestTime = 99999999;
@@ -100,11 +195,18 @@ var createRequest = (props) => {
100
195
  }
101
196
  app.logger.addLog({
102
197
  type,
103
- title: `[ Request ]: Complete - ${requestId2} 超过5s`,
198
+ title: `[ Request ]: Complete - ${requestId2}${duration > maxRequestTime ? " 超过5s" : ""}`,
104
199
  metadata: {
105
200
  error: isError ? JSON.stringify(result) : "",
106
201
  duration: `${(duration / 1e3).toFixed(2)}s`,
107
- url: url2
202
+ url: url2,
203
+ dnsLookupDuration: formatDurationInMs(timingMetrics.dnsLookupDuration),
204
+ tcpHandshakeDuration: formatDurationInMs(timingMetrics.tcpHandshakeDuration),
205
+ redirectDuration: formatDurationInMs(timingMetrics.redirectDuration),
206
+ stalledDuration: formatDurationInMs(timingMetrics.stalledDuration),
207
+ ttfbDuration: formatDurationInMs(timingMetrics.ttfbDuration),
208
+ requestDuration: formatDurationInMs(timingMetrics.requestDuration),
209
+ tlsHandshakeDuration: formatDurationInMs(timingMetrics.tlsHandshakeDuration)
108
210
  }
109
211
  });
110
212
  } catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pisell/core",
3
- "version": "1.0.63",
3
+ "version": "1.0.64",
4
4
  "sideEffects": false,
5
5
  "main": "./lib/index.js",
6
6
  "module": "./es/index.js",