DEV Community

Cover image for Criando um servidor de tracing distribuído (parte 1)
Vítor Roque
Vítor Roque

Posted on • Updated on

Criando um servidor de tracing distribuído (parte 1)

Em Haskell tudo começa pelas tipagens e dados que você precisa. Primeiramente certifique-se que tenha instalado o cabal ou stack para criar projetos em Haskell.

Criando projeto

Para criar o projeto é simples

$ cabal init -n tracer
Enter fullscreen mode Exit fullscreen mode

O cabal irá criar um projeto de modo interativo (bem como o npm init).

Tipos e dados

Primeiro precisamos definir o que será cada coisa, os componentes e a implementação.

Na estrutura temos o que chamaremos de ISO ou EDIO (Estrutura de instrumentação da observabilidade) que é nada mais que um mapa chave-valor, onde a chave é a ação originária e o valor é a uma lista de ações possíveis (ou ações alvos possíveis).

module Instrumentation () where

newtype ISO = ISO [(String, [String])] deriving (Eq, Show)
Enter fullscreen mode Exit fullscreen mode

O Map, bem utilizado em outras linguagens, se resume a uma lista de tuplas com apenas 2 valores, a chave e o valor em si. E pra isso teremos que criar algumas funções auxiliares para inserir, procurar ou deletar entradas nesse mapa.

Funções auxiliares

No caso, por agora, precisamos ter uma função para criar um ISO vazio e um para inserir.

newISO :: ISO
newISO = ISO []
Enter fullscreen mode Exit fullscreen mode

A função de criação é bem simples pois só precisamos ter uma função que usa o método construtor ISO com uma lista vazia.

insert :: (String, [String]) -> ISO -> ISO
insert (key, value) (ISO items) = ISO newIso
  where
    newIso = items ++ [(key, value)]
Enter fullscreen mode Exit fullscreen mode

A função de inserção seria apenas a concatenação da lista anterior com uma lista nova. Em Haskell, podemos ter N formas de criar essa função, usei a notação where, pois ela nos dá uma forma mais fácil de compreender o que é cada parte da função. Nesse caso eu separei a concatenação de listas numa variável desse where para facilitar a legibilidade da função em si.

Testes, pois sem testes não viveríamos

Em Haskell, testes são feitos por, acredite ou não, funções! Essas funções podem ser escritas de várias maneiras mas aqui usarei o mais comum na comunidade, que é o HUnit.

Primeiro nós instalamos o HUnit pelo cabal.

$ cabal install --lib HUnit
Enter fullscreen mode Exit fullscreen mode

E precisamos alterar no nosso arquivo tracer.cabal

test-suite tracer-test
    import:           warnings
    default-language: Haskell2010
    type:             exitcode-stdio-1.0
    hs-source-dirs:   test
    main-is:          Main.hs
    other-modules:    InstrumentationTest -- novo
    build-depends:
        base ^>=4.18.0.0,
        tracer,
        HUnit -- novo
Enter fullscreen mode Exit fullscreen mode

Nesse arquivo adicionamos um novo módulo além do Main que o cabal cria para nós, e o que depende do build desse teste.

Teste da estrutura ISO

Com isso precisamos criar os testes nesse arquivo test/InstrumentationTest.hs

module InstrumentationTest () where

import Instrumentation (ISO (..), insert, newISO)
import Test.HUnit

createNewISOTest :: Test
createNewISOTest = TestCase (assertEqual "should return empty ISO" (ISO [] newISO)

insertEntryTest :: Test
insertEntryTest = TestCase (assertEqual "should return a ISO with entry" desired appliedFunction)
   where
     desired = ISO [("chave", ["valor1"])]
     appliedFunction = insert ("chave", ["valor1"]) newISO
Enter fullscreen mode Exit fullscreen mode

Nesse arquivo criamos tanto o teste para checar a criação de uma nova ISO e a inserção de uma entrada. E agora precisamos colocar ele no arquivo test/Main.hs

module Main (main) where

import Test.HUnit
import InstrumentationTest (createNewISOTest, insertEntryTest)
import qualified System.Exit as Exit

tests :: Test
tests = TestList [TestLabel "createNewISO" createNewISOTest, TestLabel "insertEntryTest" insertEntryTest]

main :: IO ()
main = do
  result <- runTestTT tests
  if failures result > 0 then Exit.exitFailure else Exit.exitSuccess
Enter fullscreen mode Exit fullscreen mode

Nesse arquivo nós criamos uma suite de testes para que ele rode todos os testes do módulo InstrumentationTest

Para rodar os testes apenas rodamos

$ cabal test
Enter fullscreen mode Exit fullscreen mode

E ele terá um resultado parecido com esse (além dos logs de build)

Test suite eyaara-test: RUNNING...
Cases: 2  Tried: 2  Errors: 0  Failures: 0
Test suite tracer-test: PASS
Enter fullscreen mode Exit fullscreen mode

E por hoje é só! Nessa série de artigos eu irei recriar o sistema e estrutura que desenvolvi baseado no algoritmo Drain para parsing de logs.

O ṣeun! 👋🏾

Top comments (2)

Collapse
 
cherryramatis profile image
Cherry Ramatis

O primeiro artigo direto ao ponto que vejo sobre haskell, muito foda! Vlw pelo conteúdo

Collapse
 
rohlacanna profile image
Rômulo Silva

Conteúdo incrível, Roque! Parabéns mano! 💯