444 lines
9.9 KiB
Markdown
444 lines
9.9 KiB
Markdown
# Compatibility Adapters
|
|
|
|
[← Performance](performance.md) | [← Back to README](../README.md) | [Examples →](examples.md)
|
|
|
|
Guide to using lixenwraith/log with popular Go networking frameworks through compatibility adapters.
|
|
|
|
## Table of Contents
|
|
|
|
- [Overview](#overview)
|
|
- [gnet Adapter](#gnet-adapter)
|
|
- [fasthttp Adapter](#fasthttp-adapter)
|
|
- [Builder Pattern](#builder-pattern)
|
|
- [Structured Logging](#structured-logging)
|
|
- [Advanced Configuration](#advanced-configuration)
|
|
|
|
## Overview
|
|
|
|
The `compat` package provides adapters that allow the lixenwraith/log logger to work seamlessly with:
|
|
|
|
- **gnet v2**: High-performance event-driven networking framework
|
|
- **fasthttp**: Fast HTTP implementation
|
|
|
|
### Features
|
|
|
|
- ✅ Full interface compatibility
|
|
- ✅ Preserves structured logging
|
|
- ✅ Configurable behavior
|
|
- ✅ Shared logger instances
|
|
- ✅ Optional field extraction
|
|
|
|
## gnet Adapter
|
|
|
|
### Basic Usage
|
|
|
|
```go
|
|
import (
|
|
"github.com/lixenwraith/log"
|
|
"github.com/lixenwraith/log/compat"
|
|
"github.com/panjf2000/gnet/v2"
|
|
)
|
|
|
|
// Create logger
|
|
logger := log.NewLogger()
|
|
logger.InitWithDefaults("directory=/var/log/gnet")
|
|
defer logger.Shutdown()
|
|
|
|
// Create adapter
|
|
adapter := compat.NewGnetAdapter(logger)
|
|
|
|
// Use with gnet
|
|
gnet.Run(eventHandler, "tcp://127.0.0.1:9000",
|
|
gnet.WithLogger(adapter),
|
|
)
|
|
```
|
|
|
|
### gnet Interface Implementation
|
|
|
|
The adapter implements all gnet logger methods:
|
|
|
|
```go
|
|
type GnetAdapter struct {
|
|
logger *log.Logger
|
|
}
|
|
|
|
// Methods implemented:
|
|
// - Debugf(format string, args ...interface{})
|
|
// - Infof(format string, args ...interface{})
|
|
// - Warnf(format string, args ...interface{})
|
|
// - Errorf(format string, args ...interface{})
|
|
// - Fatalf(format string, args ...interface{})
|
|
```
|
|
|
|
### Custom Fatal Behavior
|
|
|
|
Override default fatal handling:
|
|
|
|
```go
|
|
adapter := compat.NewGnetAdapter(logger,
|
|
compat.WithFatalHandler(func(msg string) {
|
|
// Custom cleanup
|
|
saveApplicationState()
|
|
notifyOperations(msg)
|
|
gracefulShutdown()
|
|
os.Exit(1)
|
|
}),
|
|
)
|
|
```
|
|
|
|
### Complete gnet Example
|
|
|
|
```go
|
|
type echoServer struct {
|
|
gnet.BuiltinEventEngine
|
|
logger gnet.Logger
|
|
}
|
|
|
|
func (es *echoServer) OnBoot(eng gnet.Engine) gnet.Action {
|
|
es.logger.Infof("Server started on %s", eng.Addrs)
|
|
return gnet.None
|
|
}
|
|
|
|
func (es *echoServer) OnTraffic(c gnet.Conn) gnet.Action {
|
|
buf, _ := c.Next(-1)
|
|
es.logger.Debugf("Received %d bytes from %s", len(buf), c.RemoteAddr())
|
|
c.Write(buf)
|
|
return gnet.None
|
|
}
|
|
|
|
func main() {
|
|
logger := log.NewLogger()
|
|
logger.InitWithDefaults(
|
|
"directory=/var/log/gnet",
|
|
"format=json",
|
|
"buffer_size=2048",
|
|
)
|
|
defer logger.Shutdown()
|
|
|
|
adapter := compat.NewGnetAdapter(logger)
|
|
|
|
gnet.Run(
|
|
&echoServer{logger: adapter},
|
|
"tcp://127.0.0.1:9000",
|
|
gnet.WithMulticore(true),
|
|
gnet.WithLogger(adapter),
|
|
)
|
|
}
|
|
```
|
|
|
|
## fasthttp Adapter
|
|
|
|
### Basic Usage
|
|
|
|
```go
|
|
import (
|
|
"github.com/lixenwraith/log"
|
|
"github.com/lixenwraith/log/compat"
|
|
"github.com/valyala/fasthttp"
|
|
)
|
|
|
|
// Create logger
|
|
logger := log.NewLogger()
|
|
logger.InitWithDefaults("directory=/var/log/fasthttp")
|
|
defer logger.Shutdown()
|
|
|
|
// Create adapter
|
|
adapter := compat.NewFastHTTPAdapter(logger)
|
|
|
|
// Configure server
|
|
server := &fasthttp.Server{
|
|
Handler: requestHandler,
|
|
Logger: adapter,
|
|
}
|
|
```
|
|
|
|
### Level Detection
|
|
|
|
The adapter automatically detects log levels from message content:
|
|
|
|
```go
|
|
// Default detection rules:
|
|
// - Contains "error", "failed", "fatal", "panic" → ERROR
|
|
// - Contains "warn", "warning", "deprecated" → WARN
|
|
// - Contains "debug", "trace" → DEBUG
|
|
// - Otherwise → INFO
|
|
```
|
|
|
|
### Custom Level Detection
|
|
|
|
```go
|
|
adapter := compat.NewFastHTTPAdapter(logger,
|
|
compat.WithDefaultLevel(log.LevelInfo),
|
|
compat.WithLevelDetector(func(msg string) int64 {
|
|
// Custom detection logic
|
|
if strings.Contains(msg, "CRITICAL") {
|
|
return log.LevelError
|
|
}
|
|
if strings.Contains(msg, "performance") {
|
|
return log.LevelWarn
|
|
}
|
|
// Return 0 to use the adapter's default log level (log.LevelInfo by default)
|
|
return 0
|
|
}),
|
|
)
|
|
```
|
|
|
|
### Complete fasthttp Example
|
|
|
|
```go
|
|
func main() {
|
|
logger := log.NewLogger()
|
|
logger.InitWithDefaults(
|
|
"directory=/var/log/fasthttp",
|
|
"format=json",
|
|
"heartbeat_level=1",
|
|
)
|
|
defer logger.Shutdown()
|
|
|
|
adapter := compat.NewFastHTTPAdapter(logger,
|
|
compat.WithDefaultLevel(log.LevelInfo),
|
|
)
|
|
|
|
server := &fasthttp.Server{
|
|
Handler: func(ctx *fasthttp.RequestCtx) {
|
|
// Your handler logic
|
|
ctx.Success("text/plain", []byte("Hello!"))
|
|
},
|
|
Logger: adapter,
|
|
Name: "MyServer",
|
|
Concurrency: fasthttp.DefaultConcurrency,
|
|
DisableKeepalive: false,
|
|
TCPKeepalive: true,
|
|
ReduceMemoryUsage: true,
|
|
}
|
|
|
|
if err := server.ListenAndServe(":8080"); err != nil {
|
|
logger.Error("Server failed", "error", err)
|
|
}
|
|
}
|
|
```
|
|
|
|
## Builder Pattern
|
|
|
|
### Shared Configuration
|
|
|
|
Use the builder for multiple adapters with shared configuration:
|
|
|
|
```go
|
|
// Create builder
|
|
builder := compat.NewBuilder().
|
|
WithOptions(
|
|
"directory=/var/log/app",
|
|
"format=json",
|
|
"buffer_size=4096",
|
|
"max_size_mb=100",
|
|
"heartbeat_level=2",
|
|
)
|
|
|
|
// Build adapters
|
|
gnetAdapter, fasthttpAdapter, err := builder.Build()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Get logger for direct use
|
|
logger := builder.GetLogger()
|
|
defer logger.Shutdown()
|
|
|
|
// Use adapters in your servers
|
|
// ...
|
|
```
|
|
|
|
### Structured Adapters
|
|
|
|
For enhanced field extraction:
|
|
|
|
```go
|
|
// Build with structured adapters
|
|
gnetStructured, fasthttpAdapter, err := builder.BuildStructured()
|
|
```
|
|
|
|
## Structured Logging
|
|
|
|
### Field Extraction
|
|
|
|
Structured adapters can extract fields from printf-style formats:
|
|
|
|
```go
|
|
// Regular adapter output:
|
|
// "client=192.168.1.1 port=8080"
|
|
|
|
// Structured adapter output:
|
|
// {"client": "192.168.1.1", "port": 8080, "source": "gnet"}
|
|
```
|
|
|
|
### Pattern Detection
|
|
|
|
The structured adapter recognizes patterns like:
|
|
- `key=%v`
|
|
- `key: %v`
|
|
- `key = %v`
|
|
|
|
```go
|
|
adapter := compat.NewStructuredGnetAdapter(logger)
|
|
|
|
// These will extract structured fields:
|
|
adapter.Infof("client=%s port=%d", "192.168.1.1", 8080)
|
|
// → {"client": "192.168.1.1", "port": 8080}
|
|
|
|
adapter.Errorf("user: %s, error: %s", "john", "auth failed")
|
|
// → {"user": "john", "error": "auth failed"}
|
|
|
|
// These remain as messages:
|
|
adapter.Infof("Connected to server")
|
|
// → {"msg": "Connected to server"}
|
|
```
|
|
|
|
## Advanced Configuration
|
|
|
|
### High-Performance Setup
|
|
|
|
```go
|
|
builder := compat.NewBuilder().
|
|
WithOptions(
|
|
"directory=/var/log/highperf",
|
|
"format=json",
|
|
"buffer_size=8192", // Large buffer
|
|
"flush_interval_ms=1000", // Batch writes
|
|
"enable_periodic_sync=false", // Reduce I/O
|
|
"heartbeat_level=1", // Monitor drops
|
|
)
|
|
```
|
|
|
|
### Development Setup
|
|
|
|
```go
|
|
builder := compat.NewBuilder().
|
|
WithOptions(
|
|
"directory=./logs",
|
|
"format=txt", // Human-readable
|
|
"level=-4", // Debug level
|
|
"trace_depth=3", // Include traces
|
|
"enable_stdout=true", // Console output
|
|
"flush_interval_ms=50", // Quick feedback
|
|
)
|
|
```
|
|
|
|
### Container Setup
|
|
|
|
```go
|
|
builder := compat.NewBuilder().
|
|
WithOptions(
|
|
"disable_file=true", // No files
|
|
"enable_stdout=true", // Console only
|
|
"format=json", // For aggregators
|
|
"level=0", // Info and above
|
|
)
|
|
```
|
|
|
|
### Helper Functions
|
|
|
|
Configure servers with adapters:
|
|
|
|
```go
|
|
// Configure gnet with options
|
|
opts := compat.ConfigureGnetServer(adapter,
|
|
gnet.WithMulticore(true),
|
|
gnet.WithReusePort(true),
|
|
)
|
|
gnet.Run(handler, addr, opts...)
|
|
|
|
// Configure fasthttp
|
|
server := &fasthttp.Server{Handler: handler}
|
|
compat.ConfigureFastHTTPServer(adapter, server)
|
|
```
|
|
|
|
### Integration Examples
|
|
|
|
#### Microservice with Both Frameworks
|
|
|
|
```go
|
|
type Service struct {
|
|
gnetAdapter *compat.GnetAdapter
|
|
fasthttpAdapter *compat.FastHTTPAdapter
|
|
logger *log.Logger
|
|
}
|
|
|
|
func NewService() (*Service, error) {
|
|
builder := compat.NewBuilder().
|
|
WithOptions(
|
|
"directory=/var/log/service",
|
|
"format=json",
|
|
"heartbeat_level=2",
|
|
)
|
|
|
|
gnet, fasthttp, err := builder.Build()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Service{
|
|
gnetAdapter: gnet,
|
|
fasthttpAdapter: fasthttp,
|
|
logger: builder.GetLogger(),
|
|
}, nil
|
|
}
|
|
|
|
func (s *Service) StartTCPServer() error {
|
|
return gnet.Run(handler, "tcp://0.0.0.0:9000",
|
|
gnet.WithLogger(s.gnetAdapter),
|
|
)
|
|
}
|
|
|
|
func (s *Service) StartHTTPServer() error {
|
|
server := &fasthttp.Server{
|
|
Handler: s.handleHTTP,
|
|
Logger: s.fasthttpAdapter,
|
|
}
|
|
return server.ListenAndServe(":8080")
|
|
}
|
|
|
|
func (s *Service) Shutdown() error {
|
|
return s.logger.Shutdown(5 * time.Second)
|
|
}
|
|
```
|
|
|
|
#### Middleware Integration
|
|
|
|
```go
|
|
// gnet middleware
|
|
func loggingMiddleware(adapter *compat.GnetAdapter) gnet.EventHandler {
|
|
return func(c gnet.Conn) gnet.Action {
|
|
start := time.Now()
|
|
addr := c.RemoteAddr()
|
|
|
|
// Process connection
|
|
action := next(c)
|
|
|
|
adapter.Infof("conn_duration=%v remote=%s action=%v",
|
|
time.Since(start), addr, action)
|
|
|
|
return action
|
|
}
|
|
}
|
|
|
|
// fasthttp middleware
|
|
func requestLogger(adapter *compat.FastHTTPAdapter) fasthttp.RequestHandler {
|
|
return func(ctx *fasthttp.RequestCtx) {
|
|
start := time.Now()
|
|
|
|
// Process request
|
|
next(ctx)
|
|
|
|
// Adapter will detect level from status
|
|
adapter.Printf("method=%s path=%s status=%d duration=%v",
|
|
ctx.Method(), ctx.Path(),
|
|
ctx.Response.StatusCode(),
|
|
time.Since(start))
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
[← Performance](performance.md) | [← Back to README](../README.md) | [Examples →](examples.md) |