Skip to main content
O Reporter é entregue como um binário único com duas superfícies. O RUN_MODE seleciona quais superfícies um processo atende, então a mesma imagem roda como a API, como o worker de relatórios, ou como os dois. Quatro dependências ficam atrás delas. O Reporter lê os seus bancos de dados por um motor de extração que roda dentro do processo worker. Não há um serviço de extração separado para implantar.

O que você implanta


Modos de execução


O RUN_MODE=api atende todas as operações REST, mais /health, /readyz e /version, no endereço definido em SERVER_ADDRESS. O RUN_MODE=worker consome a fila de comandos de relatório e atende /health e /readyz na HEALTH_PORT. O RUN_MODE=all roda as duas superfícies em um só processo. Use all para desenvolvimento local. Em produção, implante as duas superfícies em separado, para a geração de relatórios escalar por conta própria.

MongoDB


As duas superfícies usam a mesma implantação de MongoDB. A superfície de API grava templates, relatórios e prazos; o worker atualiza um relatório à medida que o conclui. Em modo single-tenant, MONGO_HOST e MONGO_NAME são obrigatórias na inicialização. Em modo multi-tenant, cada tenant recebe o próprio banco, resolvido a partir do JWT da requisição. Esse caminho falha de forma fechada: uma requisição que carrega um tenant sem banco de tenant retorna um erro em vez de tocar um banco compartilhado.

RabbitMQ


Dois assuntos distintos dividem um mesmo broker.

A fila de comandos de relatório

Essa fila leva o trabalho da superfície de API até o worker. RABBITMQ_EXCHANGE, RABBITMQ_GENERATE_REPORT_QUEUE e RABBITMQ_GENERATE_REPORT_KEY nomeiam o exchange, a fila e a routing key. A superfície de API publica, então precisa das três. O worker só consome, então precisa de RABBITMQ_GENERATE_REPORT_QUEUE sozinha. As duas superfícies precisam da conexão com o broker em si, e os objetos precisam existir antes de os serviços subirem. O canal é interno do Reporter. Para saber que um relatório terminou, assine os eventos de negócio abaixo, ou consulte o relatório. Um worker que falha uma mensagem tenta de novo até cinco vezes com backoff, e depois a rejeita sem reenfileirar. Ligue um dead-letter exchange à fila de comandos, para um relatório rejeitado cair em um lugar que você possa inspecionar.

O exchange de eventos

Os eventos de negócio (template.*, report.*, deadline.*) vão para um exchange que você nomeia em RABBITMQ_REPORT_EVENTS_EXCHANGE. O valor é definido pelo operador; reporter.events é o valor de referência. Defina esse exchange, STREAMING_BROKERS e STREAMING_CLOUDEVENTS_SOURCE sempre que STREAMING_ENABLED=true. Com o streaming desligado, as duas superfícies sobem normalmente e não publicam nada.

Object storage


O Reporter usa um único bucket compatível com S3, nomeado em OBJECT_STORAGE_BUCKET. Ele guarda dois tipos de objeto, cada um sob o seu próprio prefixo:
  • a fonte do template, como templates/<templateId>.tpl
  • o relatório renderizado, como reports/<templateId>/<reportId>.<format>
Em modo multi-tenant, os dois prefixos ficam sob o tenant dono do objeto: <tenantId>/templates/... e <tenantId>/reports/.... AWS S3, MinIO e SeaweedFS funcionam. Alcance o SeaweedFS pelo gateway S3 dele. OBJECT_STORAGE_USE_PATH_STYLE=true é o que MinIO e SeaweedFS esperam, e OBJECT_STORAGE_DISABLE_SSL fica em false fora do desenvolvimento local.

Retenção de relatórios

O Reporter guarda todo relatório que renderiza, então o bucket cresce com o seu volume de relatórios. Defina a expiração no bucket, com a política de ciclo de vida do próprio object storage, sobre a janela que as suas regras de retenção exigem.
Ancore a regra no prefixo de relatórios que o seu modo de tenancy produz. Em modo single-tenant, toda chave de relatório começa em reports/, então uma regra sobre esse prefixo cobre o bucket. Em modo multi-tenant, a chave carrega o tenant à frente, então a regra precisa do prefixo completo <tenantId>/reports/, uma regra por tenant. Deixe templates/ fora do alcance nos dois casos: uma regra que cobre o bucket inteiro também remove os templates a partir dos quais os seus relatórios são renderizados.

Redis ou Valkey


REDIS_HOST é obrigatória na superfície de API. No worker ela só é obrigatória quando MULTI_TENANT_ENABLED=true, onde faz cache da descoberta de tenants. O Redis sustenta a trava de idempotência na criação de relatórios, o cache de esquemas das fontes de dados e as mensagens de ciclo de vida de tenants em modo multi-tenant. O estado de idempotência vive no Redis, e não na memória do processo, então as réplicas de API o compartilham. A mesma requisição de relatório enviada duas vezes, para duas réplicas, cria um relatório só.

Fontes de dados


O Reporter lê os dados dos relatórios de fontes de dados PostgreSQL e MongoDB declaradas no ambiente, um bloco DATASOURCE_{NAME}_* por fonte. Veja Variáveis de ambiente para o bloco. Não existe uma API que registre uma fonte de dados, então uma fonte nova é uma mudança de configuração e um reinício. O Reporter também sobe sem nenhuma configurada, e atende templates, prazos e métricas.

Dimensionar o worker


RABBITMQ_NUMBERS_OF_WORKERS define quantos trabalhos de relatório um processo worker roda em paralelo. Para escala horizontal, adicione réplicas do worker e comande-as pela profundidade da fila de comandos. A saída em PDF é renderizada por um pool de navegador headless: PDF_POOL_WORKERS renderizações concorrentes, com padrão 2, cada uma limitada por PDF_TIMEOUT_SECONDS, com padrão 90. Dimensione a memória do worker contra esse pool, e não apenas contra as linhas que um relatório lê. Os demais formatos de saída não o usam. Todo relatório carrega também limites fixos de extração. Eles são 10 fontes de dados, 50 tabelas por fonte de dados e 200 campos por tabela, com 4 fontes de dados lidas por vez, um prazo de 300 segundos e um teto de 100 MiB de dados extraídos. As variáveis ENGINE_* mudam esses valores.

Modo de implantação e TLS


O DEPLOYMENT_MODE declara o sabor da implantação: local, byoc ou saas. Ele etiqueta a resposta de /readyz e, em saas, exige TLS.
O modo SaaS exige TLS em toda dependência. Defina DEPLOYMENT_MODE=saas e uma URL em texto claro de MongoDB, RabbitMQ, Redis, object storage ou Tenant Manager interrompe o processo. A parada ocorre antes de qualquer conexão abrir.
Deixe ALLOW_INSECURE_TLS sem definir em produção. Ela ignora essas checagens, e a stack de desenvolvimento local é o único lugar para ela.

Checagens de inicialização


O Reporter valida a configuração antes de atender qualquer coisa. Cada checagem abaixo interrompe o processo, e o erro nomeia todas as variáveis em falta.
Uma dependência fora do ar no boot não produz um pod quebrado em silêncio. O /health retorna 503 até a autossondagem de inicialização passar. O kubelet então reinicia o pod, em vez de mandar tráfego para ele.

Atualizações contínuas


Em SIGTERM, as duas superfícies entram em drenagem. O /readyz responde 503 desde o momento em que o sinal chega, antes de os servidores começarem o desligamento, e as requisições e mensagens em voo terminam. O Kubernetes remove o pod dos endpoints do Service enquanto ele ainda funciona. Defina o período de graça de término acima da sua renderização de relatório mais longa. Veja a referência de saúde e prontidão para o que as sondas reportam durante uma drenagem.

Próximos passos


Variáveis de ambiente

Cada variável do Reporter, por categoria.

Configuração BYOC

Os blocos de configuração que todo produto Lerian compartilha.

Saúde e prontidão

O contrato das sondas e o que cada resposta significa.

Conectar o Reporter ao Midaz

Aponte o Reporter para um banco do Midaz e renderize seu primeiro relatório.