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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c655c861444978220b162bc7144eacd8ae34a01016acc37aa6dd8837f7c13946
4
- data.tar.gz: e83e2a0bf6faa89f429e8100154c4fa0d2d394e0eaff3aa948deacf9ebad0217
3
+ metadata.gz: 839f24e0a1a324b6965cb8aec1c0516bcb7c193215bc3cb6c1351f888bd49863
4
+ data.tar.gz: 97ba3cce211abdef8d1b08265279a2998f968a6f85a58290efe26d8109314940
5
5
  SHA512:
6
- metadata.gz: 98d0ddf6e9c5fd9e221919a502f1f9d417bfeced192958c14dda83bf126d883eea26af2aceadd2c713c9b1ee152494542f373c737ce4e833c87c8f2677210f0e
7
- data.tar.gz: 8c7a347579b7375cac6c7c481ba13cc7ff2d393d9f6eff867b080d8f93b2d545bbddd8b67193706ec3cefda03ff46c3bb26033b0e14b824fad596d13a72a5201
6
+ metadata.gz: 2d72451c46077024d79451aaea09efec073db0dcfb6dfb7601382973f80b14c99cd3b732bf57ec09a1ec962938b2219470676ba84c47b27051b5d2970cdeb8ef
7
+ data.tar.gz: fdf2b294468db11835722f3ffbcbac2e77a42a12d8083c4e7536f637659bf8e063de0b75f023e71a46d2a25e942ad197e16e70a4229db5142b741542dbaaf2f7
data/.codeclimate.yml CHANGED
@@ -11,7 +11,7 @@ engines:
11
11
  fixme:
12
12
  enabled: true
13
13
  rubocop:
14
- enabled: true
14
+ enabled: false
15
15
  ratings:
16
16
  paths:
17
17
  - "**.rb"
@@ -0,0 +1,37 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - '[0-9]+.[0-9]+.[0-9]+'
7
+
8
+ jobs:
9
+ build:
10
+ name: Build + Publish
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - name: Set env
16
+ run: echo "RELEASE_VERSION=$(echo ${GITHUB_REF:10})" >> $GITHUB_ENV
17
+
18
+ - name: Set up Ruby 2.7
19
+ uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: 2.7
22
+ - run: bundle install
23
+
24
+ - name: Run tests
25
+ run: bundle exec rake
26
+
27
+ - name: Build Gem
28
+ run: bundle exec rake build
29
+
30
+ - name: Publish to RubyGems
31
+ run: |
32
+ mkdir -p ${HOME}/.gem
33
+ echo -e "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}" >${HOME}/.gem/credentials
34
+ chmod 0600 ${HOME}/.gem/credentials
35
+ gem push pkg/*.gem
36
+ env:
37
+ GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
@@ -0,0 +1,23 @@
1
+ name: Test
2
+
3
+ on:
4
+ push:
5
+ branches-ignore: release
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ ruby-version: [2.5.9, 2.6.7, 2.7.3, 3.0.1]
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - name: Set up Ruby
16
+ uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: ${{ matrix.ruby-version }}
19
+ bundler-cache: true
20
+ - name: Install dependencies
21
+ run: bundle install
22
+ - name: Run tests
23
+ run: bundle exec rake
data/.rubocop.yml CHANGED
@@ -1,18 +1,20 @@
1
1
  ---
2
2
 
3
3
  AllCops:
4
- TargetRubyVersion: 2.4
4
+ TargetRubyVersion: 2.5
5
5
  NewCops: enable
6
6
 
7
- Metrics/ClassLength:
8
- Max: 150
7
+ require:
8
+ - rubocop-rake
9
+ - rubocop-minitest
10
+ - rubocop-performance
11
+ - rubocop-performance
9
12
 
10
- # Is nothing sacred?
11
13
  Layout/LineLength:
12
14
  Max: 80
13
-
15
+ Metrics/ClassLength:
16
+ Max: 150
14
17
  Style/StringConcatenation:
15
18
  Enabled: false
16
-
17
19
  Style/OptionalBooleanParameter:
18
20
  Enabled: false
data/HISTORY.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## 6.0.0 (2021-07-16)
4
+ * Drop support for Ruby 2.4. (Breaking change.)
5
+ * Change the name of the proxy writer from `socket` to `proxy`. (Breaking
6
+ change.)
7
+ * Change the name of the Unix datagram socket writer from `unix` to `socket`.
8
+ * added `Wavefront::Event#alert_firing_details`.
9
+ * added `Wavefront::Event#alert_queries_slug`.
10
+ * added `Wavefront::Event#events`.
11
+ * added `Wavefront::Event#alert_firings`.
12
+ * Add `Wavefront::MetricsPolicy`.
13
+ * Add `Wavefront::Spy#deltas`.
14
+
15
+ ## 5.4.4 (2021-02-01)
16
+ * Fix credential validation on writer classes.
17
+ * Improve tests for writer classes
18
+ * Change the level of "wire format" messages from `INFO` to `DEBUG`.
19
+ * Officially support Ruby 3.0.0.
20
+ * Move off Travis, and on to Github Actions.
21
+ * Modernise linting and use of linter.
22
+
23
+ ## 5.4.3 (2021-01-28)
24
+ * Always pass through invalid timestamp on time-parsing error.
25
+
26
+ ## 5.4.2 (2021-01-11)
27
+ * Fix bug which blocked event updates.
28
+
3
29
  ## 5.4.1 (2020-12-17)
4
30
  * Fix error on derived metric modification.
5
31
 
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # wavefront-sdk
2
- [![Build Status](https://travis-ci.org/snltd/wavefront-sdk.svg?branch=master)](https://travis-ci.org/snltd/wavefront-sdk) [![Code Climate](https://codeclimate.com/github/snltd/wavefront-sdk/badges/gpa.svg)](https://codeclimate.com/github/snltd/wavefront-sdk) [![Issue Count](https://codeclimate.com/github/snltd/wavefront-sdk/badges/issue_count.svg)](https://codeclimate.com/github/snltd/wavefront-sdk) [![Gem Version](https://badge.fury.io/rb/wavefront-sdk.svg)](https://badge.fury.io/rb/wavefront-sdk) ![](http://ruby-gem-downloads-badge.herokuapp.com/wavefront-sdk?type=total)
2
+ [![Test](https://github.com/snltd/wavefront-sdk/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/snltd/wavefront-sdk/actions/workflows/test.yml) [![Release](https://github.com/snltd/wavefront-sdk/actions/workflows/release.yml/badge.svg?branch=master)](https://github.com/snltd/wavefront-sdk/actions/workflows/release.yml) [![Code Climate](https://codeclimate.com/github/snltd/wavefront-sdk/badges/gpa.svg)](https://codeclimate.com/github/snltd/wavefront-sdk) [![Issue Count](https://codeclimate.com/github/snltd/wavefront-sdk/badges/issue_count.svg)](https://codeclimate.com/github/snltd/wavefront-sdk) [![Gem Version](https://badge.fury.io/rb/wavefront-sdk.svg)](https://badge.fury.io/rb/wavefront-sdk) ![](http://ruby-gem-downloads-badge.herokuapp.com/wavefront-sdk?type=total)
3
3
 
4
4
  This is a Ruby SDK for v2 of
5
5
  [Wavefront](https://www.wavefront.com/)'s public API. It aims to be
@@ -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.4. All its dependencies are pure
27
+ `wavefront-sdk` requires Ruby >= 2.5. 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
 
@@ -41,7 +41,7 @@ method will return a `Wavefront::Response` object. This object has
41
41
  `status` and `response` methods. `status` always yields a structure
42
42
  containing `result`, `message` and `code` fields which can be
43
43
  inspected to ensure an API call was processed successfully.
44
- `response` gives you a the JSON response from the API, conveniently
44
+ `response` gives you the JSON response from the API, conveniently
45
45
  processed and turned into a [`Map`](https://github.com/ahoward/map)
46
46
  object. Map objects can be interrogated in various ways. For
47
47
  instance `map['items']`, `map[:items]` and `map.items` will all get
@@ -203,7 +203,7 @@ wf.close
203
203
  ```
204
204
 
205
205
  Alternatively, pass `false` as the second argument to `Write#write`.
206
- (This is the legacy method, kept in for backward compatability.)
206
+ (This is the legacy method, kept in for backward compatibility.)
207
207
 
208
208
  ```ruby
209
209
  wf = Wavefront::Write.new(Wavefront::Credentials.new.proxy)
@@ -220,7 +220,7 @@ but other methods are supported via the `writer` option.
220
220
  wf = Wavefront::Write.new(Wavefront::Credentials.new.creds, writer: :api)
221
221
 
222
222
  # To send points via a local Unix socket
223
- wf = Wavefront::Write.new(socket: '/tmp/wf_sock', { writer: :unix })
223
+ wf = Wavefront::Write.new({ socket: '/tmp/wf_sock'}, { writer: :socket })
224
224
 
225
225
  # To send points over HTTP
226
226
  wf = Wavefront::Write.new(Wavefront::Credentials.new.creds, writer: :http)
@@ -80,7 +80,7 @@ module Wavefront
80
80
  end
81
81
 
82
82
  def valid_acl_body?(list)
83
- return true if list.is_a?(Array) && list.all? { |h| h.is_a?(String) }
83
+ return true if list.is_a?(Array) && list.all?(String)
84
84
 
85
85
  raise ArgumentError
86
86
  end
@@ -94,7 +94,7 @@ module Wavefront
94
94
  def hash_for_update(old, new)
95
95
  raise ArgumentError unless old.is_a?(Hash) && new.is_a?(Hash)
96
96
 
97
- Hash[old.merge(new).map { |k, v| [k.to_sym, v] }].select do |k, _v|
97
+ old.merge(new).transform_keys(&:to_sym).select do |k, _v|
98
98
  update_keys.include?(k)
99
99
  end
100
100
  end
@@ -134,7 +134,7 @@ module Wavefront
134
134
  def post(path, body = nil, ctype = 'text/plain')
135
135
  body = body.to_json unless body.is_a?(String)
136
136
  make_call(mk_conn(path, 'Content-Type': ctype,
137
- 'Accept': 'application/json'),
137
+ Accept: 'application/json'),
138
138
  :post, nil, body)
139
139
  end
140
140
 
@@ -149,7 +149,7 @@ module Wavefront
149
149
  #
150
150
  def put(path, body = nil, ctype = 'application/json')
151
151
  make_call(mk_conn(path, 'Content-Type': ctype,
152
- 'Accept': 'application/json'),
152
+ Accept: 'application/json'),
153
153
  :put, nil, body.to_json)
154
154
  end
155
155
 
@@ -6,61 +6,119 @@ module Wavefront
6
6
  #
7
7
  class Exception
8
8
  class CredentialError < RuntimeError; end
9
+
9
10
  class EmptyMetricName < RuntimeError; end
11
+
10
12
  class EnumerableError < RuntimeError; end
13
+
11
14
  class InvalidAccountId < RuntimeError; end
15
+
12
16
  class InvalidAlertId < RuntimeError; end
17
+
13
18
  class InvalidAlertSeverity < RuntimeError; end
19
+
14
20
  class InvalidApiTokenId < RuntimeError; end
21
+
15
22
  class InvalidAwsExternalId < RuntimeError; end
23
+
16
24
  class InvalidConfigFile < RuntimeError; end
25
+
17
26
  class InvalidCloudIntegrationId < RuntimeError; end
27
+
18
28
  class InvalidDashboardId < RuntimeError; end
29
+
19
30
  class InvalidDerivedMetricId < RuntimeError; end
31
+
20
32
  class InvalidDistribution < RuntimeError; end
33
+
21
34
  class InvalidDistributionInterval < RuntimeError; end
35
+
22
36
  class InvalidDistributionCount < RuntimeError; end
37
+
23
38
  class InvalidEndpoint < RuntimeError; end
39
+
24
40
  class InvalidEventId < RuntimeError; end
41
+
25
42
  class InvalidExternalLinkId < RuntimeError; end
43
+
26
44
  class InvalidGranularity < RuntimeError; end
45
+
27
46
  class InvalidHostname < RuntimeError; end
47
+
28
48
  class InvalidIngestionPolicyId < RuntimeError; end
49
+
29
50
  class InvalidIntegrationId < RuntimeError; end
51
+
30
52
  class InvalidLinkTemplate < RuntimeError; end
53
+
31
54
  class InvalidMaintenanceWindowId < RuntimeError; end
55
+
32
56
  class InvalidMonitoredClusterId < RuntimeError; end
57
+
33
58
  class InvalidMessageId < RuntimeError; end
59
+
34
60
  class InvalidMetricName < RuntimeError; end
61
+
62
+ class InvalidMetricsPolicyId < RuntimeError; end
63
+
35
64
  class InvalidMetricValue < RuntimeError; end
65
+
36
66
  class InvalidName < RuntimeError; end
67
+
37
68
  class InvalidNotificantId < RuntimeError; end
69
+
38
70
  class InvalidPermission < RuntimeError; end
71
+
39
72
  class InvalidPoint < RuntimeError; end
73
+
40
74
  class InvalidPrefixLength < RuntimeError; end
75
+
41
76
  class InvalidProxyId < RuntimeError; end
77
+
42
78
  class InvalidRoleId < RuntimeError; end
79
+
43
80
  class InvalidRelativeTime < RuntimeError; end
81
+
44
82
  class InvalidSamplingValue < RuntimeError; end
83
+
45
84
  class InvalidSavedSearchEntity < RuntimeError; end
85
+
46
86
  class InvalidSavedSearchId < RuntimeError; end
87
+
47
88
  class InvalidServiceAccountId < RuntimeError; end
89
+
48
90
  class InvalidSourceId < RuntimeError; end
91
+
49
92
  class InvalidString < RuntimeError; end
93
+
50
94
  class InvalidTag < RuntimeError; end
95
+
51
96
  class InvalidTimeFormat < RuntimeError; end
97
+
52
98
  class InvalidTimeUnit < RuntimeError; end
99
+
53
100
  class InvalidTimestamp < RuntimeError; end
101
+
54
102
  class InvalidUserId < RuntimeError; end
103
+
55
104
  class InvalidUserGroupId < RuntimeError; end
105
+
56
106
  class InvalidVersion < RuntimeError; end
107
+
57
108
  class InvalidWebhookId < RuntimeError; end
109
+
58
110
  class MissingConfigProfile < RuntimeError; end
111
+
59
112
  class NetworkTimeout < RuntimeError; end
113
+
60
114
  class NotImplemented < RuntimeError; end
115
+
61
116
  class SocketError < RuntimeError; end
117
+
62
118
  class UnparseableResponse < RuntimeError; end
119
+
63
120
  class UnsupportedWriter < RuntimeError; end
121
+
64
122
  class ValueOutOfRange < RuntimeError; end
65
123
  end
66
124
  end
@@ -65,12 +65,14 @@ module Wavefront
65
65
  # @return void
66
66
  #
67
67
  def populate(raw)
68
+ creds_keys = %i[endpoint token]
69
+ proxy_keys = %i[proxy port]
70
+ all_keys = creds_keys + proxy_keys
71
+
68
72
  @config = Map(raw)
69
- @creds = Map(raw.select { |k, _v| %i[endpoint token].include?(k) })
70
- @proxy = Map(raw.select { |k, _v| %i[proxy port].include?(k) })
71
- @all = Map(raw.select do |k, _v|
72
- %i[proxy port endpoint token].include?(k)
73
- end)
73
+ @creds = Map(raw.select { |k, _v| creds_keys.include?(k) })
74
+ @proxy = Map(raw.select { |k, _v| proxy_keys.include?(k) })
75
+ @all = Map(raw.select { |k, _v| all_keys.include?(k) })
74
76
  end
75
77
 
76
78
  # @return [Array] a list of possible credential files
@@ -126,9 +128,7 @@ module Wavefront
126
128
  # @return [Hash] options loaded from file. Each key becomes a symbol
127
129
  #
128
130
  def load_profile(file, profile = 'default')
129
- IniFile.load(file)[profile].each_with_object({}) do |(k, v), memo|
130
- memo[k.to_sym] = v
131
- end
131
+ IniFile.load(file)[profile].transform_keys(&:to_sym)
132
132
  rescue StandardError
133
133
  raise Wavefront::Exception::InvalidConfigFile, file
134
134
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  require 'pathname'
4
4
 
5
- WF_SDK_VERSION = '5.4.1'
5
+ WF_SDK_VERSION = '6.0.0'
6
6
  WF_SDK_LOCATION = Pathname.new(__dir__).parent.parent.parent
@@ -12,7 +12,7 @@ module Wavefront
12
12
  include Wavefront::Mixin::Tag
13
13
 
14
14
  def update_keys
15
- %i[startTime endTime name annotations]
15
+ %i[id name]
16
16
  end
17
17
 
18
18
  # GET /api/v2/event
@@ -28,6 +28,7 @@ module Wavefront
28
28
  # @param limit [Integer] the number of events to return
29
29
  # @return [Wavefront::Response]
30
30
  #
31
+ # rubocop:disable Metrics/ParameterLists
31
32
  def list(from = nil, to = Time.now, limit = 100, cursor = nil)
32
33
  raise ArgumentError unless from && to
33
34
 
@@ -37,6 +38,7 @@ module Wavefront
37
38
  wf_ms_ts?(body[:latestStartTimeEpochMillis])
38
39
  api.get('', body.cleanse)
39
40
  end
41
+ # rubocop:enable Metrics/ParameterLists
40
42
 
41
43
  # POST /api/v2/event
42
44
  # Create a specific event.
@@ -100,7 +102,9 @@ module Wavefront
100
102
 
101
103
  return api.put(id, body, 'application/json') unless modify
102
104
 
103
- api.put(id, hash_for_update(describe(id), body), 'application/json')
105
+ api.put(id,
106
+ hash_for_update(describe(id).response, body),
107
+ 'application/json')
104
108
  end
105
109
 
106
110
  # POST /api/v2/event/id/close
@@ -113,12 +117,75 @@ module Wavefront
113
117
  api.post([id, 'close'].uri_concat)
114
118
  end
115
119
 
116
- def valid_id?(id)
120
+ # GET /api/v2/event/{id}/alertFiringDetails
121
+ # Return details of a particular alert firing, including all the series
122
+ # that fired during the referred alert firing
123
+ #
124
+ # @param id [String] ID of the event
125
+ # @return [Wavefront::Response]
126
+ #
127
+ def alert_firing_details(id)
128
+ wf_event_id?(id)
129
+ api.get([id, 'alertFiringDetails'].uri_concat)
130
+ end
131
+
132
+ # GET /api/v2/event/{id}/alertQueriesSlug
133
+ # If the specified event is associated with an alert, returns a slug
134
+ # encoding the queries having to do with that alert firing or resolution
135
+ # @param id [String] ID of the event
136
+ # @return [Wavefront::Response]
137
+ #
138
+ def alert_queries_slug(id)
139
+ wf_event_id?(id)
140
+ api.get([id, 'alertQueriesSlug'].uri_concat)
141
+ end
142
+
143
+ # GET /api/v2/event/{id}/events
144
+ # List all related events for a specific firing event with a time span of
145
+ # one hour
146
+ # @param id [String] ID of the event
147
+ # @param opts [Hash] containing one or more of
148
+ # is_overlapped [Bool]
149
+ # rendering_method [Symbol,String] one of :HOST, :METRIC, :SIMILARITY
150
+ # limit [Integer]
151
+ # @return [Wavefront::Response]
152
+ #
153
+ def events(id, opts = {})
117
154
  wf_event_id?(id)
155
+
156
+ api.get([id, 'events'].uri_concat,
157
+ { isOverlapped: opts[:is_overlapped] || false,
158
+ renderingMethod: (opts[:rendering_method] || :HOST).to_s,
159
+ limit: opts[:limit] || nil }.compact)
160
+ end
161
+
162
+ # GET /api/v2/event/alertFirings
163
+ # Get firings events of an alert within a time range
164
+ # @param alert_id [String] ID of the alert
165
+ # @param opts [Hash] containing one or more of
166
+ # earliest_start [Integer] epoch ms timestamp
167
+ # latest_start [Integer] epoch ms timestamp
168
+ # ascending [Bool]
169
+ # limit [Integer]
170
+ # @return [Wavefront::Response]
171
+ #
172
+ def alert_firings(alert_id, opts = {})
173
+ wf_alert_id?(alert_id)
174
+
175
+ api.get('alertFirings',
176
+ { alertId: alert_id,
177
+ earliestStartTimeEpochMillis: opts[:earliest_start] || nil,
178
+ latestStartTimeEpochMillis: opts[:latest_start] || nil,
179
+ limit: opts[:limit] || nil,
180
+ asc: opts[:asc] || true }.compact)
118
181
  end
119
182
 
120
183
  private
121
184
 
185
+ def valid_id?(id)
186
+ wf_event_id?(id)
187
+ end
188
+
122
189
  def list_body(t_start, t_end, limit, cursor)
123
190
  { earliestStartTimeEpochMillis: parse_time(t_start, true),
124
191
  latestStartTimeEpochMillis: parse_time(t_end, true),