mirror of
https://github.com/nabbar/golib.git
synced 2025-12-24 11:51:02 +08:00
[file/bandwidth] - ADD documentation: add enhanced README and TESTING guidelines - ADD tests: complete test suites with benchmarks, concurrency, and edge cases [file/perm] - ADD documentation: add enhanced README and TESTING guidelines - ADD tests: complete test suites with benchmarks, concurrency, and edge cases - ADD function to parse form "rwx-wxr-x" or "-rwx-w-r-x" - ADD function to ParseFileMode to convert os.FileMode to file.Perm [file/progress] - ADD documentation: add enhanced README and TESTING guidelines - ADD tests: complete test suites with benchmarks, concurrency, and edge cases [ioutils/...] - UPDATE documentation: update enhanced README and TESTING guidelines - UPDATE tests: complete test suites with benchmarks, concurrency, and edge cases [logger/...] - UPDATE documentation: update enhanced README and TESTING guidelines - ADD documentation: add enhanced README and TESTING guidelines for sub packages - UPDATE tests: complete test suites with benchmarks, concurrency, and edge cases - UPDATE config: remove FileBufferSize from OptionFile (rework hookfile) - UPDATE fields: expose Store function in interface - REWORK hookfile: rework package, use aggregator to allow multi write and single file - FIX hookstderr: fix bug with NonColorable - FIX hookstdout: fix bug with NonColorable - FIX hookwriter: fix bug with NonColorable [network/protocol] - ADD function IsTCP, IsUDP, IsUnixLike to check type of protocol [runner] - FIX typo [socket] - UPDATE documentation: update enhanced README and TESTING guidelines - ADD documentation: add enhanced README and TESTING guidelines for sub packages - UPDATE tests: complete test suites with benchmarks, concurrency, and edge cases - REWORK server: use context compatible io.reader, io.writer, io.closer instead of reader / writer - REWORK server: simplify, optimize server - REMOVE reader, writer type - ADD context: add new interface in root socket interface to expose context interface that extend context, io reader/writer/closer, dediacted function to server (IsConnected, ...)
302 lines
11 KiB
Go
302 lines
11 KiB
Go
/*
|
|
* MIT License
|
|
*
|
|
* Copyright (c) 2025 Nicolas JUHEL
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*
|
|
*
|
|
*/
|
|
|
|
// Package entry provides a flexible, chainable logger entry wrapper for structured logging with logrus.
|
|
//
|
|
// # Overview
|
|
//
|
|
// The entry package wraps logrus entries to provide a fluent, chainable API for constructing structured
|
|
// log entries with context information, custom fields, errors, and arbitrary data. It supports integration
|
|
// with Gin web framework for automatic error registration.
|
|
//
|
|
// # Design Philosophy
|
|
//
|
|
// The package follows these core principles:
|
|
//
|
|
// 1. Immutability Pattern: All setter methods return the entry itself, enabling method chaining while
|
|
// maintaining a fluent API design.
|
|
//
|
|
// 2. Lazy Evaluation: The actual logging to logrus is deferred until the Log() or Check() method is called,
|
|
// allowing entries to be built incrementally.
|
|
//
|
|
// 3. Flexible Context: Entries can include timestamps, stack traces, caller information, file/line numbers,
|
|
// custom fields, arbitrary data, and multiple errors.
|
|
//
|
|
// 4. Safety First: All methods handle nil entries gracefully, returning nil or appropriate defaults rather
|
|
// than panicking.
|
|
//
|
|
// # Key Features
|
|
//
|
|
// - Fluent API: Chain methods for concise entry construction
|
|
// - Multiple log levels: Debug, Info, Warn, Error, Fatal, Panic, and Nil
|
|
// - Rich context: Time, stack, caller, file, line, and message
|
|
// - Custom fields: Add structured key-value pairs
|
|
// - Error handling: Multiple errors with nil filtering
|
|
// - Data attachment: Attach arbitrary data structures
|
|
// - Gin integration: Automatic error registration in Gin context
|
|
// - Message-only mode: Simple logging without structured fields
|
|
//
|
|
// # Architecture
|
|
//
|
|
// The package consists of the following components:
|
|
//
|
|
// ┌──────────────────────────────────────┐
|
|
// │ Entry Interface │
|
|
// │ - Configuration methods │
|
|
// │ - Field management │
|
|
// │ - Error management │
|
|
// │ - Logging methods │
|
|
// └──────────────┬───────────────────────┘
|
|
// │
|
|
// ▼
|
|
// ┌──────────────────────────────────────┐
|
|
// │ entry Implementation │
|
|
// │ │
|
|
// │ ┌────────────────────────────────┐ │
|
|
// │ │ Configuration State │ │
|
|
// │ │ - Logger function │ │
|
|
// │ │ - Gin context pointer │ │
|
|
// │ │ - Message-only flag │ │
|
|
// │ └────────────────────────────────┘ │
|
|
// │ │ │
|
|
// │ ▼ │
|
|
// │ ┌────────────────────────────────┐ │
|
|
// │ │ Context Information │ │
|
|
// │ │ - Time, Stack, Caller │ │
|
|
// │ │ - File, Line, Message │ │
|
|
// │ └────────────────────────────────┘ │
|
|
// │ │ │
|
|
// │ ▼ │
|
|
// │ ┌────────────────────────────────┐ │
|
|
// │ │ Data & Fields │ │
|
|
// │ │ - Custom fields │ │
|
|
// │ │ - Errors slice │ │
|
|
// │ │ - Arbitrary data │ │
|
|
// │ └────────────────────────────────┘ │
|
|
// │ │ │
|
|
// │ ▼ │
|
|
// │ Log to logrus │
|
|
// └──────────────────────────────────────┘
|
|
//
|
|
// # Entry Lifecycle
|
|
//
|
|
// A typical entry follows this lifecycle:
|
|
//
|
|
// 1. Creation: New(level) creates an entry with initial state
|
|
// 2. Configuration: Set logger, level, gin context, message mode
|
|
// 3. Context: Set time, stack, caller, file, line, message
|
|
// 4. Fields: Add, merge, or set custom structured fields
|
|
// 5. Errors: Add or set error information
|
|
// 6. Data: Attach arbitrary data structures
|
|
// 7. Logging: Call Log() or Check() to output to logrus
|
|
//
|
|
// # Logging Behavior
|
|
//
|
|
// The Log() method behavior depends on the entry configuration:
|
|
//
|
|
// Normal Mode (clean=false):
|
|
// - Includes all context fields (time, stack, caller, file, line)
|
|
// - Includes custom fields and data
|
|
// - Formats errors as comma-separated string
|
|
// - Respects log level filtering
|
|
// - Registers errors in Gin context if configured
|
|
//
|
|
// Message-Only Mode (clean=true):
|
|
// - Outputs only the message text
|
|
// - Ignores all context fields and custom fields
|
|
// - Uses simple Info level logging
|
|
// - Suitable for console output or simple logs
|
|
//
|
|
// Special Cases:
|
|
// - NilLevel entries are never logged
|
|
// - Nil logger or nil fields prevent logging
|
|
// - FatalLevel triggers os.Exit(1) after logging
|
|
//
|
|
// # Level Hierarchy
|
|
//
|
|
// Log levels from most to least verbose:
|
|
// - PanicLevel: System panic situations
|
|
// - FatalLevel: Fatal errors (triggers exit)
|
|
// - ErrorLevel: Error conditions
|
|
// - WarnLevel: Warning conditions
|
|
// - InfoLevel: Informational messages
|
|
// - DebugLevel: Debug information
|
|
// - TraceLevel: Detailed trace information
|
|
// - NilLevel: Disabled logging
|
|
//
|
|
// # Field Management
|
|
//
|
|
// Fields are managed through the logger/fields package and provide:
|
|
// - Type-safe key-value storage
|
|
// - Merge operations for combining field sets
|
|
// - Deletion of specific keys
|
|
// - Integration with logrus.Fields
|
|
//
|
|
// Fields must be initialized with FieldSet() before using FieldAdd(), FieldMerge(), or FieldClean().
|
|
//
|
|
// # Error Handling
|
|
//
|
|
// The package supports multiple error patterns:
|
|
//
|
|
// Standard Errors:
|
|
// - Add individual errors with ErrorAdd()
|
|
// - Set entire error slice with ErrorSet()
|
|
// - Clear errors with ErrorClean()
|
|
//
|
|
// Error Filtering:
|
|
// - ErrorAdd(cleanNil=true, ...) filters out nil errors
|
|
// - ErrorAdd(cleanNil=false, ...) includes nil errors
|
|
//
|
|
// Wrapped Errors:
|
|
// - Automatically unwraps github.com/nabbar/golib/errors
|
|
// - Extracts error slices from wrapped errors
|
|
// - Supports fmt.Errorf %w wrapping
|
|
//
|
|
// # Integration Points
|
|
//
|
|
// Logrus Integration:
|
|
// - Requires logger function returning *logrus.Logger
|
|
// - Uses logrus.Entry for actual logging
|
|
// - Supports all logrus formatters and hooks
|
|
//
|
|
// Gin Integration:
|
|
// - SetGinContext() enables automatic error registration
|
|
// - Errors are added to Gin context error slice
|
|
// - Useful for HTTP error handling and middleware
|
|
//
|
|
// # Performance Considerations
|
|
//
|
|
// Memory:
|
|
// - Entry struct is lightweight (~300 bytes base)
|
|
// - Fields and errors use slice allocation
|
|
// - No memory pooling (entries are short-lived)
|
|
//
|
|
// CPU:
|
|
// - Method chaining has minimal overhead
|
|
// - Field operations delegate to logger/fields package
|
|
// - Log() method performs string building and formatting
|
|
//
|
|
// Concurrency:
|
|
// - Entries are NOT thread-safe
|
|
// - Create separate entry per goroutine
|
|
// - Logger function should return thread-safe logger
|
|
//
|
|
// # Use Cases
|
|
//
|
|
// Simple Logging:
|
|
//
|
|
// entry.New(loglvl.InfoLevel).
|
|
// SetLogger(loggerFunc).
|
|
// FieldSet(fields).
|
|
// SetEntryContext(time.Now(), 0, "", "", 0, "Hello").
|
|
// Log()
|
|
//
|
|
// Error Logging:
|
|
//
|
|
// entry.New(loglvl.ErrorLevel).
|
|
// SetLogger(loggerFunc).
|
|
// FieldSet(fields).
|
|
// ErrorAdd(true, err1, err2).
|
|
// SetEntryContext(time.Now(), 0, "func", "file.go", 42, "Failed").
|
|
// Log()
|
|
//
|
|
// Structured Logging with Data:
|
|
//
|
|
// entry.New(loglvl.InfoLevel).
|
|
// SetLogger(loggerFunc).
|
|
// FieldSet(fields).
|
|
// FieldAdd("user_id", userID).
|
|
// DataSet(requestData).
|
|
// SetEntryContext(time.Now(), 0, "", "", 0, "Request processed").
|
|
// Log()
|
|
//
|
|
// Gin Error Registration:
|
|
//
|
|
// e := entry.New(loglvl.ErrorLevel).
|
|
// SetLogger(loggerFunc).
|
|
// SetGinContext(c).
|
|
// FieldSet(fields).
|
|
// ErrorAdd(true, dbError).
|
|
// SetEntryContext(time.Now(), 0, "", "", 0, "Database failed")
|
|
// e.Log() // Registers error in c.Errors
|
|
//
|
|
// Conditional Logging:
|
|
//
|
|
// e := entry.New(loglvl.ErrorLevel).
|
|
// SetLogger(loggerFunc).
|
|
// FieldSet(fields).
|
|
// ErrorAdd(true, err)
|
|
// if e.Check(loglvl.InfoLevel) {
|
|
// // Has errors, logged at ErrorLevel
|
|
// } else {
|
|
// // No errors, logged at InfoLevel
|
|
// }
|
|
//
|
|
// # Best Practices
|
|
//
|
|
// DO:
|
|
// - Always call FieldSet() before FieldAdd/FieldMerge/FieldClean
|
|
// - Use method chaining for concise entry construction
|
|
// - Filter nil errors with cleanNil=true in production
|
|
// - Create new entry per log statement
|
|
// - Set logger function that returns valid logger
|
|
//
|
|
// DON'T:
|
|
// - Share entries across goroutines
|
|
// - Call FieldAdd/FieldMerge/FieldClean without FieldSet
|
|
// - Ignore FatalLevel effects (os.Exit)
|
|
// - Mutate fields/errors after logging
|
|
// - Use PanicLevel in production code
|
|
//
|
|
// # Limitations
|
|
//
|
|
// - No automatic caller detection (must provide manually)
|
|
// - No log buffering or batching
|
|
// - No built-in sampling or rate limiting
|
|
// - Fields must be initialized before use
|
|
// - Not thread-safe (by design)
|
|
//
|
|
// # Dependencies
|
|
//
|
|
// Standard Library:
|
|
// - os: For exit on fatal level
|
|
// - strings: For error message joining
|
|
// - time: For timestamp handling
|
|
//
|
|
// External:
|
|
// - github.com/sirupsen/logrus: Core logging engine
|
|
// - github.com/gin-gonic/gin: Gin framework integration
|
|
// - github.com/nabbar/golib/logger/fields: Field management
|
|
// - github.com/nabbar/golib/logger/level: Log level definitions
|
|
// - github.com/nabbar/golib/logger/types: Type constants
|
|
// - github.com/nabbar/golib/errors: Error utilities
|
|
//
|
|
// # Package Status
|
|
//
|
|
// This package is production-ready and stable. It is widely used in nabbar/golib ecosystem
|
|
// for structured logging across multiple packages.
|
|
package entry
|