fluent-plugin-cloudwatch-ingest-chaeyk 0.4.2 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b77c18e98f2c2b14518b200ae364ade70b76d8a9
|
4
|
+
data.tar.gz: 3eb03829d3d30b8a4427f15b96362391e401824a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 30c46498a01f39697ed3d24987fdd8fa1d90af203df91eaffccdb1154ce4758cea2d35cd84032d0f4a0ecc0f3c365ebddc5f76a2504247b3eab1d4864380782b
|
7
|
+
data.tar.gz: d0e0a05b240b24324875d29fd6dc8425ca7478aa26b9b879aec1840633315d45331cb398bf999cf3478deeff558a44549a2681b6f53a8403d60ac100688c74b6
|
data/Gemfile
CHANGED
@@ -6,7 +6,7 @@ require 'fluent/plugin/cloudwatch/ingest/version'
|
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
8
|
spec.name = 'fluent-plugin-cloudwatch-ingest-chaeyk'
|
9
|
-
spec.version = Fluent::Plugin::Cloudwatch::Ingest::
|
9
|
+
spec.version = Fluent::Plugin::Cloudwatch::Ingest::VERSION
|
10
10
|
spec.authors = ['chaeyk']
|
11
11
|
spec.email = ['chaeyk@gmail.com']
|
12
12
|
|
@@ -181,12 +181,55 @@ module Fluent::Plugin
|
|
181
181
|
return log_streams
|
182
182
|
end
|
183
183
|
|
184
|
+
def process_stream(group, stream, next_token, start_time, state)
|
185
|
+
event_count = 0
|
186
|
+
|
187
|
+
response = @aws.get_log_events(
|
188
|
+
log_group_name: group,
|
189
|
+
log_stream_name: stream,
|
190
|
+
next_token: next_token,
|
191
|
+
limit: @limit_events,
|
192
|
+
start_time: start_time,
|
193
|
+
start_from_head: @oldest_logs_first
|
194
|
+
)
|
195
|
+
|
196
|
+
response.events.each do |e|
|
197
|
+
begin
|
198
|
+
emit(e, group, stream)
|
199
|
+
event_count += 1
|
200
|
+
rescue => boom
|
201
|
+
log.error("Failed to emit event #{e}: #{boom.inspect}")
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
has_stream_timestamp = true if state.store[group][stream]['timestamp']
|
206
|
+
|
207
|
+
if !has_stream_timestamp && response.events.count.zero?
|
208
|
+
# This stream has returned no data ever.
|
209
|
+
# In this case, don't save state (token could be an invalid one)
|
210
|
+
else
|
211
|
+
# Once all events for this stream have been processed,
|
212
|
+
# in this iteration, store the forward token
|
213
|
+
state.new_store[group][stream]['token'] = response.next_forward_token
|
214
|
+
if response.events.last
|
215
|
+
state.new_store[group][stream]['timestamp'] =
|
216
|
+
response.events.last.timestamp
|
217
|
+
else
|
218
|
+
state.new_store[group][stream]['timestamp'] =
|
219
|
+
state.store[group][stream]['timestamp']
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
return event_count
|
224
|
+
end
|
225
|
+
|
184
226
|
def run
|
185
227
|
until @finished
|
186
228
|
begin
|
187
229
|
state = State.new(@state_file_name, log)
|
188
230
|
rescue => boom
|
189
|
-
log.info("Failed lock state. Sleeping for #{@interval}:
|
231
|
+
log.info("Failed lock state. Sleeping for #{@interval}: "\
|
232
|
+
"#{boom.inspect}")
|
190
233
|
sleep @interval
|
191
234
|
next
|
192
235
|
end
|
@@ -197,96 +240,45 @@ module Fluent::Plugin
|
|
197
240
|
log_groups(@log_group_name_prefix).each do |group|
|
198
241
|
# For each log stream get and emit the events
|
199
242
|
log_streams(group, @log_stream_name_prefix).each do |stream|
|
200
|
-
|
201
|
-
|
202
|
-
|
243
|
+
state.store[group][stream] = {} unless state.store[group][stream]
|
244
|
+
|
245
|
+
log.info("processing stream: #{stream}")
|
203
246
|
|
204
247
|
# See if we have some stored state for this group and stream.
|
205
248
|
# If we have then use the stored forward_token to pick up
|
206
249
|
# from that point. Otherwise start from the start.
|
207
|
-
if state.store[group][stream]['token']
|
208
|
-
stream_token = state.store[group][stream]['token']
|
209
|
-
else
|
210
|
-
stream_token = nil
|
211
|
-
end
|
212
|
-
|
213
|
-
if state.store[group][stream]['timestamp']
|
214
|
-
stream_timestamp = state.store[group][stream]['timestamp']
|
215
|
-
else
|
216
|
-
stream_timestamp = @event_start_time
|
217
|
-
end
|
218
250
|
|
219
251
|
begin
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
start_from_head: @oldest_logs_first
|
227
|
-
)
|
228
|
-
|
229
|
-
response.events.each do |e|
|
230
|
-
begin
|
231
|
-
emit(e, group, stream)
|
232
|
-
event_count = event_count + 1
|
233
|
-
rescue => boom
|
234
|
-
log.error("Failed to emit event #{e}: #{boom.inspect}")
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
# Once all events for this stream have been processed,
|
239
|
-
# in this iteration, store the forward token
|
240
|
-
log.info("stream: #{stream} token: #{stream_token} count: #{event_count}")
|
241
|
-
if stream_token or response.events.count > 0
|
242
|
-
log.info("saving: #{response.events}")
|
243
|
-
state.store[group][stream]['token'] = response.next_forward_token
|
244
|
-
state.store[group][stream]['timestamp'] = response.events.last ? response.events.last.timestamp : stream_timestamp
|
245
|
-
else
|
246
|
-
log.info("throw out")
|
247
|
-
state.store[group].delete(stream)
|
248
|
-
end
|
249
|
-
rescue Aws::CloudWatchLogs::Errors::InvalidParameterException => boom
|
250
|
-
log.error("cloudwatch token is expired or broken. trying with timestamp.");
|
252
|
+
event_count += process_stream(group, stream,
|
253
|
+
state.store[group][stream]['token'],
|
254
|
+
@event_start_time, state)
|
255
|
+
rescue Aws::CloudWatchLogs::Errors::InvalidParameterException
|
256
|
+
log.error('cloudwatch token is expired or broken. '\
|
257
|
+
'trying with timestamp.')
|
251
258
|
|
252
259
|
# try again with timestamp instead of forward token
|
253
260
|
begin
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
start_from_head: true
|
260
|
-
)
|
261
|
-
|
262
|
-
response.events.each do |e|
|
263
|
-
begin
|
264
|
-
emit(e, group, stream)
|
265
|
-
event_count = event_count + 1
|
266
|
-
rescue => boom
|
267
|
-
log.error("Failed to emit event #{e}: #{boom.inspect}")
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
# Once all events for this stream have been processed,
|
272
|
-
# in this iteration, store the forward token
|
273
|
-
state.store[group][stream]["token"] = response.next_forward_token
|
274
|
-
state.store[group][stream]['timestamp'] = response.events.last ? response.events.last.timestamp : steam_timestamp
|
261
|
+
timestamp = state.store[group][stream]['timestamp']
|
262
|
+
timestamp = @event_start_time unless timestamp
|
263
|
+
|
264
|
+
event_count += process_stream(group, stream,
|
265
|
+
nil, timestamp, state)
|
275
266
|
rescue => boom
|
276
|
-
log.error("Unable to retrieve events for stream #{stream}
|
267
|
+
log.error("Unable to retrieve events for stream #{stream} "\
|
268
|
+
"in group #{group}: #{boom.inspect}") # rubocop:disable all
|
277
269
|
sleep @api_interval
|
278
270
|
next
|
279
271
|
end
|
280
272
|
rescue => boom
|
281
|
-
log.error("Unable to retrieve events for stream #{stream}
|
273
|
+
log.error("Unable to retrieve events for stream #{stream} "\
|
274
|
+
"in group #{group}: #{boom.inspect}") # rubocop:disable all
|
282
275
|
sleep @api_interval
|
283
276
|
next
|
284
277
|
end
|
285
278
|
end
|
286
279
|
end
|
287
280
|
|
288
|
-
log.info('
|
289
|
-
state.prune(log_groups(@log_group_name_prefix)) # Remove dead streams
|
281
|
+
log.info('Saving state')
|
290
282
|
begin
|
291
283
|
state.save
|
292
284
|
state.close
|
@@ -308,12 +300,13 @@ module Fluent::Plugin
|
|
308
300
|
|
309
301
|
class CloudwatchIngestInput::State
|
310
302
|
class LockFailed < RuntimeError; end
|
311
|
-
attr_accessor :statefile, :store
|
303
|
+
attr_accessor :statefile, :store, :new_store
|
312
304
|
|
313
305
|
def initialize(filepath, log)
|
314
306
|
@filepath = filepath
|
315
307
|
@log = log
|
316
|
-
@store = Hash.new { |h, k| h[k] = Hash.new { |
|
308
|
+
@store = Hash.new { |h, k| h[k] = Hash.new { |x, y| x[y] = {} } }
|
309
|
+
@new_store = Hash.new { |h, k| h[k] = Hash.new { |x, y| x[y] = {} } }
|
317
310
|
|
318
311
|
if File.exist?(filepath)
|
319
312
|
self.statefile = Pathname.new(@filepath).open('r+')
|
@@ -323,7 +316,8 @@ module Fluent::Plugin
|
|
323
316
|
self.statefile = Pathname.new(@filepath).open('w+')
|
324
317
|
save
|
325
318
|
rescue => boom
|
326
|
-
@log.error("Unable to create new file #{statefile.path}:
|
319
|
+
@log.error("Unable to create new file #{statefile.path}: "\
|
320
|
+
"#{boom.inspect}")
|
327
321
|
end
|
328
322
|
end
|
329
323
|
|
@@ -337,11 +331,14 @@ module Fluent::Plugin
|
|
337
331
|
@store.merge!(Psych.safe_load(statefile.read))
|
338
332
|
|
339
333
|
# Migrate old state file
|
340
|
-
@store.each
|
341
|
-
streams.update(streams)
|
342
|
-
|
343
|
-
|
344
|
-
|
334
|
+
@store.each do |_group, streams|
|
335
|
+
streams.update(streams) do |_name, stream|
|
336
|
+
if stream.is_a? String
|
337
|
+
return { 'token' => stream, 'timestamp' => Time.now.to_i }
|
338
|
+
end
|
339
|
+
return stream
|
340
|
+
end
|
341
|
+
end
|
345
342
|
|
346
343
|
@log.info("Loaded #{@store.keys.size} groups from #{statefile.path}")
|
347
344
|
rescue
|
@@ -353,7 +350,7 @@ module Fluent::Plugin
|
|
353
350
|
def save
|
354
351
|
statefile.rewind
|
355
352
|
statefile.truncate(0)
|
356
|
-
statefile.write(Psych.dump(@
|
353
|
+
statefile.write(Psych.dump(@new_store))
|
357
354
|
@log.info("Saved state to #{statefile.path}")
|
358
355
|
statefile.rewind
|
359
356
|
end
|
@@ -361,14 +358,6 @@ module Fluent::Plugin
|
|
361
358
|
def close
|
362
359
|
statefile.close
|
363
360
|
end
|
364
|
-
|
365
|
-
def prune(log_groups)
|
366
|
-
groups_before = @store.keys.size
|
367
|
-
@store.delete_if { |k, _v| true unless log_groups.include?(k) }
|
368
|
-
@log.info("Pruned #{groups_before - @store.keys.size} keys from store")
|
369
|
-
|
370
|
-
# TODO: also prune streams as these are most likely to be transient
|
371
|
-
end
|
372
361
|
end
|
373
362
|
end
|
374
363
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-cloudwatch-ingest-chaeyk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- chaeyk
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-05
|
11
|
+
date: 2017-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|