circonus 2.1.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/examples/graph_data.rb +16 -0
- data/lib/circonus.rb +61 -1
- metadata +3 -3
- data/lib/circonus/values.rb +0 -159
@@ -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:
|
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-
|
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
|
data/lib/circonus/values.rb
DELETED
@@ -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=×=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
|
-
|