diff --git a/examples/basic/main.go b/examples/basic/main.go new file mode 100644 index 0000000..ab49b17 --- /dev/null +++ b/examples/basic/main.go @@ -0,0 +1,36 @@ +// Example: basic usage of log-socket as a drop-in logger. +// +// This demonstrates using the package-level logging functions, +// which work similarly to the standard library's log package. +package main + +import ( + "fmt" + "net/http" + + "github.com/taigrr/log-socket/v2/browser" + logger "github.com/taigrr/log-socket/v2/log" + "github.com/taigrr/log-socket/v2/ws" +) + +func main() { + defer logger.Flush() + + // Set the minimum log level (default is LTrace, showing everything) + logger.SetLogLevel(logger.LDebug) + + // Package-level functions log to the "default" namespace + logger.Info("Application starting up") + logger.Debug("Debug mode enabled") + logger.Warnf("Config file not found at %s, using defaults", "/etc/app/config.yaml") + logger.Errorf("Failed to connect to database: %s", "connection refused") + + // Print/Printf/Println are aliases for Info + logger.Println("This is equivalent to Infoln") + + // Start the web UI so you can view logs at http://localhost:8080 + http.HandleFunc("/ws", ws.LogSocketHandler) + http.HandleFunc("/", browser.LogSocketViewHandler) + fmt.Println("Log viewer available at http://localhost:8080") + logger.Fatal(http.ListenAndServe("0.0.0.0:8080", nil)) +} diff --git a/examples/client/main.go b/examples/client/main.go new file mode 100644 index 0000000..f6fb9e5 --- /dev/null +++ b/examples/client/main.go @@ -0,0 +1,63 @@ +// Example: programmatic log client with namespace filtering. +// +// This shows how to create a Client that receives log entries +// programmatically, optionally filtered to specific namespaces. +// Useful for building custom log processors, alerting, or forwarding. +package main + +import ( + "fmt" + "time" + + logger "github.com/taigrr/log-socket/v2/log" +) + +func main() { + defer logger.Flush() + + // Create a client that receives ALL log entries + allLogs := logger.CreateClient() + allLogs.SetLogLevel(logger.LInfo) + + // Create a client that only receives "database" and "auth" logs + securityLogs := logger.CreateClient("database", "auth") + securityLogs.SetLogLevel(logger.LWarn) // Only warnings and above + + dbLog := logger.NewLogger("database") + authLog := logger.NewLogger("auth") + apiLog := logger.NewLogger("api") + + // Process all logs + go func() { + for { + entry := allLogs.Get() + fmt.Printf("[ALL] %s [%s] %s: %s\n", + entry.Timestamp.Format(time.TimeOnly), + entry.Namespace, entry.Level, entry.Output) + } + }() + + // Process only security-relevant warnings/errors + go func() { + for { + entry := securityLogs.Get() + if entry.Level == "ERROR" || entry.Level == "WARN" { + fmt.Printf("🚨 SECURITY ALERT [%s] %s: %s\n", + entry.Namespace, entry.Level, entry.Output) + } + } + }() + + // Generate some logs + for i := 0; i < 5; i++ { + apiLog.Info("API request processed") + dbLog.Info("Query executed successfully") + dbLog.Warn("Connection pool running low") + authLog.Error("Brute force attempt detected") + time.Sleep(1 * time.Second) + } + + // Clean up clients when done + allLogs.Destroy() + securityLogs.Destroy() +} diff --git a/examples/log-levels/main.go b/examples/log-levels/main.go new file mode 100644 index 0000000..5c922b5 --- /dev/null +++ b/examples/log-levels/main.go @@ -0,0 +1,48 @@ +// Example: log level filtering and all available levels. +// +// log-socket supports 8 log levels from TRACE (most verbose) +// to FATAL (least verbose). Setting a log level filters out +// everything below it. +package main + +import ( + "fmt" + + logger "github.com/taigrr/log-socket/v2/log" +) + +func main() { + defer logger.Flush() + + fmt.Println("=== All log levels (TRACE and above) ===") + logger.SetLogLevel(logger.LTrace) + + logger.Trace("Detailed execution trace — variable x = 42") + logger.Debug("Processing request for user_id=123") + logger.Info("Server started on :8080") + logger.Notice("Configuration reloaded") + logger.Warn("Disk usage at 85%") + logger.Error("Failed to send email: SMTP timeout") + // logger.Panic("...") — would panic + // logger.Fatal("...") — would os.Exit(1) + + fmt.Println("\n=== Formatted variants ===") + logger.Infof("Request took %dms", 42) + logger.Warnf("Retrying in %d seconds (attempt %d/%d)", 5, 2, 3) + logger.Errorf("HTTP %d: %s", 503, "Service Unavailable") + + fmt.Println("\n=== Only WARN and above ===") + logger.SetLogLevel(logger.LWarn) + + logger.Debug("This will NOT appear") + logger.Info("This will NOT appear either") + logger.Warn("This WILL appear") + logger.Error("This WILL appear too") + + fmt.Println("\n=== Per-logger levels via namespaced loggers ===") + logger.SetLogLevel(logger.LTrace) // Reset global + + appLog := logger.NewLogger("app") + appLog.Info("Namespaced loggers inherit the global output but tag entries") + appLog.Warnf("Something needs attention in the %s subsystem", "app") +} diff --git a/examples/namespaces/main.go b/examples/namespaces/main.go new file mode 100644 index 0000000..ffbd210 --- /dev/null +++ b/examples/namespaces/main.go @@ -0,0 +1,73 @@ +// Example: namespace-based logging for organizing logs by component. +// +// Namespaces let you tag log entries by subsystem (api, database, auth, etc.) +// and filter them in the web UI or via programmatic clients. +package main + +import ( + "fmt" + "math/rand" + "net/http" + "time" + + "github.com/taigrr/log-socket/v2/browser" + logger "github.com/taigrr/log-socket/v2/log" + "github.com/taigrr/log-socket/v2/ws" +) + +func main() { + defer logger.Flush() + + // Create loggers for different subsystems + apiLog := logger.NewLogger("api") + dbLog := logger.NewLogger("database") + authLog := logger.NewLogger("auth") + cacheLog := logger.NewLogger("cache") + + // Simulate application activity + go func() { + for { + apiLog.Infof("GET /api/users — 200 OK (%dms)", rand.Intn(200)) + apiLog.Debugf("Request headers: Accept=application/json") + time.Sleep(1 * time.Second) + } + }() + + go func() { + for { + dbLog.Infof("SELECT * FROM users — %d rows", rand.Intn(100)) + if rand.Float64() < 0.3 { + dbLog.Warn("Slow query detected (>500ms)") + } + time.Sleep(2 * time.Second) + } + }() + + go func() { + for { + if rand.Float64() < 0.7 { + authLog.Info("User login successful") + } else { + authLog.Error("Failed login attempt from 192.168.1.42") + } + time.Sleep(3 * time.Second) + } + }() + + go func() { + for { + cacheLog.Tracef("Cache hit ratio: %.1f%%", rand.Float64()*100) + if rand.Float64() < 0.1 { + cacheLog.Warn("Cache eviction triggered") + } + time.Sleep(5 * time.Second) + } + }() + + // The /api/namespaces endpoint lists all active namespaces + http.HandleFunc("/ws", ws.LogSocketHandler) + http.HandleFunc("/api/namespaces", ws.NamespacesHandler) + http.HandleFunc("/", browser.LogSocketViewHandler) + fmt.Println("Log viewer with namespace filtering at http://localhost:8080") + logger.Fatal(http.ListenAndServe("0.0.0.0:8080", nil)) +}