moon-logfmt 1.0.3 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 39f8167fa92c462fbf0dbcf43d839dbf7a1b5096
4
- data.tar.gz: 9d77f73ced138f99307ffab5ee5976808f8be3e7
3
+ metadata.gz: ad3d92684b23cd251495e9723dddbcd87db16ae8
4
+ data.tar.gz: e393c13c1f7c40e8d64313cf48d2826f93ae82a4
5
5
  SHA512:
6
- metadata.gz: dcc9a60b418ec171809621f3efcd5731c263bcb1b40b7dbc832aa8b35fcf1dd049b05fc3117e16b3e46b34796a56d1f92a19f83112bd7c0ca45395c71e76d725
7
- data.tar.gz: 1274ccb323dc4184f0329355b37dfe275f6b331fedb2bc33211667d0bf4674cb245220d00b6a9109dfc4d93e372dec4acfbb9460643ff0cb618bb07b815998d4
6
+ metadata.gz: ce0188e6c9f29a7a43f33648d460b2b66bd088b0f2bd14afb1eb9f6c24af87582f92925f657e06e72fb5a9679ef74e09d681cf7b2967e0eb795af51f921aad94
7
+ data.tar.gz: f81eca8be731925137a3777842e74d75ad727dfe0b95f339ca2e5f3a13e952a5ccf747a3376fbd4ab293eecdc2e4abe3f0cb9598426a1d488fe52cdda7ecb79c
@@ -1,10 +1,39 @@
1
1
  module Moon
2
2
  module Logfmt
3
- # Default KEY=VALUE formatter
4
- #
5
- # @param [String] key
6
- # @param [String] value
7
- # @return [String]
8
- FORMATTER = ->(key, value) { "#{key}=#{value}" }
3
+ # Identity Formatter, this was created to interact with the stdlib
4
+ # Logger::Formatter
5
+ class Formatter
6
+ # @return [String] message
7
+ def call(severity, time, progname, msg)
8
+ msg
9
+ end
10
+
11
+ # Returns the default instance of the formatter
12
+ #
13
+ # @return [Formatter]
14
+ def self.default
15
+ @default ||= new
16
+ end
17
+ end
18
+
19
+ # Logfmt's actual formatter, this takes a key and a value and produces
20
+ # a string
21
+ class KeyValueFormatter
22
+ # Default KEY=VALUE formatter
23
+ #
24
+ # @param [String] key
25
+ # @param [String] value
26
+ # @return [String]
27
+ def call(key, value)
28
+ "#{key}=#{value}"
29
+ end
30
+
31
+ # Returns the default instance of the key value formatter
32
+ #
33
+ # @return [KeyValueFormatter]
34
+ def self.default
35
+ @default ||= new
36
+ end
37
+ end
9
38
  end
10
39
  end
@@ -1,36 +1,2 @@
1
1
  require 'moon-logfmt/logger'
2
2
  require 'moon-logfmt/null_logger'
3
-
4
- module Moon
5
- # Implementation of logfmt for Moon
6
- module Logfmt
7
- # Regular expression used for checking strings that may need escaping.
8
- # This regular expression will validate true if the string doesn't need
9
- # escaping.
10
- UNESCAPED_STRING = /\A[\w\.\-\+\%\_\,\:\;\/]*\z/i
11
-
12
- # Escapes the context values and yields the result.
13
- #
14
- # @param [Hash<[String, Symbol], String>] data
15
- # @yieldparam [String] key
16
- # @yieldparam [String] value
17
- def self.escape_context_data(data)
18
- return to_enum :escape_context_data, data unless block_given?
19
- data.each_pair do |key, value|
20
- case value
21
- when Array
22
- value = value.join(',')
23
- else
24
- value = value.to_s
25
- end
26
- value = value.dump unless value =~ UNESCAPED_STRING
27
- yield key.to_s, value
28
- end
29
- end
30
-
31
- # (see Moon::Logfmt::Logger#initialize)
32
- def self.new(*args, &block)
33
- Moon::Logfmt::Logger.new(*args, &block)
34
- end
35
- end
36
- end
@@ -1,5 +1,6 @@
1
1
  require 'moon-logfmt/stdlib_loggable'
2
2
  require 'moon-logfmt/formatter'
3
+ require 'moon-logfmt/utils'
3
4
 
4
5
  module Moon
5
6
  module Logfmt
@@ -8,6 +9,11 @@ module Moon
8
9
  # #new will copy the current logger and append its context data
9
10
  class Logger
10
11
  include StdlibLoggable
12
+ include Severity
13
+
14
+ # The default datetime string format
15
+ # @return [String]
16
+ DEFAULT_DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S%Z'.freeze
11
17
 
12
18
  # The underlaying IO to write to, the default is STDOUT
13
19
  # @return [IO, #puts]
@@ -15,6 +21,10 @@ module Moon
15
21
 
16
22
  # A function which takes a key and value string and produces a string
17
23
  # @return [Proc]
24
+ attr_accessor :key_value_formatter
25
+
26
+ # A function which takes the final context string and formats it
27
+ # @return [Proc]
18
28
  attr_accessor :formatter
19
29
 
20
30
  # Whether to prepend timestamps to the logs
@@ -30,52 +40,91 @@ module Moon
30
40
  # @param [Hash<[String, Symbol], String>] data
31
41
  def initialize(data = {})
32
42
  @io = STDOUT
33
- @formatter = FORMATTER
43
+ @formatter = Formatter.default
44
+ @key_value_formatter = KeyValueFormatter.default
34
45
  @context = data
35
46
  @timestamp = true
47
+ @level = Moon::Logfmt::Severity::DEBUG
48
+ @datetime_format = DEFAULT_DATETIME_FORMAT
49
+ end
50
+
51
+ attr_reader :level
52
+
53
+ # @param [Symbol]
54
+ def level=(lvl)
55
+ @level = Moon::Logfmt.determine_loglevel_from_object(lvl)
36
56
  end
37
57
 
38
58
  # @param [Logfmt::Logger] org
39
59
  # @return [self]
40
60
  def initialize_copy(org)
41
61
  @io = org.io
62
+ @level = org.level
42
63
  @timestamp = org.timestamp
43
64
  @context = org.context.dup
44
65
  @formatter = org.formatter
66
+ @key_value_formatter = org.key_value_formatter
45
67
  self
46
68
  end
47
69
 
70
+ # @param [Integer] severity
71
+ # @return [Symbol]
72
+ private def severity_to_symbol(severity)
73
+ case severity
74
+ when DEBUG then :debug
75
+ when INFO then :info
76
+ when WARN then :warn
77
+ when ERROR then :error
78
+ when FATAL then :fatal
79
+ when UNKNOWN then :unknown
80
+ else
81
+ severity.to_s
82
+ end
83
+ end
84
+
85
+ # Adds timestamp information to the provided data
86
+ #
87
+ # @param [Hash<Symbol, Object>] data to add timestamp to
88
+ # @return [Hash] data given
89
+ private def timestamp_context(data)
90
+ data.tap { |d| d[:now] = Time.now.strftime(@datetime_format) }
91
+ end
92
+
48
93
  # Formats the provided context data
49
94
  #
50
95
  # @param [Hash<[String, Symbol], String>] data
51
96
  # @return [String]
52
- private def format_context(data)
97
+ private def format_context(severity, time, progname, ctx)
98
+ data = {}
99
+ data[:level] = severity_to_symbol(severity) if severity
100
+ timestamp_context(data) if @timestamp
101
+ data[:progname] = progname if progname
102
+ data.merge!(ctx)
53
103
  str = []
54
104
  Logfmt.escape_context_data data do |key, value|
55
- str << @formatter.call(key, value)
105
+ str << @key_value_formatter.call(key, value)
56
106
  end
57
- str.join(' ')
107
+ @formatter.call(severity, time, progname, str.join(' '))
58
108
  end
59
109
 
60
- # Adds timestamp information to the provided data
61
- #
62
- # @param [Hash<Symbol, Object>] data to add timestamp to
63
- # @return [Hash] data given
64
- private def timestamp_context(data)
65
- t = Time.now
66
- fmt = '%04d-%02d-%02dT%02d:%02d:%02d%s'
67
- s = sprintf(fmt, t.year, t.mon, t.day, t.hour, t.min, t.sec, t.zone)
68
- data[:now] = s
69
- data
110
+ protected def write_to_logdev(str)
111
+ @io.puts str
112
+ end
113
+
114
+ # Writes a new context line to the logdev
115
+ # @param [Integer] severity
116
+ # @param [Time] time
117
+ # @param [String] progname
118
+ # @param [Hash] ctx
119
+ protected def write_context(severity, time, progname, ctx)
120
+ write_to_logdev format_context(severity, time, progname, context.merge(ctx))
70
121
  end
71
122
 
72
123
  # Writes a new log line
73
124
  #
74
125
  # @param [Hash<[String, Symbol], String>] data
75
126
  def write(data)
76
- pre = {}
77
- timestamp_context(pre) if @timestamp
78
- @io.puts format_context(pre.merge(context.merge(data)))
127
+ write_context nil, Time.now, nil, data
79
128
  end
80
129
 
81
130
  # Creates a new context by forking the current logger
@@ -0,0 +1,19 @@
1
+ module Moon
2
+ module Logfmt
3
+ # Logging severity.
4
+ module Severity
5
+ # Low-level information, mostly for developers.
6
+ DEBUG = 0
7
+ # Generic (useful) information about system operation.
8
+ INFO = 1
9
+ # A warning.
10
+ WARN = 2
11
+ # A handleable error condition.
12
+ ERROR = 3
13
+ # An unhandleable error that results in a program crash.
14
+ FATAL = 4
15
+ # An unknown message that should always be logged.
16
+ UNKNOWN = 5
17
+ end
18
+ end
19
+ end
@@ -1,54 +1,38 @@
1
+ require 'moon-logfmt/severity'
2
+
1
3
  module Moon
2
4
  module Logfmt
3
- # Logging severity.
4
- module Severity
5
- # Low-level information, mostly for developers.
6
- DEBUG = 0
7
- # Generic (useful) information about system operation.
8
- INFO = 1
9
- # A warning.
10
- WARN = 2
11
- # A handleable error condition.
12
- ERROR = 3
13
- # An unhandleable error that results in a program crash.
14
- FATAL = 4
15
- # An unknown message that should always be logged.
16
- UNKNOWN = 5
17
- end
18
-
19
5
  # Interface for the stdlib Logger class
20
6
  module StdlibLoggable
21
7
  include Severity
22
8
 
23
9
  # @!group std Logger interface
10
+
11
+ # Adds a new logger message
12
+ #
24
13
  # @param [Severity] severity
25
14
  # @param [String, nil] message
26
15
  # @param [String, nil] progname
27
16
  # @yieldreturn [String] message
28
17
  def add(severity, message = nil, progname = nil, &block)
18
+ return if severity < @level
29
19
  message = message || (block && block.call)
30
20
  msg = message || progname
31
21
  data = {}
32
- data[:progname] = progname if progname && message
33
- data[case severity
34
- when DEBUG then :debug
35
- when ERROR then :error
36
- when FATAL then :fatal
37
- when INFO then :msg
38
- when UNKNOWN then :msg
39
- when WARN then :warn
40
- end] = msg
41
- write data
22
+ msg.is_a?(Hash) ? data.merge!(msg) : data.store(:msg, msg)
23
+ write_context(severity, Time.now, progname, data)
42
24
  end
43
25
  alias :log :add
44
26
 
45
27
  # Logs a message
46
28
  #
29
+ # @overload info(data)
30
+ # @param [Hash] data - data to log
47
31
  # @overload info(message)
48
- # @param [String] message
32
+ # @param [String] message - message to log
49
33
  # @overload info(progname, &block)
50
- # @param [String] progname
51
- # @yieldreturn [String] message
34
+ # @param [String] progname - program name
35
+ # @yieldreturn [String] message - message to log
52
36
  def info(progname = nil, &block)
53
37
  add(INFO, nil, progname, &block)
54
38
  end
@@ -0,0 +1,53 @@
1
+ require 'moon-logfmt/severity'
2
+
3
+ module Moon
4
+ # Implementation of logfmt for Moon
5
+ module Logfmt
6
+ # Regular expression used for checking strings that may need escaping.
7
+ # This regular expression will validate true if the string doesn't need
8
+ # escaping.
9
+ UNESCAPED_STRING = /\A[\w\.\-\+\%\_\,\:\;\/]*\z/i
10
+
11
+ # Escapes the context values and yields the result.
12
+ #
13
+ # @param [Hash<[String, Symbol], String>] data
14
+ # @yieldparam [String] key
15
+ # @yieldparam [String] value
16
+ def self.escape_context_data(data)
17
+ return to_enum :escape_context_data, data unless block_given?
18
+ data.each_pair do |key, value|
19
+ case value
20
+ when Array
21
+ value = value.join(',')
22
+ else
23
+ value = value.to_s
24
+ end
25
+ value = value.dump unless value =~ UNESCAPED_STRING
26
+ yield key.to_s, value
27
+ end
28
+ end
29
+
30
+ # Determines what the loglevel should be from the given object
31
+ #
32
+ # @param [Object] object
33
+ # @return [Integer] loglevel
34
+ def self.determine_loglevel_from_object(object)
35
+ return object if object.is_a?(Integer)
36
+ case object.to_s.upcase
37
+ when 'DEBUG' then Moon::Logfmt::Severity::DEBUG
38
+ when 'INFO' then Moon::Logfmt::Severity::INFO
39
+ when 'WARN' then Moon::Logfmt::Severity::WARN
40
+ when 'ERROR' then Moon::Logfmt::Severity::ERROR
41
+ when 'FATAL' then Moon::Logfmt::Severity::FATAL
42
+ when 'UNKNOWN' then Moon::Logfmt::Severity::UNKNOWN
43
+ else
44
+ raise ArgumentError, "unknown log level #{object}"
45
+ end
46
+ end
47
+
48
+ # (see Moon::Logfmt::Logger#initialize)
49
+ def self.new(*args, &block)
50
+ Moon::Logfmt::Logger.new(*args, &block)
51
+ end
52
+ end
53
+ end
@@ -3,7 +3,7 @@ module Moon
3
3
  # Version module
4
4
  module Version
5
5
  # @return [Integer, nil]
6
- MAJOR, MINOR, TEENY, PATCH = 1, 0, 3, nil
6
+ MAJOR, MINOR, TEENY, PATCH = 1, 1, 0, nil
7
7
  # @return [String]
8
8
  STRING = [MAJOR, MINOR, TEENY, PATCH].compact.join('.')
9
9
  end
data/spec/logfmt_spec.rb CHANGED
@@ -2,6 +2,13 @@ require 'spec_helper'
2
2
  require 'moon-logfmt/logfmt'
3
3
 
4
4
  describe Moon::Logfmt do
5
+ context '.new' do
6
+ it 'creates a new Logger instance' do
7
+ logger = described_class.new
8
+ expect(logger).to be_instance_of(Moon::Logfmt::Logger)
9
+ end
10
+ end
11
+
5
12
  context '.escape_context_data' do
6
13
  it 'formats a Hash to a String' do
7
14
  actual = described_class.escape_context_data(msg: 'Hello World', nums: [1, 2, 3]).to_a
data/spec/logger_spec.rb CHANGED
@@ -32,40 +32,81 @@ describe Moon::Logfmt::Logger do
32
32
  end
33
33
  end
34
34
 
35
- context '#info' do
36
- it 'writes a basic message' do
37
- null_logger.info 'Test Test Test'
35
+ context 'std logger interface' do
36
+ context '#level=' do
37
+ it 'will accept symbols' do
38
+ null_logger.level = :debug
39
+ expect(null_logger.level).to eq(Moon::Logfmt::Severity::DEBUG)
40
+
41
+ null_logger.level = :info
42
+ expect(null_logger.level).to eq(Moon::Logfmt::Severity::INFO)
43
+
44
+ null_logger.level = :warn
45
+ expect(null_logger.level).to eq(Moon::Logfmt::Severity::WARN)
46
+
47
+ null_logger.level = :error
48
+ expect(null_logger.level).to eq(Moon::Logfmt::Severity::ERROR)
49
+
50
+ null_logger.level = :fatal
51
+ expect(null_logger.level).to eq(Moon::Logfmt::Severity::FATAL)
52
+
53
+ null_logger.level = :unknown
54
+ expect(null_logger.level).to eq(Moon::Logfmt::Severity::UNKNOWN)
55
+ end
56
+
57
+ it 'will accept strings' do
58
+ null_logger.level = 'debug'
59
+ expect(null_logger.level).to eq(Moon::Logfmt::Severity::DEBUG)
60
+ end
61
+
62
+ it 'will accept integers' do
63
+ null_logger.level = 0
64
+ expect(null_logger.level).to eq(Moon::Logfmt::Severity::DEBUG)
65
+
66
+ null_logger.level = 5
67
+ expect(null_logger.level).to eq(Moon::Logfmt::Severity::UNKNOWN)
68
+ end
69
+
70
+ it 'will fail given an invalid level' do
71
+ expect { null_logger.level = :something }.to raise_error(ArgumentError)
72
+ end
38
73
  end
39
- end
40
74
 
41
- context '#debug' do
42
- it 'writes a debug message' do
43
- null_logger.debug { 'Test Test Test' }
75
+ context '#info' do
76
+ it 'writes a basic message' do
77
+ null_logger.info 'Test Test Test'
78
+ end
44
79
  end
45
- end
46
80
 
47
- context '#warn' do
48
- it 'writes a warning message' do
49
- null_logger.warn { 'Test Test Test' }
81
+ context '#debug' do
82
+ it 'writes a debug message' do
83
+ null_logger.debug { 'Test Test Test' }
84
+ end
50
85
  end
51
- end
52
86
 
53
- context '#error' do
54
- it 'writes a warning message' do
55
- null_logger.error('testapp') { 'Test Test Test' }
87
+ context '#warn' do
88
+ it 'writes a warning message' do
89
+ null_logger.warn { 'Test Test Test' }
90
+ end
56
91
  end
57
- end
58
92
 
59
- context '#fatal' do
60
- it 'writes a fatal message' do
61
- null_logger.fatal 'AND I DIED'
93
+ context '#error' do
94
+ it 'writes a warning message' do
95
+ null_logger.error('testapp') { 'Test Test Test' }
96
+ end
97
+ end
98
+
99
+ context '#fatal' do
100
+ it 'writes a fatal message' do
101
+ null_logger.fatal 'AND I DIED'
102
+ end
62
103
  end
63
- end
64
104
 
65
- context '#warn' do
66
- it 'writes a unknown message' do
67
- # more like a spooky message
68
- null_logger.unknown { 'Spoooooky' }
105
+ context '#warn' do
106
+ it 'writes a unknown message' do
107
+ # more like a spooky message
108
+ null_logger.unknown { 'Spoooooky' }
109
+ end
69
110
  end
70
111
  end
71
112
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moon-logfmt
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blaž Hrastnik
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-03-23 00:00:00.000000000 Z
12
+ date: 2016-04-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: moon-null_io
@@ -142,7 +142,9 @@ files:
142
142
  - lib/moon-logfmt/logger.rb
143
143
  - lib/moon-logfmt/null_logger.rb
144
144
  - lib/moon-logfmt/pkg.yml
145
+ - lib/moon-logfmt/severity.rb
145
146
  - lib/moon-logfmt/stdlib_loggable.rb
147
+ - lib/moon-logfmt/utils.rb
146
148
  - lib/moon-logfmt/version.rb
147
149
  - spec/logfmt_spec.rb
148
150
  - spec/logger_spec.rb