meter 0.0.10 → 0.1.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: 4b51363f08ba9926173d4fc3ea17658953d17621
4
- data.tar.gz: df0465fd8394b30a9723c8958d171a9976ea1121
3
+ metadata.gz: 1fea98858b4bdf1096610854053ff2f28532ed90
4
+ data.tar.gz: b24dab519654d590152ee94dc88f60e671575ffa
5
5
  SHA512:
6
- metadata.gz: 2bfb300157cea6663debde191fa1ad5e460329764422f6608da0f3e12de7195273fa7a7a8b9848610fc0d6fc8ac9914859caa2b3e4a63ac03415195020d27812
7
- data.tar.gz: 94945415dfd1ad008a7d89a1ea5b53ff29316333feabccc4211d1f4292d5f2ff8bcb2d1145f51d5ad074119e5ae48318173308bed89dbe50f5b50af72d498eb5
6
+ metadata.gz: 842d05e7398a50393fa7c3ee6252ef07e08ef37eda3757129d32d4b6972ffe4486b362dd881483e04d6728075d00d28a441d3d69fa1ff12cbc4401861e9af5e1
7
+ data.tar.gz: 2c57251afb124930882c5d546bb9916354a289cd91ed9499ccc10f27933bdb1914ac5b17f3d3b5a01788f56af9b031a2dfd8f154c45232be1126b6ade2a725bb
data/lib/meter/backend.rb CHANGED
@@ -1,216 +1,56 @@
1
+ require 'json'
1
2
  require 'socket'
2
- require 'pathname'
3
-
4
-
5
- # Copy and paste from https://github.com/DataDog/dogstatsd-ruby/blob/master/lib/statsd.rb
6
- # Changes:
7
- # - The class is renamed to "Backend"
8
- # - the logger class method points to meter's logger
9
3
 
10
4
  module Meter
11
- # = Statsd: A DogStatsd client (https://www.datadoghq.com)
12
- #
13
- # @example Set up a global Statsd client for a server on localhost:8125
14
- # require 'statsd'
15
- # $statsd = Statsd.new 'localhost', 8125
16
- # @example Send some stats
17
- # $statsd.increment 'page.views'
18
- # $statsd.timing 'page.load', 320
19
- # $statsd.gauge 'users.online', 100
20
- # @example Use {#time} to time the execution of a block
21
- # $statsd.time('account.activate') { @account.activate! }
22
- # @example Create a namespaced statsd client and increment 'account.activate'
23
- # statsd = Statsd.new('localhost').tap{|sd| sd.namespace = 'account'}
24
- # statsd.increment 'activate'
25
5
  class Backend
26
- # A namespace to prepend to all statsd calls.
27
- attr_reader :namespace
28
-
29
- # A String describing the environment, useful to distinguish staging/production
30
- attr_reader :environment
31
-
32
- attr_reader :log_dir
33
-
34
- # StatsD host. Defaults to 127.0.0.1.
35
- attr_accessor :host
36
6
 
37
- # StatsD port. Defaults to 8125.
38
- attr_accessor :port
39
-
40
- def self.logger
41
- Meter.config.logger
42
- end
43
-
44
- # Return the current version of the library.
45
- def self.VERSION
46
- "1.1.0"
47
- end
7
+ attr_reader :host, :port
48
8
 
49
- # @param [String] host your statsd host
50
- # @param [Integer] port your statsd port
51
9
  def initialize(host = '127.0.0.1', port = 8125)
52
- self.host, self.port = host, port
10
+ @host, @port = host, port
53
11
  @prefix = nil
54
12
  @socket = UDPSocket.new
55
13
  end
56
14
 
57
- def namespace=(namespace) #:nodoc:
58
- @namespace = namespace
59
- @prefix = "#{namespace}." if @namespace
60
- end
61
-
62
- def environment=(new_environment)
63
- @environment = new_environment.to_s
64
- end
65
-
66
- def host=(host) #:nodoc:
67
- @host = host || '127.0.0.1'
68
- end
69
-
70
- def port=(port) #:nodoc:
71
- @port = port || 8125
72
- end
73
-
74
- def log_dir=(log_dir)
75
- @log_dir = Pathname.new log_dir
15
+ def increment(stat, options = {})
16
+ send_stats stat, 1, :c, options
76
17
  end
77
18
 
78
- # Sends an increment (count = 1) for the given stat to the statsd server.
79
- #
80
- # @param [String] stat stat name
81
- # @param [Hash] opts the options to create the metric with
82
- # @option opts [Numeric] :sample_rate sample rate, 1 for always
83
- # @option opts [Array<String>] :tags An array of tags
84
- # @see #count
85
- def increment(stat, opts={})
86
- count stat, 1, opts
19
+ def gauge(stat, value, options = {})
20
+ send_stats stat, value, :g, options
87
21
  end
88
22
 
89
- # Sends a decrement (count = -1) for the given stat to the statsd server.
90
- #
91
- # @param [String] stat stat name
92
- # @param [Hash] opts the options to create the metric with
93
- # @option opts [Numeric] :sample_rate sample rate, 1 for always
94
- # @option opts [Array<String>] :tags An array of tags
95
- # @see #count
96
- def decrement(stat, opts={})
97
- count stat, -1, opts
98
- end
99
-
100
- # Sends an arbitrary count for the given stat to the statsd server.
101
- #
102
- # @param [String] stat stat name
103
- # @param [Integer] count count
104
- # @param [Hash] opts the options to create the metric with
105
- # @option opts [Numeric] :sample_rate sample rate, 1 for always
106
- # @option opts [Array<String>] :tags An array of tags
107
- def count(stat, count, opts={})
108
- send_stats stat, count, :c, opts
109
- end
110
-
111
- # Sends an arbitary gauge value for the given stat to the statsd server.
112
- #
113
- # This is useful for recording things like available disk space,
114
- # memory usage, and the like, which have different semantics than
115
- # counters.
116
- #
117
- # @param [String] stat stat name.
118
- # @param [Numeric] gauge value.
119
- # @param [Hash] opts the options to create the metric with
120
- # @option opts [Numeric] :sample_rate sample rate, 1 for always
121
- # @option opts [Array<String>] :tags An array of tags
122
- # @example Report the current user count:
123
- # $statsd.gauge('user.count', User.count)
124
- def gauge(stat, value, opts={})
125
- send_stats stat, value, :g, opts
126
- end
127
-
128
- # Sends a value to be tracked as a histogram to the statsd server.
129
- #
130
- # @param [String] stat stat name.
131
- # @param [Numeric] histogram value.
132
- # @param [Hash] opts the options to create the metric with
133
- # @option opts [Numeric] :sample_rate sample rate, 1 for always
134
- # @option opts [Array<String>] :tags An array of tags
135
- # @example Report the current user count:
136
- # $statsd.histogram('user.count', User.count)
137
- def histogram(stat, value, opts={})
138
- send_stats stat, value, :h, opts
139
- end
140
-
141
- # Sends a timing (in ms) for the given stat to the statsd server. The
142
- # sample_rate determines what percentage of the time this report is sent. The
143
- # statsd server then uses the sample_rate to correctly track the average
144
- # timing for the stat.
145
- #
146
- # @param [String] stat stat name
147
- # @param [Integer] ms timing in milliseconds
148
- # @param [Hash] opts the options to create the metric with
149
- # @option opts [Numeric] :sample_rate sample rate, 1 for always
150
- # @option opts [Array<String>] :tags An array of tags
151
- def timing(stat, ms, opts={})
152
- send_stats stat, ms, :ms, opts
153
- end
154
-
155
- # Reports execution time of the provided block using {#timing}.
156
- #
157
- # @param [String] stat stat name
158
- # @param [Hash] opts the options to create the metric with
159
- # @option opts [Numeric] :sample_rate sample rate, 1 for always
160
- # @option opts [Array<String>] :tags An array of tags
161
- # @yield The operation to be timed
162
- # @see #timing
163
- # @example Report the time (in ms) taken to activate an account
164
- # $statsd.time('account.activate') { @account.activate! }
165
- def time(stat, opts={})
166
- start = Time.now
167
- result = yield
168
- timing(stat, ((Time.now - start) * 1000).round, opts)
169
- result
170
- end
171
- # Sends a value to be tracked as a set to the statsd server.
172
- #
173
- # @param [String] stat stat name.
174
- # @param [Numeric] set value.
175
- # @param [Hash] opts the options to create the metric with
176
- # @option opts [Numeric] :sample_rate sample rate, 1 for always
177
- # @option opts [Array<String>] :tags An array of tags
178
- # @example Record a unique visitory by id:
179
- # $statsd.set('visitors.uniques', User.id)
180
- def set(stat, value, opts={})
181
- send_stats stat, value, :s, opts
23
+ def histogram(stat, value, options = {})
24
+ send_stats stat, value, :h, options
182
25
  end
183
26
 
184
27
  def log(stat, data = {})
185
- data = { environment: environment }.merge data
186
- data.merge! app: namespace, statname: stat
187
- File.open(log_dir.join('application.json.log'), 'a') {|f| f.puts(data.to_json) }
188
- end
189
-
190
- def increment_and_log(stat, data = {})
191
- increment stat
192
- log stat, data
28
+ data = { environment: ::Meter.config.environment, Timestamp: Time.now }.merge data
29
+ data.merge! app: ::Meter.config.namespace, statname: stat
30
+ ::Meter.config.logger.debug { "Logging #{log_file} - #{data}"}
31
+ log_file.open('a') { |f| f.puts(JSON.dump data) }
193
32
  end
194
33
 
195
34
  private
196
35
 
197
- def send_stats(stat, delta, type, opts={})
198
- sample_rate = opts[:sample_rate] || 1
199
- if sample_rate == 1 or rand < sample_rate
200
- # Replace Ruby module scoping with '.' and reserved chars (: | @) with underscores.
201
- stat = stat.to_s.gsub('::', '.').tr(':|@', '_')
202
- rate = "|@#{sample_rate}" unless sample_rate == 1
203
- tags = "|##{opts[:tags].join(",")}" if opts[:tags]
204
- send_to_socket "#{@prefix}#{stat}:#{delta}|#{type}#{rate}#{tags}"
205
- end
36
+ def log_file
37
+ ::Meter.config.log_dir.join('application.json.log')
38
+ end
39
+
40
+ # See https://github.com/DataDog/dogstatsd-ruby/blob/master/lib/statsd.rb
41
+ def send_stats(stat, delta, type, options = {})
42
+ sample_rate = options[:sample_rate] || 1
43
+ return unless sample_rate == 1 or rand < sample_rate
44
+ stat = stat.to_s.gsub('::', '.').tr(':|@', '_')
45
+ rate = "|@#{sample_rate}" unless sample_rate == 1
46
+ tags = "|##{Array(options[:tags]).join(",")}" if options[:tags]
47
+ send_to_socket "#{@prefix}#{stat}:#{delta}|#{type}#{rate}#{tags}"
206
48
  end
207
49
 
208
50
  def send_to_socket(message)
209
- self.class.logger.debug { "Statsd: #{message}" } if self.class.logger
210
- @socket.send(message, 0, @host, @port)
211
- rescue => boom
212
- self.class.logger.error { "boom Statsd: #{boom.class} #{boom}" } if self.class.logger
213
- nil
51
+ ::Meter.config.logger.debug { "UDP #{self.host}:#{self.port} - #{message}" }
52
+ @socket.send message, 0, self.host, self.port
214
53
  end
54
+
215
55
  end
216
56
  end
@@ -0,0 +1,16 @@
1
+ require 'meter/backend'
2
+ require 'ostruct'
3
+
4
+ module Meter
5
+
6
+ # Holds the currently known backends.
7
+ #
8
+ def self.backends
9
+ @backends ||= ::OpenStruct.new(
10
+ datadog: ::Meter::Backend.new('127.0.0.1', 8125),
11
+ counter: ::Meter::Backend.new('127.0.0.1', 3333),
12
+ heka: ::Meter::Backend.new('127.0.0.1', 8128),
13
+ )
14
+ end
15
+
16
+ end
@@ -5,164 +5,59 @@ require 'meter/backend'
5
5
  module Meter
6
6
  class Configuration
7
7
 
8
- attr_accessor :logger, :tags
9
- attr_reader :primary_backend, :secondary_backend, :counter_backend, :meter_backend
8
+ attr_reader :options
10
9
 
11
- def initialize(options={})
12
- @logger = options[:logger] || default_logger
13
-
14
- @primary_backend = Backend.new
15
- @primary_backend.host = options[:primary_host] || default_host
16
- @primary_backend.port = options[:primary_port] || default_port
17
- @primary_backend.namespace = options[:namespace] || default_namespace
18
- @primary_backend.environment = options[:environment] || default_environment
19
-
20
- @secondary_backend = Backend.new
21
- @secondary_backend.host = options[:secondary_host] || ENV['METER_SECONDARY_HOST'] || default_host
22
- @secondary_backend.port = options[:secondary_port] || default_secondary_port
23
- @secondary_backend.namespace = options[:namespace] || default_namespace
24
- @secondary_backend.environment = options[:environment] || default_environment
25
-
26
- @counter_backend = Backend.new
27
- @counter_backend.host = options[:counter_host] || default_host
28
- @counter_backend.port = options[:counter_port] || default_counter_port
29
- @counter_backend.namespace = options[:namespace] || default_namespace
30
- @counter_backend.environment = options[:environment] || default_environment
31
-
32
- @meter_backend = Backend.new
33
- @meter_backend.host = options[:meter_host] || default_host
34
- @meter_backend.port = options[:meter_port] || default_meter_port
35
- @meter_backend.namespace = options[:namespace] || default_namespace
36
- @meter_backend.environment = options[:environment] || default_environment
37
- @meter_backend.log_dir = options[:meter_log_dir] || default_meter_log_dir
38
-
39
- @tags = options[:tags] || {}
10
+ def initialize(options = {})
11
+ @options = options
40
12
  end
41
13
 
42
- def namespace=(new_namespace)
43
- primary_backend.namespace = new_namespace
44
- secondary_backend.namespace = new_namespace
45
- counter_backend.namespace = new_namespace
46
- meter_backend.namespace = new_namespace
47
- end
48
-
49
- def environment=(new_environment)
50
- primary_backend.environment = new_environment
51
- secondary_backend.environment = new_environment
52
- counter_backend.environment = new_environment
53
- meter_backend.environment = new_environment
14
+ def logger
15
+ @logger ||= options[:logger] || default_logger
54
16
  end
17
+ attr_writer :logger
55
18
 
56
19
  def namespace
57
- primary_backend.namespace
58
- end
59
-
60
- def primary_host
61
- primary_backend.host
62
- end
63
-
64
- def primary_port
65
- primary_backend.port
66
- end
67
-
68
- def secondary_host
69
- secondary_backend.host
70
- end
71
-
72
- def secondary_port
73
- secondary_backend.port
74
- end
75
-
76
- def secondary_host
77
- secondary_backend.host
78
- end
79
-
80
- def secondary_port
81
- secondary_backend.port
82
- end
83
-
84
- def primary_host=(new_host)
85
- primary_backend.host = new_host
20
+ @namespace ||= options[:namespace] || default_namespace
86
21
  end
22
+ attr_writer :namespace
87
23
 
88
- def primary_port=(new_port)
89
- primary_backend.port = new_port
24
+ def environment
25
+ @environment ||= options[:environment] || default_environment
90
26
  end
27
+ attr_writer :environment
91
28
 
92
- def secondary_host=(new_host)
93
- secondary_backend.host = new_host
29
+ def log_dir
30
+ @log_dir ||= (::Pathname.new(options[:log_dir]) if options[:log_dir]) || default_log_dir
94
31
  end
95
32
 
96
- def secondary_port=(new_port)
97
- secondary_backend.port = new_port
33
+ def log_dir=(new_dir)
34
+ @log_dir = Pathname.new new_dir
98
35
  end
99
36
 
100
37
  private
101
38
 
102
39
  def default_logger
103
- if defined?(Rails)
104
- Rails.logger
105
- else
106
- Logger.new(STDOUT)
107
- end
108
- end
109
-
110
- def default_host
111
- '127.0.0.1'
112
- end
113
-
114
- def default_port
115
- 8125
116
- end
117
-
118
- def default_secondary_port
119
- 8127
120
- end
121
-
122
- def default_counter_port
123
- 3333
124
- end
125
-
126
- def default_meter_port
127
- 8128
40
+ return ::Rails.logger if defined?(::Rails)
41
+ ::Logger.new STDOUT
128
42
  end
129
43
 
130
44
  def default_namespace
131
- nil
45
+ :meter
132
46
  end
133
47
 
134
48
  def default_environment
135
- return Rails.env if defined?(Rails)
49
+ return ::Rails.env if defined?(::Rails)
136
50
  return ENV['RACK_ENV'] if ENV['RACK_ENV'].to_s != ''
137
51
  return ENV['NODE_CHEF_ENVIRONMENT'] if ENV['NODE_CHEF_ENVIRONMENT'].to_s != ''
138
52
  'unknown'
139
53
  end
140
54
 
141
- def default_meter_log_dir
142
- return Rails.root.join('log') if defined?(Rails)
143
- Pathname.pwd
55
+ def default_log_dir
56
+ return ::Rails.root.join('log') if defined?(::Rails)
57
+ log_subdir = ::Pathname.pwd.join('log')
58
+ return log_subdir if log_subdir.directory?
59
+ Pathname.new '/dev/null'
144
60
  end
145
61
 
146
62
  end
147
63
  end
148
-
149
- module Meter
150
-
151
- # Public: Returns the the configuration instance.
152
- #
153
- def self.config
154
- @config ||= Configuration.new
155
- end
156
-
157
- # Public: Yields the configuration instance.
158
- #
159
- def self.configure(&block)
160
- yield config
161
- end
162
-
163
- # Public: Reset the configuration (useful for testing).
164
- #
165
- def self.reset!
166
- @config = nil
167
- end
168
- end
@@ -0,0 +1,17 @@
1
+ require 'meter/configuration'
2
+
3
+ module Meter
4
+
5
+ # Public: Lazy-loads and returns the the configuration instance.
6
+ #
7
+ def self.config
8
+ @config ||= ::Meter::Configuration.new
9
+ end
10
+
11
+ # Public: Yields the configuration instance.
12
+ #
13
+ def self.configure(&block)
14
+ yield config
15
+ end
16
+
17
+ end
data/lib/meter/version.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module Meter
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 0
5
- TINY = 10
4
+ MINOR = 1
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].compact.join('.')
8
8
  end
data/lib/meter.rb CHANGED
@@ -1,59 +1,36 @@
1
- require 'json'
2
- require 'meter/configuration'
1
+ require 'meter/backends'
2
+ require 'meter/configure'
3
3
 
4
- # A generic wrapper for Statsd-like gauges and counters.
5
- #
6
4
  module Meter
7
- extend self
8
5
 
9
- def increment(key, options = {})
6
+ def self.increment(key, options = {})
10
7
  id = options.delete(:id)
11
- primary.increment key, options
12
- if id
13
- counter.increment "#{key}.#{id}", options
14
- end
15
- end
16
-
17
- def count(key, delta, options = {})
18
- id = options.delete(:id)
19
- primary.count key, delta, options
20
- if id
21
- counter.count "#{key}.#{id}", delta, options
22
- end
23
- end
24
-
25
- def gauge(key, value, options = {})
26
- primary.gauge key, value, options
27
- end
8
+ backends.datadog.increment key, options
9
+ backends.counter.increment("#{key}.#{id}", options) if id
28
10
 
29
- def histogram(key, value, options = {})
30
- primary.histogram key, value, options
11
+ rescue => exception
12
+ ::Meter.config.logger.error exception.inspect
31
13
  end
32
14
 
33
- def log(key, data)
34
- meter.log(key, data)
35
- end
15
+ def self.gauge(key, value, options = {})
16
+ backends.datadog.gauge key, value, options
36
17
 
37
- def increment_and_log(key, data)
38
- meter.increment_and_log(key, data)
18
+ rescue => exception
19
+ ::Meter.config.logger.error exception.inspect
39
20
  end
40
21
 
41
- private
22
+ def self.histogram(key, value, options = {})
23
+ backends.datadog.histogram key, value, options
42
24
 
43
- def primary
44
- config.primary_backend
25
+ rescue => exception
26
+ ::Meter.config.logger.error exception.inspect
45
27
  end
46
28
 
47
- def secondary
48
- config.secondary_backend
49
- end
50
-
51
- def counter
52
- config.counter_backend
53
- end
29
+ def self.log(key, data)
30
+ backends.heka.log key, data
54
31
 
55
- def meter
56
- config.meter_backend
32
+ rescue => exception
33
+ ::Meter.config.logger.error exception.inspect
57
34
  end
58
35
 
59
36
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - bukowskis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-28 00:00:00.000000000 Z
11
+ date: 2014-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: trouble
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rspec
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,20 @@ dependencies:
52
66
  - - ">="
53
67
  - !ruby/object:Gem::Version
54
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: timecop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  description: A generic abstraction layer for fire and forgetting measurements via
56
84
  UDP.
57
85
  email:
@@ -61,7 +89,9 @@ extra_rdoc_files: []
61
89
  files:
62
90
  - lib/meter.rb
63
91
  - lib/meter/backend.rb
92
+ - lib/meter/backends.rb
64
93
  - lib/meter/configuration.rb
94
+ - lib/meter/configure.rb
65
95
  - lib/meter/version.rb
66
96
  homepage: https://github.com/bukowskis/meter
67
97
  licenses: