logstash-output-google_cloud_storage 3.2.1 → 3.3.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 86d6c651af349b7693b77ebe7483211ac98ebace
4
+ data.tar.gz: a760d92081ee3c5f7792b53e2d751151f141e031
5
+ SHA512:
6
+ metadata.gz: 40f36c944a496412d81c0dc2346c1939db6ac171e92f17b875c8336786435cc34d8e352b849d7e27ef1fc4d57a39e51c488219b88828f1302d46380a5905f153
7
+ data.tar.gz: 21d8212a8a891f8e312a112bae840ef6b77791d9ada9eb0888bc5767a5579dd8c6b4140a75aeb0a6e52234f2e820c724c101476af56ce5c59eea60025d53d10c
@@ -1,3 +1,9 @@
1
+ ## 3.3.0
2
+ Added the ability to set `gzip` as `Content-Encoding`.
3
+ This saves storage size but still allows uncompressed downloads.
4
+
5
+ - Fixes [#13](https://github.com/logstash-plugins/logstash-output-google_cloud_storage/issues/13) - Use `gzip` for `Content-Encoding` instead of `Content-Type`
6
+
1
7
  ## 3.2.1
2
8
  - Refactoring work to add locks to file rotation and writing.
3
9
  - Fixes [#2](https://github.com/logstash-plugins/logstash-output-google_cloud_storage/issues/2) - Plugin crashes on file rotation.
@@ -3,7 +3,11 @@ reports, or in general have helped logstash along its way.
3
3
 
4
4
  Contributors:
5
5
  * Aaron Mildenstein (untergeek)
6
+ * Ethan Estrada (eestrada)
7
+ * Google LLC.
6
8
  * Jordan Sissel (jordansissel)
9
+ * Joseph Lewis III (jlewisiii)
10
+ * MetaPipe
7
11
  * Pier-Hugues Pellerin (ph)
8
12
  * Richard Pijnenburg (electrical)
9
13
  * Rodrigo De Castro (rdcastro)
@@ -56,6 +56,7 @@ output {
56
56
  date_pattern => "%Y-%m-%dT%H:00" (optional)
57
57
  flush_interval_secs => 2 (optional)
58
58
  gzip => false (optional)
59
+ gzip_content_encoding => false (optional)
59
60
  uploader_interval_secs => 60 (optional)
60
61
  include_uuid => true (optional)
61
62
  include_hostname => true (optional)
@@ -83,6 +84,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
83
84
  | <<plugins-{type}s-{plugin}-date_pattern>> |<<string,string>>|No
84
85
  | <<plugins-{type}s-{plugin}-flush_interval_secs>> |<<number,number>>|No
85
86
  | <<plugins-{type}s-{plugin}-gzip>> |<<boolean,boolean>>|No
87
+ | <<plugins-{type}s-{plugin}-gzip_content_encoding>> |<<boolean,boolean>>|No
86
88
  | <<plugins-{type}s-{plugin}-include_hostname>> |<<boolean,boolean>>|No
87
89
  | <<plugins-{type}s-{plugin}-include_uuid>> |<<boolean,boolean>>|No
88
90
  | <<plugins-{type}s-{plugin}-key_password>> |<<string,string>>|No
@@ -134,7 +136,29 @@ on every message.
134
136
  * Value type is <<boolean,boolean>>
135
137
  * Default value is `false`
136
138
 
137
- Gzip output stream when writing events to log files.
139
+ Gzip output stream when writing events to log files, set
140
+ `Content-Type` to `application/gzip` instead of `text/plain`, and
141
+ use file suffix `.log.gz` instead of `.log`.
142
+
143
+ [id="plugins-{type}s-{plugin}-gzip_content_encoding"]
144
+ ===== `gzip_content_encoding`
145
+
146
+ added[3.3.0]
147
+
148
+ * Value type is <<boolean,boolean>>
149
+ * Default value is `false`
150
+
151
+ Gzip output stream when writing events to log files and set `Content-Encoding` to `gzip`.
152
+ This will upload your files as `gzip` saving network and storage costs, but they will be
153
+ transparently decompressed when you read them from the storage bucket.
154
+
155
+ See the Cloud Storage documentation on https://cloud.google.com/storage/docs/metadata#content-encoding[metadata] and
156
+ https://cloud.google.com/storage/docs/transcoding#content-type_vs_content-encoding[transcoding]
157
+ for more information.
158
+
159
+ **Note**: It is not recommended to use both `gzip_content_encoding` and `gzip`.
160
+ This compresses your file _twice_, will increase the work your machine does and makes
161
+ the files larger than just compressing once.
138
162
 
139
163
  [id="plugins-{type}s-{plugin}-include_hostname"]
140
164
  ===== `include_hostname`
@@ -245,7 +269,4 @@ around one hour).
245
269
 
246
270
 
247
271
 
248
- [id="plugins-{type}s-{plugin}-common-options"]
249
272
  include::{include_path}/{type}.asciidoc[]
250
-
251
- :default_codec!:
@@ -6,11 +6,12 @@ module LogStash
6
6
  module Outputs
7
7
  module Gcs
8
8
  class LogRotate
9
- def initialize(path_factory, max_file_size_bytes, gzip, flush_interval_secs)
9
+ def initialize(path_factory, max_file_size_bytes, gzip, flush_interval_secs, gzip_encoded=false)
10
10
  @path_factory = path_factory
11
11
  @max_file_size_bytes = max_file_size_bytes
12
12
  @gzip = gzip
13
13
  @flush_interval_secs = flush_interval_secs
14
+ @gzip_encoded = gzip_encoded
14
15
 
15
16
  @lock = Concurrent::ReentrantReadWriteLock.new
16
17
  @rotate_callback = nil
@@ -47,7 +48,7 @@ module LogStash
47
48
  @path_factory.rotate_path!
48
49
 
49
50
  path = @path_factory.current_path
50
- @temp_file = LogStash::Outputs::Gcs::LogFileFactory.create(path, @gzip)
51
+ @temp_file = LogStash::Outputs::Gcs::LogFileFactory.create(path, @gzip, true, @gzip_encoded)
51
52
  end
52
53
  end
53
54
 
@@ -10,9 +10,10 @@ module LogStash
10
10
  # optionally gzipping it and creating mutexes around modification
11
11
  # points.
12
12
  class LogFileFactory
13
- def self.create(path, gzip, synchronize=true)
13
+ def self.create(path, gzip, synchronize=true, gzip_encoded=false)
14
14
  lf = LogStash::Outputs::Gcs::PlainLogFile.new(path)
15
15
  lf = LogStash::Outputs::Gcs::GzipLogFile.new(lf) if gzip
16
+ lf = LogStash::Outputs::Gcs::GzipLogFile.new(lf) if gzip_encoded
16
17
  lf = LogStash::Outputs::Gcs::SynchronizedLogFile.new(lf) if synchronize
17
18
 
18
19
  lf
@@ -63,6 +63,7 @@ require "zlib"
63
63
  # date_pattern => "%Y-%m-%dT%H:00" (optional)
64
64
  # flush_interval_secs => 2 (optional)
65
65
  # gzip => false (optional)
66
+ # gzip_content_encoding => false (optional)
66
67
  # uploader_interval_secs => 60 (optional)
67
68
  # upload_synchronous => false (optional)
68
69
  # }
@@ -114,9 +115,15 @@ class LogStash::Outputs::GoogleCloudStorage < LogStash::Outputs::Base
114
115
  # on every message.
115
116
  config :flush_interval_secs, :validate => :number, :default => 2
116
117
 
117
- # Gzip output stream when writing events to log files.
118
+ # Gzip output stream when writing events to log files, set
119
+ # `Content-Type` to `application/gzip` instead of `text/plain`, and
120
+ # use file suffix `.log.gz` instead of `.log`.
118
121
  config :gzip, :validate => :boolean, :default => false
119
122
 
123
+ # Gzip output stream when writing events to log files and set
124
+ # `Content-Encoding` to `gzip`.
125
+ config :gzip_content_encoding, :validate => :boolean, :default => false
126
+
120
127
  # Uploader interval when uploading new files to GCS. Adjust time based
121
128
  # on your time pattern (for example, for hourly files, this interval can be
122
129
  # around one hour).
@@ -155,6 +162,7 @@ class LogStash::Outputs::GoogleCloudStorage < LogStash::Outputs::Base
155
162
  start_uploader
156
163
 
157
164
  @content_type = @gzip ? 'application/gzip' : 'text/plain'
165
+ @content_encoding = @gzip_content_encoding ? 'gzip' : 'identity'
158
166
  end
159
167
 
160
168
  # Method called for each log event. It writes the event to the current output
@@ -175,7 +183,7 @@ class LogStash::Outputs::GoogleCloudStorage < LogStash::Outputs::Base
175
183
  public
176
184
  def close
177
185
  @logger.debug('Stopping the plugin, uploading the remaining files.')
178
- Stud.stop!(@registration_thread) unless @registration_thread.nil?
186
+ Thread.kill(@uploader_thread) unless @uploader_thread.nil?
179
187
 
180
188
  # Force rotate the log. If it contains data it will be submitted
181
189
  # to the work pool and will be uploaded before the plugin stops.
@@ -215,8 +223,7 @@ class LogStash::Outputs::GoogleCloudStorage < LogStash::Outputs::Base
215
223
 
216
224
  # start_uploader periodically sends flush events through the log rotater
217
225
  def start_uploader
218
- Thread.new do
219
- @registration_thread = Thread.current
226
+ @uploader_thread = Thread.new do
220
227
  Stud.interval(@uploader_interval_secs) do
221
228
  @log_rotater.writeln(nil)
222
229
  end
@@ -252,6 +259,7 @@ class LogStash::Outputs::GoogleCloudStorage < LogStash::Outputs::Base
252
259
  :parameters => {
253
260
  'uploadType' => 'multipart',
254
261
  'bucket' => @bucket,
262
+ 'contentEncoding' => @content_encoding,
255
263
  'name' => File.basename(filename)
256
264
  },
257
265
  :body_object => {contentType: @content_type},
@@ -283,7 +291,7 @@ class LogStash::Outputs::GoogleCloudStorage < LogStash::Outputs::Base
283
291
 
284
292
  def initialize_log_rotater
285
293
  max_file_size = @max_file_size_kbytes * 1024
286
- @log_rotater = LogStash::Outputs::Gcs::LogRotate.new(@path_factory, max_file_size, @gzip, @flush_interval_secs)
294
+ @log_rotater = LogStash::Outputs::Gcs::LogRotate.new(@path_factory, max_file_size, @gzip, @flush_interval_secs, @gzip_content_encoding)
287
295
 
288
296
  @log_rotater.on_rotate do |filename|
289
297
  @logger.info("Rotated out file: #{filename}")
@@ -292,4 +300,5 @@ class LogStash::Outputs::GoogleCloudStorage < LogStash::Outputs::Base
292
300
  end
293
301
  end
294
302
  end
303
+ attr_accessor :active
295
304
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-output-google_cloud_storage'
3
- s.version = '3.2.1'
3
+ s.version = '3.3.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"
@@ -68,7 +68,7 @@ shared_examples 'a log file' do
68
68
 
69
69
  describe '#time_since_sync' do
70
70
  it 'returns a delta' do
71
- expect(Time).to receive(:now).and_return(30, 40, 50)
71
+ expect(Time).to receive(:now).and_return(Time.at(30), Time.at(40), Time.at(50))
72
72
 
73
73
  subject.fsync
74
74
 
@@ -116,4 +116,40 @@ describe LogStash::Outputs::Gcs::SynchronizedLogFile do
116
116
  subject { LogStash::Outputs::Gcs::LogFileFactory.create(path, false, true) }
117
117
 
118
118
  it_behaves_like 'a log file'
119
+ end
120
+
121
+ describe 'gzip encoded file' do
122
+ let(:tempdir) { Stud::Temporary.directory }
123
+ let(:path) { ::File.join(tempdir, 'logfile.log') }
124
+ subject { LogStash::Outputs::Gcs::LogFileFactory.create(path, false, false, true) }
125
+
126
+ it_behaves_like 'a log file'
127
+
128
+ it 'creates a valid gzip' do
129
+ subject.write('Hello, world!')
130
+ subject.close!
131
+
132
+ Zlib::GzipReader.open(path) do |gz|
133
+ expect(gz.read).to eq('Hello, world!')
134
+ end
135
+ end
136
+ end
137
+
138
+ describe 'double gzip encoded file' do
139
+ let(:tempdir) { Stud::Temporary.directory }
140
+ let(:path) { ::File.join(tempdir, 'logfile.log') }
141
+ subject { LogStash::Outputs::Gcs::LogFileFactory.create(path, true, false, true) }
142
+
143
+ it_behaves_like 'a log file'
144
+
145
+ it 'creates a valid double gzip' do
146
+ subject.write('Hello, world!')
147
+ subject.close!
148
+
149
+ Zlib::GzipReader.open(path) do |outer|
150
+ Zlib::GzipReader.new(outer) do |inner|
151
+ expect(inner.read).to eq('Hello, world!')
152
+ end
153
+ end
154
+ end
119
155
  end
@@ -8,6 +8,7 @@ describe LogStash::Outputs::Gcs::WorkerPool do
8
8
  expect(pool.workers).to_not receive(:post)
9
9
 
10
10
  pool.post { 1 + 2 }
11
+ pool.stop!
11
12
  end
12
13
 
13
14
  it 'runs the task in a different thread if asynchronous' do
@@ -15,6 +16,7 @@ describe LogStash::Outputs::Gcs::WorkerPool do
15
16
  expect(pool.workers).to receive(:post)
16
17
 
17
18
  pool.post { 1 + 2 }
19
+ pool.stop!
18
20
  end
19
21
 
20
22
  it 'raises an error if the pool is already stopped' do
@@ -23,5 +23,7 @@ describe LogStash::Outputs::GoogleCloudStorage do
23
23
 
24
24
  it "should register without errors" do
25
25
  expect { subject.register }.to_not raise_error
26
+
27
+ subject.close
26
28
  end
27
29
  end
metadata CHANGED
@@ -1,16 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-output-google_cloud_storage
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.1
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-05 00:00:00.000000000 Z
11
+ date: 2018-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
+ name: logstash-core-plugin-api
14
15
  requirement: !ruby/object:Gem::Requirement
15
16
  requirements:
16
17
  - - ">="
@@ -19,9 +20,8 @@ dependencies:
19
20
  - - "<="
20
21
  - !ruby/object:Gem::Version
21
22
  version: '2.99'
22
- name: logstash-core-plugin-api
23
- prerelease: false
24
23
  type: :runtime
24
+ prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
@@ -31,84 +31,84 @@ dependencies:
31
31
  - !ruby/object:Gem::Version
32
32
  version: '2.99'
33
33
  - !ruby/object:Gem::Dependency
34
+ name: stud
34
35
  requirement: !ruby/object:Gem::Requirement
35
36
  requirements:
36
37
  - - ">="
37
38
  - !ruby/object:Gem::Version
38
39
  version: '0'
39
- name: stud
40
- prerelease: false
41
40
  type: :runtime
41
+ prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
46
  version: '0'
47
47
  - !ruby/object:Gem::Dependency
48
+ name: google-api-client
48
49
  requirement: !ruby/object:Gem::Requirement
49
50
  requirements:
50
51
  - - "~>"
51
52
  - !ruby/object:Gem::Version
52
53
  version: 0.8.7
53
- name: google-api-client
54
- prerelease: false
55
54
  type: :runtime
55
+ prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
60
  version: 0.8.7
61
61
  - !ruby/object:Gem::Dependency
62
+ name: logstash-codec-plain
62
63
  requirement: !ruby/object:Gem::Requirement
63
64
  requirements:
64
65
  - - ">="
65
66
  - !ruby/object:Gem::Version
66
67
  version: '0'
67
- name: logstash-codec-plain
68
- prerelease: false
69
68
  type: :runtime
69
+ prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - ">="
73
73
  - !ruby/object:Gem::Version
74
74
  version: '0'
75
75
  - !ruby/object:Gem::Dependency
76
+ name: mime-types
76
77
  requirement: !ruby/object:Gem::Requirement
77
78
  requirements:
78
79
  - - "~>"
79
80
  - !ruby/object:Gem::Version
80
81
  version: '2'
81
- name: mime-types
82
- prerelease: false
83
82
  type: :runtime
83
+ prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
88
  version: '2'
89
89
  - !ruby/object:Gem::Dependency
90
+ name: concurrent-ruby
90
91
  requirement: !ruby/object:Gem::Requirement
91
92
  requirements:
92
93
  - - '='
93
94
  - !ruby/object:Gem::Version
94
95
  version: 1.0.5
95
- name: concurrent-ruby
96
- prerelease: false
97
96
  type: :runtime
97
+ prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - '='
101
101
  - !ruby/object:Gem::Version
102
102
  version: 1.0.5
103
103
  - !ruby/object:Gem::Dependency
104
+ name: logstash-devutils
104
105
  requirement: !ruby/object:Gem::Requirement
105
106
  requirements:
106
107
  - - ">="
107
108
  - !ruby/object:Gem::Version
108
109
  version: '0'
109
- name: logstash-devutils
110
- prerelease: false
111
110
  type: :development
111
+ prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - ">="
@@ -147,7 +147,7 @@ licenses:
147
147
  metadata:
148
148
  logstash_plugin: 'true'
149
149
  logstash_group: output
150
- post_install_message:
150
+ post_install_message:
151
151
  rdoc_options: []
152
152
  require_paths:
153
153
  - lib
@@ -162,9 +162,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
162
162
  - !ruby/object:Gem::Version
163
163
  version: '0'
164
164
  requirements: []
165
- rubyforge_project:
166
- rubygems_version: 2.6.13
167
- signing_key:
165
+ rubyforge_project:
166
+ rubygems_version: 2.6.14
167
+ signing_key:
168
168
  specification_version: 4
169
169
  summary: plugin to upload log events to Google Cloud Storage (GCS)
170
170
  test_files: