wavefront-sdk 1.6.0 → 1.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -2
- data/HISTORY.md +11 -0
- data/lib/wavefront-sdk/base.rb +31 -46
- data/lib/wavefront-sdk/base_write.rb +28 -29
- data/lib/wavefront-sdk/event.rb +11 -7
- data/lib/wavefront-sdk/exception.rb +1 -0
- data/lib/wavefront-sdk/externallink.rb +2 -1
- data/lib/wavefront-sdk/logger.rb +65 -0
- data/lib/wavefront-sdk/metric.rb +5 -6
- data/lib/wavefront-sdk/mixins.rb +16 -5
- data/lib/wavefront-sdk/response.rb +36 -25
- data/lib/wavefront-sdk/search.rb +2 -2
- data/lib/wavefront-sdk/stdlib/hash.rb +6 -1
- data/lib/wavefront-sdk/validators.rb +123 -115
- data/lib/wavefront-sdk/version.rb +1 -1
- data/lib/wavefront-sdk/write.rb +0 -1
- data/spec/wavefront-sdk/base_write_spec.rb +82 -0
- data/spec/wavefront-sdk/logger_spec.rb +62 -0
- data/spec/wavefront-sdk/mixins_spec.rb +17 -0
- data/spec/wavefront-sdk/resources/dummy_points.rb +20 -0
- data/spec/wavefront-sdk/write_spec.rb +3 -79
- data/wavefront-sdk.gemspec +1 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e599fd70e3a67cdc62c8ec942382db101850582e8bd98c11e8e56e18a1d1bfaf
|
4
|
+
data.tar.gz: 134f436ff650ba75a4cad1e93bcf229ea25787dbafa5fcf40aa93b067bed9402
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f051f1594d486c3b6c65ed964a0e2b822a034975a19ad9745926048e891ce5a8f89a063a17532ff8a90b3b1c89085ba448d57346dff33b6300765bd3f365b3e
|
7
|
+
data.tar.gz: 0a97bf0ed08c8ee08607b4e98f55cc5daeb7b30e6245df99407c0dddfb708ed093bbaeb3d9aaac805d09da12ca61cccdd94c96222458545bc7857d536d43002e
|
data/.rubocop.yml
CHANGED
@@ -1,8 +1,15 @@
|
|
1
|
+
---
|
1
2
|
AllCops:
|
2
|
-
TargetRubyVersion: 2.
|
3
|
+
TargetRubyVersion: 2.2
|
3
4
|
|
4
5
|
Style/FrozenStringLiteralComment:
|
5
6
|
Enabled: false
|
6
7
|
|
7
|
-
|
8
|
+
Style/FormatStringToken:
|
8
9
|
Enabled: false
|
10
|
+
|
11
|
+
Metrics/ClassLength:
|
12
|
+
Enabled: false
|
13
|
+
|
14
|
+
Metrics/MethodLength:
|
15
|
+
Max: 13
|
data/HISTORY.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.6.1 (22/08/2018)
|
4
|
+
|
5
|
+
* Fix Ruby 2.2 bugs
|
6
|
+
* Improve unit test separation
|
7
|
+
* Allow updating of all external link parameters
|
8
|
+
|
9
|
+
## 1.6.0 (07/08/2018)
|
10
|
+
* Improve validation of point tags.
|
11
|
+
* Break extensions to standard library out into their own files.
|
12
|
+
* Improve README.
|
13
|
+
|
3
14
|
## 1.5.0 (25/06/2018)
|
4
15
|
|
5
16
|
* Add [derived
|
data/lib/wavefront-sdk/base.rb
CHANGED
@@ -4,6 +4,7 @@ require 'faraday'
|
|
4
4
|
require 'pp'
|
5
5
|
require 'ostruct'
|
6
6
|
require 'addressable'
|
7
|
+
require_relative 'logger'
|
7
8
|
require_relative 'exception'
|
8
9
|
require_relative 'mixins'
|
9
10
|
require_relative 'response'
|
@@ -18,12 +19,11 @@ module Wavefront
|
|
18
19
|
#
|
19
20
|
# @return a Wavefront::Response object
|
20
21
|
#
|
21
|
-
# rubocop:disable Metrics/ClassLength
|
22
22
|
class Base
|
23
23
|
include Wavefront::Validators
|
24
24
|
include Wavefront::Mixins
|
25
|
-
attr_reader :opts, :debug, :noop, :verbose, :net, :conn,
|
26
|
-
:logger
|
25
|
+
attr_reader :opts, :debug, :noop, :verbose, :net, :conn,
|
26
|
+
:update_keys, :logger
|
27
27
|
|
28
28
|
# Create a new API object. This will always be called from a
|
29
29
|
# class which inherits this one. If the inheriting class defines
|
@@ -44,16 +44,19 @@ module Wavefront
|
|
44
44
|
# @return [Nil]
|
45
45
|
#
|
46
46
|
def initialize(creds = {}, opts = {})
|
47
|
-
@opts
|
48
|
-
@debug
|
49
|
-
@noop
|
47
|
+
@opts = opts
|
48
|
+
@debug = opts[:debug] || false
|
49
|
+
@noop = opts[:noop] || false
|
50
50
|
@verbose = opts[:verbose] || false
|
51
|
-
@logger
|
51
|
+
@logger = Wavefront::Logger.new(opts)
|
52
52
|
setup_endpoint(creds)
|
53
|
-
|
54
53
|
post_initialize(creds, opts) if respond_to?(:post_initialize)
|
55
54
|
end
|
56
55
|
|
56
|
+
def log(message, severity = :info)
|
57
|
+
logger.log(message, severity)
|
58
|
+
end
|
59
|
+
|
57
60
|
# Convert an epoch timestamp into epoch milliseconds. If the
|
58
61
|
# timestamp looks like it's already epoch milliseconds, return
|
59
62
|
# it as-is.
|
@@ -85,16 +88,15 @@ module Wavefront
|
|
85
88
|
# @return [URI::HTTPS]
|
86
89
|
#
|
87
90
|
def mk_conn(path, headers = {})
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
)
|
91
|
+
url = format('https://%s%s', net[:endpoint], [net[:api_base],
|
92
|
+
path].uri_concat)
|
93
|
+
Faraday.new(url: Addressable::URI.encode(url),
|
94
|
+
headers: net[:headers].merge(headers))
|
93
95
|
end
|
94
96
|
|
95
97
|
# Make a GET call to the Wavefront API and return the result as
|
96
98
|
# a Ruby hash. Can optionally perform a verbose noop, if the
|
97
|
-
#
|
99
|
+
# @noop class variable is set. If @verbose is set, then prints
|
98
100
|
# the information used to build the URI.
|
99
101
|
#
|
100
102
|
# @param path [String] path to be appended to the
|
@@ -109,7 +111,7 @@ module Wavefront
|
|
109
111
|
|
110
112
|
# Make a POST call to the Wavefront API and return the result as
|
111
113
|
# a Ruby hash. Can optionally perform a verbose noop, if the
|
112
|
-
#
|
114
|
+
# @noop class variable is set. If @verbose is set, then prints
|
113
115
|
# the information used to build the URI.
|
114
116
|
#
|
115
117
|
# @param path [String] path to be appended to the
|
@@ -127,7 +129,7 @@ module Wavefront
|
|
127
129
|
|
128
130
|
# Make a PUT call to the Wavefront API and return the result as
|
129
131
|
# a Ruby hash. Can optionally perform a verbose noop, if the
|
130
|
-
#
|
132
|
+
# @noop class variable is set. If @verbose is set, then prints
|
131
133
|
# the information used to build the URI.
|
132
134
|
#
|
133
135
|
# @param path [String] path to be appended to the
|
@@ -144,7 +146,7 @@ module Wavefront
|
|
144
146
|
|
145
147
|
# Make a DELETE call to the Wavefront API and return the result
|
146
148
|
# as a Ruby hash. Can optionally perform a verbose noop, if the
|
147
|
-
#
|
149
|
+
# @noop class variable is set. If @verbose is set, then prints
|
148
150
|
# the information used to build the URI.
|
149
151
|
#
|
150
152
|
# @param path [String] path to be appended to the
|
@@ -173,30 +175,6 @@ module Wavefront
|
|
173
175
|
end
|
174
176
|
end
|
175
177
|
|
176
|
-
# Send a message to a Ruby logger object if the user supplied
|
177
|
-
# one, or print to standard out if not.
|
178
|
-
#
|
179
|
-
# @param msg [String] the string to print
|
180
|
-
# @param level [Symbol] the level of the message.
|
181
|
-
# :verbose messages equate to a standard INFO log level and
|
182
|
-
# :debug to DEBUG.
|
183
|
-
#
|
184
|
-
def log(msg, level = nil)
|
185
|
-
if logger
|
186
|
-
logger.send(level || :info, msg)
|
187
|
-
else
|
188
|
-
print_message(msg, level)
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
# Print it unless it's a debug and we're not in debug
|
193
|
-
#
|
194
|
-
def print_message(msg, level)
|
195
|
-
return if level == :debug && !opts[:debug]
|
196
|
-
return if level == :info && !opts[:verbose]
|
197
|
-
puts msg
|
198
|
-
end
|
199
|
-
|
200
178
|
# If we need to massage a raw response to fit what the
|
201
179
|
# Wavefront::Response class expects (I'm looking at you,
|
202
180
|
# 'User'), a class can provide a {#response_shim} method.
|
@@ -208,7 +186,7 @@ module Wavefront
|
|
208
186
|
resp.body
|
209
187
|
end
|
210
188
|
|
211
|
-
Wavefront::Response.new(body, resp.status,
|
189
|
+
Wavefront::Response.new(body, resp.status, opts)
|
212
190
|
end
|
213
191
|
|
214
192
|
# Return all objects using a lazy enumerator
|
@@ -238,11 +216,11 @@ module Wavefront
|
|
238
216
|
# of clumsy guesswork here
|
239
217
|
#
|
240
218
|
def verbosity(conn, method, *args)
|
241
|
-
log
|
219
|
+
log format('uri: %s %s', method.upcase, conn.url_prefix)
|
242
220
|
|
243
221
|
return unless args.last && !args.last.empty?
|
244
222
|
|
245
|
-
|
223
|
+
log method == :get ? "params: #{args.last}" : "body: #{args.last}"
|
246
224
|
end
|
247
225
|
|
248
226
|
# Make the API call, or not, if noop is set.
|
@@ -261,10 +239,17 @@ module Wavefront
|
|
261
239
|
respond(resp)
|
262
240
|
end
|
263
241
|
|
264
|
-
def
|
242
|
+
def validate_credentials(creds)
|
265
243
|
%w[endpoint token].each do |k|
|
266
|
-
|
244
|
+
unless creds.key?(k.to_sym)
|
245
|
+
raise(Wavefront::Exception::CredentialError,
|
246
|
+
format('credentials must contain %s', k))
|
247
|
+
end
|
267
248
|
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def setup_endpoint(creds)
|
252
|
+
validate_credentials(creds)
|
268
253
|
|
269
254
|
unless creds.key?(:agent) && creds[:agent]
|
270
255
|
creds[:agent] = "wavefront-sdk #{WF_SDK_VERSION}"
|
@@ -83,7 +83,7 @@ module Wavefront
|
|
83
83
|
resp = { status: { result: s_str, message: nil, code: nil },
|
84
84
|
response: summary }.to_json
|
85
85
|
|
86
|
-
Wavefront::Response.new(resp, nil)
|
86
|
+
Wavefront::Response.new(resp, nil, opts)
|
87
87
|
end
|
88
88
|
|
89
89
|
def summary_string(summary)
|
@@ -125,23 +125,18 @@ module Wavefront
|
|
125
125
|
[points].flatten.map { |p| p.tap { p[:path] = DELTA + p[:path] } }
|
126
126
|
end
|
127
127
|
|
128
|
-
# rubocop:disable Metrics/MethodLength
|
129
128
|
def valid_point?(point)
|
130
129
|
return true if opts[:novalidate]
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
log("Invalid point: #{point}. (#{e})", :debug)
|
142
|
-
summary[:rejected] += 1
|
143
|
-
return false
|
144
|
-
end
|
130
|
+
wf_point?(point)
|
131
|
+
rescue Wavefront::Exception::InvalidMetricName,
|
132
|
+
Wavefront::Exception::InvalidMetricValue,
|
133
|
+
Wavefront::Exception::InvalidTimestamp,
|
134
|
+
Wavefront::Exception::InvalidSourceId,
|
135
|
+
Wavefront::Exception::InvalidTag => e
|
136
|
+
log('Invalid point, skipping.', :info)
|
137
|
+
log(format('Invalid point: %s (%s)', point, e.to_s), :debug)
|
138
|
+
summary[:rejected] += 1
|
139
|
+
false
|
145
140
|
end
|
146
141
|
|
147
142
|
# Convert a validated point to a string conforming to
|
@@ -151,21 +146,25 @@ module Wavefront
|
|
151
146
|
# @param point [Hash] a hash describing a point. See #write() for
|
152
147
|
# the format.
|
153
148
|
#
|
154
|
-
# rubocop:disable Metrics/AbcSize
|
155
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
156
149
|
def hash_to_wf(point)
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
150
|
+
format('%s %s %s source=%s %s %s',
|
151
|
+
*point_array(point)).squeeze(' ').strip
|
152
|
+
rescue StandardError
|
153
|
+
raise Wavefront::Exception::InvalidPoint
|
154
|
+
end
|
162
155
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
156
|
+
# Make an array which can be used by #hash_to_wf.
|
157
|
+
# @param point [Hash] a hash describing a point. See #write() for
|
158
|
+
# the format.
|
159
|
+
# @raise
|
160
|
+
#
|
161
|
+
def point_array(point)
|
162
|
+
[point[:path] || raise,
|
163
|
+
point[:value] || raise,
|
164
|
+
point.fetch(:ts, nil),
|
165
|
+
point.fetch(:source, HOSTNAME),
|
166
|
+
point[:tags] && point[:tags].to_wf_tag,
|
167
|
+
opts[:tags] && opts[:tags].to_wf_tag]
|
169
168
|
end
|
170
169
|
|
171
170
|
# Wrapper for #really_send_point(), which really sends points.
|
data/lib/wavefront-sdk/event.rb
CHANGED
@@ -24,17 +24,21 @@ module Wavefront
|
|
24
24
|
# @return [Wavefront::Response]
|
25
25
|
#
|
26
26
|
def list(from = nil, to = nil, limit = 100, cursor = nil)
|
27
|
-
raise ArgumentError unless from && to
|
27
|
+
raise ArgumentError unless from && to && limit.is_a?(Integer)
|
28
|
+
wf_event_id?(cursor) if cursor
|
29
|
+
|
28
30
|
from = parse_time(from, true)
|
29
|
-
to
|
31
|
+
to = parse_time(to, true)
|
32
|
+
|
30
33
|
wf_ms_ts?(from)
|
31
34
|
wf_ms_ts?(to)
|
32
|
-
wf_event_id?(cursor) if cursor
|
33
|
-
raise ArgumentError unless limit.is_a?(Integer)
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
body = { earliestStartTimeEpochMillis: from,
|
37
|
+
latestStartTimeEpochMillis: to,
|
38
|
+
cursor: cursor,
|
39
|
+
limit: limit }
|
40
|
+
|
41
|
+
api_get('', body.cleanse)
|
38
42
|
end
|
39
43
|
|
40
44
|
# POST /api/v2/event
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Wavefront
|
2
|
+
#
|
3
|
+
# Log to a user-supplied Ruby logger, or to standard output.
|
4
|
+
#
|
5
|
+
class Logger
|
6
|
+
attr_reader :logger, :verbose, :debug
|
7
|
+
|
8
|
+
# @param opts [Hash] options hash from a child of Wavefront::Base
|
9
|
+
#
|
10
|
+
def initialize(opts = {})
|
11
|
+
@logger = opts[:logger] || nil
|
12
|
+
@verbose = opts[:verbose] || nil
|
13
|
+
@debug = opts[:debug] || nil
|
14
|
+
end
|
15
|
+
|
16
|
+
# Send a message to a Ruby logger object if the user supplied
|
17
|
+
# one, or print to standard out if not.
|
18
|
+
#
|
19
|
+
# @param msg [String] the string to print
|
20
|
+
# @param level [Symbol] the level of the message.
|
21
|
+
# :verbose messages equate to a standard INFO log level and
|
22
|
+
# :debug to DEBUG.
|
23
|
+
#
|
24
|
+
def log(msg, level = :info)
|
25
|
+
if logger
|
26
|
+
logger.send(level, msg)
|
27
|
+
else
|
28
|
+
print_message(level, msg)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def print_message(level, msg)
|
33
|
+
method = format('print_%s_message', level).to_sym
|
34
|
+
msg = format_message(level, msg)
|
35
|
+
|
36
|
+
if respond_to?(:method)
|
37
|
+
send(method, msg)
|
38
|
+
else
|
39
|
+
print_warn_message(format('undefined message level:%s', level))
|
40
|
+
print_warn_message(msg)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def format_message(level, msg)
|
45
|
+
format('SDK %s: %s', level.to_s.upcase, msg)
|
46
|
+
end
|
47
|
+
|
48
|
+
def print_debug_message(msg)
|
49
|
+
return unless debug
|
50
|
+
puts msg
|
51
|
+
end
|
52
|
+
|
53
|
+
def print_info_message(msg)
|
54
|
+
puts msg
|
55
|
+
end
|
56
|
+
|
57
|
+
def print_warn_message(msg)
|
58
|
+
warn msg
|
59
|
+
end
|
60
|
+
|
61
|
+
def print_error_message(msg)
|
62
|
+
warn msg
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/wavefront-sdk/metric.rb
CHANGED
@@ -18,19 +18,18 @@ module Wavefront
|
|
18
18
|
# @param cursor [String] optionally begin from this result
|
19
19
|
#
|
20
20
|
def detail(metric, sources = [], cursor = nil)
|
21
|
-
raise ArgumentError unless metric.is_a?(String)
|
22
|
-
raise ArgumentError unless sources.is_a?(Array)
|
21
|
+
raise ArgumentError unless metric.is_a?(String) && sources.is_a?(Array)
|
23
22
|
|
24
|
-
|
23
|
+
query = [[:m, metric]]
|
25
24
|
|
26
25
|
if cursor
|
27
26
|
raise ArgumentError unless cursor.is_a?(String)
|
28
|
-
|
27
|
+
query.<< [:c, cursor]
|
29
28
|
end
|
30
29
|
|
31
|
-
sources.each { |
|
30
|
+
sources.each { |source| query.<< [:h, source] }
|
32
31
|
|
33
|
-
api_get('detail',
|
32
|
+
api_get('detail', query)
|
34
33
|
end
|
35
34
|
end
|
36
35
|
end
|
data/lib/wavefront-sdk/mixins.rb
CHANGED
@@ -43,18 +43,29 @@ module Wavefront
|
|
43
43
|
ref.to_i + parse_relative_time(time, in_ms)
|
44
44
|
end
|
45
45
|
|
46
|
+
# Do the real work for #relative_time
|
47
|
+
# @param time [String] as +1h, -3d etc
|
48
|
+
# @param in_ms [Bool] whether to return time differential in ms
|
49
|
+
# rather than s
|
50
|
+
# @return [Integer] time differential
|
51
|
+
#
|
46
52
|
def parse_relative_time(time, in_ms = false)
|
47
|
-
unless
|
53
|
+
unless valid_relative_time?(time)
|
48
54
|
raise Wavefront::Exception::InvalidRelativeTime
|
49
55
|
end
|
50
56
|
|
51
57
|
m = in_ms ? 1000 : 1
|
52
|
-
|
53
|
-
time = time[1..-1] if time.start_with?('+')
|
58
|
+
time.delete!('+')
|
54
59
|
match = time.match(/^(-?\d*\.?\d*)([smhdwy])$/)
|
55
60
|
(match[1].to_f * time_multiplier(match[2]) * m).to_i
|
56
|
-
|
57
|
-
|
61
|
+
end
|
62
|
+
|
63
|
+
# Is a relative time valid?
|
64
|
+
# @param time [String] time as +1d, -1h etc
|
65
|
+
# @return [Bool]
|
66
|
+
#
|
67
|
+
def valid_relative_time?(time)
|
68
|
+
time =~ /^[+-](-?\d*\.?\d*)[smhdwy]$/
|
58
69
|
end
|
59
70
|
|
60
71
|
# naively return the number of seconds from the given
|