InfluxDB
Coleta INFLUXDB e Entrega INFLUXDB_WRITE. Uma única Conexão Externa atende as três gerações do
produto — 1.8, 2.x e 3.x —, porque não são protocolos diferentes: é a mesma API HTTP, com endereços,
autenticação e linguagem de consulta próprios de cada versão.
| Versão | Linguagem padrão | Endereçamento | Autenticação |
|---|---|---|---|
| 1.8 | InfluxQL | database + retention policy | Token, ou usuário e senha |
| 2.x | Flux | organização + bucket | Token de API |
| 3.x | SQL | database | Token de API |
Marcar a versão errada na conexão é o erro de configuração mais comum aqui, e ele aparece como HTTP 404 em tudo — não como uma mensagem sobre versão. O Testar Conexão lê a versão real do servidor e a exibe no resultado, então use-o antes de investigar qualquer outra coisa.
Conexão
| Campo | Para que serve |
|---|---|
| URL do servidor | Raiz do servidor, sem caminho (ex.: http://influxdb:8086) |
| Versão | Define endereços da API, autenticação e linguagem padrão |
| Organização (org) | Só no 2.x. O token pertence a uma organização, e um nome errado responde 404 sem dizer que o problema é a org |
| Bucket padrão (2.x) / Database (1.8 e 3.x) | Destino padrão de leitura e escrita. Coleta e Entrega podem sobrepor este valor |
| Retention policy | Só no 1.8. Em branco usa a política padrão do database |
| Token de API | Obrigatório no 2.x e no 3.x. No 1.8, apenas se o servidor usa autenticação por token |
| Usuário / Senha | Só no 1.8. Vão como Basic — o CMS nunca usa os parâmetros ?u=&p=, que deixariam a senha no log de acesso do servidor |
| Validar certificado TLS / Certificado da CA | Mesma semântica das demais conexões: a CA só é necessária quando o certificado vem de uma CA interna |
| Consulta de teste (Keep Alive) | Opcional. Em branco, o Keep Alive só verifica se o servidor responde; preenchida, prova também que o bucket responde a leitura |
O Testar Conexão roda em três etapas, e cada uma falha por um motivo diferente: /ping valida
URL, TLS e rota (e devolve a versão do servidor); a listagem de buckets valida a credencial e a
existência do bucket configurado; a consulta de teste, se houver, prova a leitura.
Um token restrito a um único bucket — a configuração recomendada — não consegue listar os demais. O CMS trata isso como normal: a segunda etapa é pulada, e o resultado do teste diz que a listagem não estava disponível para aquela credencial.
Coleta
A Consulta roda no intervalo agendado e o resultado vira mensagens, com o mesmo Modo do Resultado das Coletas SQL (todas as linhas num payload, ou uma mensagem por linha).
Não existe aqui o par Coluna Chave + Comando Pós-Coleta das Coletas SQL: o InfluxDB não tem
“marcar linha como lida”. A varredura incremental se faz pela janela de tempo da própria
consulta — {{ultimaExecucao}} no início da janela faz cada execução continuar de onde a
anterior parou, sem repetir nem pular amostras.
// Flux (2.x) — {{bucket}} resolve para o bucket desta Coleta ou o padrão da conexão
from(bucket: "{{bucket}}")
|> range(start: {{ultimaExecucao}})
|> filter(fn: (r) => r._measurement == "producao")
|> filter(fn: (r) => r._field == "temperatura")-- InfluxQL (1.8) — a mesma ideia, no dialeto da versão
SELECT mean("temperatura") FROM "producao"
WHERE time > '{{ultimaExecucao}}' GROUP BY time(5m), "equipamento"Os placeholders disponíveis são os mesmos da Coleta HTTP: {{ultimaExecucao}}, {{dataHoraAtual}},
Variáveis e Parâmetros de Entrada, mais {{bucket}}. Não há bind variable em nenhuma das três
linguagens do InfluxDB — o valor é interpolado no texto da consulta, então trate um Parâmetro de
Entrada aqui como o que ele é: conteúdo que vai virar parte do comando.
Como o resultado vira JSON
Cada linha do resultado vira um objeto. No Flux, a resposta é o CSV anotado do próprio InfluxDB,
convertido usando os tipos declarados por ele — número volta como número, e o timestamp preserva os
nanossegundos (é texto ISO, não Date, justamente para não truncar). As colunas de controle do
protocolo (result, table) são descartadas.
{ "_time": "2026-08-22T12:00:00Z", "_value": 900.5, "_field": "temperatura", "equipamento": "forno-1" }Entrega
A Entrega grava pontos numa série. No InfluxDB o schema nasce da escrita: measurement, tags e fields passam a existir na primeira gravação — não há tabela a criar antes.
São dois modos:
Mapeado
O CMS monta o line protocol a partir dos campos do payload já transformado. Para cada campo você escolhe se ele é tag (metadado indexado, sempre texto, é por onde se filtra depois) ou field (o valor medido), e opcionalmente um nome diferente no destino.
Um payload que seja um array de objetos grava um ponto por item — é o caminho natural para um lote vindo de uma Coleta que emitiu várias linhas numa mensagem só.
O InfluxDB fixa o tipo de um field na primeira escrita. Gravar 10 como inteiro hoje faz
10.5 ser recusado amanhã com field type conflict, e corrigir isso exige reescrever a série.
Por isso o tipo Automático grava todo número como float; escolha Integer só quando tiver
certeza de que aquele field nunca terá parte fracionária.
Line Protocol
O conteúdo do Modelo de Conteúdo (ou, se ele estiver vazio, o próprio payload transformado) é gravado como veio. É a saída para formatos que o mapeamento não expressa — e, nele, o escape do line protocol passa a ser responsabilidade de quem escreveu o template.
producao,equipamento=forno-1,linha=L2 temperatura=900.5,pecas=12iTimestamp e precisão
| Origem | O que grava |
|---|---|
| Agora | O instante do envio |
| Campo do payload | Um campo da mensagem (ISO 8601 ou epoch inteiro na precisão configurada) — use quando o dado foi produzido antes de chegar ao CMS |
| Servidor | Nada: o InfluxDB carimba na ingestão |
Agora carimba o ponto com o relógio do CMS, mas a janela de uma consulta (range(start: -1h),
sem stop) termina no now() do servidor InfluxDB. Se o relógio do CMS estiver adiantado em
relação ao do InfluxDB, o ponto cai no futuro e some das consultas até o servidor alcançar aquele
instante — o dado está gravado, mas não aparece. Mantenha os dois relógios sincronizados por NTP;
onde isso não for possível, use o timestamp do Servidor.
Reduzir a precisão não descarta linhas, mas arredonda o instante — e duas amostras que caiam
no mesmo instante arredondado, com as mesmas tags, viram uma só: o InfluxDB sobrescreve por
measurement + tags + timestamp. Na dúvida, mantenha ns.
O que o CMS bloqueia na consulta
A Consulta da Coleta passa por um guard próprio, ao salvar e de novo antes de executar. O que ele barra depende da linguagem:
| Linguagem | Bloqueado |
|---|---|
| Flux | to() (grava de volta num bucket) e os pacotes de rede, SQL externo e segredos: http, requests, sql, secrets, slack, pagerduty e afins |
| InfluxQL | DELETE, DROP, CREATE, ALTER, GRANT, REVOKE, KILL, SET, SELECT ... INTO e múltiplos statements |
| SQL (3.x) | Todo DML, DDL e COPY (que grava arquivo no host do servidor); a consulta precisa começar por SELECT, WITH, SHOW, EXPLAIN ou DESCRIBE |
Texto dentro de aspas e comentários não conta: um measurement chamado http_requests ou uma coluna
delete_count passam normalmente.
Como nos bancos SQL, isto é defesa em profundidade. A proteção que de fato importa é a permissão do token usado na conexão: um token somente leitura, restrito ao bucket da integração, torna todo o resto redundante.
Ambiente de teste
O docker-compose.test.yml do projeto — o ambiente de teste, separado da stack do produto — traz
um InfluxDB 2.7 pronto para exercitar os dois lados, com dados de exemplo já carregados:
docker compose -f docker-compose.test.yml up -d influxdbNa Conexão Externa use http://host.docker.internal:8086 — endereço que vale tanto com o
cms-api em container quanto rodando nativo na máquina —, org cms, token
o valor de INFLUX_TOKEN no .env da raiz (gerado por ./scripts/instalar.sh), bucket cms_leitura para a Coleta e cms_escrita para a Entrega.