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 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