wavefront-client 0.5.2
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.
- 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
|