apitally 0.21.2 → 0.21.4
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/adonisjs/configure.cjs +6 -21
- package/dist/adonisjs/configure.cjs.map +1 -1
- package/dist/adonisjs/configure.js +3 -18
- package/dist/adonisjs/configure.js.map +1 -1
- package/dist/adonisjs/index.cjs +2 -70
- package/dist/adonisjs/index.cjs.map +1 -1
- package/dist/adonisjs/index.js +1 -66
- package/dist/adonisjs/index.js.map +1 -1
- package/dist/adonisjs/middleware.cjs +11 -116
- package/dist/adonisjs/middleware.cjs.map +1 -1
- package/dist/adonisjs/middleware.js +6 -101
- package/dist/adonisjs/middleware.js.map +1 -1
- package/dist/adonisjs/provider.cjs +15 -5663
- package/dist/adonisjs/provider.cjs.map +1 -1
- package/dist/adonisjs/provider.js +7 -5671
- package/dist/adonisjs/provider.js.map +1 -1
- package/dist/common/client.cjs +39 -800
- package/dist/common/client.cjs.map +1 -1
- package/dist/common/client.d.cts +1 -1
- package/dist/common/client.d.ts +1 -1
- package/dist/common/client.js +33 -794
- package/dist/common/client.js.map +1 -1
- package/dist/common/consumerRegistry.cjs +3 -5
- package/dist/common/consumerRegistry.cjs.map +1 -1
- package/dist/common/consumerRegistry.js +3 -5
- package/dist/common/consumerRegistry.js.map +1 -1
- package/dist/common/headers.cjs +0 -2
- package/dist/common/headers.cjs.map +1 -1
- package/dist/common/headers.js +0 -2
- package/dist/common/headers.js.map +1 -1
- package/dist/common/logging.cjs +0 -2
- package/dist/common/logging.cjs.map +1 -1
- package/dist/common/logging.js +0 -2
- package/dist/common/logging.js.map +1 -1
- package/dist/common/packageVersions.cjs +2 -4
- package/dist/common/packageVersions.cjs.map +1 -1
- package/dist/common/packageVersions.js +2 -10
- package/dist/common/packageVersions.js.map +1 -1
- package/dist/common/paramValidation.cjs +0 -2
- package/dist/common/paramValidation.cjs.map +1 -1
- package/dist/common/paramValidation.js +0 -2
- package/dist/common/paramValidation.js.map +1 -1
- package/dist/common/requestCounter.cjs +2 -4
- package/dist/common/requestCounter.cjs.map +1 -1
- package/dist/common/requestCounter.js +2 -4
- package/dist/common/requestCounter.js.map +1 -1
- package/dist/common/requestLogger.cjs +39 -162
- package/dist/common/requestLogger.cjs.map +1 -1
- package/dist/common/requestLogger.js +33 -156
- package/dist/common/requestLogger.js.map +1 -1
- package/dist/common/response.cjs +21 -4
- package/dist/common/response.cjs.map +1 -1
- package/dist/common/response.d.cts +2 -1
- package/dist/common/response.d.ts +2 -1
- package/dist/common/response.js +19 -3
- package/dist/common/response.js.map +1 -1
- package/dist/common/sentry.cjs +1 -3
- package/dist/common/sentry.cjs.map +1 -1
- package/dist/common/sentry.js +1 -3
- package/dist/common/sentry.js.map +1 -1
- package/dist/common/serverErrorCounter.cjs +7 -36
- package/dist/common/serverErrorCounter.cjs.map +1 -1
- package/dist/common/serverErrorCounter.js +6 -25
- package/dist/common/serverErrorCounter.js.map +1 -1
- package/dist/common/tempGzipFile.cjs +9 -11
- package/dist/common/tempGzipFile.cjs.map +1 -1
- package/dist/common/tempGzipFile.js +9 -11
- package/dist/common/tempGzipFile.js.map +1 -1
- package/dist/common/types.cjs +0 -2
- package/dist/common/types.cjs.map +1 -1
- package/dist/common/validationErrorCounter.cjs +3 -5
- package/dist/common/validationErrorCounter.cjs.map +1 -1
- package/dist/common/validationErrorCounter.js +3 -5
- package/dist/common/validationErrorCounter.js.map +1 -1
- package/dist/elysia/index.cjs +2 -1549
- package/dist/elysia/index.cjs.map +1 -1
- package/dist/elysia/index.js +2 -1553
- package/dist/elysia/index.js.map +1 -1
- package/dist/elysia/plugin.cjs +33 -1415
- package/dist/elysia/plugin.cjs.map +1 -1
- package/dist/elysia/plugin.js +22 -1399
- package/dist/elysia/plugin.js.map +1 -1
- package/dist/elysia/utils.cjs +3 -24
- package/dist/elysia/utils.cjs.map +1 -1
- package/dist/elysia/utils.js +1 -25
- package/dist/elysia/utils.js.map +1 -1
- package/dist/express/index.cjs +3 -6348
- package/dist/express/index.cjs.map +1 -1
- package/dist/express/index.js +1 -6361
- package/dist/express/index.js.map +1 -1
- package/dist/express/middleware.cjs +39 -6065
- package/dist/express/middleware.cjs.map +1 -1
- package/dist/express/middleware.js +14 -6056
- package/dist/express/middleware.js.map +1 -1
- package/dist/express/utils.cjs +17 -19
- package/dist/express/utils.cjs.map +1 -1
- package/dist/express/utils.js +17 -19
- package/dist/express/utils.js.map +1 -1
- package/dist/fastify/index.cjs +3 -6118
- package/dist/fastify/index.cjs.map +1 -1
- package/dist/fastify/index.js +2 -6142
- package/dist/fastify/index.js.map +1 -1
- package/dist/fastify/plugin.cjs +36 -5884
- package/dist/fastify/plugin.cjs.map +1 -1
- package/dist/fastify/plugin.js +14 -5888
- package/dist/fastify/plugin.js.map +1 -1
- package/dist/h3/index.cjs +3 -1539
- package/dist/h3/index.cjs.map +1 -1
- package/dist/h3/index.js +1 -1531
- package/dist/h3/index.js.map +1 -1
- package/dist/h3/plugin.cjs +28 -1418
- package/dist/h3/plugin.cjs.map +1 -1
- package/dist/h3/plugin.js +16 -1401
- package/dist/h3/plugin.js.map +1 -1
- package/dist/h3/utils.cjs +3 -24
- package/dist/h3/utils.cjs.map +1 -1
- package/dist/h3/utils.js +1 -25
- package/dist/h3/utils.js.map +1 -1
- package/dist/hapi/index.cjs +3 -5982
- package/dist/hapi/index.cjs.map +1 -1
- package/dist/hapi/index.js +2 -6006
- package/dist/hapi/index.js.map +1 -1
- package/dist/hapi/plugin.cjs +28 -5842
- package/dist/hapi/plugin.cjs.map +1 -1
- package/dist/hapi/plugin.js +16 -5846
- package/dist/hapi/plugin.js.map +1 -1
- package/dist/hapi/utils.cjs +3 -24
- package/dist/hapi/utils.cjs.map +1 -1
- package/dist/hapi/utils.js +1 -25
- package/dist/hapi/utils.js.map +1 -1
- package/dist/hono/index.cjs +3 -1565
- package/dist/hono/index.cjs.map +1 -1
- package/dist/hono/index.js +1 -1557
- package/dist/hono/index.js.map +1 -1
- package/dist/hono/middleware.cjs +22 -1455
- package/dist/hono/middleware.cjs.map +1 -1
- package/dist/hono/middleware.js +10 -1438
- package/dist/hono/middleware.js.map +1 -1
- package/dist/hono/utils.cjs +3 -24
- package/dist/hono/utils.cjs.map +1 -1
- package/dist/hono/utils.js +1 -27
- package/dist/hono/utils.js.map +1 -1
- package/dist/koa/index.cjs +3 -1478
- package/dist/koa/index.cjs.map +1 -1
- package/dist/koa/index.js +1 -1470
- package/dist/koa/index.js.map +1 -1
- package/dist/koa/middleware.cjs +20 -1308
- package/dist/koa/middleware.cjs.map +1 -1
- package/dist/koa/middleware.js +9 -1292
- package/dist/koa/middleware.js.map +1 -1
- package/dist/loggers/console.cjs +4 -6
- package/dist/loggers/console.cjs.map +1 -1
- package/dist/loggers/console.js +4 -6
- package/dist/loggers/console.js.map +1 -1
- package/dist/loggers/hapi.cjs +3 -5
- package/dist/loggers/hapi.cjs.map +1 -1
- package/dist/loggers/hapi.js +3 -5
- package/dist/loggers/hapi.js.map +1 -1
- package/dist/loggers/index.cjs +10 -4732
- package/dist/loggers/index.cjs.map +1 -1
- package/dist/loggers/index.js +5 -4743
- package/dist/loggers/index.js.map +1 -1
- package/dist/loggers/nestjs.cjs +5 -39
- package/dist/loggers/nestjs.cjs.map +1 -1
- package/dist/loggers/nestjs.js +4 -36
- package/dist/loggers/nestjs.js.map +1 -1
- package/dist/loggers/pino.cjs +29 -4448
- package/dist/loggers/pino.cjs.map +1 -1
- package/dist/loggers/pino.js +7 -4451
- package/dist/loggers/pino.js.map +1 -1
- package/dist/loggers/utils.cjs +1 -3
- package/dist/loggers/utils.cjs.map +1 -1
- package/dist/loggers/utils.js +1 -3
- package/dist/loggers/utils.js.map +1 -1
- package/dist/loggers/winston.cjs +6 -44
- package/dist/loggers/winston.cjs.map +1 -1
- package/dist/loggers/winston.js +4 -40
- package/dist/loggers/winston.js.map +1 -1
- package/dist/nestjs/index.cjs +17 -17779
- package/dist/nestjs/index.cjs.map +1 -1
- package/dist/nestjs/index.js +20 -17807
- package/dist/nestjs/index.js.map +1 -1
- package/package.json +1 -1
package/dist/common/client.js
CHANGED
|
@@ -2,787 +2,21 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
-
|
|
6
|
-
// src/common/client.ts
|
|
7
|
-
import fetchRetry from "fetch-retry";
|
|
8
|
-
import { randomUUID as randomUUID3 } from "crypto";
|
|
9
|
-
|
|
10
|
-
// src/common/consumerRegistry.ts
|
|
11
|
-
var _ConsumerRegistry = class _ConsumerRegistry {
|
|
12
|
-
consumers;
|
|
13
|
-
updated;
|
|
14
|
-
constructor() {
|
|
15
|
-
this.consumers = /* @__PURE__ */ new Map();
|
|
16
|
-
this.updated = /* @__PURE__ */ new Set();
|
|
17
|
-
}
|
|
18
|
-
addOrUpdateConsumer(consumer) {
|
|
19
|
-
if (!consumer || !consumer.name && !consumer.group) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
const existing = this.consumers.get(consumer.identifier);
|
|
23
|
-
if (!existing) {
|
|
24
|
-
this.consumers.set(consumer.identifier, consumer);
|
|
25
|
-
this.updated.add(consumer.identifier);
|
|
26
|
-
} else {
|
|
27
|
-
if (consumer.name && consumer.name !== existing.name) {
|
|
28
|
-
existing.name = consumer.name;
|
|
29
|
-
this.updated.add(consumer.identifier);
|
|
30
|
-
}
|
|
31
|
-
if (consumer.group && consumer.group !== existing.group) {
|
|
32
|
-
existing.group = consumer.group;
|
|
33
|
-
this.updated.add(consumer.identifier);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
getAndResetUpdatedConsumers() {
|
|
38
|
-
const data = [];
|
|
39
|
-
this.updated.forEach((identifier) => {
|
|
40
|
-
const consumer = this.consumers.get(identifier);
|
|
41
|
-
if (consumer) {
|
|
42
|
-
data.push(consumer);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
this.updated.clear();
|
|
46
|
-
return data;
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
__name(_ConsumerRegistry, "ConsumerRegistry");
|
|
50
|
-
var ConsumerRegistry = _ConsumerRegistry;
|
|
51
|
-
|
|
52
|
-
// src/common/logging.ts
|
|
53
|
-
import { createLogger, format, transports } from "winston";
|
|
54
|
-
function getLogger() {
|
|
55
|
-
return createLogger({
|
|
56
|
-
level: process.env.APITALLY_DEBUG ? "debug" : "warn",
|
|
57
|
-
format: format.combine(format.colorize(), format.timestamp(), format.printf((info) => `${info.timestamp} ${info.level}: ${info.message}`)),
|
|
58
|
-
transports: [
|
|
59
|
-
new transports.Console()
|
|
60
|
-
]
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
__name(getLogger, "getLogger");
|
|
64
|
-
|
|
65
|
-
// src/common/paramValidation.ts
|
|
66
|
-
function isValidClientId(clientId) {
|
|
67
|
-
const regexExp = /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
68
|
-
return regexExp.test(clientId);
|
|
69
|
-
}
|
|
70
|
-
__name(isValidClientId, "isValidClientId");
|
|
71
|
-
function isValidEnv(env) {
|
|
72
|
-
const regexExp = /^[\w-]{1,32}$/;
|
|
73
|
-
return regexExp.test(env);
|
|
74
|
-
}
|
|
75
|
-
__name(isValidEnv, "isValidEnv");
|
|
76
|
-
|
|
77
|
-
// src/common/requestCounter.ts
|
|
78
|
-
var _RequestCounter = class _RequestCounter {
|
|
79
|
-
requestCounts;
|
|
80
|
-
requestSizeSums;
|
|
81
|
-
responseSizeSums;
|
|
82
|
-
responseTimes;
|
|
83
|
-
requestSizes;
|
|
84
|
-
responseSizes;
|
|
85
|
-
constructor() {
|
|
86
|
-
this.requestCounts = /* @__PURE__ */ new Map();
|
|
87
|
-
this.requestSizeSums = /* @__PURE__ */ new Map();
|
|
88
|
-
this.responseSizeSums = /* @__PURE__ */ new Map();
|
|
89
|
-
this.responseTimes = /* @__PURE__ */ new Map();
|
|
90
|
-
this.requestSizes = /* @__PURE__ */ new Map();
|
|
91
|
-
this.responseSizes = /* @__PURE__ */ new Map();
|
|
92
|
-
}
|
|
93
|
-
getKey(requestInfo) {
|
|
94
|
-
return [
|
|
95
|
-
requestInfo.consumer || "",
|
|
96
|
-
requestInfo.method.toUpperCase(),
|
|
97
|
-
requestInfo.path,
|
|
98
|
-
requestInfo.statusCode
|
|
99
|
-
].join("|");
|
|
100
|
-
}
|
|
101
|
-
addRequest(requestInfo) {
|
|
102
|
-
const key = this.getKey(requestInfo);
|
|
103
|
-
this.requestCounts.set(key, (this.requestCounts.get(key) || 0) + 1);
|
|
104
|
-
if (!this.responseTimes.has(key)) {
|
|
105
|
-
this.responseTimes.set(key, /* @__PURE__ */ new Map());
|
|
106
|
-
}
|
|
107
|
-
const responseTimeMap = this.responseTimes.get(key);
|
|
108
|
-
const responseTimeMsBin = Math.floor(requestInfo.responseTime / 10) * 10;
|
|
109
|
-
responseTimeMap.set(responseTimeMsBin, (responseTimeMap.get(responseTimeMsBin) || 0) + 1);
|
|
110
|
-
if (requestInfo.requestSize !== void 0) {
|
|
111
|
-
requestInfo.requestSize = Number(requestInfo.requestSize);
|
|
112
|
-
this.requestSizeSums.set(key, (this.requestSizeSums.get(key) || 0) + requestInfo.requestSize);
|
|
113
|
-
if (!this.requestSizes.has(key)) {
|
|
114
|
-
this.requestSizes.set(key, /* @__PURE__ */ new Map());
|
|
115
|
-
}
|
|
116
|
-
const requestSizeMap = this.requestSizes.get(key);
|
|
117
|
-
const requestSizeKbBin = Math.floor(requestInfo.requestSize / 1e3);
|
|
118
|
-
requestSizeMap.set(requestSizeKbBin, (requestSizeMap.get(requestSizeKbBin) || 0) + 1);
|
|
119
|
-
}
|
|
120
|
-
if (requestInfo.responseSize !== void 0) {
|
|
121
|
-
requestInfo.responseSize = Number(requestInfo.responseSize);
|
|
122
|
-
this.responseSizeSums.set(key, (this.responseSizeSums.get(key) || 0) + requestInfo.responseSize);
|
|
123
|
-
if (!this.responseSizes.has(key)) {
|
|
124
|
-
this.responseSizes.set(key, /* @__PURE__ */ new Map());
|
|
125
|
-
}
|
|
126
|
-
const responseSizeMap = this.responseSizes.get(key);
|
|
127
|
-
const responseSizeKbBin = Math.floor(requestInfo.responseSize / 1e3);
|
|
128
|
-
responseSizeMap.set(responseSizeKbBin, (responseSizeMap.get(responseSizeKbBin) || 0) + 1);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
getAndResetRequests() {
|
|
132
|
-
const data = [];
|
|
133
|
-
this.requestCounts.forEach((count, key) => {
|
|
134
|
-
const [consumer, method, path, statusCodeStr] = key.split("|");
|
|
135
|
-
const responseTimes = this.responseTimes.get(key) || /* @__PURE__ */ new Map();
|
|
136
|
-
const requestSizes = this.requestSizes.get(key) || /* @__PURE__ */ new Map();
|
|
137
|
-
const responseSizes = this.responseSizes.get(key) || /* @__PURE__ */ new Map();
|
|
138
|
-
data.push({
|
|
139
|
-
consumer: consumer || null,
|
|
140
|
-
method,
|
|
141
|
-
path,
|
|
142
|
-
status_code: parseInt(statusCodeStr),
|
|
143
|
-
request_count: count,
|
|
144
|
-
request_size_sum: this.requestSizeSums.get(key) || 0,
|
|
145
|
-
response_size_sum: this.responseSizeSums.get(key) || 0,
|
|
146
|
-
response_times: Object.fromEntries(responseTimes),
|
|
147
|
-
request_sizes: Object.fromEntries(requestSizes),
|
|
148
|
-
response_sizes: Object.fromEntries(responseSizes)
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
this.requestCounts.clear();
|
|
152
|
-
this.requestSizeSums.clear();
|
|
153
|
-
this.responseSizeSums.clear();
|
|
154
|
-
this.responseTimes.clear();
|
|
155
|
-
this.requestSizes.clear();
|
|
156
|
-
this.responseSizes.clear();
|
|
157
|
-
return data;
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
__name(_RequestCounter, "RequestCounter");
|
|
161
|
-
var RequestCounter = _RequestCounter;
|
|
162
|
-
|
|
163
|
-
// src/common/requestLogger.ts
|
|
164
|
-
import AsyncLock from "async-lock";
|
|
165
|
-
import { Buffer as Buffer3 } from "buffer";
|
|
166
|
-
import { randomUUID as randomUUID2 } from "crypto";
|
|
167
|
-
import { unlinkSync, writeFileSync } from "fs";
|
|
168
|
-
import { tmpdir as tmpdir2 } from "os";
|
|
169
|
-
import { join as join2 } from "path";
|
|
170
|
-
|
|
171
|
-
// src/common/sentry.ts
|
|
172
|
-
var sentry;
|
|
173
|
-
(async () => {
|
|
174
|
-
try {
|
|
175
|
-
sentry = await import("@sentry/node");
|
|
176
|
-
} catch (e) {
|
|
177
|
-
}
|
|
178
|
-
})();
|
|
179
|
-
function getSentryEventId() {
|
|
180
|
-
if (sentry && sentry.lastEventId) {
|
|
181
|
-
return sentry.lastEventId();
|
|
182
|
-
}
|
|
183
|
-
return void 0;
|
|
184
|
-
}
|
|
185
|
-
__name(getSentryEventId, "getSentryEventId");
|
|
186
|
-
|
|
187
|
-
// src/common/serverErrorCounter.ts
|
|
188
|
-
import { createHash } from "crypto";
|
|
189
|
-
var MAX_MSG_LENGTH = 2048;
|
|
190
|
-
var MAX_STACKTRACE_LENGTH = 65536;
|
|
191
|
-
var _ServerErrorCounter = class _ServerErrorCounter {
|
|
192
|
-
errorCounts;
|
|
193
|
-
errorDetails;
|
|
194
|
-
sentryEventIds;
|
|
195
|
-
constructor() {
|
|
196
|
-
this.errorCounts = /* @__PURE__ */ new Map();
|
|
197
|
-
this.errorDetails = /* @__PURE__ */ new Map();
|
|
198
|
-
this.sentryEventIds = /* @__PURE__ */ new Map();
|
|
199
|
-
}
|
|
200
|
-
addServerError(serverError) {
|
|
201
|
-
const key = this.getKey(serverError);
|
|
202
|
-
if (!this.errorDetails.has(key)) {
|
|
203
|
-
this.errorDetails.set(key, serverError);
|
|
204
|
-
}
|
|
205
|
-
this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);
|
|
206
|
-
const sentryEventId = getSentryEventId();
|
|
207
|
-
if (sentryEventId) {
|
|
208
|
-
this.sentryEventIds.set(key, sentryEventId);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
getAndResetServerErrors() {
|
|
212
|
-
const data = [];
|
|
213
|
-
this.errorCounts.forEach((count, key) => {
|
|
214
|
-
const serverError = this.errorDetails.get(key);
|
|
215
|
-
if (serverError) {
|
|
216
|
-
data.push({
|
|
217
|
-
consumer: serverError.consumer || null,
|
|
218
|
-
method: serverError.method,
|
|
219
|
-
path: serverError.path,
|
|
220
|
-
type: serverError.type,
|
|
221
|
-
msg: truncateExceptionMessage(serverError.msg),
|
|
222
|
-
traceback: truncateExceptionStackTrace(serverError.traceback),
|
|
223
|
-
sentry_event_id: this.sentryEventIds.get(key) || null,
|
|
224
|
-
error_count: count
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
this.errorCounts.clear();
|
|
229
|
-
this.errorDetails.clear();
|
|
230
|
-
this.sentryEventIds.clear();
|
|
231
|
-
return data;
|
|
232
|
-
}
|
|
233
|
-
getKey(serverError) {
|
|
234
|
-
const hashInput = [
|
|
235
|
-
serverError.consumer || "",
|
|
236
|
-
serverError.method.toUpperCase(),
|
|
237
|
-
serverError.path,
|
|
238
|
-
serverError.type,
|
|
239
|
-
serverError.msg.trim(),
|
|
240
|
-
serverError.traceback.trim()
|
|
241
|
-
].join("|");
|
|
242
|
-
return createHash("md5").update(hashInput).digest("hex");
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
__name(_ServerErrorCounter, "ServerErrorCounter");
|
|
246
|
-
var ServerErrorCounter = _ServerErrorCounter;
|
|
247
|
-
function truncateExceptionMessage(msg) {
|
|
248
|
-
if (msg.length <= MAX_MSG_LENGTH) {
|
|
249
|
-
return msg;
|
|
250
|
-
}
|
|
251
|
-
const suffix = "... (truncated)";
|
|
252
|
-
const cutoff = MAX_MSG_LENGTH - suffix.length;
|
|
253
|
-
return msg.substring(0, cutoff) + suffix;
|
|
254
|
-
}
|
|
255
|
-
__name(truncateExceptionMessage, "truncateExceptionMessage");
|
|
256
|
-
function truncateExceptionStackTrace(stack) {
|
|
257
|
-
const suffix = "... (truncated) ...";
|
|
258
|
-
const cutoff = MAX_STACKTRACE_LENGTH - suffix.length;
|
|
259
|
-
const lines = stack.trim().split("\n");
|
|
260
|
-
const truncatedLines = [];
|
|
261
|
-
let length = 0;
|
|
262
|
-
for (const line of lines) {
|
|
263
|
-
if (length + line.length + 1 > cutoff) {
|
|
264
|
-
truncatedLines.push(suffix);
|
|
265
|
-
break;
|
|
266
|
-
}
|
|
267
|
-
truncatedLines.push(line);
|
|
268
|
-
length += line.length + 1;
|
|
269
|
-
}
|
|
270
|
-
return truncatedLines.join("\n");
|
|
271
|
-
}
|
|
272
|
-
__name(truncateExceptionStackTrace, "truncateExceptionStackTrace");
|
|
273
|
-
|
|
274
|
-
// src/common/tempGzipFile.ts
|
|
275
|
-
import { Buffer as Buffer2 } from "buffer";
|
|
276
|
-
import { randomUUID } from "crypto";
|
|
277
|
-
import { createWriteStream, readFile } from "fs";
|
|
278
|
-
import { unlink } from "fs/promises";
|
|
279
|
-
import { tmpdir } from "os";
|
|
280
|
-
import { join } from "path";
|
|
281
|
-
import { createGzip } from "zlib";
|
|
282
|
-
var _TempGzipFile = class _TempGzipFile {
|
|
283
|
-
uuid;
|
|
284
|
-
filePath;
|
|
285
|
-
gzip;
|
|
286
|
-
writeStream;
|
|
287
|
-
readyPromise;
|
|
288
|
-
closedPromise;
|
|
289
|
-
constructor() {
|
|
290
|
-
this.uuid = randomUUID();
|
|
291
|
-
this.filePath = join(tmpdir(), `apitally-${this.uuid}.gz`);
|
|
292
|
-
this.writeStream = createWriteStream(this.filePath);
|
|
293
|
-
this.readyPromise = new Promise((resolve, reject) => {
|
|
294
|
-
this.writeStream.once("ready", resolve);
|
|
295
|
-
this.writeStream.once("error", reject);
|
|
296
|
-
});
|
|
297
|
-
this.closedPromise = new Promise((resolve, reject) => {
|
|
298
|
-
this.writeStream.once("close", resolve);
|
|
299
|
-
this.writeStream.once("error", reject);
|
|
300
|
-
});
|
|
301
|
-
this.gzip = createGzip();
|
|
302
|
-
this.gzip.pipe(this.writeStream);
|
|
303
|
-
}
|
|
304
|
-
get size() {
|
|
305
|
-
return this.writeStream.bytesWritten;
|
|
306
|
-
}
|
|
307
|
-
async writeLine(data) {
|
|
308
|
-
await this.readyPromise;
|
|
309
|
-
return new Promise((resolve, reject) => {
|
|
310
|
-
this.gzip.write(Buffer2.concat([
|
|
311
|
-
data,
|
|
312
|
-
Buffer2.from("\n")
|
|
313
|
-
]), (error) => {
|
|
314
|
-
if (error) {
|
|
315
|
-
reject(error);
|
|
316
|
-
} else {
|
|
317
|
-
resolve();
|
|
318
|
-
}
|
|
319
|
-
});
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
async getContent() {
|
|
323
|
-
return new Promise((resolve, reject) => {
|
|
324
|
-
readFile(this.filePath, (error, data) => {
|
|
325
|
-
if (error) {
|
|
326
|
-
reject(error);
|
|
327
|
-
} else {
|
|
328
|
-
resolve(data);
|
|
329
|
-
}
|
|
330
|
-
});
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
async close() {
|
|
334
|
-
await new Promise((resolve) => {
|
|
335
|
-
this.gzip.end(() => {
|
|
336
|
-
resolve();
|
|
337
|
-
});
|
|
338
|
-
});
|
|
339
|
-
await this.closedPromise;
|
|
340
|
-
}
|
|
341
|
-
async delete() {
|
|
342
|
-
await this.close();
|
|
343
|
-
await unlink(this.filePath);
|
|
344
|
-
}
|
|
345
|
-
};
|
|
346
|
-
__name(_TempGzipFile, "TempGzipFile");
|
|
347
|
-
var TempGzipFile = _TempGzipFile;
|
|
348
|
-
|
|
349
|
-
// src/common/requestLogger.ts
|
|
350
|
-
var MAX_BODY_SIZE = 5e4;
|
|
351
|
-
var MAX_FILE_SIZE = 1e6;
|
|
352
|
-
var MAX_FILES = 50;
|
|
353
|
-
var MAX_PENDING_WRITES = 100;
|
|
354
|
-
var MAX_LOG_MSG_LENGTH = 2048;
|
|
355
|
-
var BODY_TOO_LARGE = Buffer3.from("<body too large>");
|
|
356
|
-
var BODY_MASKED = Buffer3.from("<masked>");
|
|
357
|
-
var MASKED = "******";
|
|
358
|
-
var ALLOWED_CONTENT_TYPES = [
|
|
359
|
-
"application/json",
|
|
360
|
-
"application/problem+json",
|
|
361
|
-
"application/vnd.api+json",
|
|
362
|
-
"text/plain",
|
|
363
|
-
"text/html"
|
|
364
|
-
];
|
|
365
|
-
var EXCLUDE_PATH_PATTERNS = [
|
|
366
|
-
/\/_?healthz?$/i,
|
|
367
|
-
/\/_?health[_-]?checks?$/i,
|
|
368
|
-
/\/_?heart[_-]?beats?$/i,
|
|
369
|
-
/\/ping$/i,
|
|
370
|
-
/\/ready$/i,
|
|
371
|
-
/\/live$/i
|
|
372
|
-
];
|
|
373
|
-
var EXCLUDE_USER_AGENT_PATTERNS = [
|
|
374
|
-
/health[-_ ]?check/i,
|
|
375
|
-
/microsoft-azure-application-lb/i,
|
|
376
|
-
/googlehc/i,
|
|
377
|
-
/kube-probe/i
|
|
378
|
-
];
|
|
379
|
-
var MASK_QUERY_PARAM_PATTERNS = [
|
|
380
|
-
/auth/i,
|
|
381
|
-
/api-?key/i,
|
|
382
|
-
/secret/i,
|
|
383
|
-
/token/i,
|
|
384
|
-
/password/i,
|
|
385
|
-
/pwd/i
|
|
386
|
-
];
|
|
387
|
-
var MASK_HEADER_PATTERNS = [
|
|
388
|
-
/auth/i,
|
|
389
|
-
/api-?key/i,
|
|
390
|
-
/secret/i,
|
|
391
|
-
/token/i,
|
|
392
|
-
/cookie/i
|
|
393
|
-
];
|
|
394
|
-
var MASK_BODY_FIELD_PATTERNS = [
|
|
395
|
-
/password/i,
|
|
396
|
-
/pwd/i,
|
|
397
|
-
/token/i,
|
|
398
|
-
/secret/i,
|
|
399
|
-
/auth/i,
|
|
400
|
-
/card[-_ ]?number/i,
|
|
401
|
-
/ccv/i,
|
|
402
|
-
/ssn/i
|
|
403
|
-
];
|
|
404
|
-
var DEFAULT_CONFIG = {
|
|
405
|
-
enabled: false,
|
|
406
|
-
logQueryParams: true,
|
|
407
|
-
logRequestHeaders: false,
|
|
408
|
-
logRequestBody: false,
|
|
409
|
-
logResponseHeaders: true,
|
|
410
|
-
logResponseBody: false,
|
|
411
|
-
logException: true,
|
|
412
|
-
captureLogs: false,
|
|
413
|
-
maskQueryParams: [],
|
|
414
|
-
maskHeaders: [],
|
|
415
|
-
maskBodyFields: [],
|
|
416
|
-
excludePaths: []
|
|
417
|
-
};
|
|
418
|
-
var _RequestLogger = class _RequestLogger {
|
|
419
|
-
config;
|
|
420
|
-
enabled;
|
|
421
|
-
suspendUntil = null;
|
|
422
|
-
pendingWrites = [];
|
|
423
|
-
currentFile = null;
|
|
424
|
-
files = [];
|
|
425
|
-
maintainIntervalId;
|
|
426
|
-
lock = new AsyncLock();
|
|
427
|
-
constructor(config) {
|
|
428
|
-
this.config = {
|
|
429
|
-
...DEFAULT_CONFIG,
|
|
430
|
-
...config
|
|
431
|
-
};
|
|
432
|
-
this.enabled = this.config.enabled && checkWritableFs();
|
|
433
|
-
if (this.enabled) {
|
|
434
|
-
this.maintainIntervalId = setInterval(() => {
|
|
435
|
-
this.maintain();
|
|
436
|
-
}, 1e3);
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
get maxBodySize() {
|
|
440
|
-
return MAX_BODY_SIZE;
|
|
441
|
-
}
|
|
442
|
-
shouldExcludePath(urlPath) {
|
|
443
|
-
const patterns = [
|
|
444
|
-
...this.config.excludePaths,
|
|
445
|
-
...EXCLUDE_PATH_PATTERNS
|
|
446
|
-
];
|
|
447
|
-
return matchPatterns(urlPath, patterns);
|
|
448
|
-
}
|
|
449
|
-
shouldExcludeUserAgent(userAgent) {
|
|
450
|
-
return userAgent ? matchPatterns(userAgent, EXCLUDE_USER_AGENT_PATTERNS) : false;
|
|
451
|
-
}
|
|
452
|
-
shouldMaskQueryParam(name) {
|
|
453
|
-
const patterns = [
|
|
454
|
-
...this.config.maskQueryParams,
|
|
455
|
-
...MASK_QUERY_PARAM_PATTERNS
|
|
456
|
-
];
|
|
457
|
-
return matchPatterns(name, patterns);
|
|
458
|
-
}
|
|
459
|
-
shouldMaskHeader(name) {
|
|
460
|
-
const patterns = [
|
|
461
|
-
...this.config.maskHeaders,
|
|
462
|
-
...MASK_HEADER_PATTERNS
|
|
463
|
-
];
|
|
464
|
-
return matchPatterns(name, patterns);
|
|
465
|
-
}
|
|
466
|
-
shouldMaskBodyField(name) {
|
|
467
|
-
const patterns = [
|
|
468
|
-
...this.config.maskBodyFields,
|
|
469
|
-
...MASK_BODY_FIELD_PATTERNS
|
|
470
|
-
];
|
|
471
|
-
return matchPatterns(name, patterns);
|
|
472
|
-
}
|
|
473
|
-
hasSupportedContentType(headers) {
|
|
474
|
-
var _a2;
|
|
475
|
-
const contentType = (_a2 = headers.find(([k]) => k.toLowerCase() === "content-type")) == null ? void 0 : _a2[1];
|
|
476
|
-
return this.isSupportedContentType(contentType);
|
|
477
|
-
}
|
|
478
|
-
hasJsonContentType(headers) {
|
|
479
|
-
var _a2;
|
|
480
|
-
const contentType = (_a2 = headers.find(([k]) => k.toLowerCase() === "content-type")) == null ? void 0 : _a2[1];
|
|
481
|
-
return contentType ? /\bjson\b/i.test(contentType) : null;
|
|
482
|
-
}
|
|
483
|
-
isSupportedContentType(contentType) {
|
|
484
|
-
return typeof contentType === "string" && ALLOWED_CONTENT_TYPES.some((t) => contentType.startsWith(t));
|
|
485
|
-
}
|
|
486
|
-
maskQueryParams(search) {
|
|
487
|
-
const params = new URLSearchParams(search);
|
|
488
|
-
for (const [key] of params) {
|
|
489
|
-
if (this.shouldMaskQueryParam(key)) {
|
|
490
|
-
params.set(key, MASKED);
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
return params.toString();
|
|
494
|
-
}
|
|
495
|
-
maskHeaders(headers) {
|
|
496
|
-
return headers.map(([k, v]) => [
|
|
497
|
-
k,
|
|
498
|
-
this.shouldMaskHeader(k) ? MASKED : v
|
|
499
|
-
]);
|
|
500
|
-
}
|
|
501
|
-
maskBody(data) {
|
|
502
|
-
if (typeof data === "object" && data !== null && !Array.isArray(data)) {
|
|
503
|
-
const result = {};
|
|
504
|
-
for (const [key, value] of Object.entries(data)) {
|
|
505
|
-
if (typeof value === "string" && this.shouldMaskBodyField(key)) {
|
|
506
|
-
result[key] = MASKED;
|
|
507
|
-
} else {
|
|
508
|
-
result[key] = this.maskBody(value);
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
return result;
|
|
512
|
-
}
|
|
513
|
-
if (Array.isArray(data)) {
|
|
514
|
-
return data.map((item) => this.maskBody(item));
|
|
515
|
-
}
|
|
516
|
-
return data;
|
|
517
|
-
}
|
|
518
|
-
applyMasking(item) {
|
|
519
|
-
if (this.config.maskRequestBodyCallback && item.request.body && item.request.body !== BODY_TOO_LARGE) {
|
|
520
|
-
try {
|
|
521
|
-
const maskedBody = this.config.maskRequestBodyCallback(item.request);
|
|
522
|
-
item.request.body = maskedBody ?? BODY_MASKED;
|
|
523
|
-
} catch {
|
|
524
|
-
item.request.body = void 0;
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
if (this.config.maskResponseBodyCallback && item.response.body && item.response.body !== BODY_TOO_LARGE) {
|
|
528
|
-
try {
|
|
529
|
-
const maskedBody = this.config.maskResponseBodyCallback(item.request, item.response);
|
|
530
|
-
item.response.body = maskedBody ?? BODY_MASKED;
|
|
531
|
-
} catch {
|
|
532
|
-
item.response.body = void 0;
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
if (item.request.body && item.request.body.length > MAX_BODY_SIZE) {
|
|
536
|
-
item.request.body = BODY_TOO_LARGE;
|
|
537
|
-
}
|
|
538
|
-
if (item.response.body && item.response.body.length > MAX_BODY_SIZE) {
|
|
539
|
-
item.response.body = BODY_TOO_LARGE;
|
|
540
|
-
}
|
|
541
|
-
for (const key of [
|
|
542
|
-
"request",
|
|
543
|
-
"response"
|
|
544
|
-
]) {
|
|
545
|
-
const bodyData = item[key].body;
|
|
546
|
-
if (!bodyData || bodyData === BODY_TOO_LARGE || bodyData === BODY_MASKED) {
|
|
547
|
-
continue;
|
|
548
|
-
}
|
|
549
|
-
const headers = item[key].headers;
|
|
550
|
-
const hasJsonContent = this.hasJsonContentType(headers);
|
|
551
|
-
if (hasJsonContent === null || hasJsonContent) {
|
|
552
|
-
try {
|
|
553
|
-
const parsedBody = JSON.parse(bodyData.toString());
|
|
554
|
-
const maskedBody = this.maskBody(parsedBody);
|
|
555
|
-
item[key].body = Buffer3.from(JSON.stringify(maskedBody));
|
|
556
|
-
} catch {
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
item.request.headers = this.config.logRequestHeaders ? this.maskHeaders(item.request.headers) : [];
|
|
561
|
-
item.response.headers = this.config.logResponseHeaders ? this.maskHeaders(item.response.headers) : [];
|
|
562
|
-
const url = new URL(item.request.url);
|
|
563
|
-
url.search = this.config.logQueryParams ? this.maskQueryParams(url.search) : "";
|
|
564
|
-
item.request.url = url.toString();
|
|
565
|
-
return item;
|
|
566
|
-
}
|
|
567
|
-
logRequest(request, response, error, logs) {
|
|
568
|
-
var _a2, _b, _c;
|
|
569
|
-
if (!this.enabled || this.suspendUntil !== null) return;
|
|
570
|
-
const url = new URL(request.url);
|
|
571
|
-
const path = request.path ?? url.pathname;
|
|
572
|
-
const userAgent = (_a2 = request.headers.find(([k]) => k.toLowerCase() === "user-agent")) == null ? void 0 : _a2[1];
|
|
573
|
-
if (this.shouldExcludePath(path) || this.shouldExcludeUserAgent(userAgent) || (((_c = (_b = this.config).excludeCallback) == null ? void 0 : _c.call(_b, request, response)) ?? false)) {
|
|
574
|
-
return;
|
|
575
|
-
}
|
|
576
|
-
if (!this.config.logRequestBody || !this.hasSupportedContentType(request.headers)) {
|
|
577
|
-
request.body = void 0;
|
|
578
|
-
}
|
|
579
|
-
if (!this.config.logResponseBody || !this.hasSupportedContentType(response.headers)) {
|
|
580
|
-
response.body = void 0;
|
|
581
|
-
}
|
|
582
|
-
if (request.size !== void 0 && request.size < 0) {
|
|
583
|
-
request.size = void 0;
|
|
584
|
-
}
|
|
585
|
-
if (response.size !== void 0 && response.size < 0) {
|
|
586
|
-
response.size = void 0;
|
|
587
|
-
}
|
|
588
|
-
const item = {
|
|
589
|
-
uuid: randomUUID2(),
|
|
590
|
-
request,
|
|
591
|
-
response,
|
|
592
|
-
exception: error && this.config.logException ? {
|
|
593
|
-
type: error.name,
|
|
594
|
-
message: truncateExceptionMessage(error.message),
|
|
595
|
-
stacktrace: truncateExceptionStackTrace(error.stack || ""),
|
|
596
|
-
sentryEventId: getSentryEventId()
|
|
597
|
-
} : void 0
|
|
598
|
-
};
|
|
599
|
-
if (logs && logs.length > 0) {
|
|
600
|
-
item.logs = logs.map((log) => ({
|
|
601
|
-
timestamp: log.timestamp,
|
|
602
|
-
logger: log.logger,
|
|
603
|
-
level: log.level,
|
|
604
|
-
message: truncateLogMessage(log.message)
|
|
605
|
-
}));
|
|
606
|
-
}
|
|
607
|
-
this.pendingWrites.push(item);
|
|
608
|
-
if (this.pendingWrites.length > MAX_PENDING_WRITES) {
|
|
609
|
-
this.pendingWrites.shift();
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
async writeToFile() {
|
|
613
|
-
if (!this.enabled || this.pendingWrites.length === 0) {
|
|
614
|
-
return;
|
|
615
|
-
}
|
|
616
|
-
return this.lock.acquire("file", async () => {
|
|
617
|
-
if (!this.currentFile) {
|
|
618
|
-
this.currentFile = new TempGzipFile();
|
|
619
|
-
}
|
|
620
|
-
while (this.pendingWrites.length > 0) {
|
|
621
|
-
let item = this.pendingWrites.shift();
|
|
622
|
-
if (item) {
|
|
623
|
-
item = this.applyMasking(item);
|
|
624
|
-
const finalItem = {
|
|
625
|
-
uuid: item.uuid,
|
|
626
|
-
request: skipEmptyValues(item.request),
|
|
627
|
-
response: skipEmptyValues(item.response),
|
|
628
|
-
exception: item.exception,
|
|
629
|
-
logs: item.logs
|
|
630
|
-
};
|
|
631
|
-
[
|
|
632
|
-
finalItem.request.body,
|
|
633
|
-
finalItem.response.body
|
|
634
|
-
].forEach((body) => {
|
|
635
|
-
if (body) {
|
|
636
|
-
body.toJSON = function() {
|
|
637
|
-
return this.toString("base64");
|
|
638
|
-
};
|
|
639
|
-
}
|
|
640
|
-
});
|
|
641
|
-
await this.currentFile.writeLine(Buffer3.from(JSON.stringify(finalItem)));
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
});
|
|
645
|
-
}
|
|
646
|
-
getFile() {
|
|
647
|
-
return this.files.shift();
|
|
648
|
-
}
|
|
649
|
-
retryFileLater(file) {
|
|
650
|
-
this.files.unshift(file);
|
|
651
|
-
}
|
|
652
|
-
async rotateFile() {
|
|
653
|
-
return this.lock.acquire("file", async () => {
|
|
654
|
-
if (this.currentFile) {
|
|
655
|
-
await this.currentFile.close();
|
|
656
|
-
this.files.push(this.currentFile);
|
|
657
|
-
this.currentFile = null;
|
|
658
|
-
}
|
|
659
|
-
});
|
|
660
|
-
}
|
|
661
|
-
async maintain() {
|
|
662
|
-
await this.writeToFile();
|
|
663
|
-
if (this.currentFile && this.currentFile.size > MAX_FILE_SIZE) {
|
|
664
|
-
await this.rotateFile();
|
|
665
|
-
}
|
|
666
|
-
while (this.files.length > MAX_FILES) {
|
|
667
|
-
const file = this.files.shift();
|
|
668
|
-
file == null ? void 0 : file.delete();
|
|
669
|
-
}
|
|
670
|
-
if (this.suspendUntil !== null && this.suspendUntil < Date.now()) {
|
|
671
|
-
this.suspendUntil = null;
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
async clear() {
|
|
675
|
-
this.pendingWrites = [];
|
|
676
|
-
await this.rotateFile();
|
|
677
|
-
this.files.forEach((file) => {
|
|
678
|
-
file.delete();
|
|
679
|
-
});
|
|
680
|
-
this.files = [];
|
|
681
|
-
}
|
|
682
|
-
async close() {
|
|
683
|
-
this.enabled = false;
|
|
684
|
-
await this.clear();
|
|
685
|
-
if (this.maintainIntervalId) {
|
|
686
|
-
clearInterval(this.maintainIntervalId);
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
};
|
|
690
|
-
__name(_RequestLogger, "RequestLogger");
|
|
691
|
-
var RequestLogger = _RequestLogger;
|
|
692
|
-
function matchPatterns(value, patterns) {
|
|
693
|
-
return patterns.some((pattern) => {
|
|
694
|
-
return pattern.test(value);
|
|
695
|
-
});
|
|
696
|
-
}
|
|
697
|
-
__name(matchPatterns, "matchPatterns");
|
|
698
|
-
function skipEmptyValues(data) {
|
|
699
|
-
return Object.fromEntries(Object.entries(data).filter(([_, v]) => {
|
|
700
|
-
if (v == null || Number.isNaN(v)) return false;
|
|
701
|
-
if (Array.isArray(v) || Buffer3.isBuffer(v) || typeof v === "string") {
|
|
702
|
-
return v.length > 0;
|
|
703
|
-
}
|
|
704
|
-
return true;
|
|
705
|
-
}));
|
|
706
|
-
}
|
|
707
|
-
__name(skipEmptyValues, "skipEmptyValues");
|
|
708
|
-
function truncateLogMessage(msg) {
|
|
709
|
-
if (msg.length > MAX_LOG_MSG_LENGTH) {
|
|
710
|
-
const suffix = "... (truncated)";
|
|
711
|
-
return msg.slice(0, MAX_LOG_MSG_LENGTH - suffix.length) + suffix;
|
|
712
|
-
}
|
|
713
|
-
return msg;
|
|
714
|
-
}
|
|
715
|
-
__name(truncateLogMessage, "truncateLogMessage");
|
|
716
|
-
function checkWritableFs() {
|
|
717
|
-
try {
|
|
718
|
-
const testPath = join2(tmpdir2(), `apitally-${randomUUID2()}`);
|
|
719
|
-
writeFileSync(testPath, "test");
|
|
720
|
-
unlinkSync(testPath);
|
|
721
|
-
return true;
|
|
722
|
-
} catch (error) {
|
|
723
|
-
return false;
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
__name(checkWritableFs, "checkWritableFs");
|
|
727
|
-
|
|
728
|
-
// src/common/validationErrorCounter.ts
|
|
729
|
-
import { createHash as createHash2 } from "crypto";
|
|
730
|
-
var _ValidationErrorCounter = class _ValidationErrorCounter {
|
|
731
|
-
errorCounts;
|
|
732
|
-
errorDetails;
|
|
733
|
-
constructor() {
|
|
734
|
-
this.errorCounts = /* @__PURE__ */ new Map();
|
|
735
|
-
this.errorDetails = /* @__PURE__ */ new Map();
|
|
736
|
-
}
|
|
737
|
-
addValidationError(validationError) {
|
|
738
|
-
const key = this.getKey(validationError);
|
|
739
|
-
if (!this.errorDetails.has(key)) {
|
|
740
|
-
this.errorDetails.set(key, validationError);
|
|
741
|
-
}
|
|
742
|
-
this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);
|
|
743
|
-
}
|
|
744
|
-
getAndResetValidationErrors() {
|
|
745
|
-
const data = [];
|
|
746
|
-
this.errorCounts.forEach((count, key) => {
|
|
747
|
-
const validationError = this.errorDetails.get(key);
|
|
748
|
-
if (validationError) {
|
|
749
|
-
data.push({
|
|
750
|
-
consumer: validationError.consumer || null,
|
|
751
|
-
method: validationError.method,
|
|
752
|
-
path: validationError.path,
|
|
753
|
-
loc: validationError.loc.split(".").filter(Boolean),
|
|
754
|
-
msg: validationError.msg,
|
|
755
|
-
type: validationError.type,
|
|
756
|
-
error_count: count
|
|
757
|
-
});
|
|
758
|
-
}
|
|
759
|
-
});
|
|
760
|
-
this.errorCounts.clear();
|
|
761
|
-
this.errorDetails.clear();
|
|
762
|
-
return data;
|
|
763
|
-
}
|
|
764
|
-
getKey(validationError) {
|
|
765
|
-
const hashInput = [
|
|
766
|
-
validationError.consumer || "",
|
|
767
|
-
validationError.method.toUpperCase(),
|
|
768
|
-
validationError.path,
|
|
769
|
-
validationError.loc.split(".").filter(Boolean),
|
|
770
|
-
validationError.msg.trim(),
|
|
771
|
-
validationError.type
|
|
772
|
-
].join("|");
|
|
773
|
-
return createHash2("md5").update(hashInput).digest("hex");
|
|
774
|
-
}
|
|
775
|
-
};
|
|
776
|
-
__name(_ValidationErrorCounter, "ValidationErrorCounter");
|
|
777
|
-
var ValidationErrorCounter = _ValidationErrorCounter;
|
|
778
|
-
|
|
779
|
-
// src/common/client.ts
|
|
780
|
-
var SYNC_INTERVAL = 6e4;
|
|
781
|
-
var INITIAL_SYNC_INTERVAL = 1e4;
|
|
782
|
-
var INITIAL_SYNC_INTERVAL_DURATION = 36e5;
|
|
783
|
-
var MAX_QUEUE_TIME = 36e5;
|
|
784
5
|
var _a;
|
|
785
|
-
|
|
6
|
+
import fetchRetry from "fetch-retry";
|
|
7
|
+
import { randomUUID } from "node:crypto";
|
|
8
|
+
import ConsumerRegistry from "./consumerRegistry.js";
|
|
9
|
+
import { getLogger } from "./logging.js";
|
|
10
|
+
import { isValidClientId, isValidEnv } from "./paramValidation.js";
|
|
11
|
+
import RequestCounter from "./requestCounter.js";
|
|
12
|
+
import RequestLogger from "./requestLogger.js";
|
|
13
|
+
import ServerErrorCounter from "./serverErrorCounter.js";
|
|
14
|
+
import ValidationErrorCounter from "./validationErrorCounter.js";
|
|
15
|
+
const SYNC_INTERVAL = 6e4;
|
|
16
|
+
const INITIAL_SYNC_INTERVAL = 1e4;
|
|
17
|
+
const INITIAL_SYNC_INTERVAL_DURATION = 36e5;
|
|
18
|
+
const MAX_QUEUE_TIME = 36e5;
|
|
19
|
+
let HTTPError = (_a = class extends Error {
|
|
786
20
|
response;
|
|
787
21
|
constructor(response) {
|
|
788
22
|
const reason = response.status ? `status code ${response.status}` : "an unknown error";
|
|
@@ -790,7 +24,7 @@ var HTTPError = (_a = class extends Error {
|
|
|
790
24
|
this.response = response;
|
|
791
25
|
}
|
|
792
26
|
}, __name(_a, "HTTPError"), _a);
|
|
793
|
-
|
|
27
|
+
const _ApitallyClient = class _ApitallyClient {
|
|
794
28
|
clientId;
|
|
795
29
|
env;
|
|
796
30
|
instanceUuid;
|
|
@@ -809,11 +43,14 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
809
43
|
if (_ApitallyClient.instance) {
|
|
810
44
|
throw new Error("Apitally client is already initialized");
|
|
811
45
|
}
|
|
46
|
+
this.logger = logger ?? getLogger();
|
|
812
47
|
if (!isValidClientId(clientId)) {
|
|
813
|
-
|
|
48
|
+
this.logger.error(`Invalid Apitally client ID '${clientId}' (expecting hexadecimal UUID format)`);
|
|
49
|
+
this.enabled = false;
|
|
814
50
|
}
|
|
815
51
|
if (!isValidEnv(env)) {
|
|
816
|
-
|
|
52
|
+
this.logger.error(`Invalid Apitally env '${env}' (expecting 1-32 alphanumeric characters and hyphens only)`);
|
|
53
|
+
this.enabled = false;
|
|
817
54
|
}
|
|
818
55
|
if (requestLoggingConfig && !requestLogging) {
|
|
819
56
|
console.warn("requestLoggingConfig is deprecated, use requestLogging instead.");
|
|
@@ -821,15 +58,13 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
821
58
|
_ApitallyClient.instance = this;
|
|
822
59
|
this.clientId = clientId;
|
|
823
60
|
this.env = env;
|
|
824
|
-
this.instanceUuid =
|
|
61
|
+
this.instanceUuid = randomUUID();
|
|
825
62
|
this.syncDataQueue = [];
|
|
826
63
|
this.requestCounter = new RequestCounter();
|
|
827
64
|
this.requestLogger = new RequestLogger(requestLogging ?? requestLoggingConfig);
|
|
828
65
|
this.validationErrorCounter = new ValidationErrorCounter();
|
|
829
66
|
this.serverErrorCounter = new ServerErrorCounter();
|
|
830
67
|
this.consumerRegistry = new ConsumerRegistry();
|
|
831
|
-
this.logger = logger ?? getLogger();
|
|
832
|
-
this.startSync();
|
|
833
68
|
this.handleShutdown = this.handleShutdown.bind(this);
|
|
834
69
|
}
|
|
835
70
|
static getInstance() {
|
|
@@ -884,15 +119,20 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
884
119
|
}
|
|
885
120
|
}
|
|
886
121
|
startSync() {
|
|
122
|
+
if (!this.enabled) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
887
125
|
this.sync();
|
|
888
126
|
this.syncIntervalId = setInterval(() => {
|
|
889
127
|
this.sync();
|
|
890
128
|
}, INITIAL_SYNC_INTERVAL);
|
|
891
129
|
setTimeout(() => {
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
this.
|
|
895
|
-
|
|
130
|
+
if (this.syncIntervalId) {
|
|
131
|
+
clearInterval(this.syncIntervalId);
|
|
132
|
+
this.syncIntervalId = setInterval(() => {
|
|
133
|
+
this.sync();
|
|
134
|
+
}, SYNC_INTERVAL);
|
|
135
|
+
}
|
|
896
136
|
}, INITIAL_SYNC_INTERVAL_DURATION);
|
|
897
137
|
}
|
|
898
138
|
async sync() {
|
|
@@ -920,14 +160,13 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
920
160
|
setStartupData(data) {
|
|
921
161
|
this.startupData = data;
|
|
922
162
|
this.startupDataSent = false;
|
|
923
|
-
this.sendStartupData();
|
|
924
163
|
}
|
|
925
164
|
async sendStartupData() {
|
|
926
165
|
if (this.startupData) {
|
|
927
166
|
this.logger.debug("Sending startup data to Apitally Hub");
|
|
928
167
|
const payload = {
|
|
929
168
|
instance_uuid: this.instanceUuid,
|
|
930
|
-
message_uuid:
|
|
169
|
+
message_uuid: randomUUID(),
|
|
931
170
|
...this.startupData
|
|
932
171
|
};
|
|
933
172
|
try {
|
|
@@ -949,7 +188,7 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
949
188
|
const newPayload = {
|
|
950
189
|
timestamp: Date.now() / 1e3,
|
|
951
190
|
instance_uuid: this.instanceUuid,
|
|
952
|
-
message_uuid:
|
|
191
|
+
message_uuid: randomUUID(),
|
|
953
192
|
requests: this.requestCounter.getAndResetRequests(),
|
|
954
193
|
validation_errors: this.validationErrorCounter.getAndResetValidationErrors(),
|
|
955
194
|
server_errors: this.serverErrorCounter.getAndResetServerErrors(),
|
|
@@ -1049,7 +288,7 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
1049
288
|
};
|
|
1050
289
|
__name(_ApitallyClient, "ApitallyClient");
|
|
1051
290
|
__publicField(_ApitallyClient, "instance");
|
|
1052
|
-
|
|
291
|
+
let ApitallyClient = _ApitallyClient;
|
|
1053
292
|
export {
|
|
1054
293
|
ApitallyClient
|
|
1055
294
|
};
|