Pular para o conteúdo principal
Versão: Next

Observabilidade

O pacote fornece uma camada completa de observabilidade para aplicações, integrando métricas, rastreamento (tracing) e logs. A implementação encapsula o OpenTelemetry, oferecendo recursos para monitoramento de transações, segmentos, erros e métricas personalizadas.

Configuração

A configuração é realizada automaticamente ao iniciar o colibri-sdk-go. Para exportar os dados para um coletor OpenTelemetry, utilize as seguintes variáveis de ambiente:

VariávelObrigatóriaDescrição
OTEL_EXPORTER_OTLP_ENDPOINTSimEndpoint do coletor OTLP — aceita host:porta ou URL completa (ex: http://localhost:4318)
OTEL_EXPORTER_OTLP_HEADERSNãoCabeçalhos no formato chave=valor separados por vírgula (ex: api-key=secret,x-env=prod)
OTEL_EXPORTER_OTLP_METRICS_ENDPOINTNãoSubstitui o endpoint apenas para o sinal de métricas. Usa OTEL_EXPORTER_OTLP_ENDPOINT por padrão
OTEL_SERVICE_NAMENãoNome do serviço reportado ao backend. Usa APP_NAME por padrão

Inicialização

Ao inicializar o Colibri, os seguintes componentes são configurados automaticamente:

  • Conexão OpenTelemetry.
  • Métricas padrão da aplicação.
  • Coleta de métricas de runtime do Go.

Métricas Automáticas

Quando OTEL_EXPORTER_OTLP_ENDPOINT está configurado, o SDK emite automaticamente as seguintes métricas:

  • HTTP Server/Client: duração das requisições via otelfiber e otelhttp
  • Banco de Dados: duração das operações via otelsql
  • Go Runtime: heap, GC e goroutines

Componentes Principais

1. Transações de Monitoramento

// Iniciando uma nova transação de monitoramento
txn, ctx := monitoring.StartTransaction(ctx, "MinhaOperacao")
defer monitoring.EndTransaction(txn)

2. Segmentos

// Criando um segmento de transação
segment := monitoring.StartTransactionSegment(ctx, "MinhaOperacao", map[string]string{
"operacao": "consulta",
"tipo": "banco",
})
defer monitoring.EndTransactionSegment(segment)

Atenção: Para que o segmento possa ser relacionado corretamente com a transação, devemos passar o atributo ctx criado na transação principal.

3. Rastreamento de Erros

// Notificando erros
if err != nil {
monitoring.NoticeError(txn, err)
return err
}

4. Métricas Personalizadas

O SDK expõe três tipos de instrumentos de métricas via o pacote monitoring:

Counter

Contador monotonicamente crescente para medir ocorrências de eventos.

import "github.com/colibriproject-dev/colibri-sdk-go/pkg/base/monitoring"

requests := monitoring.Counter("app.requests", "Total de requisições HTTP", "1")
requests.Add(ctx, 1, map[string]string{"route": "/api/users"})

Histogram

Registra a distribuição de valores, ideal para medir durações e tamanhos.

duration := monitoring.Histogram("app.request.duration", "Duração das requisições", "ms")
duration.Record(ctx, elapsed.Milliseconds(), map[string]string{"status": "200"})

Gauge

Captura o valor atual de uma medida em um instante de tempo.

activeConns := monitoring.Gauge("app.connections.active", "Conexões ativas", "1")
activeConns.Record(ctx, float64(count), nil)

Exemplos de Uso

1. Monitoramento de Serviços Externos

func (s *Service) ChamarAPIExterna(ctx context.Context) error {
segment := monitoring.StartTransactionSegment(ctx, "API_Pagamento")
defer monitoring.EndTransactionSegment(segment)

resp, err := http.Get("https://api.externa.com/recurso")
if err != nil {
monitoring.NoticeError(monitoring.GetTransactionInContext(ctx), err)
return err
}
defer resp.Body.Close()

return nil
}

2. Métricas Personalizadas em um Serviço

var (
pedidosProcessados = monitoring.Counter("orders.processed", "Pedidos processados", "1")
tempoDeProcesamento = monitoring.Histogram("orders.processing_time", "Tempo de processamento", "ms")
tamanhoDaFila = monitoring.Gauge("orders.queue_size", "Tamanho da fila", "1")
)

func (s *Service) ProcessarPedido(ctx context.Context, order Order) error {
start := time.Now()

if err := s.process(ctx, order); err != nil {
return err
}

pedidosProcessados.Add(ctx, 1, map[string]string{"status": "success"})
tempoDeProcesamento.Record(ctx, float64(time.Since(start).Milliseconds()), nil)
tamanhoDaFila.Record(ctx, float64(s.queue.Len()), nil)
return nil
}

Boas Práticas

  1. Nomeação de Transações:

    • Use nomes descritivos e consistentes
    • Siga um padrão de nomenclatura
    • Evite nomes dinâmicos
  2. Gestão de Contexto:

    • Sempre propague o contexto
    • Use defer para finalizar transações
    • Mantenha o ciclo de vida correto
  3. Atributos:

    • Adicione atributos relevantes
    • Não adicione dados sensíveis
    • Use chaves consistentes
  4. Erros:

    • Notifique erros relevantes
    • Adicione contexto aos erros
    • Evite notificar erros esperados
  5. Métricas:

    • Declare instrumentos como variáveis globais (evita recriação a cada chamada)
    • Prefira nomes no padrão dominio.objeto.acao (ex: app.requests.total)
    • Use unidades padronizadas: 1 para contadores adimensionais, ms para milissegundos, By para bytes
  6. Performance:

    • Monitore tempos de resposta
    • Observe uso de recursos
    • Identifique gargalos
  7. Segurança:

    • Não registre dados sensíveis nos logs ou atributos
    • Respeite as leis de proteção de dados