librato-metrics 0.7.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,8 +1,13 @@
1
1
  ## Changelog
2
2
 
3
+ ### Version 1.0.0
4
+ * Add support for annotation submission, listing, management
5
+ * Auto-convert Time objects anywhere a time is accepted
6
+ * Don't raise exception anymore for empty queue submission
7
+
3
8
  ### Version 0.7.5
4
9
  * Catch a broader range of connection failures for retrying
5
- * Add Metrics.faraday_adapter config option (Mathieu Ravaux)_
10
+ * Add Metrics.faraday_adapter config option (Mathieu Ravaux)
6
11
 
7
12
  ### Version 0.7.4
8
13
  * Support global measure_time option for Queues/Aggregators
data/README.md CHANGED
@@ -14,13 +14,13 @@ In your shell:
14
14
  Then, in your application or script:
15
15
 
16
16
  require 'librato/metrics'
17
-
17
+
18
18
  ### Optional steps
19
19
 
20
20
  For best performance we recommend installing [yajl-ruby](https://github.com/brianmario/yajl-ruby):
21
21
 
22
22
  gem install yajl-ruby
23
-
23
+
24
24
  If you are using jruby, you need to ensure [jruby-openssl](https://github.com/jruby/jruby-ossl) is available:
25
25
 
26
26
  gem install jruby-openssl
@@ -52,18 +52,18 @@ Queue up a simple gauge metric named `temperature`:
52
52
 
53
53
  queue = Librato::Metrics::Queue.new
54
54
  queue.add :temperature => 32.2
55
-
55
+
56
56
  While symbols are used by convention for metric names, strings will work just as well:
57
57
 
58
58
  queue.add 'myapp.request_time' => 86.7
59
59
 
60
- If you are tracking measurements over several seconds/minutes, the queue will handle storing measurement time for you (otherwise all metrics will be recorded as measured when they are submitted).
60
+ If you are tracking measurements over several seconds/minutes, the queue will handle storing measurement time for you (otherwise all metrics will be recorded as measured when they are submitted).
61
61
 
62
62
  If you want to specify a time other than queuing time for the measurement:
63
63
 
64
64
  # use a epoch integer
65
65
  queue.add :humidity => {:measure_time => 1336508422, :value => 48.2}
66
-
66
+
67
67
  # use a Time object to correct for a 5 second delay
68
68
  queue.add :humidity => {:measure_time => Time.now-5, :value => 37.6}
69
69
 
@@ -125,23 +125,52 @@ If you need extra attributes for a `Queue` timing measurement, simply add them o
125
125
  queue.time :my_measurement, :source => 'app1' do
126
126
  # do work...
127
127
  end
128
-
128
+
129
+ ## Annotations
130
+
131
+ Annotation streams are a great way to track events like deploys, backups or anything else that might affect your system. They can be overlaid on any other metric stream so you can easily see the impact of changes.
132
+
133
+ At a minimum each annotation needs to be assigned to a stream and to have a title. Let's add an annotation for deploying v45 of our app to the `deployments` stream:
134
+
135
+ Librato::Metrics.annotate :deployments, 'deployed v45'
136
+
137
+ There are a number of optional fields which can make annotations even more powerful:
138
+
139
+ Librato::Metrics.annotate :deployments, 'deployed v46', :source => 'frontend',
140
+ :start_time => 1354662596, :end_time => 1354662608,
141
+ :description => 'Deployed 6f3bc6e67682: fix lotsa bugs…'
142
+
143
+ More fine-grained control of annotations is available via the `Annotator` object:
144
+
145
+ annotator = Librato::Metrics::Annotator.new
146
+
147
+ # list annotation streams
148
+ streams = annotator.list
149
+
150
+ # fetch a list of events in the last hour from a stream
151
+ annotator.fetch :deployments, :start_time => (Time.now.to_i-3600)
152
+
153
+ # delete an event
154
+ annotator.delete_event 'deployments', 23
155
+
156
+ See the documentation of `Annotator` for more details and examples of use.
157
+
129
158
  ## Auto-Submitting Metrics
130
159
 
131
160
  Both `Queue` and `Aggregator` support automatically submitting measurements on a given time interval:
132
161
 
133
162
  # submit once per minute
134
163
  timed_queue = Librato::Metrics::Queue.new(:autosubmit_interval => 60)
135
-
164
+
136
165
  # submit every 5 minutes
137
166
  timed_aggregator = Librato::Metrics::Aggregator.new(:autosubmit_interval => 300)
138
-
167
+
139
168
  `Queue` also supports auto-submission based on measurement volume:
140
169
 
141
170
  # submit when the 400th measurement is queued
142
171
  volume_queue = Librato::Metrics::Queue.new(:autosubmit_count => 400)
143
172
 
144
- These options can also be combined for more flexible behavior.
173
+ These options can also be combined for more flexible behavior.
145
174
 
146
175
  Both options are driven by the addition of measurements. Specifically for time-based autosubmission if you are adding measurements irregularly (less than once per second), submission may lag past your specified interval until the next measurement is added.
147
176
 
@@ -181,7 +210,7 @@ If you ever need to remove a metric and all of its measurements, doing so is eas
181
210
 
182
211
  # Delete the metrics 'temperature' and 'humidity'
183
212
  Librato::Metrics.delete :temperature, :humidity
184
-
213
+
185
214
  Note that deleted metrics and their measurements are unrecoverable, so use with care.
186
215
 
187
216
  ## Using Multiple Accounts Simultaneously
@@ -190,7 +219,7 @@ If you need to use metrics with multiple sets of authentication credentials simu
190
219
 
191
220
  joe = Librato::Metrics::Client.new
192
221
  joe.authenticate 'email1', 'api_key1'
193
-
222
+
194
223
  mike = Librato::Metrics::Client.new
195
224
  mike.authenticate 'email2', 'api_key2'
196
225
 
@@ -198,16 +227,16 @@ All of the same operations you can call directly from `Librato::Metrics` are ava
198
227
 
199
228
  # list Joe's metrics
200
229
  joe.list
201
-
202
- # fetch the last 20 data points for Mike's metric, humidity
230
+
231
+ # fetch the last 20 data points for Mike's metric, humidity
203
232
  mike.fetch :humidity, :count => 20
204
-
233
+
205
234
  There are two ways to associate a new queue with a client:
206
235
 
207
236
  # these are functionally equivalent
208
237
  joe_queue = Librato::Metrics::Queue.new(:client => joe)
209
238
  joe_queue = joe.new_queue
210
-
239
+
211
240
  Once the queue is associated you can use it normally:
212
241
 
213
242
  joe_queue.add :temperature => {:source => 'sf', :value => 65.2}
@@ -5,6 +5,7 @@ require 'base64'
5
5
  require 'multi_json'
6
6
 
7
7
  require 'metrics/aggregator'
8
+ require 'metrics/annotator'
8
9
  require 'metrics/client'
9
10
  require 'metrics/collection'
10
11
  require 'metrics/connection'
@@ -67,12 +68,14 @@ module Librato
67
68
  PLURAL_TYPES = [:counters, :gauges]
68
69
  MIN_MEASURE_TIME = (Time.now-(3600*24*365)).to_i
69
70
 
70
- # Expose class methods of Simple via Metrics itself.
71
+ # Most of the singleton methods of Librato::Metrics are actually
72
+ # being called on a global Client instance. See further docs on
73
+ # Client.
71
74
  #
72
- def_delegators :client, :agent_identifier, :api_endpoint,
75
+ def_delegators :client, :agent_identifier, :annotate, :api_endpoint,
73
76
  :api_endpoint=, :authenticate, :connection, :delete,
74
- :faraday_adapter, :faraday_adapter=, :fetch, :list,
75
- :persistence, :persistence=, :persister, :submit,
77
+ :faraday_adapter, :faraday_adapter=, :fetch, :list,
78
+ :persistence, :persistence=, :persister, :submit,
76
79
  :update
77
80
 
78
81
  # The Librato::Metrics::Client being used by module-level
@@ -0,0 +1,106 @@
1
+ module Librato::Metrics
2
+
3
+ # manages writing and reading annotation streams for a
4
+ # given client connection
5
+ class Annotator
6
+
7
+ def initialize(options={})
8
+ @client = options[:client] || Librato::Metrics.client
9
+ end
10
+
11
+ # Creates a new annotation on the annotation stream
12
+ #
13
+ # @example Simple annotation
14
+ # annotator.add :deployments, 'deployed v45'
15
+ #
16
+ # @example Annotation with start and end times
17
+ # annotator.add :deployments, 'deployed v56', :start_time => start,
18
+ # :end_time => end
19
+ #
20
+ # @example Annotation with a specific source
21
+ # annotator.add :deployments, 'deployed v60', :source => 'app12'
22
+ #
23
+ # @example Annotation with a description
24
+ # annotator.add :deployments, 'deployed v61',
25
+ # :description => '9b562b2: shipped new feature foo!'
26
+ #
27
+ def add(stream, title, options={})
28
+ options[:title] = title
29
+ if options[:start_time]
30
+ options[:start_time] = options[:start_time].to_i
31
+ end
32
+ if options[:end_time]
33
+ options[:end_time] = options[:end_time].to_i
34
+ end
35
+ payload = SmartJSON.write(options)
36
+ # expects 200
37
+ connection.post("annotations/#{stream}", payload)
38
+ end
39
+
40
+ def client
41
+ @client
42
+ end
43
+
44
+ def connection
45
+ client.connection
46
+ end
47
+
48
+ # Delete an annotation streams
49
+ #
50
+ # @example Delete 'deployment' annotation stream
51
+ # annotator.delete :deployment
52
+ #
53
+ def delete(stream)
54
+ connection.delete do |request|
55
+ request.url connection.build_url("annotations/#{stream}")
56
+ end
57
+ # expects 204, middleware will raise exception otherwise
58
+ true
59
+ end
60
+
61
+ # Delete an event from a given annotation stream
62
+ #
63
+ # @example Delete event with id 42 from 'deployment'
64
+ # annotator.delete_event :deployment, 42
65
+ #
66
+ def delete_event(stream, id)
67
+ connection.delete do |request|
68
+ request.url connection.build_url("annotations/#{stream}/#{id}")
69
+ end
70
+ # expects 204, middleware will raise exception otherwise
71
+ true
72
+ end
73
+
74
+ # Get a list of annotation events on a given annotation stream
75
+ #
76
+ # @example See properties of the 'deployments' annotation stream
77
+ # annotator.fetch :deployments
78
+ #
79
+ # @example Get events on 'deployments' between start and end times
80
+ # annotator.fetch :deployments, :start_time => start, :end_time => end
81
+ #
82
+ # @example Source-limited listing
83
+ # annotator.fetch :deployments, :sources => ['foo','bar','baz'],
84
+ # :start_time => start, :end_time => end
85
+ #
86
+ def fetch(stream, options={})
87
+ response = connection.get("annotations/#{stream}", options)
88
+ SmartJSON.read(response.body)
89
+ end
90
+
91
+ # List currently existing annotation streams
92
+ #
93
+ # @example List all annotation streams
94
+ # streams = annotator.list
95
+ #
96
+ # @example List annotator streams with 'deploy' in the name
97
+ # deploy_streams = annotator.list :name => 'deploy'
98
+ #
99
+ def list(options={})
100
+ response = connection.get("annotations", options)
101
+ SmartJSON.read(response.body)
102
+ end
103
+
104
+ end
105
+
106
+ end
@@ -2,6 +2,10 @@ module Librato
2
2
  module Metrics
3
3
 
4
4
  class Client
5
+ extend Forwardable
6
+
7
+ def_delegator :annotator, :add, :annotate
8
+
5
9
  attr_accessor :email, :api_key
6
10
 
7
11
  # Provide agent identifier for the developer program. See:
@@ -26,6 +30,10 @@ module Librato
26
30
  @agent_identifier ||= ''
27
31
  end
28
32
 
33
+ def annotator
34
+ @annotator ||= Annotator.new(:client => self)
35
+ end
36
+
29
37
  # API endpoint to use for queries and direct
30
38
  # persistence.
31
39
  #
@@ -57,7 +65,7 @@ module Librato
57
65
  def connection
58
66
  # prevent successful creation if no credentials set
59
67
  raise CredentialsMissing unless (self.email and self.api_key)
60
- @connection ||= Connection.new(:client => self, :api_endpoint => api_endpoint,
68
+ @connection ||= Connection.new(:client => self, :api_endpoint => api_endpoint,
61
69
  :adapter => faraday_adapter)
62
70
  end
63
71
 
@@ -94,14 +102,14 @@ module Librato
94
102
  # otherwise.
95
103
  true
96
104
  end
97
-
105
+
98
106
  # Return current adapter this client will use.
99
107
  # Defaults to Metrics.faraday_adapter if set, otherwise
100
108
  # Faraday.default_adapter
101
109
  def faraday_adapter
102
110
  @faraday_adapter ||= default_faraday_adapter
103
111
  end
104
-
112
+
105
113
  # Set faraday adapter this client will use
106
114
  def faraday_adapter=(adapter)
107
115
  @faraday_adapter = adapter
@@ -234,7 +242,7 @@ module Librato
234
242
  end
235
243
 
236
244
  private
237
-
245
+
238
246
  def default_faraday_adapter
239
247
  if Metrics.client == self
240
248
  Faraday.default_adapter
@@ -5,7 +5,6 @@ module Librato
5
5
  class MetricsError < StandardError; end
6
6
 
7
7
  class CredentialsMissing < MetricsError; end
8
- class NoMetricsQueued < MetricsError; end
9
8
  class NoMetricsProvided < MetricsError; end
10
9
  class NoClientProvided < MetricsError; end
11
10
  class InvalidMeasureTime < MetricsError; end
@@ -27,7 +27,7 @@ module Librato
27
27
  #
28
28
  # @return Boolean
29
29
  def submit
30
- raise(NoMetricsQueued, "No metrics queued.") if self.queued.empty?
30
+ return true if self.queued.empty?
31
31
  options = {:per_request => @per_request}
32
32
  if persister.persist(self.client, self.queued, options)
33
33
  @last_submit_time = Time.now
@@ -84,7 +84,7 @@ module Librato
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
+ @measure_time = options[:measure_time] && options[:measure_time].to_i
88
88
  @create_time = Time.now
89
89
  @clear_on_failure = options[:clear_failures] || false
90
90
  @prefix = options[:prefix]
@@ -33,6 +33,7 @@ module Librato
33
33
  end
34
34
  type = ("#{type}s").to_sym
35
35
  if metric[:measure_time]
36
+ metric[:measure_time] = metric[:measure_time].to_i
36
37
  check_measure_time(metric)
37
38
  elsif !skip_measurement_times
38
39
  metric[:measure_time] = epoch_time
@@ -123,7 +124,7 @@ module Librato
123
124
  private
124
125
 
125
126
  def check_measure_time(data)
126
- if data[:measure_time].to_i < Metrics::MIN_MEASURE_TIME
127
+ if data[:measure_time] < Metrics::MIN_MEASURE_TIME
127
128
  raise InvalidMeasureTime, "Measure time for submitted metric (#{data}) is invalid."
128
129
  end
129
130
  end
@@ -1,5 +1,5 @@
1
1
  module Librato
2
2
  module Metrics
3
- VERSION = "0.7.5"
3
+ VERSION = "1.0.0"
4
4
  end
5
5
  end
@@ -0,0 +1,139 @@
1
+ require 'spec_helper'
2
+
3
+ module Librato
4
+ module Metrics
5
+
6
+ describe Annotator do
7
+ before(:all) { prep_integration_tests }
8
+ before(:each) { delete_all_annotations }
9
+
10
+ describe "#add" do
11
+ it "should create new annotation" do
12
+ subject.add :deployment, "deployed v68"
13
+ annos = subject.fetch(:deployment, :start_time => Time.now.to_i-60)
14
+ annos["events"]["unassigned"].length.should == 1
15
+ annos["events"]["unassigned"][0]["title"].should == 'deployed v68'
16
+ end
17
+ it "should support sources" do
18
+ subject.add :deployment, 'deployed v69', :source => 'box1'
19
+ annos = subject.fetch(:deployment, :start_time => Time.now.to_i-60)
20
+ annos["events"]["box1"].length.should == 1
21
+ first = annos["events"]["box1"][0]
22
+ first['title'].should == 'deployed v69'
23
+ end
24
+ it "should support start and end times" do
25
+ start_time = Time.now.to_i-120
26
+ end_time = Time.now.to_i-30
27
+ subject.add :deployment, 'deployed v70', :start_time => start_time,
28
+ :end_time => end_time
29
+ annos = subject.fetch(:deployment, :start_time => Time.now.to_i-180)
30
+ annos["events"]["unassigned"].length.should == 1
31
+ first = annos["events"]["unassigned"][0]
32
+ first['title'].should == 'deployed v70'
33
+ first['start_time'].should == start_time
34
+ first['end_time'].should == end_time
35
+ end
36
+ it "should support description" do
37
+ subject.add :deployment, 'deployed v71', :description => 'deployed foobar!'
38
+ annos = subject.fetch(:deployment, :start_time => Time.now.to_i-180)
39
+ annos["events"]["unassigned"].length.should == 1
40
+ first = annos["events"]["unassigned"][0]
41
+ first['title'].should == 'deployed v71'
42
+ first['description'].should == 'deployed foobar!'
43
+ end
44
+ end
45
+
46
+ describe "#delete" do
47
+ it "should remove annotation streams" do
48
+ subject.add :deployment, "deployed v45"
49
+ subject.fetch :deployment # should exist
50
+ subject.delete :deployment
51
+ lambda {
52
+ subject.fetch(:deployment)
53
+ }.should raise_error(Metrics::NotFound)
54
+ end
55
+ end
56
+
57
+ describe "#delete_event" do
58
+ it "should remove an annotation event" do
59
+ subject.add :deployment, 'deployed v46'
60
+ subject.add :deployment, 'deployed v47'
61
+ events = subject.fetch(:deployment, :start_time => Time.now.to_i-60)
62
+ events = events['events']['unassigned']
63
+ ids = events.each_with_object({}) do |event, hash|
64
+ hash[event['title']] = event['id']
65
+ end
66
+ subject.delete_event :deployment, ids['deployed v47']
67
+ events = subject.fetch(:deployment, :start_time => Time.now.to_i-60)
68
+ events = events['events']['unassigned']
69
+ events.length.should == 1
70
+ events[0]['title'].should == 'deployed v46'
71
+ end
72
+ end
73
+
74
+ describe "#fetch" do
75
+ context "without a time frame" do
76
+ it "should return stream properties" do
77
+ subject.add :backups, "backup 21"
78
+ properties = subject.fetch :backups
79
+ properties['name'].should == 'backups'
80
+ end
81
+ end
82
+
83
+ context "with a time frame" do
84
+ it "should return set of annotations" do
85
+ subject.add :backups, "backup 22"
86
+ subject.add :backups, "backup 23"
87
+ annos = subject.fetch :backups, :start_time => Time.now.to_i-60
88
+ events = annos['events']['unassigned']
89
+ events[0]['title'].should == 'backup 22'
90
+ events[1]['title'].should == 'backup 23'
91
+ end
92
+ it "should respect source limits" do
93
+ subject.add :backups, "backup 24", :source => 'server_1'
94
+ subject.add :backups, "backup 25", :source => 'server_2'
95
+ subject.add :backups, "backup 26", :source => 'server_3'
96
+ annos = subject.fetch :backups, :start_time => Time.now.to_i-60,
97
+ :sources => %w{server_1 server_3}
98
+ annos['events']['server_1'].should_not be_nil
99
+ annos['events']['server_2'].should be_nil
100
+ annos['events']['server_3'].should_not be_nil
101
+ end
102
+ end
103
+
104
+ it "should return exception if annotation is missing" do
105
+ lambda {
106
+ subject.fetch :backups
107
+ }.should raise_error(Metrics::NotFound)
108
+ end
109
+ end
110
+
111
+ describe "#list" do
112
+ before(:each) do
113
+ subject.add :backups, 'backup 1'
114
+ subject.add :deployment, 'deployed v74'
115
+ end
116
+
117
+ context "without arguments" do
118
+ it "should list annotation streams" do
119
+ streams = subject.list
120
+ streams['annotations'].length.should == 2
121
+ streams = streams['annotations'].map{|i| i['name']}
122
+ streams.should include('backups')
123
+ streams.should include('deployment')
124
+ end
125
+ end
126
+ context "with an argument" do
127
+ it "should list annotation streams which match" do
128
+ streams = subject.list :name => 'back'
129
+ streams['annotations'].length.should == 1
130
+ streams = streams['annotations'].map{|i| i['name']}
131
+ streams.should include('backups')
132
+ end
133
+ end
134
+ end
135
+
136
+ end
137
+
138
+ end
139
+ end
@@ -4,6 +4,45 @@ module Librato
4
4
  describe Metrics do
5
5
  before(:all) { prep_integration_tests }
6
6
 
7
+ describe "#annotate" do
8
+ before(:all) { @annotator = Metrics::Annotator.new }
9
+ before(:each) { delete_all_annotations }
10
+
11
+ it "should create new annotation" do
12
+ Metrics.annotate :deployment, "deployed v68"
13
+ annos = @annotator.fetch(:deployment, :start_time => Time.now.to_i-60)
14
+ annos["events"]["unassigned"].length.should == 1
15
+ annos["events"]["unassigned"][0]["title"].should == 'deployed v68'
16
+ end
17
+ it "should support sources" do
18
+ Metrics.annotate :deployment, 'deployed v69', :source => 'box1'
19
+ annos = @annotator.fetch(:deployment, :start_time => Time.now.to_i-60)
20
+ annos["events"]["box1"].length.should == 1
21
+ first = annos["events"]["box1"][0]
22
+ first['title'].should == 'deployed v69'
23
+ end
24
+ it "should support start and end times" do
25
+ start_time = Time.now.to_i-120
26
+ end_time = Time.now.to_i-30
27
+ Metrics.annotate :deployment, 'deployed v70', :start_time => start_time,
28
+ :end_time => end_time
29
+ annos = @annotator.fetch(:deployment, :start_time => Time.now.to_i-180)
30
+ annos["events"]["unassigned"].length.should == 1
31
+ first = annos["events"]["unassigned"][0]
32
+ first['title'].should == 'deployed v70'
33
+ first['start_time'].should == start_time
34
+ first['end_time'].should == end_time
35
+ end
36
+ it "should support description" do
37
+ Metrics.annotate :deployment, 'deployed v71', :description => 'deployed foobar!'
38
+ annos = @annotator.fetch(:deployment, :start_time => Time.now.to_i-180)
39
+ annos["events"]["unassigned"].length.should == 1
40
+ first = annos["events"]["unassigned"][0]
41
+ first['title'].should == 'deployed v71'
42
+ first['description'].should == 'deployed foobar!'
43
+ end
44
+ end
45
+
7
46
  describe "#delete" do
8
47
  before(:each) { delete_all_metrics }
9
48
 
@@ -21,6 +21,16 @@ RSpec.configure do |config|
21
21
  end
22
22
  end
23
23
 
24
+ # purge all annotations from test account
25
+ def delete_all_annotations
26
+ annotator = Librato::Metrics::Annotator.new
27
+ streams = annotator.list
28
+ if streams['annotations']
29
+ names = streams['annotations'].map{|s| s['name']}
30
+ names.each { |name| annotator.delete name}
31
+ end
32
+ end
33
+
24
34
  # set up test account credentials for integration tests
25
35
  def prep_integration_tests
26
36
  raise 'no TEST_API_USER specified in environment' unless ENV['TEST_API_USER']
@@ -67,7 +67,7 @@ module Librato
67
67
  :description => 'current disk utilization', :measure_time => measure_time,
68
68
  :source => 'db2'}
69
69
  expected = {:gauges => [{:value => 35.4, :name => 'disk_use', :period => 2,
70
- :description => 'current disk utilization', :measure_time => measure_time,
70
+ :description => 'current disk utilization', :measure_time => measure_time.to_i,
71
71
  :source => 'db2'}]}
72
72
  subject.queued.should equal_unordered(expected)
73
73
  end
@@ -116,7 +116,7 @@ module Librato
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
- subject.queued[:gauges][0][:measure_time].should == time
119
+ subject.queued[:gauges][0][:measure_time].should == time.to_i
120
120
  end
121
121
 
122
122
  it "should accept integers" do
@@ -128,7 +128,7 @@ module Librato
128
128
  it "should accept strings" do
129
129
  time = '1336574713'
130
130
  subject.add :foo => {:measure_time => time, :value => 123}
131
- subject.queued[:gauges][0][:measure_time].should == time
131
+ subject.queued[:gauges][0][:measure_time].should == time.to_i
132
132
  end
133
133
 
134
134
  it "should raise exception in invalid time" do
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.5
4
+ version: 1.0.0
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-11-27 00:00:00.000000000 Z
12
+ date: 2012-12-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: faraday
@@ -173,6 +173,7 @@ files:
173
173
  - benchmarks/array_vs_set.rb
174
174
  - lib/librato/metrics.rb
175
175
  - lib/librato/metrics/aggregator.rb
176
+ - lib/librato/metrics/annotator.rb
176
177
  - lib/librato/metrics/client.rb
177
178
  - lib/librato/metrics/collection.rb
178
179
  - lib/librato/metrics/connection.rb
@@ -189,6 +190,7 @@ files:
189
190
  - lib/librato/metrics/smart_json.rb
190
191
  - lib/librato/metrics/version.rb
191
192
  - librato-metrics.gemspec
193
+ - spec/integration/metrics/annotator_spec.rb
192
194
  - spec/integration/metrics/connection_spec.rb
193
195
  - spec/integration/metrics/middleware/count_requests_spec.rb
194
196
  - spec/integration/metrics/queue_spec.rb
@@ -216,7 +218,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
216
218
  version: '0'
217
219
  segments:
218
220
  - 0
219
- hash: -366569108077334223
221
+ hash: 3364933911255209794
220
222
  required_rubygems_version: !ruby/object:Gem::Requirement
221
223
  none: false
222
224
  requirements:
@@ -230,6 +232,7 @@ signing_key:
230
232
  specification_version: 2
231
233
  summary: Ruby wrapper for Librato's Metrics API
232
234
  test_files:
235
+ - spec/integration/metrics/annotator_spec.rb
233
236
  - spec/integration/metrics/connection_spec.rb
234
237
  - spec/integration/metrics/middleware/count_requests_spec.rb
235
238
  - spec/integration/metrics/queue_spec.rb