Help us shape the future of Go! Take the 2026 Go Developer Survey

oltgo

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 1, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

README

Oltgo — Biblioteca de Telemetria e Observabilidade em Go

O oltgo é uma biblioteca leve, rápida e concorrente projetada para capturar e estruturar logs e rastreamentos (traces) em microsserviços, monólitos ou quaisquer aplicações escritas em Go.


1. Arquitetura Geral

O design segue o princípio 1 Serviço -> 1 Agente, onde cada instância da sua aplicação mantém um único Agent em execução.

+-------------------------------------------------------------+
|                     Aplicação Go                            |
|                                                             |
|   +------------------+           +----------------------+   |
|   |    Collection    | --------> |       Shipping       |   |
|   | (Fila local/Mem) |  (Canal)  | (Worker assíncrono)  |   |
|   +------------------+           +----------------------+   |
+---------------------------------------------|---------------+
                                              v
                                   [ Callback ProcessLog ]
                                   (ex: Gravar em arquivo, 
                                    enviar p/ OpenTelemetry, 
                                    Stripe, ElasticSearch, etc)
Componentes Principais
  1. Agent: Orquestrador central que gerencia o ciclo de vida do pipeline. É inicializado uma única vez na inicialização do serviço.
  2. Collection: Estrutura thread-safe criada para cada transação, requisição ou trace. É responsável por acumular os dados e eventos em memória local e empacotá-los sob o schema unificado ao final da execução.
  3. Shipping: Fila de buffer baseada em Go channels. Ela recebe as instâncias estruturadas prontas do Collection e consome assincronamente os dados para que a aplicação principal nunca sofra atrasos de I/O de escrita.

2. Inicializando o Agente

Para começar, inicialize o Agent definindo os metadados do serviço e um callback opcional de destino para os logs:

package main

import (
	"encoding/json"
	"fmt"
	"github.com/joaooffzz/oltgo"
)

func main() {
	service := oltgo.Service{
		Name:    "payment-gateway",
		Version: "2.1.0",
	}

	// Callback para exportar logs estruturados (ex: saída padrão stdout)
	processLog := func(log oltgo.LogSchema) error {
		bytes, _ := json.Marshal(log)
		fmt.Println(string(bytes))
		return nil
	}

	// Inicializa
	agent := oltgo.NewAgent(service, oltgo.Production, "1", processLog)
	
	// Garante que todos os logs na fila de buffer sejam processados antes da app fechar
	defer agent.Close() 
}

3. Propagação de Contexto via context.Context

O oltgo utiliza o context.Context nativo do Go para carregar e obter a coleção de telemetria através da pilha de execução de funções (call stack), evitando o acoplamento excessivo de código e garantindo segurança concorrente.

Criação e Injeção do Contexto

No início de um fluxo de requisição (por exemplo, um middleware HTTP), você cria a coleção e injeta-a no contexto:

func HandleRequest(w http.ResponseWriter, r *http.Request) {
	// Cria a collection para esta chamada específica
	collection := agent.NewCollection("trace-unique-uuid")
	collection.SetRequestFromHTTP(r, oltgo.ProtoREST, 200)

	// Injeta a collection no contexto
	ctx := oltgo.WithCollection(r.Context(), collection)

	// Propaga o contexto modificado para as funções internas
	executeBusinessLogic(ctx)

	// Commita os dados para a fila de envio assíncrono
	collection.Commit()
}
Extração e Registro de Eventos na Pilha

Em qualquer sub-função que receba o contexto, você pode extrair a Collection com segurança e registrar eventos:

func executeBusinessLogic(ctx context.Context) {
	// Recupera a coleção. Se não estiver no contexto, retorna nil com segurança
	collection := oltgo.FromContext(ctx)
	if collection == nil {
		return
	}

	// Inicia um evento com cálculo de tempo automático
	event := collection.StartEvent("db_query", oltgo.TypeDatabase, oltgo.SeverityInfo)
	event.WithMessage("Selecionando itens do carrinho")
	
	defer event.End() // Ao finalizar a função, calcula a duração e salva o evento

	// Executa operação de fato...
	if err := queryDB(); err != nil {
		event.AddError("DB_ERROR", err.Error(), nil)
	}
}

4. O Schema de Log Estruturado

Todos os logs commitados são unificados sob uma estrutura padrão e enviados para o callback ProcessLog. A documentação completa dos campos do schema JSON pode ser vista em:

  • Documentação de Campos (docs/log.md)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func WithCollection

func WithCollection(ctx context.Context, c *Collection) context.Context

WithCollection injeta uma instância de *Collection no contexto fornecido.

Types

type Actor

type Actor struct {
	ID   string `json:"id"`
	Type string `json:"type"` // USER, SERVICE
	IP   string `json:"ip,omitempty"`
}

type Agent

type Agent struct {
	Service       Service
	Env           Environment
	SchemaVersion string
	Shipping      *Shipping
}

func NewAgent

func NewAgent(service Service, env Environment, schemaVersion string, processLog func(LogSchema) error) *Agent

NewAgent inicializa o Agent de observabilidade. O parâmetro processLog é uma função opcional de callback para processamento dos logs estruturados. Se processLog for nil, os logs serão silenciosamente descartados da memória.

func (*Agent) Close

func (a *Agent) Close()

Close encerra as goroutines do Shipping de forma limpa, garantindo o processamento de logs remanescentes.

func (*Agent) NewCollection

func (a *Agent) NewCollection(tracingID string) *Collection

NewCollection cria uma nova instância de Collection associada a este Agent para rastrear uma nova trace/requisição.

type Collection

type Collection struct {
	// contains filtered or unexported fields
}

func FromContext

func FromContext(ctx context.Context) *Collection

FromContext recupera a instância de *Collection do contexto. Retorna nil se não estiver presente.

func NewCollection

func NewCollection(agent *Agent, tracingID string) *Collection

NewCollection inicializa uma nova Collection vinculada ao Agent.

func (*Collection) AddEvent

func (c *Collection) AddEvent(event Event)

AddEvent insere um evento completo de forma thread-safe.

func (*Collection) Commit

func (c *Collection) Commit()

Commit finaliza a trace, calcula a duração e submete os dados para o Shipping do Agent.

func (*Collection) SetActor

func (c *Collection) SetActor(actor *Actor)

SetActor define informações do ator da requisição.

func (*Collection) SetRequest

func (c *Collection) SetRequest(req *Request)

SetRequest define informações de requisição de forma thread-safe.

func (*Collection) SetRequestFromHTTP

func (c *Collection) SetRequestFromHTTP(r *http.Request, comm CommunicationProto, status int)

SetRequestFromHTTP preenche informações da requisição a partir de um *http.Request nativo.

func (*Collection) StartEvent

func (c *Collection) StartEvent(name string, eventType EventType, severity Severity) *EventBuilder

StartEvent inicia a gravação de um evento. O evento será registrado no Collection chamando End().

type CommunicationProto

type CommunicationProto string
const (
	ProtoREST      CommunicationProto = "REST"
	ProtoGRPC      CommunicationProto = "gRPC"
	ProtoSOAP      CommunicationProto = "SOAP"
	ProtoWebSocket CommunicationProto = "WebSocket"
)

type Environment

type Environment string
const (
	Production  Environment = "production"
	Development Environment = "development"
	Testing     Environment = "testing"
)

type Event

type Event struct {
	EventID       string         `json:"event_id"`
	ParentEventID *string        `json:"parent_event_id"`
	Name          string         `json:"name"`
	Type          EventType      `json:"type"`
	Status        Status         `json:"status"`
	Severity      Severity       `json:"severity"`
	Timestamp     time.Time      `json:"timestamp"`
	DurationMs    int            `json:"duration_ms"`
	Message       string         `json:"message"`
	Metadata      map[string]any `json:"metadata,omitempty"`
	Errors        []EventError   `json:"errors,omitempty"`
}

type EventBuilder

type EventBuilder struct {
	// contains filtered or unexported fields
}

EventBuilder auxilia desenvolvedores a construírem eventos com cálculo de tempo automático.

func (*EventBuilder) AddError

func (eb *EventBuilder) AddError(code, message string, stack *string) *EventBuilder

AddError adiciona um erro ocorrido durante a operação do evento, definindo o status do evento como FAILURE.

func (*EventBuilder) End

func (eb *EventBuilder) End()

End calcula o tempo de duração final do evento e o adiciona à Collection.

func (*EventBuilder) WithMessage

func (eb *EventBuilder) WithMessage(msg string) *EventBuilder

WithMessage adiciona uma mensagem explicativa ao evento.

func (*EventBuilder) WithMetadata

func (eb *EventBuilder) WithMetadata(metadata map[string]any) *EventBuilder

WithMetadata injeta dados de contexto adicionais de forma flexível.

func (*EventBuilder) WithParent

func (eb *EventBuilder) WithParent(parentID string) *EventBuilder

WithParent define o ID do evento pai para construir árvores/spans.

type EventError

type EventError struct {
	Code    string  `json:"code"`
	Message string  `json:"message"`
	Stack   *string `json:"stack,omitempty"`
}

type EventType

type EventType string
const (
	TypeFunction        EventType = "FUNCTION"
	TypeDatabase        EventType = "DATABASE"
	TypeExternalService EventType = "EXTERNAL_SERVICE"
	TypeInternalService EventType = "INTERNAL_SERVICE"
)

type LogSchema

type LogSchema struct {
	TracingID     string      `json:"tracing_id"`
	Status        Status      `json:"status"`
	Environment   Environment `json:"environment"`
	SchemaVersion string      `json:"schema_version"`
	Service       Service     `json:"service"`
	Request       *Request    `json:"request,omitempty"`
	Actor         *Actor      `json:"actor,omitempty"`
	Time          TimeInfo    `json:"time"`
	Events        []Event     `json:"events"`
}

type Request

type Request struct {
	Communication CommunicationProto `json:"communication"`
	Method        string             `json:"method,omitempty"`
	Route         string             `json:"route,omitempty"`
	Status        int                `json:"status"`
	UserAgent     string             `json:"user_agent,omitempty"`
}

type Service

type Service struct {
	ID          *string   `json:"id,omitempty"`
	Name        string    `json:"name"`
	Description *string   `json:"description,omitempty"`
	Version     string    `json:"version"`
	Tags        *[]string `json:"tags,omitempty"`
}

type Severity

type Severity string
const (
	SeverityDebug Severity = "DEBUG"
	SeverityInfo  Severity = "INFO"
	SeverityWarn  Severity = "WARN"
	SeverityError Severity = "ERROR"
	SeverityFatal Severity = "FATAL"
)

type Shipping

type Shipping struct {
	// contains filtered or unexported fields
}

func NewShipping

func NewShipping(bufferSize int, processLog func(LogSchema) error) *Shipping

func (*Shipping) Close

func (s *Shipping) Close()

func (*Shipping) Ship

func (s *Shipping) Ship(log LogSchema)

type Status

type Status string
const (
	StatusSuccess Status = "SUCCESS"
	StatusFailure Status = "FAILURE"
)

type TimeInfo

type TimeInfo struct {
	DurationMs int       `json:"duration_ms"`
	CreatedAt  time.Time `json:"created_at"`
	FinishedAt time.Time `json:"finished_at"`
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL