diff options
author | Jacob Vosmaer (GitLab) <jacob@gitlab.com> | 2018-03-19 11:58:59 +0000 |
---|---|---|
committer | Douwe Maan <douwe@gitlab.com> | 2018-03-19 11:58:59 +0000 |
commit | b8a5e52193b7d02de4802b589e098bbbfa0ec425 (patch) | |
tree | 30833503feb797f8610b21f2475c04e959b0ebac /lib/gitlab_logger.rb | |
parent | 355e70e08b9180456ef57fb79a2c3b5654f85479 (diff) | |
download | gitlab-shell-b8a5e52193b7d02de4802b589e098bbbfa0ec425.tar.gz |
Switch to structured logging
Diffstat (limited to 'lib/gitlab_logger.rb')
-rw-r--r-- | lib/gitlab_logger.rb | 96 |
1 files changed, 94 insertions, 2 deletions
diff --git a/lib/gitlab_logger.rb b/lib/gitlab_logger.rb index 872d3ed..cdca25b 100644 --- a/lib/gitlab_logger.rb +++ b/lib/gitlab_logger.rb @@ -1,4 +1,6 @@ +require 'json' require 'logger' +require 'time' require_relative 'gitlab_config' @@ -10,7 +12,97 @@ rescue NameError Logger::INFO end +class GitlabLogger + # Emulate the quoting logic of logrus + # https://github.com/sirupsen/logrus/blob/v1.0.5/text_formatter.go#L143-L156 + SHOULD_QUOTE = /[^a-zA-Z0-9\-._\/@^+]/ + + LEVELS = { + Logger::INFO => 'info'.freeze, + Logger::DEBUG => 'debug'.freeze, + Logger::WARN => 'warn'.freeze + }.freeze + + def initialize(level, path, log_format) + @level = level + @log_file = File.open(path, 'ab') + @log_format = log_format + end + + def info(message, data = {}) + log_at(Logger::INFO, message, data) + end + + def debug(message, data = {}) + log_at(Logger::DEBUG, message, data) + end + + def warn(message, data = {}) + log_at(Logger::WARN, message, data) + end + + private + + attr_reader :log_file, :log_format + + def log_at(level, message, data) + return unless @level <= level + + data[:pid] = pid + data[:level] = LEVELS[level] + data[:msg] = message + + # Use RFC3339 to match logrus in the Go parts of gitlab-shell + data[:time] = time_now.to_datetime.rfc3339 + + case log_format + when 'json' + log_file.puts format_json(data) + else + log_file.puts format_text(data) + end + end + + def pid + Process.pid + end + + def time_now + Time.now + end + + def format_text(data) + # We start the line with these fields to match the behavior of logrus + result = [ + format_key_value(:time, data.delete(:time)), + format_key_value(:level, data.delete(:level)), + format_key_value(:msg, data.delete(:msg)) + ] + + data.sort.each { |k, v| result << format_key_value(k, v) } + result.join(' ') + end + + def format_key_value(key, value) + value_string = value.to_s + value_string = value_string.inspect if SHOULD_QUOTE =~ value_string + + "#{key}=#{value_string}" + end + + def format_json(data) + data.each do |key, value| + next unless value.is_a?(String) + + value = value.dup.force_encoding('utf-8') + value = value.inspect unless value.valid_encoding? + data[key] = value.freeze + end + + data.to_json + end +end + config = GitlabConfig.new -$logger = Logger.new(config.log_file) -$logger.level = convert_log_level(config.log_level) +$logger = GitlabLogger.new(convert_log_level(config.log_level), config.log_file, config.log_format) |