Pular para o conteúdo

Observabilidade: métricas e o guard de paridade Calcite

O Mondrian emite um pequeno conjunto de métricas OpenTelemetry para que você possa observar throughput de consulta, carga SQL, localidade de cache e — importante para o backend Calcite — quando o engine cai para SQL legado ou, com o guard de paridade ligado, quando os dois backends discordam.

Conectar um exporter

Os instrumentos resolvem contra o SDK OpenTelemetry global. Se sua implantação já configura o Java agent ou autoconfigure do OpenTelemetry (ex.: OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_METRICS_EXPORTER), as métricas do Mondrian fluem por ele sem setup extra. Se nenhum SDK estiver registrado, os instrumentos são no-ops — gravação é sempre segura e nunca lança.

Métricas

MétricaTipoSignificadoAtributos chave
mondrian.queries.executedcounterConsultas MDX completadasmondrian.query.outcome = success | failure
mondrian.query.durationhistogram (ms)latência por consulta MDXmesmo outcome
mondrian.sql.statementscounterStatements JDBC emitidosmondrian.sql.kind (segment-load / member-read / drillthrough / other)
mondrian.sql.durationhistogram (ms)latência por statement JDBCmesmo kind
mondrian.cache.segment.hitscounterrequisições de célula servidas do cache de segmento
mondrian.cache.segment.missescounterrequisições de célula que caíram em uma carga SQL
mondrian.calcite.fallbackcountertradução Calcite lançou → caiu para SQL legado…fallback.site, …fallback.exception
mondrian.calcite.divergencecounterguard de paridade achou que Calcite e legado discordaram…divergence.site, …divergence.detail

Uma razão alta de cache.segment.hits / misses significa boa localidade de cache. Um calcite.fallback não zero é esperado e benigno — conta casos onde o Calcite corretamente declinou um formato e o gerador legado assumiu. O counter para alertar é calcite.divergence.

O guard de paridade Calcite

O fallback baseado em exceção só pega “Calcite lançou.” Não consegue pegar a classe perigosa: SQL válido mas errado — uma tradução Calcite que roda sem erro mas retorna um resultado diferente do caminho legado. Essa divergência é invisível à rede de segurança de fallback e aparece apenas como um “sem dados” reportado por usuário ou um total errado.

O guard de paridade fecha esse gap. Quando habilitado, cada carga de segmento Calcite elegível também roda o SQL legado para a mesma carga e compara os dois row-sets JDBC. Um mismatch incrementa mondrian.calcite.divergence (com uma categoria detail de baixa cardinalidade — row-count / cell-value, nunca valores brutos) e loga um WARN.

Habilitar

Terminal window
# record divergences to telemetry + logs; still returns the Calcite result
-Dmondrian.calcite.parityCheck=true
# additionally hard-fail (throw) on any divergence — for CI / pre-prod gates
-Dmondrian.calcite.parityCheck.strict=true

Ambos default para off. Quando off, o único custo é uma única leitura booleana — não há overhead no caminho quente.

O que ele nunca faz (segurança)

O guard é deliberadamente pulado para duas classes de carga, então uma divergência gravada sempre significa um bug real de correção Calcite — nunca um falso alarme e nunca um risco de segurança:

  • Cargas predicate-secured. Um measure group protegido por um <PredicateGrant> nunca é comparado contra SQL legado — o gerador legado descarta o filtro de row-security, então rodá-lo vazaria linhas. Row security vence diagnósticos, sempre.
  • Agregações corretas apenas no Calcite. Grão distinto no nível da medida, median / percentile e bridge / fan-out simétrico são corretos por design no Calcite e diferentes do que o gerador legado computaria (ex.: uma medida de grão distinto retorna o 450 deduplicado onde um SUM legado ingênuo retornaria o 950 fanned-out). Compará-los gravaria uma falsa divergência, então são pulados.

Em outras palavras: mondrian.calcite.divergence > 0 é um alerta de alto sinal que um formato de consulta que deveria ser idêntico entre backends não é. Capture o contexto de carga do log WARN e arquive como bug de correção Calcite.

Alertas recomendados

  • Taxa de mondrian.calcite.divergence > 0 (quando o guard está habilitado em staging/CI) → bloqueie o release; um formato silenciosamente errado existe.
  • Taxa de mondrian.calcite.fallback em tendência de alta → um dialeto ou formato de schema que o Calcite parou de lidar; vale investigar por pushdown perdido, embora resultados permaneçam corretos.
  • cache.segment.misses em pico → churn de cache ou um cubo frio; considere cache warming.