Go SDK
GitHubOfficial Go SDK for LogWard with automatic batching, retry logic, circuit breaker pattern, and native OpenTelemetry integration.
Installation
bash
go get github.com/logward-dev/logward-sdk-goQuick Start
go
package main
import (
"context"
"github.com/logward-dev/logward-sdk-go"
)
func main() {
client, err := logward.New(
logward.WithAPIKey("lp_your_api_key"),
logward.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
go
client, err := logward.New(
// Required
logward.WithAPIKey("lp_your_api_key"),
logward.WithService("my-service"),
// Optional - API
logward.WithBaseURL("https://api.logward.dev"),
// Optional - Performance
logward.WithBatchSize(100), // Max logs per batch (default: 100)
logward.WithFlushInterval(5*time.Second), // Flush interval (default: 5s)
logward.WithTimeout(30*time.Second), // HTTP timeout (default: 30s)
// Optional - Reliability
logward.WithRetry(3, 1*time.Second, 60*time.Second), // maxRetries, delay, maxDelay
logward.WithCircuitBreaker(5, 30*time.Second), // threshold, timeout
// Optional - Metadata
logward.WithGlobalMetadata(map[string]any{
"environment": "production",
"version": "1.0.0",
}),
)Logging Methods
Basic Logging
go
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
go
// Add trace ID to context
ctx := logward.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
go
err := client.Info(ctx, "message", nil)
if err != nil {
switch {
case errors.Is(err, logward.ErrClientClosed):
// Client was closed, logs won't be sent
case errors.Is(err, logward.ErrCircuitOpen):
// Circuit breaker is open, too many failures
case errors.Is(err, logward.ErrInvalidAPIKey):
// Invalid API key configuration
default:
// Other error
log.Printf("Failed to send log: %v", err)
}
}OpenTelemetry Integration
go
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
go
func LoggingMiddleware(client *logward.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
go
func GinLoggingMiddleware(client *logward.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 LogWard is unavailable.