pingdom-client 0.0.1.alpha → 0.0.2.alpha

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source :rubygems
2
2
 
3
- gem "faraday", "~> 0.5.6"
3
+ gem "faraday", "~> 0.5.7"
4
4
 
5
5
  gem "excon", "~> 0.5.6"
6
6
  gem "yajl-ruby", "~> 0.8.1", :require => "yajl"
@@ -5,7 +5,7 @@ GEM
5
5
  addressable (2.2.4)
6
6
  diff-lcs (1.1.2)
7
7
  excon (0.5.6)
8
- faraday (0.5.6)
8
+ faraday (0.5.7)
9
9
  addressable (~> 2.2.4)
10
10
  multipart-post (~> 1.1.0)
11
11
  rack (>= 1.1.0, < 2)
@@ -30,7 +30,7 @@ DEPENDENCIES
30
30
  activesupport (~> 3.0.4)
31
31
  bundler (~> 1.0.0)
32
32
  excon (~> 0.5.6)
33
- faraday (~> 0.5.6)
33
+ faraday (~> 0.5.7)
34
34
  i18n (~> 0.5.0)
35
35
  rake (~> 0.8.7)
36
36
  rspec (= 2.1.0)
@@ -1,4 +1,7 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+
1
3
  require 'faraday'
4
+ require 'tinder/faraday_response'
2
5
 
3
6
  require 'active_support/core_ext/numeric/time'
4
7
  require 'active_support/core_ext/time/acts_like'
@@ -8,428 +11,15 @@ require 'active_support/core_ext/hash/reverse_merge'
8
11
  require 'active_support/core_ext/array/wrap'
9
12
  require 'active_support/core_ext/hash/slice'
10
13
 
11
- LOGGER = lambda do |app|
12
- lambda do |env|
13
- puts "Request: %s %s" % [env[:method], env[:url].to_s]
14
- app.call(env)
15
- end
16
- end
17
-
18
- module Pingdom
19
- class Client
20
-
21
- attr_accessor :limit
22
-
23
- def initialize(credentials = {})
24
- @connection = Faraday::Connection.new(:url => "https://api/pingdom.com/api/2.0/") do |builder|
25
- builder.url_prefix = "https://api.pingdom.com/api/2.0"
26
-
27
- builder.builder.run LOGGER
28
-
29
- builder.adapter :excon
30
-
31
- # builder.use Gzip # TODO: write GZip response handler, add Accept-Encoding: gzip header
32
- builder.response :yajl
33
- builder.use Tinder::FaradayResponse::WithIndifferentAccess
34
-
35
- builder.basic_auth credentials[:username], credentials[:password]
36
- end
37
- end
38
-
39
- # probes => [1,2,3] #=> probes => "1,2,3"
40
- def prepare_params(options)
41
- options.each do |(key, value)|
42
- options[key] = Array.wrap(value).map(&:to_s).join(',')
43
- options[key] = value.to_i if value.acts_like?(:time)
44
- end
45
-
46
- options
47
- end
48
-
49
- def get(uri, params = {}, &block)
50
- response = @connection.get(@connection.build_url(uri, prepare_params(params)), &block)
51
- update_limits!(response.headers['req-limit-short'], response.headers['req-limit-long'])
52
- response
53
- end
54
-
55
- def update_limits!(short, long)
56
- @limit ||= {}
57
- @limit[:short] = parse_limit(short)
58
- @limit[:long] = parse_limit(long)
59
- @limit
60
- end
61
-
62
- # "Remaining: 394 Time until reset: 3589"
63
- def parse_limit(limit)
64
- if limit.to_s =~ /Remaining: (\d+) Time until reset: (\d+)/
65
- { :remaining => $1.to_i,
66
- :resets_at => $2.to_i.seconds.from_now }
67
- end
68
- end
69
-
70
- def test!(options = {})
71
- Result.parse(self, get("single", options)).first
72
- end
73
-
74
- def checks(options = {})
75
- Check.parse(self, get("checks", options))
76
- end
77
- def check(id)
78
- Check.parse(self, get("checks/#{id}"))
79
- end
80
-
81
- # Check ID
82
- def results(id, options = {})
83
- options.reverse_merge!(:includeanalysis => true)
84
- Result.parse(self, get("results/#{id}", options))
85
- end
86
-
87
- def probes(options = {})
88
- Probe.parse(self, get("probes", options))
89
- end
90
-
91
- def contacts(options = {})
92
- Contact.parse(self, get("contacts", options))
93
- end
94
-
95
- def summary(id)
96
- Summary.proxy(self, id)
97
- end
98
-
99
- end
100
-
101
- class Base
102
- def initialize(client, response, attributes = {})
103
- @client = client
104
- @response = response
105
- @attributes = attributes
106
- end
107
-
108
- def self.attributes(hash)
109
- hash.each do |(attribute, aliases)|
110
- class_eval <<-"end;" unless instance_methods.include?(attribute.to_s)
111
- def #{attribute}
112
- @attributes[:#{attribute}]
113
- end
114
- end;
115
-
116
- Array.wrap(aliases).each do |aliased|
117
- alias_method aliased, attribute
118
- end
119
- end
120
- end
121
-
122
- def method_missing(name, *args, &block)
123
- @attributes[name] or super
124
- end
125
-
126
- def respond_to?(name)
127
- super(name) || @attributes.key?(name)
128
- end
129
-
130
- def id
131
- @attributes[:id]
132
- end
133
-
134
- def inspect
135
- "#<%s %s>" % [self.class.to_s, @attributes.inject([]){ |a, (k,v)| a << "%s: %s" % [k,v.inspect]; a }.join(' ')]
136
- end
137
-
138
- def self.check_error!(response)
139
- if response.body.key?(:error)
140
- raise Error, "%s (%s %s)" % [ response.body[:error][:errormessage],
141
- response.body[:error][:statuscode],
142
- response.body[:error][:statusdesc] ]
143
- end
144
- end
145
-
146
- def self.parse(client, response)
147
- check_error!(response)
148
- response.body
149
- end
150
- end
151
-
152
- # {"statusdesclong"=>"OK", "probeid"=>28, "responsetime"=>221, "statusdesc"=>"OK", "status"=>"up", "probedesc"=>"Amsterdam 2, Netherlands"}
153
- class Result < Base
154
- def self.parse(client, response)
155
- results = super
156
- Array.wrap(results[:results] || results[:result]).map do |result|
157
- new(client, response, result)
158
- end
159
- end
160
-
161
- attributes :responsetime => :response_time,
162
- :probeid => :probe_id
163
-
164
- def probe
165
- @client.probes.detect{ |probe| probe.id == probe_id }
166
- end
167
- end
168
-
169
- # {"name"=>"Autocomplete", "id"=>259103, "type"=>"http", "lastresponsetime"=>203173, "status"=>"up", "lasttesttime"=>1298102416}
170
- class Check < Base
171
- def self.parse(client, response)
172
- super[:checks].map do |check|
173
- new(client, response, check)
174
- end
175
- end
176
-
177
- attributes :lastresponsetime => :last_response_time,
178
- :lasttesttime => :last_test_time,
179
- :lasterrortime => :last_error_time
180
-
181
- def results(options = {})
182
- @client.results(id, options)
183
- end
184
-
185
- def summary
186
- @client.summary(id)
187
- end
188
-
189
- def lasttesttime
190
- Time.at(super)
191
- end
192
-
193
- def lasterrortime
194
- Time.at(super)
195
- end
196
-
197
- end
198
-
199
- # {"city"=>"Manchester", "name"=>"Manchester, UK", "country"=>"United Kingdom",
200
- # "countryiso"=>"GB", "id"=>46, "ip"=>"212.84.74.156", "hostname"=>"s424.pingdom.com", "active"=>true}
201
- class Probe < Base
202
- def self.parse(client, response)
203
- super[:probes].map do |probe|
204
- new(client, response, probe)
205
- end
206
- end
207
-
208
- attributes :countryiso => [:country_iso, :country_code]
209
-
210
- def test!(options)
211
- @client.test!(options.merge(:probeid => id))
212
- end
213
-
214
- end
215
-
216
- # {"name"=>"Larry Bernstein", "directtwitter"=>false, "id"=>142762, "cellphone"=>"1-510-501-7401",
217
- # "paused"=>false, "defaultsmsprovider"=>"clickatell", "email"=>"lbernstein@demandbase.com"}
218
- class Contact < Base
219
- def self.parse(client, response)
220
- super[:contacts].map do |contact|
221
- new(client, response, contact)
222
- end
223
- end
224
-
225
- attributes :cellphone => :phone
226
-
227
- end
228
-
229
- class Summary < Base
230
-
231
- class Proxy < Struct.new(:client, :check_id)
232
- def average(options = {})
233
- options.reverse_merge!(:byprobe => true, :includeuptime => true)
234
- Average.parse(client, client.get("summary.average/#{check_id}", options))
235
- end
236
- alias_method :averages, :average
237
-
238
- def outage(options = {})
239
- options.reverse_merge!(:byprobe => true, :includeuptime => true)
240
- Outage.parse(client, client.get("summary.outage/#{check_id}", options))
241
- end
242
- alias_method :outages, :outage
243
-
244
- def performance(options = {})
245
- options.reverse_merge!(:resolution => :day, :includeuptime => true)
246
- Performance.parse(client, client.get("summary.performance/#{check_id}", options))
247
- end
248
- end
249
-
250
- def self.proxy(client, check)
251
- Proxy.new(client, check)
252
- end
253
-
254
- def from
255
- Time.at(@attributes[:from])
256
- end
257
-
258
- def to
259
- Time.at(@attributes[:to])
260
- end
261
-
262
- attributes :responsetime => :response_time
263
-
264
- # summary.average includeuptime probes=34,35 byprobe
265
- # { "responsetime"=>{
266
- # "from"=>0, "to"=>1298110456, "probes"=>"34, 35", "avgresponse"=>[
267
- # {"probeid"=>35, "avgresponse"=>94},
268
- # {"probeid"=>34, "avgresponse"=>125} ]},
269
- # "status"=>{"totalup"=>5035757, "totalunknown"=>1293069551, "totaldown"=>5078}}
270
- class Average < Base
271
- def self.parse(client, response)
272
- body = super[:summary]
273
- sum = body[:responsetime]
274
- attrs = sum.slice(:from, :to)
275
- attrs[:probes] = (attrs[:probes] || "").gsub(/\w+/, '').split(',').map{|e| e.to_i }
276
-
277
- sum[:status] = Status.new(client, response, body[:status]) if body.key?(:status)
278
-
279
- case sum[:avgresponse]
280
- when Array
281
- sum[:responsetime] = 0
282
- sum[:averages] =
283
- sum.delete(:avgresponse).map do |avg|
284
- sum[:responsetime] += avg[:avgresponse]
285
- new(client, response, avg)
286
- end
287
- sum[:responsetime] = sum[:responsetime] / sum[:averages].size if sum[:averages].size > 0
288
-
289
- when Integer
290
- sum[:responsetime] = sum.delete(:avgresponse)
291
-
292
- end
293
-
294
- sum = Summary.new(client, response, sum)
295
- end
296
-
297
- attributes :probeid => :probe_id
298
-
299
- def probe
300
- @client.probes.detect{ |probe| probe.id == probe_id }
301
- end
302
-
303
- end
304
-
305
- # summary.outage
306
- # {"states"=>[{"timeto"=>1297587576, "timefrom"=>1297475316, "status"=>"up"},
307
- # {"timeto"=>1297587906, "timefrom"=>1297587576, "status"=>"down"},
308
- # {"timeto"=>1298110749, "timefrom"=>1297587906, "status"=>"up"}]}
309
- class Outage < Base
310
- def self.parse(client, response)
311
- super[:summary][:states].
312
- select{ |s| s[:status] == "down" }.
313
- map do |outage|
314
- new(client, response, outage)
315
- end
316
- end
317
-
318
- def downtime
319
- (@attributes[:timeto] - @attributes[:timefrom]).seconds
320
- end
321
-
322
- def timefrom
323
- Time.at(@attributes[:timefrom])
324
- end
325
-
326
- def timeto
327
- Time.at(@attributes[:timeto])
328
- end
329
-
330
- attributes :timefrom => [:time_from, :from],
331
- :timeto => [:time_to, :to,]
332
-
333
- end
334
-
335
- # summary.performance includeuptime resolution=day
336
- # {"days"=>[{"unmonitored"=>0, "downtime"=>0, "starttime"=>1297238400, "uptime"=>86400, "avgresponse"=>234},
337
- # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1297324800, "uptime"=>86400, "avgresponse"=>215},
338
- # {"unmonitored"=>0, "downtime"=>2648, "starttime"=>1297411200, "uptime"=>83752, "avgresponse"=>211},
339
- # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1297497600, "uptime"=>86400, "avgresponse"=>207},
340
- # {"unmonitored"=>0, "downtime"=>330, "starttime"=>1297584000, "uptime"=>86070, "avgresponse"=>228},
341
- # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1297670400, "uptime"=>86400, "avgresponse"=>236},
342
- # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1297756800, "uptime"=>86400, "avgresponse"=>230},
343
- # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1297843200, "uptime"=>86400, "avgresponse"=>256},
344
- # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1297929600, "uptime"=>86400, "avgresponse"=>216},
345
- # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1298016000, "uptime"=>86400, "avgresponse"=>251},
346
- # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1298102400, "uptime"=>8646, "avgresponse"=>223}]}
347
- class Performance < Base
348
- INTERVALS = {
349
- "hour" => 1.hour,
350
- "day" => 1.day,
351
- "week" => 1.week
352
- }
353
-
354
- def self.parse(client, response)
355
- body = super[:summary]
356
- interval = body.keys.detect{ |k| INTERVALS.keys.include?(k.chomp('s').to_s) }.chomp('s').to_sym
357
- intervals = body[interval]
358
-
359
- intervals.map do |perf|
360
- perf[:interval] = interval
361
- new(client, response, perf)
362
- end
363
- end
364
-
365
- def starttime
366
- Time.at(@attributes[:starttime])
367
- end
368
-
369
- def endtime
370
- starttime + INTERVALS[interval.to_s].to_i
371
- end
372
- alias_method :end_at, :endtime
373
-
374
- def uptime
375
- @attributes[:uptime].seconds
376
- end
377
- def downtime
378
- @attributes[:downtime].seconds
379
- end
380
- def unmonitored
381
- @attributes[:unmonitored].seconds
382
- end
383
- def monitored
384
- uptime + downtime
385
- end
386
- def period
387
- monitored + unmonitored
388
- end
389
-
390
- end
391
-
392
- # {"status"=>{"totalup"=>5035757, "totalunknown"=>1293069551, "totaldown"=>5078}}
393
- class Status < Base
394
- end
395
-
396
- end
397
-
398
- class Error < RuntimeError
399
- end
400
- end
401
-
402
- # Taken from:
403
- # https://github.com/collectiveidea/tinder/raw/master/lib/tinder/middleware.rb
404
- # See:
405
- # https://github.com/collectiveidea/tinder/blob/master/MIT-LICENSE
406
- module Tinder
407
- module FaradayResponse
408
- class WithIndifferentAccess < ::Faraday::Response::Middleware
409
- begin
410
- require 'active_support/core_ext/hash/indifferent_access'
411
- rescue LoadError, NameError => error
412
- self.load_error = error
413
- end
414
-
415
- def self.register_on_complete(env)
416
- env[:response].on_complete do |response|
417
- json = response[:body]
418
- if json.is_a?(Hash)
419
- response[:body] = ::HashWithIndifferentAccess.new(json)
420
- elsif json.is_a?(Array) and json.first.is_a?(Hash)
421
- response[:body] = json.map{|item| ::HashWithIndifferentAccess.new(item) }
422
- end
423
- end
424
- end
425
- end
426
-
427
- class RaiseOnAuthenticationFailure < ::Faraday::Response::Middleware
428
- def self.register_on_complete(env)
429
- env[:response].on_complete do |response|
430
- raise AuthenticationFailed if response[:status] == 401
431
- end
432
- end
433
- end
434
- end
435
- end
14
+ require 'pingdom'
15
+ require 'pingdom/client'
16
+ require 'pingdom/base'
17
+ require 'pingdom/base'
18
+ require 'pingdom/check'
19
+ require 'pingdom/result'
20
+ require 'pingdom/probe'
21
+ require 'pingdom/contact'
22
+ require 'pingdom/summary'
23
+ require 'pingdom/summary/average'
24
+ require 'pingdom/summary/outage'
25
+ require 'pingdom/summary/performance'
@@ -0,0 +1,8 @@
1
+ module Pingdom
2
+
3
+ VERSION = '0.0.2.alpha'
4
+
5
+ class Error < RuntimeError
6
+ end
7
+
8
+ end
@@ -0,0 +1,54 @@
1
+ module Pingdom
2
+ class Base
3
+
4
+ def initialize(client, response, attributes = {})
5
+ @client = client
6
+ @response = response
7
+ @attributes = attributes
8
+ end
9
+
10
+ def self.attributes(hash)
11
+ hash.each do |(attribute, aliases)|
12
+ class_eval <<-"end;" unless instance_methods.include?(attribute.to_s)
13
+ def #{attribute}
14
+ @attributes[:#{attribute}]
15
+ end
16
+ end;
17
+
18
+ Array.wrap(aliases).each do |aliased|
19
+ alias_method aliased, attribute
20
+ end
21
+ end
22
+ end
23
+
24
+ def method_missing(name, *args, &block)
25
+ @attributes[name] or super
26
+ end
27
+
28
+ def respond_to?(name)
29
+ super(name) || @attributes.key?(name)
30
+ end
31
+
32
+ def id
33
+ @attributes[:id]
34
+ end
35
+
36
+ def inspect
37
+ "#<%s %s>" % [self.class.to_s, @attributes.inject([]){ |a, (k,v)| a << "%s: %s" % [k,v.inspect]; a }.join(' ')]
38
+ end
39
+
40
+ def self.check_error!(response)
41
+ if response.body.key?(:error)
42
+ raise Error, "%s (%s %s)" % [ response.body[:error][:errormessage],
43
+ response.body[:error][:statuscode],
44
+ response.body[:error][:statusdesc] ]
45
+ end
46
+ end
47
+
48
+ def self.parse(client, response)
49
+ check_error!(response)
50
+ response.body
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,33 @@
1
+ module Pingdom
2
+
3
+ # {"name"=>"Autocomplete", "id"=>259103, "type"=>"http", "lastresponsetime"=>203173, "status"=>"up", "lasttesttime"=>1298102416}
4
+ class Check < Base
5
+ def self.parse(client, response)
6
+ super[:checks].map do |check|
7
+ new(client, response, check)
8
+ end
9
+ end
10
+
11
+ attributes :lastresponsetime => :last_response_time,
12
+ :lasttesttime => :last_test_time,
13
+ :lasterrortime => :last_error_time
14
+
15
+ def results(options = {})
16
+ @client.results(id, options)
17
+ end
18
+
19
+ def summary
20
+ @client.summary(id)
21
+ end
22
+
23
+ def lasttesttime
24
+ Time.at(super)
25
+ end
26
+
27
+ def lasterrortime
28
+ Time.at(super)
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,85 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'pingdom-client') unless defined? Pingdom
2
+
3
+ module Pingdom
4
+ class Client
5
+
6
+ attr_accessor :limit
7
+
8
+ def initialize(credentials = {})
9
+ @connection = Faraday::Connection.new(:url => "https://api/pingdom.com/api/2.0/") do |builder|
10
+ builder.url_prefix = "https://api.pingdom.com/api/2.0"
11
+
12
+ builder.adapter :logger
13
+
14
+ builder.adapter :excon
15
+
16
+ # builder.use Gzip # TODO: write GZip response handler, add Accept-Encoding: gzip header
17
+ builder.response :yajl
18
+ builder.use Tinder::FaradayResponse::WithIndifferentAccess
19
+
20
+ builder.basic_auth credentials[:username], credentials[:password]
21
+ end
22
+ end
23
+
24
+ # probes => [1,2,3] #=> probes => "1,2,3"
25
+ def prepare_params(options)
26
+ options.each do |(key, value)|
27
+ options[key] = Array.wrap(value).map(&:to_s).join(',')
28
+ options[key] = value.to_i if value.acts_like?(:time)
29
+ end
30
+
31
+ options
32
+ end
33
+
34
+ def get(uri, params = {}, &block)
35
+ response = @connection.get(@connection.build_url(uri, prepare_params(params)), &block)
36
+ update_limits!(response.headers['req-limit-short'], response.headers['req-limit-long'])
37
+ response
38
+ end
39
+
40
+ def update_limits!(short, long)
41
+ @limit ||= {}
42
+ @limit[:short] = parse_limit(short)
43
+ @limit[:long] = parse_limit(long)
44
+ @limit
45
+ end
46
+
47
+ # "Remaining: 394 Time until reset: 3589"
48
+ def parse_limit(limit)
49
+ if limit.to_s =~ /Remaining: (\d+) Time until reset: (\d+)/
50
+ { :remaining => $1.to_i,
51
+ :resets_at => $2.to_i.seconds.from_now }
52
+ end
53
+ end
54
+
55
+ def test!(options = {})
56
+ Result.parse(self, get("single", options)).first
57
+ end
58
+
59
+ def checks(options = {})
60
+ Check.parse(self, get("checks", options))
61
+ end
62
+ def check(id)
63
+ Check.parse(self, get("checks/#{id}"))
64
+ end
65
+
66
+ # Check ID
67
+ def results(id, options = {})
68
+ options.reverse_merge!(:includeanalysis => true)
69
+ Result.parse(self, get("results/#{id}", options))
70
+ end
71
+
72
+ def probes(options = {})
73
+ Probe.parse(self, get("probes", options))
74
+ end
75
+
76
+ def contacts(options = {})
77
+ Contact.parse(self, get("contacts", options))
78
+ end
79
+
80
+ def summary(id)
81
+ Summary.proxy(self, id)
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,16 @@
1
+ module Pingdom
2
+
3
+ # {"name"=>"Larry Bernstein", "directtwitter"=>false, "id"=>142762, "cellphone"=>"1-510-501-7401",
4
+ # "paused"=>false, "defaultsmsprovider"=>"clickatell", "email"=>"lbernstein@demandbase.com"}
5
+ class Contact < Base
6
+ def self.parse(client, response)
7
+ super[:contacts].map do |contact|
8
+ new(client, response, contact)
9
+ end
10
+ end
11
+
12
+ attributes :cellphone => :phone
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,20 @@
1
+ module Pingdom
2
+
3
+ # {"city"=>"Manchester", "name"=>"Manchester, UK", "country"=>"United Kingdom",
4
+ # "countryiso"=>"GB", "id"=>46, "ip"=>"212.84.74.156", "hostname"=>"s424.pingdom.com", "active"=>true}
5
+ class Probe < Base
6
+ def self.parse(client, response)
7
+ super[:probes].map do |probe|
8
+ new(client, response, probe)
9
+ end
10
+ end
11
+
12
+ attributes :countryiso => [:country_iso, :country_code]
13
+
14
+ def test!(options)
15
+ @client.test!(options.merge(:probeid => id))
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,20 @@
1
+ module Pingdom
2
+
3
+ # {"statusdesclong"=>"OK", "probeid"=>28, "responsetime"=>221, "statusdesc"=>"OK", "status"=>"up", "probedesc"=>"Amsterdam 2, Netherlands"}
4
+ class Result < Base
5
+ def self.parse(client, response)
6
+ results = super
7
+ Array.wrap(results[:results] || results[:result]).map do |result|
8
+ new(client, response, result)
9
+ end
10
+ end
11
+
12
+ attributes :responsetime => :response_time,
13
+ :probeid => :probe_id
14
+
15
+ def probe
16
+ @client.probes.detect{ |probe| probe.id == probe_id }
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,44 @@
1
+ module Pingdom
2
+
3
+ class Summary < Base
4
+
5
+ class Proxy < Struct.new(:client, :check_id)
6
+ def average(options = {})
7
+ options.reverse_merge!(:byprobe => true, :includeuptime => true)
8
+ Average.parse(client, client.get("summary.average/#{check_id}", options))
9
+ end
10
+ alias_method :averages, :average
11
+
12
+ def outage(options = {})
13
+ options.reverse_merge!(:byprobe => true, :includeuptime => true)
14
+ Outage.parse(client, client.get("summary.outage/#{check_id}", options))
15
+ end
16
+ alias_method :outages, :outage
17
+
18
+ def performance(options = {})
19
+ options.reverse_merge!(:resolution => :day, :includeuptime => true)
20
+ Performance.parse(client, client.get("summary.performance/#{check_id}", options))
21
+ end
22
+ end
23
+
24
+ def self.proxy(client, check)
25
+ Proxy.new(client, check)
26
+ end
27
+
28
+ def from
29
+ Time.at(@attributes[:from])
30
+ end
31
+
32
+ def to
33
+ Time.at(@attributes[:to])
34
+ end
35
+
36
+ attributes :responsetime => :response_time
37
+
38
+ # {"status"=>{"totalup"=>5035757, "totalunknown"=>1293069551, "totaldown"=>5078}}
39
+ class Status < Base
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,47 @@
1
+ module Pingdom
2
+ class Summary
3
+
4
+ # summary.average includeuptime probes=34,35 byprobe
5
+ # { "responsetime"=>{
6
+ # "from"=>0, "to"=>1298110456, "probes"=>"34, 35", "avgresponse"=>[
7
+ # {"probeid"=>35, "avgresponse"=>94},
8
+ # {"probeid"=>34, "avgresponse"=>125} ]},
9
+ # "status"=>{"totalup"=>5035757, "totalunknown"=>1293069551, "totaldown"=>5078}}
10
+ class Average < Base
11
+ def self.parse(client, response)
12
+ body = super[:summary]
13
+ sum = body[:responsetime]
14
+ attrs = sum.slice(:from, :to)
15
+ attrs[:probes] = (attrs[:probes] || "").gsub(/\w+/, '').split(',').map{|e| e.to_i }
16
+
17
+ sum[:status] = Status.new(client, response, body[:status]) if body.key?(:status)
18
+
19
+ case sum[:avgresponse]
20
+ when Array
21
+ sum[:responsetime] = 0
22
+ sum[:averages] =
23
+ sum.delete(:avgresponse).map do |avg|
24
+ sum[:responsetime] += avg[:avgresponse]
25
+ new(client, response, avg)
26
+ end
27
+ sum[:responsetime] = sum[:responsetime] / sum[:averages].size if sum[:averages].size > 0
28
+
29
+ when Integer
30
+ sum[:responsetime] = sum.delete(:avgresponse)
31
+
32
+ end
33
+
34
+ sum = Summary.new(client, response, sum)
35
+ end
36
+
37
+ attributes :probeid => :probe_id,
38
+ :responsetime => :response_time
39
+
40
+ def probe
41
+ @client.probes.detect{ |probe| probe.id == probe_id }
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,35 @@
1
+ module Pingdom
2
+ class Summary
3
+
4
+ # summary.outage
5
+ # {"states"=>[{"timeto"=>1297587576, "timefrom"=>1297475316, "status"=>"up"},
6
+ # {"timeto"=>1297587906, "timefrom"=>1297587576, "status"=>"down"},
7
+ # {"timeto"=>1298110749, "timefrom"=>1297587906, "status"=>"up"}]}
8
+ class Outage < Base
9
+ def self.parse(client, response)
10
+ super[:summary][:states].
11
+ select{ |s| s[:status] == "down" }.
12
+ map do |outage|
13
+ new(client, response, outage)
14
+ end
15
+ end
16
+
17
+ def downtime
18
+ (@attributes[:timeto] - @attributes[:timefrom]).seconds
19
+ end
20
+
21
+ def timefrom
22
+ Time.at(@attributes[:timefrom])
23
+ end
24
+
25
+ def timeto
26
+ Time.at(@attributes[:timeto])
27
+ end
28
+
29
+ attributes :timefrom => [:time_from, :from],
30
+ :timeto => [:time_to, :to,]
31
+
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,65 @@
1
+ module Pingdom
2
+ class Summary
3
+
4
+ # summary.performance includeuptime resolution=day
5
+ # {"days"=>[{"unmonitored"=>0, "downtime"=>0, "starttime"=>1297238400, "uptime"=>86400, "avgresponse"=>234},
6
+ # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1297324800, "uptime"=>86400, "avgresponse"=>215},
7
+ # {"unmonitored"=>0, "downtime"=>2648, "starttime"=>1297411200, "uptime"=>83752, "avgresponse"=>211},
8
+ # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1297497600, "uptime"=>86400, "avgresponse"=>207},
9
+ # {"unmonitored"=>0, "downtime"=>330, "starttime"=>1297584000, "uptime"=>86070, "avgresponse"=>228},
10
+ # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1297670400, "uptime"=>86400, "avgresponse"=>236},
11
+ # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1297756800, "uptime"=>86400, "avgresponse"=>230},
12
+ # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1297843200, "uptime"=>86400, "avgresponse"=>256},
13
+ # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1297929600, "uptime"=>86400, "avgresponse"=>216},
14
+ # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1298016000, "uptime"=>86400, "avgresponse"=>251},
15
+ # {"unmonitored"=>0, "downtime"=>0, "starttime"=>1298102400, "uptime"=>8646, "avgresponse"=>223}]}
16
+ class Performance < Base
17
+ INTERVALS = {
18
+ "hour" => 1.hour,
19
+ "day" => 1.day,
20
+ "week" => 1.week
21
+ }
22
+
23
+ def self.parse(client, response)
24
+ body = super[:summary]
25
+ interval = body.keys.detect{ |k| INTERVALS.keys.include?(k.chomp('s').to_s) }.chomp('s').to_sym
26
+ intervals = body[interval]
27
+
28
+ intervals.map do |perf|
29
+ perf[:interval] = interval
30
+ new(client, response, perf)
31
+ end
32
+ end
33
+
34
+ def starttime
35
+ Time.at(@attributes[:starttime])
36
+ end
37
+ alias_method :start_at, :starttime
38
+
39
+ def endtime
40
+ starttime + INTERVALS[interval.to_s].to_i
41
+ end
42
+ alias_method :end_at, :endtime
43
+
44
+ def uptime
45
+ @attributes[:uptime].seconds
46
+ end
47
+ def downtime
48
+ @attributes[:downtime].seconds
49
+ end
50
+ def unmonitored
51
+ @attributes[:unmonitored].seconds
52
+ end
53
+ def monitored
54
+ uptime + downtime
55
+ end
56
+ def period
57
+ monitored + unmonitored
58
+ end
59
+
60
+ attributes :avgresponse => :response_time
61
+
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,56 @@
1
+ # Taken from:
2
+ # https://github.com/collectiveidea/tinder/raw/master/lib/tinder/middleware.rb
3
+ # See:
4
+ # https://github.com/collectiveidea/tinder/blob/master/MIT-LICENSE
5
+ #
6
+ # Copyright (c) 2006-2010 Brandon Keepers, Collective Idea
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining
9
+ # a copy of this software and associated documentation files (the
10
+ # "Software"), to deal in the Software without restriction, including
11
+ # without limitation the rights to use, copy, modify, merge, publish,
12
+ # distribute, sublicense, and/or sell copies of the Software, and to
13
+ # permit persons to whom the Software is furnished to do so, subject to
14
+ # the following conditions:
15
+ #
16
+ # The above copyright notice and this permission notice shall be
17
+ # included in all copies or substantial portions of the Software.
18
+ #
19
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOa AND
22
+ # NONINFRINGEMENT. IN NO EVENT SaALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ #
27
+ module Tinder
28
+ module FaradayResponse
29
+ class WithIndifferentAccess < ::Faraday::Response::Middleware
30
+ begin
31
+ require 'active_support/core_ext/hash/indifferent_access'
32
+ rescue LoadError, NameError => error
33
+ self.load_error = error
34
+ end
35
+
36
+ def self.register_on_complete(env)
37
+ env[:response].on_complete do |response|
38
+ json = response[:body]
39
+ if json.is_a?(Hash)
40
+ response[:body] = ::HashWithIndifferentAccess.new(json)
41
+ elsif json.is_a?(Array) and json.first.is_a?(Hash)
42
+ response[:body] = json.map{|item| ::HashWithIndifferentAccess.new(item) }
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ class RaiseOnAuthenticationFailure < ::Faraday::Response::Middleware
49
+ def self.register_on_complete(env)
50
+ env[:response].on_complete do |response|
51
+ raise AuthenticationFailed if response[:status] == 401
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = %q{pingdom-client}
3
- s.version = "0.0.1.alpha"
3
+ s.version = "0.0.2.alpha"
4
4
 
5
5
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
6
  s.authors = ["Matt Todd"]
@@ -11,7 +11,19 @@ Gem::Specification.new do |s|
11
11
  "pingdom-client.gemspec",
12
12
  "Gemfile",
13
13
  "Gemfile.lock",
14
+ "lib/pingdom/base.rb",
15
+ "lib/pingdom/check.rb",
16
+ "lib/pingdom/client.rb",
17
+ "lib/pingdom/contact.rb",
18
+ "lib/pingdom/probe.rb",
19
+ "lib/pingdom/result.rb",
20
+ "lib/pingdom/summary/average.rb",
21
+ "lib/pingdom/summary/outage.rb",
22
+ "lib/pingdom/summary/performance.rb",
23
+ "lib/pingdom/summary.rb",
14
24
  "lib/pingdom-client.rb",
25
+ "lib/pingdom.rb",
26
+ "lib/tinder/faraday_response.rb",
15
27
  "Rakefile",
16
28
  "Readme.md",
17
29
  "spec/pingdom-client_spec.rb",
@@ -32,7 +44,7 @@ Gem::Specification.new do |s|
32
44
  s.specification_version = 3
33
45
 
34
46
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
35
- s.add_runtime_dependency("faraday", ["~> 0.5.6"])
47
+ s.add_runtime_dependency("faraday", ["~> 0.5.7"])
36
48
  s.add_runtime_dependency("excon", ["~> 0.5.6"])
37
49
  s.add_runtime_dependency("yajl-ruby", ["~> 0.8.1"])
38
50
  s.add_runtime_dependency("activesupport", ["~> 3.0.4"])
@@ -42,7 +54,7 @@ Gem::Specification.new do |s|
42
54
  s.add_development_dependency("rake", ["~> 0.8.7"])
43
55
  s.add_development_dependency("rspec", ["= 2.1.0"])
44
56
  else
45
- s.add_dependency("faraday", ["~> 0.5.6"])
57
+ s.add_dependency("faraday", ["~> 0.5.7"])
46
58
  s.add_dependency("excon", ["~> 0.5.6"])
47
59
  s.add_dependency("yajl-ruby", ["~> 0.8.1"])
48
60
  s.add_dependency("activesupport", ["~> 3.0.4"])
@@ -53,7 +65,7 @@ Gem::Specification.new do |s|
53
65
  s.add_dependency("rspec", ["= 2.1.0"])
54
66
  end
55
67
  else
56
- s.add_dependency("faraday", ["~> 0.5.6"])
68
+ s.add_dependency("faraday", ["~> 0.5.7"])
57
69
  s.add_dependency("excon", ["~> 0.5.6"])
58
70
  s.add_dependency("yajl-ruby", ["~> 0.8.1"])
59
71
  s.add_dependency("activesupport", ["~> 3.0.4"])
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pingdom-client
3
3
  version: !ruby/object:Gem::Version
4
- hash: -1851332166
4
+ hash: -1851332170
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
9
+ - 2
10
10
  - alpha
11
- version: 0.0.1.alpha
11
+ version: 0.0.2.alpha
12
12
  platform: ruby
13
13
  authors:
14
14
  - Matt Todd
@@ -27,12 +27,12 @@ dependencies:
27
27
  requirements:
28
28
  - - ~>
29
29
  - !ruby/object:Gem::Version
30
- hash: 7
30
+ hash: 5
31
31
  segments:
32
32
  - 0
33
33
  - 5
34
- - 6
35
- version: 0.5.6
34
+ - 7
35
+ version: 0.5.7
36
36
  type: :runtime
37
37
  version_requirements: *id001
38
38
  - !ruby/object:Gem::Dependency
@@ -159,7 +159,19 @@ files:
159
159
  - pingdom-client.gemspec
160
160
  - Gemfile
161
161
  - Gemfile.lock
162
+ - lib/pingdom/base.rb
163
+ - lib/pingdom/check.rb
164
+ - lib/pingdom/client.rb
165
+ - lib/pingdom/contact.rb
166
+ - lib/pingdom/probe.rb
167
+ - lib/pingdom/result.rb
168
+ - lib/pingdom/summary/average.rb
169
+ - lib/pingdom/summary/outage.rb
170
+ - lib/pingdom/summary/performance.rb
171
+ - lib/pingdom/summary.rb
162
172
  - lib/pingdom-client.rb
173
+ - lib/pingdom.rb
174
+ - lib/tinder/faraday_response.rb
163
175
  - Rakefile
164
176
  - Readme.md
165
177
  - spec/pingdom-client_spec.rb