logstash-input-s3-sns-sqs 2.0.3 → 2.0.4
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/logstash/inputs/codec_factory.rb +1 -1
- data/lib/logstash/inputs/s3/client_factory.rb +0 -6
- data/lib/logstash/inputs/s3/downloader.rb +0 -3
- data/lib/logstash/inputs/s3snssqs.rb +34 -23
- data/lib/logstash/inputs/s3snssqs/log_processor.rb +23 -14
- data/lib/logstash/inputs/sqs/poller.rb +48 -40
- data/logstash-input-s3-sns-sqs.gemspec +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 131941a4c12a2dc0399793b18b90ea9ac40bfe741d8fca8b63e6a3d257863693
|
4
|
+
data.tar.gz: 1ae77c566d3421cf36ed2e5a16039f49a526a83b09db106f537fe94d893d45f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc602eddfdb4adcf5a08244b4e392042a250773b11f98020712a9fcb3988710355ec9b1931834d7fd0e8d0a15eb0227c94578f7c4da7a146b3451a7cded8c4a5
|
7
|
+
data.tar.gz: 6f3cd9970544a86a621a0be5cb004edd14498fd3f6a3208cb6d183dde172ec98ef24b6235c4b47cf4fe2b09c14c3d8a992372669e944346517ff725606d7fd83
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
##2.0.4
|
2
|
+
- Fix minor bugs
|
3
|
+
##2.0.3
|
4
|
+
- Increase max parsing time -> drop event if reached
|
5
|
+
- watcher thread should raise an error in poller loop if timeout reached.
|
6
|
+
- remove some debug logs
|
7
|
+
|
1
8
|
##2.0.2
|
2
9
|
FIX:
|
3
10
|
- Terminate every input line by \n (BufferedReader does not)
|
@@ -25,7 +25,7 @@ class CodecFactory
|
|
25
25
|
def find_codec(record)
|
26
26
|
bucket, key, folder = record[:bucket], record[:key], record[:folder]
|
27
27
|
unless @codec_by_folder[bucket].nil?
|
28
|
-
@logger.debug("
|
28
|
+
@logger.debug("Looking up codec for folder #{folder}", :codec => @codec_by_folder[bucket][folder])
|
29
29
|
return @codec_by_folder[bucket][folder] unless @codec_by_folder[bucket][folder].nil?
|
30
30
|
end
|
31
31
|
return 'default'
|
@@ -13,7 +13,6 @@ class S3ClientFactory
|
|
13
13
|
@logger.debug("Credentials by Bucket", :credentials => @credentials_by_bucket)
|
14
14
|
@default_session_name = options[:s3_role_session_name]
|
15
15
|
@clients_by_bucket = {}
|
16
|
-
#@mutexes_by_bucket = {}
|
17
16
|
@creation_mutex = Mutex.new
|
18
17
|
end
|
19
18
|
|
@@ -27,18 +26,13 @@ class S3ClientFactory
|
|
27
26
|
end
|
28
27
|
@clients_by_bucket[bucket_symbol] = Aws::S3::Client.new(options)
|
29
28
|
@logger.debug("Created a new S3 Client", :bucket_name => bucket_name, :client => @clients_by_bucket[bucket_symbol], :used_options => options)
|
30
|
-
#@mutexes_by_bucket[bucket_symbol] = Mutex.new
|
31
29
|
end
|
32
30
|
end
|
33
31
|
# to be thread-safe, one uses this method like this:
|
34
32
|
# s3_client_factory.get_s3_client(my_s3_bucket) do
|
35
33
|
# ... do stuff ...
|
36
34
|
# end
|
37
|
-
# FIXME: this does not allow concurrent downloads from the same bucket!
|
38
|
-
#@mutexes_by_bucket[bucket_symbol].synchronize do
|
39
|
-
# So we are testing this without this mutex.
|
40
35
|
yield @clients_by_bucket[bucket_symbol]
|
41
|
-
#end
|
42
36
|
end
|
43
37
|
|
44
38
|
private
|
@@ -15,14 +15,12 @@ class S3Downloader
|
|
15
15
|
# (from docs) WARNING:
|
16
16
|
# yielding data to a block disables retries of networking errors!
|
17
17
|
begin
|
18
|
-
#@logger.info("Download File", :file => record)
|
19
18
|
@factory.get_s3_client(record[:bucket]) do |s3|
|
20
19
|
response = s3.get_object(
|
21
20
|
bucket: record[:bucket],
|
22
21
|
key: record[:key],
|
23
22
|
response_target: record[:local_file]
|
24
23
|
)
|
25
|
-
#@logger.info("READY: File", :file => record, :response => response)
|
26
24
|
end
|
27
25
|
rescue Aws::S3::Errors::ServiceError => e
|
28
26
|
@logger.error("Unable to download file. Requeuing the message", :error => e, :record => record)
|
@@ -34,7 +32,6 @@ class S3Downloader
|
|
34
32
|
end
|
35
33
|
|
36
34
|
def cleanup_local_object(record)
|
37
|
-
#@logger.info("Cleaning up file", :file => record[:local_file])
|
38
35
|
FileUtils.remove_entry_secure(record[:local_file], true) if ::File.exists?(record[:local_file])
|
39
36
|
rescue Exception => e
|
40
37
|
@logger.warn("Could not delete file", :file => record[:local_file], :error => e)
|
@@ -160,6 +160,7 @@ class LogStash::Inputs::S3SNSSQS < LogStash::Inputs::Threadable
|
|
160
160
|
config :s3_options_by_bucket, :validate => :array, :required => false # TODO: true
|
161
161
|
# Session name to use when assuming an IAM role
|
162
162
|
config :s3_role_session_name, :validate => :string, :default => "logstash"
|
163
|
+
config :delete_on_success, :validate => :boolean, :default => false
|
163
164
|
|
164
165
|
### sqs
|
165
166
|
# Name of the SQS Queue to pull messages from. Note that this is just the name of the queue, not the URL or ARN.
|
@@ -168,8 +169,8 @@ class LogStash::Inputs::S3SNSSQS < LogStash::Inputs::Threadable
|
|
168
169
|
# Whether the event is processed though an SNS to SQS. (S3>SNS>SQS = true |S3>SQS=false)
|
169
170
|
config :from_sns, :validate => :boolean, :default => true
|
170
171
|
config :sqs_skip_delete, :validate => :boolean, :default => false
|
171
|
-
config :
|
172
|
-
config :
|
172
|
+
config :visibility_timeout, :validate => :number, :default => 120
|
173
|
+
config :max_processing_time, :validate => :number, :default => 8000
|
173
174
|
|
174
175
|
### system
|
175
176
|
config :temporary_directory, :validate => :string, :default => File.join(Dir.tmpdir, "logstash")
|
@@ -185,7 +186,7 @@ class LogStash::Inputs::S3SNSSQS < LogStash::Inputs::Threadable
|
|
185
186
|
def register
|
186
187
|
# prepare system
|
187
188
|
FileUtils.mkdir_p(@temporary_directory) unless Dir.exist?(@temporary_directory)
|
188
|
-
|
189
|
+
@id ||= "Unknown" #Use INPUT{ id => name} for thread identifier
|
189
190
|
@credentials_by_bucket = hash_key_is_regex({})
|
190
191
|
# create the bucket=>folder=>codec lookup from config options
|
191
192
|
@codec_by_folder = hash_key_is_regex({})
|
@@ -238,12 +239,18 @@ class LogStash::Inputs::S3SNSSQS < LogStash::Inputs::Threadable
|
|
238
239
|
@received_stop = Concurrent::AtomicBoolean.new(false)
|
239
240
|
|
240
241
|
# instantiate helpers
|
241
|
-
@sqs_poller = SqsPoller.new(@logger, @received_stop,
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
242
|
+
@sqs_poller = SqsPoller.new(@logger, @received_stop,
|
243
|
+
{
|
244
|
+
visibility_timeout: @visibility_timeout,
|
245
|
+
skip_delete: @sqs_skip_delete
|
246
|
+
},
|
247
|
+
{
|
248
|
+
sqs_queue: @queue,
|
249
|
+
queue_owner_aws_account_id: @queue_owner_aws_account_id,
|
250
|
+
from_sns: @from_sns,
|
251
|
+
max_processing_time: @max_processing_time
|
252
|
+
},
|
253
|
+
aws_options_hash)
|
247
254
|
@s3_client_factory = S3ClientFactory.new(@logger, {
|
248
255
|
aws_region: @region,
|
249
256
|
s3_default_options: @s3_default_options,
|
@@ -271,7 +278,10 @@ class LogStash::Inputs::S3SNSSQS < LogStash::Inputs::Threadable
|
|
271
278
|
@queue_mutex = Mutex.new
|
272
279
|
#@consumer_threads= 1
|
273
280
|
@worker_threads = @consumer_threads.times.map do |thread_id|
|
274
|
-
run_worker_thread(logstash_event_queue, thread_id)
|
281
|
+
t = run_worker_thread(logstash_event_queue, thread_id)
|
282
|
+
#make thead start async to prevent polling the same message from sqs
|
283
|
+
sleep 0.5
|
284
|
+
t
|
275
285
|
end
|
276
286
|
# and wait (possibly infinitely) for them to shut down
|
277
287
|
@worker_threads.each { |t| t.join }
|
@@ -280,13 +290,16 @@ class LogStash::Inputs::S3SNSSQS < LogStash::Inputs::Threadable
|
|
280
290
|
# shutdown
|
281
291
|
def stop
|
282
292
|
@received_stop.make_true
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
293
|
+
|
294
|
+
unless @worker_threads.nil?
|
295
|
+
@worker_threads.each do |worker|
|
296
|
+
begin
|
297
|
+
@logger.info("Stopping thread ... ", :thread => worker.inspect)
|
298
|
+
worker.wakeup
|
299
|
+
rescue
|
300
|
+
@logger.error("Cannot stop thread ... try to kill him", :thread => worker.inspect)
|
301
|
+
worker.kill
|
302
|
+
end
|
290
303
|
end
|
291
304
|
end
|
292
305
|
end
|
@@ -301,14 +314,13 @@ class LogStash::Inputs::S3SNSSQS < LogStash::Inputs::Threadable
|
|
301
314
|
|
302
315
|
def run_worker_thread(queue, thread_id)
|
303
316
|
Thread.new do
|
304
|
-
|
317
|
+
LogStash::Util.set_thread_name("Worker #{@id}/#{thread_id}")
|
318
|
+
@logger.info("[#{Thread.current[:name]}] started (#{Time.now})") #PROFILING
|
305
319
|
temporary_directory = Dir.mktmpdir("#{@temporary_directory}/")
|
306
320
|
@sqs_poller.run do |record|
|
307
321
|
throw :skip_delete if stop?
|
308
|
-
@logger.debug("Outside Poller: got a record", :record => record)
|
309
322
|
# record is a valid object with the keys ":bucket", ":key", ":size"
|
310
323
|
record[:local_file] = File.join(temporary_directory, File.basename(record[:key]))
|
311
|
-
LogStash::Util.set_thread_name("[Processor #{thread_id} - Working on: #{record[:key]}")
|
312
324
|
if @s3_downloader.copy_s3object_to_disk(record)
|
313
325
|
completed = catch(:skip_delete) do
|
314
326
|
process(record, queue)
|
@@ -322,19 +334,18 @@ class LogStash::Inputs::S3SNSSQS < LogStash::Inputs::Threadable
|
|
322
334
|
end
|
323
335
|
end
|
324
336
|
|
325
|
-
# Will be
|
337
|
+
# Will be removed in further releases:
|
326
338
|
def get_object_folder(key)
|
327
339
|
if match = /#{s3_key_prefix}\/?(?<type_folder>.*?)\/.*/.match(key)
|
328
340
|
return match['type_folder']
|
329
341
|
else
|
330
|
-
#FIXME should be NIL instedt of empty sting?
|
331
342
|
return ""
|
332
343
|
end
|
333
344
|
end
|
334
345
|
|
335
346
|
def hash_key_is_regex(myhash)
|
336
347
|
myhash.default_proc = lambda do |hash, lookup|
|
337
|
-
result=nil
|
348
|
+
result = nil
|
338
349
|
hash.each_pair do |key, value|
|
339
350
|
if %r[#{key}] =~ lookup
|
340
351
|
result = value
|
@@ -14,33 +14,39 @@ module LogProcessor
|
|
14
14
|
file = record[:local_file]
|
15
15
|
codec = @codec_factory.get_codec(record)
|
16
16
|
folder = record[:folder]
|
17
|
-
type = @type_by_folder[folder]
|
17
|
+
type = @type_by_folder[folder]
|
18
18
|
metadata = {}
|
19
|
-
#@logger.info("processing file",:thread => Thread.current[:name], :local_file => record[:local_file])
|
20
19
|
line_count = 0
|
21
20
|
event_count = 0
|
21
|
+
#start_time = Time.now
|
22
|
+
file_t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC) #PROFILING
|
22
23
|
read_file(file) do |line|
|
23
24
|
line_count += 1
|
24
|
-
#@logger.info("got a yielded line", :line_count => line_count) if line_count < 10
|
25
25
|
if stop?
|
26
|
-
@logger.warn("Abort reading in the middle of the file, we will read it again when logstash is started")
|
26
|
+
@logger.warn("[#{Thread.current[:name]}] Abort reading in the middle of the file, we will read it again when logstash is started")
|
27
27
|
throw :skip_delete
|
28
28
|
end
|
29
29
|
line = line.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: "\u2370")
|
30
|
-
|
30
|
+
# Potentially dangerous! See https://medium.com/@adamhooper/in-ruby-dont-use-timeout-77d9d4e5a001
|
31
|
+
# Decoding a line must not last longer than a few seconds. Otherwise, the file is probably corrupt.
|
31
32
|
codec.decode(line) do |event|
|
32
|
-
decorate_event(event, metadata, type, record[:key], record[:bucket], folder)
|
33
33
|
event_count += 1
|
34
|
+
decorate_event(event, metadata, type, record[:key], record[:bucket], folder)
|
35
|
+
#event_time = Time.now #PROFILING
|
36
|
+
#event.set("[@metadata][progress][begin]", start_time)
|
37
|
+
#event.set("[@metadata][progress][index_time]", event_time)
|
38
|
+
#event.set("[@metadata][progress][line]", line_count)
|
34
39
|
logstash_event_queue << event
|
35
|
-
#@logger.info("queued event ", :lines => line_count, :events => event_count, :thread => Thread.current[:name]) if event_count < 10
|
36
40
|
end
|
37
|
-
#@logger.info("DEcoded line", :line_count => line_count) if line_count < 10
|
38
41
|
end
|
39
|
-
|
42
|
+
file_t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC) #PROFILING
|
43
|
+
processing_time = (file_t1 - file_t0)
|
44
|
+
#@logger.warn("[#{Thread.current[:name]}] Completed long running File ( took #{processing_time} ) s", file: record[:key], events: event_count, processing_time: processing_time ) if processing_time > 600.0 #PROFILING
|
40
45
|
# ensure any stateful codecs (such as multi-line ) are flushed to the queue
|
41
46
|
codec.flush do |event|
|
47
|
+
event_count += 1
|
42
48
|
decorate_event(event, metadata, type, record[:key], record[:bucket], folder)
|
43
|
-
@logger.debug("Flushing an incomplete event", :event => event.to_s)
|
49
|
+
@logger.debug("[#{Thread.current[:name]}] Flushing an incomplete event", :event => event.to_s)
|
44
50
|
logstash_event_queue << event
|
45
51
|
end
|
46
52
|
# signal completion:
|
@@ -55,7 +61,7 @@ module LogProcessor
|
|
55
61
|
update_metadata(metadata, event)
|
56
62
|
else
|
57
63
|
# type by folder - set before "decorate()" enforces default
|
58
|
-
event.set('type', type) if type
|
64
|
+
event.set('type', type) if type and ! event.include?('type')
|
59
65
|
decorate(event)
|
60
66
|
|
61
67
|
event.set("cloudfront_version", metadata[:cloudfront_version]) unless metadata[:cloudfront_version].nil?
|
@@ -63,7 +69,6 @@ module LogProcessor
|
|
63
69
|
|
64
70
|
event.set("[@metadata][s3][object_key]", key)
|
65
71
|
event.set("[@metadata][s3][bucket_name]", bucket)
|
66
|
-
event.set("[@metadata][s3][full_folder]", folder)
|
67
72
|
event.set("[@metadata][s3][object_folder]", get_object_folder(key))
|
68
73
|
end
|
69
74
|
end
|
@@ -99,9 +104,13 @@ module LogProcessor
|
|
99
104
|
decoder.close unless decoder.nil?
|
100
105
|
gzip_stream.close unless gzip_stream.nil?
|
101
106
|
file_stream.close unless file_stream.nil?
|
102
|
-
throw :skip_delete unless completed
|
103
|
-
end
|
104
107
|
|
108
|
+
unless completed
|
109
|
+
@logger.warn("[#{Thread.current[:name]}] Incomplete message in read_file. We´ll throw skip_delete.", :filename => filename)
|
110
|
+
throw :skip_delete
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
105
114
|
|
106
115
|
def event_is_metadata?(event)
|
107
116
|
return false unless event.get("message").class == String
|
@@ -15,11 +15,13 @@ class SqsPoller
|
|
15
15
|
# "DefaultVisibilityTimeout" for your queue so that there's enough time
|
16
16
|
# to process the log files!)
|
17
17
|
max_number_of_messages: 1,
|
18
|
-
visibility_timeout:
|
18
|
+
visibility_timeout: 10,
|
19
19
|
# long polling; by default we use the queue's setting.
|
20
20
|
# A good value is 10 seconds to to balance between a quick logstash
|
21
21
|
# shutdown and fewer api calls.
|
22
22
|
wait_time_seconds: nil,
|
23
|
+
#attribute_names: ["All"], # Receive all available built-in message attributes.
|
24
|
+
#message_attribute_names: ["All"], # Receive any custom message attributes.
|
23
25
|
skip_delete: false,
|
24
26
|
}
|
25
27
|
|
@@ -33,20 +35,19 @@ class SqsPoller
|
|
33
35
|
|
34
36
|
# initialization and setup happens once, outside the threads:
|
35
37
|
#
|
36
|
-
def initialize(logger, stop_semaphore,
|
38
|
+
def initialize(logger, stop_semaphore, poller_options = {}, client_options = {}, aws_options_hash)
|
37
39
|
@logger = logger
|
38
40
|
@stopped = stop_semaphore
|
39
|
-
@queue = sqs_queue
|
40
|
-
|
41
|
-
@
|
42
|
-
@options = DEFAULT_OPTIONS.merge(
|
43
|
-
@options[:skip_delete] = options[:sqs_skip_delete]
|
41
|
+
@queue = client_options[:sqs_queue]
|
42
|
+
@from_sns = client_options[:from_sns]
|
43
|
+
@max_processing_time = client_options[:max_processing_time]
|
44
|
+
@options = DEFAULT_OPTIONS.merge(poller_options)
|
44
45
|
begin
|
45
46
|
@logger.info("Registering SQS input", :queue => @queue)
|
46
47
|
sqs_client = Aws::SQS::Client.new(aws_options_hash)
|
47
48
|
queue_url = sqs_client.get_queue_url({
|
48
49
|
queue_name: @queue,
|
49
|
-
queue_owner_aws_account_id:
|
50
|
+
queue_owner_aws_account_id: client_options[:queue_owner_aws_account_id]
|
50
51
|
}).queue_url # is a method according to docs. Was [:queue_url].
|
51
52
|
@poller = Aws::SQS::QueuePoller.new(queue_url,
|
52
53
|
:client => sqs_client
|
@@ -57,13 +58,11 @@ class SqsPoller
|
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
60
|
-
#
|
61
61
|
# this is called by every worker thread:
|
62
|
-
#
|
63
62
|
def run() # not (&block) - pass explicitly (use yield below)
|
64
63
|
# per-thread timer to extend visibility if necessary
|
65
64
|
extender = nil
|
66
|
-
message_backoff = (@options[:visibility_timeout] *
|
65
|
+
message_backoff = (@options[:visibility_timeout] * 95).to_f / 100.0
|
67
66
|
new_visibility = 2 * @options[:visibility_timeout]
|
68
67
|
|
69
68
|
# "shutdown handler":
|
@@ -79,19 +78,39 @@ class SqsPoller
|
|
79
78
|
end
|
80
79
|
|
81
80
|
run_with_backoff do
|
81
|
+
message_count = 0 #PROFILING
|
82
82
|
@poller.poll(@options) do |message|
|
83
|
-
|
84
|
-
|
83
|
+
message_count += 1 #PROFILING
|
84
|
+
message_t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC) #PROFILING
|
85
|
+
# auto-increase the timeout if processing takes too long:
|
86
|
+
poller_thread = Thread.current
|
85
87
|
extender = Thread.new do
|
86
|
-
|
87
|
-
|
88
|
-
|
88
|
+
while new_visibility < @max_processing_time do
|
89
|
+
sleep message_backoff
|
90
|
+
begin
|
91
|
+
@poller.change_message_visibility_timeout(message, new_visibility)
|
92
|
+
@logger.warn("[#{Thread.current[:name]}] Extended visibility for a long running message", :visibility => new_visibility) if new_visibility > 600.0
|
93
|
+
new_visibility += message_backoff
|
94
|
+
rescue Aws::SQS::Errors::InvalidParameterValue => e
|
95
|
+
@logger.debug("Extending visibility failed for message", :error => e)
|
96
|
+
else
|
97
|
+
@logger.debug("[#{Thread.current[:name]}] Extended visibility for message", :visibility => new_visibility) #PROFILING
|
98
|
+
end
|
99
|
+
end
|
100
|
+
@logger.error("[#{Thread.current[:name]}] Maximum visibility reached! We will delete this message from queue!")
|
101
|
+
@poller.delete_message(message)
|
102
|
+
poller_thread.raise "[#{poller_thread[:name]}] Maximum visibility reached...!".freeze
|
89
103
|
end
|
104
|
+
extender[:name] = "#{Thread.current[:name]}/extender" #PROFILING
|
90
105
|
failed = false
|
106
|
+
record_count = 0
|
91
107
|
begin
|
92
|
-
|
93
|
-
|
94
|
-
|
108
|
+
message_completed = catch(:skip_delete) do
|
109
|
+
preprocess(message) do |record|
|
110
|
+
record_count += 1
|
111
|
+
extender[:name] = "#{Thread.current[:name]}/extender/#{record[:key]}" #PROFILING
|
112
|
+
yield(record)
|
113
|
+
end
|
95
114
|
end
|
96
115
|
rescue Exception => e
|
97
116
|
@logger.warn("Error in poller loop", :error => e)
|
@@ -100,9 +119,14 @@ class SqsPoller
|
|
100
119
|
end
|
101
120
|
# at this time the extender has either fired or is obsolete
|
102
121
|
extender.kill
|
103
|
-
#@logger.info("Inside Poller: killed background thread", :message => message)
|
104
122
|
extender = nil
|
105
|
-
|
123
|
+
message_t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC) #PROFILING
|
124
|
+
unless message_completed
|
125
|
+
@logger.debug("[#{Thread.current[:name]}] uncompleted message at the end of poller loop. We´ll throw skip_delete.", :message_count => message_count)
|
126
|
+
extender.run
|
127
|
+
end
|
128
|
+
throw :skip_delete if failed or ! message_completed
|
129
|
+
#@logger.info("[#{Thread.current[:name]}] completed message.", :message => message_count)
|
106
130
|
end
|
107
131
|
end
|
108
132
|
end
|
@@ -114,7 +138,7 @@ class SqsPoller
|
|
114
138
|
end
|
115
139
|
|
116
140
|
def preprocess(message)
|
117
|
-
@logger.debug("Inside Preprocess: Start", :
|
141
|
+
@logger.debug("Inside Preprocess: Start", :event => message)
|
118
142
|
payload = JSON.parse(message.body)
|
119
143
|
payload = JSON.parse(payload['Message']) if @from_sns
|
120
144
|
@logger.debug("Payload in Preprocess: ", :payload => payload)
|
@@ -132,20 +156,8 @@ class SqsPoller
|
|
132
156
|
bucket: bucket,
|
133
157
|
key: key,
|
134
158
|
size: size,
|
135
|
-
folder:
|
159
|
+
folder: get_object_path(key)
|
136
160
|
})
|
137
|
-
|
138
|
-
# -v- this stuff goes into s3 and processor handling: -v-
|
139
|
-
|
140
|
-
# type_folder = get_object_folder(key)
|
141
|
-
# Set input codec by :set_codec_by_folder
|
142
|
-
# instance_codec = set_codec(type_folder) unless set_codec_by_folder["#{type_folder}"].nil?
|
143
|
-
# try download and :skip_delete if it fails
|
144
|
-
#if record['s3']['object']['size'] < 10000000 then
|
145
|
-
# process_log(bucket, key, type_folder, instance_codec, queue, message, size)
|
146
|
-
#else
|
147
|
-
# @logger.info("Your file is too big")
|
148
|
-
#end
|
149
161
|
end
|
150
162
|
end
|
151
163
|
end
|
@@ -171,11 +183,7 @@ class SqsPoller
|
|
171
183
|
end
|
172
184
|
end
|
173
185
|
|
174
|
-
def
|
175
|
-
# TEST THIS!
|
176
|
-
# if match = /.*\/?(?<type_folder>)\/[^\/]*.match(key)
|
177
|
-
# return match['type_folder']
|
178
|
-
# end
|
186
|
+
def get_object_path(key)
|
179
187
|
folder = ::File.dirname(key)
|
180
188
|
return '' if folder == '.'
|
181
189
|
return folder
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-input-s3-sns-sqs'
|
3
|
-
s.version = '2.0.
|
3
|
+
s.version = '2.0.4'
|
4
4
|
s.licenses = ['Apache-2.0']
|
5
5
|
s.summary = "Get logs from AWS s3 buckets as issued by an object-created event via sns -> sqs."
|
6
6
|
s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-input-s3-sns-sqs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christian Herweg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-08-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|