hooksyslog

package
v1.19.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 4, 2026 License: MIT Imports: 22 Imported by: 0

README

Logger HookSyslog

Go Version License Coverage

Thread-safe logrus hook that writes log entries to syslog (Unix/Linux) or Windows Event Log with asynchronous buffered processing, automatic reconnection, and flexible field filtering.


Table of Contents


Overview

The hooksyslog package provides a production-ready logrus hook for sending structured logs to syslog (RFC 5424) on Unix/Linux systems or Windows Event Log on Windows. It features asynchronous buffered writes, automatic reconnection, and flexible configuration to handle high-throughput logging scenarios.

Design Philosophy
  1. Platform Agnostic: Seamless support for Unix syslog and Windows Event Log
  2. Non-Blocking: Asynchronous buffered writes prevent logging from slowing down application
  3. Reliability: Automatic reconnection on network failures
  4. Flexibility: Configurable field filtering and log level mapping
  5. Standards Compliance: Full RFC 5424 syslog compatibility
Key Features
  • Multi-Platform: Unix/Linux (tcp, udp, unix, unixgram) and Windows (Event Log)
  • Asynchronous Processing: Buffered channel (250 entries) for non-blocking writes
  • Auto-Reconnection: Automatic retry every 1 second on connection failures
  • Logrus Integration: Implements logrus.Hook interface seamlessly
  • Field Filtering: Optional removal of stack, timestamp, and trace fields
  • Access Log Mode: Special mode where message is used instead of fields
  • Level Filtering: Configure which log levels are sent to syslog
  • Graceful Shutdown: Context-based shutdown for clean application termination
  • RFC 5424 Compliant: Standard syslog severity and facility codes
  • Zero External Dependencies: Only standard library and golib packages

Architecture

Component Diagram
┌────────────────────────────────────────────────────────────────┐
│                      HookSyslog                                │
├────────────────────────────────────────────────────────────────┤
│                                                                │
│  ┌──────────┐         ┌──────────────┐        ┌──────────────┐ │
│  │ Logrus   │────────▶│              │───────▶│              │ │
│  │ Entry    │         │              │        │              │ │
│  │          │         │              │        │              │ │
│  │ Fields   │         │   Buffered   │        │  Aggregator  │ │
│  │ Level    │         │   Channel    │        │  Goroutine   │ │
│  │ Message  │────────▶│  (cap: 250)  │───────▶│              │ │
│  │          │         │              │        │              │ │
│  └──────────┘         │              │        │              │ │
│                       │              │        │              │ │
│       Fire()          │    data      │        │    Write     │ │
│         │             └──────────────┘        └───────┬──────┘ │
│         │                                            │         │
│         ▼                                            ▼         │
│  ┌──────────────┐                           ┌────────────────┐ │
│  │ Formatter    │                           │    Client      │ │
│  │ JSON/Text    │                           │  (Socket)      │ │
│  └──────────────┘                           │                │ │
│                                             │  Unix: syslog  │ │
│  ┌──────────────┐                           │  Win: EventLog │ │
│  │ Field Filter │                           └────────────────┘ │
│  │ - Stack      │                                   │          │
│  │ - Timestamp  │                                   ▼          │
│  │ - Trace      │                          ┌─────────────────┐ │
│  └──────────────┘                          │  Syslog/Event   │ │
│                                            │      Log        │ │
│                                            └─────────────────┘ │
└────────────────────────────────────────────────────────────────┘
Data Flow
Logrus Log Statement → Fire(entry) → Format → Filter → Channel → Aggregator → Syslog
                           │            │        │         │        │           │
                           │            │        │         │        │           └─▶ TCP/UDP/Unix
                           │            │        │         │        │
                           │            │        │         │        └─▶ Retry on failure
                           │            │        │         │
                           │            │        │         └─▶ Buffer (250 entries)
                           │            │        │
                           │            │        └─▶ Remove stack/time/trace fields
                           │            │
                           │            └─▶ JSON or Text formatting
                           │
                           └─▶ Map logrus level to syslog severity
Platform Support

Unix/Linux (via log/syslog):

  • Protocols: TCP, UDP, Unix domain sockets (stream/datagram)
  • Syslog Daemon: Compatible with rsyslog, syslog-ng, systemd-journald
  • Network: Supports remote syslog servers
  • Build Tag: linux or darwin

Windows (via golang.org/x/sys/windows/svc/eventlog):

  • Event Log: Writes to Windows Event Log
  • Registration: Automatic service registration on first use
  • Severity Mapping: Maps syslog severities to Windows event types
  • Build Tag: windows

Performance

Benchmarks

Based on test suite results (40 specs, AMD64):

Operation Median Mean Max Notes
Hook Creation ~10ms ~15ms ~50ms Includes syslog connection check
Fire() (fields) <100µs <500µs <2ms Non-blocking (buffered)
Fire() (access log) <50µs <300µs <1ms Message-only mode
WriteSev() <100µs <200µs <1ms Direct write to buffer
Run() startup ~100ms ~150ms ~200ms Initial syslog connection
Shutdown (Close) ~50ms ~100ms ~200ms Graceful channel close

Throughput:

  • Single logger: ~10,000 entries/second
  • Multiple hooks: ~5,000 entries/second per hook
  • Network I/O: Limited by syslog server, not hook overhead
Memory Usage
Base overhead:        ~2KB (struct + channels)
Per buffered entry:   len(formatted) + ~64 bytes (data struct + channel overhead)
Total at capacity:    250 × (AvgEntrySize + 64 bytes)

Example:

  • Buffer capacity: 250
  • Average entry: 256 bytes (JSON formatted)
  • Peak memory ≈ 250 × 320 = 80KB
Scalability
  • Concurrent Loggers: Tested with up to 10 concurrent loggers
  • Buffer Capacity: Fixed at 250 entries (adjustable in code)
  • Log Levels: All logrus levels supported (Panic, Fatal, Error, Warn, Info, Debug, Trace)
  • Zero Race Conditions: All tests pass with -race detector

Use Cases

1. Centralized Log Collection

Problem: Multiple servers need to send logs to a central syslog server.

// Configure remote syslog over UDP
opts := logcfg.OptionsSyslog{
    Network:  libptc.NetworkUDP.Code(),
    Host:     "logs.example.com:514",
    Tag:      "myapp",
    Facility: "LOCAL0",
}

hook, _ := logsys.New(opts, &logrus.JSONFormatter{})
logger.AddHook(hook)

ctx, cancel := context.WithCancel(context.Background())
go hook.Run(ctx)
defer func() {
    cancel()
    hook.Close()
}()

Real-world: Used in microservices for shipping logs to ELK or Splunk via syslog forwarders.

2. HTTP Access Logging

Problem: Log HTTP access logs in standard Apache/Nginx format.

// Access log mode: use entry.Message instead of fields
opts := logcfg.OptionsSyslog{
    Network:         libptc.NetworkUnixGram.Code(),
    Host:            "/dev/log",
    Tag:             "nginx-access",
    EnableAccessLog: true,  // Message mode
}

hook, _ := logsys.New(opts, nil)
logger.AddHook(hook)

// Log statement - message will be written to syslog
logger.Info("192.168.1.1 - - [01/Dec/2025:20:00:00 +0100] \"GET /api HTTP/1.1\" 200 1234")
3. System Service Logging

Problem: Daemon service needs to log to system syslog (journald/Event Log).

// Unix: logs to journald via /dev/log
// Windows: logs to Windows Event Log
opts := logcfg.OptionsSyslog{
    Network:  libptc.NetworkUnixGram.Code(),  // or NetworkUnknown for default
    Host:     "",  // Default system socket
    Tag:      "myservice",
    Facility: "DAEMON",
    LogLevel: []string{"info", "warning", "error"},
}

hook, _ := logsys.New(opts, &logrus.TextFormatter{})
logger.AddHook(hook)
4. Security Audit Trail

Problem: Security-sensitive operations need to be logged to tamper-proof syslog.

opts := logcfg.OptionsSyslog{
    Network:  libptc.NetworkTCP.Code(),  // TCP for reliability
    Host:     "audit.internal:601",
    Tag:      "security-audit",
    Facility: "AUTHPRIV",  // Restricted facility
    LogLevel: []string{"warning", "error"},  // Security events only
}

hook, _ := logsys.New(opts, &logrus.JSONFormatter{})
securityLogger.AddHook(hook)

// All security events go to dedicated audit syslog
securityLogger.WithFields(logrus.Fields{
    "user":   "admin",
    "action": "login",
    "source": "192.168.1.100",
}).Warn("Failed login attempt")
5. Multi-Destination Logging

Problem: Send different log levels to different syslog destinations.

// Errors to dedicated error server
errorOpts := logcfg.OptionsSyslog{
    Network:  libptc.NetworkUDP.Code(),
    Host:     "errors.example.com:514",
    Tag:      "myapp-errors",
    LogLevel: []string{"error", "fatal"},
}

// All logs to general server
allOpts := logcfg.OptionsSyslog{
    Network:  libptc.NetworkUDP.Code(),
    Host:     "logs.example.com:514",
    Tag:      "myapp",
}

errorHook, _ := logsys.New(errorOpts, nil)
allHook, _ := logsys.New(allOpts, nil)

logger.AddHook(errorHook)
logger.AddHook(allHook)

Quick Start

Installation
go get github.com/nabbar/golib/logger/hooksyslog
Basic Example
package main

import (
    "context"
    "github.com/sirupsen/logrus"
    
    logcfg "github.com/nabbar/golib/logger/config"
    logsys "github.com/nabbar/golib/logger/hooksyslog"
    libptc "github.com/nabbar/golib/network/protocol"
)

func main() {
    // Create logger
    logger := logrus.New()
    
    // Configure syslog hook
    opts := logcfg.OptionsSyslog{
        Network:  libptc.NetworkUDP.Code(),
        Host:     "localhost:514",
        Tag:      "myapp",
        LogLevel: []string{"info", "warning", "error"},
    }
    
    hook, err := logsys.New(opts, &logrus.JSONFormatter{})
    if err != nil {
        panic(err)
    }
    
    // Register hook
    logger.AddHook(hook)
    
    // Start background writer
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()
    go hook.Run(ctx)
    
    // Graceful shutdown
    defer func() {
        cancel()
        hook.Close()
    }()
    
    // IMPORTANT: In standard mode, the message parameter is IGNORED.
    // Only fields are formatted and sent to syslog.
    logger.WithField("msg", "Application started").Info("ignored")
    logger.WithFields(logrus.Fields{
        "msg":     "User logged in",
        "user":    "john",
        "session": "abc123",
    }).Info("ignored")
}
Remote Syslog
// Send logs to remote syslog server via UDP
opts := logcfg.OptionsSyslog{
    Network:  libptc.NetworkUDP.Code(),
    Host:     "logs.example.com:514",
    Tag:      "myapp",
    Facility: "LOCAL0",
}

hook, _ := logsys.New(opts, &logrus.JSONFormatter{})
logger.AddHook(hook)

ctx, cancel := context.WithCancel(context.Background())
go hook.Run(ctx)
defer func() {
    cancel()
    hook.Close()
}()

// Only fields are sent - message "ignored" is discarded
logger.WithFields(logrus.Fields{
    "msg":      "Remote logging test",
    "service":  "api",
    "instance": "prod-1",
}).Info("ignored")
Access Log Mode
// Access log mode: Message IS used, fields are IGNORED
opts := logcfg.OptionsSyslog{
    Network:         libptc.NetworkUDP.Code(),
    Host:            "localhost:514",
    Tag:             "http-access",
    EnableAccessLog: true,  // Reverses behavior!
    LogLevel:        []string{"info"},
}

hook, _ := logsys.New(opts, nil)
logger.AddHook(hook)

ctx, cancel := context.WithCancel(context.Background())
go hook.Run(ctx)

// In AccessLog mode, the MESSAGE is written, fields are ignored
logger.WithFields(logrus.Fields{
    "ignored": "these fields are discarded",
}).Info("GET /api/users - 200 OK - 45ms")  // This message IS sent to syslog

defer func() {
    cancel()
    hook.Close()
}()
Level Filtering
// Only send errors and above to syslog
opts := logcfg.OptionsSyslog{
    Network:  libptc.NetworkUDP.Code(),
    Host:     "localhost:514",
    Tag:      "myapp-errors",
    LogLevel: []string{"error", "fatal"},  // Info/Debug won't be sent
}

hook, _ := logsys.New(opts, &logrus.TextFormatter{})
logger.AddHook(hook)

ctx, cancel := context.WithCancel(context.Background())
go hook.Run(ctx)

// This will NOT be sent (Info level)
logger.WithField("msg", "Request completed").Info("ignored")

// This WILL be sent (Error level)
logger.WithField("msg", "Database connection failed").Error("ignored")

defer func() {
    cancel()
    hook.Close()
}()
Field Filtering
// Remove stack traces and timestamps from syslog output
opts := logcfg.OptionsSyslog{
    Network:          libptc.NetworkUDP.Code(),
    Host:             "localhost:514",
    Tag:              "myapp",
    DisableStack:     true,  // Remove "stack" field
    DisableTimestamp: true,  // Remove "time" field
    EnableTrace:      false, // Remove "caller", "file", "line" fields
    LogLevel:         []string{"info"},
}

hook, _ := logsys.New(opts, &logrus.TextFormatter{})
logger.AddHook(hook)

ctx, cancel := context.WithCancel(context.Background())
go hook.Run(ctx)

// Fields "stack", "time", "caller" will be filtered out before sending
logger.WithFields(logrus.Fields{
    "msg":    "Filtered log entry",
    "user":   "john",
    "action": "login",
    "stack":  "will be filtered out",
    "caller": "will be filtered out",
}).Info("ignored")

defer func() {
    cancel()
    hook.Close()
}()

Best Practices

Testing

The package includes a comprehensive test suite with 84.3% code coverage and 40 test specifications using BDD methodology (Ginkgo v2 + Gomega).

Key test coverage:

  • ✅ All public APIs and lifecycle operations
  • ✅ Concurrent access with race detector (zero races detected)
  • ✅ Integration tests with mock syslog server
  • ✅ Error handling and edge cases
  • ✅ Platform-specific implementations (Unix/Windows)

For detailed test documentation, see TESTING.md.

✅ DO

Always Start Run() Goroutine:

// ✅ GOOD: Start background writer
ctx, cancel := context.WithCancel(context.Background())
go hook.Run(ctx)

// Logs are processed asynchronously
logger.Info("message")

Graceful Shutdown:

// ✅ GOOD: Complete shutdown sequence
defer func() {
    cancel()        // Signal Run() to stop
    hook.Close()    // Close channels
}()

Use Fields, Not Messages (Standard Mode):

// ✅ GOOD: Fields are sent to syslog
logger.WithFields(logrus.Fields{
    "msg":    "User logged in",
    "user":   "john",
    "action": "login",
}).Info("this message is IGNORED")

Use Messages, Not Fields (AccessLog Mode):

// ✅ GOOD: Message is sent to syslog (EnableAccessLog: true)
logger.Info("192.168.1.1 - GET /api - 200 OK")
// Fields would be ignored in this mode

Configure Appropriate Log Levels:

// ✅ GOOD: Filter noisy logs
opts := logcfg.OptionsSyslog{
    LogLevel: []string{"warning", "error"},  // Only send important logs
}

Use Structured Logging:

// ✅ GOOD: Structured fields for parsing
logger.WithFields(logrus.Fields{
    "msg":        "API request",
    "method":     "GET",
    "path":       "/api/users",
    "status":     200,
    "duration_ms": 45,
}).Info("ignored")
❌ DON'T

Don't Forget Run() Goroutine:

// ❌ BAD: Hook never processes logs
hook, _ := logsys.New(opts, nil)
logger.AddHook(hook)
// Missing: go hook.Run(ctx)

Don't Use Message Parameter (Standard Mode):

// ❌ BAD: Message "User logged in" is IGNORED
logger.Info("User logged in")

// ✅ GOOD: Use fields instead
logger.WithField("msg", "User logged in").Info("ignored")

Don't Use Fields (AccessLog Mode):

// ❌ BAD: Fields are IGNORED in AccessLog mode
logger.WithField("msg", "access log").Info("ignored")

// ✅ GOOD: Use message parameter
logger.Info("192.168.1.1 - GET /api - 200")

Don't Skip Graceful Shutdown:

// ❌ BAD: Buffered logs may be lost
cancel()
os.Exit(0)  // Immediate exit loses buffered entries

// ✅ GOOD: Wait for buffer to flush
cancel()
hook.Close()

Don't Block in Production:

// ❌ BAD: Checking IsRunning() on every log
if hook.IsRunning() {
    logger.Info("message")
}

// ✅ GOOD: Just log, hook handles buffering
logger.Info("message")

Don't Use Without Formatter (if needed):

// ❌ BAD: Default formatter may not be optimal
hook, _ := logsys.New(opts, nil)  // Uses logrus default

// ✅ GOOD: Explicit formatter for consistency
hook, _ := logsys.New(opts, &logrus.JSONFormatter{
    TimestampFormat: time.RFC3339,
})

API Reference

HookSyslog Interface
type HookSyslog interface {
    logrus.Hook
    
    // Run starts the hook's main processing loop
    Run(ctx context.Context)
    
    // IsRunning checks if the hook is currently active
    IsRunning() bool
    
    // Close terminates the hook
    Close() error
}

Methods:

  • Levels() []logrus.Level: Returns configured log levels for this hook
  • Fire(entry *logrus.Entry) error: Processes log entry (called by logrus)
  • Run(ctx context.Context): Start background writer (must be called in goroutine)
  • Close() error: Close channels
  • IsRunning() bool: Check if background writer is active
  • RegisterHook(logger): Convenience method to add hook to logger
Configuration
type OptionsSyslog struct {
    // Connection
    Network  string   // tcp, udp, unix, unixgram (NetworkProtocol code)
    Host     string   // "host:port" or socket path
    Tag      string   // Syslog tag (application name)
    Facility string   // Syslog facility (USER, DAEMON, LOCAL0-7, etc.)
    
    // Filtering
    LogLevel         []string  // Log levels to process (empty = all)
    DisableStack     bool      // Remove "stack" field
    DisableTimestamp bool      // Remove "time" field
    EnableTrace      bool      // Keep "caller", "file", "line" fields
    
    // Modes
    EnableAccessLog  bool      // Reverse behavior: use Message, ignore Fields
}

Network Protocols:

  • tcp: TCP connection (requires host:port)
  • udp: UDP datagrams (requires host:port)
  • unix: Unix domain socket stream
  • unixgram: Unix domain socket datagram
  • Empty: Platform default (/dev/log on Unix, Event Log on Windows)

Facilities:

KERN, USER, MAIL, DAEMON, AUTH, SYSLOG, LPR, NEWS,
UUCP, CRON, AUTHPRIV, FTP, LOCAL0-LOCAL7
Severity Mapping
Logrus Level Syslog Severity Numeric Description
PanicLevel ALERT 1 Action must be taken immediately
FatalLevel CRIT 2 Critical conditions
ErrorLevel ERR 3 Error conditions
WarnLevel WARNING 4 Warning conditions
InfoLevel INFO 6 Informational messages
DebugLevel DEBUG 7 Debug-level messages
TraceLevel INFO 6 Debug-level messages (fallback to INFO)
Error Handling
var errStreamClosed = errors.New("stream is closed")

Error Behavior:

  • Errors from syslog connection are logged but don't stop processing
  • Automatic reconnection every 1 second on connection failure
  • WriteSev() returns errStreamClosed if called after Close()
  • Context cancellation triggers graceful shutdown
  • Panics in Run() are recovered and logged

Contributing

Contributions are welcome! Please follow these guidelines:

  1. Code Quality

    • Follow Go best practices and idioms
    • Maintain or improve code coverage (target: >80%)
    • Pass all tests including race detector
    • Use gofmt and golint
  2. AI Usage Policy

    • AI must NEVER be used to generate package code or core functionality
    • AI assistance is limited to:
      • Testing (writing and improving tests)
      • Debugging (troubleshooting and bug resolution)
      • Documentation (comments, README, TESTING.md)
    • All AI-assisted work must be reviewed and validated by humans
  3. Testing

    • Add tests for new features
    • Use Ginkgo v2 / Gomega for test framework
    • Ensure zero race conditions with CGO_ENABLED=1 go test -race
    • Update test documentation in TESTING.md
  4. Documentation

    • Update GoDoc comments for public APIs
    • Add examples for new features
    • Update README.md and TESTING.md if needed
    • Document behavior differences (standard vs AccessLog mode)
  5. Pull Request Process

    • Fork the repository
    • Create a feature branch
    • Write clear commit messages
    • Ensure all tests pass
    • Update documentation
    • Submit PR with description of changes

Improvements & Security

Current Status

The package is production-ready with no urgent improvements or security vulnerabilities identified.

Code Quality Metrics
  • 84.3% test coverage (target: >80%)
  • Zero race conditions detected with -race flag
  • Thread-safe implementation using atomic operations and channels
  • Panic recovery in Run() goroutine
  • Platform-tested on Unix/Linux and Windows
Future Enhancements (Non-urgent)

The following enhancements could be considered for future versions:

  1. Configurable Buffer Size: Allow users to adjust channel capacity (currently fixed at 250)
  2. Metrics Export: Optional integration with Prometheus for monitoring
  3. Compression: Optional gzip compression for large log entries
  4. Batch Writing: Combine multiple entries into single syslog write for efficiency

These are optional improvements and not required for production use. The current implementation is stable and performant.


Resources

Package Documentation
  • GoDoc - Complete API reference with function signatures, method descriptions, and runnable examples. Essential for understanding the public interface and usage patterns.

  • doc.go - In-depth package documentation including design philosophy, architecture diagrams, syslog severity mapping, and best practices for production use. Provides detailed explanations of standard mode vs AccessLog mode behavior.

  • TESTING.md - Comprehensive test suite documentation covering test architecture, BDD methodology with Ginkgo v2, coverage analysis (84.3%), integration tests with mock syslog server, and guidelines for writing new tests.

  • github.com/nabbar/golib/logger/config - Configuration structures for logger components including OptionsSyslog used to configure the syslog hook. Provides standardized configuration across logger ecosystem.

  • github.com/nabbar/golib/logger/types - Common logger types and interfaces including field names (FieldStack, FieldTime) used for field filtering. Ensures consistency across logger hooks.

  • github.com/nabbar/golib/network/protocol - Network protocol enumeration and parsing used for syslog network configuration. Supports TCP, UDP, Unix sockets with type-safe protocol handling.

  • github.com/nabbar/golib/runner - Panic recovery mechanism used in Run() goroutine via RecoveryCaller(). Ensures graceful error handling without crashing the application.

External References
  • RFC 5424 - Syslog Protocol - Official syslog protocol specification defining severity levels, facility codes, and message format. The package implements full RFC 5424 compliance for Unix/Linux systems.

  • logrus Documentation - Popular structured logger for Go. This package integrates as a logrus hook, inheriting logrus's design philosophy of structured logging with fields.

  • Go log/syslog Package - Standard library syslog implementation used internally on Unix/Linux. Understanding this package helps debug connection issues and network configurations.

  • Windows Event Log - Microsoft documentation for Windows Event Log system. The package uses this API on Windows, mapping syslog severities to Windows event types.


AI Transparency

In compliance with EU AI Act Article 50.4: AI assistance was used for testing, documentation, and bug resolution under human supervision. All core functionality is human-designed and validated.


License

MIT License - See LICENSE file for details.

Copyright (c) 2025 Nicolas JUHEL


Maintained by: Nicolas JUHEL
Package: github.com/nabbar/golib/logger/hooksyslog
Version: See releases for versioning

Documentation

Overview

Package hooksyslog provides a robust and flexible logrus hook for writing log entries to syslog endpoints. It leverages a custom socket implementation for cross-platform network communication (TCP, UDP, Unix sockets), ensuring that syslog messages can be sent from any supported OS, including Windows. The package is designed for high-performance, asynchronous, and buffered logging with features like connection aggregation, automatic reconnection, and RFC 5424 compliance.

Overview

The `hooksyslog` package integrates with `logrus` to redirect log messages to local or remote syslog servers. By abstracting network communication, it provides a unified logging mechanism across different operating systems. The implementation ensures non-blocking log operations by delegating buffering and asynchronous writing to an underlying aggregator component, which processes log entries in a dedicated background goroutine.

Design Philosophy

The core principles guiding the design of this package are:

  • True Cross-Platform Support: A single, consistent API for sending syslog messages over the network from any OS, including Windows, without relying on platform-specific logging APIs like Windows Event Log.
  • Asynchronous Operation: Log calls from the application are non-blocking. The hook delegates the I/O operations to an internal aggregator that uses a buffered channel and a background worker, preventing performance bottlenecks.
  • Connection Efficiency: A global connection aggregator manages and shares network connections to syslog endpoints. This reduces the overhead of creating new connections for each hook instance and minimizes resource usage.
  • Robustness and Reliability: The underlying socket client implements automatic reconnection logic, ensuring that logging can resume seamlessly after transient network or service disruptions.
  • Standard Compliance: Adheres to RFC 5424 for syslog message formatting, including priority, facility, and severity, enabling seamless integration with standard syslog collectors and analyzers.

Architecture

The package's architecture is designed for modularity, connection sharing, and asynchronous processing.

┌───────────────────────────────────────────────────────────────────────────┐
│                           Application (logrus)                            │
│                                                                           │
│  ┌─────────────────────────────────────────────────────────────────────┐  │
│  │                          HookSyslog Interface                       │  │
│  │                        (logrus.Hook + Closer)                       │  │
│  └───────────────────────────────▲─────────────────────────────────────┘  │
│                                   │                                       │
│                                   │ Fire(entry *logrus.Entry)             │
│                                   │ (non-blocking, writes to aggregator)  │
│                                   │                                       │
│  ┌────────────────────────────────▼────────────────────────────────────┐  │
│  │                           hks struct                                │  │
│  │  - Formatter and log level configuration                            │  │
│  │  - Reference to a shared, global connection aggregator (io.Writer)  │  │
│  └─────────────────────────────────▲───────────────────────────────────┘  │
│                                    │                                      │
│                                    │ (Shared across multiple hooks)       │
│                                    │                                      │
│  ┌─────────────────────────────────▼───────────────────────────────────┐  │
│  │                    Global Connection Aggregator Map                 │  │
│  │           (Manages one aggregator per unique syslog endpoint)       │  │
│  │                                                                     │  │
│  │  ┌───────────────────────────────────────────────────────────────┐  │  │
│  │  │                 sysAgg (Connection Aggregator)                │  │  │
│  │  │  - Reference counting for active hooks                        │  │  │
│  │  │  - Wraps an `iotagg.Aggregator` for buffering & async writes  │  │  │
│  │  │  - Holds the underlying `libsck.Client` socket connection     │  │  │
│  │  └──────────────────────────────▲────────────────────────────────┘  │  │
│  └─────────────────────────────────│───────────────────────────────────┘  │
│                                    │                                      │
│                                    │ (Delegated Async Processing)         │
│                                    │                                      │
│  ┌─────────────────────────────────▼───────────────────────────────────┐  │
│  │               iotagg.Aggregator (from ioutils package)              │  │
│  │  - Internal buffer (250 entries) and background goroutine           │  │
│  │  - Pulls formatted messages and writes them to the socket           │  │
│  │  - Manages write synchronization and error handling                 │  │
│  └─────────────────────────────────▲───────────────────────────────────┘  │
│                                    │                                      │
│                                    │ Write to network socket              │
│                                    │                                      │
│  ┌─────────────────────────────────▼───────────────────────────────────┐  │
│  │                libsck.Client (from socket package)                  │  │
│  │  - Cross-platform TCP, UDP, and Unix socket client                  │  │
│  │  - Handles connection establishment and automatic reconnection      │  │
│  └─────────────────────────────────────────────────────────────────────┘  │
│                                                                           │
└───────────────────────────────────────────────────────────────────────────┘

Platform-Specific Behavior

The hook now provides consistent behavior across all platforms by using a network-first approach.

  • Unix/Linux (`sys_syslog.go`): If no network address is specified, the hook attempts to auto-discover the local syslog service by checking for standard Unix domain sockets (`/dev/log`, `/var/run/syslog`).

  • Windows (`sys_winlog.go`): Local syslog auto-discovery is not supported. An explicit network address (e.g., "udp", "localhost:514") must be provided in the configuration. The hook will send standard syslog messages to this endpoint.

Key Features

  • Connection Aggregation: A global, thread-safe map manages a pool of aggregators, one for each unique syslog endpoint (protocol/address pair). This allows multiple `HookSyslog` instances to share a single underlying network connection, significantly reducing resource consumption. Reference counting ensures connections are closed only when no hooks are using them.

  • Delegated Asynchronous Writing: The hook itself is lightweight. The heavy lifting of buffering, asynchronous processing, and I/O is delegated to the `iotagg.Aggregator` component. This component runs a background goroutine to process a buffer of 250 log entries, ensuring `Fire()` calls are non-blocking.

  • Automatic Reconnection: The underlying `libsck.Client` automatically handles connection failures. If a write fails, it will attempt to reconnect to the syslog server before retrying the write, providing resilience against transient network issues.

  • RFC 5424 Formatting: The hook manually constructs RFC 5424-compliant syslog messages, including the priority value (calculated from facility and severity), timestamp, hostname, tag, and the log message itself.

Advantages

  • True Cross-Platform Operation: Eliminates dependencies on platform-specific APIs like `log/syslog` or Windows Event Log, providing a consistent syslog-over-network implementation everywhere.
  • Resource Efficiency: Connection aggregation prevents the proliferation of sockets when multiple hooks point to the same destination.
  • Non-blocking: Logrus calls return immediately, as I/O is handled by a background worker in the shared aggregator.
  • Reliable: The combination of buffering and automatic reconnection minimizes log loss during temporary service unavailability.

Disadvantages

  • Latency: Asynchronous writes introduce a small delay between the log call and the actual transmission of the syslog message.
  • Error Handling: Network errors are handled internally by the aggregator and printed to `os.Stderr`. They are not propagated back to the application's logging call.
  • Global State: The use of a global map for connection aggregation introduces a shared state within the application, which can have implications for testing and resource management in complex scenarios.

Limitations

  • Buffer Overflow: If the rate of log production consistently exceeds the network write speed, the internal buffer (250 entries) can fill up, causing subsequent `Fire()` calls to block.
  • No TLS: The current socket implementation does not support TLS-encrypted syslog connections.

Example Usage

Refer to the `example_test.go` file for comprehensive examples, including:

  • Configuration for remote syslog via TCP/UDP on any platform.
  • Auto-discovery of local syslog on Unix-like systems.
  • Graceful shutdown patterns using the `Close()` method on the hook.
Example (AccessLog)

Example_accessLog demonstrates using access log mode for HTTP request logging. In this mode, behavior is reversed: the message IS written, fields are IGNORED.

package main

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/sirupsen/logrus"

	logcfg "github.com/nabbar/golib/logger/config"
	logsys "github.com/nabbar/golib/logger/hooksyslog"

	libptc "github.com/nabbar/golib/network/protocol"
)

func main() {
	// reset between examples
	defer logsys.ResetOpenSyslog()

	opts := logcfg.OptionsSyslog{
		Network:         libptc.NetworkUDP.Code(),
		Host:            "localhost:514",
		Tag:             "http-access",
		EnableAccessLog: true, // Message-only mode
		LogLevel:        []string{"info"},
	}

	hook, err := logsys.New(opts, nil)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	defer hook.Close()

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	go hook.Run(ctx)

	time.Sleep(100 * time.Millisecond)

	logger := logrus.New()
	logger.SetOutput(os.Stderr)
	logger.AddHook(hook)

	// IMPORTANT: In AccessLog mode, behavior is REVERSED!
	// The message "GET /api/users - 200 OK - 45ms" IS output.
	// The fields (method, path, status) are IGNORED.
	logger.WithFields(logrus.Fields{
		"method": "GET",
		"path":   "/api/users",
		"status": 200,
	}).Info("GET /api/users - 200 OK - 45ms")

	time.Sleep(100 * time.Millisecond)

	fmt.Println("Access log sent to syslog")

}
Output:

Access log sent to syslog
Example (Basic)

Example_basic demonstrates the simplest use case: creating a hook that writes to local syslog. Note: This example uses UDP which doesn't require an actual syslog daemon to be running.

package main

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/sirupsen/logrus"

	logcfg "github.com/nabbar/golib/logger/config"
	logsys "github.com/nabbar/golib/logger/hooksyslog"

	libptc "github.com/nabbar/golib/network/protocol"
)

func main() {
	// reset between examples
	defer logsys.ResetOpenSyslog()

	// Configure the hook with minimal settings
	// In this example, we use UDP protocol which doesn't fail if no server is running
	opts := logcfg.OptionsSyslog{
		Network:  libptc.NetworkUDP.Code(),
		Host:     "localhost:514", // UDP doesn't fail without server
		Tag:      "myapp",
		LogLevel: []string{"info", "warning", "error"},
	}

	// Create the hook
	hook, err := logsys.New(opts, &logrus.TextFormatter{
		DisableTimestamp: true, // Disable timestamp for predictable output
	})
	if err != nil {
		fmt.Printf("Error creating hook: %v\n", err)
		return
	}
	defer hook.Close()

	// Start async writer goroutine
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	go hook.Run(ctx)

	// Wait for hook to be ready
	time.Sleep(100 * time.Millisecond)

	// Create and configure logger
	logger := logrus.New()
	logger.SetOutput(os.Stderr) // Use Stderr to separate from syslog output
	logger.AddHook(hook)

	// IMPORTANT: The message parameter "ignored" is NOT used by the hook in standard mode.
	// Only the fields (here "msg") are written to syslog.
	// Exception: In AccessLog mode, only the message is used and fields are ignored.
	logger.WithField("msg", "Application started successfully").Info("ignored")

	// Wait for async write
	time.Sleep(100 * time.Millisecond)

	fmt.Println("Log sent to syslog")

}
Output:

Log sent to syslog
Example (FieldFiltering)

Example_fieldFiltering demonstrates filtering specific fields from output.

package main

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/sirupsen/logrus"

	logcfg "github.com/nabbar/golib/logger/config"
	logsys "github.com/nabbar/golib/logger/hooksyslog"

	libptc "github.com/nabbar/golib/network/protocol"
)

func main() {
	// reset between examples
	defer logsys.ResetOpenSyslog()

	// Configure to filter out stack and timestamp
	opts := logcfg.OptionsSyslog{
		Network:          libptc.NetworkUDP.Code(),
		Host:             "localhost:514",
		Tag:              "clean-app",
		DisableStack:     true,  // Remove stack fields
		DisableTimestamp: true,  // Remove time fields
		EnableTrace:      false, // Remove caller/file/line fields
		LogLevel:         []string{"info"},
	}

	hook, err := logsys.New(opts, &logrus.TextFormatter{
		DisableTimestamp: true,
	})
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	defer hook.Close()

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	go hook.Run(ctx)

	time.Sleep(100 * time.Millisecond)

	logger := logrus.New()
	logger.SetOutput(os.Stderr)
	logger.AddHook(hook)

	// IMPORTANT: message "ignored" is NOT used, only fields
	logger.WithFields(logrus.Fields{
		"msg":    "Filtered log entry",
		"stack":  "will be filtered out",
		"caller": "will be filtered out",
		"user":   "john",
		"action": "login",
	}).Info("ignored")

	time.Sleep(100 * time.Millisecond)

	fmt.Println("Filtered log sent to syslog")

}
Output:

Filtered log sent to syslog
Example (LevelFiltering)

Example_levelFiltering demonstrates filtering logs by level.

package main

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/sirupsen/logrus"

	logcfg "github.com/nabbar/golib/logger/config"
	logsys "github.com/nabbar/golib/logger/hooksyslog"

	libptc "github.com/nabbar/golib/network/protocol"
)

func main() {
	// reset between examples
	defer logsys.ResetOpenSyslog()

	opts := logcfg.OptionsSyslog{
		Network:  libptc.NetworkUDP.Code(),
		Host:     "localhost:514",
		Tag:      "filtered-app",
		LogLevel: []string{"error", "fatal"}, // Only errors and above
	}

	hook, err := logsys.New(opts, &logrus.TextFormatter{
		DisableTimestamp: true,
	})
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	defer hook.Close()

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	go hook.Run(ctx)

	time.Sleep(100 * time.Millisecond)

	logger := logrus.New()
	logger.SetOutput(os.Stderr)
	logger.AddHook(hook)

	// This will be written (error level)
	// Note: message "ignored" is NOT used, only the field "msg"
	logger.WithField("msg", "Database connection failed").Error("ignored")

	// This won't be written to syslog (wrong level)
	logger.WithField("msg", "Request completed").Info("ignored")

	time.Sleep(100 * time.Millisecond)

	fmt.Println("Filtered logs sent to syslog")

}
Output:

Filtered logs sent to syslog
Example (MultipleHooks)

Example_multipleHooks demonstrates using multiple hooks for different destinations.

package main

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/sirupsen/logrus"

	logcfg "github.com/nabbar/golib/logger/config"
	logsys "github.com/nabbar/golib/logger/hooksyslog"

	libptc "github.com/nabbar/golib/network/protocol"
)

func main() {
	// reset between examples
	defer logsys.ResetOpenSyslog()

	// Hook for errors only
	errorOpts := logcfg.OptionsSyslog{
		Network:  libptc.NetworkUDP.Code(),
		Host:     "localhost:514",
		Tag:      "errors",
		LogLevel: []string{"error", "fatal"},
	}

	errorHook, err := logsys.New(errorOpts, nil)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	defer errorHook.Close()

	// Hook for all levels
	allOpts := logcfg.OptionsSyslog{
		Network: libptc.NetworkUDP.Code(),
		Host:    "localhost:514",
		Tag:     "all-logs",
	}

	allHook, err := logsys.New(allOpts, nil)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	defer allHook.Close()

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	go errorHook.Run(ctx)
	go allHook.Run(ctx)

	time.Sleep(100 * time.Millisecond)

	logger := logrus.New()
	logger.SetOutput(os.Stderr)
	logger.AddHook(errorHook)
	logger.AddHook(allHook)

	// This goes to both hooks
	logger.WithField("msg", "Critical error occurred").Error("ignored")

	// This goes only to allHook
	logger.WithField("msg", "Normal operation").Info("ignored")

	time.Sleep(100 * time.Millisecond)

	fmt.Println("Logs sent to multiple syslog destinations")

}
Output:

Logs sent to multiple syslog destinations
Example (RemoteUdp)

Example_remoteUdp demonstrates sending logs to a remote syslog server via UDP.

package main

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/sirupsen/logrus"

	logcfg "github.com/nabbar/golib/logger/config"
	logsys "github.com/nabbar/golib/logger/hooksyslog"

	libptc "github.com/nabbar/golib/network/protocol"
)

func main() {
	// reset between examples
	defer logsys.ResetOpenSyslog()

	opts := logcfg.OptionsSyslog{
		Network:  libptc.NetworkUDP.Code(),
		Host:     "localhost:514", // Remote syslog server
		Tag:      "remote-app",
		Facility: "LOCAL0", // Use LOCAL0 facility
		LogLevel: []string{"info", "error"},
	}

	hook, err := logsys.New(opts, &logrus.JSONFormatter{})
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	defer hook.Close()

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	go hook.Run(ctx)

	time.Sleep(100 * time.Millisecond)

	logger := logrus.New()
	logger.SetOutput(os.Stderr)
	logger.AddHook(hook)

	// IMPORTANT: Use fields, not message parameter
	logger.WithFields(logrus.Fields{
		"msg":      "Remote logging test",
		"service":  "api",
		"instance": "prod-1",
	}).Info("ignored")

	time.Sleep(100 * time.Millisecond)

	fmt.Println("Log sent to remote syslog via UDP")

}
Output:

Log sent to remote syslog via UDP
Example (StructuredLogging)

Example_structuredLogging demonstrates structured logging with JSON formatter.

package main

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/sirupsen/logrus"

	logcfg "github.com/nabbar/golib/logger/config"
	logsys "github.com/nabbar/golib/logger/hooksyslog"

	libptc "github.com/nabbar/golib/network/protocol"
)

func main() {
	// reset between examples
	defer logsys.ResetOpenSyslog()

	opts := logcfg.OptionsSyslog{
		Network:  libptc.NetworkUDP.Code(),
		Host:     "localhost:514",
		Tag:      "structured-app",
		LogLevel: []string{"info"},
	}

	hook, err := logsys.New(opts, &logrus.JSONFormatter{})
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	defer hook.Close()

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	go hook.Run(ctx)

	time.Sleep(100 * time.Millisecond)

	logger := logrus.New()
	logger.SetOutput(os.Stderr)
	logger.AddHook(hook)

	// IMPORTANT: message parameter is NOT used, only fields
	logger.WithFields(logrus.Fields{
		"user_id":    12345,
		"action":     "purchase",
		"amount":     99.99,
		"currency":   "USD",
		"msg":        "Purchase completed",
		"request_id": "abc-123-def",
	}).Info("ignored")

	time.Sleep(100 * time.Millisecond)

	fmt.Println("Structured log sent to syslog")

}
Output:

Structured log sent to syslog
Example (TraceEnabled)

Example_traceEnabled demonstrates enabling trace information in logs.

package main

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/sirupsen/logrus"

	logcfg "github.com/nabbar/golib/logger/config"
	logsys "github.com/nabbar/golib/logger/hooksyslog"

	libptc "github.com/nabbar/golib/network/protocol"
)

func main() {
	// reset between examples
	defer logsys.ResetOpenSyslog()

	opts := logcfg.OptionsSyslog{
		Network:     libptc.NetworkUDP.Code(),
		Host:        "localhost:514",
		Tag:         "trace-app",
		EnableTrace: true, // Include caller/file/line information
		LogLevel:    []string{"info"},
	}

	hook, err := logsys.New(opts, &logrus.TextFormatter{
		DisableTimestamp: true,
	})
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	defer hook.Close()

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	go hook.Run(ctx)

	time.Sleep(100 * time.Millisecond)

	logger := logrus.New()
	logger.SetOutput(os.Stderr)
	logger.AddHook(hook)

	// IMPORTANT: message "ignored" is NOT used, only fields
	logger.WithFields(logrus.Fields{
		"msg":    "Log with trace info",
		"caller": "main.processRequest",
		"file":   "main.go",
		"line":   42,
	}).Info("ignored")

	time.Sleep(100 * time.Millisecond)

	fmt.Println("Log with trace sent to syslog")

}
Output:

Log with trace sent to syslog

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func PriorityCalc added in v1.19.1

func PriorityCalc(f Facility, s Severity) uint8

PriorityCalc calculates the syslog Priority value (PRIVAL) as defined in RFC 5424. PRIVAL = (Facility * 8) + Severity. This value is placed at the beginning of a syslog message in angle brackets (e.g., <165>).

func ResetOpenSyslog added in v1.19.1

func ResetOpenSyslog()

ResetOpenSyslog closes all active syslog connections and clears the aggregator map. This is primarily useful for testing or for scenarios requiring a full reset of the logging infrastructure.

Types

type Facility added in v1.19.1

type Facility uint8

Facility represents the facility code of a syslog message according to RFC 5424. The facility indicates the type of program or system component generating the message.

Facilities are typically used for filtering and routing syslog messages:

  • KERN: Kernel messages
  • USER: User-level messages (default for applications)
  • MAIL: Mail system
  • DAEMON: System daemons
  • AUTH: Security/authorization messages
  • SYSLOG: Messages generated internally by syslogd
  • LPR: Line printer subsystem
  • NEWS: Network news subsystem
  • UUCP: UUCP subsystem
  • CRON: Clock daemon
  • AUTHPRIV: Security/authorization messages (private)
  • FTP: FTP daemon
  • LOCAL0-LOCAL7: Reserved for local use (application-specific)
const (
	FacilityKern     Facility = iota // Kernel messages
	FacilityUser                     // User-level messages
	FacilityMail                     // Mail system
	FacilityDaemon                   // System daemons
	FacilityAuth                     // Security/authorization messages
	FacilitySyslog                   // Messages generated internally by syslogd
	FacilityLpr                      // Line printer subsystem
	FacilityNews                     // Network news subsystem
	FacilityUucp                     // UUCP subsystem
	FacilityCron                     // Clock daemon
	FacilityAuthPriv                 // Security/authorization messages (private)
	FacilityFTP                      // FTP daemon

	FacilityLocal0 // Local use 0
	FacilityLocal1 // Local use 1
	FacilityLocal2 // Local use 2
	FacilityLocal3 // Local use 3
	FacilityLocal4 // Local use 4
	FacilityLocal5 // Local use 5
	FacilityLocal6 // Local use 6
	FacilityLocal7 // Local use 7
)

func MakeFacility

func MakeFacility(facility string) Facility

MakeFacility converts a facility string to a Facility value. The conversion is case-insensitive. Returns 0 if the string doesn't match any known facility.

func (Facility) String added in v1.19.1

func (f Facility) String() string

String returns the RFC 5424 name of the facility in uppercase. Returns an empty string for invalid/unknown facility values.

Example:

fac := FacilityUser
fmt.Println(fac.String()) // Outputs: "USER"

func (Facility) Uint8 added in v1.19.1

func (f Facility) Uint8() uint8

type HookSyslog

type HookSyslog interface {
	logtps.Hook
}

HookSyslog is a logrus hook that writes log entries to a syslog endpoint. It extends the standard logrus.Hook interface with additional methods for lifecycle management.

The hook operates asynchronously by delegating the actual writing to a shared, buffered aggregator. This prevents blocking the main logging goroutine.

Platform support:

  • Unix/Linux: Supports local syslog (via Unix domain sockets) and remote syslog (TCP/UDP).
  • Windows: Supports remote syslog (TCP/UDP). Local syslog is not supported.

Thread safety:

  • Fire() is safe for concurrent calls.
  • Close() should be called once during shutdown to release resources.

Example:

opts := logcfg.OptionsSyslog{
	Network:  "udp",
	Host:     "syslog.example.com:514",
	Tag:      "myapp",
	LogLevel: []string{"info", "error"},
}
hook, _ := New(opts, &logrus.JSONFormatter{})
logger.AddHook(hook)
defer hook.Close()

func New

New creates a new HookSyslog instance with the specified configuration.

This function initializes the hook and establishes a connection to the syslog endpoint via a shared aggregator. If an aggregator for the specified endpoint already exists, it is reused, and its reference count is incremented.

The background writer goroutine is managed automatically by the aggregator, so there is no need to manually start a run loop.

Parameters:

  • opt: Configuration options including network, host, tag, facility, and filters.
  • format: Logrus formatter for log entries (nil for default text format).

Configuration:

  • opt.Network: Protocol ("tcp", "udp", "unixgram", "unix"). Empty string implies local auto-discovery (Unix only).
  • opt.Host: Syslog server address ("host:port" for TCP/UDP, "/dev/log" for Unix).
  • opt.Tag: Syslog tag/application name (appears in syslog output). Defaults to process name.
  • opt.Facility: Syslog facility ("LOCAL0"-"LOCAL7", "USER", "DAEMON", etc.).
  • opt.LogLevel: Filter log levels (empty = all levels).
  • opt.DisableStack: Remove "stack" field from output.
  • opt.DisableTimestamp: Remove "time" field from output.
  • opt.EnableTrace: Include "caller", "file", "line" fields.
  • opt.EnableAccessLog: Write entry.Message instead of formatted fields.

Returns:

  • HookSyslog: Configured hook ready to use.
  • error: Non-nil if unable to initialize the connection aggregator.

Example:

opts := logcfg.OptionsSyslog{
	Network:  "tcp",
	Host:     "192.168.1.50:514",
	Tag:      "myapp",
	Facility: "USER",
	LogLevel: []string{"info", "warning", "error"},
}
hook, err := New(opts, &logrus.JSONFormatter{})
if err != nil {
	return nil, fmt.Errorf("failed to create syslog hook: %w", err)
}
logger.AddHook(hook)

type Severity added in v1.19.1

type Severity uint8

Severity represents the severity level of a syslog message according to RFC 5424. Lower numerical values indicate higher severity.

The severity levels map to logrus levels as follows:

  • Emergency (0): System is unusable
  • Alert (1): Action must be taken immediately → logrus.PanicLevel
  • Critical (2): Critical conditions → logrus.FatalLevel
  • Error (3): Error conditions → logrus.ErrorLevel
  • Warning (4): Warning conditions → logrus.WarnLevel
  • Notice (5): Normal but significant condition
  • Informational (6): Informational messages → logrus.InfoLevel
  • Debug (7): Debug-level messages → logrus.DebugLevel
const (
	SeverityEmerg   Severity = iota // System is unusable
	SeverityAlert                   // Action must be taken immediately
	SeverityCrit                    // Critical conditions
	SeverityErr                     // Error conditions
	SeverityWarning                 // Warning conditions
	SeverityNotice                  // Normal but significant condition
	SeverityInfo                    // Informational messages
	SeverityDebug                   // Debug-level messages
)

func ListSeverity added in v1.19.1

func ListSeverity() []Severity

ListSeverity returns a slice containing all defined Severity levels in order from Emergency (0) to Debug (7).

func MakeSeverity

func MakeSeverity(severity string) Severity

MakeSeverity converts a severity string to a Severity value. The conversion is case-insensitive. Returns 0 if the string doesn't match any known severity.

func (Severity) String added in v1.19.1

func (s Severity) String() string

String returns the RFC 5424 name of the severity level in uppercase. Returns an empty string for invalid/unknown severity values.

Example:

sev := SeverityInfo
fmt.Println(sev.String()) // Outputs: "INFO"

func (Severity) Uint8 added in v1.19.1

func (s Severity) Uint8() uint8

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL