Observabilidade de Dados: Uma Abordagem Prática

Observabilidade de Dados: Uma Abordagem Prática

7 de nov. de 2024

Sabemos da importância de implementar mecanismos de observabilidade de dados, neste artigo vamos cobrir uma forma rápida e simples de colocar isso em prática. E o melhor, mudando muito pouco sua stack ou fluxos de integração.

Vamos começar utilizando uma abordagem de arquitetura medalhão, onde temos várias camadas que apresentam os dados de mais brutos (em verde) até mais prontos para a análise (em laranja).

É legal entender que cada camada da arquitetura medalhão serve como um nível de segurança, uma espécie de divisão lógica do nosso ambiente analítico, dessa forma se um erro acontece em uma camada mais bruta, podemos impedir que as camadas dependentes apresentem o mesmo erro. Pensando em um caso prático: se tivermos um erro na ETL, é melhor que o seu dashboard não apresente os dados de hoje do que não apresentar nenhuma informação.


Uma ótima forma de implementar a modelagem de dados, seguindo a arquitetura medalhão, é o DBT core. Este projeto coloca a nossa disposição uma série de ferramentas que aceleram o processo de desenvolvimento, como modelos de dados que podem ser materializados em formatos diferentes, um conjunto grande de customização de funções, documentação, linhagem de dados e várias formas de realizar testes sobre nossos dados, esta última funcionalidade é o que vamos explorar neste artigo.

Existem duas principais formas que podemos definir testes de dados no DBT, a primeira é chamada de testes de dados singulares, e nada mais é do que uma consulta SQL que retorna registros errados do ponto de vista do nosso teste (se o retorno for vazio, o teste passa). Para implementar um teste deste tipo, basta criar um arquivo no diretório de testes do projeto DBT, como o exemplo a seguir que testa vendas com valor total positivo:

-- ./testes/validar_valor_total_positivo.sql
select
    venda_id,
    sum(valor) as valor_total
from {{ ref('fct_vendas' )}}
group by 1
having valor_total < 0

Entretanto existem testes de dados que podem ser feitos em vários modelos diferentes certo? Para lidar com isso temos os testes genéricos, que são criados utilizando jinja em um formato semelhante a criação de macros, a implementação de um teste de nulos seria assim:

{% test nao_nulo(tabela, coluna) %}

    select *
    from {{ tabela }}
    where {{ coluna }} is null

{% endtest %}

Para este teste ser executado para o modelo e coluna que desejamos, é necessário fazer a inclusão no YML de schema do projeto, para testarmos se existem registros de vendas com identificador (venda_id) sendo nulo teríamos que implementar algo como:

version: 2

models:
  - name: fct_vendas
    columns:
      - name: venda_id
        tests

Por fim utilizamos o comando a seguir para fazer as validações dos testes configurados no projeto.

Quero ressaltar que pensar em cada caso de uso para teste de dados pode dar uma trabalheira danada, e muitas vezes quando eu implementei testes com DBT fiquei com a sensação de estar reinventando a roda. Para lidar com isso, sugiro a utilização do pacote dbt_expectations, que justamente traz o poder de observabilidade de dados do Great Expectations para a praticidade do DBT.

Para fazer isso, basta adicionar o pacote no arquivo packages.yml do projeto dbt:

packages:
  -

Agora temos a disposição um grande número de testes genéricos para diferentes cenários, como:

  • Formatos de tabela;

  • Tipos de dados, valores nulos e únicos;

  • Valores dentro de intervalos ou conjuntos;

  • Funções de agregação;

  • multiplas colunas;

  • Funções de distribuição;

  • Comparação de strings.

O mais bacana é que utilizamos exatamente da mesma forma que fazemos uso dos testes genéricos, basta declarar no YML de schema o teste a ser realizado para a coluna desejada. O teste de valor nulo que fizemos anteriormente pode ser implementado da seguinte forma:

version: 2

models:
  - name: fct_vendas
    columns:
      - name: venda_id
        tests

Para ter mais detalhes sobre quais testes podem ser utilizados, sugiro ver a documentação do dbt_expectations.

Sabemos da importância de implementar mecanismos de observabilidade de dados, neste artigo vamos cobrir uma forma rápida e simples de colocar isso em prática. E o melhor, mudando muito pouco sua stack ou fluxos de integração.

Vamos começar utilizando uma abordagem de arquitetura medalhão, onde temos várias camadas que apresentam os dados de mais brutos (em verde) até mais prontos para a análise (em laranja).

É legal entender que cada camada da arquitetura medalhão serve como um nível de segurança, uma espécie de divisão lógica do nosso ambiente analítico, dessa forma se um erro acontece em uma camada mais bruta, podemos impedir que as camadas dependentes apresentem o mesmo erro. Pensando em um caso prático: se tivermos um erro na ETL, é melhor que o seu dashboard não apresente os dados de hoje do que não apresentar nenhuma informação.


Uma ótima forma de implementar a modelagem de dados, seguindo a arquitetura medalhão, é o DBT core. Este projeto coloca a nossa disposição uma série de ferramentas que aceleram o processo de desenvolvimento, como modelos de dados que podem ser materializados em formatos diferentes, um conjunto grande de customização de funções, documentação, linhagem de dados e várias formas de realizar testes sobre nossos dados, esta última funcionalidade é o que vamos explorar neste artigo.

Existem duas principais formas que podemos definir testes de dados no DBT, a primeira é chamada de testes de dados singulares, e nada mais é do que uma consulta SQL que retorna registros errados do ponto de vista do nosso teste (se o retorno for vazio, o teste passa). Para implementar um teste deste tipo, basta criar um arquivo no diretório de testes do projeto DBT, como o exemplo a seguir que testa vendas com valor total positivo:

-- ./testes/validar_valor_total_positivo.sql
select
    venda_id,
    sum(valor) as valor_total
from {{ ref('fct_vendas' )}}
group by 1
having valor_total < 0

Entretanto existem testes de dados que podem ser feitos em vários modelos diferentes certo? Para lidar com isso temos os testes genéricos, que são criados utilizando jinja em um formato semelhante a criação de macros, a implementação de um teste de nulos seria assim:

{% test nao_nulo(tabela, coluna) %}

    select *
    from {{ tabela }}
    where {{ coluna }} is null

{% endtest %}

Para este teste ser executado para o modelo e coluna que desejamos, é necessário fazer a inclusão no YML de schema do projeto, para testarmos se existem registros de vendas com identificador (venda_id) sendo nulo teríamos que implementar algo como:

version: 2

models:
  - name: fct_vendas
    columns:
      - name: venda_id
        tests

Por fim utilizamos o comando a seguir para fazer as validações dos testes configurados no projeto.

Quero ressaltar que pensar em cada caso de uso para teste de dados pode dar uma trabalheira danada, e muitas vezes quando eu implementei testes com DBT fiquei com a sensação de estar reinventando a roda. Para lidar com isso, sugiro a utilização do pacote dbt_expectations, que justamente traz o poder de observabilidade de dados do Great Expectations para a praticidade do DBT.

Para fazer isso, basta adicionar o pacote no arquivo packages.yml do projeto dbt:

packages:
  -

Agora temos a disposição um grande número de testes genéricos para diferentes cenários, como:

  • Formatos de tabela;

  • Tipos de dados, valores nulos e únicos;

  • Valores dentro de intervalos ou conjuntos;

  • Funções de agregação;

  • multiplas colunas;

  • Funções de distribuição;

  • Comparação de strings.

O mais bacana é que utilizamos exatamente da mesma forma que fazemos uso dos testes genéricos, basta declarar no YML de schema o teste a ser realizado para a coluna desejada. O teste de valor nulo que fizemos anteriormente pode ser implementado da seguinte forma:

version: 2

models:
  - name: fct_vendas
    columns:
      - name: venda_id
        tests

Para ter mais detalhes sobre quais testes podem ser utilizados, sugiro ver a documentação do dbt_expectations.

Sabemos da importância de implementar mecanismos de observabilidade de dados, neste artigo vamos cobrir uma forma rápida e simples de colocar isso em prática. E o melhor, mudando muito pouco sua stack ou fluxos de integração.

Vamos começar utilizando uma abordagem de arquitetura medalhão, onde temos várias camadas que apresentam os dados de mais brutos (em verde) até mais prontos para a análise (em laranja).

É legal entender que cada camada da arquitetura medalhão serve como um nível de segurança, uma espécie de divisão lógica do nosso ambiente analítico, dessa forma se um erro acontece em uma camada mais bruta, podemos impedir que as camadas dependentes apresentem o mesmo erro. Pensando em um caso prático: se tivermos um erro na ETL, é melhor que o seu dashboard não apresente os dados de hoje do que não apresentar nenhuma informação.


Uma ótima forma de implementar a modelagem de dados, seguindo a arquitetura medalhão, é o DBT core. Este projeto coloca a nossa disposição uma série de ferramentas que aceleram o processo de desenvolvimento, como modelos de dados que podem ser materializados em formatos diferentes, um conjunto grande de customização de funções, documentação, linhagem de dados e várias formas de realizar testes sobre nossos dados, esta última funcionalidade é o que vamos explorar neste artigo.

Existem duas principais formas que podemos definir testes de dados no DBT, a primeira é chamada de testes de dados singulares, e nada mais é do que uma consulta SQL que retorna registros errados do ponto de vista do nosso teste (se o retorno for vazio, o teste passa). Para implementar um teste deste tipo, basta criar um arquivo no diretório de testes do projeto DBT, como o exemplo a seguir que testa vendas com valor total positivo:

-- ./testes/validar_valor_total_positivo.sql
select
    venda_id,
    sum(valor) as valor_total
from {{ ref('fct_vendas' )}}
group by 1
having valor_total < 0

Entretanto existem testes de dados que podem ser feitos em vários modelos diferentes certo? Para lidar com isso temos os testes genéricos, que são criados utilizando jinja em um formato semelhante a criação de macros, a implementação de um teste de nulos seria assim:

{% test nao_nulo(tabela, coluna) %}

    select *
    from {{ tabela }}
    where {{ coluna }} is null

{% endtest %}

Para este teste ser executado para o modelo e coluna que desejamos, é necessário fazer a inclusão no YML de schema do projeto, para testarmos se existem registros de vendas com identificador (venda_id) sendo nulo teríamos que implementar algo como:

version: 2

models:
  - name: fct_vendas
    columns:
      - name: venda_id
        tests

Por fim utilizamos o comando a seguir para fazer as validações dos testes configurados no projeto.

Quero ressaltar que pensar em cada caso de uso para teste de dados pode dar uma trabalheira danada, e muitas vezes quando eu implementei testes com DBT fiquei com a sensação de estar reinventando a roda. Para lidar com isso, sugiro a utilização do pacote dbt_expectations, que justamente traz o poder de observabilidade de dados do Great Expectations para a praticidade do DBT.

Para fazer isso, basta adicionar o pacote no arquivo packages.yml do projeto dbt:

packages:
  -

Agora temos a disposição um grande número de testes genéricos para diferentes cenários, como:

  • Formatos de tabela;

  • Tipos de dados, valores nulos e únicos;

  • Valores dentro de intervalos ou conjuntos;

  • Funções de agregação;

  • multiplas colunas;

  • Funções de distribuição;

  • Comparação de strings.

O mais bacana é que utilizamos exatamente da mesma forma que fazemos uso dos testes genéricos, basta declarar no YML de schema o teste a ser realizado para a coluna desejada. O teste de valor nulo que fizemos anteriormente pode ser implementado da seguinte forma:

version: 2

models:
  - name: fct_vendas
    columns:
      - name: venda_id
        tests

Para ter mais detalhes sobre quais testes podem ser utilizados, sugiro ver a documentação do dbt_expectations.

Sabemos da importância de implementar mecanismos de observabilidade de dados, neste artigo vamos cobrir uma forma rápida e simples de colocar isso em prática. E o melhor, mudando muito pouco sua stack ou fluxos de integração.

Vamos começar utilizando uma abordagem de arquitetura medalhão, onde temos várias camadas que apresentam os dados de mais brutos (em verde) até mais prontos para a análise (em laranja).

É legal entender que cada camada da arquitetura medalhão serve como um nível de segurança, uma espécie de divisão lógica do nosso ambiente analítico, dessa forma se um erro acontece em uma camada mais bruta, podemos impedir que as camadas dependentes apresentem o mesmo erro. Pensando em um caso prático: se tivermos um erro na ETL, é melhor que o seu dashboard não apresente os dados de hoje do que não apresentar nenhuma informação.


Uma ótima forma de implementar a modelagem de dados, seguindo a arquitetura medalhão, é o DBT core. Este projeto coloca a nossa disposição uma série de ferramentas que aceleram o processo de desenvolvimento, como modelos de dados que podem ser materializados em formatos diferentes, um conjunto grande de customização de funções, documentação, linhagem de dados e várias formas de realizar testes sobre nossos dados, esta última funcionalidade é o que vamos explorar neste artigo.

Existem duas principais formas que podemos definir testes de dados no DBT, a primeira é chamada de testes de dados singulares, e nada mais é do que uma consulta SQL que retorna registros errados do ponto de vista do nosso teste (se o retorno for vazio, o teste passa). Para implementar um teste deste tipo, basta criar um arquivo no diretório de testes do projeto DBT, como o exemplo a seguir que testa vendas com valor total positivo:

-- ./testes/validar_valor_total_positivo.sql
select
    venda_id,
    sum(valor) as valor_total
from {{ ref('fct_vendas' )}}
group by 1
having valor_total < 0

Entretanto existem testes de dados que podem ser feitos em vários modelos diferentes certo? Para lidar com isso temos os testes genéricos, que são criados utilizando jinja em um formato semelhante a criação de macros, a implementação de um teste de nulos seria assim:

{% test nao_nulo(tabela, coluna) %}

    select *
    from {{ tabela }}
    where {{ coluna }} is null

{% endtest %}

Para este teste ser executado para o modelo e coluna que desejamos, é necessário fazer a inclusão no YML de schema do projeto, para testarmos se existem registros de vendas com identificador (venda_id) sendo nulo teríamos que implementar algo como:

version: 2

models:
  - name: fct_vendas
    columns:
      - name: venda_id
        tests

Por fim utilizamos o comando a seguir para fazer as validações dos testes configurados no projeto.

Quero ressaltar que pensar em cada caso de uso para teste de dados pode dar uma trabalheira danada, e muitas vezes quando eu implementei testes com DBT fiquei com a sensação de estar reinventando a roda. Para lidar com isso, sugiro a utilização do pacote dbt_expectations, que justamente traz o poder de observabilidade de dados do Great Expectations para a praticidade do DBT.

Para fazer isso, basta adicionar o pacote no arquivo packages.yml do projeto dbt:

packages:
  -

Agora temos a disposição um grande número de testes genéricos para diferentes cenários, como:

  • Formatos de tabela;

  • Tipos de dados, valores nulos e únicos;

  • Valores dentro de intervalos ou conjuntos;

  • Funções de agregação;

  • multiplas colunas;

  • Funções de distribuição;

  • Comparação de strings.

O mais bacana é que utilizamos exatamente da mesma forma que fazemos uso dos testes genéricos, basta declarar no YML de schema o teste a ser realizado para a coluna desejada. O teste de valor nulo que fizemos anteriormente pode ser implementado da seguinte forma:

version: 2

models:
  - name: fct_vendas
    columns:
      - name: venda_id
        tests

Para ter mais detalhes sobre quais testes podem ser utilizados, sugiro ver a documentação do dbt_expectations.

Conheça a Erathos, a melhor plataforma de movimentação de dados da LATAM.

Conheça a Erathos, a melhor plataforma de movimentação de dados da LATAM.