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.
- 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
|
-
|