hobots 2.0.0 → 2.2.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/README.md +22 -3
- package/dist/index.cjs +109 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -8
- package/dist/index.d.ts +28 -8
- package/dist/index.js +109 -29
- package/dist/index.js.map +1 -1
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.cts +24 -4
- package/dist/protocol.d.ts +24 -4
- package/docs/api-reference.md +17 -7
- package/docs/concepts.md +13 -11
- package/docs/protocol.md +3 -1
- package/docs/tasks.md +39 -1
- package/docs/telemetry.md +3 -3
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Breadcrumb, EventUser,
|
|
2
|
-
export { Envelope, EnvelopeItem, ExceptionData, InstanceInfo, PollRequest, PollResponse, RunAttachmentConfirmRequest, RunAttachmentConfirmResponse, RunAttachmentCreateRequest, RunAttachmentCreateResponse, RunDescriptor, RunError, RunItemInput, RunItemsCreateRequest, RunItemsCreateResponse, RunLogEntry, RunStatus, RunUpdateRequest, RunUpdateResponse, RunUpdateStatus, StackFrame } from './protocol.cjs';
|
|
1
|
+
import { Breadcrumb, EventUser, EventType, EventPayload, TransactionPayload, HeartbeatPayload, StepStatus, RunLogLevel, StepData, RunItemStatus, RunProgress, RunAttachmentContentType } from './protocol.cjs';
|
|
2
|
+
export { BreadcrumbLevel, Envelope, EnvelopeItem, ExceptionData, InstanceInfo, PollRequest, PollResponse, RunAttachmentConfirmRequest, RunAttachmentConfirmResponse, RunAttachmentCreateRequest, RunAttachmentCreateResponse, RunDescriptor, RunError, RunItemInput, RunItemsCreateRequest, RunItemsCreateResponse, RunLogEntry, RunStatus, RunUpdateRequest, RunUpdateResponse, RunUpdateStatus, StackFrame } from './protocol.cjs';
|
|
3
3
|
|
|
4
4
|
/** Aceita tudo que o handler pode ter em mãos: bytes ou um caminho de arquivo (só Node). */
|
|
5
5
|
type AttachInput = Uint8Array | ArrayBuffer | string;
|
|
@@ -25,7 +25,7 @@ declare class Scope {
|
|
|
25
25
|
user?: EventUser;
|
|
26
26
|
contexts: Record<string, Record<string, unknown>>;
|
|
27
27
|
extra: Record<string, unknown>;
|
|
28
|
-
|
|
28
|
+
type?: EventType;
|
|
29
29
|
fingerprint?: string[];
|
|
30
30
|
breadcrumbs: Breadcrumb[];
|
|
31
31
|
setTag(key: string, value: string): this;
|
|
@@ -34,7 +34,7 @@ declare class Scope {
|
|
|
34
34
|
setContext(name: string, context: Record<string, unknown> | null): this;
|
|
35
35
|
setExtra(key: string, value: unknown): this;
|
|
36
36
|
setExtras(extras: Record<string, unknown>): this;
|
|
37
|
-
|
|
37
|
+
setType(type: EventType): this;
|
|
38
38
|
setFingerprint(fingerprint: string[]): this;
|
|
39
39
|
addBreadcrumb(crumb: BreadcrumbInput, maxBreadcrumbs: number): this;
|
|
40
40
|
clearBreadcrumbs(): this;
|
|
@@ -59,7 +59,7 @@ declare class Client {
|
|
|
59
59
|
/** Serialização explícita nunca inclui o secret. */
|
|
60
60
|
toJSON(): Record<string, unknown>;
|
|
61
61
|
captureException(error: unknown, hint: CaptureHint | undefined, scope: Scope): string;
|
|
62
|
-
captureMessage(message: string,
|
|
62
|
+
captureMessage(message: string, type: EventType, hint: CaptureHint | undefined, scope: Scope): string;
|
|
63
63
|
captureEvent(event: EventPayload, hint: CaptureHint | undefined, scope: Scope): string;
|
|
64
64
|
private prepareEvent;
|
|
65
65
|
sendTransaction(payload: TransactionPayload): void;
|
|
@@ -198,6 +198,24 @@ interface RunItems {
|
|
|
198
198
|
/** Ocorrência de negócio (ex.: "nota nº 10 não encontrada") — não é falha do bot. */
|
|
199
199
|
occurrence(message: string, payload?: Record<string, unknown>, options?: RunItemOptions): void;
|
|
200
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Progresso da execução (itens processados / total) — opcional e independente de
|
|
203
|
+
* `ctx.items`. Declare o total antes do loop e avance a cada item: a plataforma e o
|
|
204
|
+
* Studio mostram barra, percentual e tempo restante estimado. Sem `total()` nada é
|
|
205
|
+
* enviado. Chamadas são síncronas e baratas (≤ 1 PATCH/s, pegando carona nos logs).
|
|
206
|
+
*/
|
|
207
|
+
interface RunProgressReporter {
|
|
208
|
+
/** Declara (ou ajusta) o total de itens previsto — inteiro >= 1. Idempotente. */
|
|
209
|
+
total(total: number): void;
|
|
210
|
+
/** Incrementa os processados (padrão 1). Clampa em `total`. */
|
|
211
|
+
advance(count?: number): void;
|
|
212
|
+
/** Define o valor absoluto de processados e, opcionalmente, o total. */
|
|
213
|
+
set(current: number, total?: number): void;
|
|
214
|
+
/** Processados até agora (0 antes de qualquer chamada). */
|
|
215
|
+
readonly current: number;
|
|
216
|
+
/** `{ current, total }` quando há total declarado; null caso contrário. */
|
|
217
|
+
readonly snapshot: RunProgress | null;
|
|
218
|
+
}
|
|
201
219
|
interface RunContext {
|
|
202
220
|
runId: string;
|
|
203
221
|
task: string;
|
|
@@ -205,6 +223,8 @@ interface RunContext {
|
|
|
205
223
|
log: RunLogger;
|
|
206
224
|
/** Itens processados/gerados pela execução — a entrega do bot, com status e atributos */
|
|
207
225
|
items: RunItems;
|
|
226
|
+
/** Progresso declarado (barra + ETA no app) — opcional, independente de `ctx.items` */
|
|
227
|
+
progress: RunProgressReporter;
|
|
208
228
|
/**
|
|
209
229
|
* Transaction de performance desta execução — já correlacionada à run e finalizada
|
|
210
230
|
* automaticamente ao fim do handler. Use `ctx.tx.startChild(op, description)` pra medir
|
|
@@ -277,7 +297,7 @@ interface CaptureAttachment {
|
|
|
277
297
|
contentType?: RunAttachmentContentType;
|
|
278
298
|
}
|
|
279
299
|
interface CaptureHint {
|
|
280
|
-
|
|
300
|
+
type?: EventType;
|
|
281
301
|
tags?: Record<string, string>;
|
|
282
302
|
extra?: Record<string, unknown>;
|
|
283
303
|
fingerprint?: string[];
|
|
@@ -305,7 +325,7 @@ declare function getClient(): Client | undefined;
|
|
|
305
325
|
* como miniatura na linha de log da run correspondente ao erro.
|
|
306
326
|
*/
|
|
307
327
|
declare function captureException(error: unknown, hint?: CaptureHint): string | undefined;
|
|
308
|
-
declare function captureMessage(message: string,
|
|
328
|
+
declare function captureMessage(message: string, type?: EventType, hint?: CaptureHint): string | undefined;
|
|
309
329
|
/** Registra um breadcrumb — anexado aos próximos eventos como trilha do que aconteceu antes. */
|
|
310
330
|
declare function addBreadcrumb(crumb: BreadcrumbInput): void;
|
|
311
331
|
declare function setTag(key: string, value: string): void;
|
|
@@ -336,4 +356,4 @@ declare function close(timeoutMs?: number): Promise<boolean>;
|
|
|
336
356
|
|
|
337
357
|
declare function scrubSecrets(text: string): string;
|
|
338
358
|
|
|
339
|
-
export { type AttachInput, Breadcrumb, type BreadcrumbInput, type CaptureAttachment, type CaptureHint, Client, DEFAULT_BASE_URL, EventPayload, EventUser, type HeartbeatOptions, HeartbeatPayload, type InitOptions, RunAttachmentContentType, type RunContext, type RunItemOptions, RunItemStatus, type RunItems, RunLogLevel,
|
|
359
|
+
export { type AttachInput, Breadcrumb, type BreadcrumbInput, type CaptureAttachment, type CaptureHint, Client, DEFAULT_BASE_URL, EventPayload, EventType, EventUser, type HeartbeatOptions, HeartbeatPayload, type InitOptions, RunAttachmentContentType, type RunContext, type RunItemOptions, RunItemStatus, type RunItems, RunLogLevel, RunProgress, type RunProgressReporter, Scope, Step, StepData, type TaskHandler, type TasksOptions, Transaction, TransactionPayload, addBreadcrumb, captureException, captureMessage, close, flush, getClient, init, register, scrubSecrets, setContext, setExtra, setTag, setTags, setUser, start, startTransaction, stop, withScope };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Breadcrumb, EventUser,
|
|
2
|
-
export { Envelope, EnvelopeItem, ExceptionData, InstanceInfo, PollRequest, PollResponse, RunAttachmentConfirmRequest, RunAttachmentConfirmResponse, RunAttachmentCreateRequest, RunAttachmentCreateResponse, RunDescriptor, RunError, RunItemInput, RunItemsCreateRequest, RunItemsCreateResponse, RunLogEntry, RunStatus, RunUpdateRequest, RunUpdateResponse, RunUpdateStatus, StackFrame } from './protocol.js';
|
|
1
|
+
import { Breadcrumb, EventUser, EventType, EventPayload, TransactionPayload, HeartbeatPayload, StepStatus, RunLogLevel, StepData, RunItemStatus, RunProgress, RunAttachmentContentType } from './protocol.js';
|
|
2
|
+
export { BreadcrumbLevel, Envelope, EnvelopeItem, ExceptionData, InstanceInfo, PollRequest, PollResponse, RunAttachmentConfirmRequest, RunAttachmentConfirmResponse, RunAttachmentCreateRequest, RunAttachmentCreateResponse, RunDescriptor, RunError, RunItemInput, RunItemsCreateRequest, RunItemsCreateResponse, RunLogEntry, RunStatus, RunUpdateRequest, RunUpdateResponse, RunUpdateStatus, StackFrame } from './protocol.js';
|
|
3
3
|
|
|
4
4
|
/** Aceita tudo que o handler pode ter em mãos: bytes ou um caminho de arquivo (só Node). */
|
|
5
5
|
type AttachInput = Uint8Array | ArrayBuffer | string;
|
|
@@ -25,7 +25,7 @@ declare class Scope {
|
|
|
25
25
|
user?: EventUser;
|
|
26
26
|
contexts: Record<string, Record<string, unknown>>;
|
|
27
27
|
extra: Record<string, unknown>;
|
|
28
|
-
|
|
28
|
+
type?: EventType;
|
|
29
29
|
fingerprint?: string[];
|
|
30
30
|
breadcrumbs: Breadcrumb[];
|
|
31
31
|
setTag(key: string, value: string): this;
|
|
@@ -34,7 +34,7 @@ declare class Scope {
|
|
|
34
34
|
setContext(name: string, context: Record<string, unknown> | null): this;
|
|
35
35
|
setExtra(key: string, value: unknown): this;
|
|
36
36
|
setExtras(extras: Record<string, unknown>): this;
|
|
37
|
-
|
|
37
|
+
setType(type: EventType): this;
|
|
38
38
|
setFingerprint(fingerprint: string[]): this;
|
|
39
39
|
addBreadcrumb(crumb: BreadcrumbInput, maxBreadcrumbs: number): this;
|
|
40
40
|
clearBreadcrumbs(): this;
|
|
@@ -59,7 +59,7 @@ declare class Client {
|
|
|
59
59
|
/** Serialização explícita nunca inclui o secret. */
|
|
60
60
|
toJSON(): Record<string, unknown>;
|
|
61
61
|
captureException(error: unknown, hint: CaptureHint | undefined, scope: Scope): string;
|
|
62
|
-
captureMessage(message: string,
|
|
62
|
+
captureMessage(message: string, type: EventType, hint: CaptureHint | undefined, scope: Scope): string;
|
|
63
63
|
captureEvent(event: EventPayload, hint: CaptureHint | undefined, scope: Scope): string;
|
|
64
64
|
private prepareEvent;
|
|
65
65
|
sendTransaction(payload: TransactionPayload): void;
|
|
@@ -198,6 +198,24 @@ interface RunItems {
|
|
|
198
198
|
/** Ocorrência de negócio (ex.: "nota nº 10 não encontrada") — não é falha do bot. */
|
|
199
199
|
occurrence(message: string, payload?: Record<string, unknown>, options?: RunItemOptions): void;
|
|
200
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Progresso da execução (itens processados / total) — opcional e independente de
|
|
203
|
+
* `ctx.items`. Declare o total antes do loop e avance a cada item: a plataforma e o
|
|
204
|
+
* Studio mostram barra, percentual e tempo restante estimado. Sem `total()` nada é
|
|
205
|
+
* enviado. Chamadas são síncronas e baratas (≤ 1 PATCH/s, pegando carona nos logs).
|
|
206
|
+
*/
|
|
207
|
+
interface RunProgressReporter {
|
|
208
|
+
/** Declara (ou ajusta) o total de itens previsto — inteiro >= 1. Idempotente. */
|
|
209
|
+
total(total: number): void;
|
|
210
|
+
/** Incrementa os processados (padrão 1). Clampa em `total`. */
|
|
211
|
+
advance(count?: number): void;
|
|
212
|
+
/** Define o valor absoluto de processados e, opcionalmente, o total. */
|
|
213
|
+
set(current: number, total?: number): void;
|
|
214
|
+
/** Processados até agora (0 antes de qualquer chamada). */
|
|
215
|
+
readonly current: number;
|
|
216
|
+
/** `{ current, total }` quando há total declarado; null caso contrário. */
|
|
217
|
+
readonly snapshot: RunProgress | null;
|
|
218
|
+
}
|
|
201
219
|
interface RunContext {
|
|
202
220
|
runId: string;
|
|
203
221
|
task: string;
|
|
@@ -205,6 +223,8 @@ interface RunContext {
|
|
|
205
223
|
log: RunLogger;
|
|
206
224
|
/** Itens processados/gerados pela execução — a entrega do bot, com status e atributos */
|
|
207
225
|
items: RunItems;
|
|
226
|
+
/** Progresso declarado (barra + ETA no app) — opcional, independente de `ctx.items` */
|
|
227
|
+
progress: RunProgressReporter;
|
|
208
228
|
/**
|
|
209
229
|
* Transaction de performance desta execução — já correlacionada à run e finalizada
|
|
210
230
|
* automaticamente ao fim do handler. Use `ctx.tx.startChild(op, description)` pra medir
|
|
@@ -277,7 +297,7 @@ interface CaptureAttachment {
|
|
|
277
297
|
contentType?: RunAttachmentContentType;
|
|
278
298
|
}
|
|
279
299
|
interface CaptureHint {
|
|
280
|
-
|
|
300
|
+
type?: EventType;
|
|
281
301
|
tags?: Record<string, string>;
|
|
282
302
|
extra?: Record<string, unknown>;
|
|
283
303
|
fingerprint?: string[];
|
|
@@ -305,7 +325,7 @@ declare function getClient(): Client | undefined;
|
|
|
305
325
|
* como miniatura na linha de log da run correspondente ao erro.
|
|
306
326
|
*/
|
|
307
327
|
declare function captureException(error: unknown, hint?: CaptureHint): string | undefined;
|
|
308
|
-
declare function captureMessage(message: string,
|
|
328
|
+
declare function captureMessage(message: string, type?: EventType, hint?: CaptureHint): string | undefined;
|
|
309
329
|
/** Registra um breadcrumb — anexado aos próximos eventos como trilha do que aconteceu antes. */
|
|
310
330
|
declare function addBreadcrumb(crumb: BreadcrumbInput): void;
|
|
311
331
|
declare function setTag(key: string, value: string): void;
|
|
@@ -336,4 +356,4 @@ declare function close(timeoutMs?: number): Promise<boolean>;
|
|
|
336
356
|
|
|
337
357
|
declare function scrubSecrets(text: string): string;
|
|
338
358
|
|
|
339
|
-
export { type AttachInput, Breadcrumb, type BreadcrumbInput, type CaptureAttachment, type CaptureHint, Client, DEFAULT_BASE_URL, EventPayload, EventUser, type HeartbeatOptions, HeartbeatPayload, type InitOptions, RunAttachmentContentType, type RunContext, type RunItemOptions, RunItemStatus, type RunItems, RunLogLevel,
|
|
359
|
+
export { type AttachInput, Breadcrumb, type BreadcrumbInput, type CaptureAttachment, type CaptureHint, Client, DEFAULT_BASE_URL, EventPayload, EventType, EventUser, type HeartbeatOptions, HeartbeatPayload, type InitOptions, RunAttachmentContentType, type RunContext, type RunItemOptions, RunItemStatus, type RunItems, RunLogLevel, RunProgress, type RunProgressReporter, Scope, Step, StepData, type TaskHandler, type TasksOptions, Transaction, TransactionPayload, addBreadcrumb, captureException, captureMessage, close, flush, getClient, init, register, scrubSecrets, setContext, setExtra, setTag, setTags, setUser, start, startTransaction, stop, withScope };
|
package/dist/index.js
CHANGED
|
@@ -103,7 +103,7 @@ function scrubSecrets(text) {
|
|
|
103
103
|
|
|
104
104
|
// src/utils.ts
|
|
105
105
|
var SDK_NAME = "hobots";
|
|
106
|
-
var SDK_VERSION = true ? "2.
|
|
106
|
+
var SDK_VERSION = true ? "2.2.0" : "0.0.0-dev";
|
|
107
107
|
function isNode() {
|
|
108
108
|
return typeof process !== "undefined" && typeof process.versions?.node === "string";
|
|
109
109
|
}
|
|
@@ -233,34 +233,34 @@ function safeString(value) {
|
|
|
233
233
|
}
|
|
234
234
|
return String(value);
|
|
235
235
|
}
|
|
236
|
-
function eventFromException(error,
|
|
237
|
-
let
|
|
236
|
+
function eventFromException(error, type = "error") {
|
|
237
|
+
let exceptionType;
|
|
238
238
|
let value;
|
|
239
239
|
let frames = [];
|
|
240
240
|
if (error instanceof Error) {
|
|
241
|
-
|
|
241
|
+
exceptionType = error.name || "Error";
|
|
242
242
|
value = scrubSecrets(error.message);
|
|
243
243
|
frames = parseStacktrace(error.stack);
|
|
244
244
|
} else {
|
|
245
|
-
|
|
245
|
+
exceptionType = "NonError";
|
|
246
246
|
value = scrubSecrets(safeString(error));
|
|
247
247
|
}
|
|
248
248
|
return {
|
|
249
249
|
event_id: uuid4(),
|
|
250
250
|
timestamp: nowISO(),
|
|
251
|
-
|
|
251
|
+
type,
|
|
252
252
|
exception: {
|
|
253
|
-
type,
|
|
253
|
+
type: exceptionType,
|
|
254
254
|
value,
|
|
255
255
|
...frames.length > 0 ? { stacktrace: { frames } } : {}
|
|
256
256
|
}
|
|
257
257
|
};
|
|
258
258
|
}
|
|
259
|
-
function eventFromMessage(message,
|
|
259
|
+
function eventFromMessage(message, type = "warning") {
|
|
260
260
|
return {
|
|
261
261
|
event_id: uuid4(),
|
|
262
262
|
timestamp: nowISO(),
|
|
263
|
-
|
|
263
|
+
type,
|
|
264
264
|
message: scrubSecrets(message)
|
|
265
265
|
};
|
|
266
266
|
}
|
|
@@ -423,10 +423,10 @@ var Client = class {
|
|
|
423
423
|
return `Client { baseUrl: '${this.#config.baseUrl}' }`;
|
|
424
424
|
}
|
|
425
425
|
captureException(error, hint, scope2) {
|
|
426
|
-
return this.captureEvent(eventFromException(error, hint?.
|
|
426
|
+
return this.captureEvent(eventFromException(error, hint?.type ?? "error"), hint, scope2);
|
|
427
427
|
}
|
|
428
|
-
captureMessage(message,
|
|
429
|
-
return this.captureEvent(eventFromMessage(message,
|
|
428
|
+
captureMessage(message, type, hint, scope2) {
|
|
429
|
+
return this.captureEvent(eventFromMessage(message, type), hint, scope2);
|
|
430
430
|
}
|
|
431
431
|
captureEvent(event, hint, scope2) {
|
|
432
432
|
const sampleRate = this.options.sampleRate ?? 1;
|
|
@@ -448,7 +448,7 @@ var Client = class {
|
|
|
448
448
|
const extra = { ...scope2.extra, ...event.extra, ...hint?.extra };
|
|
449
449
|
return {
|
|
450
450
|
...event,
|
|
451
|
-
|
|
451
|
+
type: hint?.type ?? event.type ?? scope2.type ?? "error",
|
|
452
452
|
release: event.release ?? this.options.release,
|
|
453
453
|
environment: event.environment ?? this.options.environment ?? "production",
|
|
454
454
|
tags: Object.keys(tags).length > 0 ? tags : void 0,
|
|
@@ -566,7 +566,7 @@ function installGlobalHandlers(client2, getScope) {
|
|
|
566
566
|
process.on(
|
|
567
567
|
"uncaughtException",
|
|
568
568
|
markInternal((error) => {
|
|
569
|
-
client2.captureException(error, {
|
|
569
|
+
client2.captureException(error, { type: "fatal", tags: { mechanism: "uncaughtException" } }, getScope());
|
|
570
570
|
void client2.flush(2e3).then(async () => {
|
|
571
571
|
if (externalListenerCount("uncaughtException") === 0) {
|
|
572
572
|
await awaitEmergencyTasks(EMERGENCY_REPORT_CAP_MS);
|
|
@@ -579,7 +579,7 @@ function installGlobalHandlers(client2, getScope) {
|
|
|
579
579
|
process.on(
|
|
580
580
|
"unhandledRejection",
|
|
581
581
|
markInternal((reason) => {
|
|
582
|
-
client2.captureException(reason, {
|
|
582
|
+
client2.captureException(reason, { type: "error", tags: { mechanism: "unhandledRejection" } }, getScope());
|
|
583
583
|
void client2.flush(2e3);
|
|
584
584
|
})
|
|
585
585
|
);
|
|
@@ -610,7 +610,7 @@ var Scope = class _Scope {
|
|
|
610
610
|
user;
|
|
611
611
|
contexts = {};
|
|
612
612
|
extra = {};
|
|
613
|
-
|
|
613
|
+
type;
|
|
614
614
|
fingerprint;
|
|
615
615
|
breadcrumbs = [];
|
|
616
616
|
setTag(key, value) {
|
|
@@ -641,8 +641,8 @@ var Scope = class _Scope {
|
|
|
641
641
|
Object.assign(this.extra, extras);
|
|
642
642
|
return this;
|
|
643
643
|
}
|
|
644
|
-
|
|
645
|
-
this.
|
|
644
|
+
setType(type) {
|
|
645
|
+
this.type = type;
|
|
646
646
|
return this;
|
|
647
647
|
}
|
|
648
648
|
setFingerprint(fingerprint) {
|
|
@@ -666,7 +666,7 @@ var Scope = class _Scope {
|
|
|
666
666
|
next.user = this.user ? { ...this.user } : void 0;
|
|
667
667
|
next.contexts = Object.fromEntries(Object.entries(this.contexts).map(([k, v]) => [k, { ...v }]));
|
|
668
668
|
next.extra = { ...this.extra };
|
|
669
|
-
next.
|
|
669
|
+
next.type = this.type;
|
|
670
670
|
next.fingerprint = this.fingerprint ? [...this.fingerprint] : void 0;
|
|
671
671
|
next.breadcrumbs = [...this.breadcrumbs];
|
|
672
672
|
return next;
|
|
@@ -1143,6 +1143,7 @@ var MAX_ITEM_MESSAGE_CHARS = 2e3;
|
|
|
1143
1143
|
var MAX_ITEM_PAYLOAD_BYTES = 16384;
|
|
1144
1144
|
var ITEMS_FLUSH_AT_BUFFERED = 100;
|
|
1145
1145
|
var ITEMS_DRAIN_MS = 15e3;
|
|
1146
|
+
var PROGRESS_FLUSH_MS = 1e3;
|
|
1146
1147
|
function scrubPayloadValue(value, depth) {
|
|
1147
1148
|
if (typeof value === "string") return scrubSecrets(value);
|
|
1148
1149
|
if (depth >= 4 || value === null || typeof value !== "object") return value;
|
|
@@ -1177,12 +1178,28 @@ var RunReporter = class {
|
|
|
1177
1178
|
failed: (message, payload, options) => this.addItem("failed", message, payload, options?.id),
|
|
1178
1179
|
occurrence: (message, payload, options) => this.addItem("occurrence", message, payload, options?.id)
|
|
1179
1180
|
};
|
|
1181
|
+
const progress = Object.defineProperties(
|
|
1182
|
+
{
|
|
1183
|
+
total: (total) => this.setProgress(this.progressCurrent, total),
|
|
1184
|
+
advance: (count = 1) => this.setProgress(this.progressCurrent + count, this.progressTotal),
|
|
1185
|
+
set: (current, total) => this.setProgress(current, total ?? this.progressTotal)
|
|
1186
|
+
},
|
|
1187
|
+
{
|
|
1188
|
+
current: { enumerable: true, get: () => this.progressCurrent },
|
|
1189
|
+
snapshot: {
|
|
1190
|
+
enumerable: true,
|
|
1191
|
+
get: () => this.progressTotal == null ? null : { current: this.progressCurrent, total: this.progressTotal }
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
// defineProperties não tipa os getters adicionados — a interface é a fonte de verdade
|
|
1195
|
+
);
|
|
1180
1196
|
const signal = this.abortController.signal;
|
|
1181
1197
|
this.context = {
|
|
1182
1198
|
runId,
|
|
1183
1199
|
task,
|
|
1184
1200
|
log,
|
|
1185
1201
|
items,
|
|
1202
|
+
progress,
|
|
1186
1203
|
tx,
|
|
1187
1204
|
signal,
|
|
1188
1205
|
throwIfCanceled: () => {
|
|
@@ -1226,6 +1243,14 @@ var RunReporter = class {
|
|
|
1226
1243
|
uploadQueue = [];
|
|
1227
1244
|
/** Uma vez que a instalação recusa anexos, para de tentar (e de avisar) nesta run. */
|
|
1228
1245
|
attachmentsUnsupported = false;
|
|
1246
|
+
// Progresso (ctx.progress): snapshot absoluto, enviado com throttle via piggyback
|
|
1247
|
+
// em `enqueue()` — nunca gera tráfego próprio enquanto logs/heartbeat já fluem.
|
|
1248
|
+
progressCurrent = 0;
|
|
1249
|
+
progressTotal = null;
|
|
1250
|
+
/** Snapshot ainda não entregue ao servidor. */
|
|
1251
|
+
progressDirty = false;
|
|
1252
|
+
progressTimer;
|
|
1253
|
+
progressWarned = false;
|
|
1229
1254
|
get isDead() {
|
|
1230
1255
|
return this.dead;
|
|
1231
1256
|
}
|
|
@@ -1243,6 +1268,7 @@ var RunReporter = class {
|
|
|
1243
1268
|
this.abort();
|
|
1244
1269
|
this.dead = true;
|
|
1245
1270
|
this.clearFlushTimer();
|
|
1271
|
+
this.clearProgressTimer();
|
|
1246
1272
|
this.buffer = [];
|
|
1247
1273
|
this.itemsClosed = true;
|
|
1248
1274
|
this.clearItemsTimer();
|
|
@@ -1322,13 +1348,63 @@ var RunReporter = class {
|
|
|
1322
1348
|
reportSuccess() {
|
|
1323
1349
|
this.stopCancelWatch();
|
|
1324
1350
|
this.clearFlushTimer();
|
|
1351
|
+
this.forceFinalProgress();
|
|
1325
1352
|
this.enqueue({ status: "succeeded", logs: this.takeLogs() });
|
|
1326
1353
|
}
|
|
1327
1354
|
reportFailure(error) {
|
|
1328
1355
|
this.stopCancelWatch();
|
|
1329
1356
|
this.clearFlushTimer();
|
|
1357
|
+
this.forceFinalProgress();
|
|
1330
1358
|
this.enqueue({ status: "failed", error, logs: this.takeLogs() });
|
|
1331
1359
|
}
|
|
1360
|
+
// ── Progresso ────────────────────────────────────────────────────────────────
|
|
1361
|
+
/** Valida, clampa e marca o snapshot como pendente; agenda flush só se nada mais vai sair. */
|
|
1362
|
+
setProgress(current, total) {
|
|
1363
|
+
if (this.dead) return;
|
|
1364
|
+
if (total != null && (!Number.isInteger(total) || total < 1)) {
|
|
1365
|
+
if (!this.progressWarned) {
|
|
1366
|
+
this.progressWarned = true;
|
|
1367
|
+
this.logger.warn(`ctx.progress: total inv\xE1lido (${String(total)}) \u2014 precisa ser inteiro >= 1; ignorado`);
|
|
1368
|
+
}
|
|
1369
|
+
return;
|
|
1370
|
+
}
|
|
1371
|
+
const safeCurrent = Number.isFinite(current) ? Math.max(0, Math.floor(current)) : this.progressCurrent;
|
|
1372
|
+
const next = total == null ? safeCurrent : Math.min(safeCurrent, total);
|
|
1373
|
+
if (next === this.progressCurrent && total === this.progressTotal) return;
|
|
1374
|
+
this.progressCurrent = next;
|
|
1375
|
+
this.progressTotal = total;
|
|
1376
|
+
if (total == null) return;
|
|
1377
|
+
this.progressDirty = true;
|
|
1378
|
+
if (this.progressTimer) return;
|
|
1379
|
+
this.progressTimer = setTimeout(() => {
|
|
1380
|
+
this.progressTimer = void 0;
|
|
1381
|
+
this.flushProgress();
|
|
1382
|
+
}, PROGRESS_FLUSH_MS);
|
|
1383
|
+
unrefTimer(this.progressTimer);
|
|
1384
|
+
}
|
|
1385
|
+
flushProgress() {
|
|
1386
|
+
this.clearProgressTimer();
|
|
1387
|
+
if (this.dead || !this.progressDirty) return;
|
|
1388
|
+
if (this.buffer.length > 0) this.flushLogs();
|
|
1389
|
+
else this.enqueue({ status: "running" });
|
|
1390
|
+
}
|
|
1391
|
+
clearProgressTimer() {
|
|
1392
|
+
if (this.progressTimer) {
|
|
1393
|
+
clearTimeout(this.progressTimer);
|
|
1394
|
+
this.progressTimer = void 0;
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
/** O PATCH terminal sempre leva o snapshot final (o app mostra "87/100" numa run que falhou). */
|
|
1398
|
+
forceFinalProgress() {
|
|
1399
|
+
this.clearProgressTimer();
|
|
1400
|
+
this.progressDirty = this.progressTotal != null;
|
|
1401
|
+
}
|
|
1402
|
+
/** Consome o snapshot pendente para pegar carona no próximo PATCH. */
|
|
1403
|
+
takeProgress() {
|
|
1404
|
+
if (!this.progressDirty || this.progressTotal == null) return void 0;
|
|
1405
|
+
this.progressDirty = false;
|
|
1406
|
+
return { current: this.progressCurrent, total: this.progressTotal };
|
|
1407
|
+
}
|
|
1332
1408
|
/**
|
|
1333
1409
|
* Heartbeat de cancelamento: enquanto o handler roda, um PATCH 'running' vazio
|
|
1334
1410
|
* periódico faz o servidor responder 409 se a run foi cancelada no app — o que
|
|
@@ -1591,11 +1667,14 @@ var RunReporter = class {
|
|
|
1591
1667
|
new Promise((resolve) => unrefTimer(setTimeout(resolve, timeoutMs)))
|
|
1592
1668
|
]);
|
|
1593
1669
|
}
|
|
1594
|
-
enqueue(
|
|
1670
|
+
enqueue(updateIn) {
|
|
1595
1671
|
if (this.dead) {
|
|
1596
|
-
this.salvageLogs(
|
|
1672
|
+
this.salvageLogs(updateIn.logs);
|
|
1597
1673
|
return;
|
|
1598
1674
|
}
|
|
1675
|
+
this.clearProgressTimer();
|
|
1676
|
+
const progress = this.takeProgress();
|
|
1677
|
+
const update = progress ? { ...updateIn, progress } : updateIn;
|
|
1599
1678
|
this.pendingUpdates++;
|
|
1600
1679
|
this.chain = this.chain.then(async () => {
|
|
1601
1680
|
if (this.dead) {
|
|
@@ -1621,6 +1700,7 @@ var RunReporter = class {
|
|
|
1621
1700
|
this.buffer.unshift(...update.logs);
|
|
1622
1701
|
this.scheduleFlush();
|
|
1623
1702
|
}
|
|
1703
|
+
if (update.progress && this.progressTotal != null) this.progressDirty = true;
|
|
1624
1704
|
this.logger.error(`update da run ${this.runId} perdido:`, error);
|
|
1625
1705
|
}
|
|
1626
1706
|
}).finally(() => {
|
|
@@ -2026,10 +2106,10 @@ function init(options) {
|
|
|
2026
2106
|
function getClient() {
|
|
2027
2107
|
return client;
|
|
2028
2108
|
}
|
|
2029
|
-
function toRunLogLevel(
|
|
2030
|
-
return
|
|
2109
|
+
function toRunLogLevel(type) {
|
|
2110
|
+
return type === "fatal" ? "error" : type;
|
|
2031
2111
|
}
|
|
2032
|
-
function forwardAttachment(attachment, message,
|
|
2112
|
+
function forwardAttachment(attachment, message, type) {
|
|
2033
2113
|
const attach = currentRunAttach();
|
|
2034
2114
|
if (!attach) {
|
|
2035
2115
|
client?.logger.warn("attachment descartado \u2014 s\xF3 \xE9 suportado dentro de uma execu\xE7\xE3o de task (register/start)");
|
|
@@ -2038,7 +2118,7 @@ function forwardAttachment(attachment, message, level) {
|
|
|
2038
2118
|
const withMeta = typeof attachment === "object" && "image" in attachment ? attachment : { image: attachment };
|
|
2039
2119
|
void attach(withMeta.image, {
|
|
2040
2120
|
message,
|
|
2041
|
-
level: toRunLogLevel(
|
|
2121
|
+
level: toRunLogLevel(type),
|
|
2042
2122
|
caption: withMeta.caption,
|
|
2043
2123
|
contentType: withMeta.contentType
|
|
2044
2124
|
});
|
|
@@ -2046,15 +2126,15 @@ function forwardAttachment(attachment, message, level) {
|
|
|
2046
2126
|
function captureException(error, hint) {
|
|
2047
2127
|
if (hint?.attachment) {
|
|
2048
2128
|
const message = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
|
|
2049
|
-
forwardAttachment(hint.attachment, message, hint.
|
|
2129
|
+
forwardAttachment(hint.attachment, message, hint.type ?? "error");
|
|
2050
2130
|
}
|
|
2051
2131
|
return client?.captureException(error, hint, scope);
|
|
2052
2132
|
}
|
|
2053
|
-
function captureMessage(message,
|
|
2133
|
+
function captureMessage(message, type = "warning", hint) {
|
|
2054
2134
|
if (hint?.attachment) {
|
|
2055
|
-
forwardAttachment(hint.attachment, message, hint.
|
|
2135
|
+
forwardAttachment(hint.attachment, message, hint.type ?? type);
|
|
2056
2136
|
}
|
|
2057
|
-
return client?.captureMessage(message,
|
|
2137
|
+
return client?.captureMessage(message, type, hint, scope);
|
|
2058
2138
|
}
|
|
2059
2139
|
function addBreadcrumb(crumb) {
|
|
2060
2140
|
scope.addBreadcrumb(crumb, client?.options.maxBreadcrumbs ?? DEFAULT_MAX_BREADCRUMBS);
|