Go
Send logs from Go services using the standard net/http package — no external dependencies required.
Quick start
No external packages needed — just the standard library:
go
package main
import (
"bytes"
"encoding/json"
"net/http"
"time"
)
const logflowAPIKey = "lf_YOUR_API_KEY"
type LogEntry struct {
Level string `json:"level"`
Message string `json:"message"`
Service string `json:"service"`
Attributes map[string]string `json:"attributes,omitempty"`
}
var httpClient = &http.Client{Timeout: 3 * time.Second}
func Log(level, message, service string, attrs map[string]string) error {
entry := LogEntry{Level: level, Message: message, Service: service, Attributes: attrs}
body, _ := json.Marshal(entry)
req, _ := http.NewRequest("POST", "https://api.getlogflow.com/v1/logs", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+logflowAPIKey)
req.Header.Set("Content-Type", "application/json")
resp, err := httpClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
func main() {
Log("info", "Server started", "api", map[string]string{"port": "8080"})
Log("error", "DB timeout", "api", map[string]string{"host": "db-1"})
}Logger wrapper
A reusable logger struct with level helpers:
go
package logflow
import (
"bytes"
"encoding/json"
"net/http"
"os"
"time"
)
type Logger struct {
apiKey string
service string
client *http.Client
}
func New(service string) *Logger {
return &Logger{
apiKey: os.Getenv("LOGFLOW_API_KEY"),
service: service,
client: &http.Client{Timeout: 3 * time.Second},
}
}
func (l *Logger) send(level, msg string, attrs map[string]string) {
go func() { // non-blocking
body, _ := json.Marshal(map[string]any{
"level": level, "message": msg,
"service": l.service, "attributes": attrs,
})
req, _ := http.NewRequest("POST", "https://api.getlogflow.com/v1/logs", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+l.apiKey)
req.Header.Set("Content-Type", "application/json")
l.client.Do(req) //nolint:errcheck
}()
}
func (l *Logger) Info(msg string, attrs ...map[string]string) { l.send("info", msg, merge(attrs)) }
func (l *Logger) Warn(msg string, attrs ...map[string]string) { l.send("warn", msg, merge(attrs)) }
func (l *Logger) Error(msg string, attrs ...map[string]string) { l.send("error", msg, merge(attrs)) }
func (l *Logger) Fatal(msg string, attrs ...map[string]string) { l.send("fatal", msg, merge(attrs)) }
func merge(maps []map[string]string) map[string]string {
out := map[string]string{}
for _, m := range maps {
for k, v := range m { out[k] = v }
}
return out
}
// Usage
// logger := logflow.New("payments-service")
// logger.Info("Payment processed", map[string]string{"order_id": "ord_123"})
// logger.Error("Stripe timeout", map[string]string{"attempt": "2"})💡
The
go func() goroutine makes logging non-blocking — your handlers return immediately even if the LogFlow API is slow.Batch sending
Buffer logs and flush periodically for high-throughput services:
go
package main
import (
"bytes"
"encoding/json"
"net/http"
"sync"
"time"
)
type BatchLogger struct {
mu sync.Mutex
buffer []map[string]any
apiKey string
service string
}
func NewBatch(service string) *BatchLogger {
l := &BatchLogger{apiKey: "lf_YOUR_API_KEY", service: service}
go l.flush()
return l
}
func (l *BatchLogger) Log(level, msg string) {
l.mu.Lock()
l.buffer = append(l.buffer, map[string]any{"level": level, "message": msg, "service": l.service})
l.mu.Unlock()
}
func (l *BatchLogger) flush() {
for range time.Tick(2 * time.Second) {
l.mu.Lock()
if len(l.buffer) == 0 { l.mu.Unlock(); continue }
batch := l.buffer
l.buffer = nil
l.mu.Unlock()
body, _ := json.Marshal(map[string]any{"logs": batch})
req, _ := http.NewRequest("POST", "https://api.getlogflow.com/v1/logs/batch", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+l.apiKey)
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req) //nolint:errcheck
}
}slog integration (Go 1.21+)
Implement slog.Handler to plug into Go's structured logging:
go
// Full slog.Handler implementation coming soon.
// For now, use the Logger wrapper above with your slog middleware.