Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Visualizando jobs do BigQuery com Stackdriver, Cloud Functions, Firebase e Pub/Sub

By Aviv LauferNov 8, 20174 min read

Esta página também está disponível em English, Deutsch, Español, Français, Italiano e 日本語.

1 bimx94i4agv23fzxumvs4a 2

Na DoiT International, usamos o Google BigQuery a fundo como plataforma de análise de dados do reOptimize (hoje parte do DoiT Cloud Intelligence™) — nossa plataforma de otimização de custos para o Google Cloud Platform.

O Google BigQuery é uma ferramenta serverless sensacional para consultar grandes volumes de dados com sintaxe SQL padrão. O modelo de cobrança leva em conta o volume de dados varrido em cada consulta, e dá para rodar até 50 queries simultâneas (queries em cache não entram na conta).

Se a sua organização tem várias equipes, você precisa de um jeito de saber o que está rodando agora. Não existe nada nativo para visualizar as queries em execução — e é aí que entra o bqtop para resolver o problema.

75cce 1qv99kz0h12i8ea5lc7rhrq

Queríamos um utilitário simples de linha de comando e também uma aplicação web para visualizar as queries em execução, além de parte do histórico. Para reunir as informações necessárias, montamos um pipeline 100% serverless que entrega esses dados para a nossa aplicação.

Vamos começar pelo lado do "servidor"

Primeiro, precisamos criar alguns Stackdriver Logs Sinks para exportar os logs do BigQuery para o Google Pub/Sub. Serão dois sinks: o primeiro filtra as mensagens de log que indicam o início de uma query:

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

e o segundo sink, para as queries concluídas:

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

Cada sink grava seus dados em um tópico diferente do Pub/Sub — bqtop-running-jobs e bqtop-finished-jobs.

Com os dados fluindo dos logs para o Pub/Sub, precisamos gravá-los em um banco de dados que possa ser lido depois pela web app ou pela cli. Para esse caso de uso, queríamos algo simples, mas robusto, que nos permitisse ler direto do cliente — assim, evitamos montar um backend completo — e que também enviasse notificações de dados novos ou atualizados, dispensando a necessidade de consultar o banco periodicamente em busca de atualizações. O Firebase do Google foi a escolha natural.

Para levar os dados do Pub/Sub até o banco do Firebase, usamos as Firebase Cloud Functions. Ficamos de olho em novos eventos nos tópicos do Pub/Sub e, na sequência, inserimos esses eventos no banco.

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

Os dados ficam em duas "tabelas" distintas: uma para jobs em execução e outra para tarefas concluídas. Quando um job termina, precisamos removê-lo da tabela de jobs em execução. Por fim, criamos algumas funções adicionais que ficam observando mudanças nos dados.

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

Quando chega um evento indicando um novo dado na referência de jobs concluídos, procuramos um evento com o mesmo jobId na referência de jobs em execução e o apagamos.

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

Para ganhar performance, criamos um índice (feito no arquivo database.rules.json)

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

E agora é a vez do "cliente"

Com o lado do "servidor" pronto, vamos para o cliente. Queríamos uma ferramenta de linha de comando para os Engineers e também uma web app para exibir na TV de dashboard do escritório.

O app de linha de comando é uma pequena aplicação em python que usa curses em toda a manipulação da UI. Como wrapper da API do Firebase, usamos o pyrebase. Como mencionamos acima, não queremos consultar o banco o tempo todo em busca de mudanças — preferimos receber uma notificação quando algo muda. Isso é feito por meio de duas streams do banco, acionadas a cada alteração.

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

Quando a função de handler é chamada, recuperamos os dados e os exibimos para o usuário.

Na web app, usamos o framework React e o Firebase Javascript SDK para ler os dados do banco e exibi-los na página.

Resumindo: montamos um pipeline bacana para enviar logs do BigQuery ao Google Pub/Sub, processá-los com Cloud Functions e, por fim, armazená-los no Firebase Realtime Database — sem precisar provisionar servidores e com pouquíssimo código.