circonus 2.1.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
-