wavefront-sdk 5.4.1 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
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