Module: Legion::Logging::Builder
- Included in:
- Legion::Logging, Logger
- Defined in:
- lib/legion/logging/builder.rb
Instance Method Summary collapse
- #async? ⇒ Boolean
- #build_context_kv_pairs ⇒ Object
- #build_runner_trace(loc = caller_locations(6, 1)&.first) ⇒ Object
- #json? ⇒ Boolean
- #json_format(include_pid: false) ⇒ Object
- #level ⇒ Object
- #log ⇒ Object
- #log_format(format: :text, include_pid: false) ⇒ Object
- #log_level(level = 'debug') ⇒ Object
- #output(**options) ⇒ Object
- #prepare_log_path(path) ⇒ Object
- #resolve_lex_tag(options) ⇒ Object
- #set_log(logfile: nil, log_stdout: nil) ⇒ Object
-
#start_async_writer(buffer_size: 10_000) ⇒ Object
rubocop:disable Naming/PredicateMethod.
- #stop_async_writer ⇒ Object
- #text_format(include_pid: false, **options) ⇒ Object
Instance Method Details
#async? ⇒ Boolean
174 175 176 |
# File 'lib/legion/logging/builder.rb', line 174 def async? (@async == true && @async_writer&.alive?) || false end |
#build_context_kv_pairs ⇒ Object
88 89 90 91 92 93 94 95 96 97 |
# File 'lib/legion/logging/builder.rb', line 88 def build_context_kv_pairs pairs = [] request_id = Thread.current[:legion_log_request_id] pairs << "request_id=#{request_id}" if request_id.is_a?(String) && !request_id.empty? exchange_id = Thread.current[:legion_log_exchange_id] pairs << "exchange_id=#{exchange_id}" if exchange_id.is_a?(String) && !exchange_id.empty? chain_id = Thread.current[:legion_log_chain_id] pairs << "chain_id=#{chain_id}" if chain_id.is_a?(String) && !chain_id.empty? pairs.join(' ') end |
#build_runner_trace(loc = caller_locations(6, 1)&.first) ⇒ Object
99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/legion/logging/builder.rb', line 99 def build_runner_trace(loc = caller_locations(6, 1)&.first) return unless loc path = loc.to_s.split('/').last(2) { type: path[0], file: File.basename(loc.path, '.*'), function: loc.base_label, line_number: loc.lineno } end |
#json? ⇒ Boolean
17 18 19 |
# File 'lib/legion/logging/builder.rb', line 17 def json? @format == :json end |
#json_format(include_pid: false) ⇒ Object
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 |
# File 'lib/legion/logging/builder.rb', line 21 def json_format(include_pid: false) log.formatter = proc do |severity, datetime, _progname, msg| entry = { timestamp: datetime.utc.iso8601(3), level: severity.downcase, message: msg.is_a?(String) ? msg.gsub(/\e\[[0-9;]*m/, '') : msg.to_s, thread: Thread.current.object_id } entry[:pid] = ::Process.pid if include_pid segments = Thread.current[:legion_log_segments] entry[:segments] = segments if segments method_ctx = Thread.current[:legion_log_method] entry[:method] = method_ctx if method_ctx conv_id = Thread.current[:legion_log_conv_id] entry[:conversation_id] = conv_id if conv_id.is_a?(String) && !conv_id.empty? request_id = Thread.current[:legion_log_request_id] entry[:request_id] = request_id if request_id.is_a?(String) && !request_id.empty? exchange_id = Thread.current[:legion_log_exchange_id] entry[:exchange_id] = exchange_id if exchange_id.is_a?(String) && !exchange_id.empty? chain_id = Thread.current[:legion_log_chain_id] entry[:chain_id] = chain_id if chain_id.is_a?(String) && !chain_id.empty? "#{::JSON.generate(entry)}\n" rescue StandardError => e warn("Legion::Logging::Builder#json_format formatter failed: #{e.}") "{\"timestamp\":\"#{datetime}\",\"level\":\"#{severity}\",\"message\":#{msg.to_s.dump}}\n" end end |
#level ⇒ Object
147 148 149 |
# File 'lib/legion/logging/builder.rb', line 147 def level log.level end |
#log ⇒ Object
115 116 117 |
# File 'lib/legion/logging/builder.rb', line 115 def log @log ||= set_log end |
#log_format(format: :text, include_pid: false) ⇒ Object
8 9 10 11 12 13 14 15 |
# File 'lib/legion/logging/builder.rb', line 8 def log_format(format: :text, include_pid: false, **) @format = format.to_sym if @format == :json json_format(include_pid: include_pid) else text_format(include_pid: include_pid, **) end end |
#log_level(level = 'debug') ⇒ Object
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/legion/logging/builder.rb', line 151 def log_level(level = 'debug') log.level = case level when 'trace', 'debug' ::Logger::DEBUG when 'info' ::Logger::INFO when 'warn' ::Logger::WARN when 'error' ::Logger::ERROR when 'fatal' ::Logger::FATAL when nil 42 else if level.is_a? Integer level else 1 end end end |
#output(**options) ⇒ Object
111 112 113 |
# File 'lib/legion/logging/builder.rb', line 111 def output(**) set_log(logfile: [:log_file], log_stdout: [:log_stdout]) end |
#prepare_log_path(path) ⇒ Object
141 142 143 144 145 |
# File 'lib/legion/logging/builder.rb', line 141 def prepare_log_path(path) = File.(path) FileUtils.mkdir_p(File.dirname()) end |
#resolve_lex_tag(options) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/legion/logging/builder.rb', line 70 def resolve_lex_tag() segments = Thread.current[:legion_log_segments] tag = if segments segments.map { |s| "[#{s}]" }.join elsif .key?(:lex_segments) [:lex_segments].map { |s| "[#{s}]" }.join elsif .key?(:lex) && ![:lex].nil? "[#{[:lex]}]" end method_ctx = Thread.current[:legion_log_method] tag = "#{tag}{#{method_ctx}}" if tag && method_ctx context_id = Thread.current[:legion_log_conv_id] tag = "#{tag}{#{context_id}}" if tag && context_id.is_a?(String) && !context_id.empty? tag end |
#set_log(logfile: nil, log_stdout: nil) ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/legion/logging/builder.rb', line 119 def set_log(logfile: nil, log_stdout: nil, **) previous_log = @log if logfile && log_stdout != false path = prepare_log_path(logfile) require_relative 'multi_io' file = File.new(path, 'a') file.sync = true io = MultiIO.new($stdout, file) @log = ::Logger.new(io) elsif logfile file = File.new(prepare_log_path(logfile), 'a') file.sync = true @log = ::Logger.new(file) else @log = ::Logger.new($stdout) end close_replaced_log(previous_log) @log end |
#start_async_writer(buffer_size: 10_000) ⇒ Object
rubocop:disable Naming/PredicateMethod
179 180 181 182 183 184 185 186 187 |
# File 'lib/legion/logging/builder.rb', line 179 def start_async_writer(buffer_size: 10_000) require_relative 'async_writer' return false if @async_writer&.alive? && stop_async_writer == false @async_writer = AsyncWriter.new(log, buffer_size: buffer_size) @async_writer.start @async = true true end |
#stop_async_writer ⇒ Object
189 190 191 192 193 194 195 196 197 198 |
# File 'lib/legion/logging/builder.rb', line 189 def stop_async_writer writer = @async_writer stopped = writer&.stop return false if stopped == false close_replaced_log(writer.logger) if writer.respond_to?(:logger) @async_writer = nil if @async_writer.equal?(writer) @async = false true end |
#text_format(include_pid: false, **options) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/legion/logging/builder.rb', line 49 def text_format(include_pid: false, **) log.formatter = proc do |severity, datetime, _progname, msg| lex_name = resolve_lex_tag() runner_trace = Thread.current[:legion_log_caller] || build_runner_trace if lex_name string = "[#{datetime}]" string.concat("[#{::Process.pid}]") if include_pid string.concat(lex_name) if lex_name if runner_trace.is_a?(Hash) && ([:extended] || severity == 'debug') string.concat("[#{runner_trace[:type]}:#{runner_trace[:file]}:#{runner_trace[:function]}:#{runner_trace[:line_number]}]") end ctx_pairs = build_context_kv_pairs if ctx_pairs.empty? string.concat(" #{severity} #{msg}\n") else string.concat(" #{severity} #{msg} #{ctx_pairs}\n") end string end end |