formatted-metrics 1.2.0 → 1.3.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: c1b6315788115f3dec6f76777cbd7cc6bb4fb5c5
4
- data.tar.gz: fc2d26549dfbfc21f2df6f33342304a888e21ae6
3
+ metadata.gz: f61de2711adaea249e6fc4f6eb53d9899ed805ef
4
+ data.tar.gz: 5292dea3deae43f089de2eeb20d0512acbd3aebb
5
5
  SHA512:
6
- metadata.gz: a9d1a8c00d92e3354ba7ac7fba98ae2648ef789853d88b9e5e87b4b8a9dff16cc2774a74e4791fb5730306a70b8f062d6280f5ad0c2dcf9e967b2733eba748fa
7
- data.tar.gz: e1e1b00fbe7724f47a3d492ffd7ad0793d06bec3435197bfc6ad6e923fcdd263e3cb466d3bc39ca7bc0c1331d5298fb9d772e293d5d1859d9b65e597ae22563c
6
+ metadata.gz: 7c34b9936b1ae2ea1c6504e85432c9c0a7a63384cb063799e1be98f94702c652dec05d993c432152f47f9132d19fc6cc0cb86e945041dc1d4ecc2650d395a931
7
+ data.tar.gz: 330e3349dbc4848df534f4a9d85bff0ca0a187897cda130500d9bf89f9dcf631cd595634a39c484ed0e46ac3dbe6869112af4ca7617fe78cf9909d2b830d7634
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/remind101/formatted-metrics.png)](https://travis-ci.org/remind101/formatted-metrics) [![Code Climate](https://codeclimate.com/github/remind101/formatted-metrics.png)](https://codeclimate.com/github/remind101/formatted-metrics)
4
4
 
5
- Easily produce metrics that can be consumed by [l2met](https://github.com/ryandotsmith/l2met).
5
+ Easily produce metrics that can be consumed by [l2met](https://github.com/ryandotsmith/l2met) or statsd.
6
6
 
7
7
  ## Installation
8
8
 
data/lib/metrics.rb CHANGED
@@ -10,9 +10,10 @@ module Metrics
10
10
  autoload :Grouping, 'metrics/grouping'
11
11
  autoload :Handler, 'metrics/handler'
12
12
 
13
- module Formatters
14
- autoload :Base, 'metrics/formatters/base'
15
- autoload :L2Met, 'metrics/formatters/l2met'
13
+ module Drivers
14
+ autoload :Base, 'metrics/drivers/base'
15
+ autoload :L2Met, 'metrics/drivers/l2met'
16
+ autoload :Statsd, 'metrics/drivers/statsd'
16
17
  end
17
18
 
18
19
  module Helpers
@@ -65,8 +66,9 @@ module Metrics
65
66
  # end
66
67
  #
67
68
  # Returns nothing.
68
- def group(*args, &block)
69
- Handler.handle(Grouping.instrument(*args, &block))
69
+ def group(namespace = nil, options = {}, &block)
70
+ instrumenters = Grouping.instrument(namespace, &block)
71
+ Handler.handle(*instrumenters)
70
72
  end
71
73
 
72
74
  def subscribe
@@ -2,15 +2,24 @@ require 'logger'
2
2
 
3
3
  module Metrics
4
4
  class Configuration
5
+ # The driver to use.
6
+ #
7
+ # Drivers are objects that implement the following method:
8
+ #
9
+ # driver.write(*instrumenters) # => instrumenters written
10
+ #
11
+ # Defaults to Metrics::Drivers::L2Met.new(logger, source).
12
+ attr_accessor :driver
13
+
5
14
  # The stream source to write to. Defaults to STDOUT.
6
15
  attr_accessor :logger
7
16
 
8
17
  # The base source for all metrics.
9
18
  attr_accessor :source
10
19
 
11
- # The formatter to use. Only needs to be a class that responds to `to_s`.
12
- # Defaults to Metrics::Formatter.
13
- attr_accessor :formatter
20
+ def driver
21
+ @driver ||= Metrics::Drivers::L2Met.new(logger, source)
22
+ end
14
23
 
15
24
  def logger
16
25
  @logger ||= Logger.new(STDOUT).tap { |log| log.formatter = log_formatter }
@@ -24,9 +33,5 @@ module Metrics
24
33
  return @source if defined? @source
25
34
  @source = ENV['METRICS_SOURCE'] || ENV['APP_NAME'] || `hostname`.chomp
26
35
  end
27
-
28
- def formatter
29
- @formatter ||= Metrics::Formatters::L2Met
30
- end
31
36
  end
32
37
  end
@@ -1,11 +1,24 @@
1
- module Metrics::Formatters
1
+ module Metrics::Drivers
2
2
  PRECISION = 3.freeze
3
3
 
4
- class L2Met < Base
4
+ class L2Met
5
+ attr_reader :logger, :source_prefix
6
+ def initialize(logger, source_prefix)
7
+ @logger = logger
8
+ @source_prefix = source_prefix
9
+ end
10
+
11
+ def write(*instrumenters)
12
+ lines(instrumenters).each do |line|
13
+ logger.info line
14
+ end
15
+ instrumenters
16
+ end
17
+
5
18
  # Example
6
19
  # source=web.2 sample#load_avg_1m=0.31 sample#load_avg_5m=0.10 sample#load_avg_15m=0.05
7
- def lines
8
- groups.map do |source, instrumenters|
20
+ def lines(instrumenters)
21
+ groups(instrumenters).map do |source, instrumenters|
9
22
  measurements = instrumenters.map { |instrumenter| measurement(instrumenter) }
10
23
  Lines.new(full_source(source), measurements).lines
11
24
  end.flatten
@@ -15,12 +28,12 @@ module Metrics::Formatters
15
28
 
16
29
  # Internal: We group the metrics by their source so that we can separate
17
30
  # the lines.
18
- def groups
31
+ def groups(instrumenters)
19
32
  instrumenters.group_by(&:source)
20
33
  end
21
34
 
22
35
  def full_source(source=nil)
23
- [configuration.source, source].reject { |s| blank?(s) }.join('.')
36
+ [source_prefix, source].reject { |s| blank?(s) }.join('.')
24
37
  end
25
38
 
26
39
  def measurement(instrumenter)
@@ -0,0 +1,46 @@
1
+ module Metrics::Drivers
2
+ class Statsd
3
+ attr_reader :client, :template, :source_prefix
4
+
5
+ def initialize(client, template, source_prefix)
6
+ @client = client # The statsd client
7
+ @template = template # The template for the metric name
8
+ @source_prefix = source_prefix # Source prefix
9
+ end
10
+
11
+ def write(*instrumenters)
12
+ instrumenters.each do |instrumenter|
13
+ emit(instrumenter)
14
+ end
15
+ instrumenters
16
+ end
17
+
18
+ def emit(instrumenter)
19
+ name = name_for(instrumenter)
20
+ value = instrumenter.value
21
+
22
+ case instrumenter.type
23
+ when 'measure', 'sample'
24
+ if instrumenter.units == 'ms'
25
+ client.timing(name, value)
26
+ else
27
+ client.gauge(name, value)
28
+ end
29
+ when 'count'
30
+ client.count(name, value)
31
+ else
32
+ raise ArgumentError.new("unsupported instrumenter type for statsd: '%s'" % instrumenter.type)
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def name_for(instrumenter)
39
+ template.gsub('{{name}}', instrumenter.metric).gsub('{{source}}', source(instrumenter))
40
+ end
41
+
42
+ def source(instrumenter)
43
+ [source_prefix, instrumenter.source].compact.join('.')
44
+ end
45
+ end
46
+ end
@@ -3,9 +3,9 @@ module Metrics
3
3
  # instruments to output on a single line.
4
4
  class Grouping
5
5
  attr_reader :namespace, :instrumenters, :options
6
-
7
- def self.instrument(*args, &block)
8
- new(*args, &block).instrumenters
6
+
7
+ def self.instrument(namespace = nil, options = {}, &block)
8
+ new(namespace, options, &block).instrumenters
9
9
  end
10
10
 
11
11
  def initialize(namespace = nil, options = {}, &block)
@@ -1,7 +1,7 @@
1
1
  module Metrics
2
2
 
3
3
  # Internal: Responsible for taking a list or an Array of
4
- # Metrics::Instrumenters and passing them to the formatter.
4
+ # Metrics::Instrumenters and passing them to the driver.
5
5
  class Handler
6
6
  attr_reader :instrumenters
7
7
 
@@ -10,34 +10,27 @@ module Metrics
10
10
  end
11
11
 
12
12
  def initialize(*instrumenters)
13
- @instrumenters = instrumenters.flatten
13
+ @instrumenters = instrumenters
14
14
  end
15
15
 
16
- # Public: Writes all of the instrumenters to STDOUT using the formatter.
16
+ # Public: Writes all of the instrumenters to the driver.
17
17
  #
18
- # Returns an Array of Metrics::Instrumenters that were written to STDOUT.
18
+ # Returns an Array of Metrics::Instrumenters that were written.
19
19
  def handle
20
- write instrumenters
21
- result
20
+ return write(*instrumenters)
22
21
  end
23
22
 
24
23
  private
24
+ def write(*instrumenters)
25
+ driver.write(*instrumenters)
26
+ end
25
27
 
26
- def result
27
- instrumenters.last.result
28
+ def driver
29
+ configuration.driver
28
30
  end
29
31
 
30
32
  def configuration
31
33
  Metrics.configuration
32
34
  end
33
-
34
- def write(*args, &block)
35
- formatter.write(*args, &block)
36
- end
37
-
38
- def formatter
39
- configuration.formatter
40
- end
41
-
42
35
  end
43
36
  end
@@ -25,8 +25,8 @@ module Metrics
25
25
  Metrics.instrument(*args, &block)
26
26
  end
27
27
 
28
- def group(*args, &block)
29
- Metrics.group(*args, &block)
28
+ def group(namespace, options, &block)
29
+ Metrics.group(namespace, options, &block)
30
30
  end
31
31
  end
32
32
  end
@@ -1,3 +1,3 @@
1
1
  module FormattedMetrics
2
- VERSION = '1.2.0'
2
+ VERSION = '1.3.0'
3
3
  end
@@ -2,6 +2,7 @@ require 'spec_helper'
2
2
  require 'faraday/instrumentation'
3
3
 
4
4
  describe Faraday::Instrumentation do
5
+
5
6
  let(:response) { double('response', status: 200) }
6
7
  let(:app) { double('app', call: response) }
7
8
  let(:middleware) { described_class.new(app) }
@@ -1,19 +1,15 @@
1
1
  require 'spec_helper'
2
2
  require 'securerandom'
3
3
 
4
- describe Metrics::Formatters::L2Met do
5
- let(:formatter) { described_class.new *instrumenters }
6
-
7
- before do
8
- Metrics.configuration.stub source: 'app'
9
- end
4
+ describe Metrics::Drivers::L2Met do
5
+ let(:driver) { described_class.new(Logger.new('/dev/null'), 'app') }
10
6
 
11
7
  def instrumenter(values)
12
8
  double Metrics::Instrumenter, { source: nil, type: 'measure' }.merge(values)
13
9
  end
14
10
 
15
11
  describe '.lines' do
16
- subject(:lines) { formatter.lines }
12
+ subject(:lines) { driver.lines(instrumenters) }
17
13
 
18
14
  context 'with a single instrumenter' do
19
15
  let(:instrumenters) { [ instrumenter(metric: 'rack.request.time', value: 10.3333, units: 'ms', type: 'sample') ] }
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+ require 'securerandom'
3
+
4
+ describe Metrics::Drivers::Statsd do
5
+ let(:client) { double }
6
+
7
+ def instrumenter(*args)
8
+ Metrics::Instrumenter.new(*args)
9
+ end
10
+
11
+ def write(*instrumenters)
12
+ described_class.new(client, '{{name}}.source__{{source}}__', 'app').write(*instrumenters)
13
+ end
14
+
15
+ describe '.write' do
16
+ context 'metric types' do
17
+ it 'should call statsd.timing' do
18
+ client.should_receive(:timing).with('rack.request.time.source__app__', 10.3333)
19
+ write(instrumenter('rack.request.time', 10.3333, units: 'ms', type: 'sample'))
20
+ end
21
+
22
+ it 'should call statsd.gauge' do
23
+ client.should_receive(:gauge).with('rack.request.size.source__app__', 10)
24
+ write(instrumenter('rack.request.size', 10, type: 'measure'))
25
+ end
26
+
27
+ it 'should call statsd.count' do
28
+ client.should_receive(:count).with('foo.bar.source__app__', 10)
29
+ write(instrumenter('foo.bar', 10, type: 'count'))
30
+ end
31
+ end
32
+
33
+ context 'metric sources' do
34
+ it 'should insert the globally configured source' do
35
+ client.should_receive(:count).with('foo.bar.source__app__', 10)
36
+ write(instrumenter('foo.bar', 10, type: 'count'))
37
+ end
38
+
39
+ it 'should append the instrumenter source' do
40
+ client.should_receive(:count).with('foo.bar.source__app.us__', 10)
41
+ write(instrumenter('foo.bar', 10, type: 'count', source: 'us'))
42
+ end
43
+ end
44
+ end
45
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,2 +1,4 @@
1
1
  require 'bundler/setup'
2
2
  Bundler.require
3
+
4
+ Metrics.configuration.driver = Metrics::Drivers::L2Met.new(Logger.new('/dev/null'), 'app')
metadata CHANGED
@@ -1,69 +1,69 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: formatted-metrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric J. Holmes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-09 00:00:00.000000000 Z
11
+ date: 2015-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '2.14'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '2.14'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: faraday
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: 0.9.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 0.9.0
69
69
  description: Easily output formatted metrics to stdout
@@ -73,9 +73,9 @@ executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
- - .gitignore
77
- - .rspec
78
- - .travis.yml
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".travis.yml"
79
79
  - Gemfile
80
80
  - LICENSE
81
81
  - README.md
@@ -86,8 +86,8 @@ files:
86
86
  - lib/metrics.rb
87
87
  - lib/metrics/configuration.rb
88
88
  - lib/metrics/core_ext.rb
89
- - lib/metrics/formatters/base.rb
90
- - lib/metrics/formatters/l2met.rb
89
+ - lib/metrics/drivers/l2met.rb
90
+ - lib/metrics/drivers/statsd.rb
91
91
  - lib/metrics/grouping.rb
92
92
  - lib/metrics/handler.rb
93
93
  - lib/metrics/instrumentable.rb
@@ -98,7 +98,8 @@ files:
98
98
  - lib/rack/instrumentation.rb
99
99
  - lib/sidekiq/middleware/server/instrumentation.rb
100
100
  - spec/faraday/instrumentation_spec.rb
101
- - spec/metrics/formatters/l2met_spec.rb
101
+ - spec/metrics/drivers/l2met_spec.rb
102
+ - spec/metrics/drivers/statsd_spec.rb
102
103
  - spec/metrics/grouping_spec.rb
103
104
  - spec/metrics/instrumentable_spec.rb
104
105
  - spec/metrics/instrumenter_spec.rb
@@ -115,26 +116,28 @@ require_paths:
115
116
  - lib
116
117
  required_ruby_version: !ruby/object:Gem::Requirement
117
118
  requirements:
118
- - - '>='
119
+ - - ">="
119
120
  - !ruby/object:Gem::Version
120
121
  version: '0'
121
122
  required_rubygems_version: !ruby/object:Gem::Requirement
122
123
  requirements:
123
- - - '>='
124
+ - - ">="
124
125
  - !ruby/object:Gem::Version
125
126
  version: '0'
126
127
  requirements: []
127
128
  rubyforge_project:
128
- rubygems_version: 2.0.14
129
+ rubygems_version: 2.4.5
129
130
  signing_key:
130
131
  specification_version: 4
131
132
  summary: Easily output formatted metrics to stdout
132
133
  test_files:
133
134
  - spec/faraday/instrumentation_spec.rb
134
- - spec/metrics/formatters/l2met_spec.rb
135
+ - spec/metrics/drivers/l2met_spec.rb
136
+ - spec/metrics/drivers/statsd_spec.rb
135
137
  - spec/metrics/grouping_spec.rb
136
138
  - spec/metrics/instrumentable_spec.rb
137
139
  - spec/metrics/instrumenter_spec.rb
138
140
  - spec/metrics_spec.rb
139
141
  - spec/rack/instrumentation_spec.rb
140
142
  - spec/spec_helper.rb
143
+ has_rdoc:
@@ -1,31 +0,0 @@
1
- module Metrics::Formatters
2
- class Base
3
- attr_reader :instrumenters
4
-
5
- def self.write(*instrumenters)
6
- new(*instrumenters).write
7
- end
8
-
9
- def initialize(*instrumenters)
10
- @instrumenters = instrumenters.flatten
11
- end
12
-
13
- def write
14
- lines.each do |line|
15
- configuration.logger.info line
16
- end
17
- instrumenters
18
- end
19
-
20
- def lines
21
- raise NotImplementedError
22
- end
23
-
24
- private
25
-
26
- def configuration
27
- Metrics.configuration
28
- end
29
-
30
- end
31
- end