wavefront-sdk 1.6.0 → 1.6.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e68e0e9c6233a7fb449408c84111beaf522c023370188d155c234aa3387c411c
4
- data.tar.gz: 0a3575ed176110827a011b6793b1d6f3cf8eb64e96dba1ce4b2f129ef1234219
3
+ metadata.gz: e599fd70e3a67cdc62c8ec942382db101850582e8bd98c11e8e56e18a1d1bfaf
4
+ data.tar.gz: 134f436ff650ba75a4cad1e93bcf229ea25787dbafa5fcf40aa93b067bed9402
5
5
  SHA512:
6
- metadata.gz: 47af2cca2a5ca29d545aefb936e3850234e117d53d6ee46580b931e505fda6fdb446004680102631b1b19d463889cf601d6578de27b0e7358094b498a24174ee
7
- data.tar.gz: 736e992312831e5c1b2f37558c70cfec883950eab7f82777baa1c9a2ba3848b0adc0abc20972d27f70e34fbe77ce027b850b65bc6781c55e78cc50a6edbfa294
6
+ metadata.gz: 3f051f1594d486c3b6c65ed964a0e2b822a034975a19ad9745926048e891ce5a8f89a063a17532ff8a90b3b1c89085ba448d57346dff33b6300765bd3f365b3e
7
+ data.tar.gz: 0a97bf0ed08c8ee08607b4e98f55cc5daeb7b30e6245df99407c0dddfb708ed093bbaeb3d9aaac805d09da12ca61cccdd94c96222458545bc7857d536d43002e
@@ -1,8 +1,15 @@
1
+ ---
1
2
  AllCops:
2
- TargetRubyVersion: 2.3
3
+ TargetRubyVersion: 2.2
3
4
 
4
5
  Style/FrozenStringLiteralComment:
5
6
  Enabled: false
6
7
 
7
- Lint/MissingCopEnableDirective:
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
@@ -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, :update_keys,
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 = opts
48
- @debug = opts[:debug] || false
49
- @noop = opts[:noop] || false
47
+ @opts = opts
48
+ @debug = opts[:debug] || false
49
+ @noop = opts[:noop] || false
50
50
  @verbose = opts[:verbose] || false
51
- @logger = opts[:logger] || nil
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
- Faraday.new(
89
- url: Addressable::URI.encode("https://#{net[:endpoint]}" +
90
- [net[:api_base], path].uri_concat),
91
- headers: net[:headers].merge(headers)
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
- # #noop class variable is set. If #verbose is set, then prints
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
- # #noop class variable is set. If #verbose is set, then prints
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
- # #noop class variable is set. If #verbose is set, then prints
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
- # #noop class variable is set. If #verbose is set, then prints
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, debug)
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 "uri: #{method.upcase} #{conn.url_prefix}"
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
- puts log method == :get ? "params: #{args.last}" : "body: #{args.last}"
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 setup_endpoint(creds)
242
+ def validate_credentials(creds)
265
243
  %w[endpoint token].each do |k|
266
- raise "creds must contain #{k}" unless creds.key?(k.to_sym)
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
- begin
133
- wf_point?(point)
134
- return true
135
- rescue Wavefront::Exception::InvalidMetricName,
136
- Wavefront::Exception::InvalidMetricValue,
137
- Wavefront::Exception::InvalidTimestamp,
138
- Wavefront::Exception::InvalidSourceId,
139
- Wavefront::Exception::InvalidTag => e
140
- log('Invalid point, skipping.', :info)
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
- unless point.key?(:path) && point.key?(:value)
158
- raise Wavefront::Exception::InvalidPoint
159
- end
160
-
161
- point[:source] = HOSTNAME unless point.key?(:source)
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
- m = [point[:path], point[:value]]
164
- m.<< point[:ts] if point[:ts]
165
- m.<< 'source=' + point[:source]
166
- m.<< point[:tags].to_wf_tag if point[:tags]
167
- m.<< opts[:tags].to_wf_tag if opts[:tags]
168
- m.join(' ')
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.
@@ -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 = parse_time(to, true)
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
- api_get('', { earliestStartTimeEpochMillis: from,
36
- latestStartTimeEpochMillis: to,
37
- cursor: cursor, limit: limit }.select { |_k, v| v })
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
@@ -3,6 +3,7 @@ module Wavefront
3
3
  # Simple exception classes
4
4
  #
5
5
  class Exception
6
+ class CredentialError < RuntimeError; end
6
7
  class EmptyMetricName < RuntimeError; end
7
8
  class InvalidAlertId < RuntimeError; end
8
9
  class InvalidAlertSeverity < RuntimeError; end
@@ -10,7 +10,8 @@ module Wavefront
10
10
  end
11
11
 
12
12
  def update_keys
13
- %i[name template description]
13
+ %i[name template description metricFilterRegex sourceFilterRegex
14
+ pointTagFilterRegexes]
14
15
  end
15
16
 
16
17
  # GET /api/v2/extlink
@@ -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
@@ -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
- q = [[:m, metric]]
23
+ query = [[:m, metric]]
25
24
 
26
25
  if cursor
27
26
  raise ArgumentError unless cursor.is_a?(String)
28
- q.<< [:c, cursor]
27
+ query.<< [:c, cursor]
29
28
  end
30
29
 
31
- sources.each { |s| q.<< [:h, s] }
30
+ sources.each { |source| query.<< [:h, source] }
32
31
 
33
- api_get('detail', q)
32
+ api_get('detail', query)
34
33
  end
35
34
  end
36
35
  end
@@ -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 time.start_with?('+', '-')
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
- rescue NoMethodError
57
- raise Wavefront::Exception::InvalidRelativeTime
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