feat: add Docker support and logging enhancements

- Introduced Dockerfile and .dockerignore for containerization of the backend service.
- Added logging configuration with support for daily rolling logs and customizable log levels.
- Enhanced the server to utilize structured logging with zap, including detailed request and error logging.
- Updated configuration to include logging parameters and proxy settings.
- Implemented tests for logging configuration and proxy settings.
This commit is contained in:
2026-02-15 18:24:48 +08:00
parent 3284ce07c7
commit eab464060b
9 changed files with 870 additions and 27 deletions

View File

@@ -2,6 +2,7 @@ package main
import (
"os"
"path/filepath"
"testing"
)
@@ -85,6 +86,139 @@ func TestLoadConfigNacosFromEnv(t *testing.T) {
}
}
func TestLoadConfigLoggingDefaults(t *testing.T) {
withEnv(t, "APP_NAME", "")
withEnv(t, "APP_ENV", "")
withEnv(t, "LOG_PATH", "")
withEnv(t, "LOG_LEVEL", "")
withEnv(t, "LOG_MAX_SIZE_MB", "")
withEnv(t, "LOG_MAX_BACKUPS", "")
withEnv(t, "LOG_MAX_AGE_DAYS", "")
withEnv(t, "LOG_COMPRESS", "")
withEnv(t, "LOG_CONSOLE_ENABLED", "")
cfg, err := loadConfig()
if err != nil {
t.Fatalf("loadConfig() error = %v", err)
}
if cfg.AppName != "lsp-gateway" {
t.Fatalf("expected default AppName lsp-gateway, got %q", cfg.AppName)
}
if cfg.AppEnv != "dev" {
t.Fatalf("expected default AppEnv dev, got %q", cfg.AppEnv)
}
expectedPath := filepath.Join(".", "logs", "lsp-gateway")
if cfg.LogPath != expectedPath {
t.Fatalf("expected default LogPath %q, got %q", expectedPath, cfg.LogPath)
}
if cfg.LogLevel != "info" {
t.Fatalf("expected default LogLevel info, got %q", cfg.LogLevel)
}
if cfg.LogMaxSizeMB != 100 {
t.Fatalf("expected default LogMaxSizeMB 100, got %d", cfg.LogMaxSizeMB)
}
if cfg.LogMaxBackups != 31 {
t.Fatalf("expected default LogMaxBackups 31, got %d", cfg.LogMaxBackups)
}
if cfg.LogMaxAgeDays != 31 {
t.Fatalf("expected default LogMaxAgeDays 31, got %d", cfg.LogMaxAgeDays)
}
if !cfg.LogCompress {
t.Fatalf("expected default LogCompress true")
}
if !cfg.LogConsoleEnabled {
t.Fatalf("expected default LogConsoleEnabled true")
}
}
func TestLoadConfigLoggingFromEnv(t *testing.T) {
withEnv(t, "APP_NAME", "editor-bff")
withEnv(t, "APP_ENV", "prod")
withEnv(t, "LOG_PATH", "/data/logs/editor-bff")
withEnv(t, "LOG_LEVEL", "warn")
withEnv(t, "LOG_MAX_SIZE_MB", "200")
withEnv(t, "LOG_MAX_BACKUPS", "50")
withEnv(t, "LOG_MAX_AGE_DAYS", "15")
withEnv(t, "LOG_COMPRESS", "false")
withEnv(t, "LOG_CONSOLE_ENABLED", "false")
cfg, err := loadConfig()
if err != nil {
t.Fatalf("loadConfig() error = %v", err)
}
if cfg.AppName != "editor-bff" {
t.Fatalf("unexpected AppName %q", cfg.AppName)
}
if cfg.AppEnv != "prod" {
t.Fatalf("unexpected AppEnv %q", cfg.AppEnv)
}
if cfg.LogPath != "/data/logs/editor-bff" {
t.Fatalf("unexpected LogPath %q", cfg.LogPath)
}
if cfg.LogLevel != "warn" {
t.Fatalf("unexpected LogLevel %q", cfg.LogLevel)
}
if cfg.LogMaxSizeMB != 200 {
t.Fatalf("unexpected LogMaxSizeMB %d", cfg.LogMaxSizeMB)
}
if cfg.LogMaxBackups != 50 {
t.Fatalf("unexpected LogMaxBackups %d", cfg.LogMaxBackups)
}
if cfg.LogMaxAgeDays != 15 {
t.Fatalf("unexpected LogMaxAgeDays %d", cfg.LogMaxAgeDays)
}
if cfg.LogCompress {
t.Fatalf("expected LogCompress false")
}
if cfg.LogConsoleEnabled {
t.Fatalf("expected LogConsoleEnabled false")
}
}
func TestLoadConfigProxyDefaults(t *testing.T) {
withEnv(t, "TRUSTED_PROXIES", "")
withEnv(t, "REMOTE_IP_HEADERS", "")
withEnv(t, "FORWARDED_BY_CLIENT_IP", "")
cfg, err := loadConfig()
if err != nil {
t.Fatalf("loadConfig() error = %v", err)
}
if len(cfg.TrustedProxies) != 0 {
t.Fatalf("expected default TrustedProxies empty, got %v", cfg.TrustedProxies)
}
if len(cfg.RemoteIPHeaders) != 2 || cfg.RemoteIPHeaders[0] != "X-Forwarded-For" || cfg.RemoteIPHeaders[1] != "X-Real-IP" {
t.Fatalf("unexpected default RemoteIPHeaders %v", cfg.RemoteIPHeaders)
}
if !cfg.ForwardedByClientIP {
t.Fatalf("expected default ForwardedByClientIP true")
}
}
func TestLoadConfigProxyFromEnv(t *testing.T) {
withEnv(t, "TRUSTED_PROXIES", "10.0.0.0/8,172.16.0.0/12")
withEnv(t, "REMOTE_IP_HEADERS", "X-Forwarded-For,X-Real-IP")
withEnv(t, "FORWARDED_BY_CLIENT_IP", "false")
cfg, err := loadConfig()
if err != nil {
t.Fatalf("loadConfig() error = %v", err)
}
if len(cfg.TrustedProxies) != 2 || cfg.TrustedProxies[0] != "10.0.0.0/8" || cfg.TrustedProxies[1] != "172.16.0.0/12" {
t.Fatalf("unexpected TrustedProxies %v", cfg.TrustedProxies)
}
if len(cfg.RemoteIPHeaders) != 2 || cfg.RemoteIPHeaders[0] != "X-Forwarded-For" || cfg.RemoteIPHeaders[1] != "X-Real-IP" {
t.Fatalf("unexpected RemoteIPHeaders %v", cfg.RemoteIPHeaders)
}
if cfg.ForwardedByClientIP {
t.Fatalf("expected ForwardedByClientIP false")
}
}
func withEnv(t *testing.T, key, value string) {
t.Helper()
old, existed := os.LookupEnv(key)