logstash-output-s3 4.3.4 → 4.3.7
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 +15 -5
- data/docs/index.asciidoc +13 -3
- data/lib/logstash/outputs/s3/file_repository.rb +11 -11
- data/lib/logstash/outputs/s3.rb +30 -19
- data/logstash-output-s3.gemspec +1 -1
- data/spec/outputs/s3/file_repository_spec.rb +7 -2
- data/spec/outputs/s3_spec.rb +6 -4
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 238e7be91fe40e4fcb80736f3e8d62e76b6f8108be35e5a0c054cb19bb239428
|
4
|
+
data.tar.gz: eb0c70181aa21d20b794cd05d2e458b322b10f6e343ae41d96a1e6f49cf85858
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1194c4ee3defe1104fcc1c68d914c20e2ca2548ba6405960c75d4b398a7cd9949287c3410ead913ff82b5183164c4bd5bf858fe836f94f63654c582efab78ab5
|
7
|
+
data.tar.gz: cb135c3b28297db0f5ad90a4f7ab4ba6b8c112574815e38bdccdec685f5caa28ed7636f68569586f71205d651118dad7cc7dd0194786efb59bfb8113fa7d0afb
|
data/CHANGELOG.md
CHANGED
@@ -1,17 +1,27 @@
|
|
1
|
+
## 4.3.7
|
2
|
+
- Refactor: avoid usage of CHM (JRuby 9.3.4 work-around) [#248](https://github.com/logstash-plugins/logstash-output-s3/pull/248)
|
3
|
+
|
4
|
+
## 4.3.6
|
5
|
+
- Docs: more documentation on restore + temp dir [#236](https://github.com/logstash-plugins/logstash-output-s3/pull/236)
|
6
|
+
* minor logging improvements - use the same path: naming convention
|
7
|
+
|
8
|
+
## 4.3.5
|
9
|
+
- Feat: cast true/false values for additional_settings [#241](https://github.com/logstash-plugins/logstash-output-s3/pull/241)
|
10
|
+
|
1
11
|
## 4.3.4
|
2
|
-
-
|
12
|
+
- [DOC] Added note about performance implications of interpolated strings in prefixes [#233](https://github.com/logstash-plugins/logstash-output-s3/pull/233)
|
3
13
|
|
4
14
|
## 4.3.3
|
5
|
-
-
|
15
|
+
- [DOC] Updated links to use shared attributes [#230](https://github.com/logstash-plugins/logstash-output-s3/pull/230)
|
6
16
|
|
7
17
|
## 4.3.2
|
8
|
-
-
|
18
|
+
- [DOC] Added note that only AWS S3 is supported. No other S3 compatible storage solutions are supported. [#223](https://github.com/logstash-plugins/logstash-output-s3/pull/223)
|
9
19
|
|
10
20
|
## 4.3.1
|
11
|
-
-
|
21
|
+
- [DOC] Updated setting descriptions for clarity [#219](https://github.com/logstash-plugins/logstash-output-s3/pull/219) and [#220](https://github.com/logstash-plugins/logstash-output-s3/pull/220)
|
12
22
|
|
13
23
|
## 4.3.0
|
14
|
-
-
|
24
|
+
- Feat: Added retry_count and retry_delay config [#218](https://github.com/logstash-plugins/logstash-output-s3/pull/218)
|
15
25
|
|
16
26
|
## 4.2.0
|
17
27
|
- Added ability to specify [ONEZONE_IA](https://aws.amazon.com/s3/storage-classes/#__) as storage_class
|
data/docs/index.asciidoc
CHANGED
@@ -30,8 +30,9 @@ Other S3 compatible storage solutions are not supported.
|
|
30
30
|
S3 outputs create temporary files into the OS' temporary directory.
|
31
31
|
You can specify where to save them using the `temporary_directory` option.
|
32
32
|
|
33
|
-
IMPORTANT: For configurations containing multiple s3 outputs with the restore
|
34
|
-
option enabled, each output should define its own
|
33
|
+
IMPORTANT: For configurations containing multiple s3 outputs with the `restore`
|
34
|
+
option enabled, each output should define its own `temporary_directory`.
|
35
|
+
Shared or nested directories can cause data loss upon recovery.
|
35
36
|
|
36
37
|
===== Requirements
|
37
38
|
|
@@ -255,6 +256,10 @@ The AWS Region
|
|
255
256
|
Used to enable recovery after crash/abnormal termination.
|
256
257
|
Temporary log files will be recovered and uploaded.
|
257
258
|
|
259
|
+
NOTE: If you're using multiple S3 outputs, always set
|
260
|
+
<<plugins-{type}s-{plugin}-temporary_directory>> to a
|
261
|
+
unique directory. Otherwise the recovery mechanism won't work correctly.
|
262
|
+
|
258
263
|
[id="plugins-{type}s-{plugin}-retry_count"]
|
259
264
|
===== `retry_count`
|
260
265
|
|
@@ -388,7 +393,12 @@ Defaults to STANDARD.
|
|
388
393
|
* Default value is `"/tmp/logstash"`
|
389
394
|
|
390
395
|
Set the directory where logstash will store the tmp files before sending it to S3
|
391
|
-
default to the current OS temporary directory in linux
|
396
|
+
default to the current OS temporary directory in linux `/tmp/logstash`.
|
397
|
+
|
398
|
+
WARNING: Using multiple S3 outputs with `restore => true` requires unique directories
|
399
|
+
per output. All of the directory's contents are processed and deleted upon recovery, and shared or nested directories can cause data loss.
|
400
|
+
For example, an output using `/tmp/s3` and a second configured with `/tmp/s3/sub` would
|
401
|
+
cause issues. Having temporary directories `/tmp/s3/sub1` and `/tmp/s3/sub2` is fine.
|
392
402
|
|
393
403
|
[id="plugins-{type}s-{plugin}-time_file"]
|
394
404
|
===== `time_file`
|
@@ -1,11 +1,9 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require "java"
|
3
|
-
require "concurrent"
|
3
|
+
require "concurrent/map"
|
4
4
|
require "concurrent/timer_task"
|
5
5
|
require "logstash/util"
|
6
6
|
|
7
|
-
ConcurrentHashMap = java.util.concurrent.ConcurrentHashMap
|
8
|
-
|
9
7
|
module LogStash
|
10
8
|
module Outputs
|
11
9
|
class S3
|
@@ -41,7 +39,7 @@ module LogStash
|
|
41
39
|
end
|
42
40
|
|
43
41
|
class FactoryInitializer
|
44
|
-
|
42
|
+
|
45
43
|
def initialize(tags, encoding, temporary_directory, stale_time)
|
46
44
|
@tags = tags
|
47
45
|
@encoding = encoding
|
@@ -49,9 +47,10 @@ module LogStash
|
|
49
47
|
@stale_time = stale_time
|
50
48
|
end
|
51
49
|
|
52
|
-
def
|
50
|
+
def create_value(prefix_key)
|
53
51
|
PrefixedValue.new(TemporaryFileFactory.new(prefix_key, @tags, @encoding, @temporary_directory), @stale_time)
|
54
52
|
end
|
53
|
+
|
55
54
|
end
|
56
55
|
|
57
56
|
def initialize(tags, encoding, temporary_directory,
|
@@ -59,7 +58,7 @@ module LogStash
|
|
59
58
|
sweeper_interval = DEFAULT_STATE_SWEEPER_INTERVAL_SECS)
|
60
59
|
# The path need to contains the prefix so when we start
|
61
60
|
# logtash after a crash we keep the remote structure
|
62
|
-
@prefixed_factories =
|
61
|
+
@prefixed_factories = Concurrent::Map.new
|
63
62
|
|
64
63
|
@sweeper_interval = sweeper_interval
|
65
64
|
|
@@ -69,18 +68,19 @@ module LogStash
|
|
69
68
|
end
|
70
69
|
|
71
70
|
def keys
|
72
|
-
@prefixed_factories.
|
71
|
+
@prefixed_factories.keys
|
73
72
|
end
|
74
73
|
|
75
74
|
def each_files
|
76
|
-
@prefixed_factories.
|
75
|
+
@prefixed_factories.values.each do |prefixed_file|
|
77
76
|
prefixed_file.with_lock { |factory| yield factory.current }
|
78
77
|
end
|
79
78
|
end
|
80
79
|
|
81
80
|
# Return the file factory
|
82
81
|
def get_factory(prefix_key)
|
83
|
-
@prefixed_factories.
|
82
|
+
prefix_val = @prefixed_factories.fetch_or_store(prefix_key) { @factory_initializer.create_value(prefix_key) }
|
83
|
+
prefix_val.with_lock { |factory| yield factory }
|
84
84
|
end
|
85
85
|
|
86
86
|
def get_file(prefix_key)
|
@@ -97,7 +97,7 @@ module LogStash
|
|
97
97
|
|
98
98
|
def remove_stale(k, v)
|
99
99
|
if v.stale?
|
100
|
-
@prefixed_factories.
|
100
|
+
@prefixed_factories.delete_pair(k, v)
|
101
101
|
v.delete!
|
102
102
|
end
|
103
103
|
end
|
@@ -106,7 +106,7 @@ module LogStash
|
|
106
106
|
@stale_sweeper = Concurrent::TimerTask.new(:execution_interval => @sweeper_interval) do
|
107
107
|
LogStash::Util.set_thread_name("S3, Stale factory sweeper")
|
108
108
|
|
109
|
-
@prefixed_factories.
|
109
|
+
@prefixed_factories.each { |k, v| remove_stale(k,v) }
|
110
110
|
end
|
111
111
|
|
112
112
|
@stale_sweeper.execute
|
data/lib/logstash/outputs/s3.rb
CHANGED
@@ -110,7 +110,8 @@ class LogStash::Outputs::S3 < LogStash::Outputs::Base
|
|
110
110
|
|
111
111
|
# Set the size of file in bytes, this means that files on bucket when have dimension > file_size, they are stored in two or more file.
|
112
112
|
# If you have tags then it will generate a specific size file for every tags
|
113
|
-
|
113
|
+
#
|
114
|
+
# NOTE: define size of file is the better thing, because generate a local temporary file on disk and then put it in bucket.
|
114
115
|
config :size_file, :validate => :number, :default => 1024 * 1024 * 5
|
115
116
|
|
116
117
|
# Set the time, in MINUTES, to close the current sub_time_section of bucket.
|
@@ -118,10 +119,10 @@ class LogStash::Outputs::S3 < LogStash::Outputs::Base
|
|
118
119
|
# If it's valued 0 and rotation_strategy is 'time' or 'size_and_time' then the plugin reaise a configuration error.
|
119
120
|
config :time_file, :validate => :number, :default => 15
|
120
121
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
122
|
+
# If `restore => false` is specified and Logstash crashes, the unprocessed files are not sent into the bucket.
|
123
|
+
#
|
124
|
+
# NOTE: that the `recovery => true` default assumes multiple S3 outputs would set a unique `temporary_directory => ...`
|
125
|
+
# if they do not than only a single S3 output is safe to recover (since let-over files are processed and deleted).
|
125
126
|
config :restore, :validate => :boolean, :default => true
|
126
127
|
|
127
128
|
# The S3 canned ACL to use when putting the file. Defaults to "private".
|
@@ -147,6 +148,9 @@ class LogStash::Outputs::S3 < LogStash::Outputs::Base
|
|
147
148
|
|
148
149
|
# Set the directory where logstash will store the tmp files before sending it to S3
|
149
150
|
# default to the current OS temporary directory in linux /tmp/logstash
|
151
|
+
#
|
152
|
+
# NOTE: the reason we do not have a unique (isolated) temporary directory as a default, to support multiple plugin instances,
|
153
|
+
# is that we would have to rely on something static that does not change between restarts (e.g. a user set id => ...).
|
150
154
|
config :temporary_directory, :validate => :string, :default => File.join(Dir.tmpdir, "logstash")
|
151
155
|
|
152
156
|
# Specify a prefix to the uploaded filename, this can simulate directories on S3. Prefix does not require leading slash.
|
@@ -283,17 +287,24 @@ class LogStash::Outputs::S3 < LogStash::Outputs::Base
|
|
283
287
|
end
|
284
288
|
|
285
289
|
def symbolized_settings
|
286
|
-
@symbolized_settings ||=
|
290
|
+
@symbolized_settings ||= symbolize_keys_and_cast_true_false(@additional_settings)
|
287
291
|
end
|
288
292
|
|
289
|
-
def
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
293
|
+
def symbolize_keys_and_cast_true_false(hash)
|
294
|
+
case hash
|
295
|
+
when Hash
|
296
|
+
symbolized = {}
|
297
|
+
hash.each { |key, value| symbolized[key.to_sym] = symbolize_keys_and_cast_true_false(value) }
|
298
|
+
symbolized
|
299
|
+
when 'true'
|
300
|
+
true
|
301
|
+
when 'false'
|
302
|
+
false
|
303
|
+
else
|
304
|
+
hash
|
305
|
+
end
|
294
306
|
end
|
295
307
|
|
296
|
-
|
297
308
|
def normalize_key(prefix_key)
|
298
309
|
prefix_key.gsub(PathValidator.matches_re, PREFIX_KEY_NORMALIZE_CHARACTER)
|
299
310
|
end
|
@@ -340,10 +351,10 @@ class LogStash::Outputs::S3 < LogStash::Outputs::Base
|
|
340
351
|
temp_file = factory.current
|
341
352
|
|
342
353
|
if @rotation.rotate?(temp_file)
|
343
|
-
@logger.debug("Rotate file",
|
344
|
-
|
345
|
-
|
346
|
-
|
354
|
+
@logger.debug? && @logger.debug("Rotate file",
|
355
|
+
:key => temp_file.key,
|
356
|
+
:path => temp_file.path,
|
357
|
+
:strategy => @rotation.class.name)
|
347
358
|
|
348
359
|
upload_file(temp_file)
|
349
360
|
factory.rotate!
|
@@ -353,7 +364,7 @@ class LogStash::Outputs::S3 < LogStash::Outputs::Base
|
|
353
364
|
end
|
354
365
|
|
355
366
|
def upload_file(temp_file)
|
356
|
-
@logger.debug("Queue for upload", :path => temp_file.path)
|
367
|
+
@logger.debug? && @logger.debug("Queue for upload", :path => temp_file.path)
|
357
368
|
|
358
369
|
# if the queue is full the calling thread will be used to upload
|
359
370
|
temp_file.close # make sure the content is on disk
|
@@ -376,7 +387,7 @@ class LogStash::Outputs::S3 < LogStash::Outputs::Base
|
|
376
387
|
end
|
377
388
|
|
378
389
|
def clean_temporary_file(file)
|
379
|
-
@logger.debug("Removing temporary file", :
|
390
|
+
@logger.debug? && @logger.debug("Removing temporary file", :path => file.path)
|
380
391
|
file.delete!
|
381
392
|
end
|
382
393
|
|
@@ -391,7 +402,7 @@ class LogStash::Outputs::S3 < LogStash::Outputs::Base
|
|
391
402
|
.each do |file|
|
392
403
|
temp_file = TemporaryFile.create_from_existing_file(file, temp_folder_path)
|
393
404
|
if temp_file.size > 0
|
394
|
-
@logger.debug("Recovering from crash and uploading", :
|
405
|
+
@logger.debug? && @logger.debug("Recovering from crash and uploading", :path => temp_file.path)
|
395
406
|
@crash_uploader.upload_async(temp_file, :on_complete => method(:clean_temporary_file), :upload_options => upload_options)
|
396
407
|
else
|
397
408
|
clean_temporary_file(temp_file)
|
data/logstash-output-s3.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-output-s3'
|
3
|
-
s.version = '4.3.
|
3
|
+
s.version = '4.3.7'
|
4
4
|
s.licenses = ['Apache-2.0']
|
5
5
|
s.summary = "Sends Logstash events to the Amazon Simple Storage Service"
|
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/logstash-plugin install gemname. This gem is not a stand-alone program"
|
@@ -88,8 +88,8 @@ describe LogStash::Outputs::S3::FileRepository do
|
|
88
88
|
|
89
89
|
it "returns all available keys" do
|
90
90
|
subject.get_file(prefix_key) { |file| file.write("something") }
|
91
|
-
expect(subject.keys
|
92
|
-
expect(subject.keys.
|
91
|
+
expect(subject.keys).to include(prefix_key)
|
92
|
+
expect(subject.keys.size).to eq(1)
|
93
93
|
end
|
94
94
|
|
95
95
|
it "clean stale factories" do
|
@@ -105,9 +105,14 @@ describe LogStash::Outputs::S3::FileRepository do
|
|
105
105
|
|
106
106
|
@file_repository.get_file("another-prefix") { |file| file.write("hello") }
|
107
107
|
expect(@file_repository.size).to eq(2)
|
108
|
+
sleep 1.2 # allow sweeper to kick in
|
108
109
|
try(10) { expect(@file_repository.size).to eq(1) }
|
109
110
|
expect(File.directory?(path)).to be_falsey
|
111
|
+
|
112
|
+
sleep 1.5 # allow sweeper to kick in, again
|
113
|
+
expect(@file_repository.size).to eq(1)
|
110
114
|
end
|
115
|
+
|
111
116
|
end
|
112
117
|
|
113
118
|
|
data/spec/outputs/s3_spec.rb
CHANGED
@@ -140,7 +140,7 @@ describe LogStash::Outputs::S3 do
|
|
140
140
|
|
141
141
|
describe "temporary directory" do
|
142
142
|
let(:temporary_directory) { Stud::Temporary.pathname }
|
143
|
-
let(:options) { super.merge({ "temporary_directory" => temporary_directory }) }
|
143
|
+
let(:options) { super().merge({ "temporary_directory" => temporary_directory }) }
|
144
144
|
|
145
145
|
it "creates the directory when it doesn't exist" do
|
146
146
|
expect(Dir.exist?(temporary_directory)).to be_falsey
|
@@ -160,13 +160,15 @@ describe LogStash::Outputs::S3 do
|
|
160
160
|
end
|
161
161
|
|
162
162
|
describe "additional_settings" do
|
163
|
-
context "
|
163
|
+
context "supported settings" do
|
164
164
|
let(:additional_settings) do
|
165
|
-
{ "additional_settings" => { "force_path_style" => true } }
|
165
|
+
{ "additional_settings" => { "force_path_style" => 'true', "ssl_verify_peer" => 'false', "profile" => 'logstash' } }
|
166
166
|
end
|
167
167
|
|
168
168
|
it "validates the prefix" do
|
169
|
-
expect(Aws::S3::Bucket).to receive(:new).twice.
|
169
|
+
expect(Aws::S3::Bucket).to receive(:new).twice.
|
170
|
+
with(anything, hash_including(:force_path_style => true, :ssl_verify_peer => false, :profile => 'logstash')).
|
171
|
+
and_call_original
|
170
172
|
described_class.new(options.merge(additional_settings)).register
|
171
173
|
end
|
172
174
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-output-s3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.3.
|
4
|
+
version: 4.3.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-06-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -185,8 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
185
|
- !ruby/object:Gem::Version
|
186
186
|
version: '0'
|
187
187
|
requirements: []
|
188
|
-
|
189
|
-
rubygems_version: 2.6.13
|
188
|
+
rubygems_version: 3.1.6
|
190
189
|
signing_key:
|
191
190
|
specification_version: 4
|
192
191
|
summary: Sends Logstash events to the Amazon Simple Storage Service
|