perfume 0.1.0 → 0.2.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: cdbf43b151d7f376a9858e70e92c2a86dc815a73
4
- data.tar.gz: 44e31ee400a397f536e36ee94eea30f7abe6fc06
3
+ metadata.gz: 454092b73948923a75a389d4a257cd138ae50bf8
4
+ data.tar.gz: 6b5fa43f55f038d41d5335eeb199cc986f39f59b
5
5
  SHA512:
6
- metadata.gz: 1506aa517bcc89219aabaa16765d51f140fc5d841625f3f8f8a4a7813485f76057fc83e8608bfb8c316c039224ad474bac11efb4286703a200acb98e77a69a07
7
- data.tar.gz: cf04e57c3e583617460867bae3d1b45df456daedac7e4206c576c34ee2ed829129bdf5204b24de088bf739a30e2a444af397db8eca361b7c9f011885c02e9e67
6
+ metadata.gz: a8deebaf11ab4fae66403efb78f2978e5fa928aad29cf75040ff551832a4a44eab95945dde167ab60ec69fccf28884862edf5728f81caa64a1625ea8ca1ccd61
7
+ data.tar.gz: b6cd61497493f609e3a23c348116e4e97a1dc5e53bbe5b62a108985171a157eb18d33c75d8697e570261eab52cf18c1831308555dd343499c6c051f0567c6781
data/CHANGELOG.md CHANGED
@@ -4,7 +4,11 @@ This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
- ...
7
+ ## [0.2.0]
8
+
9
+ ### Added
10
+
11
+ - Logging with new Gallus library bundled.
8
12
 
9
13
  ## [0.1.0]
10
14
 
data/README.md CHANGED
@@ -20,7 +20,7 @@ shorthands to deal with common problems. At the moment it includes the following
20
20
  Add this line to your application's Gemfile:
21
21
 
22
22
  ```ruby
23
- gem 'perfume', '0.1.0'
23
+ gem 'perfume', '0.2.0'
24
24
  ```
25
25
 
26
26
  And then execute:
@@ -29,7 +29,7 @@ And then execute:
29
29
 
30
30
  Or install it yourself as:
31
31
 
32
- $ gem install perfume --version 0.1.0
32
+ $ gem install perfume --version 0.2.0
33
33
 
34
34
  ## Usage
35
35
 
@@ -0,0 +1,10 @@
1
+ module Gallus
2
+ Event = Struct.new(:logger, :level, :message, :payload) do
3
+ attr_reader :recorded_at
4
+
5
+ def initialize(*)
6
+ super
7
+ @recorded_at = Time.now.utc
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module Gallus
2
+ module Format
3
+ class SimpleConsole
4
+ def call(event)
5
+ parts = [ [ event.message, event.payload ].compact.join('; ') ]
6
+ parts.unshift("#{event.level.name}:") unless event.level == Level::INFO
7
+ parts.compact.join(' ')
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module Gallus
2
+ module Format
3
+ class SimpleLog
4
+ def call(event)
5
+ message = [ event.message, event.payload ].compact.join('; ')
6
+ "#{event.level.to_s[0]} @ #{event.recorded_at.iso8601} $ #{event.logger} > #{message}"
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,42 @@
1
+ module Gallus
2
+ class Level
3
+ include Comparable
4
+
5
+ def self.all
6
+ @all ||= []
7
+ end
8
+
9
+ def self.each(&block)
10
+ self.all.each(&block)
11
+ end
12
+
13
+ def self.[](name)
14
+ const_get(name.to_s)
15
+ end
16
+
17
+ attr_reader :name, :id
18
+
19
+ def initialize(name, id)
20
+ @name, @id = name.to_s, id
21
+
22
+ self.class.const_set(@name, self)
23
+ self.class.all << self
24
+ end
25
+
26
+ def <=>(other)
27
+ self.id <=> other.id
28
+ rescue => err
29
+ return nil
30
+ end
31
+
32
+ def to_s
33
+ name
34
+ end
35
+
36
+ new :TRACE, 1
37
+ new :DEBUG, 2
38
+ new :INFO, 3
39
+ new :WARN, 4
40
+ new :ERROR, 5
41
+ end
42
+ end
data/lib/gallus/log.rb ADDED
@@ -0,0 +1,98 @@
1
+ module Gallus
2
+ class Log
3
+ @@global_context_mutex = Mutex.new
4
+ @@global_context = {}
5
+
6
+ class << self
7
+ def configure(name = '', &block)
8
+ Repository.get_or_create_logger(name, &block)
9
+ end
10
+
11
+ def [](name)
12
+ configure(name)
13
+ end
14
+
15
+ def delete(name)
16
+ Repository.delete_with_children(name)
17
+ end
18
+
19
+ def define_log_methods!(log_level)
20
+ Level.each do |level|
21
+ method_name = level.name.downcase
22
+ remove_method(method_name) if method_defined?(method_name)
23
+
24
+ if level >= log_level
25
+ define_method(method_name) do |message, payload = {}|
26
+ log(level, message, payload)
27
+ end
28
+ else
29
+ define_method(method_name) do |message, payload = {}|
30
+ # supressed...
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def global_context
37
+ @@global_context_mutex.synchronize { yield @@global_context }
38
+ end
39
+
40
+ def current_thread_context
41
+ yield (Thread.current[:log_context] ||= {})
42
+ end
43
+
44
+ def root
45
+ @@root
46
+ end
47
+ end
48
+
49
+ attr_accessor :name, :level, :output, :serialization
50
+
51
+ def initialize(parent, name, &block)
52
+ @parent, @name = parent, name.to_s
53
+
54
+ if @parent
55
+ self.level = @parent.level
56
+ self.output = @parent.output.dup
57
+ self.serialization = @parent.serialization
58
+ end
59
+
60
+ yield self if block_given?
61
+ end
62
+
63
+ def level=(level)
64
+ level = level.is_a?(Level) ? level : Level[level.to_s]
65
+ return if @level == level
66
+ self.class.class_eval { define_log_methods!(level) }
67
+ @level = level
68
+ end
69
+
70
+ def context
71
+ @context ||= {}
72
+ end
73
+
74
+ private
75
+
76
+ def merged_context
77
+ {}.tap do |merged|
78
+ self.class.global_context { |ctx| merged.merge!(ctx) }
79
+ self.class.current_thread_context { |ctx| merged.merge!(ctx) }
80
+ merged.merge!(context)
81
+ end
82
+ end
83
+
84
+ def log(level, message, payload = {}, &block)
85
+ payload = merged_context.merge(payload)
86
+ serialized_payload = serialization.call(Payload.new(payload).to_h)
87
+ event = Event.new(@name, level, message.to_s, serialized_payload.empty? ? nil : serialized_payload)
88
+ output.each { |out| out.call(event) }
89
+ end
90
+
91
+ @@root = Log.configure do |log|
92
+ log.name = 'root'
93
+ log.level = Level::INFO
94
+ log.output = []
95
+ log.serialization = Serialization::Inspect.new
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,8 @@
1
+ module Gallus
2
+ module Output
3
+ class Null
4
+ def call
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module Gallus
2
+ module Output
3
+ class Stderr
4
+ def initialize(format)
5
+ super(STDERR, format)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Gallus
2
+ module Output
3
+ class Stdout
4
+ def initialize(format)
5
+ super(STDOUT, format)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,20 @@
1
+ module Gallus
2
+ module Output
3
+ class Stream
4
+ def initialize(stream, format)
5
+ @mutex = Mutex.new
6
+ @stream, @format = stream, format
7
+ end
8
+
9
+ def call(event)
10
+ @mutex.synchronize { call!(event) }
11
+ end
12
+
13
+ protected
14
+
15
+ def call!(event)
16
+ @stream.write(@format.call(event) + "\n")
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ module Gallus
2
+ class Payload
3
+ def initialize(payload)
4
+ @h = payload.inject({}) do |res,(k,v)|
5
+ res[k.to_s] = v.is_a?(Proc) ? v.call : v
6
+ res
7
+ end
8
+ end
9
+
10
+ def to_h
11
+ @h
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,42 @@
1
+ module Gallus
2
+ class Repository
3
+ PARENT_DELIMITER = '::'
4
+
5
+ @mutex = Mutex.new
6
+
7
+ def self.all
8
+ @all ||= {}
9
+ end
10
+
11
+ def self.find_parent(name)
12
+ parent, name = nil, name.dup
13
+
14
+ while parent.nil?
15
+ name = name.split(PARENT_DELIMITER)[0..-2].join(PARENT_DELIMITER)
16
+ parent = all[name]
17
+ break if name.empty?
18
+ end
19
+
20
+ parent
21
+ end
22
+
23
+ def self.delete_with_children(name)
24
+ @mutex.synchronize do
25
+ all.keys.each { |k| all.delete(k) if k.start_with?(name + PARENT_DELIMITER) }
26
+ all.delete(name)
27
+ end
28
+ end
29
+
30
+ def self.get_or_create_logger(name, &block)
31
+ name, log = name.to_s, nil
32
+
33
+ @mutex.synchronize do
34
+ unless log = all[name]
35
+ all[name] = (log = Class.new(Log).new(find_parent(name), name, &block))
36
+ end
37
+ end
38
+
39
+ log
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,11 @@
1
+ module Gallus
2
+ module Serialization
3
+ class JSON
4
+ def call(payload)
5
+ require 'json'
6
+ payload ||= {}
7
+ payload.to_json
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module Gallus
2
+ module Serialization
3
+ class Inspect
4
+ def call(payload)
5
+ payload ||= {}
6
+ payload.map { |k,v| "#{k}=#{v.inspect}" }.join(" ")
7
+ end
8
+ end
9
+ end
10
+ end
data/lib/gallus.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'date'
2
+ require 'thread'
3
+
4
+ module Gallus
5
+ require 'gallus/format/simple_console'
6
+ require 'gallus/format/simple_log'
7
+ require 'gallus/output/null'
8
+ require 'gallus/output/stream'
9
+ require 'gallus/output/stdout'
10
+ require 'gallus/output/stderr'
11
+ require 'gallus/serialization/inspect'
12
+ require 'gallus/serialization/json'
13
+ require 'gallus/level'
14
+ require 'gallus/payload'
15
+ require 'gallus/event'
16
+ require 'gallus/repository'
17
+ require 'gallus/log'
18
+ end
@@ -5,13 +5,15 @@ module Perfume
5
5
  class Log4rAdapter
6
6
  class Event
7
7
  def initialize(message, payload)
8
- @message, @payload = message, payload || {}
9
- @payload_formatted = @payload.map { |k,v| "#{k}=#{v.inspect}" }.join(" ")
10
- @s = [ @message, @payload_formatted.empty? ? nil : @payload_formatted].compact.join("; ")
8
+ @proc = -> {
9
+ payload ||= {}
10
+ payload_formatted = payload.map { |k,v| "#{k}=#{v.is_a?(Proc) ? v.call.inspect : v.inspect}" }.join(" ")
11
+ str = [ message, payload_formatted.empty? ? nil : payload_formatted].compact.join("; ")
12
+ }
11
13
  end
12
14
 
13
- def to_s
14
- @s
15
+ def to_proc
16
+ @proc
15
17
  end
16
18
  end
17
19
 
@@ -19,13 +21,15 @@ module Perfume
19
21
  @log = log
20
22
  end
21
23
 
22
- def method_missing(method, *args, &block)
23
- @log.send(method, *args, &block)
24
+ %w[level level= add name].each do |method|
25
+ define_method(method) do |*args, &block|
26
+ @log.send(method, *args, &block)
27
+ end
24
28
  end
25
29
 
26
30
  %w[debug info warn error fatal].each do |level|
27
31
  define_method(level) do |obj_or_msg, payload=nil|
28
- @log.send(level, obj_or_msg.is_a?(String) ? Event.new(obj_or_msg, payload).to_s : obj_or_msg)
32
+ @log.send(level, obj_or_msg.is_a?(String) ? Event.new(obj_or_msg, payload).to_proc : obj_or_msg)
29
33
  end
30
34
  end
31
35
  end
@@ -11,7 +11,7 @@ module Perfume
11
11
  # outputters, formatters, log level, etc.
12
12
  module PackageLogger
13
13
  def self.included(klass)
14
- klass.const_set(:LOGGER, Logging::Log4rAdapter.new(Log4r::Logger.new(klass.name)))
14
+ klass.const_set(:LOGGER, Gallus::Log.configure(klass.name))
15
15
  klass.extend(ClassMethods)
16
16
  end
17
17
 
@@ -19,7 +19,7 @@ module Perfume
19
19
 
20
20
  module ClassMethods
21
21
  def log
22
- @log ||= Log4rAdapter.new(Log4r::Logger.new(self.name))
22
+ @log ||= Gallus::Log.configure(self.name)
23
23
  end
24
24
  end
25
25
  end
@@ -1,3 +1,3 @@
1
1
  module Perfume
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: perfume
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - jobandtalent
@@ -141,6 +141,20 @@ files:
141
141
  - bin/console
142
142
  - bin/setup
143
143
  - docker-compose.yml
144
+ - lib/gallus.rb
145
+ - lib/gallus/event.rb
146
+ - lib/gallus/format/simple_console.rb
147
+ - lib/gallus/format/simple_log.rb
148
+ - lib/gallus/level.rb
149
+ - lib/gallus/log.rb
150
+ - lib/gallus/output/null.rb
151
+ - lib/gallus/output/stderr.rb
152
+ - lib/gallus/output/stdout.rb
153
+ - lib/gallus/output/stream.rb
154
+ - lib/gallus/payload.rb
155
+ - lib/gallus/repository.rb
156
+ - lib/gallus/serialization/inspect.rb
157
+ - lib/gallus/serialization/json.rb
144
158
  - lib/perfume.rb
145
159
  - lib/perfume/all.rb
146
160
  - lib/perfume/console.rb