Official Go SDK for LogTide with automatic batching, retry logic, circuit breaker pattern, and native OpenTelemetry integration.
Installation
go get github.com/logtide-dev/logtide-sdk-go Quick Start
package main
import (
"context"
"github.com/logtide-dev/logtide-sdk-go"
)
func main() {
client, err := logtide.New(
logtide.WithAPIKey("lp_your_api_key"),
logtide.WithService("my-service"),
)
if err != nil {
panic(err)
}
defer client.Close()
ctx := context.Background()
// Send logs
client.Info(ctx, "Server started", map[string]any{"port": 8080})
client.Error(ctx, "Connection failed", map[string]any{"error": "timeout"})
} Features
- ✅ Automatic batching with configurable size and interval
- ✅ Retry logic with exponential backoff
- ✅ Circuit breaker pattern for fault tolerance
- ✅ Goroutine-safe logging
- ✅ Context support for request-scoped logging
- ✅ Native OpenTelemetry integration
- ✅ Graceful shutdown with flush
- ✅ Structured metadata support
- ✅ 87% test coverage
Configuration
client, err := logtide.New(
// Required
logtide.WithAPIKey("lp_your_api_key"),
logtide.WithService("my-service"),
// Optional - API
logtide.WithBaseURL("https://api.logtide.dev"),
// Optional - Performance
logtide.WithBatchSize(100), // Max logs per batch (default: 100)
logtide.WithFlushInterval(5*time.Second), // Flush interval (default: 5s)
logtide.WithTimeout(30*time.Second), // HTTP timeout (default: 30s)
// Optional - Reliability
logtide.WithRetry(3, 1*time.Second, 60*time.Second), // maxRetries, delay, maxDelay
logtide.WithCircuitBreaker(5, 30*time.Second), // threshold, timeout
// Optional - Metadata
logtide.WithGlobalMetadata(map[string]any{
"environment": "production",
"version": "1.0.0",
}),
) Logging Methods
Basic Logging
ctx := context.Background()
// Log levels: Debug, Info, Warn, Error, Critical
client.Debug(ctx, "Debug message", map[string]any{"detail": "value"})
client.Info(ctx, "Request received", map[string]any{"method": "GET", "path": "/users"})
client.Warn(ctx, "Cache miss", map[string]any{"key": "user:123"})
client.Error(ctx, "Query failed", map[string]any{"query": "SELECT *"})
client.Critical(ctx, "Out of memory", map[string]any{"used": "95%"}) With Trace ID
// Add trace ID to context
ctx := logtide.WithTraceID(context.Background(), "550e8400-e29b-41d4-a716-446655440000")
// All logs will include the trace ID
client.Info(ctx, "Processing request", nil)
client.Info(ctx, "Query executed", nil) Error Handling
err := client.Info(ctx, "message", nil)
if err != nil {
switch {
case errors.Is(err, logtide.ErrClientClosed):
// Client was closed, logs won't be sent
case errors.Is(err, logtide.ErrCircuitOpen):
// Circuit breaker is open, too many failures
case errors.Is(err, logtide.ErrInvalidAPIKey):
// Invalid API key configuration
default:
// Other error
log.Printf("Failed to send log: %v", err)
}
} OpenTelemetry Integration
import (
"go.opentelemetry.io/otel"
)
tracer := otel.Tracer("my-service")
func handleRequest(ctx context.Context) {
ctx, span := tracer.Start(ctx, "handle-request")
defer span.End()
// Trace ID and Span ID are automatically extracted from context
client.Info(ctx, "Processing request", map[string]any{
"user_id": 123,
})
// Nested spans work too
ctx, dbSpan := tracer.Start(ctx, "database-query")
client.Debug(ctx, "Executing query", nil)
dbSpan.End()
} HTTP Middleware
Standard Library
func LoggingMiddleware(client *logtide.Client) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
// Create wrapped response writer to capture status
wrapped := &responseWriter{ResponseWriter: w, statusCode: 200}
next.ServeHTTP(wrapped, r)
client.Info(r.Context(), "HTTP request", map[string]any{
"method": r.Method,
"path": r.URL.Path,
"status": wrapped.statusCode,
"duration_ms": time.Since(start).Milliseconds(),
})
})
}
}
// Usage
mux := http.NewServeMux()
handler := LoggingMiddleware(client)(mux)
http.ListenAndServe(":8080", handler) Gin Framework
func GinLoggingMiddleware(client *logtide.Client) gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
c.Next()
client.Info(c.Request.Context(), "HTTP request", map[string]any{
"method": c.Request.Method,
"path": c.Request.URL.Path,
"status": c.Writer.Status(),
"duration_ms": time.Since(start).Milliseconds(),
})
}
}
// Usage
r := gin.Default()
r.Use(GinLoggingMiddleware(client)) Best Practices
1. Always Defer Close
Use
defer client.Close() immediately after creating
the client to ensure all buffered logs are flushed on shutdown.
2. Pass Context
Always pass the request context to logging methods. This enables
trace correlation and allows logs to be cancelled with the request.
3. Use Global Metadata
Add environment, version, and hostname as global metadata
instead of repeating them in every log call.
4. Handle Errors Appropriately
Check for specific errors like
ErrCircuitOpen to implement
fallback logging strategies when LogTide is unavailable.