File: local_log_template.rb

package info (click to toggle)
ruby-lumberjack 2.0.4-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 956 kB
  • sloc: ruby: 7,957; makefile: 2
file content (209 lines) | stat: -rw-r--r-- 7,020 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# frozen_string_literal: true

module Lumberjack
  # This is a log template designed for local environments. It provides a simple,
  # human-readable format that includes key information about log entries while
  # omitting extraneous details. The template can be configured to include or
  # exclude certain components such as the times, process ID, program name,
  # and attributes.
  #
  # It is registered with the TemplateRegistry as :local.
  #
  # @see Template
  class LocalLogTemplate
    TemplateRegistry.add(:local, self)

    # Create a new LocalLogTemplate instance.
    #
    # @param options [Hash] Options for configuring the template.
    # @option options [Boolean, Array<String>, nil] :exclude_attributes If true, all attributes are excluded.
    #   If an array of strings is provided, those attributes (and their sub-attributes) are excluded.
    #   Defaults to nil (include all attributes).
    # @option options [Boolean] :exclude_progname If true, the progname is excluded. Defaults to false.
    # @option options [Boolean] :exclude_pid If true, the process ID is excluded. Defaults to true.
    # @option options [Boolean] :exclude_time If true, the time is excluded. Defaults to true.
    # @option options [Boolean] :colorize If true, colorize the output based on severity. Defaults to false.
    # @option options [Symbol, Formatter, #call] :exception_formatter The formatter to use for exceptions in messages.
    #   Can be a symbol registered in the FormatterRegistry, a Formatter instance, or any object that responds to #call.
    #   Defaults to nil (use default exception formatting). If the logger does not have an exception formatter
    #   configured, then the device will use this to format exceptions.
    # @option options [String, Symbol] :severity_format The optional format for severity labels (padded, char, emoji).
    def initialize(options = {})
      self.exclude_progname = options.fetch(:exclude_progname, false)
      self.exclude_pid = options.fetch(:exclude_pid, true)
      self.exclude_time = options.fetch(:exclude_time, true)
      self.exclude_attributes = options.fetch(:exclude_attributes, nil)
      self.colorize = options.fetch(:colorize, false)
      self.severity_format = options.fetch(:severity_format, nil)
      self.exception_formatter = options.fetch(:exception_formatter, :exception)
    end

    # Format a log entry according to the template.
    #
    # @param entry [LogEntry] The log entry to format.
    # @return [String] The formatted log entry.
    def call(entry)
      message = entry.message
      if message.is_a?(Exception) && exception_formatter
        message = exception_formatter.call(message)
      end

      formatted = +""
      formatted << entry.time.strftime("%Y-%m-%d %H:%M:%S.%6N ") unless exclude_time?
      formatted << "#{severity_label(entry)} #{message}"
      formatted << "#{Lumberjack::LINE_SEPARATOR}    progname: #{entry.progname}" if entry.progname.to_s != "" && !exclude_progname?
      formatted << "#{Lumberjack::LINE_SEPARATOR}    pid: #{entry.pid}" unless exclude_pid?

      if entry.attributes && !entry.attributes.empty? && !exclude_attributes?
        Lumberjack::Utils.flatten_attributes(entry.attributes).to_a.sort_by(&:first).each do |name, value|
          next if @attribute_filter.any? do |filter_name|
            if name.start_with?(filter_name)
              next_char = name[filter_name.length]
              next_char.nil? || next_char == "."
            end
          end

          formatted << "#{Lumberjack::LINE_SEPARATOR}    #{name}: #{value}"
        end
      end

      formatted = Template.colorize_entry(formatted, entry) if colorize?
      formatted << Lumberjack::LINE_SEPARATOR
    end

    # Return true if all attributes are excluded, false otherwise.
    #
    # @return [Boolean]
    def exclude_attributes?
      @exclude_attributes
    end

    # Return the list of excluded attribute names.
    #
    # @return [Array<String>]
    def excluded_attributes
      @attribute_filter.dup
    end

    # Set the attributes to exclude. If set to true, all attributes are excluded.
    # If set to an array of strings, those attributes (and their sub-attributes)
    # are excluded. If set to false or nil, no attributes are excluded.
    #
    # @param value [Boolean, Array<String>, nil]
    # @return [void]
    def exclude_attributes=(value)
      @exclude_attributes = false
      @attribute_filter = []
      if value == true
        @exclude_attributes = true
      elsif value
        @attribute_filter = Array(value).map(&:to_s)
      end
    end

    # Return true if the progname is excluded, false otherwise.
    #
    # @return [Boolean]
    def exclude_progname?
      @exclude_progname
    end

    # Set whether to exclude the progname.
    #
    # @param value [Boolean]
    # @return [void]
    def exclude_progname=(value)
      @exclude_progname = !!value
    end

    # Return true if the pid is excluded, false otherwise.
    #
    # @return [Boolean]
    def exclude_pid?
      @exclude_pid
    end

    # Set whether to exclude the pid.
    #
    # @param value [Boolean]
    # @return [void]
    def exclude_pid=(value)
      @exclude_pid = !!value
    end

    # Return true if the time is excluded, false otherwise.
    #
    # @return [Boolean]
    def exclude_time?
      @exclude_time
    end

    # Set whether to exclude the time.
    #
    # @param value [Boolean]
    # @return [void]
    def exclude_time=(value)
      @exclude_time = !!value
    end

    # Return true if colorization is enabled, false otherwise.
    #
    # @return [Boolean]
    def colorize?
      @colorize
    end

    # Set whether to enable colorization.
    #
    # @param value [Boolean]
    # @return [void]
    def colorize=(value)
      @colorize = !!value
    end

    # Set the severity format.
    #
    # @param value [String, Symbol] The severity format (:padded, :char, :emoji, :level, nil).
    # @return [void]
    def severity_format=(value)
      @severity_format = value.to_s
    end

    # Return the current severity format.
    #
    # @return [String]
    attr_reader :severity_format

    # Set the exception formatter. Can be a symbol registered in the FormatterRegistry,
    # a Formatter instance, or any object that responds to #call.
    #
    # @param value [Symbol, Formatter, #call] The exception formatter to use.
    # @return [void]
    def exception_formatter=(value)
      @exception_formatter = value.is_a?(Symbol) ? FormatterRegistry.formatter(value) : value
    end

    # Return the exception formatter.
    #
    # @return [#call, nil]
    attr_reader :exception_formatter

    private

    def severity_label(entry)
      severity = entry.severity_data
      case severity_format
      when "padded"
        severity.padded_label
      when "char"
        severity.char
      when "emoji"
        severity.emoji
      when "level"
        severity.level.to_s
      else
        severity.label
      end
    end
  end
end