logstash-output-google_cloud_storage 4.0.1-java → 4.1.0-java
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 +3 -0
- data/docs/index.asciidoc +11 -4
- data/lib/logstash/outputs/gcs/log_rotate.rb +4 -4
- data/lib/logstash/outputs/google_cloud_storage.rb +20 -15
- data/logstash-output-google_cloud_storage.gemspec +7 -5
- data/spec/outputs/gcs/log_rotate_spec.rb +13 -13
- data/spec/outputs/gcs/path_factory_spec.rb +2 -2
- data/spec/outputs/google_cloud_storage_spec.rb +79 -1
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c96bc2ab86ede5dcbcb77ba9ca521f952122cb6fe2b010e3858b45fe70a2bf83
|
4
|
+
data.tar.gz: 44f8de48f9d8e1d225ed42a4bb30e2b38448cfee556d1491970cb4fa28fc24f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c198cf37eaf81b51e3325af6b519782780fdf0334a81b78654df6663f11c3eda7466297bc997b5dd1551f97cf4f667791bf54d2292aeba3a87d6f672f22c43a3
|
7
|
+
data.tar.gz: 9a872177cfd7b33cc934983f708414d6cd06abfd1f2d2ab0d69e576403bcab0ac67d705197cce9fc266e5239937b7e0532bf4613c47d2b9de8cf18b7d92a8714
|
data/CHANGELOG.md
CHANGED
data/docs/index.asciidoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
:plugin: google_cloud_storage
|
2
2
|
:type: output
|
3
|
-
:default_codec:
|
3
|
+
:default_codec: line
|
4
4
|
|
5
5
|
///////////////////////////////////////////
|
6
6
|
START - GENERATED VARIABLES, DO NOT EDIT!
|
@@ -101,7 +101,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
|
|
101
101
|
| <<plugins-{type}s-{plugin}-log_file_prefix>> |<<string,string>>|No
|
102
102
|
| <<plugins-{type}s-{plugin}-max_concurrent_uploads>> |<<number,number>>|No
|
103
103
|
| <<plugins-{type}s-{plugin}-max_file_size_kbytes>> |<<number,number>>|No
|
104
|
-
| <<plugins-{type}s-{plugin}-output_format>> |<<string,string>>, one of `["json", "plain"]`|
|
104
|
+
| <<plugins-{type}s-{plugin}-output_format>> |<<string,string>>, one of `["json", "plain", nil]`|__Deprecated__
|
105
105
|
| <<plugins-{type}s-{plugin}-service_account>> |<<string,string>>|__Deprecated__
|
106
106
|
| <<plugins-{type}s-{plugin}-temp_directory>> |<<string,string>>|No
|
107
107
|
| <<plugins-{type}s-{plugin}-uploader_interval_secs>> |<<number,number>>|No
|
@@ -264,11 +264,18 @@ Sets max file size in kbytes. 0 disable max file check.
|
|
264
264
|
[id="plugins-{type}s-{plugin}-output_format"]
|
265
265
|
===== `output_format`
|
266
266
|
|
267
|
-
* Value can be any of: `json`, `plain
|
268
|
-
* Default value is
|
267
|
+
* Value can be any of: `json`, `plain`, or no value
|
268
|
+
* Default value is no value
|
269
|
+
|
270
|
+
**Deprecated**, this feature will be removed in the next major release. Use codecs instead.
|
271
|
+
|
272
|
+
* If you are using the `json` value today, switch to the `json_lines` codec.
|
273
|
+
* If you are using the `plain` value today, switch to the `line` codec.
|
269
274
|
|
270
275
|
The event format you want to store in files. Defaults to plain text.
|
271
276
|
|
277
|
+
Note: if you want to use a codec you MUST not set this value.
|
278
|
+
|
272
279
|
[id="plugins-{type}s-{plugin}-service_account"]
|
273
280
|
===== `service_account`
|
274
281
|
|
@@ -19,15 +19,15 @@ module LogStash
|
|
19
19
|
rotate_log!
|
20
20
|
end
|
21
21
|
|
22
|
-
#
|
23
|
-
#
|
22
|
+
# write writes zero or more messages to the open log file
|
23
|
+
# rotating and syncing it if necessary.
|
24
24
|
#
|
25
25
|
# nil messages do not get written, but may cause the log to rotate
|
26
|
-
def
|
26
|
+
def write(*messages)
|
27
27
|
@lock.with_write_lock do
|
28
28
|
rotate_log! if should_rotate?
|
29
29
|
|
30
|
-
@temp_file.write(
|
30
|
+
@temp_file.write(*messages) unless messages.empty?
|
31
31
|
|
32
32
|
@temp_file.fsync if @temp_file.time_since_sync >= @flush_interval_secs
|
33
33
|
end
|
@@ -58,7 +58,6 @@ require "zlib"
|
|
58
58
|
# temp_directory => "/tmp/logstash-gcs" (optional)
|
59
59
|
# log_file_prefix => "logstash_gcs" (optional)
|
60
60
|
# max_file_size_kbytes => 1024 (optional)
|
61
|
-
# output_format => "plain" (optional)
|
62
61
|
# date_pattern => "%Y-%m-%dT%H:00" (optional)
|
63
62
|
# flush_interval_secs => 2 (optional)
|
64
63
|
# gzip => false (optional)
|
@@ -79,6 +78,7 @@ class LogStash::Outputs::GoogleCloudStorage < LogStash::Outputs::Base
|
|
79
78
|
config_name "google_cloud_storage"
|
80
79
|
|
81
80
|
concurrency :single
|
81
|
+
default :codec, "line"
|
82
82
|
|
83
83
|
# GCS bucket name, without "gs://" or any other prefix.
|
84
84
|
config :bucket, :validate => :string, :required => true
|
@@ -104,7 +104,7 @@ class LogStash::Outputs::GoogleCloudStorage < LogStash::Outputs::Base
|
|
104
104
|
config :max_file_size_kbytes, :validate => :number, :default => 10000
|
105
105
|
|
106
106
|
# The event format you want to store in files. Defaults to plain text.
|
107
|
-
config :output_format, :validate => [ "json", "plain" ], :default =>
|
107
|
+
config :output_format, :validate => [ "json", "plain", nil ], :default => nil, :deprecated => 'Use codec instead.'
|
108
108
|
|
109
109
|
# Time pattern for log file, defaults to hourly files.
|
110
110
|
# Must Time.strftime patterns: www.ruby-doc.org/core-2.0/Time.html#method-i-strftime
|
@@ -154,10 +154,18 @@ class LogStash::Outputs::GoogleCloudStorage < LogStash::Outputs::Base
|
|
154
154
|
|
155
155
|
config :max_concurrent_uploads, :validate => :number, :default => 5
|
156
156
|
|
157
|
+
attr_accessor :disable_uploader
|
158
|
+
|
157
159
|
public
|
158
160
|
def register
|
159
161
|
@logger.debug('Registering Google Cloud Storage plugin')
|
160
162
|
|
163
|
+
# NOTE: this is a hacky solution to get around the fact that we used to
|
164
|
+
# do our own pseudo-codec processing. This should be removed in the
|
165
|
+
# next major release.
|
166
|
+
params['codec'] = LogStash::Plugin.lookup('codec', 'json_lines').new if @output_format == 'json'
|
167
|
+
params['codec'] = LogStash::Plugin.lookup('codec', 'line').new if @output_format == 'plain'
|
168
|
+
|
161
169
|
@workers = LogStash::Outputs::Gcs::WorkerPool.new(@max_concurrent_uploads, @upload_synchronous)
|
162
170
|
initialize_temp_directory
|
163
171
|
initialize_path_factory
|
@@ -171,25 +179,20 @@ class LogStash::Outputs::GoogleCloudStorage < LogStash::Outputs::Base
|
|
171
179
|
@content_encoding = @gzip_content_encoding ? 'gzip' : 'identity'
|
172
180
|
end
|
173
181
|
|
174
|
-
# Method called for
|
182
|
+
# Method called for incoming log events. It writes the event to the current output
|
175
183
|
# file, flushing depending on flush interval configuration.
|
176
184
|
public
|
177
|
-
def
|
178
|
-
|
179
|
-
|
180
|
-
if @output_format == 'json'
|
181
|
-
message = LogStash::Json.dump(event.to_hash)
|
182
|
-
else
|
183
|
-
message = event.to_s
|
184
|
-
end
|
185
|
+
def multi_receive_encoded(event_encoded_pairs)
|
186
|
+
encoded = event_encoded_pairs.map{ |event, encoded| encoded }
|
187
|
+
@logger.debug? && @logger.debug('Received events', :events => encoded)
|
185
188
|
|
186
|
-
@log_rotater.
|
189
|
+
@log_rotater.write(*encoded)
|
187
190
|
end
|
188
191
|
|
189
192
|
public
|
190
193
|
def close
|
191
194
|
@logger.debug('Stopping the plugin, uploading the remaining files.')
|
192
|
-
Stud.stop!(@
|
195
|
+
Stud.stop!(@uploader_thread) unless @uploader_thread.nil?
|
193
196
|
|
194
197
|
# Force rotate the log. If it contains data it will be submitted
|
195
198
|
# to the work pool and will be uploaded before the plugin stops.
|
@@ -229,9 +232,11 @@ class LogStash::Outputs::GoogleCloudStorage < LogStash::Outputs::Base
|
|
229
232
|
|
230
233
|
# start_uploader periodically sends flush events through the log rotater
|
231
234
|
def start_uploader
|
232
|
-
|
235
|
+
return if @disable_uploader
|
236
|
+
|
237
|
+
@uploader_thread = Thread.new do
|
233
238
|
Stud.interval(@uploader_interval_secs) do
|
234
|
-
@log_rotater.
|
239
|
+
@log_rotater.write
|
235
240
|
end
|
236
241
|
end
|
237
242
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-output-google_cloud_storage'
|
3
|
-
s.version = '4.0
|
3
|
+
s.version = '4.1.0'
|
4
4
|
s.licenses = ['Apache-2.0']
|
5
5
|
s.summary = "plugin to upload log events to Google Cloud Storage (GCS)"
|
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"
|
@@ -18,16 +18,18 @@ Gem::Specification.new do |s|
|
|
18
18
|
# Special flag to let us know this is actually a logstash plugin
|
19
19
|
s.metadata = { "logstash_plugin" => "true", "logstash_group" => "output" }
|
20
20
|
|
21
|
+
# JARs
|
22
|
+
s.platform = 'java'
|
23
|
+
|
21
24
|
# Gem dependencies
|
22
25
|
s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
|
23
26
|
|
24
27
|
s.add_runtime_dependency 'stud'
|
25
|
-
s.add_runtime_dependency 'logstash-codec-
|
28
|
+
s.add_runtime_dependency 'logstash-codec-line'
|
29
|
+
s.add_runtime_dependency 'logstash-codec-json_lines'
|
26
30
|
s.add_runtime_dependency 'mime-types', '~> 2' # last version compatible with ruby 2.x
|
27
31
|
s.add_runtime_dependency 'concurrent-ruby' # use version bundled with Logstash to avoid platform mismatch on plugin install
|
28
|
-
s.add_development_dependency 'logstash-devutils'
|
29
32
|
|
30
|
-
|
31
|
-
s.platform = 'java'
|
33
|
+
s.add_development_dependency 'logstash-devutils'
|
32
34
|
end
|
33
35
|
|
@@ -27,7 +27,7 @@ describe LogStash::Outputs::Gcs::LogRotate do
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
describe '#
|
30
|
+
describe '#write' do
|
31
31
|
subject { LogStash::Outputs::Gcs::LogRotate.new(path_factory, 10, false, 30) }
|
32
32
|
|
33
33
|
it 'does not rotate if size is small and path is the same' do
|
@@ -35,15 +35,15 @@ describe LogStash::Outputs::Gcs::LogRotate do
|
|
35
35
|
# once for init
|
36
36
|
expect(path_factory).to receive(:rotate_path!).once
|
37
37
|
|
38
|
-
subject.
|
38
|
+
subject.write('foo')
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'rotates the file if the size is too big' do
|
42
42
|
# once for init, once for writeln
|
43
43
|
expect(path_factory).to receive(:rotate_path!).twice
|
44
44
|
|
45
|
-
subject.
|
46
|
-
subject.
|
45
|
+
subject.write('this line is longer than ten characters' * 1000)
|
46
|
+
subject.write('flush')
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'rotates the file if the path changed' do
|
@@ -51,35 +51,35 @@ describe LogStash::Outputs::Gcs::LogRotate do
|
|
51
51
|
# once for init, once for writeln
|
52
52
|
expect(path_factory).to receive(:rotate_path!).twice
|
53
53
|
|
54
|
-
subject.
|
54
|
+
subject.write('foo')
|
55
55
|
end
|
56
56
|
|
57
57
|
it 'writes the message' do
|
58
58
|
expect(LogStash::Outputs::Gcs::LogFileFactory).to receive(:create).and_return(open_file_1)
|
59
|
-
expect(open_file_1).to receive(:write).with('foo',
|
59
|
+
expect(open_file_1).to receive(:write).with('foo', 'bar')
|
60
60
|
|
61
|
-
subject.
|
61
|
+
subject.write('foo', 'bar')
|
62
62
|
end
|
63
63
|
|
64
|
-
it 'does not write
|
64
|
+
it 'does not write if there are no parameters' do
|
65
65
|
expect(LogStash::Outputs::Gcs::LogFileFactory).to receive(:create).and_return(open_file_1)
|
66
66
|
expect(open_file_1).not_to receive(:write)
|
67
67
|
|
68
|
-
subject.
|
68
|
+
subject.write
|
69
69
|
end
|
70
70
|
|
71
71
|
it 'does not fsync if delta less than limit' do
|
72
72
|
expect(LogStash::Outputs::Gcs::LogFileFactory).to receive(:create).and_return(open_file_1)
|
73
73
|
expect(open_file_1).not_to receive(:fsync)
|
74
74
|
|
75
|
-
subject.
|
75
|
+
subject.write
|
76
76
|
end
|
77
77
|
|
78
78
|
it 'fsyncs if delta greater than limit' do
|
79
79
|
expect(LogStash::Outputs::Gcs::LogFileFactory).to receive(:create).and_return(open_file_2)
|
80
80
|
expect(open_file_2).to receive(:fsync)
|
81
81
|
|
82
|
-
subject.
|
82
|
+
subject.write
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -106,10 +106,10 @@ describe LogStash::Outputs::Gcs::LogRotate do
|
|
106
106
|
|
107
107
|
it 'opens a new file based on the new path' do
|
108
108
|
expect(LogStash::Outputs::Gcs::LogFileFactory).to receive(:create).and_return(open_file_1, open_file_2)
|
109
|
-
expect(open_file_2).to receive(:write).with('foo',
|
109
|
+
expect(open_file_2).to receive(:write).with('foo', 'bar')
|
110
110
|
|
111
111
|
subject.rotate_log!
|
112
|
-
subject.
|
112
|
+
subject.write('foo', 'bar')
|
113
113
|
end
|
114
114
|
end
|
115
115
|
|
@@ -114,13 +114,13 @@ describe LogStash::Outputs::Gcs::PathFactory do
|
|
114
114
|
builder.set_directory 'dir'
|
115
115
|
builder.set_prefix 'pre'
|
116
116
|
builder.set_include_host false
|
117
|
-
builder.set_date_pattern '%
|
117
|
+
builder.set_date_pattern '%s'
|
118
118
|
builder.set_include_part true
|
119
119
|
builder.set_include_uuid false
|
120
120
|
builder.set_is_gzipped false
|
121
121
|
end
|
122
122
|
expect(pf.current_path).to include('part000')
|
123
|
-
|
123
|
+
sleep(1)
|
124
124
|
pf.rotate_path!
|
125
125
|
expect(pf.current_path).to include('part000')
|
126
126
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require_relative "../spec_helper"
|
3
3
|
require "tempfile"
|
4
|
+
require "json"
|
4
5
|
|
5
6
|
describe LogStash::Outputs::GoogleCloudStorage do
|
6
7
|
|
@@ -15,9 +16,86 @@ describe LogStash::Outputs::GoogleCloudStorage do
|
|
15
16
|
allow(javaclient).to receive(:initialize_storage).and_return(:javastorage)
|
16
17
|
end
|
17
18
|
|
18
|
-
it
|
19
|
+
it 'should register without errors' do
|
19
20
|
expect { subject.register }.to_not raise_error
|
20
21
|
|
21
22
|
subject.close
|
22
23
|
end
|
24
|
+
|
25
|
+
describe '#encode' do
|
26
|
+
it 'should dump the event hash if output_format is json' do
|
27
|
+
encoded = encode_test({
|
28
|
+
:output_format => 'json',
|
29
|
+
:event => {'message' => 'contents'}
|
30
|
+
})
|
31
|
+
|
32
|
+
expect(encoded.end_with?("\n")).to eq(true)
|
33
|
+
|
34
|
+
encoded_hash = JSON.parse(encoded)
|
35
|
+
expect(encoded_hash).to eq({
|
36
|
+
'message' => 'contents',
|
37
|
+
'@timestamp' => '1970-01-01T00:00:00.000Z',
|
38
|
+
'host' => 'localhost',
|
39
|
+
'@version' => '1'})
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should convert to a string if output_format is plain' do
|
43
|
+
encoded = encode_test({
|
44
|
+
:output_format => 'plain',
|
45
|
+
:event => {'message' => 'contents'}
|
46
|
+
})
|
47
|
+
|
48
|
+
expect(encoded).to eq("1970-01-01T00:00:00.000Z localhost contents\n")
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should call the codec if output_format is blank' do
|
53
|
+
encoded = encode_test({
|
54
|
+
:output_format => nil,
|
55
|
+
:event => {'message' => 'contents'}
|
56
|
+
})
|
57
|
+
|
58
|
+
expect(encoded).to eq("1970-01-01T00:00:00.000Z localhost contents\n")
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should call the codec if no output_format' do
|
62
|
+
encoded = encode_test({
|
63
|
+
:event => {'message' => 'contents'}
|
64
|
+
})
|
65
|
+
|
66
|
+
expect(encoded).to eq("1970-01-01T00:00:00.000Z localhost contents\n")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def encode_test(params)
|
72
|
+
config = {
|
73
|
+
'bucket' => '',
|
74
|
+
'service_account' => '',
|
75
|
+
'uploader_interval_secs' => 10000,
|
76
|
+
'upload_synchronous' => true,
|
77
|
+
}
|
78
|
+
config['output_format'] = params[:output_format] if params[:output_format]
|
79
|
+
|
80
|
+
rotater = double('rotater')
|
81
|
+
allow(rotater).to receive(:on_rotate)
|
82
|
+
allow(rotater).to receive(:rotate_log!)
|
83
|
+
|
84
|
+
allow(LogStash::Outputs::Gcs::LogRotate).to receive(:new).and_return(rotater)
|
85
|
+
|
86
|
+
gcsout = LogStash::Outputs::GoogleCloudStorage.new(config)
|
87
|
+
gcsout.disable_uploader = true
|
88
|
+
gcsout.register
|
89
|
+
|
90
|
+
event = LogStash::Event.new(params[:event])
|
91
|
+
event.timestamp = LogStash::Timestamp.at(0)
|
92
|
+
event.set('host', 'localhost')
|
93
|
+
|
94
|
+
value = ''
|
95
|
+
allow(rotater).to receive(:write){ |line| value = line }
|
96
|
+
|
97
|
+
gcsout.multi_receive([event])
|
98
|
+
gcsout.close
|
99
|
+
|
100
|
+
value
|
23
101
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-output-google_cloud_storage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0
|
4
|
+
version: 4.1.0
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-08-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,7 +50,21 @@ dependencies:
|
|
50
50
|
- - ">="
|
51
51
|
- !ruby/object:Gem::Version
|
52
52
|
version: '0'
|
53
|
-
name: logstash-codec-
|
53
|
+
name: logstash-codec-line
|
54
|
+
prerelease: false
|
55
|
+
type: :runtime
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
name: logstash-codec-json_lines
|
54
68
|
prerelease: false
|
55
69
|
type: :runtime
|
56
70
|
version_requirements: !ruby/object:Gem::Requirement
|