circonus 2.1.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # Query Circonus data (uses official API not the one the javascript uses)
3
+ #
4
+
5
+ require 'rubygems'
6
+ require 'circonus'
7
+
8
+ require 'pp'
9
+ apikey="myapikey"
10
+ server="api.circonus.com"
11
+ appname="curl"
12
+ @c = Circonus.new(apikey,appname)
13
+ @c.set_server(server)
14
+ pp @a.get_graph_data('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa')
15
+
16
+
data/lib/circonus.rb CHANGED
@@ -152,11 +152,71 @@ class Circonus
152
152
  params['period'] = 300 unless params.has_key? 'period'
153
153
  params['type'] = 'numeric' unless params.has_key? 'type'
154
154
  url = @url_prefix + 'data' + '/' + CGI.escape(cid.to_s.split('/').last) + '_' + CGI::escape(metric)
155
- #puts "url=#{url}" if @debug
156
155
  headers = @headers.merge({:params => params})
157
156
  r,err = _rest('get',url, headers)
158
157
  return nil,err if r.nil?
159
158
  return Yajl::Parser.parse(r)
160
159
  end
160
+
161
+ def _data_formula(formula,data)
162
+ vals = []
163
+ formula = formula.clone
164
+ formula.tr!('^A-Za-z0-9/+.*_)(-','' ) # prevent injection
165
+ formula.tr!('A-Z','a-z')
166
+ formula.gsub!(/[a-z]+/) { |n| "var_#{n}" } # prevent clobbering of ruby keywords
167
+ data.each_with_index do |v,i|
168
+ res = eval "var_val=#{v[1]}\n#{formula}\n"
169
+ vals[i] = [v[0],res]
170
+ end
171
+ return vals
172
+ end
173
+
174
+ def _data_derive(data,datapoint)
175
+ derive = datapoint['derive']
176
+ derive = 'value' if derive == 'gauge'
177
+ data = data.map { |m| [m[0],(m[1] ? m[1][derive] : nil)] }
178
+ data = _data_formula(datapoint['data_formula'],data) if datapoint['data_formula']
179
+ return data
180
+ end
181
+
182
+ def _composite_formula(formula,graph)
183
+ formula = formula.clone
184
+ formula.tr!('^A-Za-z0-9/+.*_)(-','' ) # prevent injection
185
+ formula.tr!('A-Z','a-z')
186
+ formula.gsub!(/[a-z]+/) { |n| "var_#{n}" } # prevent clobbering of ruby keywords
187
+ dps = graph['datapoints']
188
+ ndps = dps.length
189
+ nvals = dps.first['data'].length
190
+ data = []
191
+ (0...nvals).each do |n|
192
+ evalstr = ""
193
+ ('a'..'zzzz').each_with_index do |x,i|
194
+ break if i == ndps
195
+ evalstr += "var_#{x}=#{dps[i]['data'][n].last.to_f.to_s}\n" # force an s->i->s conversion to prevent injection in the values
196
+ end
197
+ res = eval "#{evalstr}\n#{formula}\n"
198
+ data[n] = [dps.first['data'][n].first,res]
199
+ end
200
+ return data
201
+ end
202
+
203
+ # Get the range of data values from start to end time
204
+ # This calculates out the datapoints and composites using the formulas in each graph
205
+ # --TODO This is very slow at the moment.......
206
+ def get_graph_data(gid,t_start=nil,t_end=nil)
207
+ t_end ||= Time.new.to_i
208
+ t_start ||= (t_end - 600)
209
+ g = get_graph(gid)
210
+ params = {'end'=>t_end.to_i,'start'=>t_start.to_i}
211
+ g['datapoints'].each do |dp|
212
+ res = get_data(dp['check_id'],dp['metric_name'],params)
213
+ data = res['data']
214
+ dp['data'] = _data_derive(data,dp)
215
+ end
216
+ g['composites'].each do |cmp|
217
+ cmp['data'] = _composite_formula(cmp['data_formula'],g)
218
+ end
219
+ return g
220
+ end
161
221
  end
162
222
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: circonus
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 3.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: 2014-01-22 00:00:00.000000000 Z
12
+ date: 2014-01-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client
@@ -68,7 +68,6 @@ extensions: []
68
68
  extra_rdoc_files: []
69
69
  files:
70
70
  - lib/circonus.rb
71
- - lib/circonus/values.rb
72
71
  - bin/update_all_composites.rb
73
72
  - bin/circonus_list_checkbundle
74
73
  - bin/circonus-data-cli
@@ -83,6 +82,7 @@ files:
83
82
  - examples/add_nginx_graphs.rb
84
83
  - examples/util.rb
85
84
  - examples/cache_copy.rb
85
+ - examples/graph_data.rb
86
86
  - examples/add_http_check.rb
87
87
  - examples/add_apache_node.rb
88
88
  homepage: https://github.com/venturaville/circonus-api
@@ -1,159 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # Query Circonus data (used by the Circonus UI's javascript)
3
- # Notes:
4
- # - This is not the permanent API for this....
5
- #
6
- # Tue Oct 9 11:11:01 EDT 2012
7
- # -- David Nicklay
8
-
9
- require 'rubygems'
10
- require 'net/http' # necessarily evil ... rest-client won't return set-cookie values on 302s....
11
- require 'net/https'
12
- require 'pp'
13
- require 'cgi'
14
- require 'yajl'
15
-
16
-
17
- class Circonus
18
- class Values
19
- attr_accessor :raise_errors
20
- attr_accessor :debug
21
-
22
- def initialize(username,password,account='')
23
- @username = username
24
- @password = password
25
- @cookie = ''
26
- @debug = true
27
- @host = 'circonus.com'
28
- @login_host = "login.circonus.com"
29
- @account = account
30
- @data_host = "#{@account}.circonus.com"
31
- @raise_errors = false
32
- @data_prefix = "/json/graph/data/"
33
- @metrics_prefix = "/account/#{@account}/json/metrics/value"
34
-
35
- @headers = {
36
- "X-Circonus-Auth-Token" => @apitoken,
37
- "X-Circonus-App-Name" => @appname,
38
- "Accept" => 'application/json'
39
- }
40
- @url_prefix = "https://api.circonus.com/v2/"
41
- end
42
-
43
- # You need to call login before doing anything ... This gives us our session id
44
- def login()
45
- http = Net::HTTP.new(@login_host, 443)
46
- http.use_ssl = true
47
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
48
- path = '/login'
49
- headers = {
50
- 'Content-Type' => 'application/x-www-form-urlencoded'
51
- }
52
- data="login_username=#{CGI.escape @username}&login_password=#{CGI.escape @password}&login_remember=1&whereTo=https://#{@account}.circonus.com%2Flogin&&login_submit=Sign+In+%BB&welcome_submit=Sign+In+%BB"
53
-
54
- resp = http.post(path, data, headers)
55
- @cookie = resp.response['set-cookie'].split('; ')[0]
56
- return true
57
- end
58
-
59
- # Get the value of a particular metric name
60
- def metric_value(checkid,metric_name)
61
- http = Net::HTTP.new(@data_host, 443)
62
- http.use_ssl = true
63
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
64
- path = "#{@metrics_prefix}?check_id=#{CGI.escape checkid.to_s}&metric_name=#{CGI.escape metric_name}"
65
- headers = {
66
- 'Cookie' => @cookie,
67
- 'Accept' => 'application/application/json, text/javascript, */*; q=0.01'
68
- }
69
- resp = http.get(path, headers)
70
- return Yajl::Parser.parse(resp.body)
71
- end
72
-
73
- # Get the range of data values from start to end time (t_start and t_end should be Time class vars)
74
- def graph_data(uuid,t_start=nil,t_end=nil)
75
- http = Net::HTTP.new(@data_host, 443)
76
- http.use_ssl = true
77
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
78
- # set sane defaults
79
- t_end = Time.new if t_end.nil?
80
- t_start = (t_end - 300) if t_start.nil?
81
- # convert to strings
82
- s_t_mid = (t_start + ((t_end - t_start) / 2)).strftime('%s')
83
- s_t_start = t_start.strftime('%s')
84
- s_t_end = t_end.strftime('%s')
85
- uuid = uuid.split('/').last # make sure we don't have /graph in the id....
86
- path = "#{@data_prefix}#{uuid}?start=#{s_t_start}000&end=#{s_t_end}000cnt=&type=&times=epoch_ms&_=#{s_t_mid}000"
87
- headers = {
88
- 'Cookie' => @cookie,
89
- 'Accept' => 'application/application/json, text/javascript, */*; q=0.01'
90
- }
91
- resp = http.get(path, headers)
92
- return Yajl::Parser.parse(resp.body)
93
- end
94
-
95
- # Convenience function ... get the last graph data points
96
- # (We use 300 seconds to make sure we at least have something....)
97
- def last_graph_data(uuid)
98
- t = Time.new
99
- return graph_data(uuid,t - 300, t)
100
- end
101
-
102
- # Find the first valid data point in our set
103
- def _first_valid_datapoint(data)
104
- return nil if data.nil? or not data.any?
105
- begin
106
- data.reverse.select { |s| not s[1].nil? }.first[1]
107
- rescue Exception => e
108
- return nil
109
- end
110
- end
111
-
112
- # Get the sum of the last valid graph point
113
- def total_last_graph_data(uuid)
114
- data = last_graph_data(uuid)
115
- sum = 0
116
- data['data'].each do |d|
117
- next unless d['metric_type'] == 'numeric'
118
- sum += _first_valid_datapoint(d['data']).to_f
119
- end
120
- return sum
121
- end
122
-
123
- def eval_formula(formula,values=[])
124
- formula = formula.clone
125
- formula.tr!('^A-Za-z0-9/+.*_)(-','' ) # prevent injection
126
- formula.tr!('A-Z','a-z')
127
- formula.gsub!(/[a-z]+/) { |n| "var_#{n}" } # prevent clobbering of ruby keywords
128
- evalstr = ""
129
- ('a'..'zzzz').each_with_index do |x,i|
130
- break if i == values.length
131
- evalstr += "var_#{x}=#{values[i].to_f.to_s}\n" # force an s->i->s conversion to prevent injection in the values
132
- end
133
- results = eval "#{evalstr}\n#{formula}\n"
134
- end
135
-
136
- def eval_composite(composite,values)
137
- return eval_formula(composite['reconnoiter_source_expression'],values)
138
- end
139
-
140
- def eval_composites(uuid)
141
- data = last_graph_data(uuid)
142
- values = []
143
- composites = []
144
- data['data'].each do |d|
145
- if d['metric_type'] == 'numeric'
146
- values << _first_valid_datapoint(d['data']).to_f
147
- elsif d['metric_type'] == 'composite'
148
- composites << d
149
- end
150
- end
151
- composites.each do |composite|
152
- composite['result'] = eval_composite(composite,values)
153
- end
154
- return composites
155
- end
156
-
157
- end
158
- end
159
-