formatted-metrics 1.2.0 → 1.3.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: 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