logstash-output-google_cloud_storage 4.0.1-java → 4.1.0-java

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
  SHA256:
3
- metadata.gz: 4aa7c73beda983444233b7943c788a49c2a9a7ac56218e78dce4bbe1932fb39a
4
- data.tar.gz: 7f88b0005ff2fada77f84d55365693e3a9eb582178923bdf240fe66db3f15ef0
3
+ metadata.gz: c96bc2ab86ede5dcbcb77ba9ca521f952122cb6fe2b010e3858b45fe70a2bf83
4
+ data.tar.gz: 44f8de48f9d8e1d225ed42a4bb30e2b38448cfee556d1491970cb4fa28fc24f6
5
5
  SHA512:
6
- metadata.gz: dddd13b7892f549aa748efcfd4a8bc16f108bb840c5179006ce12b57f027d55cafc5ed18ad36c03d7c2e2a370460ed1ebec26252323096cda3407eda5158dd94
7
- data.tar.gz: 2195cf539ad95c824a0c1f4f93527c76c6ff9c0ae5c6b9c98d44670004372ef49bd5fdfc843461e3d6879f11818a5bb5ad5103efde785193484ea4b73dcc07a9
6
+ metadata.gz: c198cf37eaf81b51e3325af6b519782780fdf0334a81b78654df6663f11c3eda7466297bc997b5dd1551f97cf4f667791bf54d2292aeba3a87d6f672f22c43a3
7
+ data.tar.gz: 9a872177cfd7b33cc934983f708414d6cd06abfd1f2d2ab0d69e576403bcab0ac67d705197cce9fc266e5239937b7e0532bf4613c47d2b9de8cf18b7d92a8714
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## 4.1.0
2
+ - Added ability to use Logstash codecs.
3
+
1
4
  ## 4.0.1
2
5
  - Fixes [#38](https://github.com/logstash-plugins/logstash-output-google_cloud_storage/issues/38) - Plugin doesn't start on logstash 7.1.1 - TypeError
3
6
 
data/docs/index.asciidoc CHANGED
@@ -1,6 +1,6 @@
1
1
  :plugin: google_cloud_storage
2
2
  :type: output
3
- :default_codec: plain
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"]`|No
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 `"plain"`
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
- # writeln writes a message and carriage-return character to the open
23
- # log file, rotating and syncing it if necessary.
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 writeln(message=nil)
26
+ def write(*messages)
27
27
  @lock.with_write_lock do
28
28
  rotate_log! if should_rotate?
29
29
 
30
- @temp_file.write(message, "\n") unless message.nil?
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 => "plain"
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 each log event. It writes the event to the current output
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 receive(event)
178
- @logger.debug('Received event', :event => event)
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.writeln(message)
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!(@registration_thread) unless @registration_thread.nil?
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
- @registration_thread = Thread.new do
235
+ return if @disable_uploader
236
+
237
+ @uploader_thread = Thread.new do
233
238
  Stud.interval(@uploader_interval_secs) do
234
- @log_rotater.writeln(nil)
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.1'
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-plain'
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
- # JARs
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 '#writeln' do
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.writeln('foo')
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.writeln('this line is longer than ten characters' * 1000)
46
- subject.writeln('flush')
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.writeln('foo')
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', "\n")
59
+ expect(open_file_1).to receive(:write).with('foo', 'bar')
60
60
 
61
- subject.writeln('foo')
61
+ subject.write('foo', 'bar')
62
62
  end
63
63
 
64
- it 'does not write nil messages' do
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.writeln(nil)
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.writeln(nil)
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.writeln(nil)
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', "\n")
109
+ expect(open_file_2).to receive(:write).with('foo', 'bar')
110
110
 
111
111
  subject.rotate_log!
112
- subject.writeln('foo')
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 '%N'
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 "should register without errors" do
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.1
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-06-24 00:00:00.000000000 Z
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-plain
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