hobots 0.3.0 → 1.0.0
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 +21 -0
- package/README.md +346 -0
- package/dist/chunk-FW32OR7V.js +75 -0
- package/dist/chunk-FW32OR7V.js.map +1 -0
- package/dist/index.cjs +764 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +187 -0
- package/dist/index.d.ts +187 -0
- package/dist/index.js +691 -0
- package/dist/index.js.map +1 -0
- package/dist/manager/protocol.cjs +19 -0
- package/dist/manager/protocol.cjs.map +1 -0
- package/dist/manager/protocol.d.cts +72 -0
- package/dist/manager/protocol.d.ts +72 -0
- package/dist/manager/protocol.js +1 -0
- package/dist/manager/protocol.js.map +1 -0
- package/dist/manager.cjs +519 -0
- package/dist/manager.cjs.map +1 -0
- package/dist/manager.d.cts +118 -0
- package/dist/manager.d.ts +118 -0
- package/dist/manager.js +464 -0
- package/dist/manager.js.map +1 -0
- package/dist/protocol.cjs +19 -0
- package/dist/protocol.cjs.map +1 -0
- package/dist/protocol.d.cts +126 -0
- package/dist/protocol.d.ts +126 -0
- package/dist/protocol.js +1 -0
- package/dist/protocol.js.map +1 -0
- package/dist/utils-LReLqjzN.d.cts +7 -0
- package/dist/utils-LReLqjzN.d.ts +7 -0
- package/docs/README.md +39 -0
- package/docs/api-reference.md +140 -0
- package/docs/getting-started.md +88 -0
- package/docs/manager.md +90 -0
- package/docs/monitor.md +136 -0
- package/docs/protocol.md +87 -0
- package/package.json +50 -2
- package/auth/index.d.ts +0 -10
- package/csv/index.d.ts +0 -9
- package/datasets/index.d.ts +0 -2
- package/db/drizzle.config.d.ts +0 -8
- package/db/index.d.ts +0 -9
- package/db/migrate.d.ts +0 -3
- package/db/schema.d.ts +0 -215
- package/db/storages/base.d.ts +0 -23
- package/db/storages/index.d.ts +0 -3
- package/db/storages/job.d.ts +0 -233
- package/exceptions/break.d.ts +0 -6
- package/exceptions/ignore.d.ts +0 -6
- package/exceptions/index.d.ts +0 -4
- package/exceptions/warning.d.ts +0 -6
- package/foreach/foreach.d.ts +0 -7
- package/foreach/index.d.ts +0 -5
- package/foreach/item.d.ts +0 -13
- package/hobots/samples/bot.d.ts +0 -2
- package/hobots/samples/index.d.ts +0 -2
- package/hobots/src/auth/index.d.ts +0 -10
- package/hobots/src/csv/index.d.ts +0 -9
- package/hobots/src/datasets/index.d.ts +0 -2
- package/hobots/src/db/drizzle.config.d.ts +0 -8
- package/hobots/src/db/index.d.ts +0 -9
- package/hobots/src/db/migrate.d.ts +0 -3
- package/hobots/src/db/schema.d.ts +0 -215
- package/hobots/src/db/storages/base.d.ts +0 -23
- package/hobots/src/db/storages/index.d.ts +0 -3
- package/hobots/src/db/storages/job.d.ts +0 -233
- package/hobots/src/exceptions/break.d.ts +0 -6
- package/hobots/src/exceptions/ignore.d.ts +0 -6
- package/hobots/src/exceptions/index.d.ts +0 -4
- package/hobots/src/exceptions/warning.d.ts +0 -6
- package/hobots/src/foreach/foreach.d.ts +0 -7
- package/hobots/src/foreach/index.d.ts +0 -5
- package/hobots/src/foreach/item.d.ts +0 -13
- package/hobots/src/index.d.ts +0 -9
- package/hobots/src/reports/data-report.d.ts +0 -9
- package/hobots/src/reports/index.d.ts +0 -3
- package/hobots/src/reports/job-report.d.ts +0 -22
- package/hobots/src/setup.d.ts +0 -20
- package/hobots/src/sheets/index.d.ts +0 -13
- package/hobots/src/types/hobots-types.d.ts +0 -20
- package/hobots/src/utils/date.d.ts +0 -117
- package/hobots/src/utils/dist.d.ts +0 -8
- package/hobots/src/utils/garbage.d.ts +0 -2
- package/hobots/src/utils/index.d.ts +0 -10
- package/hobots/src/utils/logger.d.ts +0 -21
- package/hobots/src/utils/manifest.d.ts +0 -2
- package/hobots/src/utils/path.d.ts +0 -13
- package/hobots/src/utils/publish.d.ts +0 -2
- package/hobots/src/utils/retry.d.ts +0 -5
- package/hobots/src/utils/text.d.ts +0 -74
- package/hobots/src/utils/timer.d.ts +0 -3
- package/index.d.ts +0 -9
- package/index.js +0 -131866
- package/index.js.map +0 -1
- package/reports/data-report.d.ts +0 -9
- package/reports/index.d.ts +0 -3
- package/reports/job-report.d.ts +0 -22
- package/setup.d.ts +0 -20
- package/sheets/index.d.ts +0 -13
- package/types/hobots-types.d.ts +0 -20
- package/utils/date.d.ts +0 -117
- package/utils/dist.d.ts +0 -8
- package/utils/garbage.d.ts +0 -2
- package/utils/index.d.ts +0 -10
- package/utils/logger.d.ts +0 -21
- package/utils/manifest.d.ts +0 -2
- package/utils/path.d.ts +0 -13
- package/utils/publish.d.ts +0 -2
- package/utils/retry.d.ts +0 -5
- package/utils/src/path.d.ts +0 -14
- package/utils/text.d.ts +0 -74
- package/utils/timer.d.ts +0 -3
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,764 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
Client: () => Client,
|
|
24
|
+
Scope: () => Scope,
|
|
25
|
+
Span: () => Span,
|
|
26
|
+
Transaction: () => Transaction,
|
|
27
|
+
addBreadcrumb: () => addBreadcrumb,
|
|
28
|
+
captureException: () => captureException,
|
|
29
|
+
captureMessage: () => captureMessage,
|
|
30
|
+
checkIn: () => checkIn,
|
|
31
|
+
close: () => close,
|
|
32
|
+
flush: () => flush,
|
|
33
|
+
getClient: () => getClient,
|
|
34
|
+
init: () => init,
|
|
35
|
+
parseDsn: () => parseDsn,
|
|
36
|
+
setContext: () => setContext,
|
|
37
|
+
setExtra: () => setExtra,
|
|
38
|
+
setTag: () => setTag,
|
|
39
|
+
setTags: () => setTags,
|
|
40
|
+
setUser: () => setUser,
|
|
41
|
+
startTransaction: () => startTransaction,
|
|
42
|
+
withMonitor: () => withMonitor,
|
|
43
|
+
withScope: () => withScope
|
|
44
|
+
});
|
|
45
|
+
module.exports = __toCommonJS(src_exports);
|
|
46
|
+
|
|
47
|
+
// src/dsn.ts
|
|
48
|
+
function parseDsnUrl(dsn, prefix) {
|
|
49
|
+
let url;
|
|
50
|
+
try {
|
|
51
|
+
url = new URL(dsn);
|
|
52
|
+
} catch {
|
|
53
|
+
throw new Error(`${prefix} DSN inv\xE1lido: "${dsn}"`);
|
|
54
|
+
}
|
|
55
|
+
const key = url.username;
|
|
56
|
+
const path = url.pathname.replace(/^\/+/, "");
|
|
57
|
+
if (!key || !path) {
|
|
58
|
+
throw new Error(`${prefix} DSN inv\xE1lido: "${dsn}" \u2014 esperado https://<key>@host/<projeto>`);
|
|
59
|
+
}
|
|
60
|
+
return { key, path, origin: `${url.protocol}//${url.host}` };
|
|
61
|
+
}
|
|
62
|
+
function parseDsn(dsn) {
|
|
63
|
+
const { key, path, origin } = parseDsnUrl(dsn, "[hobots-monitor]");
|
|
64
|
+
return {
|
|
65
|
+
publicKey: key,
|
|
66
|
+
projectId: path,
|
|
67
|
+
endpoint: `${origin}/api/ingest/${key}`
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/stacktrace.ts
|
|
72
|
+
var MAX_FRAMES = 50;
|
|
73
|
+
var FRAME_RE = /^\s*at\s+(?:async\s+)?(?:(.+?)\s+\()?(.+?)\)?$/;
|
|
74
|
+
var LOCATION_RE = /^(.*?):(\d+):(\d+)$/;
|
|
75
|
+
function isInApp(filename) {
|
|
76
|
+
if (!filename) return false;
|
|
77
|
+
if (filename.startsWith("node:")) return false;
|
|
78
|
+
if (filename.startsWith("internal/")) return false;
|
|
79
|
+
if (filename.includes("node_modules")) return false;
|
|
80
|
+
if (filename === "<anonymous>") return false;
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
function parseStacktrace(stack) {
|
|
84
|
+
if (!stack) return [];
|
|
85
|
+
const frames = [];
|
|
86
|
+
for (const line of stack.split("\n")) {
|
|
87
|
+
if (frames.length >= MAX_FRAMES) break;
|
|
88
|
+
const match = FRAME_RE.exec(line);
|
|
89
|
+
if (!match || !line.trimStart().startsWith("at ")) continue;
|
|
90
|
+
const [, fn, location] = match;
|
|
91
|
+
const loc = LOCATION_RE.exec(location ?? "");
|
|
92
|
+
const filename = loc ? loc[1] : location;
|
|
93
|
+
frames.push({
|
|
94
|
+
function: fn || "<anonymous>",
|
|
95
|
+
filename: filename || void 0,
|
|
96
|
+
lineno: loc?.[2] ? Number(loc[2]) : void 0,
|
|
97
|
+
colno: loc?.[3] ? Number(loc[3]) : void 0,
|
|
98
|
+
in_app: isInApp(filename)
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return frames;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/utils.ts
|
|
105
|
+
var SDK_NAME = "hobots";
|
|
106
|
+
var SDK_VERSION = "1.0.0";
|
|
107
|
+
function isNode() {
|
|
108
|
+
return typeof process !== "undefined" && typeof process.versions?.node === "string";
|
|
109
|
+
}
|
|
110
|
+
function uuid4() {
|
|
111
|
+
const cryptoRef = globalThis.crypto;
|
|
112
|
+
if (cryptoRef && typeof cryptoRef.randomUUID === "function") {
|
|
113
|
+
return cryptoRef.randomUUID().replace(/-/g, "");
|
|
114
|
+
}
|
|
115
|
+
let out = "";
|
|
116
|
+
for (let i = 0; i < 32; i++) {
|
|
117
|
+
out += Math.floor(Math.random() * 16).toString(16);
|
|
118
|
+
}
|
|
119
|
+
return out;
|
|
120
|
+
}
|
|
121
|
+
function nowISO() {
|
|
122
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
123
|
+
}
|
|
124
|
+
function unrefTimer(timer) {
|
|
125
|
+
timer?.unref?.();
|
|
126
|
+
}
|
|
127
|
+
function sleep(ms) {
|
|
128
|
+
return new Promise((resolve) => {
|
|
129
|
+
const timer = setTimeout(resolve, ms);
|
|
130
|
+
unrefTimer(timer);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
var PREFIX = "[hobots-monitor]";
|
|
134
|
+
function makeLogger(enabled, prefix = PREFIX) {
|
|
135
|
+
return {
|
|
136
|
+
debug: (...args) => enabled && console.debug(prefix, ...args),
|
|
137
|
+
warn: (...args) => enabled && console.warn(prefix, ...args),
|
|
138
|
+
error: (...args) => console.error(prefix, ...args)
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/eventbuilder.ts
|
|
143
|
+
function safeString(value) {
|
|
144
|
+
if (typeof value === "string") return value;
|
|
145
|
+
try {
|
|
146
|
+
const json = JSON.stringify(value);
|
|
147
|
+
if (json && json !== "{}") return json;
|
|
148
|
+
} catch {
|
|
149
|
+
}
|
|
150
|
+
return String(value);
|
|
151
|
+
}
|
|
152
|
+
function eventFromException(error, level = "error") {
|
|
153
|
+
let type;
|
|
154
|
+
let value;
|
|
155
|
+
let frames = [];
|
|
156
|
+
if (error instanceof Error) {
|
|
157
|
+
type = error.name || "Error";
|
|
158
|
+
value = error.message;
|
|
159
|
+
frames = parseStacktrace(error.stack);
|
|
160
|
+
} else {
|
|
161
|
+
type = "NonError";
|
|
162
|
+
value = safeString(error);
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
event_id: uuid4(),
|
|
166
|
+
timestamp: nowISO(),
|
|
167
|
+
level,
|
|
168
|
+
exception: {
|
|
169
|
+
type,
|
|
170
|
+
value,
|
|
171
|
+
...frames.length > 0 ? { stacktrace: { frames } } : {}
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function eventFromMessage(message, level = "info") {
|
|
176
|
+
return {
|
|
177
|
+
event_id: uuid4(),
|
|
178
|
+
timestamp: nowISO(),
|
|
179
|
+
level,
|
|
180
|
+
message
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// src/transport.ts
|
|
185
|
+
var RETRY_DELAYS_MS = [1e3, 4e3, 16e3];
|
|
186
|
+
var DEFAULT_FLUSH_INTERVAL_MS = 2e3;
|
|
187
|
+
var DEFAULT_MAX_BATCH_SIZE = 10;
|
|
188
|
+
var DEFAULT_MAX_QUEUE_SIZE = 200;
|
|
189
|
+
var Transport = class {
|
|
190
|
+
endpoint;
|
|
191
|
+
logger;
|
|
192
|
+
flushIntervalMs;
|
|
193
|
+
maxBatchSize;
|
|
194
|
+
maxQueueSize;
|
|
195
|
+
buffer = [];
|
|
196
|
+
timer;
|
|
197
|
+
pending = /* @__PURE__ */ new Set();
|
|
198
|
+
closed = false;
|
|
199
|
+
constructor(options) {
|
|
200
|
+
this.endpoint = options.endpoint;
|
|
201
|
+
this.logger = options.logger;
|
|
202
|
+
this.flushIntervalMs = options.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;
|
|
203
|
+
this.maxBatchSize = options.maxBatchSize ?? DEFAULT_MAX_BATCH_SIZE;
|
|
204
|
+
this.maxQueueSize = options.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE;
|
|
205
|
+
}
|
|
206
|
+
enqueue(item) {
|
|
207
|
+
if (this.closed) {
|
|
208
|
+
this.logger.warn("transport fechado, item descartado:", item.type);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (this.buffer.length >= this.maxQueueSize) {
|
|
212
|
+
this.buffer.shift();
|
|
213
|
+
this.logger.warn("fila cheia, item mais antigo descartado");
|
|
214
|
+
}
|
|
215
|
+
this.buffer.push(item);
|
|
216
|
+
if (this.buffer.length >= this.maxBatchSize) {
|
|
217
|
+
void this.flushBuffer();
|
|
218
|
+
} else {
|
|
219
|
+
this.schedule();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
schedule() {
|
|
223
|
+
if (this.timer) return;
|
|
224
|
+
this.timer = setTimeout(() => {
|
|
225
|
+
this.timer = void 0;
|
|
226
|
+
void this.flushBuffer();
|
|
227
|
+
}, this.flushIntervalMs);
|
|
228
|
+
unrefTimer(this.timer);
|
|
229
|
+
}
|
|
230
|
+
flushBuffer() {
|
|
231
|
+
if (this.timer) {
|
|
232
|
+
clearTimeout(this.timer);
|
|
233
|
+
this.timer = void 0;
|
|
234
|
+
}
|
|
235
|
+
if (this.buffer.length === 0) return Promise.resolve();
|
|
236
|
+
const items = this.buffer.splice(0, this.buffer.length);
|
|
237
|
+
const envelope = {
|
|
238
|
+
sdk: { name: SDK_NAME, version: SDK_VERSION },
|
|
239
|
+
sent_at: nowISO(),
|
|
240
|
+
items
|
|
241
|
+
};
|
|
242
|
+
const request = this.sendWithRetry(envelope).finally(() => {
|
|
243
|
+
this.pending.delete(request);
|
|
244
|
+
});
|
|
245
|
+
this.pending.add(request);
|
|
246
|
+
return request;
|
|
247
|
+
}
|
|
248
|
+
async sendWithRetry(envelope) {
|
|
249
|
+
for (let attempt = 0; ; attempt++) {
|
|
250
|
+
try {
|
|
251
|
+
const response = await fetch(this.endpoint, {
|
|
252
|
+
method: "POST",
|
|
253
|
+
headers: { "content-type": "application/json" },
|
|
254
|
+
body: JSON.stringify(envelope)
|
|
255
|
+
});
|
|
256
|
+
if (response.ok) {
|
|
257
|
+
this.logger.debug(`envelope enviado (${envelope.items.length} itens)`);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (response.status >= 400 && response.status < 500 && response.status !== 429) {
|
|
261
|
+
this.logger.error(`envelope rejeitado (HTTP ${response.status}), descartado`);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
throw new Error(`HTTP ${response.status}`);
|
|
265
|
+
} catch (error) {
|
|
266
|
+
const delay = RETRY_DELAYS_MS[attempt];
|
|
267
|
+
if (delay === void 0) {
|
|
268
|
+
this.logger.error("envelope descartado ap\xF3s retries:", error);
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
this.logger.warn(`falha no envio (${String(error)}), retry em ${delay}ms`);
|
|
272
|
+
await sleep(delay);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/** Envia o que estiver na fila e aguarda envios em andamento (até timeoutMs). */
|
|
277
|
+
async flush(timeoutMs = 5e3) {
|
|
278
|
+
void this.flushBuffer();
|
|
279
|
+
const all = Promise.allSettled([...this.pending]).then(() => true);
|
|
280
|
+
return Promise.race([all, sleep(timeoutMs).then(() => false)]);
|
|
281
|
+
}
|
|
282
|
+
async close(timeoutMs = 5e3) {
|
|
283
|
+
const result = await this.flush(timeoutMs);
|
|
284
|
+
this.closed = true;
|
|
285
|
+
return result;
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// src/client.ts
|
|
290
|
+
function runtimeContexts() {
|
|
291
|
+
if (isNode()) {
|
|
292
|
+
return {
|
|
293
|
+
runtime: { name: "node", version: process.version },
|
|
294
|
+
os: { name: process.platform, arch: process.arch }
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
return { runtime: { name: "browser" } };
|
|
298
|
+
}
|
|
299
|
+
var Client = class {
|
|
300
|
+
options;
|
|
301
|
+
dsn;
|
|
302
|
+
logger;
|
|
303
|
+
transport;
|
|
304
|
+
constructor(options) {
|
|
305
|
+
this.options = options;
|
|
306
|
+
this.logger = makeLogger(!!options.debug);
|
|
307
|
+
this.dsn = parseDsn(options.dsn);
|
|
308
|
+
this.transport = new Transport({
|
|
309
|
+
endpoint: this.dsn.endpoint,
|
|
310
|
+
logger: this.logger,
|
|
311
|
+
flushIntervalMs: options.flushIntervalMs,
|
|
312
|
+
maxBatchSize: options.maxBatchSize
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
captureException(error, hint, scope2) {
|
|
316
|
+
return this.captureEvent(eventFromException(error, hint?.level ?? "error"), hint, scope2);
|
|
317
|
+
}
|
|
318
|
+
captureMessage(message, level, hint, scope2) {
|
|
319
|
+
return this.captureEvent(eventFromMessage(message, level), hint, scope2);
|
|
320
|
+
}
|
|
321
|
+
captureEvent(event, hint, scope2) {
|
|
322
|
+
const sampleRate = this.options.sampleRate ?? 1;
|
|
323
|
+
if (sampleRate < 1 && Math.random() >= sampleRate) {
|
|
324
|
+
this.logger.debug("evento descartado por sampleRate");
|
|
325
|
+
return event.event_id;
|
|
326
|
+
}
|
|
327
|
+
const prepared = this.prepareEvent(event, hint, scope2);
|
|
328
|
+
const final = this.options.beforeSend ? this.options.beforeSend(prepared) : prepared;
|
|
329
|
+
if (!final) {
|
|
330
|
+
this.logger.debug("evento descartado por beforeSend");
|
|
331
|
+
return event.event_id;
|
|
332
|
+
}
|
|
333
|
+
this.transport.enqueue({ type: "event", payload: final });
|
|
334
|
+
return final.event_id;
|
|
335
|
+
}
|
|
336
|
+
prepareEvent(event, hint, scope2) {
|
|
337
|
+
const tags = { ...this.options.tags, ...scope2.tags, ...event.tags, ...hint?.tags };
|
|
338
|
+
const extra = { ...scope2.extra, ...event.extra, ...hint?.extra };
|
|
339
|
+
return {
|
|
340
|
+
...event,
|
|
341
|
+
level: hint?.level ?? event.level ?? scope2.level ?? "error",
|
|
342
|
+
release: event.release ?? this.options.release,
|
|
343
|
+
environment: event.environment ?? this.options.environment ?? "production",
|
|
344
|
+
server_name: event.server_name ?? this.options.serverName,
|
|
345
|
+
tags: Object.keys(tags).length > 0 ? tags : void 0,
|
|
346
|
+
extra: Object.keys(extra).length > 0 ? extra : void 0,
|
|
347
|
+
user: event.user ?? scope2.user,
|
|
348
|
+
contexts: { ...runtimeContexts(), ...scope2.contexts, ...event.contexts },
|
|
349
|
+
breadcrumbs: scope2.breadcrumbs.length > 0 ? [...scope2.breadcrumbs] : event.breadcrumbs,
|
|
350
|
+
fingerprint: hint?.fingerprint ?? event.fingerprint ?? scope2.fingerprint
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
sendTransaction(payload) {
|
|
354
|
+
this.transport.enqueue({
|
|
355
|
+
type: "transaction",
|
|
356
|
+
payload: {
|
|
357
|
+
...payload,
|
|
358
|
+
release: payload.release ?? this.options.release,
|
|
359
|
+
environment: payload.environment ?? this.options.environment ?? "production",
|
|
360
|
+
server_name: payload.server_name ?? this.options.serverName,
|
|
361
|
+
tags: { ...this.options.tags, ...payload.tags }
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
sendCheckIn(payload) {
|
|
366
|
+
this.transport.enqueue({
|
|
367
|
+
type: "check_in",
|
|
368
|
+
payload: {
|
|
369
|
+
...payload,
|
|
370
|
+
environment: payload.environment ?? this.options.environment ?? "production"
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
sendHeartbeat(payload) {
|
|
375
|
+
this.transport.enqueue({ type: "heartbeat", payload });
|
|
376
|
+
}
|
|
377
|
+
flush(timeoutMs) {
|
|
378
|
+
return this.transport.flush(timeoutMs);
|
|
379
|
+
}
|
|
380
|
+
close(timeoutMs) {
|
|
381
|
+
return this.transport.close(timeoutMs);
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
// src/heartbeat.ts
|
|
386
|
+
var DEFAULT_INTERVAL_MS = 3e4;
|
|
387
|
+
function defaultInstanceId() {
|
|
388
|
+
if (isNode()) {
|
|
389
|
+
const host = process.env.HOSTNAME || process.env.COMPUTERNAME;
|
|
390
|
+
if (host) return host;
|
|
391
|
+
}
|
|
392
|
+
return `instance-${uuid4().slice(0, 8)}`;
|
|
393
|
+
}
|
|
394
|
+
var Heartbeat = class {
|
|
395
|
+
constructor(client2, options = {}, serverName) {
|
|
396
|
+
this.client = client2;
|
|
397
|
+
this.intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;
|
|
398
|
+
this.instanceId = options.instanceId ?? serverName ?? defaultInstanceId();
|
|
399
|
+
this.name = options.name ?? this.instanceId;
|
|
400
|
+
this.metadata = options.metadata;
|
|
401
|
+
}
|
|
402
|
+
intervalMs;
|
|
403
|
+
instanceId;
|
|
404
|
+
name;
|
|
405
|
+
metadata;
|
|
406
|
+
timer;
|
|
407
|
+
start() {
|
|
408
|
+
if (this.timer) return;
|
|
409
|
+
this.beat();
|
|
410
|
+
this.timer = setInterval(() => this.beat(), this.intervalMs);
|
|
411
|
+
unrefTimer(this.timer);
|
|
412
|
+
}
|
|
413
|
+
stop() {
|
|
414
|
+
if (this.timer) {
|
|
415
|
+
clearInterval(this.timer);
|
|
416
|
+
this.timer = void 0;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
beat() {
|
|
420
|
+
this.client.sendHeartbeat({
|
|
421
|
+
instance_id: this.instanceId,
|
|
422
|
+
name: this.name,
|
|
423
|
+
interval_ms: this.intervalMs,
|
|
424
|
+
timestamp: nowISO(),
|
|
425
|
+
metadata: this.metadata
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
// src/instrument.ts
|
|
431
|
+
var installed = false;
|
|
432
|
+
function installGlobalHandlers(client2, getScope) {
|
|
433
|
+
if (installed) return;
|
|
434
|
+
installed = true;
|
|
435
|
+
if (isNode()) {
|
|
436
|
+
process.on("uncaughtException", (error) => {
|
|
437
|
+
client2.captureException(error, { level: "fatal", tags: { mechanism: "uncaughtException" } }, getScope());
|
|
438
|
+
void client2.flush(2e3).then(() => {
|
|
439
|
+
if (process.listenerCount("uncaughtException") <= 1) {
|
|
440
|
+
console.error(error);
|
|
441
|
+
process.exit(1);
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
});
|
|
445
|
+
process.on("unhandledRejection", (reason) => {
|
|
446
|
+
client2.captureException(reason, { level: "error", tags: { mechanism: "unhandledRejection" } }, getScope());
|
|
447
|
+
void client2.flush(2e3);
|
|
448
|
+
});
|
|
449
|
+
process.on("beforeExit", () => {
|
|
450
|
+
void client2.flush(2e3);
|
|
451
|
+
});
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
if (typeof window !== "undefined") {
|
|
455
|
+
window.addEventListener("error", (event) => {
|
|
456
|
+
client2.captureException(event.error ?? event.message, { tags: { mechanism: "onerror" } }, getScope());
|
|
457
|
+
});
|
|
458
|
+
window.addEventListener("unhandledrejection", (event) => {
|
|
459
|
+
client2.captureException(event.reason, { tags: { mechanism: "onunhandledrejection" } }, getScope());
|
|
460
|
+
});
|
|
461
|
+
window.addEventListener("pagehide", () => {
|
|
462
|
+
void client2.flush(1e3);
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// src/scope.ts
|
|
468
|
+
var Scope = class _Scope {
|
|
469
|
+
tags = {};
|
|
470
|
+
user;
|
|
471
|
+
contexts = {};
|
|
472
|
+
extra = {};
|
|
473
|
+
level;
|
|
474
|
+
fingerprint;
|
|
475
|
+
breadcrumbs = [];
|
|
476
|
+
setTag(key, value) {
|
|
477
|
+
this.tags[key] = value;
|
|
478
|
+
return this;
|
|
479
|
+
}
|
|
480
|
+
setTags(tags) {
|
|
481
|
+
Object.assign(this.tags, tags);
|
|
482
|
+
return this;
|
|
483
|
+
}
|
|
484
|
+
setUser(user) {
|
|
485
|
+
this.user = user ?? void 0;
|
|
486
|
+
return this;
|
|
487
|
+
}
|
|
488
|
+
setContext(name, context) {
|
|
489
|
+
if (context === null) {
|
|
490
|
+
delete this.contexts[name];
|
|
491
|
+
} else {
|
|
492
|
+
this.contexts[name] = context;
|
|
493
|
+
}
|
|
494
|
+
return this;
|
|
495
|
+
}
|
|
496
|
+
setExtra(key, value) {
|
|
497
|
+
this.extra[key] = value;
|
|
498
|
+
return this;
|
|
499
|
+
}
|
|
500
|
+
setExtras(extras) {
|
|
501
|
+
Object.assign(this.extra, extras);
|
|
502
|
+
return this;
|
|
503
|
+
}
|
|
504
|
+
setLevel(level) {
|
|
505
|
+
this.level = level;
|
|
506
|
+
return this;
|
|
507
|
+
}
|
|
508
|
+
setFingerprint(fingerprint) {
|
|
509
|
+
this.fingerprint = fingerprint;
|
|
510
|
+
return this;
|
|
511
|
+
}
|
|
512
|
+
addBreadcrumb(crumb, maxBreadcrumbs) {
|
|
513
|
+
this.breadcrumbs.push({ timestamp: nowISO(), ...crumb });
|
|
514
|
+
if (this.breadcrumbs.length > maxBreadcrumbs) {
|
|
515
|
+
this.breadcrumbs.splice(0, this.breadcrumbs.length - maxBreadcrumbs);
|
|
516
|
+
}
|
|
517
|
+
return this;
|
|
518
|
+
}
|
|
519
|
+
clearBreadcrumbs() {
|
|
520
|
+
this.breadcrumbs = [];
|
|
521
|
+
return this;
|
|
522
|
+
}
|
|
523
|
+
clone() {
|
|
524
|
+
const next = new _Scope();
|
|
525
|
+
next.tags = { ...this.tags };
|
|
526
|
+
next.user = this.user ? { ...this.user } : void 0;
|
|
527
|
+
next.contexts = Object.fromEntries(Object.entries(this.contexts).map(([k, v]) => [k, { ...v }]));
|
|
528
|
+
next.extra = { ...this.extra };
|
|
529
|
+
next.level = this.level;
|
|
530
|
+
next.fingerprint = this.fingerprint ? [...this.fingerprint] : void 0;
|
|
531
|
+
next.breadcrumbs = [...this.breadcrumbs];
|
|
532
|
+
return next;
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
// src/transaction.ts
|
|
537
|
+
function spanId() {
|
|
538
|
+
return uuid4().slice(0, 16);
|
|
539
|
+
}
|
|
540
|
+
var Span = class {
|
|
541
|
+
constructor(transaction, parentSpanId, op, description) {
|
|
542
|
+
this.transaction = transaction;
|
|
543
|
+
this.parentSpanId = parentSpanId;
|
|
544
|
+
this.op = op;
|
|
545
|
+
this.description = description;
|
|
546
|
+
}
|
|
547
|
+
spanId = spanId();
|
|
548
|
+
startTimestamp = nowISO();
|
|
549
|
+
status = "ok";
|
|
550
|
+
endTimestamp;
|
|
551
|
+
data;
|
|
552
|
+
setStatus(status) {
|
|
553
|
+
this.status = status;
|
|
554
|
+
return this;
|
|
555
|
+
}
|
|
556
|
+
setData(key, value) {
|
|
557
|
+
this.data = { ...this.data, [key]: value };
|
|
558
|
+
return this;
|
|
559
|
+
}
|
|
560
|
+
/** Span aninhado (filho deste span). */
|
|
561
|
+
startChild(op, description) {
|
|
562
|
+
return this.transaction.createSpan(this.spanId, op, description);
|
|
563
|
+
}
|
|
564
|
+
finish() {
|
|
565
|
+
if (!this.endTimestamp) this.endTimestamp = nowISO();
|
|
566
|
+
}
|
|
567
|
+
toJSON() {
|
|
568
|
+
return {
|
|
569
|
+
span_id: this.spanId,
|
|
570
|
+
parent_span_id: this.parentSpanId,
|
|
571
|
+
op: this.op,
|
|
572
|
+
description: this.description,
|
|
573
|
+
status: this.status,
|
|
574
|
+
start_timestamp: this.startTimestamp,
|
|
575
|
+
timestamp: this.endTimestamp ?? nowISO(),
|
|
576
|
+
data: this.data
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
var Transaction = class {
|
|
581
|
+
constructor(client2, name, op, sampled = true) {
|
|
582
|
+
this.client = client2;
|
|
583
|
+
this.name = name;
|
|
584
|
+
this.op = op;
|
|
585
|
+
this.sampled = sampled;
|
|
586
|
+
}
|
|
587
|
+
eventId = uuid4();
|
|
588
|
+
spanId = spanId();
|
|
589
|
+
startTimestamp = nowISO();
|
|
590
|
+
status = "ok";
|
|
591
|
+
spans = [];
|
|
592
|
+
tags = {};
|
|
593
|
+
finished = false;
|
|
594
|
+
createSpan(parentSpanId, op, description) {
|
|
595
|
+
const span = new Span(this, parentSpanId, op, description);
|
|
596
|
+
this.spans.push(span);
|
|
597
|
+
return span;
|
|
598
|
+
}
|
|
599
|
+
/** Span direto da transaction. */
|
|
600
|
+
startChild(op, description) {
|
|
601
|
+
return this.createSpan(this.spanId, op, description);
|
|
602
|
+
}
|
|
603
|
+
setTag(key, value) {
|
|
604
|
+
this.tags[key] = value;
|
|
605
|
+
return this;
|
|
606
|
+
}
|
|
607
|
+
setStatus(status) {
|
|
608
|
+
this.status = status;
|
|
609
|
+
return this;
|
|
610
|
+
}
|
|
611
|
+
setName(name) {
|
|
612
|
+
this.name = name;
|
|
613
|
+
return this;
|
|
614
|
+
}
|
|
615
|
+
finish() {
|
|
616
|
+
if (this.finished) return;
|
|
617
|
+
this.finished = true;
|
|
618
|
+
for (const span of this.spans) span.finish();
|
|
619
|
+
if (!this.sampled || !this.client) return;
|
|
620
|
+
const payload = {
|
|
621
|
+
event_id: this.eventId,
|
|
622
|
+
name: this.name,
|
|
623
|
+
op: this.op,
|
|
624
|
+
status: this.status,
|
|
625
|
+
start_timestamp: this.startTimestamp,
|
|
626
|
+
timestamp: nowISO(),
|
|
627
|
+
spans: this.spans.map((span) => span.toJSON()),
|
|
628
|
+
tags: Object.keys(this.tags).length > 0 ? this.tags : void 0
|
|
629
|
+
};
|
|
630
|
+
this.client.sendTransaction(payload);
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
// src/checkin.ts
|
|
635
|
+
function sendCheckIn(client2, options) {
|
|
636
|
+
const checkInId = options.checkInId ?? uuid4();
|
|
637
|
+
client2.sendCheckIn({
|
|
638
|
+
check_in_id: checkInId,
|
|
639
|
+
monitor_slug: options.monitorSlug,
|
|
640
|
+
status: options.status,
|
|
641
|
+
duration_ms: options.durationMs,
|
|
642
|
+
schedule: options.schedule,
|
|
643
|
+
timezone: options.timezone
|
|
644
|
+
});
|
|
645
|
+
return checkInId;
|
|
646
|
+
}
|
|
647
|
+
async function withMonitorImpl(client2, captureError, monitorSlug, fn, options) {
|
|
648
|
+
const checkInId = sendCheckIn(client2, {
|
|
649
|
+
monitorSlug,
|
|
650
|
+
status: "in_progress",
|
|
651
|
+
schedule: options?.schedule,
|
|
652
|
+
timezone: options?.timezone
|
|
653
|
+
});
|
|
654
|
+
const startedAt = Date.now();
|
|
655
|
+
try {
|
|
656
|
+
const result = await fn();
|
|
657
|
+
sendCheckIn(client2, {
|
|
658
|
+
monitorSlug,
|
|
659
|
+
status: "ok",
|
|
660
|
+
checkInId,
|
|
661
|
+
durationMs: Date.now() - startedAt,
|
|
662
|
+
schedule: options?.schedule,
|
|
663
|
+
timezone: options?.timezone
|
|
664
|
+
});
|
|
665
|
+
return result;
|
|
666
|
+
} catch (error) {
|
|
667
|
+
sendCheckIn(client2, {
|
|
668
|
+
monitorSlug,
|
|
669
|
+
status: "error",
|
|
670
|
+
checkInId,
|
|
671
|
+
durationMs: Date.now() - startedAt,
|
|
672
|
+
schedule: options?.schedule,
|
|
673
|
+
timezone: options?.timezone
|
|
674
|
+
});
|
|
675
|
+
captureError(error);
|
|
676
|
+
throw error;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// src/core.ts
|
|
681
|
+
var DEFAULT_MAX_BREADCRUMBS = 100;
|
|
682
|
+
var client;
|
|
683
|
+
var scope = new Scope();
|
|
684
|
+
var heartbeat;
|
|
685
|
+
function init(options) {
|
|
686
|
+
if (client) {
|
|
687
|
+
client.logger.warn("init() chamado mais de uma vez \u2014 substituindo o client anterior");
|
|
688
|
+
heartbeat?.stop();
|
|
689
|
+
heartbeat = void 0;
|
|
690
|
+
}
|
|
691
|
+
client = new Client(options);
|
|
692
|
+
if (options.captureUnhandled !== false) {
|
|
693
|
+
installGlobalHandlers(client, () => scope);
|
|
694
|
+
}
|
|
695
|
+
if (options.heartbeat) {
|
|
696
|
+
const heartbeatOptions = options.heartbeat === true ? {} : options.heartbeat;
|
|
697
|
+
heartbeat = new Heartbeat(client, heartbeatOptions, options.serverName);
|
|
698
|
+
heartbeat.start();
|
|
699
|
+
}
|
|
700
|
+
client.logger.debug("inicializado", { endpoint: client.dsn.endpoint });
|
|
701
|
+
}
|
|
702
|
+
function getClient() {
|
|
703
|
+
return client;
|
|
704
|
+
}
|
|
705
|
+
function captureException(error, hint) {
|
|
706
|
+
return client?.captureException(error, hint, scope);
|
|
707
|
+
}
|
|
708
|
+
function captureMessage(message, level = "info", hint) {
|
|
709
|
+
return client?.captureMessage(message, level, hint, scope);
|
|
710
|
+
}
|
|
711
|
+
function addBreadcrumb(crumb) {
|
|
712
|
+
scope.addBreadcrumb(crumb, client?.options.maxBreadcrumbs ?? DEFAULT_MAX_BREADCRUMBS);
|
|
713
|
+
}
|
|
714
|
+
function setTag(key, value) {
|
|
715
|
+
scope.setTag(key, value);
|
|
716
|
+
}
|
|
717
|
+
function setTags(tags) {
|
|
718
|
+
scope.setTags(tags);
|
|
719
|
+
}
|
|
720
|
+
function setUser(user) {
|
|
721
|
+
scope.setUser(user);
|
|
722
|
+
}
|
|
723
|
+
function setContext(name, context) {
|
|
724
|
+
scope.setContext(name, context);
|
|
725
|
+
}
|
|
726
|
+
function setExtra(key, value) {
|
|
727
|
+
scope.setExtra(key, value);
|
|
728
|
+
}
|
|
729
|
+
function withScope(callback) {
|
|
730
|
+
const previous = scope;
|
|
731
|
+
scope = previous.clone();
|
|
732
|
+
try {
|
|
733
|
+
return callback(scope);
|
|
734
|
+
} finally {
|
|
735
|
+
scope = previous;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
function startTransaction(name, op) {
|
|
739
|
+
const rate = client?.options.tracesSampleRate ?? 1;
|
|
740
|
+
const sampled = rate >= 1 || Math.random() < rate;
|
|
741
|
+
return new Transaction(client, name, op, sampled);
|
|
742
|
+
}
|
|
743
|
+
function checkIn(options) {
|
|
744
|
+
return client ? sendCheckIn(client, options) : void 0;
|
|
745
|
+
}
|
|
746
|
+
async function withMonitor(monitorSlug, fn, options) {
|
|
747
|
+
if (!client) return fn();
|
|
748
|
+
return withMonitorImpl(
|
|
749
|
+
client,
|
|
750
|
+
(error) => captureException(error, { tags: { monitor: monitorSlug } }),
|
|
751
|
+
monitorSlug,
|
|
752
|
+
fn,
|
|
753
|
+
options
|
|
754
|
+
);
|
|
755
|
+
}
|
|
756
|
+
function flush(timeoutMs) {
|
|
757
|
+
return client ? client.flush(timeoutMs) : Promise.resolve(true);
|
|
758
|
+
}
|
|
759
|
+
function close(timeoutMs) {
|
|
760
|
+
heartbeat?.stop();
|
|
761
|
+
heartbeat = void 0;
|
|
762
|
+
return client ? client.close(timeoutMs) : Promise.resolve(true);
|
|
763
|
+
}
|
|
764
|
+
//# sourceMappingURL=index.cjs.map
|