v0.1.4 formatter race fix, fiber adapter added, default config changed, docs updated

This commit is contained in:
2025-11-17 16:33:08 -05:00
parent 4ed618abbb
commit 9b0a632b52
22 changed files with 797 additions and 56 deletions

View File

@ -349,4 +349,286 @@ func requestLogger(adapter *compat.FastHTTPAdapter) fasthttp.RequestHandler {
time.Since(start))
}
}
```
```
### Simple integration example suite
Below simple client and server examples can be used to test the basic functionality of the adapters. They are not included in the package to avoid dependency creep.
#### gnet server
```go
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"github.com/lixenwraith/log"
"github.com/lixenwraith/log/compat"
"github.com/panjf2000/gnet/v2"
)
type echoServer struct {
gnet.BuiltinEventEngine
adapter *compat.GnetAdapter
}
func (es *echoServer) OnTraffic(c gnet.Conn) gnet.Action {
buf, _ := c.Next(-1)
if len(buf) > 0 {
es.adapter.Infof("Echo %d bytes", len(buf))
c.Write(buf)
}
return gnet.None
}
func main() {
// Minimal logger config
logger, err := log.NewBuilder().
Directory("./logs_gnet").
Format("json").
LevelString("info").
HeartbeatLevel(0).
Build()
if err != nil {
panic(err)
}
if err := logger.Start(); err != nil {
panic(err)
}
adapter, err := compat.NewBuilder().WithLogger(logger).BuildGnet()
if err != nil {
panic(err)
}
handler := &echoServer{adapter: adapter}
fmt.Println("Starting gnet server on :9000")
fmt.Println("Press Ctrl+C to stop")
// Signal handling
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
go func() {
if err := gnet.Run(handler, "tcp://:9000",
gnet.WithLogger(adapter),
); err != nil {
fmt.Printf("gnet error: %v\n", err)
os.Exit(1)
}
}()
<-sigChan
fmt.Println("\nShutting down...")
logger.Shutdown()
}
```
#### fasthttp server
```go
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"github.com/lixenwraith/log"
"github.com/lixenwraith/log/compat"
"github.com/valyala/fasthttp"
)
func main() {
// Minimal logger config
logger, err := log.NewBuilder().
Directory("./logs_fasthttp").
Format("json").
LevelString("info").
HeartbeatLevel(0).
Build()
if err != nil {
panic(err)
}
if err := logger.Start(); err != nil {
panic(err)
}
adapter, err := compat.NewBuilder().WithLogger(logger).BuildFastHTTP()
if err != nil {
panic(err)
}
server := &fasthttp.Server{
Handler: func(ctx *fasthttp.RequestCtx) {
adapter.Printf("Request: %s %s", ctx.Method(), ctx.Path())
ctx.WriteString("OK")
},
Logger: adapter,
Name: "TestServer",
}
fmt.Println("Starting FastHTTP server on :8080")
fmt.Println("Press Ctrl+C to stop")
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
go func() {
if err := server.ListenAndServe(":8080"); err != nil {
fmt.Printf("FastHTTP error: %v\n", err)
os.Exit(1)
}
}()
<-sigChan
fmt.Println("\nShutting down...")
server.Shutdown()
logger.Shutdown()
}
```
#### Fiber server
```go
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"time"
"github.com/gofiber/fiber/v2"
"github.com/lixenwraith/log"
"github.com/lixenwraith/log/compat"
)
func main() {
// Minimal logger config
logger, err := log.NewBuilder().
Directory("./logs_fiber").
Format("json").
LevelString("info").
HeartbeatLevel(0).
Build()
if err != nil {
panic(err)
}
if err := logger.Start(); err != nil {
panic(err)
}
adapter, err := compat.NewBuilder().WithLogger(logger).BuildFiber()
if err != nil {
panic(err)
}
app := fiber.New(fiber.Config{
DisableStartupMessage: true,
})
app.Use(func(c *fiber.Ctx) error {
adapter.Infow("Request", "method", c.Method(), "path", c.Path())
return c.Next()
})
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("OK")
})
fmt.Println("Starting Fiber server on :3000")
fmt.Println("Press Ctrl+C to stop")
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
go func() {
if err := app.Listen(":3000"); err != nil {
fmt.Printf("Fiber error: %v\n", err)
os.Exit(1)
}
}()
<-sigChan
fmt.Println("\nShutting down...")
app.ShutdownWithTimeout(2 * time.Second)
logger.Shutdown()
}
```
#### Client
Client for all adapter servers.
```bash
# Run with:
go run client.go -target=gnet
go run client.go -target=fasthttp
go run client.go -target=fiber
```
```go
package main
import (
"flag"
"fmt"
"io"
"net"
"net/http"
)
var target = flag.String("target", "fiber", "Target: gnet|fasthttp|fiber")
func main() {
flag.Parse()
switch *target {
case "gnet":
conn, err := net.Dial("tcp", "localhost:9000")
if err != nil {
panic(err)
}
conn.Write([]byte("TEST"))
buf := make([]byte, 4)
conn.Read(buf)
conn.Close()
fmt.Println("gnet: received echo")
case "fasthttp":
resp, err := http.Get("http://localhost:8080/")
if err != nil {
panic(err)
}
body, _ := io.ReadAll(resp.Body)
resp.Body.Close()
fmt.Printf("fasthttp: %s\n", body)
case "fiber":
resp, err := http.Get("http://localhost:3000/")
if err != nil {
panic(err)
}
body, _ := io.ReadAll(resp.Body)
resp.Body.Close()
fmt.Printf("fiber: %s\n", body)
}
}
```

View File

@ -19,7 +19,9 @@ Direct struct configuration using the Config struct, or key-value overrides:
```go
logger := log.NewLogger() // logger instance created with DefaultConfig (using default values)
logger.Info("info txt log record written to ./log/log.log")
// Note: with default config, logs only go to stderr (file output disabled by default)
logger.Start() // Required before logging
logger.Info("info raw log record written to stderr")
// Directly change config struct
cfg := log.GetConfig()
@ -51,7 +53,7 @@ logger.Info("info txt log record written to /var/log/myapp.txt")
| `name` | `string` | Base name for log files | `"log"` |
| `extension` | `string` | Log file extension (without dot) | `"log"` |
| `directory` | `string` | Directory to store log files | `"./log"` |
| `format` | `string` | Output format: `"txt"`, `"json"`, or `"raw"` | `"txt"` |
| `format` | `string` | Output format: `"txt"`, `"json"`, or `"raw"` | `"raw"` |
| `sanitization` | `string` | Sanitization policy: `"raw"`, `"txt"`, `"json"`, or `"shell"` | `"raw"` |
| `timestamp_format` | `string` | Custom timestamp format (Go time format) | `time.RFC3339Nano` |
| `internal_errors_to_stderr` | `bool` | Write logger's internal errors to stderr | `false` |
@ -63,8 +65,8 @@ logger.Info("info txt log record written to /var/log/myapp.txt")
| `show_timestamp` | `bool` | Include timestamps in log entries | `true` |
| `show_level` | `bool` | Include log level in entries | `true` |
| `enable_console` | `bool` | Enable console output (stdout/stderr) | `true` |
| `console_target` | `string` | Console target: `"stdout"`, `"stderr"`, or `"split"` | `"stdout"` |
| `enable_file` | `bool` | Enable file output (console-only) | `true` |
| `console_target` | `string` | Console target: `"stdout"`, `"stderr"`, or `"split"` | `"stderr"` |
| `enable_file` | `bool` | Enable file output (console-only) | `false` |
**Note:** When `console_target="split"`, INFO/DEBUG logs go to stdout while WARN/ERROR logs go to stderr.

View File

@ -33,8 +33,8 @@ func main() {
// Create a new logger instance with default configuration
logger := log.NewLogger()
// Apply configuration
err := logger.ApplyConfigString("directory=/var/log/myapp")
// Apply configuration (enable file output since it's disabled by default)
err := logger.ApplyConfigString("directory=/var/log/myapp", "enable_file=true")
if err != nil {
panic(fmt.Errorf("failed to apply logger config: %w", err))
}

View File

@ -126,7 +126,7 @@ func logWithContext(ctx context.Context, logger *log.Logger, level string, msg s
## Output Formats
The logger supports three output formats, each with configurable sanitization. For advanced formatting needs, see [Formatting & Sanitization](formatting.md) for standalone usage of the formatter and sanitizer packages.
The logger supports three output formats, each with configurable sanitization. The default format is "raw".
### Txt Format (Human-Readable)

View File

@ -26,7 +26,8 @@ func main() {
LevelString("info"). // Minimum log level
Format("json"). // Output format
Sanitization("json"). // Sanitization policy
BufferSize(2048). // Channel buffer size
EnableFile(true). // Enable file output (disabled by default)
BufferSize(2048). // Channel buffer size
MaxSizeMB(10). // Max file size before rotation
HeartbeatLevel(1). // Enable operational monitoring
HeartbeatIntervalS(300). // Every 5 minutes