perfume 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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