Criando um monitor de logs em Go - parte 1
Vítor Roque
Posted on April 20, 2023
Esse é um post onde vou mostrar como eu desenvolvi esse monitor de logs, que você pode estar acompanhando nesse repositório.
Protocolo AWO e Parser
Eu precisava de uma estrutura para esse protocolo, como seria uma aplicação que muitas apps podem utilizar essa estrutura precisava de um padrão. Segue um exemplo:
LOG abc@123 AWO1.1
02:30:22
This is my LOG message content!
Como todo protocolo em cima do TCP, tudo isso é um texto, então eu precisava converte-lo em alguma estrutura.
Em Go, criei um parser para tratar todo tipo de mensagem que enviarem para a aplicação. Caso ele não siga esse padrão, um erro deve ser gerado.
type Log struct {
Header Header
Timer string
Message string
}
type Header struct {
Verb, AppKey, Version string
}
Essas estruturas serão a base da mensagem, onde Header tem sua verificação, pois se algo estiver errado antes da validação, não queremos receber a mensagem.
Validando o Header
Precisamos também criar um construtor para esse Header.
func NewHeader(head string) (Header, error) {
parts := strings.Split(head, " ")
if len(parts) != 3 {
return Header{}, errors.New("malformed header")
}
verb := parts[0]
app_key := parts[1]
version := parts[2]
return Header{Verb: verb, AppKey: app_key, Version: version}, nil
}
Aqui apenas divido o header em 3 pelo whitespace, e caso ele venha mais ou venha menos partes, ele está errado. Aqui também poderia adicionar alguma forma de validação da app_key
ou se o verb
não faz parte dos verbos do protocolo que estamos criando (o que implementarei mais para frente).
Criando a função Parse
Agora que tenho o Header com sua validação preciso transformar a mensagem numa estrutura.
func Parse(packet string) (Log, error) {
parts := strings.Split(packet, "\n")
if len(parts) != 3 {
return Log{}, errors.New("malformed packet")
}
header, header_error := NewHeader(parts[0])
if header_error != nil {
return Log{}, header_error
}
timer := parts[1]
if timer == "" {
return Log{}, errors.New("timer is empty")
}
message := parts[2]
return Log{
Header: header,
Timer: timer,
Message: message,
}, nil
}
Esse parser irá validar se a mensagem tem também 3 partes, pois só tenho a estrutura: Header, Timer e Message. Então caso não siga isso, irei trata-lo como inválido.
Logo depois crio o Header e também checo se o timer
está vazio ou não, pois preciso do tempo que esse log chegou na aplicação.
Por fim, coloco ele numa estrutura Log como já definido e o retorno.
Na próxima publicação sobre esse projeto irei abordar como criei o sistema de regras para a monitoração customizada usando o Oluwoye.
O ṣeun, e até a próxima!
Posted on April 20, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.