hooksyslog

package
v1.19.0 Latest Latest
Warning

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

Go to latest
Published: Dec 26, 2025 License: MIT Imports: 14 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: Done channel 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   │        │    Run()     │ │
│  │ Level    │         │   Channel    │        │  Goroutine   │ │
│  │ Message  │────────▶│  (cap: 250)  │───────▶│              │ │
│  │          │         │              │        │              │ │
│  └──────────┘         │              │        │              │ │
│                       │              │        │              │ │
│       Fire()          │    data      │        │ writeWrapper │ │
│         │             └──────────────┘        └───────┬──────┘ │
│         │                                            │         │
│         ▼                                            ▼         │
│  ┌──────────────┐                           ┌────────────────┐ │
│  │ Formatter    │                           │    Wrapper     │ │
│  │ JSON/Text    │                           │  (Platform)    │ │
│  └──────────────┘                           │                │ │
│                                             │  Unix: syslog  │ │
│  ┌──────────────┐                           │  Win: EventLog │ │
│  │ Field Filter │                           └────────────────┘ │
│  │ - Stack      │                                   │          │
│  │ - Timestamp  │                                   ▼          │
│  │ - Trace      │                          ┌─────────────────┐ │
│  └──────────────┘                          │  Syslog/Event   │ │
│                                            │      Log        │ │
│                                            └─────────────────┘ │
└────────────────────────────────────────────────────────────────┘
Data Flow
Logrus Log Statement → Fire(entry) → Format → Filter → Channel → Run() → 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 (41 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()
    <-hook.Done()
}()

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()
        <-hook.Done()
    }()
    
    // 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()
    <-hook.Done()
}()

// 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()
    <-hook.Done()
}()
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()
    <-hook.Done()
}()
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()
    <-hook.Done()
}()

Best Practices

Testing

The package includes a comprehensive test suite with 83.2% code coverage and 41 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
    <-hook.Done()   // Wait for completion
}()

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()
<-hook.Done()  // Wait for all logs to be written

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
    
    // Done returns a channel that closes when Run() exits
    Done() <-chan struct{}
    
    // WriteSev writes data with specific severity directly to syslog
    WriteSev(s SyslogSeverity, p []byte) (n int, err error)
}

Methods:

  • Levels() []logrus.Level: Returns configured log levels for this hook
  • Fire(entry *logrus.Entry) error: Processes log entry (called by logrus)
  • Done() <-chan struct{}: Returns channel that closes when Run() completes
  • WriteSev(s, p) (int, error): Write raw bytes with specific severity
  • Run(ctx context.Context): Start background writer (must be called in goroutine)
  • Close() error: Close channels (call before waiting on Done())
  • 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
  • 83.2% 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 (83.2%), 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 logrus hook for writing log entries to syslog.

Overview

The hooksyslog package implements a logrus hook that sends log messages to system syslog. It supports both Unix/Linux syslog (via log/syslog) and Windows Event Log (via golang.org/x/sys/windows/svc/eventlog). The hook provides asynchronous, buffered logging with automatic reconnection and graceful shutdown.

Design Philosophy

  • Cross-platform: Transparent support for Unix/Linux syslog and Windows Event Log
  • Asynchronous: Non-blocking writes using buffered channels (capacity: 250)
  • Flexible: Configurable levels, formatters, and syslog facilities
  • Robust: Automatic reconnection on connection failures
  • Standard: Full compliance with RFC 5424 syslog severity levels

Architecture

The package consists of several key components:

┌─────────────────────────────────────────────┐
│          HookSyslog Interface               │
│  (logrus.Hook + Done + WriteSev)            │
└──────────────┬──────────────────────────────┘
               │
     ┌─────────▼─────────┐
     │   hks struct      │
     │  - channels       │
     │  - options        │
     │  - running state  │
     └─────────┬─────────┘
               │
     ┌─────────▼─────────┐
     │   Run() goroutine │
     │  - reads channel  │
     │  - writes syslog  │
     │  - reconnects     │
     └─────────┬─────────┘
               │
       ┌───────┴───────┐
       │               │
┌──────▼──────┐  ┌─────▼──────┐
│  _Syslog    │  │  _WinLog   │
│  (Unix)     │  │ (Windows)  │
└─────────────┘  └────────────┘

Platform-Specific Implementation

Unix/Linux (sys_syslog.go):

  • Uses log/syslog package
  • Supports network protocols: tcp, udp, unixgram
  • Full RFC 5424 severity and facility support
  • Build tags: linux || darwin

Windows (sys_winlog.go):

  • Uses golang.org/x/sys/windows/svc/eventlog
  • Maps severity to Windows event types (Error, Warning, Info)
  • Automatic Windows Event Source registration
  • Build tags: windows

Key Features

Asynchronous Buffered Writing:

  • Buffered channel capacity: 250 entries
  • Non-blocking Fire() method (unless buffer full)
  • Background goroutine handles actual syslog writes
  • Graceful shutdown with Done() channel

Automatic Reconnection:

  • Retries connection on startup (1-second intervals)
  • Continues logging even if syslog temporarily unavailable
  • Connection errors printed to stdout (not propagated to logrus)

Level Mapping:

  • logrus.PanicLevel → SyslogSeverityAlert
  • logrus.FatalLevel → SyslogSeverityCrit
  • logrus.ErrorLevel → SyslogSeverityErr
  • logrus.WarnLevel → SyslogSeverityWarning
  • logrus.InfoLevel → SyslogSeverityInfo
  • logrus.DebugLevel → SyslogSeverityDebug

Field Filtering:

  • DisableStack: Remove "stack" field
  • DisableTimestamp: Remove "time" field
  • EnableTrace: Include "caller", "file", "line" fields

Access Log Mode:

  • EnableAccessLog: true → writes entry.Message, ignores fields
  • EnableAccessLog: false → writes formatted fields, ignores Message

Advantages

  • Non-blocking: Logrus calls don't wait for syslog I/O
  • Reliable: Buffering prevents log loss during temporary unavailability
  • Flexible: Works with any logrus.Formatter (JSON, Text, custom)
  • Cross-platform: Single API for Unix and Windows
  • Standard: RFC 5424 compliant severity and facility

Disadvantages

  • Memory overhead: Buffered channel holds up to 250 entries (~250KB typical)
  • Latency: Async writes introduce small delay before syslog write
  • Errors silent: Syslog write errors printed to stdout, not returned to caller
  • Requires Run(): Must call Run(ctx) in goroutine, not automatic
  • No batching: Each log entry results in separate syslog write

Limitations

  • Buffer overflow: If buffer fills (>250 entries), Fire() blocks
  • Platform-specific: Windows has limited severity mapping (3 types)
  • Network only: Windows remote logging requires network protocol
  • No TLS: Unix syslog over network doesn't support TLS
  • Tag immutable: Syslog tag set at creation, can't change per-entry

Typical Use Cases

  • System service logging to local syslog
  • Application logging to remote syslog server
  • Windows service logging to Event Log
  • Structured logging with JSON formatter
  • HTTP access logs (EnableAccessLog mode)
  • Multi-destination logging (syslog + file + console)

Performance Considerations

  • Channel capacity: 250 entries is default, suitable for most use cases
  • Write throughput: Limited by syslog server/daemon, not this package
  • Memory usage: ~1KB per buffered entry (depends on entry size)
  • Goroutine overhead: Single goroutine per hook instance
  • Reconnection: 1-second retry interval on connection failures

Example Usage

See the example_test.go file for complete examples, including:

  • Basic setup with local syslog
  • Remote syslog via TCP/UDP
  • Windows Event Log
  • Custom formatter with JSON
  • Access log mode
  • Graceful shutdown pattern
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() {
	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() {
	// 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() {
	// 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 (GracefulShutdown)

Example_gracefulShutdown demonstrates proper shutdown with the Done channel.

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() {
	opts := logcfg.OptionsSyslog{
		Network:  libptc.NetworkUDP.Code(),
		Host:     "localhost:514",
		Tag:      "shutdown-test",
		LogLevel: []string{"info"},
	}

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

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

	time.Sleep(100 * time.Millisecond)

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

	// Send some logs
	logger.WithField("msg", "Starting shutdown sequence").Info("ignored")
	time.Sleep(100 * time.Millisecond)

	// Signal shutdown
	cancel()
	hook.Close()

	// Wait for completion
	select {
	case <-hook.Done():
		fmt.Println("Hook shutdown complete")
	case <-time.After(2 * time.Second):
		fmt.Println("Timeout waiting for shutdown")
	}

}
Output:

Hook shutdown complete
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() {
	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() {
	// 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() {
	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() {
	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() {
	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

This section is empty.

Types

type HookSyslog

type HookSyslog interface {
	logtps.Hook

	// Done returns a receive-only channel that is closed when the hook's
	// Run goroutine terminates. This allows graceful shutdown coordination.
	//
	// The channel is closed when:
	//   - The context passed to Run() is cancelled
	//   - Close() is called on the hook
	//
	// Use this to wait for all buffered log entries to be written before
	// terminating the application:
	//
	//	cancel() // Stop the Run goroutine
	//	hook.Close() // Close the channels
	//	<-hook.Done() // Wait for completion
	//
	// Note: This channel is safe to read from multiple goroutines, but
	// each reader will only receive the close signal once.
	Done() <-chan struct{}
	// WriteSev writes a log entry to the syslog buffer with the specified
	// severity level and data.
	//
	// This method bypasses the logrus.Entry mechanism and directly writes
	// to syslog. It's useful for custom logging scenarios or when you need
	// explicit control over the severity level.
	//
	// Parameters:
	//   - s: Syslog severity (Emergency, Alert, Critical, Error, Warning, Notice, Info, Debug)
	//   - p: Log message data (will be sent as-is to syslog)
	//
	// Returns:
	//   - n: Number of bytes accepted (len(p)) if successful
	//   - err: Error if the channel is closed or buffer is full
	//
	// Behavior:
	//   - Non-blocking if buffer has space (typical case)
	//   - Blocks if buffer is full (250 entries) until space is available
	//   - Returns error if Close() was called (channel closed)
	//
	// The data is queued to a buffered channel and written asynchronously
	// by the Run() goroutine. There's no guarantee of immediate delivery.
	//
	// Example:
	//
	//	hook, _ := New(opts, nil)
	//	go hook.Run(ctx)
	//	_, err := hook.WriteSev(SyslogSeverityInfo, []byte("Custom log entry"))
	//	if err != nil {
	//		log.Printf("Failed to write: %v", err)
	//	}
	WriteSev(s SyslogSeverity, p []byte) (n int, err error)
}

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

The hook operates asynchronously using a buffered channel (capacity: 250) to prevent blocking the logging goroutine. A background goroutine (started via Run) processes the buffered entries and writes them to syslog.

Platform support:

  • Unix/Linux: Uses log/syslog with TCP, UDP, or Unix domain sockets
  • Windows: Uses Windows Event Log via golang.org/x/sys/windows/svc/eventlog

Thread safety:

  • Fire() is safe for concurrent calls (buffered channel)
  • WriteSev() is safe for concurrent calls (buffered channel)
  • Done() and Close() should only be called once during shutdown

Example:

opts := logcfg.OptionsSyslog{
	Network:  "unixgram",
	Host:     "/dev/log",
	Tag:      "myapp",
	LogLevel: []string{"info", "error"},
}
hook, _ := New(opts, &logrus.JSONFormatter{})
go hook.Run(ctx)
logger.AddHook(hook)

func New

New creates a new HookSyslog instance with the specified configuration.

This function initializes the hook but does NOT start the background writer goroutine. You must call Run(ctx) in a separate goroutine after creating the hook.

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", "" for local)
  • opt.Host: Syslog server address ("host:port" for TCP/UDP, "/dev/log" for Unix)
  • opt.Tag: Syslog tag/application name (appears in syslog output)
  • 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 (call Run to start)
  • error: Non-nil if unable to connect to syslog (validates connection)

The function validates the syslog connection by opening and immediately closing it. This ensures early detection of configuration errors.

Example:

opts := logcfg.OptionsSyslog{
	Network:  "unixgram",
	Host:     "/dev/log",
	Tag:      "myapp",
	Facility: "USER",
	LogLevel: []string{"info", "warning", "error"},
}
hook, err := New(opts, &logrus.JSONFormatter{})
if err != nil {
	return fmt.Errorf("failed to create syslog hook: %w", err)
}
go hook.Run(context.Background())
defer hook.Close()

type SyslogFacility

type SyslogFacility uint8

SyslogFacility 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 (
	SyslogFacilityKern SyslogFacility = iota + 1
	SyslogFacilityUser
	SyslogFacilityMail
	SyslogFacilityDaemon
	SyslogFacilityAuth
	SyslogFacilitySyslog
	SyslogFacilityLpr
	SyslogFacilityNews
	SyslogFacilityUucp
	SyslogFacilityCron
	SyslogFacilityAuthPriv
	SyslogFacilityFTP
	SyslogFacilityLocal0
	SyslogFacilityLocal1
	SyslogFacilityLocal2
	SyslogFacilityLocal3
	SyslogFacilityLocal4
	SyslogFacilityLocal5
	SyslogFacilityLocal6
	SyslogFacilityLocal7
)

func MakeFacility

func MakeFacility(facility string) SyslogFacility

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

func (SyslogFacility) String

func (s SyslogFacility) String() string

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

Example:

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

type SyslogSeverity

type SyslogSeverity uint8

SyslogSeverity 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 (
	SyslogSeverityEmerg SyslogSeverity = iota + 1
	SyslogSeverityAlert
	SyslogSeverityCrit
	SyslogSeverityErr
	SyslogSeverityWarning
	SyslogSeverityNotice
	SyslogSeverityInfo
	SyslogSeverityDebug
)

func MakeSeverity

func MakeSeverity(severity string) SyslogSeverity

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

func (SyslogSeverity) String

func (s SyslogSeverity) 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 := SyslogSeverityInfo
fmt.Println(sev.String()) // Outputs: "INFO"

type Wrapper

type Wrapper interface {
	io.WriteCloser

	// Panic writes a message with ALERT severity (syslog) or ERROR (Windows).
	// This is the highest severity level after EMERGENCY.
	Panic(p []byte) (n int, err error)

	// Fatal writes a message with CRITICAL severity (syslog) or ERROR (Windows).
	// Used for critical conditions that require immediate attention.
	Fatal(p []byte) (n int, err error)

	// Error writes a message with ERROR severity.
	// Used for error conditions.
	Error(p []byte) (n int, err error)

	// Warning writes a message with WARNING severity.
	// Used for warning conditions.
	Warning(p []byte) (n int, err error)

	// Info writes a message with INFORMATIONAL severity.
	// Used for informational messages.
	Info(p []byte) (n int, err error)

	// Debug writes a message with DEBUG severity (syslog) or INFO (Windows).
	// Used for debug-level messages.
	Debug(p []byte) (n int, err error)
}

Wrapper is a platform-specific interface for writing to syslog. It abstracts the differences between Unix syslog and Windows Event Log.

Implementations:

  • _Syslog: Unix/Linux implementation using log/syslog
  • _WinLog: Windows implementation using golang.org/x/sys/windows/svc/eventlog

The interface provides severity-specific methods that map to syslog/event log severity levels. Each method writes the provided byte slice to the underlying logging system.

Jump to

Keyboard shortcuts

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