wavefront-sdk 5.4.1 → 6.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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +1 -1
  3. data/.github/workflows/release.yml +37 -0
  4. data/.github/workflows/test.yml +23 -0
  5. data/.rubocop.yml +8 -6
  6. data/HISTORY.md +26 -0
  7. data/README.md +5 -5
  8. data/lib/wavefront-sdk/api_mixins/acl.rb +1 -1
  9. data/lib/wavefront-sdk/core/api.rb +1 -1
  10. data/lib/wavefront-sdk/core/api_caller.rb +2 -2
  11. data/lib/wavefront-sdk/core/exception.rb +58 -0
  12. data/lib/wavefront-sdk/credentials.rb +8 -8
  13. data/lib/wavefront-sdk/defs/version.rb +1 -1
  14. data/lib/wavefront-sdk/event.rb +70 -3
  15. data/lib/wavefront-sdk/metricspolicy.rb +57 -0
  16. data/lib/wavefront-sdk/query.rb +2 -0
  17. data/lib/wavefront-sdk/search.rb +2 -0
  18. data/lib/wavefront-sdk/spy.rb +22 -0
  19. data/lib/wavefront-sdk/support/parse_time.rb +1 -1
  20. data/lib/wavefront-sdk/user.rb +1 -1
  21. data/lib/wavefront-sdk/validators.rb +17 -2
  22. data/lib/wavefront-sdk/write.rb +3 -3
  23. data/lib/wavefront-sdk/writers/api.rb +2 -2
  24. data/lib/wavefront-sdk/writers/core.rb +1 -1
  25. data/lib/wavefront-sdk/writers/http.rb +2 -2
  26. data/lib/wavefront-sdk/writers/proxy.rb +71 -0
  27. data/lib/wavefront-sdk/writers/socket.rb +15 -27
  28. data/spec/.rubocop.yml +3 -15
  29. data/spec/constants.rb +2 -2
  30. data/spec/support/mocket.rb +3 -1
  31. data/spec/test_mixins/general.rb +1 -1
  32. data/spec/wavefront-sdk/core/response_spec.rb +2 -2
  33. data/spec/wavefront-sdk/event_spec.rb +46 -0
  34. data/spec/wavefront-sdk/metric_helper_spec.rb +6 -4
  35. data/spec/wavefront-sdk/metricspolicy_spec.rb +94 -0
  36. data/spec/wavefront-sdk/spy_spec.rb +27 -0
  37. data/spec/wavefront-sdk/validators_spec.rb +11 -1
  38. data/spec/wavefront-sdk/write_spec.rb +1 -1
  39. data/spec/wavefront-sdk/writers/api_spec.rb +4 -0
  40. data/spec/wavefront-sdk/writers/core_spec.rb +1 -3
  41. data/spec/wavefront-sdk/writers/http_spec.rb +24 -21
  42. data/spec/wavefront-sdk/writers/proxy_spec.rb +129 -0
  43. data/spec/wavefront-sdk/writers/socket_spec.rb +49 -27
  44. data/wavefront-sdk.gemspec +5 -3
  45. metadata +58 -11
  46. data/.github/workflows/ruby.yml +0 -32
  47. data/.travis.yml +0 -21
  48. data/lib/wavefront-sdk/writers/unix.rb +0 -59
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'core/api'
4
+
5
+ module Wavefront
6
+ #
7
+ # Manage and query Wavefront metrics policies
8
+ #
9
+ class MetricsPolicy < CoreApi
10
+ # GET /api/v2/metricspolicy
11
+ # Get the metrics policy
12
+ # GET /api/v2/metricspolicy/history/{version}
13
+ # Get a specific historical version of a metrics policy
14
+ # @param version [Integer] specify version to describe
15
+ # @return [Wavefront::Response]
16
+ #
17
+ def describe(version = nil)
18
+ if version
19
+ wf_version?(version)
20
+ api.get(['history', version].uri_concat)
21
+ else
22
+ api.get('')
23
+ end
24
+ end
25
+
26
+ # GET /api/v2/metricspolicy/history
27
+ # Get the version history of metrics policy
28
+ #
29
+ # @param offset [Integer] version at which the list begins
30
+ # @param limit [Integer] the number of versions to return
31
+ #
32
+ def history(offset = 0, limit = 100)
33
+ api.get('', offset: offset, limit: limit)
34
+ end
35
+
36
+ # POST /api/v2/metricspolicy/revert/{version}
37
+ # Revert to a specific historical version of a metrics policy
38
+ # @param version [Integer] specify version to describe
39
+ # @return [Wavefront::Response]
40
+ #
41
+ def revert(version)
42
+ wf_version?(version)
43
+ api.post(['revert', version].uri_concat)
44
+ end
45
+
46
+ # PUT /api/v2/metricspolicy
47
+ # Update the metrics policy
48
+ # @param body [Hash] hash describing metrics policy
49
+ # @return [Wavefront::Response]
50
+ #
51
+ def update(body)
52
+ raise ArgumentError unless body.is_a?(Hash)
53
+
54
+ api.put('', body, 'application/json')
55
+ end
56
+ end
57
+ end
@@ -30,6 +30,7 @@ module Wavefront
30
30
  # @raise [ArgumentError] if query is not a string
31
31
  # @return [Wavefront::Response]
32
32
  #
33
+ # rubocop:disable Metrics/ParameterLists
33
34
  def query(query, granularity = nil, t_start = nil, t_end = nil,
34
35
  options = {})
35
36
 
@@ -45,6 +46,7 @@ module Wavefront
45
46
 
46
47
  api.get('api', options)
47
48
  end
49
+ # rubocop:enable Metrics/ParameterLists
48
50
 
49
51
  # GET /api/v2/chart/raw
50
52
  # Perform a raw data query against Wavefront servers that
@@ -113,6 +113,7 @@ module Wavefront
113
113
  # specified in the body. See the Swagger docs for more
114
114
  # information.
115
115
  #
116
+ # rubocop:disable Metrics/ParameterLists
116
117
  def raw_facet_search(entity = nil, body = nil, deleted = false,
117
118
  facet = false)
118
119
  raise ArgumentError unless entity.is_a?(String) && body.is_a?(Hash)
@@ -122,5 +123,6 @@ module Wavefront
122
123
  path.<< facet || 'facets'
123
124
  api.post(path, body, 'application/json')
124
125
  end
126
+ # rubocop:enable Metrics/ParameterLists
125
127
  end
126
128
  end
@@ -32,6 +32,21 @@ module Wavefront
32
32
  api.get_stream('points', points_filter(sampling, filters), options)
33
33
  end
34
34
 
35
+ # GET /api/spy/deltas
36
+ # Gets new deltas that are added to existing time series.
37
+ # @param sampling [Float] see #points
38
+ # @param filter [Hash] see #points
39
+ # @param options [Hash] see #points
40
+ # @raise Wavefront::Exception::InvalidSamplingValue
41
+ # @return [Nil]
42
+ #
43
+ def deltas(sampling = 0.01, filters = {}, options = {})
44
+ wf_sampling_value?(sampling)
45
+ api.get_stream('deltas',
46
+ deltas_filter(sampling, filters),
47
+ options)
48
+ end
49
+
35
50
  # GET /api/spy/histograms
36
51
  # Gets new histograms that are added to existing time series.
37
52
  # @param sampling [Float] see #points
@@ -103,6 +118,13 @@ module Wavefront
103
118
  pointTagKey: filters.fetch(:tag_key, nil) }.compact
104
119
  end
105
120
 
121
+ def deltas_filter(sampling, filters)
122
+ { counter: filters.fetch(:prefix, nil),
123
+ host: filters.fetch(:host, nil),
124
+ sampling: sampling,
125
+ counterTagKey: filters.fetch(:tag_key, nil) }.compact
126
+ end
127
+
106
128
  def histograms_filter(sampling, filters)
107
129
  { histogram: filters.fetch(:prefix, nil),
108
130
  host: filters.fetch(:host, nil),
@@ -58,7 +58,7 @@ module Wavefront
58
58
  method = ('parse_time_' + t.class.name.downcase).to_sym
59
59
  send(method)
60
60
  rescue StandardError
61
- raise Wavefront::Exception::InvalidTimestamp
61
+ raise Wavefront::Exception::InvalidTimestamp, t
62
62
  end
63
63
  end
64
64
  end
@@ -19,7 +19,7 @@ module Wavefront
19
19
 
20
20
  def deprecation_warning
21
21
  logger.log('Wavefront::User is deprecated and will be removed from the ' \
22
- 'next major release. Please use Wavefront::Account.', :warn)
22
+ 'next major release. Please use Wavefront::Account.', :warn)
23
23
  end
24
24
 
25
25
  def post_initialize(_creds, _opts)
@@ -48,8 +48,8 @@ module Wavefront
48
48
  #
49
49
  def wf_metric_name?(metric)
50
50
  if metric.is_a?(String) && metric.size < 1024 &&
51
- (metric.match(/^#{DELTA}?[\w\-.]+$/) ||
52
- metric.match(%r{^"#{DELTA}?[\w\-./,]+"$}))
51
+ (metric.match(/^#{DELTA}?[\w\-.]+$/o) ||
52
+ metric.match(%r{^"#{DELTA}?[\w\-./,]+"$}o))
53
53
  return true
54
54
  end
55
55
 
@@ -467,6 +467,9 @@ module Wavefront
467
467
  true
468
468
  end
469
469
 
470
+ # @
471
+ def wf_trace?(trace); end
472
+
470
473
  # Validate an array of distribution values
471
474
  # @param vals [Array[Array]] [count, value]
472
475
  # @return true if valid
@@ -639,6 +642,18 @@ module Wavefront
639
642
 
640
643
  raise Wavefront::Exception::InvalidAwsExternalId, id
641
644
  end
645
+
646
+ # Ensure the given argument is a valid Wavefront metrics policy ID
647
+ # @param id [String] the metrics policy ID to validate
648
+ # @return true if the role ID is valid
649
+ # @raise Wavefront::Exception::InvalidMetricsPolicyId if the ID is
650
+ # not valid
651
+ #
652
+ def wf_metricspolicy_id?(id)
653
+ return true if uuid?(id)
654
+
655
+ raise Wavefront::Exception::InvalidMetricsPolicyId, id
656
+ end
642
657
  end
643
658
  # rubocop:enable Metrics/ModuleLength
644
659
  end
@@ -39,7 +39,7 @@ module Wavefront
39
39
  # verbose [Bool]
40
40
  # debug [Bool]
41
41
  # writer [Symbol, String] the name of the writer class to use.
42
- # Defaults to :socket
42
+ # Defaults to :proxy
43
43
  # noauto [Bool] if this is false, #write will automatically
44
44
  # open a connection to Wavefront on each invocation. Set
45
45
  # this to true to manually manage the connection.
@@ -62,7 +62,7 @@ module Wavefront
62
62
  #
63
63
  def defaults
64
64
  { tags: nil,
65
- writer: :socket,
65
+ writer: :proxy,
66
66
  noop: false,
67
67
  novalidate: false,
68
68
  noauto: false,
@@ -118,7 +118,7 @@ module Wavefront
118
118
  summary = { sent: 0, rejected: 0, unsent: 0 }
119
119
 
120
120
  %i[sent rejected unsent].each do |k|
121
- summary[k] = responses.map { |r| r.response[k] }.inject(:+)
121
+ summary[k] = responses.sum { |r| r.response[k] }
122
122
  end
123
123
 
124
124
  Wavefront::Response.new(
@@ -19,12 +19,12 @@ module Wavefront
19
19
  end
20
20
 
21
21
  def validate_credentials(creds)
22
- unless creds.key?(:endpoint)
22
+ unless creds.key?(:endpoint) && creds[:endpoint]
23
23
  raise(Wavefront::Exception::CredentialError,
24
24
  'credentials must contain API endpoint')
25
25
  end
26
26
 
27
- return true if creds.key?(:token)
27
+ return true if creds.key?(:token) && creds[:token]
28
28
 
29
29
  raise(Wavefront::Exception::CredentialError,
30
30
  'credentials must contain API token')
@@ -99,7 +99,7 @@ module Wavefront
99
99
  #
100
100
  def hash_to_wf(point)
101
101
  wf_point = calling_class.hash_to_wf(point)
102
- logger.log(wf_point, :info)
102
+ logger.log(wf_point, :debug)
103
103
  wf_point
104
104
  end
105
105
 
@@ -29,10 +29,10 @@ module Wavefront
29
29
  end
30
30
 
31
31
  def validate_credentials(creds)
32
- return true if creds.key?(:proxy)
32
+ return true if creds.key?(:proxy) && creds[:proxy]
33
33
 
34
34
  raise(Wavefront::Exception::CredentialError,
35
- 'credentials must contain proxy')
35
+ 'credentials must contain proxy address')
36
36
  end
37
37
 
38
38
  def chunk_size
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'core'
4
+
5
+ module Wavefront
6
+ module Writer
7
+ #
8
+ # Everything specific to writing points to a Wavefront proxy, in
9
+ # native Wavefront format, to a socket. (The original and,
10
+ # once, only way to send points.)
11
+ #
12
+ class Proxy < Core
13
+ # Open a connection to a socket to a Wavefront proxy, putting the
14
+ # descriptor in instance variable @conn.
15
+ # @return [TCPSocket]
16
+ #
17
+ def open
18
+ if opts[:noop]
19
+ logger.log('No-op requested. Not opening connection to proxy.')
20
+ return true
21
+ end
22
+
23
+ port = creds[:port] || default_port
24
+ logger.log("Connecting to #{creds[:proxy]}:#{port}.", :debug)
25
+ open_socket(creds[:proxy], port)
26
+ end
27
+
28
+ # Close the connection described by the @conn instance variable.
29
+ #
30
+ def close
31
+ return if opts[:noop]
32
+
33
+ logger.log('Closing connection to proxy.', :debug)
34
+ conn.close
35
+ end
36
+
37
+ def validate_credentials(creds)
38
+ return true if creds.key?(:proxy) && creds[:proxy]
39
+
40
+ raise(Wavefront::Exception::CredentialError,
41
+ 'credentials must contain proxy address')
42
+ end
43
+
44
+ private
45
+
46
+ def open_socket(proxy, port)
47
+ @conn = TCPSocket.new(proxy, port)
48
+ rescue StandardError => e
49
+ logger.log(e, :error)
50
+ raise Wavefront::Exception::InvalidEndpoint
51
+ end
52
+
53
+ # @param point [String] point or points in native Wavefront format.
54
+ # @raise [SocketError] if point cannot be written
55
+ #
56
+ def _send_point(point)
57
+ return if opts[:noop]
58
+
59
+ conn.puts(point)
60
+ rescue StandardError
61
+ raise Wavefront::Exception::SocketError
62
+ end
63
+
64
+ # return [Integer] the port to connect to, if none is supplied
65
+ #
66
+ def default_port
67
+ 2878
68
+ end
69
+ end
70
+ end
71
+ end
@@ -1,70 +1,58 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'socket'
3
4
  require_relative 'core'
4
5
 
5
6
  module Wavefront
6
7
  module Writer
7
8
  #
8
- # Everything specific to writing points to a Wavefront proxy, in
9
- # native Wavefront format, to a socket. (The original and,
10
- # once, only way to send points.)
9
+ # Everything specific to writing points to a Unix datagram socket.
11
10
  #
12
11
  class Socket < Core
13
- # Open a socket to a Wavefront proxy, putting the descriptor
14
- # in instance variable @conn.
15
- # @return [TCPSocket]
12
+ # Make a connection to a Unix datagram socket, putting the
13
+ # descriptor in instance variable @conn.
14
+ # This requires the name of the socket file in creds[:socket]
15
+ # @return [UnixSocket]
16
16
  #
17
17
  def open
18
18
  if opts[:noop]
19
- logger.log('No-op requested. Not opening connection to proxy.')
19
+ logger.log('No-op requested. Not opening socket connection.')
20
20
  return true
21
21
  end
22
22
 
23
- port = creds[:port] || default_port
24
- logger.log("Connecting to #{creds[:proxy]}:#{port}.", :debug)
25
- open_socket(creds[:proxy], port)
23
+ logger.log("Connecting to #{creds[:socket]}.", :debug)
24
+ open_socket(creds[:socket])
26
25
  end
27
26
 
28
- # Close the connection described by the @conn instance variable.
29
- #
30
27
  def close
31
28
  return if opts[:noop]
32
29
 
33
- logger.log('Closing connection to proxy.', :debug)
30
+ logger.log('Closing socket connection.', :debug)
34
31
  conn.close
35
32
  end
36
33
 
37
34
  def validate_credentials(creds)
38
- return true if creds.key?(:proxy)
35
+ return true if creds.key?(:socket) && creds[:socket]
39
36
 
40
37
  raise(Wavefront::Exception::CredentialError,
41
- 'creds must contain proxy address')
38
+ 'credentials must contain socket file path')
42
39
  end
43
40
 
44
41
  private
45
42
 
46
- def open_socket(proxy, port)
47
- @conn = TCPSocket.new(proxy, port)
43
+ def open_socket(socket)
44
+ @conn = UNIXSocket.new(socket)
48
45
  rescue StandardError => e
49
46
  logger.log(e, :error)
50
47
  raise Wavefront::Exception::InvalidEndpoint
51
48
  end
52
49
 
53
50
  # @param point [String] point or points in native Wavefront format.
54
- # @raise [SocketError] if point cannot be written
55
51
  #
56
52
  def _send_point(point)
57
53
  return if opts[:noop]
58
54
 
59
- conn.puts(point)
60
- rescue StandardError
61
- raise Wavefront::Exception::SocketError
62
- end
63
-
64
- # return [Integer] the port to connect to, if none is supplied
65
- #
66
- def default_port
67
- 2878
55
+ conn.write(point)
68
56
  end
69
57
  end
70
58
  end
data/spec/.rubocop.yml CHANGED
@@ -1,23 +1,11 @@
1
- AllCops:
2
- NewCops: enable
1
+ inherit_from:
2
+ - ../.rubocop.yml
3
3
 
4
4
  Metrics/AbcSize:
5
5
  Max: 64
6
-
7
- # Configuration parameters: CountComments.
8
6
  Metrics/ClassLength:
9
7
  Max: 400
10
-
11
- # Configuration parameters: CountComments, ExcludedMethods.
12
8
  Metrics/MethodLength:
13
9
  Max: 39
14
-
15
- # Is nothing sacred?
16
- Layout/LineLength:
17
- Max: 80
18
-
19
- Style/StringConcatenation:
20
- Enabled: false
21
-
22
- Style/OptionalBooleanParameter:
10
+ Naming/VariableNumber:
23
11
  Enabled: false
data/spec/constants.rb CHANGED
@@ -26,7 +26,7 @@ U_ACL_1 = 'someone@example.com'
26
26
  U_ACL_2 = 'other@elsewhere.com'
27
27
  GRP_ACL = 'f8dc0c14-91a0-4ca9-8a2a-7d47f4db4672'
28
28
 
29
- DEFAULT_HEADERS = { 'Accept': /.*/,
29
+ DEFAULT_HEADERS = { Accept: /.*/,
30
30
  'Accept-Encoding': /.*/,
31
- 'Authorization': 'Bearer 0123456789-ABCDEF',
31
+ Authorization: 'Bearer 0123456789-ABCDEF',
32
32
  'User-Agent': /wavefront-sdk \d+\.\d+\.\d+/ }.freeze