Official Go SDK for LogTide — structured logging with automatic batching, retry, circuit breaker, and OpenTelemetry integration.
- Leveled logging — Debug, Info, Warn, Error, Critical, CaptureError
- Hub / Scope model — per-request context isolation with breadcrumbs, tags, and user metadata
- Automatic batching — configurable batch size and flush interval
- Retry with backoff — exponential backoff with jitter
- Circuit breaker — prevents cascading failures
- OpenTelemetry — trace/span IDs extracted automatically; span exporter included
- net/http middleware — per-request scope isolation out of the box
- Thread-safe — safe for concurrent use
- Go 1.23 or later
- A LogTide account and DSN
go get github.com/logtide-dev/logtide-sdk-gopackage main
import (
"context"
logtide "github.com/logtide-dev/logtide-sdk-go"
)
func main() {
flush := logtide.Init(logtide.ClientOptions{
DSN: "https://lp_your_api_key@api.logtide.dev",
Service: "my-service",
Environment: "production",
Release: "v1.2.3",
})
defer flush()
logtide.Info(context.Background(), "Hello LogTide!", nil)
logtide.Error(context.Background(), "Something went wrong", map[string]any{
"user_id": 42,
})
}opts := logtide.NewClientOptions()
opts.DSN = "https://lp_your_api_key@api.logtide.dev"
opts.Service = "my-service"
client, err := logtide.NewClient(opts)
if err != nil {
log.Fatal(err)
}
defer client.Close()
id := client.Info(context.Background(), "Hello", nil)
fmt.Println("event id:", id)https://{api_key}@{host}
Example: https://lp_abc123@api.logtide.dev
opts := logtide.NewClientOptions()
opts.DSN = "https://lp_abc@api.logtide.dev"
opts.Service = "my-service" // required
opts.Release = "v1.2.3"
opts.Environment = "production"
opts.Tags = map[string]string{"region": "eu-west-1"}
opts.BatchSize = 100 // entries per HTTP batch
opts.FlushInterval = 5 * time.Second
opts.FlushTimeout = 10 * time.Second
opts.MaxRetries = 3
opts.RetryMinBackoff = 1 * time.Second
opts.RetryMaxBackoff = 60 * time.Second
opts.CircuitBreakerThreshold = 5 // consecutive failures before open
opts.CircuitBreakerTimeout = 30 * time.Second
opts.AttachStacktrace = logtide.Bool(true)All log methods return the EventID assigned to the entry, or "" if the entry was dropped.
ctx := context.Background()
client.Debug(ctx, "cache miss", map[string]any{"key": "user:42"})
client.Info(ctx, "request handled", map[string]any{"status": 200, "ms": 12})
client.Warn(ctx, "rate limit approaching", nil)
client.Error(ctx, "db query failed", map[string]any{"query": "SELECT ..."})
client.Critical(ctx, "out of memory", nil)
// Capture an error with full stack trace
if err := doSomething(); err != nil {
client.CaptureError(ctx, err, map[string]any{"op": "doSomething"})
}The Hub/Scope model lets you attach contextual data (tags, breadcrumbs, user info, trace context) to all log entries within a logical unit of work.
// Configure the global scope
logtide.ConfigureScope(func(s *logtide.Scope) {
s.SetTag("region", "eu-west-1")
s.SetUser(logtide.User{ID: "u123", Email: "alice@example.com"})
})
// Per-request isolation via PushScope / PopScope
logtide.PushScope()
defer logtide.PopScope()
logtide.ConfigureScope(func(s *logtide.Scope) {
s.SetTag("request_id", requestID)
s.AddBreadcrumb(&logtide.Breadcrumb{
Category: "auth",
Message: "user authenticated",
Level: logtide.LevelInfo,
Timestamp: time.Now(),
}, nil)
})
logtide.Info(ctx, "processing order", nil) // includes request_id tag + breadcrumbimport lnethttp "github.com/logtide-dev/logtide-sdk-go/integrations/nethttp"
http.Handle("/", lnethttp.Middleware(myHandler))The middleware automatically:
- clones the Hub for each request (scope isolation)
- sets
http.method,http.url,http.host,http.client_iptags - parses the
Traceparentheader and stores trace/span IDs on the scope - adds request and response breadcrumbs
Trace and span IDs are extracted automatically from any active OTel span in the context:
ctx, span := tracer.Start(ctx, "process-order")
defer span.End()
// trace_id and span_id are included automatically
client.Info(ctx, "order processed", map[string]any{"order_id": 99})Export completed spans to LogTide:
import "github.com/logtide-dev/logtide-sdk-go/integrations/otelexport"
integration := otelexport.New()
flush := logtide.Init(logtide.ClientOptions{
DSN: "https://lp_abc@api.logtide.dev",
Service: "my-service",
Integrations: func(defaults []logtide.Integration) []logtide.Integration {
return append(defaults, integration)
},
})
defer flush()
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(integration.Exporter()),
)// Flush with deadline
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
client.Flush(ctx)
// Close flushes and releases all resources
client.Close()Inspect or drop entries before they are sent:
opts.BeforeSend = func(entry *logtide.LogEntry, hint *logtide.EventHint) *logtide.LogEntry {
// drop health-check noise
if entry.Message == "health check" {
return nil
}
return entry
}Use NoopTransport to silence all output in tests:
client, _ := logtide.NewClient(logtide.ClientOptions{
Service: "test",
Transport: logtide.NoopTransport{},
})| Example | Description |
|---|---|
| examples/basic | All log levels, metadata, CaptureError |
| examples/gin | Gin framework integration |
| examples/echo | Echo framework integration |
| examples/stdlib | Standard library net/http |
| examples/otel | OpenTelemetry distributed tracing |
- Online: pkg.go.dev/github.com/logtide-dev/logtide-sdk-go
- Local:
godoc -http=:6060
See CONTRIBUTING.md.
MIT — see LICENSE.
