wavefront-client 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +5 -0
- data/.ruby-version +1 -0
- data/.travis.yml +17 -0
- data/Gemfile +2 -0
- data/LICENSE +202 -0
- data/NOTICE +12 -0
- data/README.md +156 -0
- data/Rakefile +28 -0
- data/bin/wavefront-client +57 -0
- data/lib/wavefront/alerting.rb +57 -0
- data/lib/wavefront/client.rb +70 -0
- data/lib/wavefront/client/constants.rb +17 -0
- data/lib/wavefront/client/version.rb +21 -0
- data/lib/wavefront/events.rb +68 -0
- data/lib/wavefront/exception.rb +27 -0
- data/lib/wavefront/metadata.rb +90 -0
- data/lib/wavefront/response.rb +93 -0
- data/lib/wavefront/writer.rb +55 -0
- data/spec/example_response.json +1 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/wavefront/client_spec.rb +47 -0
- data/spec/wavefront/metadata_spec.rb +38 -0
- data/spec/wavefront/response_spec.rb +74 -0
- data/spec/wavefront/writer_spec.rb +94 -0
- data/wavefront-client.gemspec +46 -0
- metadata +150 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Copyright 2015 Wavefront Inc.
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require 'wavefront/client'
|
17
|
+
require 'slop'
|
18
|
+
|
19
|
+
@opts = Slop.parse(strict: true) do
|
20
|
+
banner 'Usage: wavefront-client QUERY (OPTIONS)'
|
21
|
+
on 'm', 'minutes', 'Query granularity of minutes'
|
22
|
+
on 'h', 'hours', 'Query granularity of hours'
|
23
|
+
on 'S', 'seconds', 'Query granularity of seconds'
|
24
|
+
on 's', 'start=', 'Time in UNIX epoch seconds to begin the query from'
|
25
|
+
on 't', 'token=', 'Wavefront authentication token'
|
26
|
+
on 'e', 'end=', 'Time in UNIX epoch seconds to query to'
|
27
|
+
on 'h', 'help', 'Display this message'
|
28
|
+
end
|
29
|
+
|
30
|
+
if @opts.help?
|
31
|
+
puts @opts
|
32
|
+
exit 0
|
33
|
+
end
|
34
|
+
|
35
|
+
query = ARGV[0]
|
36
|
+
if @opts.minutes?
|
37
|
+
granularity = 'm'
|
38
|
+
elsif @opts.hours?
|
39
|
+
granularity = 'h'
|
40
|
+
elsif @opts.seconds?
|
41
|
+
granularity = 's'
|
42
|
+
else
|
43
|
+
puts "You must specify a granularity of either --seconds, --minutes or --hours. See --help for more information."
|
44
|
+
exit 1
|
45
|
+
end
|
46
|
+
|
47
|
+
options = Hash.new
|
48
|
+
if @opts[:start]
|
49
|
+
options[:start_time] = @opts[:start]
|
50
|
+
end
|
51
|
+
|
52
|
+
if @opts[:end]
|
53
|
+
options[:end_time] = @opts[:end]
|
54
|
+
end
|
55
|
+
|
56
|
+
wave = Wavefront::Client.new(@opts[:token])
|
57
|
+
puts wave.query(query, granularity, options)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2015 Wavefront Inc.
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
14
|
+
|
15
|
+
=end
|
16
|
+
|
17
|
+
require "wavefront/client/version"
|
18
|
+
require "wavefront/exception"
|
19
|
+
require 'rest_client'
|
20
|
+
require 'uri'
|
21
|
+
require 'logger'
|
22
|
+
|
23
|
+
module Wavefront
|
24
|
+
class Alerting
|
25
|
+
DEFAULT_HOST = 'metrics.wavefront.com'
|
26
|
+
DEFAULT_PATH = '/api/alert/'
|
27
|
+
|
28
|
+
attr_reader :token
|
29
|
+
|
30
|
+
def initialize(token)
|
31
|
+
@token = token
|
32
|
+
end
|
33
|
+
|
34
|
+
def active(options={})
|
35
|
+
|
36
|
+
options[:host] ||= DEFAULT_HOST
|
37
|
+
options[:path] ||= DEFAULT_PATH
|
38
|
+
|
39
|
+
uri = URI::HTTPS.build(:host => options[:host], :path => options[:path])
|
40
|
+
uri = URI.join(uri.to_s,"active")
|
41
|
+
uri = URI.join(uri.to_s,"?t=#{@token}")
|
42
|
+
|
43
|
+
response = RestClient.get(uri.to_s)
|
44
|
+
|
45
|
+
return response
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def debug(enabled)
|
51
|
+
if enabled
|
52
|
+
RestClient.log = 'stdout'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2015 Wavefront Inc.
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
14
|
+
|
15
|
+
=end
|
16
|
+
|
17
|
+
require "wavefront/client/version"
|
18
|
+
require "wavefront/client/constants"
|
19
|
+
require "wavefront/exception"
|
20
|
+
require "wavefront/response"
|
21
|
+
require 'rest_client'
|
22
|
+
require 'uri'
|
23
|
+
require 'logger'
|
24
|
+
|
25
|
+
module Wavefront
|
26
|
+
class Client
|
27
|
+
DEFAULT_PERIOD_SECONDS = 600
|
28
|
+
DEFAULT_PATH = '/chart/api'
|
29
|
+
DEFAULT_FORMAT = :raw
|
30
|
+
FORMATS = [ :raw, :ruby, :graphite, :highcharts ]
|
31
|
+
GRANULARITIES = %w( s m h d )
|
32
|
+
|
33
|
+
attr_reader :headers, :base_uri
|
34
|
+
|
35
|
+
def initialize(token, host=DEFAULT_HOST, debug=false)
|
36
|
+
@headers = {'X-AUTH-TOKEN' => token}
|
37
|
+
@base_uri = URI::HTTPS.build(:host => host, :path => DEFAULT_PATH)
|
38
|
+
debug(debug)
|
39
|
+
end
|
40
|
+
|
41
|
+
def query(query, granularity='m', options={})
|
42
|
+
|
43
|
+
options[:end_time] ||= Time.now
|
44
|
+
options[:start_time] ||= options[:end_time] - DEFAULT_PERIOD_SECONDS
|
45
|
+
options[:response_format] ||= DEFAULT_FORMAT
|
46
|
+
|
47
|
+
[ options[:start_time], options[:end_time] ].each { |o| raise Wavefront::Exception::InvalidTimeFormat unless o.is_a?(Time) }
|
48
|
+
raise Wavefront::Exception::InvalidGranularity unless GRANULARITIES.include?(granularity)
|
49
|
+
raise Wavefront::Exception::InvalidResponseFormat unless FORMATS.include?(options[:response_format])
|
50
|
+
|
51
|
+
args = {:params =>
|
52
|
+
{:q => query, :g => granularity, :n => 'Unknown',
|
53
|
+
:s => options[:start_time].to_i, :e => options[:end_time].to_i}}.merge(@headers)
|
54
|
+
response = RestClient.get @base_uri.to_s, args
|
55
|
+
|
56
|
+
klass = Object.const_get('Wavefront').const_get('Response').const_get(options[:response_format].to_s.capitalize)
|
57
|
+
return klass.new(response)
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def debug(enabled)
|
64
|
+
if enabled
|
65
|
+
RestClient.log = 'stdout'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2015 Wavefront Inc.
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
14
|
+
|
15
|
+
=end
|
16
|
+
|
17
|
+
DEFAULT_HOST = 'metrics.wavefront.com'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2015 Wavefront Inc.
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
14
|
+
|
15
|
+
=end
|
16
|
+
|
17
|
+
module Wavefront
|
18
|
+
class Client
|
19
|
+
VERSION = "0.5.2"
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require_relative 'client/version'
|
2
|
+
require_relative 'exception'
|
3
|
+
require 'rest_client'
|
4
|
+
require 'uri'
|
5
|
+
require 'logger'
|
6
|
+
#
|
7
|
+
# Add basic support to cover Wavefront's events API. I have followed
|
8
|
+
# the standards and conventions established in the files already in
|
9
|
+
# this repository.
|
10
|
+
#
|
11
|
+
# R Fisher 07/2015
|
12
|
+
#
|
13
|
+
module Wavefront
|
14
|
+
#
|
15
|
+
# These methods expect to be called with a hash whose keys are as
|
16
|
+
# defined in the Wavefront API Console. That is, 'n' as 'name for
|
17
|
+
# the event', 's' as 'start time for the event' and so-on.
|
18
|
+
#
|
19
|
+
class Events
|
20
|
+
DEFAULT_HOST = 'metrics.wavefront.com'
|
21
|
+
DEFAULT_PATH = '/api/events/'
|
22
|
+
|
23
|
+
attr_reader :token
|
24
|
+
|
25
|
+
def initialize(token)
|
26
|
+
@token = token
|
27
|
+
end
|
28
|
+
|
29
|
+
def create(payload = {}, options = {})
|
30
|
+
options[:host] ||= DEFAULT_HOST
|
31
|
+
options[:path] ||= DEFAULT_PATH
|
32
|
+
|
33
|
+
uri = URI::HTTPS.build(
|
34
|
+
host: options[:host],
|
35
|
+
path: options[:path],
|
36
|
+
query: "t=#{@token}"
|
37
|
+
)
|
38
|
+
|
39
|
+
RestClient.post(uri.to_s, payload)
|
40
|
+
end
|
41
|
+
|
42
|
+
def close(payload = {}, options = {})
|
43
|
+
options[:host] ||= DEFAULT_HOST
|
44
|
+
options[:path] ||= DEFAULT_PATH
|
45
|
+
|
46
|
+
# This request seems to need the data as a query string. I was
|
47
|
+
# getting a 500 when I posted a hash. A map will do the
|
48
|
+
# needful.
|
49
|
+
|
50
|
+
uri = URI::HTTPS.build(
|
51
|
+
host: options[:host],
|
52
|
+
path: options[:path] + 'close',
|
53
|
+
query: URI.escape(
|
54
|
+
payload.map { |k, v| [k, v].join('=') }.join('&') + '&t=' + @token
|
55
|
+
)
|
56
|
+
)
|
57
|
+
puts uri.to_s
|
58
|
+
|
59
|
+
RestClient.post(uri.to_s, payload)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def debug(enabled)
|
65
|
+
RestClient.log = 'stdout' if enabled
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2015 Wavefront Inc.
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
14
|
+
|
15
|
+
=end
|
16
|
+
|
17
|
+
require "wavefront/client/version"
|
18
|
+
|
19
|
+
module Wavefront
|
20
|
+
class Exception
|
21
|
+
class InvalidTimeFormat < ::Exception; end
|
22
|
+
class InvalidGranularity < ::Exception; end
|
23
|
+
class InvaldResponseFormat < ::Exception; end
|
24
|
+
class EmptyMetricName < ::Exception; end
|
25
|
+
class NotImplemented < ::Exception; end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2015 Wavefront Inc.
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
14
|
+
|
15
|
+
=end
|
16
|
+
|
17
|
+
require "wavefront/client/version"
|
18
|
+
require "wavefront/client/constants"
|
19
|
+
require "wavefront/exception"
|
20
|
+
require 'rest_client'
|
21
|
+
require 'uri'
|
22
|
+
require 'logger'
|
23
|
+
|
24
|
+
module Wavefront
|
25
|
+
class Metadata
|
26
|
+
DEFAULT_PATH = '/api/manage/source/'
|
27
|
+
|
28
|
+
attr_reader :headers, :base_uri
|
29
|
+
|
30
|
+
def initialize(token, host=DEFAULT_HOST, debug=false)
|
31
|
+
@headers = {'X-AUTH-TOKEN' => token}
|
32
|
+
@base_uri = URI::HTTPS.build(:host => host, :path => DEFAULT_PATH)
|
33
|
+
debug(debug)
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_tags(hostname='')
|
37
|
+
uri = @base_uri
|
38
|
+
|
39
|
+
unless hostname.empty?
|
40
|
+
uri = URI.join(@base_uri.to_s, hostname)
|
41
|
+
end
|
42
|
+
|
43
|
+
begin
|
44
|
+
response = RestClient.get(uri.to_s, @headers)
|
45
|
+
rescue RestClient::ResourceNotFound
|
46
|
+
# If a 404 is returned, we return an empty JSON as this is the expected behaviour for untagged hosts
|
47
|
+
response = {}
|
48
|
+
end
|
49
|
+
|
50
|
+
return response
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_tags(hostnames, tags)
|
55
|
+
|
56
|
+
# Build and call tagging URI for each host and tag.
|
57
|
+
hostnames.each do |hostname|
|
58
|
+
host_uri = URI.join(@base_uri.to_s,"#{hostname}/")
|
59
|
+
extended_uri = URI.join(host_uri.to_s,"tags/")
|
60
|
+
tags.each do |tag|
|
61
|
+
final_uri = URI.join(extended_uri.to_s,tag)
|
62
|
+
RestClient.put(final_uri.to_s, {}, @headers)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
def remove_tags(hostnames, tags, options={})
|
69
|
+
|
70
|
+
hostnames.each do |hostname|
|
71
|
+
host_uri = URI.join(@base_uri.to_s,"#{hostname}/")
|
72
|
+
extended_uri = URI.join(host_uri.to_s,"tags/")
|
73
|
+
tags.each do |tag|
|
74
|
+
final_uri = URI.join(extended_uri.to_s,tag)
|
75
|
+
RestClient.delete(final_uri.to_s, @headers)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def debug(enabled)
|
84
|
+
if enabled
|
85
|
+
RestClient.log = 'stdout'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2015 Wavefront Inc.
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
14
|
+
|
15
|
+
=end
|
16
|
+
|
17
|
+
require 'wavefront/client/version'
|
18
|
+
require 'wavefront/exception'
|
19
|
+
require 'json'
|
20
|
+
|
21
|
+
module Wavefront
|
22
|
+
class Response
|
23
|
+
class Raw
|
24
|
+
attr_reader :response
|
25
|
+
|
26
|
+
def initialize(response)
|
27
|
+
@response = response
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
return @response
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
class Ruby
|
37
|
+
include JSON
|
38
|
+
attr_reader :response
|
39
|
+
|
40
|
+
def initialize(response)
|
41
|
+
@response = response
|
42
|
+
|
43
|
+
JSON.parse(response).each_pair do |k,v|
|
44
|
+
self.instance_variable_set("@#{k}", v) # Dynamically populate instance vars
|
45
|
+
self.class.__send__(:attr_reader, k) # and set accessors
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
class Graphite < Wavefront::Response::Ruby
|
52
|
+
attr_reader :response, :graphite
|
53
|
+
|
54
|
+
def initialize(response)
|
55
|
+
super
|
56
|
+
|
57
|
+
datapoints = Array.new
|
58
|
+
self.timeseries.each do |ts|
|
59
|
+
ts['data'].each do |d|
|
60
|
+
datapoints << [d[1], d[0]]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
@graphite = [{ 'target' => self.query, 'datapoints' => datapoints }]
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
class Highcharts < Wavefront::Response::Ruby
|
70
|
+
include JSON
|
71
|
+
attr_reader :response, :highcharts
|
72
|
+
|
73
|
+
def initialize(response)
|
74
|
+
super
|
75
|
+
|
76
|
+
@response = JSON.parse(response)
|
77
|
+
|
78
|
+
@highcharts = []
|
79
|
+
self.timeseries.each do |series|
|
80
|
+
# Highcharts expects the time in milliseconds since the epoch
|
81
|
+
# And for some reason the first value tends to be BS
|
82
|
+
|
83
|
+
@highcharts << { 'name' => series['label'], 'data' => series['data'][1..-1].map!{|x,y| [ x * 1000, y ]} }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_json
|
88
|
+
@highcharts.to_json
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|