@gyramais/log-transport 0.1.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/src/options.ts ADDED
@@ -0,0 +1,153 @@
1
+ /*
2
+ Contrato de configuração do pacote.
3
+
4
+ Tudo entra por parâmetro: o pacote NÃO lê `process.env` em nenhum ponto. São três
5
+ razões, em ordem de peso:
6
+
7
+ 1. Correção. Os 15 serviços não leem os mesmos envs — `gyra-export` lê `APP_NAME`,
8
+ e `gyra-file` e `gyra-websocket-server` não leem `ENVIRONMENT` nem `LOG_LEVEL`.
9
+ Um helper de env compartilhado mudaria o comportamento desses em silêncio.
10
+ 2. Testabilidade. Ler env obriga o teste a mutar estado global do processo, o que
11
+ torna a suíte sensível à ordem de execução.
12
+ 3. Contrato visível. A assinatura diz o que o pacote precisa, sem o consumidor
13
+ ter que ler o código-fonte.
14
+
15
+ Quem lê env é o serviço, no entrypoint, onde o env já mora hoje.
16
+ */
17
+
18
+ /*
19
+ Estrutura mínima do transport que o pacote manipula, declarada aqui para o
20
+ `options.ts` não precisar importar o winston-loki.
21
+
22
+ Lista os membros que são de fato tocados — `log` pelo winston ao montar o
23
+ logger, e `flush`/`close`/`once`/`off` pelo caminho de exceção fatal.
24
+
25
+ Era `object`, que aceitava `{ qualquer: 'coisa' }` e até um `Date` em tempo de
26
+ compilação; o erro só aparecia no boot, quando o winston recusava o transport
27
+ com "Invalid transport, must be an object with a log method".
28
+ */
29
+ export interface LokiTransportLike {
30
+ /*
31
+ Todos os membros são opcionais, e isso é deliberado — não desleixo.
32
+
33
+ Não existe membro que dê para exigir: o tipo real do `LokiTransport` declara
34
+ `log` e `flush` como opcionais, então exigir qualquer um deles rejeitaria o
35
+ transport de verdade. Tentei, e o `tsc` recusou o caso legítimo.
36
+
37
+ Com todos opcionais, a detecção de "weak type" do TypeScript faz o trabalho:
38
+ um objeto sem NENHUMA propriedade em comum com esta interface é rejeitado. É o
39
+ suficiente para pegar `{ qualquer: 'coisa' }` e `Date`, que passavam quando o
40
+ tipo era `object`.
41
+ */
42
+ log?: unknown;
43
+ flush?: () => Promise<void>;
44
+ close?: () => void;
45
+ once?: (event: string, listener: (...args: unknown[]) => void) => unknown;
46
+ off?: (event: string, listener: (...args: unknown[]) => void) => unknown;
47
+ }
48
+
49
+ export interface LokiOptions {
50
+ /* Endereço do Loki. Sem ele não há para onde enviar, então é obrigatório. */
51
+ host: string;
52
+
53
+ basicAuth?: string;
54
+
55
+ /*
56
+ Intervalo do batch em segundos. É a janela de linhas que ficam apenas em
57
+ memória e morrem junto com o processo num crash — daí o default curto.
58
+ */
59
+ interval?: number;
60
+
61
+ timeout?: number;
62
+
63
+ /*
64
+ Labels extras, somados aos default (`service`, `app`, `instance`). Serve para
65
+ dimensão específica do serviço; sobrescrever os default é possível, mas quebra
66
+ as consultas existentes.
67
+ */
68
+ labels?: Record<string, string>;
69
+ }
70
+
71
+ export interface FileOptions {
72
+ filename: string;
73
+ }
74
+
75
+ export interface LoggerOptions {
76
+ /*
77
+ Nome do serviço, como aparece no label `service` das consultas.
78
+
79
+ Obrigatório de propósito: o `gyra-nest-boilerplate` rotula hoje
80
+ `service: 'gyra-credit-policy'` por cópia de arquivo, e todo serviço criado a
81
+ partir dele nasce logando sob o rótulo errado até alguém notar. Sendo
82
+ obrigatório no tipo, esse erro passa a ser falha de compilação.
83
+ */
84
+ service: string;
85
+
86
+ /*
87
+ Label `app`. Default `'saas'` porque é o que as consultas e dashboards
88
+ existentes usam (`{app="saas", service="gyra-x"}`) — mudar aqui quebra painel
89
+ em produção.
90
+ */
91
+ app?: string;
92
+
93
+ level?: string;
94
+
95
+ /*
96
+ Identidade da instância, para as réplicas não dividirem uma única stream. Sem
97
+ isso não há como investigar um pod específico nem comparar o volume dele com o
98
+ próprio stdout. Default é o hostname do processo, que no Kubernetes é o nome
99
+ do pod.
100
+ */
101
+ instance?: string;
102
+
103
+ /*
104
+ Formato legível para humano, com cor e indentação, em vez de JSON.
105
+
106
+ É `boolean` e não um nome de ambiente: substitui o
107
+ `process.env.ENVIRONMENT === 'DEVELOPMENT'` do código original, para o pacote
108
+ não precisar conhecer os nomes de ambiente da organização.
109
+ */
110
+ pretty?: boolean;
111
+
112
+ /*
113
+ A PRESENÇA deste objeto é o gate de envio — substitui o
114
+ `LOG_GRAFANA_LOKI === 'true'`. Ausente significa não enviar, e o pacote não
115
+ precisa parsear string booleana.
116
+
117
+ Cada chamada com `loki` constrói um transport NOVO. Serviço que monta mais de
118
+ um logger no mesmo processo deve usar `lokiTransport` — ver abaixo.
119
+ */
120
+ loki?: LokiOptions;
121
+
122
+ /*
123
+ Transport já construído, para COMPARTILHAR um único batcher entre vários
124
+ loggers do mesmo processo.
125
+
126
+ Isto não é conveniência, é correção. O worker do gyra-core monta quatro
127
+ loggers — um para a app e três para conexões RMQ. Com quatro transports
128
+ independentes há quatro batchers, e o `registerFatalHandlers` drena apenas o
129
+ que recebeu: as linhas bufferizadas nos outros três morrem com o processo, que
130
+ é exatamente o sintoma que a entrega confiável existe para impedir.
131
+
132
+ A fonte original resolvia isso com um singleton de módulo. Aqui a decisão fica
133
+ com o consumidor — ele chama `createLokiTransport` uma vez e passa o mesmo
134
+ transport para cada logger — sem estado global escondido no pacote.
135
+
136
+ Mutuamente exclusivo com `loki`.
137
+ */
138
+ lokiTransport?: LokiTransportLike;
139
+
140
+ /*
141
+ Transport de arquivo, usado quando não há Loki. Mantém a precedência do código
142
+ original: havendo `loki`, o arquivo é ignorado.
143
+ */
144
+ file?: FileOptions;
145
+ }
146
+
147
+ export const DEFAULT_APP_LABEL = 'saas';
148
+ export const DEFAULT_LEVEL = 'debug';
149
+
150
+ /* Curto de propósito — ver o comentário de `interval` acima. */
151
+ export const DEFAULT_LOKI_INTERVAL_SECONDS = 5;
152
+
153
+ export const DEFAULT_LOKI_TIMEOUT_MS = 60000;