Observabilidad: métricas y el guard de paridad de Calcite
Mondrian emite un pequeño conjunto de métricas de OpenTelemetry para que pueda observar el rendimiento de consultas, la carga SQL, la localidad de caché y — importante para el backend de Calcite — cuándo el motor cae a SQL heredado o, con el guard de paridad activo, cuándo los dos backends no coinciden.
Conectar un exporter
Los instrumentos se resuelven contra el SDK global de OpenTelemetry. Si su despliegue ya configura el agente Java de OpenTelemetry o autoconfigure (por ejemplo, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_METRICS_EXPORTER), las métricas de Mondrian fluyen a través de él sin configuración adicional. Si no hay SDK registrado, los instrumentos son no-ops — registrar es siempre seguro y nunca lanza.
Métricas
| Métrica | Tipo | Significado | Atributos clave |
|---|---|---|---|
mondrian.queries.executed | contador | Consultas MDX completadas | mondrian.query.outcome = success | failure |
mondrian.query.duration | histograma (ms) | latencia por consulta MDX | mismo outcome |
mondrian.sql.statements | contador | Sentencias JDBC emitidas | mondrian.sql.kind (segment-load / member-read / drillthrough / other) |
mondrian.sql.duration | histograma (ms) | latencia por sentencia JDBC | mismo kind |
mondrian.cache.segment.hits | contador | peticiones de celda servidas desde la caché de segmentos | — |
mondrian.cache.segment.misses | contador | peticiones de celda que cayeron a una carga SQL | — |
mondrian.calcite.fallback | contador | La traducción de Calcite lanzó → cayó a SQL heredado | …fallback.site, …fallback.exception |
mondrian.calcite.divergence | contador | el guard de paridad encontró que Calcite y heredado no coincidieron | …divergence.site, …divergence.detail |
Una alta razón cache.segment.hits / misses significa buena localidad de caché. Un calcite.fallback distinto de cero es esperable y benigno — cuenta casos donde Calcite declinó correctamente una forma y el generador heredado tomó el relevo. El contador sobre el que alertar es calcite.divergence.
El guard de paridad de Calcite
El fallback basado en excepciones solo captura “Calcite lanzó.” No puede capturar la clase peligrosa: SQL válido pero incorrecto — una traducción de Calcite que se ejecuta sin error pero devuelve un resultado diferente al de la ruta heredada. Esa divergencia es invisible para la red de seguridad del fallback y solo aparece como un “sin datos” reportado por el usuario o un total incorrecto.
El guard de paridad cierra ese hueco. Cuando está habilitado, cada carga de segmento elegible de Calcite también ejecuta el SQL heredado para la misma carga y compara los dos conjuntos de filas JDBC. Una discrepancia incrementa mondrian.calcite.divergence (con una categoría detail de baja cardinalidad — row-count / cell-value, nunca valores crudos) y registra un WARN.
Habilitarlo
# 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=trueAmbos por defecto están desactivados. Cuando están desactivados, el único coste es una lectura de un booleano — no hay sobrecarga en la ruta caliente.
Lo que nunca hace (seguridad)
El guard se omite deliberadamente para dos clases de carga, para que una divergencia registrada siempre signifique un bug real de corrección de Calcite — nunca una falsa alarma y nunca un riesgo de seguridad:
- Cargas aseguradas por predicado. Un grupo de medidas protegido por un
<PredicateGrant>nunca se compara contra SQL heredado — el generador heredado descarta el filtro de seguridad de fila, así que ejecutarlo filtraría filas. La seguridad de fila gana sobre los diagnósticos, siempre. - Agregaciones solo correctas en Calcite. La granularidad distinct a nivel de medida, la mediana / percentil y el fan-out de puente / simétrico son correctos por diseño en Calcite y diferentes de lo que computaría el generador heredado (por ejemplo, una medida de granularidad distinct devuelve los 450 deduplicados donde un
SUMheredado ingenuo devolvería los 950 expandidos). Compararlos registraría una falsa divergencia, así que se omiten.
En otras palabras: mondrian.calcite.divergence > 0 es una alerta de alta señal de que una forma de consulta que debería ser idéntica en todos los backends no lo es. Capture el contexto de carga del log WARN y archívelo como un bug de corrección de Calcite.
Alertas recomendadas
- Tasa de
mondrian.calcite.divergence> 0 (cuando el guard está habilitado en staging/CI) → bloquee la release; existe una forma silenciosa con resultado incorrecto. - Tasa de
mondrian.calcite.fallbackcon tendencia al alza → un dialecto o forma de schema que Calcite dejó de gestionar; vale la pena investigar la pérdida de pushdown, aunque los resultados siguen siendo correctos. - Picos de
cache.segment.misses→ caché batida o un cubo frío; considere el calentamiento de caché.