wavefront-sdk 3.0.2 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/HISTORY.md +12 -1
  3. data/README.md +4 -0
  4. data/Rakefile +1 -0
  5. data/lib/wavefront-sdk/alert.rb +36 -49
  6. data/lib/wavefront-sdk/api_mixins/acl.rb +76 -0
  7. data/lib/wavefront-sdk/api_mixins/tag.rb +62 -0
  8. data/lib/wavefront-sdk/api_mixins/user.rb +26 -0
  9. data/lib/wavefront-sdk/apitoken.rb +49 -0
  10. data/lib/wavefront-sdk/core/exception.rb +1 -0
  11. data/lib/wavefront-sdk/dashboard.rb +6 -106
  12. data/lib/wavefront-sdk/defs/version.rb +1 -1
  13. data/lib/wavefront-sdk/derivedmetric.rb +6 -56
  14. data/lib/wavefront-sdk/event.rb +4 -50
  15. data/lib/wavefront-sdk/paginator/base.rb +8 -7
  16. data/lib/wavefront-sdk/paginator/post.rb +7 -5
  17. data/lib/wavefront-sdk/source.rb +4 -48
  18. data/lib/wavefront-sdk/user.rb +2 -2
  19. data/lib/wavefront-sdk/usergroup.rb +2 -2
  20. data/lib/wavefront-sdk/validators.rb +10 -0
  21. data/lib/wavefront-sdk/write.rb +43 -12
  22. data/lib/wavefront-sdk/writers/socket.rb +2 -2
  23. data/spec/.rubocop.yml +1 -1
  24. data/spec/spec_helper.rb +66 -0
  25. data/spec/wavefront-sdk/alert_spec.rb +14 -0
  26. data/spec/wavefront-sdk/{support → api_mixins}/user_mixins_spec.rb +2 -2
  27. data/spec/wavefront-sdk/apitoken_spec.rb +31 -0
  28. data/spec/wavefront-sdk/core/api_spec.rb +3 -5
  29. data/spec/wavefront-sdk/credentials_spec.rb +41 -37
  30. data/spec/wavefront-sdk/dashboard_spec.rb +4 -52
  31. data/spec/wavefront-sdk/distribution_spec.rb +1 -3
  32. data/spec/wavefront-sdk/metric_helper_spec.rb +6 -8
  33. data/spec/wavefront-sdk/report_spec.rb +2 -2
  34. data/spec/wavefront-sdk/stdlib/array_spec.rb +6 -6
  35. data/spec/wavefront-sdk/stdlib/hash_spec.rb +5 -5
  36. data/spec/wavefront-sdk/support/mixins_spec.rb +34 -36
  37. data/spec/wavefront-sdk/support/parse_time_spec.rb +25 -29
  38. data/spec/wavefront-sdk/usergroup_spec.rb +34 -34
  39. data/spec/wavefront-sdk/validators_spec.rb +10 -1
  40. data/spec/wavefront-sdk/write_spec.rb +71 -4
  41. data/spec/wavefront-sdk/writers/core_spec.rb +10 -10
  42. data/spec/wavefront-sdk/writers/socket_spec.rb +13 -1
  43. metadata +10 -5
  44. data/lib/wavefront-sdk/support/user_mixins.rb +0 -24
@@ -1,4 +1,4 @@
1
1
  require 'pathname'
2
2
 
3
- WF_SDK_VERSION = '3.0.2'.freeze
3
+ WF_SDK_VERSION = '3.2.0'.freeze
4
4
  WF_SDK_LOCATION = Pathname.new(__FILE__).dirname.parent.parent.parent
@@ -1,13 +1,12 @@
1
1
  require_relative 'core/api'
2
+ require_relative 'api_mixins/tag'
2
3
 
3
4
  module Wavefront
4
5
  #
5
6
  # View and manage derived metrics
6
7
  #
7
8
  class DerivedMetric < CoreApi
8
- def update_keys
9
- # %i[id name url description sections]
10
- end
9
+ include Wavefront::Mixin::Tag
11
10
 
12
11
  # GET /api/v2/derivedmetric
13
12
  # Get all derived metric definitions for a customer.
@@ -94,59 +93,6 @@ module Wavefront
94
93
  api.get([id, 'history'].uri_concat)
95
94
  end
96
95
 
97
- # GET /api/v2/derivedmetric/id/tag
98
- # Get all tags associated with a specific derived metric
99
- # definition.
100
- #
101
- # @param id [String] ID of the derived metric
102
- # @return [Wavefront::Response]
103
- #
104
- def tags(id)
105
- wf_derivedmetric_id?(id)
106
- api.get([id, 'tag'].uri_concat)
107
- end
108
-
109
- # POST /api/v2/derivedmetric/id/tag
110
- # Set all tags associated with a specific derived metric
111
- # definition.
112
- #
113
- # @param id [String] ID of the derived metric
114
- # @param tags [Array] list of tags to set.
115
- # @return [Wavefront::Response]
116
- #
117
- def tag_set(id, tags)
118
- wf_derivedmetric_id?(id)
119
- tags = Array(tags)
120
- tags.each { |t| wf_string?(t) }
121
- api.post([id, 'tag'].uri_concat, tags.to_json, 'application/json')
122
- end
123
-
124
- # DELETE /api/v2/derivedmetric/id/tag/tagValue
125
- # Remove a tag from a specific derived metric definition.
126
- #
127
- # @param id [String] ID of the derived metric
128
- # @param tag [String] tag to delete
129
- # @return [Wavefront::Response]
130
- #
131
- def tag_delete(id, tag)
132
- wf_derivedmetric_id?(id)
133
- wf_string?(tag)
134
- api.delete([id, 'tag', tag].uri_concat)
135
- end
136
-
137
- # PUT /api/v2/derivedmetric/id/tag/tagValue
138
- # Add a tag to a specific derived metric definition.
139
- #
140
- # @param id [String] ID of the derived metric
141
- # @param tag [String] tag to set.
142
- # @return [Wavefront::Response]
143
- #
144
- def tag_add(id, tag)
145
- wf_derivedmetric_id?(id)
146
- wf_string?(tag)
147
- api.put([id, 'tag', tag].uri_concat)
148
- end
149
-
150
96
  # POST /api/v2/derivedmetric/id/undelete
151
97
  # Move a derived metric definition from 'trash' back into active
152
98
  # service.
@@ -158,5 +104,9 @@ module Wavefront
158
104
  wf_derivedmetric_id?(id)
159
105
  api.post([id, 'undelete'].uri_concat)
160
106
  end
107
+
108
+ def valid_id?(id)
109
+ wf_derivedmetric_id?(id)
110
+ end
161
111
  end
162
112
  end
@@ -1,4 +1,5 @@
1
1
  require_relative 'core/api'
2
+ require_relative 'api_mixins/tag'
2
3
 
3
4
  module Wavefront
4
5
  #
@@ -6,6 +7,8 @@ module Wavefront
6
7
  # epoch timestamp.
7
8
  #
8
9
  class Event < CoreApi
10
+ include Wavefront::Mixin::Tag
11
+
9
12
  def update_keys
10
13
  %i[startTime endTime name annotations]
11
14
  end
@@ -115,57 +118,8 @@ module Wavefront
115
118
  api.post([id, 'close'].uri_concat)
116
119
  end
117
120
 
118
- # GET /api/v2/event/id/tag
119
- # Get all tags associated with a specific event
120
- #
121
- # @param id [String] ID of the event
122
- # @return [Wavefront::Response]
123
- # response keys
124
- #
125
- def tags(id)
126
- wf_event_id?(id)
127
- api.get([id, 'tag'].uri_concat)
128
- end
129
-
130
- # POST /api/v2/event/id/tag
131
- # Set all tags associated with a specific event.
132
- #
133
- # @param id [String] ID of the event
134
- # @param tags [Array] list of tags to set.
135
- # @return [Wavefront::Response]
136
- # response keys
137
- #
138
- def tag_set(id, tags)
139
- wf_event_id?(id)
140
- tags = Array(tags)
141
- tags.each { |t| wf_string?(t) }
142
- api.post([id, 'tag'].uri_concat, tags, 'application/json')
143
- end
144
-
145
- # DELETE /api/v2/event/id/tag/tagValue
146
- # Remove a tag from a specific event.
147
- #
148
- # @param id [String] ID of the event
149
- # @param tag [String] tag to delete
150
- # @return [Wavefront::Response]
151
- #
152
- def tag_delete(id, tag)
153
- wf_event_id?(id)
154
- wf_string?(tag)
155
- api.delete([id, 'tag', tag].uri_concat)
156
- end
157
-
158
- # PUT /api/v2/event/id/tag/tagValue
159
- # Add a tag to a specific event.
160
- #
161
- # @param id [String] ID of the event
162
- # @param tag [String] tag to set.
163
- # @return [Wavefront::Response]
164
- #
165
- def tag_add(id, tag)
121
+ def valid_id?(id)
166
122
  wf_event_id?(id)
167
- wf_string?(tag)
168
- api.put([id, 'tag', tag].uri_concat)
169
123
  end
170
124
  end
171
125
  end
@@ -80,13 +80,14 @@ module Wavefront
80
80
  #
81
81
  def set_pagination(offset, page_size, args)
82
82
  args.map do |arg|
83
- if arg.is_a?(Hash)
84
- arg.tap do |a|
85
- a[:limit] = page_size if a.key?(:limit)
86
- a[:offset] = offset if a.key?(:offset)
87
- end
88
- end
89
- arg
83
+ arg.is_a?(Hash) ? set_limit_and_offset(arg, page_size, offset) : arg
84
+ end
85
+ end
86
+
87
+ def set_limit_and_offset(arg, page_size, offset)
88
+ arg.tap do |a|
89
+ a[:limit] = page_size if a.key?(:limit)
90
+ a[:offset] = offset if a.key?(:offset)
90
91
  end
91
92
  end
92
93
 
@@ -50,15 +50,17 @@ module Wavefront
50
50
 
51
51
  return args if body.class == desired
52
52
 
53
- args[index] = if body.is_a?(String)
54
- JSON.parse(body, symbolize_names: true)
55
- else
56
- body.to_json
57
- end
53
+ args[index] = body_as_json(body)
58
54
  args
59
55
  rescue JSON::ParserError
60
56
  []
61
57
  end
58
+
59
+ def body_as_json(body)
60
+ return body.to_json unless body.is_a?(String)
61
+
62
+ JSON.parse(body, symbolize_names: true)
63
+ end
62
64
  end
63
65
  end
64
66
  end
@@ -1,10 +1,13 @@
1
1
  require_relative 'core/api'
2
+ require_relative 'api_mixins/tag'
2
3
 
3
4
  module Wavefront
4
5
  #
5
6
  # View and manage source metadata.
6
7
  #
7
8
  class Source < CoreApi
9
+ include Wavefront::Mixin::Tag
10
+
8
11
  def update_keys
9
12
  %i[sourceName tags description]
10
13
  end
@@ -100,55 +103,8 @@ module Wavefront
100
103
  'application/json')
101
104
  end
102
105
 
103
- # GET /api/v2/source/id/tag
104
- # Get all tags associated with a specific source.
105
- #
106
- # @param id [String] ID of the source
107
- # @return [Wavefront::Response]
108
- #
109
- def tags(id)
110
- wf_source_id?(id)
111
- api.get([id, 'tag'].uri_concat)
112
- end
113
-
114
- # POST /api/v2/source/id/tag
115
- # Set all tags associated with a specific source.
116
- #
117
- # @param id [String] ID of the source
118
- # @param tags [Array] list of tags to set.
119
- # @return [Wavefront::Response]
120
- #
121
- def tag_set(id, tags)
122
- wf_source_id?(id)
123
- tags = Array(tags)
124
- tags.each { |t| wf_string?(t) }
125
- api.post([id, 'tag'].uri_concat, tags.to_json, 'application/json')
126
- end
127
-
128
- # DELETE /api/v2/source/id/tag/tagValue
129
- # Remove a tag from a specific source.
130
- #
131
- # @param id [String] ID of the source
132
- # @param tag [String] tag to delete
133
- # @return [Wavefront::Response]
134
- #
135
- def tag_delete(id, tag)
136
- wf_source_id?(id)
137
- wf_string?(tag)
138
- api.delete([id, 'tag', tag].uri_concat)
139
- end
140
-
141
- # PUT /api/v2/source/id/tag/tagValue
142
- # Add a tag to a specific source
143
- #
144
- # @param id [String] ID of the source
145
- # @param tag [String] tag to set.
146
- # @return [Wavefront::Response]
147
- #
148
- def tag_add(id, tag)
106
+ def valid_id?(id)
149
107
  wf_source_id?(id)
150
- wf_string?(tag)
151
- api.put([id, 'tag', tag].uri_concat)
152
108
  end
153
109
  end
154
110
  end
@@ -1,12 +1,12 @@
1
1
  require_relative 'core/api'
2
- require_relative 'support/user_mixins'
2
+ require_relative 'api_mixins/user'
3
3
 
4
4
  module Wavefront
5
5
  #
6
6
  # Manage and query Wavefront users
7
7
  #
8
8
  class User < CoreApi
9
- include Wavefront::UserMixins
9
+ include Wavefront::Mixin::User
10
10
 
11
11
  # GET /api/v2/user
12
12
  # Get all users.
@@ -1,12 +1,12 @@
1
1
  require_relative 'core/api'
2
- require_relative 'support/user_mixins'
2
+ require_relative 'api_mixins/user'
3
3
 
4
4
  module Wavefront
5
5
  #
6
6
  # Manage and query Wavefront user groups
7
7
  #
8
8
  class UserGroup < CoreApi
9
- include Wavefront::UserMixins
9
+ include Wavefront::Mixin::User
10
10
 
11
11
  def update_keys
12
12
  %i[id name]
@@ -502,6 +502,16 @@ module Wavefront
502
502
  return true if count.is_a?(Integer) && count.positive?
503
503
  raise Wavefront::Exception::InvalidDistributionCount
504
504
  end
505
+
506
+ # Ensure the given argument is a valid API token ID
507
+ # @param id [String]
508
+ # @raise Wavefront::Exception::InvalidApiTokenId if the
509
+ # count is not valid
510
+ #
511
+ def wf_apitoken_id?(id)
512
+ return true if uuid?(id)
513
+ raise Wavefront::Exception::InvalidApiTokenId
514
+ end
505
515
  end
506
516
  # rubocop:enable Metrics/ModuleLength
507
517
  end
@@ -1,6 +1,7 @@
1
1
  require 'socket'
2
2
  require_relative 'core/exception'
3
3
  require_relative 'core/logger'
4
+ require_relative 'core/response'
4
5
  require_relative 'defs/constants'
5
6
  require_relative 'validators'
6
7
 
@@ -40,16 +41,14 @@ module Wavefront
40
41
  # noauto [Bool] if this is false, #write will automatically
41
42
  # open a connection to Wavefront on each invocation. Set
42
43
  # this to true to manually manage the connection.
44
+ # chunk_size [Integer] So as not to create unusable metric
45
+ # payloads, large batches of points will be broken into
46
+ # chunks. This property controls the number of metrics in a
47
+ # chunk. Defaults to 1,000.
48
+ # chunk_pause [Integer] pause this many seconds between
49
+ # writing chunks. Defaults to zero.
43
50
  #
44
51
  def initialize(creds = {}, opts = {})
45
- defaults = { tags: nil,
46
- writer: :socket,
47
- noop: false,
48
- novalidate: false,
49
- noauto: false,
50
- verbose: false,
51
- debug: false }
52
-
53
52
  @opts = setup_options(opts, defaults)
54
53
  @creds = creds
55
54
  wf_point_tags?(opts[:tags]) if opts[:tags]
@@ -57,6 +56,18 @@ module Wavefront
57
56
  @writer = setup_writer
58
57
  end
59
58
 
59
+ def defaults
60
+ { tags: nil,
61
+ writer: :socket,
62
+ noop: false,
63
+ novalidate: false,
64
+ noauto: false,
65
+ verbose: false,
66
+ debug: false,
67
+ chunk_size: 1000,
68
+ chunk_pause: 0 }
69
+ end
70
+
60
71
  def setup_options(user, defaults)
61
72
  defaults.merge(user)
62
73
  end
@@ -78,15 +89,35 @@ module Wavefront
78
89
  # Writers implement this method differently, Check the
79
90
  # appropriate class documentation for @return information etc.
80
91
  # The signature is always the same.
92
+ # @return [Boolean] false should any chunk fail
93
+ # @raise any exceptions raised by the writer classes are passed
94
+ # through
81
95
  #
82
96
  def write(points = [], openclose = manage_conn, prefix = nil)
83
- writer.write(points, openclose, prefix)
97
+ resps = [points].flatten.each_slice(opts[:chunk_size]).map do |chunk|
98
+ resp = writer.write(chunk, openclose, prefix)
99
+ sleep(opts[:chunk_pause])
100
+ resp
101
+ end
102
+
103
+ composite_response(resps)
84
104
  end
85
105
 
86
- # Wrapper around writer class's #flush method
106
+ # Compound the responses of all chunked writes into one. It will
107
+ # be 'ok' only if *everything* passed.
87
108
  #
88
- def flush
89
- writer.flush
109
+ def composite_response(responses)
110
+ result = responses.all?(&:ok?) ? 'OK' : 'ERROR'
111
+ summary = { sent: 0, rejected: 0, unsent: 0 }
112
+
113
+ %i[sent rejected unsent].each do |k|
114
+ summary[k] = responses.map { |r| r.response[k] }.inject(:+)
115
+ end
116
+
117
+ Wavefront::Response.new(
118
+ { status: { result: result, message: nil, code: nil },
119
+ response: summary.to_h }.to_json, nil
120
+ )
90
121
  end
91
122
 
92
123
  def manage_conn
@@ -49,11 +49,11 @@ module Wavefront
49
49
 
50
50
  private
51
51
 
52
- # @param point [String] point or points in native Wavefront
53
- # format.
52
+ # @param point [String] point or points in native Wavefront format.
54
53
  # @raise [SocketError] if point cannot be written
55
54
  #
56
55
  def _send_point(point)
56
+ return if opts[:noop]
57
57
  conn.puts(point)
58
58
  rescue StandardError
59
59
  raise Wavefront::Exception::SocketError
data/spec/.rubocop.yml CHANGED
@@ -11,7 +11,7 @@ Metrics/MethodLength:
11
11
  Max: 80
12
12
 
13
13
  Metrics/AbcSize:
14
- Max: 45
14
+ Max: 80
15
15
 
16
16
  Metrics/ClassLength:
17
17
  Max: 300