wavefront-sdk 3.7.1 → 4.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/.travis.yml +0 -1
- data/HISTORY.md +8 -0
- data/README.md +1 -1
- data/lib/wavefront-sdk/core/api_caller.rb +50 -7
- data/lib/wavefront-sdk/core/exception.rb +3 -0
- data/lib/wavefront-sdk/defs/version.rb +1 -3
- data/lib/wavefront-sdk/monitoredcluster.rb +93 -0
- data/lib/wavefront-sdk/stdlib/time.rb +13 -0
- data/lib/wavefront-sdk/unstable/README.md +4 -0
- data/lib/wavefront-sdk/unstable/chart.rb +90 -0
- data/lib/wavefront-sdk/unstable/spy.rb +134 -0
- data/lib/wavefront-sdk/unstable/unstable.rb +9 -0
- data/lib/wavefront-sdk/validators.rb +21 -0
- data/lib/wavefront-sdk/write.rb +9 -9
- data/spec/spec_helper.rb +4 -0
- data/spec/support/minitest_assertions.rb +4 -4
- data/spec/wavefront-sdk/core/api_caller_spec.rb +43 -0
- data/spec/wavefront-sdk/monitoredcluster_spec.rb +55 -0
- data/spec/wavefront-sdk/unstable/chart_spec.rb +39 -0
- data/spec/wavefront-sdk/unstable/spy_spec.rb +113 -0
- data/spec/wavefront-sdk/validators_spec.rb +15 -0
- data/wavefront-sdk.gemspec +2 -2
- metadata +17 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 578159c0ff0dac09b94caa4dac4e37f03436cb3e2b4cdda54886ce91b9ce4c9b
|
4
|
+
data.tar.gz: 93eac0630e97d53e3b26d222fd09df61f8cd7966c62e39520dbf27525982cb1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3f09ae6d818b0acc7e81e2e4da585c10a59efba18a4ab373679783d62b5a5ccc300e14435b7cbe8a0f2d64adec361e080c55f089732ffbb6c171f619524440e
|
7
|
+
data.tar.gz: d558a6d0eafe0d09120317113758ee70807cae035a7e9677a22cf643e537103ff66d671e7e6a031151cd03572f6b62a78e9aa92a86a2fb052f0cb31ba92c4f17
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
data/HISTORY.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 4.0.0 (2020-02-17)
|
4
|
+
* Drop support for Ruby 2.3. (Breaking change.)
|
5
|
+
* Add `Wavefront::MonitoredCluster` class.
|
6
|
+
* Add `Wavefront::Unstable::Spy` class to speak to (undocumented) spy
|
7
|
+
interface.
|
8
|
+
* Add `Wavefront::Unstable::Chart` class to speak to (undocumented) chart
|
9
|
+
interface.
|
10
|
+
|
3
11
|
## 3.7.1 (2020-02-09)
|
4
12
|
* `Response` object returned by `Wavefront::Write#write` includes a valid HTTP
|
5
13
|
code, rather than `nil`.
|
data/README.md
CHANGED
@@ -24,7 +24,7 @@ or to build locally,
|
|
24
24
|
$ gem build wavefront-sdk.gemspec
|
25
25
|
```
|
26
26
|
|
27
|
-
`wavefront-sdk` requires Ruby >= 2.
|
27
|
+
`wavefront-sdk` requires Ruby >= 2.4. All its dependencies are pure
|
28
28
|
Ruby, right the way down, so a compiler should never be required to
|
29
29
|
install it.
|
30
30
|
|
@@ -6,6 +6,7 @@ require 'addressable'
|
|
6
6
|
require_relative 'response'
|
7
7
|
require_relative '../defs/version'
|
8
8
|
require_relative '../support/mixins'
|
9
|
+
require_relative '../stdlib/time'
|
9
10
|
|
10
11
|
module Wavefront
|
11
12
|
#
|
@@ -78,14 +79,47 @@ module Wavefront
|
|
78
79
|
# was cleaner to add this method. Parameters are same as #get.
|
79
80
|
#
|
80
81
|
def get_flat_params(path, query = {})
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
82
|
+
make_call(flat_param_conn(path, query), :get)
|
83
|
+
end
|
84
|
+
|
85
|
+
# This is used by the Wavefront::Unstable::Spy methods to stream data.
|
86
|
+
# It prints to standard out.
|
87
|
+
# @param path [String] path to be appended to the net[:api_base] path.
|
88
|
+
# @param query [Hash] optional key-value pairs with will be made into a
|
89
|
+
# query string
|
90
|
+
# @param opts [Hash] keys:
|
91
|
+
# timestamp_chunks -- prints a timestamp before each chunk of streamed
|
92
|
+
# data
|
93
|
+
# timeout -- after approximately this many seconds, return. It will be
|
94
|
+
# the first chunk *after* the given time
|
95
|
+
# @return
|
96
|
+
#
|
97
|
+
def get_stream(path, query = {}, opts = {})
|
98
|
+
conn = flat_param_conn(path, query)
|
99
|
+
verbosity(conn, :get, query)
|
100
|
+
stream_connection(conn, query, opts)
|
101
|
+
rescue Faraday::TimeoutError
|
102
|
+
raise Wavefront::Exception::NetworkTimeout
|
103
|
+
rescue StopIteration
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
|
107
|
+
def stream_connection(conn, query, opts)
|
108
|
+
t_end = end_time(opts)
|
109
|
+
|
110
|
+
conn.get do |req|
|
111
|
+
req.params = query
|
112
|
+
req.options.on_data = proc do |chunk, _size|
|
113
|
+
raise StopIteration if t_end && Time.right_now >= t_end
|
87
114
|
|
88
|
-
|
115
|
+
puts Time.now if opts[:timestamp_chunks]
|
116
|
+
puts chunk
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def end_time(opts)
|
122
|
+
Time.right_now + opts[:timeout] if opts[:timeout]&.positive?
|
89
123
|
end
|
90
124
|
|
91
125
|
# Make a POST call to the Wavefront API and return the result as
|
@@ -240,5 +274,14 @@ module Wavefront
|
|
240
274
|
end
|
241
275
|
end
|
242
276
|
end
|
277
|
+
|
278
|
+
def flat_param_conn(path, query)
|
279
|
+
mk_conn(path,
|
280
|
+
{},
|
281
|
+
request: {
|
282
|
+
params_encoder: Faraday::FlatParamsEncoder
|
283
|
+
},
|
284
|
+
params: query)
|
285
|
+
end
|
243
286
|
end
|
244
287
|
end
|
@@ -28,6 +28,7 @@ module Wavefront
|
|
28
28
|
class InvalidIntegrationId < RuntimeError; end
|
29
29
|
class InvalidLinkTemplate < RuntimeError; end
|
30
30
|
class InvalidMaintenanceWindowId < RuntimeError; end
|
31
|
+
class InvalidMonitoredClusterId < RuntimeError; end
|
31
32
|
class InvalidMessageId < RuntimeError; end
|
32
33
|
class InvalidMetricName < RuntimeError; end
|
33
34
|
class InvalidMetricValue < RuntimeError; end
|
@@ -38,6 +39,7 @@ module Wavefront
|
|
38
39
|
class InvalidPrefixLength < RuntimeError; end
|
39
40
|
class InvalidProxyId < RuntimeError; end
|
40
41
|
class InvalidRelativeTime < RuntimeError; end
|
42
|
+
class InvalidSamplingValue < RuntimeError; end
|
41
43
|
class InvalidSavedSearchEntity < RuntimeError; end
|
42
44
|
class InvalidSavedSearchId < RuntimeError; end
|
43
45
|
class InvalidServiceAccountId < RuntimeError; end
|
@@ -51,6 +53,7 @@ module Wavefront
|
|
51
53
|
class InvalidUserGroupId < RuntimeError; end
|
52
54
|
class InvalidVersion < RuntimeError; end
|
53
55
|
class InvalidWebhookId < RuntimeError; end
|
56
|
+
class NetworkTimeout < RuntimeError; end
|
54
57
|
class NotImplemented < RuntimeError; end
|
55
58
|
class SocketError < RuntimeError; end
|
56
59
|
class UnparseableResponse < RuntimeError; end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'core/api'
|
4
|
+
require_relative 'api_mixins/tag'
|
5
|
+
|
6
|
+
module Wavefront
|
7
|
+
#
|
8
|
+
# Manage and query Wavefront monitored clusters
|
9
|
+
#
|
10
|
+
class MonitoredCluster < CoreApi
|
11
|
+
include Wavefront::Mixin::Tag
|
12
|
+
|
13
|
+
def update_keys
|
14
|
+
%i[id]
|
15
|
+
end
|
16
|
+
|
17
|
+
# GET /api/v2/monitoredcluster
|
18
|
+
# Get all monitored clusters
|
19
|
+
# @param offset [Integer] cluster at which the list begins
|
20
|
+
# @param limit [Integer] the number of clusters to return
|
21
|
+
# @return [Wavefront::Response]
|
22
|
+
#
|
23
|
+
def list(offset = 0, limit = 100)
|
24
|
+
api.get('', offset: offset, limit: limit)
|
25
|
+
end
|
26
|
+
|
27
|
+
# POST /api/v2/monitoredcluster
|
28
|
+
# Create a specific cluster
|
29
|
+
# @param body [Hash] a hash of parameters describing the cluster.
|
30
|
+
# Please refer to the Wavefront Swagger docs for key:value
|
31
|
+
# information
|
32
|
+
# @return [Wavefront::Response]
|
33
|
+
#
|
34
|
+
def create(body)
|
35
|
+
raise ArgumentError unless body.is_a?(Hash)
|
36
|
+
|
37
|
+
api.post('', body, 'application/json')
|
38
|
+
end
|
39
|
+
|
40
|
+
# DELETE /api/v2/monitoredcluster/{id}
|
41
|
+
# Delete a specific cluster
|
42
|
+
# @param id [String, Integer] ID of the maintenance cluster
|
43
|
+
# @return [Wavefront::Response]
|
44
|
+
#
|
45
|
+
def delete(id)
|
46
|
+
wf_monitoredcluster_id?(id)
|
47
|
+
api.delete(id)
|
48
|
+
end
|
49
|
+
|
50
|
+
# GET /api/v2/monitoredcluster/{id}
|
51
|
+
# Get a specific cluster
|
52
|
+
# @param id [String, Integer] ID of the cluster
|
53
|
+
# @return [Wavefront::Response]
|
54
|
+
#
|
55
|
+
def describe(id)
|
56
|
+
wf_monitoredcluster_id?(id)
|
57
|
+
api.get(id)
|
58
|
+
end
|
59
|
+
|
60
|
+
# PUT /api/v2/monitoredcluster/{id}
|
61
|
+
# Update a specific cluster
|
62
|
+
# @return [Wavefront::Response]
|
63
|
+
#
|
64
|
+
def update(id, body, modify = true)
|
65
|
+
wf_monitoredcluster_id?(id)
|
66
|
+
raise ArgumentError unless body.is_a?(Hash)
|
67
|
+
|
68
|
+
return api.put(id, body, 'application/json') unless modify
|
69
|
+
|
70
|
+
api.put(id, hash_for_update(describe(id).response, body),
|
71
|
+
'application/json')
|
72
|
+
end
|
73
|
+
|
74
|
+
# PUT /api/v2/monitoredcluster/merge/{id1}/{id2}
|
75
|
+
# Merge two monitored clusters. The first cluster will remain and the
|
76
|
+
# second cluster will be deleted, with its id added as an alias to the
|
77
|
+
# first cluster.
|
78
|
+
# @param id1 [String, Integer] ID of the target cluster
|
79
|
+
# @param id2 [String, Integer] ID of the other cluster
|
80
|
+
# @return [Wavefront::Response]
|
81
|
+
#
|
82
|
+
def merge(id1, id2)
|
83
|
+
wf_monitoredcluster_id?(id1)
|
84
|
+
wf_monitoredcluster_id?(id2)
|
85
|
+
|
86
|
+
api.put(['merge', id1, id2].uri_concat, nil, 'application/json')
|
87
|
+
end
|
88
|
+
|
89
|
+
def valid_id?(id)
|
90
|
+
wf_monitoredcluster_id?(id)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Extensions to the stdlib Time class
|
4
|
+
#
|
5
|
+
class Time
|
6
|
+
#
|
7
|
+
# The real hi-res time. See
|
8
|
+
# https://blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way/
|
9
|
+
#
|
10
|
+
def self.right_now
|
11
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../defs/constants'
|
4
|
+
require_relative '../core/api'
|
5
|
+
|
6
|
+
module Wavefront
|
7
|
+
module Unstable
|
8
|
+
#
|
9
|
+
# This is an unstable class. Please refer to README.md.
|
10
|
+
#
|
11
|
+
class Chart < CoreApi
|
12
|
+
def all_metrics
|
13
|
+
metrics_under('')
|
14
|
+
end
|
15
|
+
|
16
|
+
# Gets a list of metrics under the given path. This must be done via
|
17
|
+
# recursive calls to the API, so calls can take a while. If you ask for
|
18
|
+
# all your metrics, expect to be waiting some time.
|
19
|
+
#
|
20
|
+
# @return [Wavefront::Response]
|
21
|
+
#
|
22
|
+
# rubocop:disable Metrics/MethodLength
|
23
|
+
# rubocop:disable Metrics/AbcSize
|
24
|
+
def metrics_under(path, cursor = nil, limit = 100)
|
25
|
+
resp = api.get('metrics/all',
|
26
|
+
{ trie: true, q: path, p: cursor, l: limit }.compact)
|
27
|
+
|
28
|
+
return resp unless resp.ok?
|
29
|
+
|
30
|
+
metrics = resp.response.items
|
31
|
+
|
32
|
+
metrics.each do |m|
|
33
|
+
if m.end_with?('.')
|
34
|
+
metrics += metrics_under(m).response.items
|
35
|
+
metrics.delete(m)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# resp.more_items? doesn't work: we don't get that from this API
|
40
|
+
|
41
|
+
if metrics.size == limit
|
42
|
+
metrics += metrics_under(path, metrics.last, limit).response.items
|
43
|
+
end
|
44
|
+
|
45
|
+
resp.response.items = metrics.sort
|
46
|
+
resp
|
47
|
+
end
|
48
|
+
# rubocop:enable Metrics/MethodLength
|
49
|
+
# rubocop:enable Metrics/AbcSize
|
50
|
+
|
51
|
+
def api_path
|
52
|
+
'/chart'
|
53
|
+
end
|
54
|
+
|
55
|
+
# We have to try to make the response we get from the API look
|
56
|
+
# like the one we get from the public API. To begin with, it's
|
57
|
+
# nothing like it.
|
58
|
+
#
|
59
|
+
# This method must be public because a #respond_to? looks for
|
60
|
+
# it.
|
61
|
+
#
|
62
|
+
def response_shim(resp, status)
|
63
|
+
{ response: parse_response(resp),
|
64
|
+
status: { result: status == 200 ? 'OK' : 'ERROR',
|
65
|
+
message: extract_api_message(status, resp),
|
66
|
+
code: status } }.to_json
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def parse_response(resp)
|
72
|
+
metrics = JSON.parse(resp, symbolize_names: true)[:metrics]
|
73
|
+
|
74
|
+
{ items: metrics,
|
75
|
+
offset: 0,
|
76
|
+
limit: metrics.size,
|
77
|
+
totalItems: metrics.size,
|
78
|
+
moreItems: false }
|
79
|
+
rescue JSON::ParserError
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
|
83
|
+
def extract_api_message(_status, resp)
|
84
|
+
resp.match(/^message='(.*)'/)[1]
|
85
|
+
rescue NoMethodError
|
86
|
+
''
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../defs/constants'
|
4
|
+
require_relative '../core/api'
|
5
|
+
|
6
|
+
module Wavefront
|
7
|
+
module Unstable
|
8
|
+
#
|
9
|
+
# THIS IS AN UNSTABLE CLASS. PLEASE REFER TO README.md.
|
10
|
+
#
|
11
|
+
# Everything about this API is different from the public one. To make it
|
12
|
+
# appear similar we must change various things we normally take for
|
13
|
+
# granted.
|
14
|
+
#
|
15
|
+
# This class is built according to the documentation at
|
16
|
+
# https://docs.wavefront.com/wavefront_monitoring_spy.html
|
17
|
+
#
|
18
|
+
class Spy < CoreApi
|
19
|
+
# https://<cluster>.wavefront.com/api/spy/points
|
20
|
+
# Gets new metric data points that are added to existing time series.
|
21
|
+
# @param sampling [Float] the amount of points to sample, from 0
|
22
|
+
# (none) to 1 (all)
|
23
|
+
# @param filter [Hash] with the following keys:
|
24
|
+
# :prefix [String] only list points whose metric name begins with this
|
25
|
+
# case-sensitive string
|
26
|
+
# :host [Array] only list points if source name begins with this
|
27
|
+
# case-sensitive string
|
28
|
+
# :tag_key [String,Array[String]] only list points with one or more of
|
29
|
+
# the given points tags
|
30
|
+
# @param options [Hash] with the following keys
|
31
|
+
# :timestamp [Boolean] prefix each block of streamed data with a
|
32
|
+
# timestamp
|
33
|
+
# :timeout [Integer] how many seconds to run the spy. After this time
|
34
|
+
# the method returns
|
35
|
+
# @raise Wavefront::Exception::InvalidSamplingValue
|
36
|
+
# @return [Nil]
|
37
|
+
#
|
38
|
+
def points(sampling = 0.01, filters = {}, options = {})
|
39
|
+
wf_sampling_value?(sampling)
|
40
|
+
api.get_stream('points', points_filter(sampling, filters), options)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Gets new histograms that are added to existing time series.
|
44
|
+
# @param sampling [Float] see #points
|
45
|
+
# @param filter [Hash] see #points
|
46
|
+
# @param options [Hash] see #points
|
47
|
+
# @raise Wavefront::Exception::InvalidSamplingValue
|
48
|
+
# @return [Nil]
|
49
|
+
#
|
50
|
+
def histograms(sampling = 0.01, filters = {}, options = {})
|
51
|
+
wf_sampling_value?(sampling)
|
52
|
+
api.get_stream('histograms',
|
53
|
+
histograms_filter(sampling, filters),
|
54
|
+
options)
|
55
|
+
end
|
56
|
+
|
57
|
+
# https://<cluster>.wavefront.com/api/spy/spans
|
58
|
+
# Gets new spans with existing source names and span tags.
|
59
|
+
# @param sampling [Float] see #points
|
60
|
+
# @param filter [Hash] see #points
|
61
|
+
# @param options [Hash] see #points
|
62
|
+
# @raise Wavefront::Exception::InvalidSamplingValue
|
63
|
+
# @return [Nil]
|
64
|
+
#
|
65
|
+
def spans(sampling = 0.01, filters = {}, options = {})
|
66
|
+
wf_sampling_value?(sampling)
|
67
|
+
api.get_stream('spans', spans_filter(sampling, filters), options)
|
68
|
+
end
|
69
|
+
|
70
|
+
# https://<cluster>.wavefront.com/api/spy/ids
|
71
|
+
# Gets newly allocated IDs that correspond to new metric names, source
|
72
|
+
# names, point tags, or span tags. A new ID generally indicates that a
|
73
|
+
# new time series has been introduced.
|
74
|
+
# @param sampling [Float] see #points
|
75
|
+
# @param filter [Hash] with keys:
|
76
|
+
# :prefix [String] only list assignments whose metric name begins with
|
77
|
+
# this case-sensitive string
|
78
|
+
# :type [String] one of METRIC, SPAN, HOST or STRING
|
79
|
+
# @param options [Hash] see #points
|
80
|
+
#
|
81
|
+
def ids(sampling = 0.01, filters = {}, options = {})
|
82
|
+
wf_sampling_value?(sampling)
|
83
|
+
api.get_stream('ids', ids_filter(sampling, filters), options)
|
84
|
+
end
|
85
|
+
|
86
|
+
def api_path
|
87
|
+
'/api/spy'
|
88
|
+
end
|
89
|
+
|
90
|
+
# We have to try to make the response we get from the API look
|
91
|
+
# like the one we get from the public API. To begin with, it's
|
92
|
+
# nothing like it.
|
93
|
+
#
|
94
|
+
# This method must be public because a #respond_to? looks for
|
95
|
+
# it.
|
96
|
+
#
|
97
|
+
def _response_shim(resp, status)
|
98
|
+
{ response: parse_response(resp),
|
99
|
+
status: { result: status == 200 ? 'OK' : 'ERROR',
|
100
|
+
message: extract_api_message(status, resp),
|
101
|
+
code: status } }.to_json
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def points_filter(sampling, filters)
|
107
|
+
{ metric: filters.fetch(:prefix, nil),
|
108
|
+
host: filters.fetch(:host, nil),
|
109
|
+
sampling: sampling,
|
110
|
+
pointTagKey: filters.fetch(:tag_key, nil) }.compact
|
111
|
+
end
|
112
|
+
|
113
|
+
def histograms_filter(sampling, filters)
|
114
|
+
{ histogram: filters.fetch(:prefix, nil),
|
115
|
+
host: filters.fetch(:host, nil),
|
116
|
+
sampling: sampling,
|
117
|
+
histogramTagKey: filters.fetch(:tag_key, nil) }.compact
|
118
|
+
end
|
119
|
+
|
120
|
+
def spans_filter(sampling, filters)
|
121
|
+
{ name: filters.fetch(:prefix, nil),
|
122
|
+
host: filters.fetch(:host, nil),
|
123
|
+
sampling: sampling,
|
124
|
+
spanTagKey: filters.fetch(:tag_key, nil) }.compact
|
125
|
+
end
|
126
|
+
|
127
|
+
def ids_filter(sampling, filters)
|
128
|
+
{ name: filters.fetch(:prefix, nil),
|
129
|
+
type: filters.fetch(:type, nil),
|
130
|
+
sampling: sampling }.compact
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -594,6 +594,27 @@ module Wavefront
|
|
594
594
|
raise Wavefront::Exception::InvalidAccountId, id
|
595
595
|
end
|
596
596
|
end
|
597
|
+
|
598
|
+
# Ensure the given argument is a valid monitored cluster ID
|
599
|
+
# @param id [String]
|
600
|
+
# @raise Wavefront::Exception::InvalidMonitoredClusterId if the ID is not
|
601
|
+
# valid
|
602
|
+
#
|
603
|
+
def wf_monitoredcluster_id?(id)
|
604
|
+
return true if id.is_a?(String) && id.size < 256 && id =~ /^[a-z0-9\-_]+$/
|
605
|
+
|
606
|
+
raise Wavefront::Exception::InvalidMonitoredClusterId, id
|
607
|
+
end
|
608
|
+
|
609
|
+
# Ensure the given value is a valid sampling rate.
|
610
|
+
# @param rate [Float]
|
611
|
+
# @raise Wavefront::Exception::InvalidSamplingValue
|
612
|
+
#
|
613
|
+
def wf_sampling_value?(value)
|
614
|
+
return true if value.is_a?(Numeric) && value.between?(0, 0.05)
|
615
|
+
|
616
|
+
raise Wavefront::Exception::InvalidSamplingValue, value
|
617
|
+
end
|
597
618
|
end
|
598
619
|
# rubocop:enable Metrics/ModuleLength
|
599
620
|
end
|
data/lib/wavefront-sdk/write.rb
CHANGED
@@ -113,7 +113,7 @@ module Wavefront
|
|
113
113
|
# @return Wavefront::Response
|
114
114
|
#
|
115
115
|
def composite_response(responses)
|
116
|
-
result, code =
|
116
|
+
result, code = response_results(responses)
|
117
117
|
|
118
118
|
summary = { sent: 0, rejected: 0, unsent: 0 }
|
119
119
|
|
@@ -127,6 +127,14 @@ module Wavefront
|
|
127
127
|
)
|
128
128
|
end
|
129
129
|
|
130
|
+
def response_results(responses)
|
131
|
+
if responses.all?(&:ok?)
|
132
|
+
['OK', 200]
|
133
|
+
else
|
134
|
+
['ERROR', 400]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
130
138
|
def manage_conn
|
131
139
|
opts[:noauto] ? false : true
|
132
140
|
end
|
@@ -248,13 +256,5 @@ module Wavefront
|
|
248
256
|
rescue LoadError
|
249
257
|
raise(Wavefront::Exception::UnsupportedWriter, writer)
|
250
258
|
end
|
251
|
-
|
252
|
-
def response_codes(responses)
|
253
|
-
if responses.all?(&:ok?)
|
254
|
-
['OK', 200]
|
255
|
-
else
|
256
|
-
['ERROR', 400]
|
257
|
-
end
|
258
|
-
end
|
259
259
|
end
|
260
260
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -20,7 +20,7 @@ module Minitest
|
|
20
20
|
headers = DEFAULT_HEADERS
|
21
21
|
stub_request(:get, uri(api_path))
|
22
22
|
.with(headers: headers)
|
23
|
-
.to_return(body:
|
23
|
+
.to_return(body: dummy_response, status: 200)
|
24
24
|
yield block
|
25
25
|
assert_requested(:get, uri(api_path), headers: headers)
|
26
26
|
WebMock.reset!
|
@@ -39,7 +39,7 @@ module Minitest
|
|
39
39
|
payload = 'null' if payload.nil?
|
40
40
|
stub_request(:post, uri(api_path))
|
41
41
|
.with(body: payload, headers: headers)
|
42
|
-
.to_return(body:
|
42
|
+
.to_return(body: dummy_response, status: 200)
|
43
43
|
yield block
|
44
44
|
assert_requested(:post, uri(api_path), headers: headers)
|
45
45
|
WebMock.reset!
|
@@ -58,7 +58,7 @@ module Minitest
|
|
58
58
|
payload = 'null' if payload.nil?
|
59
59
|
stub_request(:put, uri(api_path))
|
60
60
|
.with(body: payload, headers: headers)
|
61
|
-
.to_return(body:
|
61
|
+
.to_return(body: dummy_response, status: 200)
|
62
62
|
yield block
|
63
63
|
assert_requested(:put, uri(api_path), headers: headers)
|
64
64
|
WebMock.reset!
|
@@ -72,7 +72,7 @@ module Minitest
|
|
72
72
|
headers = DEFAULT_HEADERS
|
73
73
|
stub_request(:delete, uri(api_path))
|
74
74
|
.with(headers: headers)
|
75
|
-
.to_return(body:
|
75
|
+
.to_return(body: dummy_response, status: 200)
|
76
76
|
yield block
|
77
77
|
assert_requested(:delete, uri(api_path), headers: headers)
|
78
78
|
WebMock.reset!
|
@@ -37,6 +37,49 @@ class WavefrontApiCallerTest < MiniTest::Test
|
|
37
37
|
assert_requested(:get, uri, headers: headers)
|
38
38
|
end
|
39
39
|
|
40
|
+
def test_get_flat_params
|
41
|
+
query = { rkey: %w[val1 val2 val3], ukey: 36 }
|
42
|
+
uri = "#{uri_base}/path?rkey=val1&rkey=val2&rkey=val3&ukey=36"
|
43
|
+
stub_request(:get, uri).to_return(body: DUMMY_RESPONSE, status: 200)
|
44
|
+
wf.get_flat_params('/path', query)
|
45
|
+
assert_requested(:get, uri, headers: headers)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_get_stream
|
49
|
+
uri = "#{uri_base}/path?key1=val1"
|
50
|
+
stub_request(:get, uri).to_return(body: DUMMY_RESPONSE, status: 200)
|
51
|
+
out, err = capture_io { wf.get_stream('/path', key1: 'val1') }
|
52
|
+
assert_requested(:get, uri, headers: headers)
|
53
|
+
assert_equal(out.strip, DUMMY_RESPONSE)
|
54
|
+
assert_empty(err)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_get_stream_array_params
|
58
|
+
uri = "#{uri_base}/path?key=val1&key=val2"
|
59
|
+
stub_request(:get, uri).to_return(body: DUMMY_RESPONSE, status: 200)
|
60
|
+
out, err = capture_io { wf.get_stream('/path', key: %w[val1 val2]) }
|
61
|
+
assert_requested(:get, uri, headers: headers)
|
62
|
+
assert_equal(out.strip, DUMMY_RESPONSE)
|
63
|
+
assert_empty(err)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_get_stream_timestamp
|
67
|
+
uri = "#{uri_base}/path?key1=val1"
|
68
|
+
stub_request(:get, uri).to_return(body: DUMMY_RESPONSE, status: 200)
|
69
|
+
|
70
|
+
out, err = capture_io do
|
71
|
+
wf.get_stream('/path',
|
72
|
+
{ key1: 'val1' },
|
73
|
+
timestamp_chunks: true)
|
74
|
+
end
|
75
|
+
|
76
|
+
assert_requested(:get, uri, headers: headers)
|
77
|
+
out_lines = out.split("\n")
|
78
|
+
assert_match(/^\d{4}-\d\d-\d\d \d\d:\d\d:\d\d \+\d{4}$/, out_lines[0])
|
79
|
+
assert_equal(out_lines[1], DUMMY_RESPONSE)
|
80
|
+
assert_empty(err)
|
81
|
+
end
|
82
|
+
|
40
83
|
def test_post
|
41
84
|
uri = "#{uri_base}/path"
|
42
85
|
obj = { key: 'value' }
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../spec_helper'
|
5
|
+
require_relative '../test_mixins/general'
|
6
|
+
require_relative '../test_mixins/tag'
|
7
|
+
|
8
|
+
# Unit tests for MonitoredCluster class
|
9
|
+
#
|
10
|
+
class WavefrontMonitoredClusterTest < WavefrontTestBase
|
11
|
+
include WavefrontTest::Create
|
12
|
+
include WavefrontTest::Delete
|
13
|
+
include WavefrontTest::Describe
|
14
|
+
include WavefrontTest::List
|
15
|
+
include WavefrontTest::Update
|
16
|
+
include WavefrontTest::Tag
|
17
|
+
|
18
|
+
def test_merge
|
19
|
+
assert_puts("/api/v2/monitoredcluster/merge/#{id}/#{id2}", nil, :json) do
|
20
|
+
wf.merge(id, id2)
|
21
|
+
end
|
22
|
+
|
23
|
+
assert_invalid_id { wf.merge(id, invalid_id) }
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def api_class
|
29
|
+
'monitoredcluster'
|
30
|
+
end
|
31
|
+
|
32
|
+
def id
|
33
|
+
'k8s-sample'
|
34
|
+
end
|
35
|
+
|
36
|
+
def id2
|
37
|
+
'eks-cluster'
|
38
|
+
end
|
39
|
+
|
40
|
+
def invalid_id
|
41
|
+
'!!!!'
|
42
|
+
end
|
43
|
+
|
44
|
+
def payload
|
45
|
+
{ id: 'k8s-sample',
|
46
|
+
name: 'Sample cluster',
|
47
|
+
platform: 'EKS',
|
48
|
+
version: '1.2',
|
49
|
+
additionalTags: {
|
50
|
+
region: 'us-west-2',
|
51
|
+
az: 'testing'
|
52
|
+
},
|
53
|
+
tags: %w[alertTag1] }
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../../spec_helper'
|
5
|
+
require_relative '../../../lib/wavefront-sdk/unstable/chart'
|
6
|
+
|
7
|
+
# Unit tests for Chart class
|
8
|
+
#
|
9
|
+
class WavefrontChartTest < MiniTest::Test
|
10
|
+
attr_reader :wf
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@wf = Wavefront::Unstable::Chart.new(CREDS)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_all_metrics
|
17
|
+
assert_gets('/chart/metrics/all?l=100&q=&trie=true') do
|
18
|
+
wf.metrics_under('')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_metrics_under
|
23
|
+
assert_gets('/chart/metrics/all?l=100&q=test.path&trie=true') do
|
24
|
+
wf.metrics_under('test.path')
|
25
|
+
end
|
26
|
+
|
27
|
+
assert_gets('/chart/metrics/all?l=10&q=test.path&trie=true') do
|
28
|
+
wf.metrics_under('test.path', nil, 10)
|
29
|
+
end
|
30
|
+
|
31
|
+
assert_gets('/chart/metrics/all?l=100&p=last.one&q=test.path&trie=true') do
|
32
|
+
wf.metrics_under('test.path', 'last.one')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def dummy_response
|
37
|
+
{ metrics: ['test data'] }.to_json
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../../spec_helper'
|
5
|
+
require_relative '../../../lib/wavefront-sdk/unstable/spy'
|
6
|
+
|
7
|
+
# Unit tests for Spy class
|
8
|
+
#
|
9
|
+
class WavefrontSpyTest < MiniTest::Test
|
10
|
+
attr_reader :wf
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@wf = Wavefront::Unstable::Spy.new(CREDS)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_points
|
17
|
+
capture_io do
|
18
|
+
assert_gets('/api/spy/points?sampling=0.01') { wf.points }
|
19
|
+
assert_gets('/api/spy/points?sampling=0.05') { wf.points(0.05) }
|
20
|
+
|
21
|
+
assert_gets('/api/spy/points?sampling=0.05&metric=my_prefix') do
|
22
|
+
wf.points(0.05, prefix: 'my_prefix')
|
23
|
+
end
|
24
|
+
|
25
|
+
assert_gets('/api/spy/points?sampling=0.05&metric=my_prefix&host=h1') do
|
26
|
+
wf.points(0.05, prefix: 'my_prefix', host: 'h1')
|
27
|
+
end
|
28
|
+
|
29
|
+
assert_gets('/api/spy/points?sampling=0.02&metric=my_prefix&' \
|
30
|
+
'pointTagKey=mytag') do
|
31
|
+
wf.points(0.02, prefix: 'my_prefix', tag_key: 'mytag')
|
32
|
+
end
|
33
|
+
|
34
|
+
assert_gets('/api/spy/points?sampling=0.02&metric=my_prefix&' \
|
35
|
+
'pointTagKey=tag1&pointTagKey=tag2') do
|
36
|
+
wf.points(0.02, prefix: 'my_prefix', tag_key: %w[tag1 tag2])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_histograms
|
42
|
+
capture_io do
|
43
|
+
assert_gets('/api/spy/histograms?sampling=0.01') { wf.histograms }
|
44
|
+
assert_gets('/api/spy/histograms?sampling=0.05') { wf.histograms(0.05) }
|
45
|
+
|
46
|
+
assert_gets('/api/spy/histograms?sampling=0.05&histogram=my_prefix') do
|
47
|
+
wf.histograms(0.05, prefix: 'my_prefix')
|
48
|
+
end
|
49
|
+
|
50
|
+
assert_gets(
|
51
|
+
'/api/spy/histograms?sampling=0.05&histogram=my_prefix&host=h1'
|
52
|
+
) do
|
53
|
+
wf.histograms(0.05, prefix: 'my_prefix', host: 'h1')
|
54
|
+
end
|
55
|
+
|
56
|
+
assert_gets('/api/spy/histograms?sampling=0.02&histogram=my_prefix&' \
|
57
|
+
'histogramTagKey=the_tag') do
|
58
|
+
wf.histograms(0.02, prefix: 'my_prefix', tag_key: 'the_tag')
|
59
|
+
end
|
60
|
+
|
61
|
+
assert_gets('/api/spy/histograms?sampling=0.02&histogram=my_prefix&' \
|
62
|
+
'histogramTagKey=tag1&histogramTagKey=tag2') do
|
63
|
+
wf.histograms(0.02, prefix: 'my_prefix', tag_key: %w[tag1 tag2])
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_spans
|
69
|
+
capture_io do
|
70
|
+
assert_gets('/api/spy/spans?sampling=0.01') { wf.spans }
|
71
|
+
assert_gets('/api/spy/spans?sampling=0.05') { wf.spans(0.05) }
|
72
|
+
|
73
|
+
assert_gets('/api/spy/spans?sampling=0.05&name=my_prefix') do
|
74
|
+
wf.spans(0.05, prefix: 'my_prefix')
|
75
|
+
end
|
76
|
+
|
77
|
+
assert_gets(
|
78
|
+
'/api/spy/spans?sampling=0.05&name=my_prefix&host=h1'
|
79
|
+
) do
|
80
|
+
wf.spans(0.05, prefix: 'my_prefix', host: 'h1')
|
81
|
+
end
|
82
|
+
|
83
|
+
assert_gets('/api/spy/spans?sampling=0.02&name=my_prefix&' \
|
84
|
+
'spanTagKey=the_tag') do
|
85
|
+
wf.spans(0.02, prefix: 'my_prefix', tag_key: 'the_tag')
|
86
|
+
end
|
87
|
+
|
88
|
+
assert_gets('/api/spy/spans?sampling=0.02&name=my_prefix&' \
|
89
|
+
'spanTagKey=tag1&spanTagKey=tag2') do
|
90
|
+
wf.spans(0.02, prefix: 'my_prefix', tag_key: %w[tag1 tag2])
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_ids
|
96
|
+
capture_io do
|
97
|
+
assert_gets('/api/spy/ids?sampling=0.01') { wf.ids }
|
98
|
+
assert_gets('/api/spy/ids?sampling=0.05') { wf.ids(0.05) }
|
99
|
+
|
100
|
+
assert_gets('/api/spy/ids?sampling=0.05&type=METRIC') do
|
101
|
+
wf.ids(0.05, type: 'METRIC')
|
102
|
+
end
|
103
|
+
|
104
|
+
assert_gets('/api/spy/ids?sampling=0.05&type=SPAN&name=my_prefix') do
|
105
|
+
wf.ids(0.05, type: 'SPAN', prefix: 'my_prefix')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def dummy_response
|
111
|
+
DUMMY_RESPONSE
|
112
|
+
end
|
113
|
+
end
|
@@ -386,4 +386,19 @@ class WavefrontValidatorsTest < MiniTest::Test
|
|
386
386
|
bad = ['', [], {}, 'a' * 1000]
|
387
387
|
good_and_bad('wf_account_id?', 'InvalidAccountId', good, bad)
|
388
388
|
end
|
389
|
+
|
390
|
+
def test_wf_managedcluster_id
|
391
|
+
good = %w[test-cluster other-cluster cluster]
|
392
|
+
bad = ['', [], {}, 'a' * 1000, '£"^WR"!']
|
393
|
+
good_and_bad('wf_monitoredcluster_id?',
|
394
|
+
'InvalidMonitoredClusterId',
|
395
|
+
good,
|
396
|
+
bad)
|
397
|
+
end
|
398
|
+
|
399
|
+
def test_wf_sampling_value
|
400
|
+
good = [0, 0.01, 0.003, 0.05]
|
401
|
+
bad = ['a', 0.1, 0.99, 1, -1, 1.1]
|
402
|
+
good_and_bad('wf_sampling_value?', 'InvalidSamplingValue', good, bad)
|
403
|
+
end
|
389
404
|
end
|
data/wavefront-sdk.gemspec
CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |gem|
|
|
23
23
|
gem.bindir = 'bin'
|
24
24
|
|
25
25
|
gem.add_dependency 'addressable', '~> 2.7'
|
26
|
-
gem.add_dependency 'faraday', '~>
|
26
|
+
gem.add_dependency 'faraday', '~> 1.0'
|
27
27
|
gem.add_dependency 'inifile', '~> 3.0'
|
28
28
|
gem.add_dependency 'map', '~> 6.6'
|
29
29
|
|
@@ -35,5 +35,5 @@ Gem::Specification.new do |gem|
|
|
35
35
|
gem.add_development_dependency 'webmock', '~> 3.7'
|
36
36
|
gem.add_development_dependency 'yard', '~> 0.9'
|
37
37
|
|
38
|
-
gem.required_ruby_version = Gem::Requirement.new('>= 2.
|
38
|
+
gem.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
|
39
39
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wavefront-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Fisher
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-02-
|
11
|
+
date: 2020-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: '1.0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: '1.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: inifile
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -205,6 +205,7 @@ files:
|
|
205
205
|
- lib/wavefront-sdk/message.rb
|
206
206
|
- lib/wavefront-sdk/metric.rb
|
207
207
|
- lib/wavefront-sdk/metric_helper.rb
|
208
|
+
- lib/wavefront-sdk/monitoredcluster.rb
|
208
209
|
- lib/wavefront-sdk/notificant.rb
|
209
210
|
- lib/wavefront-sdk/paginator/base.rb
|
210
211
|
- lib/wavefront-sdk/paginator/delete.rb
|
@@ -222,9 +223,14 @@ files:
|
|
222
223
|
- lib/wavefront-sdk/stdlib/array.rb
|
223
224
|
- lib/wavefront-sdk/stdlib/hash.rb
|
224
225
|
- lib/wavefront-sdk/stdlib/string.rb
|
226
|
+
- lib/wavefront-sdk/stdlib/time.rb
|
225
227
|
- lib/wavefront-sdk/support/mixins.rb
|
226
228
|
- lib/wavefront-sdk/support/parse_time.rb
|
227
229
|
- lib/wavefront-sdk/types/status.rb
|
230
|
+
- lib/wavefront-sdk/unstable/README.md
|
231
|
+
- lib/wavefront-sdk/unstable/chart.rb
|
232
|
+
- lib/wavefront-sdk/unstable/spy.rb
|
233
|
+
- lib/wavefront-sdk/unstable/unstable.rb
|
228
234
|
- lib/wavefront-sdk/usage.rb
|
229
235
|
- lib/wavefront-sdk/user.rb
|
230
236
|
- lib/wavefront-sdk/usergroup.rb
|
@@ -270,6 +276,7 @@ files:
|
|
270
276
|
- spec/wavefront-sdk/message_spec.rb
|
271
277
|
- spec/wavefront-sdk/metric_helper_spec.rb
|
272
278
|
- spec/wavefront-sdk/metric_spec.rb
|
279
|
+
- spec/wavefront-sdk/monitoredcluster_spec.rb
|
273
280
|
- spec/wavefront-sdk/notificant_spec.rb
|
274
281
|
- spec/wavefront-sdk/paginator/base_spec.rb
|
275
282
|
- spec/wavefront-sdk/paginator/post_spec.rb
|
@@ -296,6 +303,8 @@ files:
|
|
296
303
|
- spec/wavefront-sdk/stdlib/string_spec.rb
|
297
304
|
- spec/wavefront-sdk/support/mixins_spec.rb
|
298
305
|
- spec/wavefront-sdk/support/parse_time_spec.rb
|
306
|
+
- spec/wavefront-sdk/unstable/chart_spec.rb
|
307
|
+
- spec/wavefront-sdk/unstable/spy_spec.rb
|
299
308
|
- spec/wavefront-sdk/usage_spec.rb
|
300
309
|
- spec/wavefront-sdk/user_spec.rb
|
301
310
|
- spec/wavefront-sdk/usergroup_spec.rb
|
@@ -320,7 +329,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
320
329
|
requirements:
|
321
330
|
- - ">="
|
322
331
|
- !ruby/object:Gem::Version
|
323
|
-
version: 2.
|
332
|
+
version: 2.4.0
|
324
333
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
325
334
|
requirements:
|
326
335
|
- - ">="
|
@@ -365,6 +374,7 @@ test_files:
|
|
365
374
|
- spec/wavefront-sdk/message_spec.rb
|
366
375
|
- spec/wavefront-sdk/metric_helper_spec.rb
|
367
376
|
- spec/wavefront-sdk/metric_spec.rb
|
377
|
+
- spec/wavefront-sdk/monitoredcluster_spec.rb
|
368
378
|
- spec/wavefront-sdk/notificant_spec.rb
|
369
379
|
- spec/wavefront-sdk/paginator/base_spec.rb
|
370
380
|
- spec/wavefront-sdk/paginator/post_spec.rb
|
@@ -391,6 +401,8 @@ test_files:
|
|
391
401
|
- spec/wavefront-sdk/stdlib/string_spec.rb
|
392
402
|
- spec/wavefront-sdk/support/mixins_spec.rb
|
393
403
|
- spec/wavefront-sdk/support/parse_time_spec.rb
|
404
|
+
- spec/wavefront-sdk/unstable/chart_spec.rb
|
405
|
+
- spec/wavefront-sdk/unstable/spy_spec.rb
|
394
406
|
- spec/wavefront-sdk/usage_spec.rb
|
395
407
|
- spec/wavefront-sdk/user_spec.rb
|
396
408
|
- spec/wavefront-sdk/usergroup_spec.rb
|