librato-metrics 0.7.3 → 0.7.4

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.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## Changelog
2
2
 
3
+ ### Version 0.7.4
4
+ * Support global measure_time option for Queues/Aggregators
5
+ * Support all versions of multi_json so we can relax version constraint_
6
+
3
7
  ### Version 0.7.3
4
8
  * Allow prefixes to be changed after instantiation on Queues/Aggregators
5
9
 
data/README.md CHANGED
@@ -217,13 +217,6 @@ Once the queue is associated you can use it normally:
217
217
 
218
218
  The `librato-metrics` gem currently does not do internal locking for thread safety. When used in multi-threaded applications, please add your own mutexes for sensitive operations.
219
219
 
220
- ## Feature Roadmap
221
-
222
- These are features we expect to add in future versions, roughly in the order of current priority. If you feel strongly about a feature, feel free to [create an issue](https://github.com/librato/librato-metrics/issues) or [join us in live chat](https://librato.campfirenow.com/269d3) and talk to us about it.
223
-
224
- * Queue objects support a single default measure_time to use for any measurements which don't have it set
225
- * Query actions return a collection object which auto-paginates large result sets
226
-
227
220
  ## Contribution
228
221
 
229
222
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
@@ -11,6 +11,7 @@ require 'metrics/connection'
11
11
  require 'metrics/errors'
12
12
  require 'metrics/persistence'
13
13
  require 'metrics/queue'
14
+ require 'metrics/smart_json'
14
15
  require 'metrics/version'
15
16
 
16
17
  module Librato
@@ -69,8 +70,8 @@ module Librato
69
70
  # Expose class methods of Simple via Metrics itself.
70
71
  #
71
72
  def_delegators :client, :agent_identifier, :api_endpoint,
72
- :api_endpoint=, :authenticate, :connection, :delete,
73
- :fetch, :list, :persistence, :persistence=, :persister,
73
+ :api_endpoint=, :authenticate, :connection, :delete,
74
+ :fetch, :list, :persistence, :persistence=, :persister,
74
75
  :submit, :update
75
76
 
76
77
  # The Librato::Metrics::Client being used by module-level
@@ -6,7 +6,7 @@ module Librato
6
6
 
7
7
  class Aggregator
8
8
  SOURCE_SEPARATOR = '%%' # must not be in valid source name criteria
9
-
9
+
10
10
  include Processor
11
11
 
12
12
  attr_reader :source
@@ -40,7 +40,7 @@ module Librato
40
40
  autosubmit_check
41
41
  self
42
42
  end
43
-
43
+
44
44
  # Returns true if aggregate contains no measurements
45
45
  #
46
46
  # @return Boolean
@@ -80,6 +80,7 @@ module Librato
80
80
 
81
81
  req = { :gauges => gauges }
82
82
  req[:source] = @source if @source
83
+ req[:measure_time] = @measure_time if @measure_time
83
84
 
84
85
  req
85
86
  end
@@ -59,7 +59,7 @@ module Librato
59
59
  raise CredentialsMissing unless (self.email and self.api_key)
60
60
  @connection ||= Connection.new(:client => self, :api_endpoint => api_endpoint)
61
61
  end
62
-
62
+
63
63
  # Overrride user agent for this client's connections. If you
64
64
  # are trying to specify an agent identifier for developer
65
65
  # program, see #agent_identifier.
@@ -68,17 +68,17 @@ module Librato
68
68
  @user_agent = agent
69
69
  @connection = nil
70
70
  end
71
-
71
+
72
72
  def custom_user_agent
73
73
  @user_agent
74
74
  end
75
-
75
+
76
76
  # Completely delete metrics with the given names. Be
77
77
  # careful with this, this is instant and permanent.
78
78
  #
79
79
  # @example Delete metric 'temperature'
80
80
  # Librato::Metrics.delete :temperature
81
- #
81
+ #
82
82
  # @example Delete metrics 'foo' and 'bar'
83
83
  # Librato::Metrics.delete :foo, :bar
84
84
  def delete(*metric_names)
@@ -87,7 +87,7 @@ module Librato
87
87
  params = {:names => metric_names }
88
88
  connection.delete do |request|
89
89
  request.url connection.build_url("metrics")
90
- request.body = MultiJson.dump(params)
90
+ request.body = SmartJSON.write(params)
91
91
  end
92
92
  # expects 204, middleware will raise exception
93
93
  # otherwise.
@@ -137,7 +137,7 @@ module Librato
137
137
  # expects 200
138
138
  url = connection.build_url("metrics/#{metric}", query)
139
139
  response = connection.get(url)
140
- parsed = MultiJson.load(response.body)
140
+ parsed = SmartJSON.read(response.body)
141
141
  # TODO: pagination support
142
142
  query.empty? ? parsed : parsed["measurements"]
143
143
  end
@@ -198,13 +198,13 @@ module Librato
198
198
  # Submit all queued metrics.
199
199
  #
200
200
  def submit(args)
201
- @queue ||= Queue.new(:client => self,
202
- :skip_measurement_times => true,
201
+ @queue ||= Queue.new(:client => self,
202
+ :skip_measurement_times => true,
203
203
  :clear_failures => true)
204
204
  @queue.add args
205
205
  @queue.submit
206
206
  end
207
-
207
+
208
208
  # Update metric with the given name.
209
209
  #
210
210
  # @example Update metric 'temperature'
@@ -216,7 +216,7 @@ module Librato
216
216
  def update(metric, options = {})
217
217
  connection.put do |request|
218
218
  request.url connection.build_url("metrics/#{metric}")
219
- request.body = MultiJson.dump(options)
219
+ request.body = SmartJSON.write(options)
220
220
  end
221
221
  end
222
222
 
@@ -14,7 +14,7 @@ module Librato
14
14
  # expects 200
15
15
  url = connection.build_url(path, query)
16
16
  response = connection.get(url)
17
- parsed = MultiJson.load(response.body)
17
+ parsed = SmartJSON.read(response.body)
18
18
  results = parsed["metrics"]
19
19
  return results if parsed["query"]["found"] <= MAX_RESULTS
20
20
  query[:offset] = MAX_RESULTS
@@ -22,7 +22,7 @@ module Librato
22
22
  # expects 200
23
23
  url = connection.build_url(path, query)
24
24
  response = connection.get(url)
25
- parsed = MultiJson.load(response.body)
25
+ parsed = SmartJSON.read(response.body)
26
26
  results.push(*parsed["metrics"])
27
27
  query[:offset] += MAX_RESULTS
28
28
  end while query[:offset] < parsed["query"]["found"]
@@ -6,37 +6,37 @@ require 'metrics/middleware/retry'
6
6
 
7
7
  module Librato
8
8
  module Metrics
9
-
9
+
10
10
  class Connection
11
11
  extend Forwardable
12
-
13
- DEFAULT_API_ENDPOINT = 'https://metrics-api.librato.com'
14
-
12
+
13
+ DEFAULT_API_ENDPOINT = 'https://metrics-api.librato.com'
14
+
15
15
  def_delegators :transport, :get, :post, :head, :put, :delete,
16
16
  :build_url
17
-
17
+
18
18
  def initialize(options={})
19
19
  @client = options[:client]
20
20
  @api_endpoint = options[:api_endpoint]
21
21
  end
22
-
22
+
23
23
  # API endpoint that will be used for requests.
24
24
  #
25
25
  def api_endpoint
26
26
  @api_endpoint || DEFAULT_API_ENDPOINT
27
27
  end
28
-
28
+
29
29
  def transport
30
30
  raise(NoClientProvided, "No client provided.") unless @client
31
31
  @transport ||= Faraday::Connection.new(:url => api_endpoint + "/v1/") do |f|
32
32
  #f.use FaradayMiddleware::EncodeJson
33
33
  f.use Librato::Metrics::Middleware::RequestBody
34
34
  f.use Librato::Metrics::Middleware::Retry
35
- f.use Librato::Metrics::Middleware::CountRequests
36
-
35
+ f.use Librato::Metrics::Middleware::CountRequests
36
+
37
37
  f.use Librato::Metrics::Middleware::ExpectsStatus
38
38
  #f.use FaradayMiddleware::ParseJson, :content_type => /\bjson$/
39
-
39
+
40
40
  f.adapter Faraday.default_adapter
41
41
  end.tap do |transport|
42
42
  transport.headers[:user_agent] = user_agent
@@ -44,7 +44,7 @@ module Librato
44
44
  transport.basic_auth @client.email, @client.api_key
45
45
  end
46
46
  end
47
-
47
+
48
48
  # User-agent used when making requests.
49
49
  #
50
50
  def user_agent
@@ -61,7 +61,7 @@ module Librato
61
61
  #ua_chunks << "(#{transport_adapter})"
62
62
  ua_chunks.join(' ')
63
63
  end
64
-
64
+
65
65
  private
66
66
 
67
67
  def adapter_version
@@ -82,17 +82,17 @@ module Librato
82
82
  return RUBY_ENGINE if Object.constants.include?(:RUBY_ENGINE)
83
83
  RUBY_DESCRIPTION.split[0]
84
84
  end
85
-
85
+
86
86
  # figure out which adapter faraday is using
87
87
  def transport_adapter
88
88
  transport.builder.handlers.each do |handler|
89
89
  if handler.name[0,16] == "Faraday::Adapter"
90
90
  return handler.name[18..-1]
91
- end
91
+ end
92
92
  end
93
93
  end
94
-
94
+
95
95
  end
96
-
96
+
97
97
  end
98
98
  end
@@ -10,15 +10,15 @@ module Librato
10
10
  class NoClientProvided < MetricsError; end
11
11
  class InvalidMeasureTime < MetricsError; end
12
12
  class NotMergeable < MetricsError; end
13
-
13
+
14
14
  class NetworkError < StandardError; end
15
-
15
+
16
16
  class ClientError < NetworkError; end
17
17
  class Unauthorized < ClientError; end
18
18
  class Forbidden < ClientError; end
19
19
  class NotFound < ClientError; end
20
20
  class EntityAlreadyExists < ClientError; end
21
-
21
+
22
22
  class ServerError < NetworkError; end
23
23
 
24
24
  end
@@ -1,17 +1,17 @@
1
1
  module Librato
2
2
  module Metrics
3
3
  module Middleware
4
-
4
+
5
5
  class CountRequests < Faraday::Response::Middleware
6
6
  @total_requests = 0
7
-
7
+
8
8
  class << self
9
9
  attr_reader :total_requests
10
-
10
+
11
11
  def increment
12
12
  @total_requests += 1
13
13
  end
14
-
14
+
15
15
  def reset
16
16
  @total_requests = 0
17
17
  end
@@ -22,8 +22,7 @@ module Librato
22
22
  @app.call(env)
23
23
  end
24
24
  end
25
-
25
+
26
26
  end
27
27
  end
28
28
  end
29
-
@@ -1,9 +1,9 @@
1
1
  module Librato
2
2
  module Metrics
3
3
  module Middleware
4
-
4
+
5
5
  class ExpectsStatus < Faraday::Response::Middleware
6
-
6
+
7
7
  def on_complete(env)
8
8
  # TODO: make exception output prettier
9
9
  case env[:status]
@@ -21,9 +21,9 @@ module Librato
21
21
  raise ServerError, env.to_s
22
22
  end
23
23
  end
24
-
24
+
25
25
  end
26
-
26
+
27
27
  end
28
28
  end
29
29
  end
@@ -2,9 +2,9 @@
2
2
  module Librato
3
3
  module Metrics
4
4
  module Middleware
5
-
5
+
6
6
  class Retry < Faraday::Middleware
7
-
7
+
8
8
  def initialize(app, retries = 3)
9
9
  @retries = retries
10
10
  super(app)
@@ -21,9 +21,9 @@ module Librato
21
21
  raise
22
22
  end
23
23
  end
24
-
24
+
25
25
  end
26
-
26
+
27
27
  end
28
28
  end
29
29
  end
@@ -17,14 +17,14 @@ module Librato
17
17
  requests = [queued]
18
18
  end
19
19
  requests.each do |request|
20
- payload = MultiJson.dump(request)
20
+ payload = SmartJSON.write(request)
21
21
  # expects 200
22
22
  client.connection.post('metrics', payload)
23
23
  end
24
24
  end
25
-
25
+
26
26
  private
27
-
27
+
28
28
  def chunk_queued(queued, per_request)
29
29
  return [queued] if queue_count(queued) <= per_request
30
30
  reqs = []
@@ -42,7 +42,7 @@ module Librato
42
42
  end
43
43
  reqs
44
44
  end
45
-
45
+
46
46
  def queue_count(queued)
47
47
  queued.inject(0) { |result, data| result + data.last.size }
48
48
  end
@@ -1,12 +1,12 @@
1
1
  module Librato
2
2
  module Metrics
3
-
3
+
4
4
  module Processor
5
5
  MEASUREMENTS_PER_REQUEST = 500
6
-
6
+
7
7
  attr_reader :per_request, :last_submit_time
8
8
  attr_accessor :prefix
9
-
9
+
10
10
  # The current Client instance this queue is using to authenticate
11
11
  # and connect to Librato Metrics. This will default to the primary
12
12
  # client used by the Librato::Metrics module unless it has been
@@ -39,7 +39,7 @@ module Librato
39
39
  clear if @clear_on_failure
40
40
  raise
41
41
  end
42
-
42
+
43
43
  # Capture execution time for a block and queue
44
44
  # it as the value for a metric. Times are recorded
45
45
  # in milliseconds.
@@ -67,7 +67,7 @@ module Librato
67
67
  end
68
68
  end
69
69
  alias :benchmark :time
70
-
70
+
71
71
  private
72
72
 
73
73
  def create_persister
@@ -78,25 +78,26 @@ module Librato
78
78
  def epoch_time
79
79
  Time.now.to_i
80
80
  end
81
-
81
+
82
82
  def setup_common_options(options)
83
83
  @autosubmit_interval = options[:autosubmit_interval]
84
84
  @client = options[:client] || Librato::Metrics.client
85
85
  @per_request = options[:per_request] || MEASUREMENTS_PER_REQUEST
86
86
  @source = options[:source]
87
+ @measure_time = options[:measure_time]
87
88
  @create_time = Time.now
88
89
  @clear_on_failure = options[:clear_failures] || false
89
90
  @prefix = options[:prefix]
90
91
  end
91
-
92
+
92
93
  def autosubmit_check
93
94
  if @autosubmit_interval
94
95
  last = @last_submit_time || @create_time
95
96
  self.submit if (Time.now - last).to_i >= @autosubmit_interval
96
97
  end
97
98
  end
98
-
99
+
99
100
  end
100
-
101
+
101
102
  end
102
103
  end
@@ -71,7 +71,7 @@ module Librato
71
71
  def gauges
72
72
  @queued[:gauges] || []
73
73
  end
74
-
74
+
75
75
  # Combines queueable measures from the given object
76
76
  # into this queue.
77
77
  #
@@ -108,6 +108,7 @@ module Librato
108
108
  return {} if @queued.empty?
109
109
  globals = {}
110
110
  globals[:source] = @source if @source
111
+ globals[:measure_time] = @measure_time if @measure_time
111
112
  @queued.merge(globals)
112
113
  end
113
114
 
@@ -118,15 +119,15 @@ module Librato
118
119
  self.queued.inject(0) { |result, data| result + data.last.size }
119
120
  end
120
121
  alias :length :size
121
-
122
+
122
123
  private
123
-
124
+
124
125
  def check_measure_time(data)
125
126
  if data[:measure_time].to_i < Metrics::MIN_MEASURE_TIME
126
127
  raise InvalidMeasureTime, "Measure time for submitted metric (#{data}) is invalid."
127
128
  end
128
129
  end
129
-
130
+
130
131
  def reconcile_source(measurements, source)
131
132
  return measurements if !source || source == @source
132
133
  measurements.map! do |measurement|
@@ -137,7 +138,7 @@ module Librato
137
138
  end
138
139
  measurements
139
140
  end
140
-
141
+
141
142
  def submit_check
142
143
  autosubmit_check # in Processor
143
144
  if @autosubmit_count && self.length >= @autosubmit_count
@@ -0,0 +1,31 @@
1
+ # wrap MultiJSON's implementation so we can use any version
2
+ module Librato
3
+ module Metrics
4
+ class SmartJSON
5
+
6
+ class << self
7
+
8
+ # prefer modern syntax; def once at startup
9
+ if MultiJson.respond_to?(:load)
10
+ def read(json)
11
+ MultiJson.load(json)
12
+ end
13
+
14
+ def write(data)
15
+ MultiJson.dump(data)
16
+ end
17
+ else
18
+ def read(json)
19
+ MultiJson.decode(json)
20
+ end
21
+
22
+ def write(data)
23
+ MultiJson.encode(data)
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -1,5 +1,5 @@
1
1
  module Librato
2
2
  module Metrics
3
- VERSION = "0.7.3"
3
+ VERSION = "0.7.4"
4
4
  end
5
5
  end
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
25
25
 
26
26
  ## runtime dependencies
27
27
  s.add_dependency 'faraday', '~> 0.7'
28
- s.add_dependency 'multi_json', '~> 1.3'
28
+ s.add_dependency 'multi_json'
29
29
  s.add_dependency 'aggregate', '~> 0.2.2'
30
30
 
31
31
  ## development dependencies
@@ -35,7 +35,7 @@ Gem::Specification.new do |s|
35
35
  s.add_development_dependency 'yard'
36
36
  s.add_development_dependency 'sinatra'
37
37
  s.add_development_dependency 'popen4'
38
-
38
+
39
39
  # omitting for now because jruby-19mode can't handle
40
40
  #s.add_development_dependency 'rdiscount' # for yard
41
41
 
@@ -2,13 +2,13 @@ require 'spec_helper'
2
2
 
3
3
  module Librato
4
4
  module Metrics
5
-
5
+
6
6
  describe Connection do
7
-
7
+
8
8
  # TODO: test retry support
9
9
  # TODO: test status code support
10
-
10
+
11
11
  end
12
-
12
+
13
13
  end
14
14
  end
@@ -3,26 +3,26 @@ require 'spec_helper'
3
3
  module Librato
4
4
  module Metrics
5
5
  module Middleware
6
-
6
+
7
7
  describe CountRequests do
8
8
  before(:all) { prep_integration_tests }
9
-
9
+
10
10
  it "should count requests" do
11
11
  CountRequests.reset
12
12
  Metrics.submit :foo => 123
13
13
  Metrics.submit :foo => 135
14
- CountRequests.total_requests.should == 2
14
+ CountRequests.total_requests.should == 2
15
15
  end
16
-
16
+
17
17
  it "should be resettable" do
18
18
  Metrics.submit :foo => 123
19
19
  CountRequests.total_requests.should > 0
20
20
  CountRequests.reset
21
21
  CountRequests.total_requests.should == 0
22
22
  end
23
-
23
+
24
24
  end
25
-
25
+
26
26
  end
27
27
  end
28
28
  end
@@ -2,11 +2,11 @@ require 'spec_helper'
2
2
 
3
3
  module Librato
4
4
  module Metrics
5
-
5
+
6
6
  describe Queue do
7
7
  before(:all) { prep_integration_tests }
8
8
  before(:each) { delete_all_metrics }
9
-
9
+
10
10
  context "with a large number of metrics" do
11
11
  it "should submit them in multiple requests" do
12
12
  Middleware::CountRequests.reset
@@ -17,7 +17,7 @@ module Librato
17
17
  queue.submit
18
18
  Middleware::CountRequests.total_requests.should == 4
19
19
  end
20
-
20
+
21
21
  it "should persist all metrics" do
22
22
  queue = Queue.new(:per_request => 2)
23
23
  (1..5).each do |i|
@@ -27,7 +27,7 @@ module Librato
27
27
  queue.add "counter_#{i}" => {:type => :counter, :value => i}
28
28
  end
29
29
  queue.submit
30
-
30
+
31
31
  metrics = Metrics.list
32
32
  metrics.length.should == 8
33
33
  counter = Metrics.fetch :counter_3, :count => 1
@@ -36,21 +36,21 @@ module Librato
36
36
  gauge['unassigned'][0]['value'].should == 5
37
37
  end
38
38
  end
39
-
39
+
40
40
  it "should respect default and individual sources" do
41
41
  queue = Queue.new(:source => 'default')
42
42
  queue.add :foo => 123
43
43
  queue.add :bar => {:value => 456, :source => 'barsource'}
44
44
  queue.submit
45
-
45
+
46
46
  foo = Metrics.fetch :foo, :count => 2
47
47
  foo['default'][0]['value'].should == 123
48
-
48
+
49
49
  bar = Metrics.fetch :bar, :count => 2
50
50
  bar['barsource'][0]['value'].should == 456
51
51
  end
52
-
52
+
53
53
  end
54
-
54
+
55
55
  end
56
56
  end
@@ -6,7 +6,7 @@ module Librato
6
6
 
7
7
  describe "#delete" do
8
8
  before(:each) { delete_all_metrics }
9
-
9
+
10
10
  context "with a single argument" do
11
11
  it "should delete named metric" do
12
12
  Metrics.submit :foo => 123
@@ -15,7 +15,7 @@ module Librato
15
15
  Metrics.list(:name => :foo).should be_empty
16
16
  end
17
17
  end
18
-
18
+
19
19
  context "with multiple arguments" do
20
20
  it "should delete named metrics" do
21
21
  Metrics.submit :foo => 123, :bar => 345, :baz => 567
@@ -25,7 +25,7 @@ module Librato
25
25
  Metrics.list(:name => :baz).should_not be_empty
26
26
  end
27
27
  end
28
-
28
+
29
29
  context "with missing metric" do
30
30
  it "should run cleanly" do
31
31
  # the API currently returns success even if
@@ -33,7 +33,7 @@ module Librato
33
33
  Metrics.delete :missing
34
34
  end
35
35
  end
36
-
36
+
37
37
  context "with no arguments" do
38
38
  it "should not make request" do
39
39
  lambda {
@@ -150,7 +150,7 @@ module Librato
150
150
  data['baz'][0]['value'] == 456.0
151
151
  end
152
152
  end
153
-
153
+
154
154
  it "should not retain errors" do
155
155
  delete_all_metrics
156
156
  Metrics.submit :foo => {:type => :counter, :value => 12}
@@ -163,15 +163,15 @@ module Librato
163
163
  end
164
164
 
165
165
  end
166
-
166
+
167
167
  describe "#update" do
168
-
168
+
169
169
  context "with existing metric" do
170
170
  before do
171
171
  delete_all_metrics
172
172
  Metrics.submit :foo => 123
173
173
  end
174
-
174
+
175
175
  it "should upate the metric" do
176
176
  Metrics.update :foo, :display_name => "Foo Metric",
177
177
  :period => 15,
@@ -184,7 +184,7 @@ module Librato
184
184
  foo['attributes'].should == {'display_max' => 1000}
185
185
  end
186
186
  end
187
-
187
+
188
188
  context "without an existing metric" do
189
189
  it "should create the metric if type specified" do
190
190
  delete_all_metrics
@@ -199,7 +199,7 @@ module Librato
199
199
  foo['period'].should == 15
200
200
  foo['attributes'].should == {'display_max' => 1000}
201
201
  end
202
-
202
+
203
203
  it "should raise error if no type specified" do
204
204
  delete_all_metrics
205
205
  lambda {
@@ -211,7 +211,7 @@ module Librato
211
211
  }.should raise_error
212
212
  end
213
213
  end
214
-
214
+
215
215
  end
216
216
 
217
217
  end
@@ -12,7 +12,7 @@ class App < Sinatra::Base
12
12
  get('/v1/not_found') do
13
13
  status 404
14
14
  end
15
-
15
+
16
16
  post('/v1/service_unavailable') do
17
17
  status 503
18
18
  end
data/spec/spec_helper.rb CHANGED
@@ -10,7 +10,7 @@ require 'set'
10
10
  require 'librato/metrics'
11
11
 
12
12
  RSpec.configure do |config|
13
-
13
+
14
14
  # purge all metrics from test account
15
15
  def delete_all_metrics
16
16
  connection = Librato::Metrics.client.connection
@@ -20,7 +20,7 @@ RSpec.configure do |config|
20
20
  connection.delete("metrics/#{metric['name']}")
21
21
  end
22
22
  end
23
-
23
+
24
24
  # set up test account credentials for integration tests
25
25
  def prep_integration_tests
26
26
  raise 'no TEST_API_USER specified in environment' unless ENV['TEST_API_USER']
@@ -30,11 +30,11 @@ RSpec.configure do |config|
30
30
  end
31
31
  Librato::Metrics.authenticate ENV['TEST_API_USER'], ENV['TEST_API_KEY']
32
32
  end
33
-
33
+
34
34
  def rackup_path(*parts)
35
35
  File.expand_path(File.join(File.dirname(__FILE__), 'rackups', *parts))
36
36
  end
37
-
37
+
38
38
  # fire up a given rackup file for the enclosed tests
39
39
  def with_rackup(name)
40
40
  if RUBY_PLATFORM == 'java'
@@ -64,9 +64,9 @@ RSpec::Matchers.define :start_with do |start_string|
64
64
  end
65
65
  end
66
66
 
67
- # Compares hashes of arrays by converting the arrays to
67
+ # Compares hashes of arrays by converting the arrays to
68
68
  # sets before comparision
69
- #
69
+ #
70
70
  # @example
71
71
  # {:foo => [1,3,2]}.should equal_unordered({:foo => [1,2,3]})
72
72
  RSpec::Matchers.define :equal_unordered do |result|
@@ -44,7 +44,7 @@ module Librato
44
44
  it "should allow chaining" do
45
45
  subject.add(:foo => 1234).should == subject
46
46
  end
47
-
47
+
48
48
  context "with single hash argument" do
49
49
  it "should record a single aggregate" do
50
50
  subject.add :foo => 3000
@@ -76,7 +76,7 @@ module Librato
76
76
  }
77
77
  subject.queued.should equal_unordered(expected)
78
78
  end
79
-
79
+
80
80
  it "should respect source argument" do
81
81
  subject.add :foo => {:source => 'alpha', :value => 1}
82
82
  subject.add :foo => 5
@@ -85,19 +85,19 @@ module Librato
85
85
  expected = { :gauges => [
86
86
  { :name => 'foo', :source => 'alpha', :count => 2,
87
87
  :sum => 7.0, :min => 1.0, :max => 6.0 },
88
- { :name => 'foo', :count => 2,
88
+ { :name => 'foo', :count => 2,
89
89
  :sum => 15.0, :min => 5.0, :max => 10.0 }
90
90
  ]}
91
91
  subject.queued.should equal_unordered(expected)
92
92
  end
93
-
93
+
94
94
  context "with a prefix set" do
95
95
  it "should auto-prepend names" do
96
96
  subject = Aggregator.new(:prefix => 'foo')
97
97
  subject.add :bar => 1
98
98
  subject.add :bar => 12
99
99
  expected = {:gauges => [
100
- { :name =>'foo.bar',
100
+ { :name =>'foo.bar',
101
101
  :count => 2,
102
102
  :sum => 13.0,
103
103
  :min => 1.0,
@@ -114,7 +114,7 @@ module Librato
114
114
  it "should record a single aggregate" do
115
115
  subject.add :foo => 3000
116
116
  subject.add :bar => 30
117
- expected = {
117
+ expected = {
118
118
  #:measure_time => @time, TODO: support specific time
119
119
  :gauges => [
120
120
  { :name => 'foo',
@@ -162,6 +162,21 @@ module Librato
162
162
  end
163
163
  end
164
164
 
165
+ describe "#queued" do
166
+ it "should include global source if set" do
167
+ a = Aggregator.new(:source => 'blah')
168
+ a.add :foo => 12
169
+ a.queued[:source].should == 'blah'
170
+ end
171
+
172
+ it "should include global measure_time if set" do
173
+ measure_time = (Time.now-1000).to_i
174
+ a = Aggregator.new(:measure_time => measure_time)
175
+ a.add :foo => 12
176
+ a.queued[:measure_time].should == measure_time
177
+ end
178
+ end
179
+
165
180
  describe "#submit" do
166
181
  before(:all) do
167
182
  Librato::Metrics.authenticate 'me@librato.com', 'foo'
@@ -210,20 +225,20 @@ module Librato
210
225
  end
211
226
  end
212
227
  end
213
-
228
+
214
229
  context "with an autosubmit interval" do
215
230
  let(:client) do
216
231
  client = Client.new
217
232
  client.persistence = :test
218
233
  client
219
234
  end
220
-
235
+
221
236
  it "should not submit immediately" do
222
237
  timed_agg = Aggregator.new(:client => client, :autosubmit_interval => 1)
223
238
  timed_agg.add :foo => 1
224
239
  timed_agg.persister.persisted.should be_nil # nothing sent
225
240
  end
226
-
241
+
227
242
  it "should submit after interval" do
228
243
  timed_agg = Aggregator.new(:client => client, :autosubmit_interval => 1)
229
244
  timed_agg.add :foo => 1
@@ -4,21 +4,21 @@ module Librato
4
4
  module Metrics
5
5
 
6
6
  describe Connection do
7
-
7
+
8
8
  describe "#api_endpoint" do
9
9
  context "when not provided" do
10
10
  it "should be default" do
11
11
  subject.api_endpoint.should == 'https://metrics-api.librato.com'
12
12
  end
13
13
  end
14
-
14
+
15
15
  context "when provided" do
16
16
  it "should be respected" do
17
17
  connection = Connection.new(:api_endpoint => 'http://test.com/')
18
18
  connection.api_endpoint.should == 'http://test.com/'
19
19
  end
20
20
  end
21
- end
21
+ end
22
22
 
23
23
  describe "#user_agent" do
24
24
  context "without an agent_identifier" do
@@ -36,7 +36,7 @@ module Librato
36
36
  connection.user_agent.should start_with('foo/0.5')
37
37
  end
38
38
  end
39
-
39
+
40
40
  context "with a custom user agent set" do
41
41
  it "should use custom user agent" do
42
42
  client = Client.new
@@ -45,17 +45,17 @@ module Librato
45
45
  connection.user_agent.should == 'foo agent'
46
46
  end
47
47
  end
48
-
48
+
49
49
  # TODO: verify user agent is being sent with rackup test
50
50
  end
51
-
51
+
52
52
  describe "network operations" do
53
53
  context "when missing client" do
54
54
  it "should raise exception" do
55
55
  lambda { subject.get 'metrics' }.should raise_error(NoClientProvided)
56
56
  end
57
57
  end
58
-
58
+
59
59
  context "with 400 class errors" do
60
60
  it "should not retry" do
61
61
  Middleware::CountRequests.reset
@@ -73,7 +73,7 @@ module Librato
73
73
  Middleware::CountRequests.total_requests.should == 2
74
74
  end
75
75
  end
76
-
76
+
77
77
  context "with 500 class errors" do
78
78
  it "should retry" do
79
79
  Middleware::CountRequests.reset
@@ -89,8 +89,8 @@ module Librato
89
89
  end
90
90
  end
91
91
  end
92
-
92
+
93
93
  end
94
-
94
+
95
95
  end
96
96
  end
@@ -4,7 +4,7 @@ module Librato
4
4
  module Metrics
5
5
 
6
6
  describe Queue do
7
-
7
+
8
8
  let(:client) {
9
9
  client = Client.new
10
10
  client.persistence = :test
@@ -18,7 +18,7 @@ module Librato
18
18
  vol_queue.add :bar => 2
19
19
  vol_queue.persister.persisted.should_not be_nil # sent
20
20
  end
21
-
21
+
22
22
  it "should not submit if the max has not been reached" do
23
23
  vol_queue = Queue.new(:client => client, :autosubmit_count => 5)
24
24
  vol_queue.add :foo => 1
@@ -26,14 +26,14 @@ module Librato
26
26
  vol_queue.persister.persisted.should be_nil # nothing sent
27
27
  end
28
28
  end
29
-
29
+
30
30
  context "with an autosubmit interval" do
31
31
  it "should not submit immediately" do
32
32
  vol_queue = Queue.new(:client => client, :autosubmit_interval => 1)
33
33
  vol_queue.add :foo => 1
34
34
  vol_queue.persister.persisted.should be_nil # nothing sent
35
35
  end
36
-
36
+
37
37
  it "should submit after interval" do
38
38
  vol_queue = Queue.new(:client => client, :autosubmit_interval => 1)
39
39
  vol_queue.add :foo => 1
@@ -31,7 +31,7 @@ module Librato
31
31
  it "should allow chaining" do
32
32
  subject.add(:foo => 123).should == subject
33
33
  end
34
-
34
+
35
35
  context "with single hash argument" do
36
36
  it "should record a key-value gauge" do
37
37
  expected = {:gauges => [{:name => 'foo', :value => 3000, :measure_time => @time}]}
@@ -71,18 +71,18 @@ module Librato
71
71
  :source => 'db2'}]}
72
72
  subject.queued.should equal_unordered(expected)
73
73
  end
74
-
74
+
75
75
  context "with a prefix set" do
76
76
  it "should auto-prepend names" do
77
77
  subject = Queue.new(:prefix => 'foo')
78
78
  subject.add :bar => 1
79
79
  subject.add :baz => {:value => 23}
80
- expected = {:gauges => [{:name =>'foo.bar', :value => 1, :measure_time => @time},
80
+ expected = {:gauges => [{:name =>'foo.bar', :value => 1, :measure_time => @time},
81
81
  {:name => 'foo.baz', :value => 23, :measure_time => @time}]}
82
82
  subject.queued.should equal_unordered(expected)
83
83
  end
84
84
  end
85
-
85
+
86
86
  context "when dynamically changing prefix" do
87
87
  it "should auto-append names" do
88
88
  subject.add :bar => 12
@@ -94,7 +94,7 @@ module Librato
94
94
  subject.add :bar => 45
95
95
  expected = {:gauges => [
96
96
  {:name => 'bar', :value => 12, :measure_time => @time},
97
- {:name => 'foo.bar', :value => 23, :measure_time => @time},
97
+ {:name => 'foo.bar', :value => 23, :measure_time => @time},
98
98
  {:name => 'foo.bar', :value => 34, :measure_time => @time},
99
99
  {:name => 'bar', :value => 45, :measure_time => @time}]}
100
100
  subject.queued.should equal_unordered(expected)
@@ -111,26 +111,26 @@ module Librato
111
111
  subject.queued.should equal_unordered(expected)
112
112
  end
113
113
  end
114
-
114
+
115
115
  context "with a measure_time" do
116
116
  it "should accept time objects" do
117
117
  time = Time.now-5
118
118
  subject.add :foo => {:measure_time => time, :value => 123}
119
119
  subject.queued[:gauges][0][:measure_time].should == time
120
120
  end
121
-
121
+
122
122
  it "should accept integers" do
123
123
  time = 1336574713
124
124
  subject.add :foo => {:measure_time => time, :value => 123}
125
125
  subject.queued[:gauges][0][:measure_time].should == time
126
126
  end
127
-
127
+
128
128
  it "should accept strings" do
129
129
  time = '1336574713'
130
130
  subject.add :foo => {:measure_time => time, :value => 123}
131
131
  subject.queued[:gauges][0][:measure_time].should == time
132
132
  end
133
-
133
+
134
134
  it "should raise exception in invalid time" do
135
135
  lambda {
136
136
  subject.add :foo => {:measure_time => '12', :value => 123}
@@ -173,17 +173,17 @@ module Librato
173
173
  subject.gauges.should eql []
174
174
  end
175
175
  end
176
-
176
+
177
177
  describe "#last_submit_time" do
178
178
  before(:all) do
179
179
  Librato::Metrics.authenticate 'me@librato.com', 'foo'
180
180
  Librato::Metrics.persistence = :test
181
181
  end
182
-
182
+
183
183
  it "should default to nil" do
184
184
  subject.last_submit_time.should be_nil
185
185
  end
186
-
186
+
187
187
  it "should store last submission time" do
188
188
  prior = Time.now
189
189
  subject.add :foo => 123
@@ -191,7 +191,7 @@ module Librato
191
191
  subject.last_submit_time.should >= prior
192
192
  end
193
193
  end
194
-
194
+
195
195
  describe "#merge!" do
196
196
  context "with another queue" do
197
197
  it "should merge gauges" do
@@ -205,7 +205,7 @@ module Librato
205
205
  {:name=>"baz", :value=>678, :measure_time => @time}]}
206
206
  q2.queued.should equal_unordered(expected)
207
207
  end
208
-
208
+
209
209
  it "should merge counters" do
210
210
  q1 = Queue.new
211
211
  q1.add :users => {:type => :counter, :value => 1000}
@@ -218,7 +218,7 @@ module Librato
218
218
  {:name=>"signups", :value=>500, :measure_time => @time}]}
219
219
  q2.queued.should equal_unordered(expected)
220
220
  end
221
-
221
+
222
222
  it "should maintain specified sources" do
223
223
  q1 = Queue.new
224
224
  q1.add :neo => {:source => 'matrix', :value => 123}
@@ -226,7 +226,7 @@ module Librato
226
226
  q2.merge!(q1)
227
227
  q2.queued[:gauges][0][:source].should == 'matrix'
228
228
  end
229
-
229
+
230
230
  it "should not change default source" do
231
231
  q1 = Queue.new(:source => 'matrix')
232
232
  q1.add :neo => 456
@@ -234,7 +234,7 @@ module Librato
234
234
  q2.merge!(q1)
235
235
  q2.queued[:source].should == 'red_pill'
236
236
  end
237
-
237
+
238
238
  it "should track previous default source" do
239
239
  q1 = Queue.new(:source => 'matrix')
240
240
  q1.add :neo => 456
@@ -247,7 +247,7 @@ module Librato
247
247
  end
248
248
  end
249
249
  end
250
-
250
+
251
251
  it "should handle empty cases" do
252
252
  q1 = Queue.new
253
253
  q1.add :foo => 123, :users => {:type => :counter, :value => 1000}
@@ -258,7 +258,7 @@ module Librato
258
258
  q2.queued.should == expected
259
259
  end
260
260
  end
261
-
261
+
262
262
  context "with an aggregator" do
263
263
  it "should merge" do
264
264
  aggregator = Aggregator.new(:source => 'aggregator')
@@ -267,14 +267,14 @@ module Librato
267
267
  queue = Queue.new(:source => 'queue')
268
268
  queue.add :gauge => 42
269
269
  queue.merge!(aggregator)
270
- expected = {:gauges=>[{:name=>"gauge", :value=>42, :measure_time=>@time},
270
+ expected = {:gauges=>[{:name=>"gauge", :value=>42, :measure_time=>@time},
271
271
  {:name=>"timing", :count=>2, :sum=>305.0, :min=>102.0, :max=>203.0, :source=>"aggregator"}],
272
272
  :source=>'queue'}
273
273
  queue.queued.should equal_unordered(expected)
274
-
274
+
275
275
  end
276
276
  end
277
-
277
+
278
278
  context "with a hash" do
279
279
  it "should merge" do
280
280
  to_merge = {:gauges=>[{:name => 'foo', :value => 123}],
@@ -286,13 +286,28 @@ module Librato
286
286
  end
287
287
  end
288
288
  end
289
-
289
+
290
290
  describe "#per_request" do
291
291
  it "should default to 500" do
292
292
  subject.per_request.should == 500
293
293
  end
294
294
  end
295
295
 
296
+ describe "#queued" do
297
+ it "should include global source if set" do
298
+ q = Queue.new(:source => 'blah')
299
+ q.add :foo => 12
300
+ q.queued[:source].should == 'blah'
301
+ end
302
+
303
+ it "should include global measure_time if set" do
304
+ measure_time = (Time.now-1000).to_i
305
+ q = Queue.new(:measure_time => measure_time)
306
+ q.add :foo => 12
307
+ q.queued[:measure_time].should == measure_time
308
+ end
309
+ end
310
+
296
311
  describe "#size" do
297
312
  it "should return empty if gauges and counters are emtpy" do
298
313
  subject.size.should eq 0
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: librato-metrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3
4
+ version: 0.7.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-16 00:00:00.000000000 Z
12
+ date: 2012-11-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: faraday
@@ -32,17 +32,17 @@ dependencies:
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  none: false
34
34
  requirements:
35
- - - ~>
35
+ - - ! '>='
36
36
  - !ruby/object:Gem::Version
37
- version: '1.3'
37
+ version: '0'
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
- - - ~>
43
+ - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
- version: '1.3'
45
+ version: '0'
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: aggregate
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -186,6 +186,7 @@ files:
186
186
  - lib/librato/metrics/persistence/test.rb
187
187
  - lib/librato/metrics/processor.rb
188
188
  - lib/librato/metrics/queue.rb
189
+ - lib/librato/metrics/smart_json.rb
189
190
  - lib/librato/metrics/version.rb
190
191
  - librato-metrics.gemspec
191
192
  - spec/integration/metrics/connection_spec.rb
@@ -215,7 +216,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
215
216
  version: '0'
216
217
  segments:
217
218
  - 0
218
- hash: -3606609391443233543
219
+ hash: -3428658007385951534
219
220
  required_rubygems_version: !ruby/object:Gem::Requirement
220
221
  none: false
221
222
  requirements: