Overview
Ruby's Syslog module provides access to the system logging facility found on Unix-like operating systems. The module acts as a wrapper around the system's syslog(3) library functions, enabling Ruby applications to send messages to system log files, remote logging servers, or other configured destinations.
The Syslog module operates as a singleton, maintaining a single connection to the syslog daemon throughout the application's lifecycle. Messages sent through Syslog include priority levels, facility codes, and formatting options that determine how the system processes and routes log entries.
Ruby's implementation supports all standard syslog facilities including mail, daemon, local0-7, and user facilities. Priority levels range from emergency through debug, following RFC 3164 specifications. The module handles message formatting, encoding, and transmission to the underlying system logging infrastructure.
require 'syslog'
# Open connection with program name
Syslog.open("myapp") do |s|
s.info("Application started")
s.warning("Configuration file missing, using defaults")
end
# Manual connection management
Syslog.open("worker", Syslog::LOG_PID, Syslog::LOG_DAEMON)
Syslog.notice("Worker process initialized with PID #{Process.pid}")
Syslog.close
The module integrates with system log rotation, filtering, and forwarding mechanisms configured by system administrators. Ruby applications using Syslog automatically inherit the logging infrastructure's reliability, persistence, and centralization features without requiring additional configuration or external dependencies.
Basic Usage
The Syslog module requires explicit opening before sending messages. The open
method accepts a program identifier, logging options, and facility designation. Once opened, the connection remains active until explicitly closed or the process terminates.
require 'syslog'
# Basic connection with program name only
Syslog.open("myapp")
Syslog.info("User authentication successful")
Syslog.error("Database connection failed")
Syslog.close
# Block form automatically closes connection
Syslog.open("service", Syslog::LOG_PID | Syslog::LOG_CONS) do |syslog|
syslog.debug("Processing request #{request_id}")
syslog.warning("High memory usage detected: #{memory_usage}MB")
end
Priority levels determine message importance and filtering behavior. Each level corresponds to a specific method name and numeric value. System administrators configure filtering rules based on these priorities to control which messages reach specific destinations.
# Priority levels from most to least severe
Syslog.open("critical_app") do |s|
s.emerg("System unusable, immediate attention required")
s.alert("Action must be taken immediately")
s.crit("Critical conditions detected")
s.err("Error conditions occurred")
s.warning("Warning conditions present")
s.notice("Normal but significant condition")
s.info("Informational messages")
s.debug("Debug-level messages")
end
Facility codes categorize message sources, enabling system administrators to route messages from different application types to appropriate destinations. Common facilities include daemon for background processes, local0-7 for custom applications, and mail for email-related services.
# Specify facility during connection
Syslog.open("webapp", Syslog::LOG_PID, Syslog::LOG_LOCAL0)
Syslog.info("Web server request processed")
# Different facility for background jobs
Syslog.open("worker", Syslog::LOG_PID, Syslog::LOG_LOCAL1)
Syslog.notice("Background job completed")
Syslog.close
Message formatting follows printf-style conventions, accepting format strings and argument substitution. The module handles string encoding and character escaping automatically, ensuring messages remain readable across different system configurations.
Syslog.open("formatter_demo") do |s|
user_id = 12345
action = "login"
ip_address = "192.168.1.100"
# Printf-style formatting
s.info("User %d performed %s from %s", user_id, action, ip_address)
# String interpolation also works
s.warning("Failed login attempt from #{ip_address} for user #{user_id}")
end
Error Handling & Debugging
Syslog operations can fail due to system resource constraints, permission restrictions, or network connectivity issues when logging to remote destinations. Ruby raises specific exceptions for different failure modes, requiring appropriate error handling strategies.
require 'syslog'
begin
Syslog.open("test_app")
Syslog.info("Application message")
rescue SystemCallError => e
# Handle system-level errors (permissions, resources)
STDERR.puts "Syslog unavailable: #{e.message}"
# Fallback to file logging or stderr
rescue RuntimeError => e
# Handle Ruby-level errors (already open, invalid arguments)
STDERR.puts "Syslog configuration error: #{e.message}"
ensure
Syslog.close if Syslog.opened?
end
Multiple connection attempts without proper cleanup result in runtime errors. The module maintains singleton state, preventing concurrent connections from the same process. Proper resource management requires explicit connection closure or block-form usage.
# Detect and handle existing connections
def safe_syslog_operation(program_name)
if Syslog.opened?
current_identity = Syslog.ident
if current_identity == program_name
yield Syslog
else
raise "Syslog already open with different identity: #{current_identity}"
end
else
Syslog.open(program_name) do |s|
yield s
end
end
end
# Usage with error recovery
safe_syslog_operation("myapp") do |syslog|
syslog.info("Operation completed successfully")
end
Message truncation occurs when log entries exceed system-defined limits, typically 1024 or 2048 bytes. Applications generating large messages require chunking or summarization strategies to prevent data loss.
def safe_syslog_message(syslog, priority, message, max_length: 1000)
if message.length <= max_length
case priority
when :info then syslog.info(message)
when :warning then syslog.warning(message)
when :error then syslog.err(message)
end
else
# Split long messages into chunks
chunks = message.scan(/.{1,#{max_length - 20}}/)
chunks.each_with_index do |chunk, index|
formatted_message = "[#{index + 1}/#{chunks.length}] #{chunk}"
case priority
when :info then syslog.info(formatted_message)
when :warning then syslog.warning(formatted_message)
when :error then syslog.err(formatted_message)
end
end
end
end
# Handle potentially large error messages
Syslog.open("error_handler") do |s|
begin
# Some operation that might fail
complex_operation
rescue => e
error_details = "#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
safe_syslog_message(s, :error, error_details)
end
end
Debugging syslog integration requires understanding both Ruby-level behavior and system configuration. Message delivery failures might not raise exceptions, making verification through system log inspection necessary.
# Debugging helper for syslog integration
class SyslogDebugger
def self.test_connection(program_name, facility = Syslog::LOG_USER)
puts "Testing syslog connection for '#{program_name}'"
begin
Syslog.open(program_name, Syslog::LOG_PID, facility) do |s|
puts " Connection successful"
puts " Identity: #{Syslog.ident}"
puts " Facility: #{Syslog.facility}"
puts " Options: #{Syslog.options}"
# Send test messages at different priorities
s.debug("Debug test message")
s.info("Info test message")
s.warning("Warning test message")
puts " Test messages sent successfully"
end
rescue => e
puts " Connection failed: #{e.message}"
puts " Error class: #{e.class}"
end
puts "Check system logs (usually /var/log/messages or /var/log/syslog) for test messages"
end
end
# Run debugging test
SyslogDebugger.test_connection("debug_app", Syslog::LOG_LOCAL0)
Thread Safety & Concurrency
The Syslog module maintains process-global state, creating thread safety concerns in concurrent Ruby applications. Multiple threads sharing a single syslog connection can interfere with each other's operations, leading to message corruption or connection errors.
Concurrent access to syslog methods requires synchronization mechanisms to prevent race conditions. Ruby's Thread class and Mutex objects provide coordination tools for safe multi-threaded logging operations.
require 'syslog'
require 'thread'
class ThreadSafeSyslog
def initialize(program_name, facility = Syslog::LOG_USER)
@mutex = Mutex.new
@program_name = program_name
@facility = facility
@connection_active = false
end
def log(priority, message)
@mutex.synchronize do
ensure_connection
case priority
when :debug then Syslog.debug(message)
when :info then Syslog.info(message)
when :warning then Syslog.warning(message)
when :error then Syslog.err(message)
end
end
end
def close
@mutex.synchronize do
if @connection_active
Syslog.close
@connection_active = false
end
end
end
private
def ensure_connection
unless @connection_active
Syslog.open(@program_name, Syslog::LOG_PID, @facility)
@connection_active = true
end
end
end
# Usage with multiple threads
logger = ThreadSafeSyslog.new("concurrent_app")
threads = 10.times.map do |i|
Thread.new do
5.times do |j|
logger.log(:info, "Thread #{i} message #{j}")
sleep(rand * 0.1) # Simulate work
end
end
end
threads.each(&:join)
logger.close
Process forking creates additional complexity because child processes inherit the parent's syslog connection state. Forked processes require connection re-establishment to prevent message routing issues and resource conflicts.
def fork_safe_syslog_operation
parent_pid = Process.pid
if Syslog.opened?
# Close parent connection before forking
parent_ident = Syslog.ident
parent_facility = Syslog.facility
Syslog.close
should_reopen = true
end
pid = fork do
# Child process: establish new connection
if should_reopen
Syslog.open("#{parent_ident}-child-#{Process.pid}",
Syslog::LOG_PID, parent_facility)
end
Syslog.info("Child process #{Process.pid} started")
# Child work here
sleep(1)
Syslog.info("Child process #{Process.pid} completed")
Syslog.close if Syslog.opened?
end
# Parent process: reopen connection if needed
if should_reopen
Syslog.open(parent_ident, Syslog::LOG_PID, parent_facility)
Syslog.info("Parent process #{parent_pid} resumed after fork")
end
Process.wait(pid)
end
Fiber-based concurrency requires careful consideration of syslog state across fiber switches. The global connection state persists across fiber boundaries, but message ordering might become unpredictable under heavy concurrent load.
require 'fiber'
class FiberAwareSyslog
def initialize(program_name)
@program_name = program_name
@fiber_mutex = Mutex.new
end
def with_logging
@fiber_mutex.synchronize do
unless Syslog.opened?
Syslog.open(@program_name, Syslog::LOG_PID)
end
fiber_id = Fiber.current.object_id
Syslog.info("Fiber #{fiber_id} started logging")
begin
yield
ensure
Syslog.info("Fiber #{fiber_id} finished logging")
end
end
end
end
# Fiber coordination example
syslog_manager = FiberAwareSyslog.new("fiber_app")
fibers = 3.times.map do |i|
Fiber.new do
syslog_manager.with_logging do
5.times do |j|
Syslog.debug("Fiber #{i} iteration #{j}")
Fiber.yield # Allow other fibers to run
end
end
end
end
# Round-robin fiber scheduling
until fibers.all? { |f| !f.alive? }
fibers.select(&:alive?).each do |fiber|
fiber.resume rescue nil
end
end
Syslog.close if Syslog.opened?
Production Patterns
Production Ruby applications require robust syslog integration patterns that handle service restarts, log rotation, monitoring integration, and operational visibility. Syslog connections must survive application lifecycle events while maintaining message delivery guarantees.
class ProductionSyslogManager
def self.configure(app_name:, facility: Syslog::LOG_LOCAL0,
min_level: :info, include_pid: true)
@app_name = app_name
@facility = facility
@min_level = min_level
@include_pid = include_pid
@mutex = Mutex.new
establish_connection
setup_signal_handlers
register_exit_handler
end
def self.log(level, message, context: {})
return if skip_level?(level)
@mutex.synchronize do
ensure_connection_health
formatted_message = format_message(message, context)
send_message(level, formatted_message)
end
rescue => e
# Fallback to stderr if syslog fails
STDERR.puts "[SYSLOG_ERROR] #{e.message}: #{message}"
end
private
def self.establish_connection
options = Syslog::LOG_CONS | Syslog::LOG_NDELAY
options |= Syslog::LOG_PID if @include_pid
Syslog.open(@app_name, options, @facility)
Syslog.info("Application #{@app_name} logging initialized")
end
def self.ensure_connection_health
unless Syslog.opened?
establish_connection
Syslog.warning("Syslog connection restored after interruption")
end
end
def self.format_message(message, context)
if context.any?
context_str = context.map { |k, v| "#{k}=#{v}" }.join(" ")
"#{message} [#{context_str}]"
else
message.to_s
end
end
def self.send_message(level, message)
case level
when :debug then Syslog.debug(message)
when :info then Syslog.info(message)
when :warning then Syslog.warning(message)
when :error then Syslog.err(message)
when :critical then Syslog.crit(message)
end
end
def self.skip_level?(level)
level_priorities = {
debug: 7, info: 6, warning: 4, error: 3, critical: 2
}
min_priority = level_priorities[@min_level]
current_priority = level_priorities[level]
current_priority > min_priority
end
def self.setup_signal_handlers
Signal.trap('USR1') do
Syslog.info("Received USR1 signal - logging statistics")
# Implementation specific statistics logging
end
Signal.trap('HUP') do
@mutex.synchronize do
Syslog.info("Received HUP signal - reconnecting to syslog")
Syslog.close if Syslog.opened?
establish_connection
end
end
end
def self.register_exit_handler
at_exit do
if Syslog.opened?
Syslog.info("Application #{@app_name} shutting down")
Syslog.close
end
end
end
end
# Production initialization
ProductionSyslogManager.configure(
app_name: "webapp",
facility: Syslog::LOG_LOCAL0,
min_level: :warning,
include_pid: true
)
# Usage in application code
ProductionSyslogManager.log(:info, "User session created",
context: { user_id: 12345, ip: "10.0.0.1" })
ProductionSyslogManager.log(:error, "Payment processing failed",
context: { order_id: 67890, amount: 99.99 })
Structured logging with syslog requires consistent message formatting that parsing tools can process reliably. JSON formatting within syslog messages enables automated log analysis while preserving syslog delivery benefits.
require 'json'
class StructuredSyslogLogger
def initialize(service_name, version:, environment:)
@service_name = service_name
@version = version
@environment = environment
@base_context = {
service: service_name,
version: version,
environment: environment,
hostname: Socket.gethostname,
pid: Process.pid
}
Syslog.open(service_name, Syslog::LOG_PID, Syslog::LOG_LOCAL0)
end
def log_event(level, event_type, message, **context)
log_data = @base_context.merge(
timestamp: Time.now.utc.iso8601,
level: level.to_s,
event_type: event_type.to_s,
message: message,
**context
)
json_message = JSON.generate(log_data)
case level
when :info then Syslog.info(json_message)
when :warning then Syslog.warning(json_message)
when :error then Syslog.err(json_message)
when :critical then Syslog.crit(json_message)
end
rescue JSON::GeneratorError => e
# Fallback for non-serializable data
fallback_message = "JSON_ERROR: #{e.message} - #{message}"
Syslog.err(fallback_message)
end
def log_request(method, path, status, duration, **context)
log_event(:info, :http_request, "#{method} #{path}",
http_status: status,
duration_ms: duration,
**context)
end
def log_error(exception, **context)
log_event(:error, :exception, exception.message,
exception_class: exception.class.name,
backtrace: exception.backtrace&.first(10),
**context)
end
end
# Usage in web application
logger = StructuredSyslogLogger.new("api-service",
version: "1.2.3",
environment: "production")
# HTTP request logging
logger.log_request("POST", "/api/users", 201, 45.2, user_id: 123)
# Error logging with context
begin
raise StandardError, "Database connection timeout"
rescue => e
logger.log_error(e, operation: "user_lookup", database: "primary")
end
High-throughput applications require syslog message batching and buffering strategies to prevent logging operations from impacting application performance. Asynchronous message delivery with background thread processing maintains throughput while preserving message ordering.
require 'thread'
require 'json'
class AsyncSyslogBuffer
def initialize(app_name, buffer_size: 100, flush_interval: 5)
@app_name = app_name
@buffer = Queue.new
@buffer_size = buffer_size
@flush_interval = flush_interval
@running = false
@mutex = Mutex.new
initialize_syslog
start_background_thread
end
def log(level, message, **context)
return unless @running
log_entry = {
level: level,
message: message,
context: context,
timestamp: Time.now.utc.iso8601
}
@buffer.push(log_entry)
force_flush if @buffer.size >= @buffer_size
end
def shutdown
@running = false
@flush_thread&.join(5) # Wait up to 5 seconds for flush
flush_remaining_messages
Syslog.close if Syslog.opened?
end
private
def initialize_syslog
Syslog.open(@app_name, Syslog::LOG_PID | Syslog::LOG_NDELAY,
Syslog::LOG_LOCAL0)
end
def start_background_thread
@running = true
@flush_thread = Thread.new do
while @running
sleep(@flush_interval)
flush_buffer
end
end
end
def flush_buffer
return if @buffer.empty?
@mutex.synchronize do
messages_to_flush = []
messages_to_flush << @buffer.pop until @buffer.empty?
messages_to_flush.each do |entry|
send_to_syslog(entry)
end
end
rescue => e
# Log flush errors to stderr to avoid recursion
STDERR.puts "Syslog flush error: #{e.message}"
end
def force_flush
Thread.new { flush_buffer }
end
def flush_remaining_messages
flush_buffer until @buffer.empty?
end
def send_to_syslog(entry)
formatted_message = format_entry(entry)
case entry[:level]
when :debug then Syslog.debug(formatted_message)
when :info then Syslog.info(formatted_message)
when :warning then Syslog.warning(formatted_message)
when :error then Syslog.err(formatted_message)
end
end
def format_entry(entry)
if entry[:context].any?
context_json = JSON.generate(entry[:context])
"#{entry[:message]} #{context_json}"
else
entry[:message]
end
rescue JSON::GeneratorError
entry[:message]
end
end
# Production usage
async_logger = AsyncSyslogBuffer.new("high_volume_app",
buffer_size: 50,
flush_interval: 2)
# High frequency logging won't block application
1000.times do |i|
async_logger.log(:info, "Processing item #{i}",
batch_id: "batch_001", item_count: i)
end
# Ensure clean shutdown
at_exit { async_logger.shutdown }
Common Pitfalls
Message formatting inconsistencies create parsing difficulties and information loss in production logging systems. Applications mixing formatted and unformatted messages, or using inconsistent field separators, complicate automated log analysis and monitoring setup.
# PROBLEMATIC: Inconsistent message formats
Syslog.open("inconsistent_app") do |s|
s.info("User login successful") # Plain text
s.info("user_id=123 action=login status=success") # Key-value pairs
s.info('{"user_id": 123, "action": "login"}') # JSON
s.info("LOGIN: user 123 from 192.168.1.1") # Custom format
end
# BETTER: Consistent structured format
class ConsistentLogger
def initialize(app_name)
@app_name = app_name
Syslog.open(app_name, Syslog::LOG_PID)
end
def log_structured(level, event, **fields)
# Always use consistent key=value format
message_parts = ["event=#{event}"]
message_parts += fields.map { |k, v| "#{k}=#{v.inspect}" }
formatted_message = message_parts.join(" ")
case level
when :info then Syslog.info(formatted_message)
when :warning then Syslog.warning(formatted_message)
when :error then Syslog.err(formatted_message)
end
end
end
logger = ConsistentLogger.new("consistent_app")
logger.log_structured(:info, "user_login", user_id: 123, ip: "192.168.1.1")
logger.log_structured(:error, "db_error", table: "users", error: "timeout")
Facility misuse leads to message routing problems and operational confusion. Applications incorrectly using system facilities like kern or mail, or failing to coordinate facility usage across related services, create log management complications.
# PROBLEMATIC: Using inappropriate facilities
Syslog.open("webapp", Syslog::LOG_PID, Syslog::LOG_KERN) # Kernel facility!
Syslog.open("emailer", Syslog::LOG_PID, Syslog::LOG_CRON) # Cron facility!
# CORRECT: Use appropriate facilities for application types
class FacilityManager
# Define facility mappings for different application types
FACILITY_MAP = {
web_application: Syslog::LOG_LOCAL0,
background_worker: Syslog::LOG_LOCAL1,
database_service: Syslog::LOG_LOCAL2,
cache_service: Syslog::LOG_LOCAL3,
monitoring_agent: Syslog::LOG_LOCAL4,
custom_daemon: Syslog::LOG_DAEMON,
user_script: Syslog::LOG_USER
}.freeze
def self.open_for_type(app_name, app_type)
facility = FACILITY_MAP[app_type] || Syslog::LOG_USER
unless FACILITY_MAP.key?(app_type)
warn "Unknown app_type #{app_type}, defaulting to LOG_USER"
end
Syslog.open(app_name, Syslog::LOG_PID, facility)
Syslog.info("Opened syslog with facility #{facility} for #{app_type}")
end
end
# Proper facility usage
FacilityManager.open_for_type("web_server", :web_application)
FacilityManager.open_for_type("job_processor", :background_worker)
Connection state assumptions cause runtime errors and message loss. Applications assuming syslog connections persist across process boundaries, signal handling, or exception recovery create unreliable logging behavior.
# PROBLEMATIC: Assuming connection persistence
def unsafe_logging_pattern
# This fails if connection was closed elsewhere
Syslog.info("This might fail silently")
# This fails after process fork
fork do
Syslog.info("Child process message") # Uses parent's connection!
end
end
# ROBUST: Always verify connection state
class SafeSyslogWrapper
def initialize(app_name, facility = Syslog::LOG_USER)
@app_name = app_name
@facility = facility
@options = Syslog::LOG_PID | Syslog::LOG_CONS
@mutex = Mutex.new
end
def with_syslog
@mutex.synchronize do
was_open = ensure_connection
begin
yield Syslog
rescue => e
# Log the error and attempt reconnection
attempt_error_recovery(e)
raise e
ensure
# Only close if we opened it in this call
Syslog.close if !was_open && Syslog.opened?
end
end
end
private
def ensure_connection
if Syslog.opened?
# Verify connection is for correct identity
if Syslog.ident != @app_name
Syslog.close
Syslog.open(@app_name, @options, @facility)
return false
end
return true
else
Syslog.open(@app_name, @options, @facility)
return false
end
end
def attempt_error_recovery(error)
case error
when SystemCallError
# System-level error, try reconnecting
Syslog.close if Syslog.opened?
sleep(0.1) # Brief delay before retry
Syslog.open(@app_name, @options, @facility)
when RuntimeError
# Ruby-level error, might be connection state issue
if error.message.include?("syslog")
Syslog.close if Syslog.opened?
Syslog.open(@app_name, @options, @facility)
end
end
rescue
# If recovery fails, fall back to stderr
STDERR.puts "Syslog recovery failed: #{error.message}"
end
end
# Usage with automatic connection management
wrapper = SafeSyslogWrapper.new("reliable_app")
wrapper.with_syslog do |s|
s.info("This message will be delivered reliably")
end
# Safe across process boundaries
fork do
wrapper.with_syslog do |s|
s.info("Child process message with proper connection")
end
end
Priority level confusion leads to inappropriate message filtering and alerting behavior. Applications misusing emergency or critical levels for routine errors, or failing to distinguish between warning and error conditions, create operational noise and missed alerts.
# PROBLEMATIC: Incorrect priority usage
def bad_priority_usage
Syslog.open("confused_app")
# These are wrong priority levels for these situations
Syslog.emerg("User entered invalid email format") # Not an emergency!
Syslog.alert("Database query took 2 seconds") # Not urgent!
Syslog.debug("Payment processed successfully") # Should be info!
Syslog.info("Database server unreachable") # Should be error!
Syslog.close
end
# CORRECT: Appropriate priority selection
class PriorityGuideLogger
def initialize(app_name)
@app_name = app_name
Syslog.open(app_name, Syslog::LOG_PID)
end
def log_user_error(message, **context)
# User errors are informational for debugging
Syslog.info(format_message("USER_ERROR", message, context))
end
def log_validation_warning(message, **context)
# Validation issues worth noting but not errors
Syslog.notice(format_message("VALIDATION", message, context))
end
def log_performance_warning(message, duration:, threshold:, **context)
if duration > threshold * 3
# Severe performance degradation
Syslog.warning(format_message("PERFORMANCE_SEVERE", message,
context.merge(duration: duration)))
else
# Minor performance issue
Syslog.notice(format_message("PERFORMANCE_MINOR", message,
context.merge(duration: duration)))
end
end
def log_system_error(message, recoverable: true, **context)
if recoverable
# Recoverable system error
Syslog.err(format_message("RECOVERABLE_ERROR", message, context))
else
# Non-recoverable system error requiring intervention
Syslog.crit(format_message("CRITICAL_ERROR", message, context))
end
end
def log_emergency(message, **context)
# Only for system unusable conditions
# Requires immediate human intervention
Syslog.emerg(format_message("EMERGENCY", message, context))
end
private
def format_message(category, message, context)
context_str = context.map { |k, v| "#{k}=#{v}" }.join(" ")
"[#{category}] #{message} #{context_str}".strip
end
end
# Proper usage examples
logger = PriorityGuideLogger.new("priority_aware_app")
# Appropriate priority selections
logger.log_user_error("Invalid email format", user_id: 123, email: "bad-email")
logger.log_performance_warning("Slow query detected",
duration: 5.2, threshold: 2.0, query: "SELECT * FROM users")
logger.log_system_error("Database connection failed",
recoverable: true, database: "primary", retry_count: 2)
logger.log_system_error("Disk space critically low",
recoverable: false, filesystem: "/var", available: "1%")
Reference
Core Methods
Method | Parameters | Returns | Description |
---|---|---|---|
Syslog.open(...) |
ident (String), options (Integer), facility (Integer) |
Syslog |
Opens connection with program identity, logging options, and facility |
Syslog.open(...) { } |
ident (String), block |
Block result | Opens connection and yields to block, automatically closes |
Syslog.close |
None | nil |
Closes active syslog connection |
Syslog.opened? |
None | Boolean |
Returns true if connection is currently open |
Syslog.reopen |
None | Syslog |
Reopens connection with same parameters |
Message Priority Methods
Method | Priority Level | Numeric Value | Usage Guidelines |
---|---|---|---|
#emerg(message, ...) |
Emergency | 0 | System unusable, requires immediate action |
#alert(message, ...) |
Alert | 1 | Action must be taken immediately |
#crit(message, ...) |
Critical | 2 | Critical conditions requiring urgent attention |
#err(message, ...) |
Error | 3 | Error conditions that affect functionality |
#warning(message, ...) |
Warning | 4 | Warning conditions worth monitoring |
#notice(message, ...) |
Notice | 5 | Normal but significant conditions |
#info(message, ...) |
Informational | 6 | General informational messages |
#debug(message, ...) |
Debug | 7 | Debug-level messages for development |
Connection State Methods
Method | Parameters | Returns | Description |
---|---|---|---|
Syslog.ident |
None | String |
Returns current program identity string |
Syslog.options |
None | Integer |
Returns current logging options bitmask |
Syslog.facility |
None | Integer |
Returns current facility code |
Logging Options Constants
Constant | Value | Description |
---|---|---|
LOG_PID |
Process ID inclusion | Includes process ID in each message |
LOG_CONS |
Console fallback | Writes to console if syslog unavailable |
LOG_ODELAY |
Delayed open | Delays connection until first message |
LOG_NDELAY |
Immediate open | Opens connection immediately |
LOG_NOWAIT |
No wait | Does not wait for child processes |
LOG_PERROR |
Standard error | Also logs to standard error |
Facility Constants
Constant | Purpose | Typical Usage |
---|---|---|
LOG_KERN |
Kernel messages | System kernel (restricted) |
LOG_USER |
User-level messages | Default for user applications |
LOG_MAIL |
Mail system | Email server applications |
LOG_DAEMON |
System daemons | Background service processes |
LOG_AUTH |
Security/authorization | Authentication systems |
LOG_SYSLOG |
Syslog daemon | Internal syslog messages |
LOG_LPR |
Line printer | Print system messages |
LOG_NEWS |
Network news | USENET news systems |
LOG_UUCP |
UUCP system | Unix-to-Unix copy protocol |
LOG_CRON |
Clock daemon | Scheduled task systems |
LOG_AUTHPRIV |
Security/authorization | Private authentication |
LOG_FTP |
FTP daemon | File transfer systems |
LOG_LOCAL0 through LOG_LOCAL7 |
Local use | Custom application facilities |
Priority Level Bitmasks
Priority | Bitmask Value | Filtering Usage |
---|---|---|
LOG_EMERG |
0 | Most critical messages only |
LOG_ALERT |
1 | Alert level and above |
LOG_CRIT |
2 | Critical level and above |
LOG_ERR |
3 | Error level and above |
LOG_WARNING |
4 | Warning level and above |
LOG_NOTICE |
5 | Notice level and above |
LOG_INFO |
6 | Info level and above |
LOG_DEBUG |
7 | All messages including debug |
Common Exception Classes
Exception | Trigger Conditions | Recovery Strategy |
---|---|---|
RuntimeError |
Connection already open, invalid arguments | Check opened? state, verify parameters |
SystemCallError |
System resource limits, permissions | Fallback logging, retry with delay |
Errno::ENOENT |
Syslog daemon unavailable | Alternative logging destination |
Errno::EACCES |
Permission denied | Check process privileges, facility permissions |
Errno::EMFILE |
File descriptor limit reached | Close unused connections, system tuning |
Format String Guidelines
Format Type | Example | Best Practice |
---|---|---|
Printf-style | "User %d logged in from %s" |
Use for type safety |
String interpolation | "User #{id} from #{ip}" |
Acceptable for simple cases |
Structured | "event=login user_id=#{id} ip=#{ip}" |
Preferred for parsing |
JSON | JSON.generate(event: "login", user: id) |
Best for complex data |