l2meter 0.0.9 → 0.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: 99e89f47ef4f4e2a71ff7867df4e7fd25015c1b0
4
- data.tar.gz: 4ebb453038d24bb27de1aa5b2b1e9558a66760ba
3
+ metadata.gz: f503003e9477cf9593c912bbe56e0ec5732e5888
4
+ data.tar.gz: 5c0f2b7eeb06f8600b8a9204a397f46457dfea51
5
5
  SHA512:
6
- metadata.gz: 24e32b52f972db37ad2878521f340520ea9b7de85d57b0716081816f5c800461c60e2f89b5c79da9dcbedada0dc5dc114e62da22ae5afe5aac90949bbe61778e
7
- data.tar.gz: 587cc1f87cf361935a480c39f80f27d410bf0acd999e3b7f89f9f0b2c3f8bcedb458b7f30153f6ad7a562d35506508573d97585df17961bb6ac3c10af38b2770
6
+ metadata.gz: 70852339270abfbf8abcf19a5b287e92cb7244e496e5aad7a1bb64598feb9e12e4dc0e7bd888887eb3bf84ec7c1661f82ecf31602c472a4484f529259e87e8a1
7
+ data.tar.gz: cd3cb10da8ccb5c15a6576d81812689dc4c7d6a04781613caa9f2f647b13033f595e48b0639a1ff08dac37162d5e6b2d24c2acf5a7487a16ef9e12b618819fdf
@@ -6,10 +6,11 @@ module L2meter
6
6
  autoload :Configuration, "l2meter/configuration"
7
7
  autoload :Emitter, "l2meter/emitter"
8
8
  autoload :NullObject, "l2meter/null_object"
9
+ autoload :ThreadSafe, "l2meter/thread_safe"
9
10
 
10
- def build
11
- Emitter.new.tap do |emitter|
12
- yield emitter.configuration if block_given?
13
- end
11
+ def build(configuration: Configuration.new)
12
+ yield configuration if block_given?
13
+ emitter = Emitter.new(configuration: configuration.freeze)
14
+ ThreadSafe.new(emitter)
14
15
  end
15
16
  end
@@ -2,51 +2,52 @@ module L2meter
2
2
  class Configuration
3
3
  attr_writer :output
4
4
  attr_accessor :source, :prefix
5
- attr_reader :contexts
5
+ attr_reader :context, :key_formatter, :value_formatter, :output
6
6
 
7
- def initialize
8
- @contexts = []
7
+ DEFAULT_KEY_FORMATTER = ->(key) do
8
+ key.to_s.strip.downcase.gsub(/[^-a-z\d.#]+/, ?-)
9
9
  end
10
10
 
11
- def output
12
- @output ||= $stdout
11
+ DEFAULT_VALUE_FORMATTER = ->(value) do
12
+ value = value.to_s
13
+ value =~ /\s/ ? value.inspect : value
13
14
  end
14
15
 
15
- def key_formatter
16
- @key_formatter ||= ->(key) do
17
- key.to_s.strip.downcase.gsub(/[^-a-z\d.#]+/, ?-)
18
- end
16
+ private_constant :DEFAULT_KEY_FORMATTER, :DEFAULT_VALUE_FORMATTER
17
+
18
+ def initialize
19
+ @sort = false
20
+ @key_formatter = DEFAULT_KEY_FORMATTER
21
+ @value_formatter = DEFAULT_VALUE_FORMATTER
22
+ @output = $stdout
19
23
  end
20
24
 
21
25
  def format_keys(&block)
22
26
  @key_formatter = block
23
27
  end
24
28
 
25
- def value_formatter
26
- @value_formatter ||= ->(value) do
27
- value = value.to_s
28
- value =~ /\s/ ? value.inspect : value
29
- end
30
- end
31
-
32
29
  def format_values(&block)
33
30
  @value_formatter = block
34
31
  end
35
32
 
36
33
  def sort?
37
- defined?(@apply_sort) ? @apply_sort : false
34
+ @sort
38
35
  end
39
36
 
40
37
  def sort=(value)
41
- @apply_sort = !!value
38
+ @sort = !!value
42
39
  end
43
40
 
44
- def context(&block)
45
- @contexts = [block]
41
+ def context
42
+ if block_given?
43
+ @context = Proc.new
44
+ else
45
+ @context
46
+ end
46
47
  end
47
48
 
48
49
  def context=(block_or_value)
49
- @contexts = [block_or_value]
50
+ @context = block_or_value
50
51
  end
51
52
  end
52
53
  end
@@ -5,6 +5,8 @@ module L2meter
5
5
  def initialize(configuration: Configuration.new)
6
6
  @configuration = configuration
7
7
  @start_times = []
8
+ @contexts = []
9
+ @outputs = []
8
10
  end
9
11
 
10
12
  def log(*args)
@@ -26,11 +28,10 @@ module L2meter
26
28
  end
27
29
 
28
30
  def silence
29
- output = configuration.output
30
- configuration.output = NullObject.new
31
+ @outputs.push NullObject.new
31
32
  yield
32
33
  ensure
33
- configuration.output = output
34
+ @outputs.pop
34
35
  end
35
36
 
36
37
  def measure(metric, value, unit: nil)
@@ -50,10 +51,14 @@ module L2meter
50
51
  end
51
52
 
52
53
  def context(hash_or_proc)
53
- configuration_contexts.push hash_or_proc
54
+ @contexts.push hash_or_proc
54
55
  yield
55
56
  ensure
56
- configuration_contexts.pop
57
+ @contexts.pop
58
+ end
59
+
60
+ def clone
61
+ self.class.new(configuration: configuration)
57
62
  end
58
63
 
59
64
  private
@@ -81,12 +86,8 @@ module L2meter
81
86
  params.merge(elapsed: "%.4fs" % elapsed)
82
87
  end
83
88
 
84
- def configuration_contexts
85
- configuration.contexts
86
- end
87
-
88
89
  def current_context
89
- configuration_contexts.inject({}) do |result, c|
90
+ contexts_queue.inject({}) do |result, c|
90
91
  current = c.respond_to?(:call) ? c.call.to_h : c.clone
91
92
  result.merge(current)
92
93
  end.to_a.reverse.to_h
@@ -113,7 +114,7 @@ module L2meter
113
114
 
114
115
  tokens.sort! if configuration.sort?
115
116
 
116
- configuration.output.print tokens.join(" ") + "\n"
117
+ output_queue.last.print tokens.join(" ") + "\n"
117
118
  end
118
119
 
119
120
  def log_with_prefix(method, key, value, unit: nil)
@@ -150,5 +151,13 @@ module L2meter
150
151
  ensure
151
152
  return [ result, caught_exception, Time.now - time_at_start ]
152
153
  end
154
+
155
+ def contexts_queue
156
+ [ configuration.context, *@contexts ].compact
157
+ end
158
+
159
+ def output_queue
160
+ [ configuration.output, *@outputs ].compact
161
+ end
153
162
  end
154
163
  end
@@ -0,0 +1,41 @@
1
+ module L2meter
2
+ # This class is a wrapper around Emitter that makes sure that we have a
3
+ # completely separate clone of Emitter per thread running. It doesn't truly
4
+ # make Emitter thread-safe, it makes sure that you don't access the same
5
+ # instance of emitter from different threads.
6
+ class ThreadSafe
7
+ extend Forwardable
8
+
9
+ EMITTER_METHODS = %i[
10
+ configuration
11
+ context
12
+ count
13
+ log
14
+ measure
15
+ sample
16
+ silence
17
+ unique
18
+ with_elapsed
19
+ ]
20
+
21
+ private_constant :EMITTER_METHODS
22
+
23
+ def initialize(emitter)
24
+ @emitter = emitter.freeze
25
+ end
26
+
27
+ def_delegators :current_emitter, *EMITTER_METHODS
28
+
29
+ private
30
+
31
+ attr_reader :emitter
32
+
33
+ def current_emitter
34
+ Thread.current[thread_key] ||= emitter.clone
35
+ end
36
+
37
+ def thread_key
38
+ @thread_key ||= "_l2meter_emitter_#{emitter.object_id}".freeze
39
+ end
40
+ end
41
+ end
@@ -1,3 +1,3 @@
1
1
  module L2meter
2
- VERSION = "0.0.9".freeze
2
+ VERSION = "0.1.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: l2meter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pavel Pravosud
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-23 00:00:00.000000000 Z
11
+ date: 2015-10-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -23,6 +23,7 @@ files:
23
23
  - lib/l2meter/configuration.rb
24
24
  - lib/l2meter/emitter.rb
25
25
  - lib/l2meter/null_object.rb
26
+ - lib/l2meter/thread_safe.rb
26
27
  - lib/l2meter/version.rb
27
28
  homepage: https://github.com/heroku/l2meter
28
29
  licenses:
@@ -44,7 +45,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
44
45
  version: '0'
45
46
  requirements: []
46
47
  rubyforge_project:
47
- rubygems_version: 2.4.8
48
+ rubygems_version: 2.4.5.1
48
49
  signing_key:
49
50
  specification_version: 4
50
51
  summary: L2met friendly log formatter