@loglayer/transport-http 1.1.1 → 1.1.2
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/dist/index.cjs +329 -334
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +200 -192
- package/dist/index.d.ts +200 -192
- package/dist/index.js +301 -333
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.cjs
CHANGED
|
@@ -1,348 +1,343 @@
|
|
|
1
|
-
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
let __loglayer_transport = require("@loglayer/transport");
|
|
25
|
+
__loglayer_transport = __toESM(__loglayer_transport);
|
|
26
|
+
|
|
27
|
+
//#region src/errors.ts
|
|
28
|
+
/**
|
|
29
|
+
* Error thrown when HTTP request fails
|
|
30
|
+
*/
|
|
2
31
|
var HttpTransportError = class extends Error {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
32
|
+
constructor(message, status, response) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.status = status;
|
|
35
|
+
this.response = response;
|
|
36
|
+
this.name = "HttpTransportError";
|
|
37
|
+
}
|
|
9
38
|
};
|
|
39
|
+
/**
|
|
40
|
+
* Error thrown when rate limit is exceeded
|
|
41
|
+
*/
|
|
10
42
|
var RateLimitError = class extends Error {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
43
|
+
constructor(message, retryAfter) {
|
|
44
|
+
super(message);
|
|
45
|
+
this.retryAfter = retryAfter;
|
|
46
|
+
this.name = "RateLimitError";
|
|
47
|
+
}
|
|
16
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* Error thrown when log entry exceeds size limits
|
|
51
|
+
*/
|
|
17
52
|
var LogSizeError = class extends Error {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
53
|
+
constructor(message, logEntry, size, limit) {
|
|
54
|
+
super(message);
|
|
55
|
+
this.logEntry = logEntry;
|
|
56
|
+
this.size = size;
|
|
57
|
+
this.limit = limit;
|
|
58
|
+
this.name = "LogSizeError";
|
|
59
|
+
}
|
|
25
60
|
};
|
|
26
61
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/utils.ts
|
|
64
|
+
/**
|
|
65
|
+
* Compresses data using gzip compression
|
|
66
|
+
*/
|
|
31
67
|
async function compressData(data) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
throw new Error("Gzip compression not supported in this environment");
|
|
68
|
+
const dataBytes = new TextEncoder().encode(data);
|
|
69
|
+
if (typeof CompressionStream !== "undefined") {
|
|
70
|
+
const stream = new CompressionStream("gzip");
|
|
71
|
+
const writer = stream.writable.getWriter();
|
|
72
|
+
const reader = stream.readable.getReader();
|
|
73
|
+
await writer.write(dataBytes);
|
|
74
|
+
await writer.close();
|
|
75
|
+
const chunks = [];
|
|
76
|
+
while (true) {
|
|
77
|
+
const { done, value } = await reader.read();
|
|
78
|
+
if (done) break;
|
|
79
|
+
chunks.push(value);
|
|
80
|
+
}
|
|
81
|
+
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
|
|
82
|
+
const result = new Uint8Array(totalLength);
|
|
83
|
+
let offset = 0;
|
|
84
|
+
for (const chunk of chunks) {
|
|
85
|
+
result.set(chunk, offset);
|
|
86
|
+
offset += chunk.length;
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
throw new Error("Gzip compression not supported in this environment");
|
|
56
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Sends HTTP request with retry logic and rate limiting
|
|
94
|
+
*/
|
|
57
95
|
async function sendWithRetry(url, method, headers, payload, maxRetries, retryDelay, respectRateLimit = true, onDebugReqRes, onError) {
|
|
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
|
-
if (error instanceof RateLimitError && respectRateLimit) {
|
|
110
|
-
await new Promise((resolve) => setTimeout(resolve, error.retryAfter));
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
if (attempt === maxRetries) {
|
|
114
|
-
throw error;
|
|
115
|
-
}
|
|
116
|
-
const waitTime = retryDelay * 2 ** attempt;
|
|
117
|
-
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
throw lastError;
|
|
96
|
+
let lastError;
|
|
97
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) try {
|
|
98
|
+
const response = await fetch(url, {
|
|
99
|
+
method,
|
|
100
|
+
headers,
|
|
101
|
+
body: payload
|
|
102
|
+
});
|
|
103
|
+
if (onDebugReqRes) try {
|
|
104
|
+
const responseBody = await response.clone().text();
|
|
105
|
+
const responseHeaders = {};
|
|
106
|
+
response.headers.forEach((value, key) => {
|
|
107
|
+
responseHeaders[key] = value;
|
|
108
|
+
});
|
|
109
|
+
onDebugReqRes({
|
|
110
|
+
req: {
|
|
111
|
+
url,
|
|
112
|
+
method,
|
|
113
|
+
headers,
|
|
114
|
+
body: payload
|
|
115
|
+
},
|
|
116
|
+
res: {
|
|
117
|
+
status: response.status,
|
|
118
|
+
statusText: response.statusText,
|
|
119
|
+
headers: responseHeaders,
|
|
120
|
+
body: responseBody
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
} catch (debugError) {
|
|
124
|
+
if (onError) onError(/* @__PURE__ */ new Error(`Debug callback error: ${debugError}`));
|
|
125
|
+
}
|
|
126
|
+
if (response.status === 429 && respectRateLimit) {
|
|
127
|
+
const retryAfter = response.headers.get("retry-after");
|
|
128
|
+
const waitTime = retryAfter ? Number.parseInt(retryAfter, 10) * 1e3 : retryDelay;
|
|
129
|
+
throw new RateLimitError(`Rate limit exceeded. Retry after ${waitTime}ms`, waitTime);
|
|
130
|
+
}
|
|
131
|
+
if (response.status < 200 || response.status >= 300) {
|
|
132
|
+
if (onError) onError(/* @__PURE__ */ new Error(`HTTP request failed with status ${response.status}: ${response.statusText}`));
|
|
133
|
+
}
|
|
134
|
+
if (!response.ok) throw new HttpTransportError(`HTTP ${response.status}: ${response.statusText}`, response.status, response);
|
|
135
|
+
return response;
|
|
136
|
+
} catch (error) {
|
|
137
|
+
lastError = error;
|
|
138
|
+
if (error instanceof RateLimitError && respectRateLimit) {
|
|
139
|
+
await new Promise((resolve) => setTimeout(resolve, error.retryAfter));
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (attempt === maxRetries) throw error;
|
|
143
|
+
const waitTime = retryDelay * 2 ** attempt;
|
|
144
|
+
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
145
|
+
}
|
|
146
|
+
throw lastError;
|
|
121
147
|
}
|
|
122
148
|
|
|
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
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
* Sends a single payload to the HTTP endpoint
|
|
312
|
-
*/
|
|
313
|
-
async sendPayload(payload, contentType) {
|
|
314
|
-
const headers = typeof this.headers === "function" ? this.headers() : { ...this.headers };
|
|
315
|
-
if (!headers["content-type"]) {
|
|
316
|
-
headers["content-type"] = _nullishCoalesce(contentType, () => ( this.contentType));
|
|
317
|
-
}
|
|
318
|
-
let finalPayload = payload;
|
|
319
|
-
if (this.compression && !this.enableNextJsEdgeCompat) {
|
|
320
|
-
try {
|
|
321
|
-
finalPayload = await compressData(payload);
|
|
322
|
-
headers["content-encoding"] = "gzip";
|
|
323
|
-
} catch (error) {
|
|
324
|
-
if (this.onError) {
|
|
325
|
-
this.onError(new Error(`Compression failed: ${error}`));
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
await sendWithRetry(
|
|
330
|
-
this.url,
|
|
331
|
-
this.method,
|
|
332
|
-
headers,
|
|
333
|
-
finalPayload,
|
|
334
|
-
this.maxRetries,
|
|
335
|
-
this.retryDelay,
|
|
336
|
-
this.respectRateLimit,
|
|
337
|
-
this.onDebugReqRes,
|
|
338
|
-
this.onError
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
}, _class);
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
149
|
+
//#endregion
|
|
150
|
+
//#region src/HttpTransport.ts
|
|
151
|
+
/**
|
|
152
|
+
* HttpTransport is responsible for sending logs to any HTTP endpoint.
|
|
153
|
+
* It supports batching, compression, retries, and rate limiting.
|
|
154
|
+
*
|
|
155
|
+
* Features:
|
|
156
|
+
* - Configurable HTTP method and headers
|
|
157
|
+
* - Custom payload template function
|
|
158
|
+
* - Gzip compression support
|
|
159
|
+
* - Retry logic with exponential backoff
|
|
160
|
+
* - Rate limiting support
|
|
161
|
+
* - Batch sending with configurable size and timeout
|
|
162
|
+
* - Error and debug callbacks
|
|
163
|
+
* - Log size validation
|
|
164
|
+
* - Payload size tracking for batching
|
|
165
|
+
*/
|
|
166
|
+
var HttpTransport = class extends __loglayer_transport.LoggerlessTransport {
|
|
167
|
+
url;
|
|
168
|
+
method;
|
|
169
|
+
headers;
|
|
170
|
+
contentType;
|
|
171
|
+
batchContentType;
|
|
172
|
+
onError;
|
|
173
|
+
onDebug;
|
|
174
|
+
onDebugReqRes;
|
|
175
|
+
payloadTemplate;
|
|
176
|
+
compression;
|
|
177
|
+
maxRetries;
|
|
178
|
+
retryDelay;
|
|
179
|
+
respectRateLimit;
|
|
180
|
+
enableBatchSend;
|
|
181
|
+
batchSize;
|
|
182
|
+
batchSendTimeout;
|
|
183
|
+
batchSendDelimiter;
|
|
184
|
+
batchMode;
|
|
185
|
+
batchFieldName;
|
|
186
|
+
maxLogSize;
|
|
187
|
+
maxPayloadSize;
|
|
188
|
+
enableNextJsEdgeCompat;
|
|
189
|
+
batchQueue = [];
|
|
190
|
+
batchTimeout;
|
|
191
|
+
isProcessingBatch = false;
|
|
192
|
+
currentBatchSize = 0;
|
|
193
|
+
/**
|
|
194
|
+
* Creates a new instance of HttpTransport.
|
|
195
|
+
*
|
|
196
|
+
* @param config - Configuration options for the transport
|
|
197
|
+
*/
|
|
198
|
+
constructor(config) {
|
|
199
|
+
super(config);
|
|
200
|
+
this.url = config.url;
|
|
201
|
+
this.method = config.method ?? "POST";
|
|
202
|
+
this.headers = config.headers ?? {};
|
|
203
|
+
this.contentType = config.contentType ?? "application/json";
|
|
204
|
+
this.batchContentType = config.batchContentType ?? "application/json";
|
|
205
|
+
this.onError = config.onError;
|
|
206
|
+
this.onDebug = config.onDebug;
|
|
207
|
+
this.onDebugReqRes = config.onDebugReqRes;
|
|
208
|
+
this.payloadTemplate = config.payloadTemplate;
|
|
209
|
+
this.compression = config.compression ?? false;
|
|
210
|
+
this.maxRetries = config.maxRetries ?? 3;
|
|
211
|
+
this.retryDelay = config.retryDelay ?? 1e3;
|
|
212
|
+
this.respectRateLimit = config.respectRateLimit ?? true;
|
|
213
|
+
this.enableBatchSend = config.enableBatchSend ?? true;
|
|
214
|
+
this.batchSize = config.batchSize ?? 100;
|
|
215
|
+
this.batchSendTimeout = config.batchSendTimeout ?? 5e3;
|
|
216
|
+
this.batchSendDelimiter = config.batchSendDelimiter ?? "\n";
|
|
217
|
+
this.batchMode = config.batchMode ?? "delimiter";
|
|
218
|
+
this.batchFieldName = config.batchFieldName;
|
|
219
|
+
if (this.batchMode === "field" && !this.batchFieldName) throw new Error("batchFieldName is required when batchMode is 'field'");
|
|
220
|
+
this.maxLogSize = config.maxLogSize ?? 1048576;
|
|
221
|
+
this.maxPayloadSize = config.maxPayloadSize ?? 5242880;
|
|
222
|
+
this.enableNextJsEdgeCompat = config.enableNextJsEdgeCompat ?? false;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Processes and ships log entries to the HTTP endpoint.
|
|
226
|
+
*
|
|
227
|
+
* @param params - Log parameters including level, messages, and metadata
|
|
228
|
+
* @returns The original messages array
|
|
229
|
+
*/
|
|
230
|
+
shipToLogger({ logLevel, messages, data, hasData }) {
|
|
231
|
+
try {
|
|
232
|
+
const message = messages.join(" ");
|
|
233
|
+
const payloadTemplate = {
|
|
234
|
+
logLevel,
|
|
235
|
+
message
|
|
236
|
+
};
|
|
237
|
+
if (hasData) payloadTemplate["data"] = data;
|
|
238
|
+
const payload = this.payloadTemplate(payloadTemplate);
|
|
239
|
+
if (this.onDebug) this.onDebug({
|
|
240
|
+
logLevel,
|
|
241
|
+
message,
|
|
242
|
+
data
|
|
243
|
+
});
|
|
244
|
+
let logEntrySize;
|
|
245
|
+
if (this.enableNextJsEdgeCompat || typeof TextEncoder === "undefined") logEntrySize = Buffer.byteLength(payload, "utf8");
|
|
246
|
+
else logEntrySize = new TextEncoder().encode(payload).length;
|
|
247
|
+
if (logEntrySize > this.maxLogSize) {
|
|
248
|
+
const error = new LogSizeError(`Log entry exceeds maximum size of ${this.maxLogSize} bytes. Size: ${logEntrySize} bytes`, {
|
|
249
|
+
logLevel,
|
|
250
|
+
message,
|
|
251
|
+
data
|
|
252
|
+
}, logEntrySize, this.maxLogSize);
|
|
253
|
+
if (this.onError) this.onError(error);
|
|
254
|
+
return messages;
|
|
255
|
+
}
|
|
256
|
+
if (this.enableBatchSend) this.addToBatch(payload, logEntrySize);
|
|
257
|
+
else this.sendPayload(payload).catch((err) => {
|
|
258
|
+
if (this.onError) this.onError(err);
|
|
259
|
+
});
|
|
260
|
+
} catch (error) {
|
|
261
|
+
if (this.onError) this.onError(error);
|
|
262
|
+
}
|
|
263
|
+
return messages;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Adds a payload to the batch queue and triggers sending if conditions are met
|
|
267
|
+
*/
|
|
268
|
+
addToBatch(payload, logEntrySize) {
|
|
269
|
+
if (this.currentBatchSize + logEntrySize + this.batchSendDelimiter.length > this.maxPayloadSize * .9 && this.batchQueue.length > 0) this.processBatch();
|
|
270
|
+
this.batchQueue.push(payload);
|
|
271
|
+
this.currentBatchSize += logEntrySize + this.batchSendDelimiter.length;
|
|
272
|
+
if (!this.batchTimeout) this.batchTimeout = setTimeout(() => {
|
|
273
|
+
this.processBatch();
|
|
274
|
+
}, this.batchSendTimeout);
|
|
275
|
+
if (this.batchQueue.length >= this.batchSize) this.processBatch();
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Processes the current batch and sends it to the HTTP endpoint
|
|
279
|
+
*/
|
|
280
|
+
async processBatch() {
|
|
281
|
+
if (this.isProcessingBatch || this.batchQueue.length === 0) return;
|
|
282
|
+
this.isProcessingBatch = true;
|
|
283
|
+
if (this.batchTimeout) {
|
|
284
|
+
clearTimeout(this.batchTimeout);
|
|
285
|
+
this.batchTimeout = void 0;
|
|
286
|
+
}
|
|
287
|
+
const batch = this.batchQueue.splice(0, this.batchSize);
|
|
288
|
+
this.currentBatchSize = 0;
|
|
289
|
+
try {
|
|
290
|
+
await this.sendBatch(batch);
|
|
291
|
+
} catch (error) {
|
|
292
|
+
if (this.onError) this.onError(error);
|
|
293
|
+
} finally {
|
|
294
|
+
this.isProcessingBatch = false;
|
|
295
|
+
if (this.batchQueue.length > 0) this.processBatch();
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Sends a batch of payloads to the HTTP endpoint
|
|
300
|
+
*/
|
|
301
|
+
async sendBatch(batch) {
|
|
302
|
+
let batchPayload;
|
|
303
|
+
switch (this.batchMode) {
|
|
304
|
+
case "array": {
|
|
305
|
+
const batchEntries = batch.map((payload) => JSON.parse(payload));
|
|
306
|
+
batchPayload = JSON.stringify(batchEntries);
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
case "field": {
|
|
310
|
+
const fieldEntries = batch.map((payload) => JSON.parse(payload));
|
|
311
|
+
const batchObject = { [this.batchFieldName]: fieldEntries };
|
|
312
|
+
batchPayload = JSON.stringify(batchObject);
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
default:
|
|
316
|
+
batchPayload = batch.join(this.batchSendDelimiter);
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
await this.sendPayload(batchPayload, this.batchContentType);
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Sends a single payload to the HTTP endpoint
|
|
323
|
+
*/
|
|
324
|
+
async sendPayload(payload, contentType) {
|
|
325
|
+
const headers = typeof this.headers === "function" ? this.headers() : { ...this.headers };
|
|
326
|
+
if (!headers["content-type"]) headers["content-type"] = contentType ?? this.contentType;
|
|
327
|
+
let finalPayload = payload;
|
|
328
|
+
if (this.compression && !this.enableNextJsEdgeCompat) try {
|
|
329
|
+
finalPayload = await compressData(payload);
|
|
330
|
+
headers["content-encoding"] = "gzip";
|
|
331
|
+
} catch (error) {
|
|
332
|
+
if (this.onError) this.onError(/* @__PURE__ */ new Error(`Compression failed: ${error}`));
|
|
333
|
+
}
|
|
334
|
+
await sendWithRetry(this.url, this.method, headers, finalPayload, this.maxRetries, this.retryDelay, this.respectRateLimit, this.onDebugReqRes, this.onError);
|
|
335
|
+
}
|
|
336
|
+
};
|
|
346
337
|
|
|
347
|
-
|
|
338
|
+
//#endregion
|
|
339
|
+
exports.HttpTransport = HttpTransport;
|
|
340
|
+
exports.HttpTransportError = HttpTransportError;
|
|
341
|
+
exports.LogSizeError = LogSizeError;
|
|
342
|
+
exports.RateLimitError = RateLimitError;
|
|
348
343
|
//# sourceMappingURL=index.cjs.map
|