librato-metrics 0.7.3 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
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: