Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Visualiza jobs de BigQuery con Stackdriver, Cloud Functions, Firebase y Pub/Sub

By Aviv LauferNov 8, 20174 min read

Esta página también está disponible en English, Deutsch, Français, Italiano, 日本語 y Português.

1 bimx94i4agv23fzxumvs4a 2

En DoiT International usamos Google BigQuery a fondo como plataforma de análisis de datos para reOptimize (hoy parte de DoiT Cloud Intelligence™), nuestra plataforma de optimización de costos para Google Cloud Platform.

Google BigQuery es una herramienta serverless excelente para consultar grandes volúmenes de datos con sintaxis SQL estándar. El modelo de precios se basa en la cantidad de datos que se escanean en cada consulta, y se pueden ejecutar hasta 50 consultas en simultáneo (las consultas en caché no cuentan).

Si tienes varios equipos en tu organización, necesitas una forma de saber qué se está ejecutando en cada momento. No hay una forma nativa de ver las consultas en curso, y ahí es donde entra bqtop al rescate.

75cce 1qv99kz0h12i8ea5lc7rhrq

Queríamos armar tanto una utilidad sencilla de línea de comandos como una aplicación web que nos permitiera ver las consultas en ejecución y parte del historial. Para conseguir esa información montamos un pipeline totalmente serverless que la pone a disposición de nuestra aplicación.

Empecemos por el lado del "servidor"

Primero hay que crear un par de Stackdriver Logs Sinks para exportar los logs de BigQuery a Google Pub/Sub. Vamos a crear dos sinks: el primero filtra los mensajes de log que indican el inicio de una consulta:

resource.type=bigquery_resource protoPayload.methodName=jobservice.insert

y el segundo, para las consultas finalizadas:

resource.type=bigquery_resource protoPayload.methodName=jobservice.jobcompleted

Cada sink escribe sus datos en un topic distinto de Pub/Sub: bqtop-running-jobs y bqtop-finished-jobs.

Ahora que los datos fluyen desde los logs hacia Pub/Sub, hay que escribirlos en una base de datos que luego se pueda leer desde la aplicación web o el cli. Para este caso queríamos algo simple pero potente, que nos permitiera leer directamente desde el cliente (y así evitar levantar un backend completo) y que además notificara cuando hubiera datos nuevos o actualizados, para no tener que consultar la base de datos cada cierto tiempo. Firebase de Google nos pareció la elección natural.

Para llevar los datos de Pub/Sub a la base de datos de Firebase usamos Firebase Cloud Functions. Escuchamos los eventos nuevos en los topics de Pub/Sub y los insertamos en la base de datos.

https://gist.github.com/avivl/30d92a579abd48dd4b3a9131b7f6abfb

Los datos se guardan en dos "tablas" distintas: una para los jobs en ejecución y otra para las tareas finalizadas. Cuando un job termina, hay que eliminarlo de la tabla de jobs en ejecución. Para cerrar, sumamos un par de funciones adicionales que escuchan los cambios en los datos.

https://gist.github.com/avivl/58dbe67e6ade2b45f89e5a5d698c3dd3

Cuando llega un evento que indica que hay nuevos datos en la referencia de jobs finalizados, buscamos el evento con el mismo jobId en la referencia de jobs en ejecución y lo eliminamos.

https://gist.github.com/avivl/c16af302a09a338f41480a11689a10d9

Para mejorar el rendimiento creamos un índice (esto se hace en el archivo database.rules.json).

https://gist.github.com/avivl/7ab33806e5d8da4caf62b9a57778433a

Y ahora, el turno del "cliente"

Listo el lado del "servidor", pasemos al cliente. Queríamos tener tanto una herramienta de línea de comandos para los Engineers como una aplicación web para mostrar en el dashboard de la TV de la oficina.

La app de línea de comandos es una pequeña aplicación en Python que usa curses para toda la manipulación de la UI. Usamos pyrebase como wrapper de la API de Firebase. Como mencionamos arriba, no queremos estar consultando la base de datos en busca de cambios todo el tiempo, sino recibir una notificación cuando algo cambia. Esto se logra con dos streams de la base de datos que se disparan ante cualquier cambio.

https://gist.github.com/avivl/8ea27a7f98feb1d8735151ae3ba97bff

Cuando se invoca la función handler, recuperamos los datos y se los mostramos al usuario.

Para la aplicación web usamos el framework React y el SDK de Firebase para JavaScript, con el fin de leer los datos de la base de datos y visualizarlos en la página.

En resumen, montamos un pipeline buenísimo para enviar logs de BigQuery a Google Pub/Sub, procesarlos con Cloud Functions y guardarlos en Firebase Realtime Database, sin desplegar un solo servidor y con un esfuerzo de código mínimo.