Module: JsonLogging::JsonLoggerExtension

Included in:
JsonLogger
Defined in:
lib/json_logging/json_logger_extension.rb

Overview

Module that extends any Logger with JSON formatting capabilities This is used by JsonLogging.new to wrap standard loggers

Constant Summary collapse

SEVERITY_NAMES =
{
  ::Logger::DEBUG => "DEBUG",
  ::Logger::INFO => "INFO",
  ::Logger::WARN => "WARN",
  ::Logger::ERROR => "ERROR",
  ::Logger::FATAL => "FATAL",
  ::Logger::UNKNOWN => "UNKNOWN"
}.freeze

Instance Method Summary collapse

Instance Method Details

#add(severity, message = nil, progname = nil) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/json_logging/json_logger_extension.rb', line 29

def add(severity, message = nil, progname = nil)
  return true if severity < level

  msg = if message.nil?
    if block_given?
      yield
    else
      progname
    end
  else
    message
  end

  payload = build_payload(severity, progname, msg)

  stringified = stringify_keys(payload)
  @logdev&.write("#{stringified.to_json}\n")
  true
rescue => e
  # Never fail logging - write a fallback entry
  # Initialize msg if it wasn't set due to error
  msg ||= "<uninitialized>"

  fallback = {
    timestamp: Helpers.normalize_timestamp(Time.now),
    severity: severity_name(severity),
    message: Sanitizer.sanitize_string(Helpers.safe_string(msg)),
    logger_error: {
      class: Sanitizer.sanitize_string(e.class.name),
      message: Sanitizer.sanitize_string(Helpers.safe_string(e.message))
    }
  }
  @logdev&.write("#{fallback.compact.to_json}\n")
  true
end

#flushObject

Flush tags (used by Rails when request completes)



87
88
89
90
# File 'lib/json_logging/json_logger_extension.rb', line 87

def flush
  clear_tags!
  super if defined?(super)
end

#format_message(severity, datetime, progname, msg) ⇒ Object

Override format_message to ensure it uses JSON formatting even if called directly



66
67
68
# File 'lib/json_logging/json_logger_extension.rb', line 66

def format_message(severity, datetime, progname, msg)
  formatter.call(severity, datetime, progname, msg)
end

#formatterObject



14
15
16
17
18
19
20
# File 'lib/json_logging/json_logger_extension.rb', line 14

def formatter
  @formatter_with_tags ||= begin
    formatter_with_tags = FormatterWithTags.new(self)
    instance_variable_set(:@formatter, formatter_with_tags)
    formatter_with_tags
  end
end

#formatter=(formatter) ⇒ Object



22
23
24
25
26
27
# File 'lib/json_logging/json_logger_extension.rb', line 22

def formatter=(formatter)
  # Always use FormatterWithTags to ensure JSON formatting
  formatter_with_tags = @formatter_with_tags || FormatterWithTags.new(self)
  instance_variable_set(:@formatter, formatter_with_tags)
  @formatter_with_tags = formatter_with_tags
end

#tagged(*tags) ⇒ Object

Native tag support compatible with Rails.logger.tagged



71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/json_logging/json_logger_extension.rb', line 71

def tagged(*tags)
  if block_given?
    formatter.tagged(*tags) { yield self }
  else
    # Return a new wrapped logger with tags applied (similar to TaggedLogging)
    logger = JsonLogging.new(self)
    # Extend formatter with LocalTagStorage to preserve current tags when creating nested loggers
    # This matches Rails' TaggedLogging behavior
    logger.formatter.extend(LocalTagStorage)
    # Push tags through formatter (matches Rails delegation pattern)
    logger.formatter.push_tags(*formatter.current_tags, *tags)
    logger
  end
end