hobots 2.4.0 → 3.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/docs/telemetry.md DELETED
@@ -1,162 +0,0 @@
1
- # Telemetria
2
-
3
- Capability de telemetria: erros (módulo **Issues**), performance e uptime (módulo **Agentes**). Sempre ativa no `init()` único:
4
-
5
- ```js
6
- import * as Hobots from 'hobots';
7
- ```
8
-
9
- Todas as funções abaixo são no-op seguros se `Hobots.init()` não foi chamado (com aviso no console). Assinaturas completas em [Referência de API](./api-reference.md); o que cada conceito **é**, em [Conceitos](./concepts.md).
10
-
11
- ## init
12
-
13
- ```js
14
- Hobots.init({
15
- clientSecret: 'hb_<64 hex>',
16
- environment: 'production',
17
- release: 'robo-nfe@1.4.2',
18
- instanceId: 'vm-cliente-01',
19
- tags: { squad: 'automacoes' },
20
- heartbeat: true,
21
- });
22
- ```
23
-
24
- Cria o cliente, instala handlers globais de erro (a menos que `captureUnhandled: false`) e inicia o heartbeat se configurado. Chamar de novo substitui o cliente. Todos os campos em [Referência de API → InitOptions](./api-reference.md#initoptions).
25
-
26
- ## Captura de erros e mensagens
27
-
28
- ```js
29
- // exceções
30
- Hobots.captureException(error, {
31
- tags: { cliente: 'acme' },
32
- type: 'error',
33
- fingerprint: ['sefaz-timeout'], // agrupa manualmente; sem isso o servidor agrupa pelo stack
34
- });
35
-
36
- // mensagens sem exceção
37
- Hobots.captureMessage('Lote processado com sucesso', 'info');
38
- ```
39
-
40
- Ambas retornam o `event_id` (ou `undefined` se não inicializado). O segundo argumento é um [`CaptureHint`](./api-reference.md#capturehint) (`type`, `tags`, `extra`, `fingerprint`).
41
-
42
- > **Atenção:** o `event_id` retornado **não é confirmação de envio** — se o evento foi descartado por amostragem ou por `beforeSend`, você recebe um id normalmente e nada foi enfileirado.
43
-
44
- Erros **não tratados** (`uncaughtException` / `unhandledRejection`) são capturados e flushados automaticamente antes do processo sair — desligue com `captureUnhandled: false`.
45
-
46
- Conceitos: [Evento](./concepts.md#evento) · [Type](./concepts.md#type-tipo-do-evento) · [Fingerprint](./concepts.md#fingerprint).
47
-
48
- ## Breadcrumbs
49
-
50
- Trilha do que aconteceu antes do erro; enviada junto do próximo evento.
51
-
52
- ```js
53
- Hobots.addBreadcrumb({ category: 'nfe', message: 'Baixou XML da nota 123', level: 'info' });
54
- ```
55
-
56
- O buffer é limitado por `maxBreadcrumbs` (default 100, mais antigos descartados).
57
-
58
- Dois pontos que costumam surpreender: a lista **não é limpa** ao enviar um evento (o próximo evento leva as mesmas migalhas de novo), e ela é **global** — para uma trilha que não vaze, adicione dentro de um `withScope`. Conceito: [Breadcrumb](./concepts.md#breadcrumb).
59
-
60
- ## Escopo: tags, usuário, contexto, extras
61
-
62
- Dados anexados a **todos** os eventos seguintes:
63
-
64
- ```js
65
- Hobots.setTag('regiao', 'nordeste');
66
- Hobots.setTags({ squad: 'automacoes', cliente: 'acme' });
67
- Hobots.setUser({ id: 'op-42', email: 'op@acme.com' });
68
- Hobots.setContext('vm', { cpu: 4, ram: '8GB' });
69
- Hobots.setExtra('ultimoLote', 128);
70
- ```
71
-
72
- Qual usar para quê: **tag** é rótulo curto e indexável (você vai filtrar por isso), **context** é grupo nomeado de dados que andam juntos (você vai ler), **extra** é depósito livre para o resto. Detalhes e critérios em [Tag](./concepts.md#tag) · [Context](./concepts.md#context) · [Extra](./concepts.md#extra).
73
-
74
- Três comportamentos que valem saber:
75
-
76
- - Tags podem vir de quatro lugares e a última vence: `init({ tags })` → scope → evento → `hint` da chamada.
77
- - `setContext(nome, null)` **apaga** o grupo. O SDK já injeta os grupos `runtime` e `os` em todo evento.
78
- - `setExtra` não é indexado — se você quiser filtrar por aquele campo, ele deveria ser uma tag.
79
-
80
- Para um escopo **isolado** (sem vazar para o global), use `withScope`:
81
-
82
- ```js
83
- Hobots.withScope((scope) => {
84
- scope.setTag('lote', '128').setFingerprint(['reprocessamento']);
85
- Hobots.captureMessage('Reprocessando lote 128');
86
- });
87
- ```
88
-
89
- > **Atenção:** `withScope` é **síncrono** — ele troca o scope global e restaura no fim do callback. Se você der `await` lá dentro, o scope isolado vale para qualquer código que capturar eventos enquanto aquele `await` está pendente. Em código concorrente (várias runs em paralelo), passe as tags no `hint`: `captureException(error, { tags: { lote: '128' } })`. Conceito: [withScope](./concepts.md#withscope).
90
-
91
- ## Performance: transactions e etapas
92
-
93
- Uma **transaction** é uma unidade de trabalho nomeada e medida ("quanto minha rotina demorou"); as **etapas** são as unidades dentro dela ("onde o tempo foi gasto"). Conceitos: [Transaction](./concepts.md#transaction) · [Step](./concepts.md#step).
94
-
95
- ```js
96
- const tx = Hobots.startTransaction('processar-lote', 'rpa.job');
97
-
98
- const step = tx.startChild('http.client', 'GET /api/notas');
99
- await api.buscarNotas();
100
- step.setData('notas', 42).finish();
101
-
102
- const filho = step.startChild('db.query', 'INSERT INTO notas'); // etapas aninham
103
- await gravar();
104
- filho.finish();
105
-
106
- tx.setStatus('ok'); // ou 'error'
107
- tx.finish(); // só aqui a transaction é enviada (respeitando tracesSampleRate)
108
- ```
109
-
110
- - `startChild(op?, description?)` existe tanto em `Transaction` quanto em `Step` (aninhamento arbitrário).
111
- - Métodos encadeáveis: `setStatus`, `setData` (step), `setTag`/`setName` (transaction).
112
- - Status de step: `'ok'` (default), `'warning'` (atenção, não é falha) ou `'error'` — cores distintas no waterfall.
113
- - `finish()` na transaction fecha etapas abertas e envia o payload; nada é enviado se ela não foi amostrada. É **idempotente** — chamar duas vezes não envia duas.
114
- - A decisão de amostragem acontece no **`startTransaction()`**, não no `finish()`. Esquecer o `finish()` de uma step não perde o dado: ela é fechada no instante em que a transaction fecha.
115
- - Uma transaction leva as tags do `init()` e as que você marcar com `tx.setTag()` — ela **não** herda as tags do scope.
116
-
117
- Dentro de um handler de task, `startTransaction()` **retorna a transaction da própria run** ([`ctx.tx`](./concepts.md#transaction-de-run-ctxtx)) em vez de criar uma segunda — cada execução tem exatamente **uma** transaction. Fora de um handler, ela cria uma transaction nova, sem correlação com run nenhuma.
118
-
119
- ## Heartbeat (uptime)
120
-
121
- Bate "estou vivo" periodicamente; o servidor acusa o robô **offline** quando os batimentos param.
122
-
123
- ```js
124
- Hobots.init({
125
- clientSecret,
126
- heartbeat: { intervalMs: 30_000, name: 'Robô NFe — VM 01' },
127
- });
128
- ```
129
-
130
- `heartbeat: true` usa os defaults. A identidade é o `instanceId` do `init()`. Campos em [HeartbeatOptions](./api-reference.md#heartbeatoptions); conceito em [Heartbeat](./concepts.md#heartbeat).
131
-
132
- O primeiro batimento sai **na hora** em que o `init()` roda — não depois do primeiro intervalo. O batimento também carrega o intervalo configurado: é assim que o servidor sabe quanto silêncio é normal antes de declarar o robô offline.
133
-
134
- Essa identidade é a mesma que o poll de tasks envia (`agent.instance_id`) — os dois canais derivam do `instanceId` do `init()`, então o robô aparece como **um agente só** no módulo Agentes automaticamente. Por isso, com `tasks: true` o heartbeat é **opcional** (o poll já marca a presença do agente); ele é essencial para agentes só de telemetria.
135
-
136
- ## Recursos da máquina (CPU, memória, disco)
137
-
138
- Ligado por padrão em Node (`machineMetrics: true`), o SDK coleta CPU do sistema, memória, disco do volume do bot e RSS/CPU do próprio processo — **sem dependência nova** e sem timer próprio: a leitura pega carona em cada heartbeat e em cada poll de tasks (série da instância em **Instâncias → recursos da máquina**) e vai como `contexts.machine` em cada evento (card **"máquina no momento do erro"** no detalhe da issue). Assim dá para responder se o ambiente tem recurso suficiente e se um erro coincidiu com CPU/memória no limite.
139
-
140
- ```js
141
- Hobots.init({ clientSecret, instanceId: 'vm-01', heartbeat: true }); // coleta ligada
142
- Hobots.init({ clientSecret, instanceId: 'vm-01', machineMetrics: false }); // desliga
143
- ```
144
-
145
- O snapshot tem ~600 bytes (teto do servidor: 4 KiB). Formato em [Protocolo → MachineSnapshot](./protocol.md#machinesnapshot).
146
-
147
- ## Flush e close
148
-
149
- Nada é enviado na hora: cada evento, transaction e heartbeat entra numa **fila em memória** e sai em lote. É por isso que essas duas funções existem — quando o processo morre, a fila morre com ele. Conceito: [Fila, flush e close](./concepts.md#fila-flush-e-close).
150
-
151
- ```js
152
- await Hobots.flush(2000); // envia o que está em buffer, mantém o SDK vivo
153
- await Hobots.close(2000); // para o polling de tasks (se ativo) + heartbeat + flush final do transport
154
- ```
155
-
156
- O `timeoutMs` é opcional nas duas — o default é 5s (veja [Tempos e intervalos](./api-reference.md#tempos-e-intervalos)). As duas devolvem `false` quando estouram o prazo, o que significa que o SDK parou de esperar, **não** que os dados foram perdidos: os envios em voo continuam tentando enquanto o processo existir.
157
-
158
- Chame `close` antes do processo sair. Os timers da telemetria são `unref`'d, então ela **não** segura o processo vivo sozinha (só o `start()` das tasks segura).
159
-
160
- > **Atenção:** `close()` é **terminal**. Depois dele, todo evento, transaction ou heartbeat novo é **descartado** com aviso no console — não existe `reopen()`. Se o programa precisar voltar a emitir telemetria, chame `Hobots.init()` de novo.
161
-
162
- > **Atenção:** o `timeoutMs` do `close()` é gasto **duas vezes, em sequência** — uma esperando as runs de tasks, outra no flush final. `close(15_000)` pode levar até ~30s no pior caso. Dimensione por aí se o seu SIGTERM tem prazo curto.