Files
golib/logger/entry/doc.go
nabbar 3837f0b2bb Improvements, test & documentatons (2025-12 #1)
[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, ...)
2025-12-02 02:56:20 +01:00

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