logstash-output-scalyr 0.1.3 → 0.1.4

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: f07d1addbee89789c0819a0566262a22754990d87a70f479b33534f1d793410d
4
- data.tar.gz: 72a1ebd3076e811232cfca2851b923e5fa0a2ef444cf3710d3268de41935532b
3
+ metadata.gz: f02a9ffc8738ad5eef45acc94337eaa36f3e567883429b761691318f40de5eda
4
+ data.tar.gz: 124d1ced3db2cbf8ad6a38b196f1697f75b2852bc9b55585c19dc6a87a72469a
5
5
  SHA512:
6
- metadata.gz: b1e01a579378b28d69c184e6513d9c33f86963a4ce4bc6078cbbd78c9a380367605e369013417792041eb7b40efa3380c4e2b39b6b3b2bb2ec6761421329b92b
7
- data.tar.gz: b5554805e01d55a70b20bfc51c70b1e1bf96164d24c43fe5e56dd1444c3891434a5202aa181341d318787605aacc92a6f21c2ff0601872636ff621de929dc292
6
+ metadata.gz: aa3669f7d0fe767ae50b7e4ac82448d2cd08ca850276b66b2b9d9dd4d0a06f17d32e45b07a1b4980dc41211b314e307c447d9b26bf8adb10e5db5c7c65677e13
7
+ data.tar.gz: 62d214449bba6046617016291a2da8be3df21a6505f891ec0afc2d647b777e80fb64db01b0882565e591e4aa7de6fd2ad3d5eab921669c801521a1f85235c4db
data/README.md CHANGED
@@ -10,7 +10,7 @@ You can view documentation for this plugin [on the Scalyr website](https://app.s
10
10
  # Quick start
11
11
 
12
12
  1. Build the gem, run `gem build logstash-output-scalyr.gemspec`
13
- 2. Install the gem into a Logstash installation, run `/usr/share/logstash/bin/logstash-plugin install logstash-output-scalyr-0.1.3.gem` or follow the latest official instructions on working with plugins from Logstash.
13
+ 2. Install the gem into a Logstash installation, run `/usr/share/logstash/bin/logstash-plugin install logstash-output-scalyr-0.1.4.gem` or follow the latest official instructions on working with plugins from Logstash.
14
14
  3. Configure the output plugin (e.g. add it to a pipeline .conf)
15
15
  4. Restart Logstash
16
16
 
@@ -56,7 +56,7 @@ In the above example, the Logstash pipeline defines a file input that reads from
56
56
 
57
57
  - Path to SSL bundle file.
58
58
 
59
- `config :ssl_ca_bundle_path, :validate => :string, :default => "/etc/ssl/certs/ca-bundle.crt"`
59
+ `config :ssl_ca_bundle_path, :validate => :string, :default => nil`
60
60
 
61
61
  ---
62
62
 
@@ -37,7 +37,10 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
37
37
  config :scalyr_server, :validate => :string, :default => "https://agent.scalyr.com/"
38
38
 
39
39
  # Path to SSL bundle file.
40
- config :ssl_ca_bundle_path, :validate => :string, :default => "/etc/ssl/certs/ca-bundle.crt"
40
+ config :ssl_ca_bundle_path, :validate => :string, :default => "/etc/ssl/certs/ca-bundle.crt"
41
+
42
+ # If we should append our built-in Scalyr cert to the one we find at `ssl_ca_bundle_path`.
43
+ config :append_builtin_cert, :validate => :boolean, :default => true
41
44
 
42
45
  # server_attributes is a dictionary of key value pairs that represents/identifies the logstash aggregator server
43
46
  # (where this plugin is running). Keys are arbitrary except for the 'serverHost' key which holds special meaning to
@@ -177,7 +180,8 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
177
180
  @client_session = Scalyr::Common::Client::ClientSession.new(
178
181
  @logger, @add_events_uri,
179
182
  @compression_type, @compression_level,
180
- @ssl_verify_peer, @ssl_ca_bundle_path, @ssl_verify_depth
183
+ @ssl_verify_peer, @ssl_ca_bundle_path, @ssl_verify_depth,
184
+ @append_builtin_cert
181
185
  )
182
186
 
183
187
  @logger.info("Started Scalyr output plugin", :class => self.class.name)
@@ -212,9 +216,13 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
212
216
  while !multi_event_request_array.to_a.empty?
213
217
  begin
214
218
  multi_event_request = multi_event_request_array.pop
215
- @client_session.post_add_events(multi_event_request[:body])
216
- sleep_interval = 0
217
- result.push(multi_event_request)
219
+ # For some reason a retry on the multi_receive may result in the request array containing `nil` elements, we
220
+ # ignore these.
221
+ if !multi_event_request.nil?
222
+ @client_session.post_add_events(multi_event_request[:body])
223
+ sleep_interval = 0
224
+ result.push(multi_event_request)
225
+ end
218
226
 
219
227
  rescue OpenSSL::SSL::SSLError => e
220
228
  # cannot rely on exception message, so we always log the following warning
@@ -229,7 +237,7 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
229
237
  sleep_interval = sleep_for(sleep_interval)
230
238
  message = "Error uploading to Scalyr (will backoff-retry)"
231
239
  exc_data = {
232
- :url => e.url.sanitized.to_s,
240
+ :url => e.url.to_s,
233
241
  :message => e.message,
234
242
  :batch_num => batch_num,
235
243
  :total_batches => total_batches,
@@ -247,7 +255,7 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
247
255
  # all other failed uploads should be errors
248
256
  @logger.error(message, exc_data)
249
257
  end
250
- retry if @running.true?
258
+ retry if @running
251
259
 
252
260
  rescue => e
253
261
  # Any unexpected errors should be fully logged
@@ -259,7 +267,7 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
259
267
  )
260
268
  @logger.debug("Failed multi_event_request", :multi_event_request => multi_event_request)
261
269
  sleep_interval = sleep_for(sleep_interval)
262
- retry if @running.true?
270
+ retry if @running
263
271
  end
264
272
  end
265
273
 
@@ -583,15 +591,13 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
583
591
  @last_status_transmit_time = Float::INFINITY
584
592
  return saved_last_time
585
593
  end
586
- ensure
587
-
588
594
  end
589
595
  end
590
596
 
591
597
 
592
598
  # Helper method that performs synchronous sleep for a certain time interval
593
599
  def sleep_for(sleep_interval)
594
- Stud.stoppable_sleep(sleep_interval) { @running.false? }
600
+ Stud.stoppable_sleep(sleep_interval) { !@running }
595
601
  get_sleep_sec(sleep_interval)
596
602
  end
597
603
 
@@ -52,15 +52,58 @@ end
52
52
  class ClientSession
53
53
 
54
54
  def initialize(logger, add_events_uri, compression_type, compression_level,
55
- ssl_verify_peer, ssl_ca_bundle_path, ssl_verify_depth)
55
+ ssl_verify_peer, ssl_ca_bundle_path, ssl_verify_depth, append_builtin_cert)
56
56
  @logger = logger
57
57
  @add_events_uri = add_events_uri # typically /addEvents
58
58
  @compression_type = compression_type
59
59
  @compression_level = compression_level
60
60
  @ssl_verify_peer = ssl_verify_peer
61
61
  @ssl_ca_bundle_path = ssl_ca_bundle_path
62
+ @append_builtin_cert = append_builtin_cert
62
63
  @ssl_verify_depth = ssl_verify_depth
63
64
 
65
+ # A cert to use by default to avoid issues caused by the OpenSSL library not validating certs according to standard
66
+ @cert_string = "" \
67
+ "-----BEGIN CERTIFICATE-----\n" \
68
+ "MIIG6zCCBNOgAwIBAgIJAM5aknNWtN6oMA0GCSqGSIb3DQEBCwUAMIGpMQswCQYD\n" \
69
+ "VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEXMBUGA1UEBxMOUG9ydG9sYSBW\n" \
70
+ "YWxsZXkxEzARBgNVBAoTClNjYWx5ciBJbmMxFTATBgNVBAsTDFNjYWx5ciBBZ2Vu\n" \
71
+ "dDEdMBsGA1UEAxMUU2NhbHlyIEFnZW50IENBIFJvb3QxITAfBgkqhkiG9w0BCQEW\n" \
72
+ "EmNvbnRhY3RAc2NhbHlyLmNvbTAeFw0xNDA5MDkyMTUyMDVaFw0yNDA5MDYyMTUy\n" \
73
+ "MDVaMIGpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEXMBUGA1UE\n" \
74
+ "BxMOUG9ydG9sYSBWYWxsZXkxEzARBgNVBAoTClNjYWx5ciBJbmMxFTATBgNVBAsT\n" \
75
+ "DFNjYWx5ciBBZ2VudDEdMBsGA1UEAxMUU2NhbHlyIEFnZW50IENBIFJvb3QxITAf\n" \
76
+ "BgkqhkiG9w0BCQEWEmNvbnRhY3RAc2NhbHlyLmNvbTCCAiIwDQYJKoZIhvcNAQEB\n" \
77
+ "BQADggIPADCCAgoCggIBALdNamcMNVxkIB6qVWmNCi1jeyeqOX00rYAWDlyBHff7\n" \
78
+ "vU833Evuixgrf0HxrOQNiPsOK66ehG6LfJd2UIBDEHBCXRo+aeFQLrCLIVXiqJ2W\n" \
79
+ "Tvl7dUU9d7zfw/XXif3lMQTiyQAWYTyjfugDczEScEUk93EWFfW47j9PTGh96yKm\n" \
80
+ "nVbfOxD4XbN0ykdo85cs7M/NOHQj4q34l77XGXrit+nb1cL3wS9ZzJG8s40J2+Dp\n" \
81
+ "LUA8KBQuvim6hfqrjaDX0bXVvc52a7TSh/zb58gkLbiqvBuPo5P8PBLHCx8bJtZu\n" \
82
+ "fjWRdjaftgw7CcsdIuMhbm3823WI/A+/p4s1B5KOPqOYRkgG8FBqFIRTecKAV5wC\n" \
83
+ "Z2ruTytoOUBWItrheyJhm+99X1I2y/6mdecBdk7j3+8U+nCsGHkH5Jwjl2BH9tfT\n" \
84
+ "RUhVTCQs25XLNm41kZo7xK464xZsJKHXj9jr5gLIdF6CgzU2uYsQHKcw1pAVITLe\n" \
85
+ "bfGEob8AcL0E7+1hurRjyYxtxZpsZeGMwI0/BStT+fLEAOJ1byGUgSUbhi9lJ8Hc\n" \
86
+ "+NZDfaCaCZKRxjePCqeWjZUUdVoH3fNSi2GuNLqtOFzxlkP5tBErnXufE6XZAtEQ\n" \
87
+ "lv/9qxa4ZLsvhbt+6qQryIAHL4aReh/VReER438ARdwG2QDK+vRfhNpke69em5Kb\n" \
88
+ "AgMBAAGjggESMIIBDjAdBgNVHQ4EFgQUENX6MjnzqTJdTQMAEakSdXV/I80wgd4G\n" \
89
+ "A1UdIwSB1jCB04AUENX6MjnzqTJdTQMAEakSdXV/I82hga+kgawwgakxCzAJBgNV\n" \
90
+ "BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRcwFQYDVQQHEw5Qb3J0b2xhIFZh\n" \
91
+ "bGxleTETMBEGA1UEChMKU2NhbHlyIEluYzEVMBMGA1UECxMMU2NhbHlyIEFnZW50\n" \
92
+ "MR0wGwYDVQQDExRTY2FseXIgQWdlbnQgQ0EgUm9vdDEhMB8GCSqGSIb3DQEJARYS\n" \
93
+ "Y29udGFjdEBzY2FseXIuY29tggkAzlqSc1a03qgwDAYDVR0TBAUwAwEB/zANBgkq\n" \
94
+ "hkiG9w0BAQsFAAOCAgEAmmgm1AeO7wfuR36HHgpZCKZxboRFwc2FzKaHNSg2FQ0G\n" \
95
+ "MuOP6HZUQWsaXLe0Kc8emJKrIwrn6x2jMm19Bjbps2bPW6ao6UE/6fb5Z7CX82IX\n" \
96
+ "pKlDDH6OfYjDplBzoqf5PkPgxZNyiZ7nyNUWz+P2vesLFVynmej2MvLIZVnEJ2Wp\n" \
97
+ "xzyHMKQo92DP8yNEudoK8QQpoLcuNcAli9blt8+NIV9RSDrI9CvArLNpZJMlS1Vx\n" \
98
+ "gdzEU3wEQYWc36j3XCsp7ZDvgTm6FpyHS5ccMpXR1E62tVINGX9r+97ZHyxjqurb\n" \
99
+ "606y1FzV/5Mf/aihPYSSreq63UVqdsaQfyS77Q4tpJofq875w8nd2Vs3guDs2T0h\n" \
100
+ "1bOlV3e2HfglWsHKwNguQZo2nfMUp11IYfV/HOKWNQkbrPhuayXMi3i2wCZe9JNt\n" \
101
+ "P9uZ2OjzsVu2QFcSlvZF6y02/bjbNATRfj/J/SHNFyCDu6bXhtAu0yZzFLiOZxjD\n" \
102
+ "LwzunBMoWcJj+P2Vx3OhbE9FMyMeKdOWdTgiI1GLEkfJi6s7d/tk1ayLmbBTRD/e\n" \
103
+ "XkjSeLBss6mA1INuE1+gKVA4MABsUiLqGZ8xCPN16CyPcTqL2TJFo1IOqivMxKDh\n" \
104
+ "H4Z/mHoGi5SRnye+Wo+jyiQiWjJQ5LrlQPbHmuO0tLs9lM1t9nhzLifzga5F4+o=\n" \
105
+ "-----END CERTIFICATE-----"
106
+
64
107
  # Request statistics are accumulated across multiple threads and must be accessed through a mutex
65
108
  @stats_lock = Mutex.new
66
109
  @stats = {
@@ -79,7 +122,18 @@ class ClientSession
79
122
 
80
123
  # verify peers to prevent potential MITM attacks
81
124
  if @ssl_verify_peer
82
- @http.ca_file = @ssl_ca_bundle_path
125
+ @ca_cert = Tempfile.new("ca_cert")
126
+ if File.file?(@ssl_ca_bundle_path)
127
+ @ca_cert.write(File.read(@ssl_ca_bundle_path))
128
+ @ca_cert.flush
129
+ end
130
+ if @append_builtin_cert
131
+ open(@ca_cert.path, 'a') do |f|
132
+ f.puts @cert_string
133
+ end
134
+ end
135
+ @ca_cert.flush
136
+ @http.ca_file = @ca_cert.path
83
137
  @http.verify_mode = OpenSSL::SSL::VERIFY_PEER
84
138
  @http.verify_depth = @ssl_verify_depth
85
139
  else
@@ -105,7 +159,6 @@ class ClientSession
105
159
  compressed_bytes_sent = 0
106
160
  bytes_received = 0
107
161
  begin
108
-
109
162
  response = @http.request(@add_events_uri, post)
110
163
  handle_response(response)
111
164
 
@@ -115,6 +168,17 @@ class ClientSession
115
168
  bytes_received = response.body.bytesize # echee: double check
116
169
  # echee TODO add more statistics
117
170
 
171
+ rescue OpenSSL::SSL::SSLError => e
172
+ if @ssl_verify_peer and @ssl_ca_bundle_path.nil? and !File.file?(@ca_cert.path)
173
+ @ca_cert = Tempfile.new("ca_cert")
174
+ @ca_cert.write(@cert_string)
175
+ @ca_cert.flush
176
+ @http.ca_file = @ca_cert.path
177
+ raise ClientError.new("Packaged certificate appears to have been deleted, writing a new one.", @add_events_uri)
178
+ else
179
+ raise e
180
+ end
181
+
118
182
  rescue Net::HTTP::Persistent::Error => e
119
183
  # The underlying persistent-connection library automatically retries when there are network-related errors.
120
184
  # Eventually, it will give up and raise this generic error, at which time, we convert it to a ClientError
@@ -163,7 +227,7 @@ class ClientSession
163
227
 
164
228
  post = Net::HTTP::Post.new uri_path
165
229
  post.add_field('Content-Type', 'application/json')
166
- version = 'output-logstash-scalyr 0.1.3'
230
+ version = 'output-logstash-scalyr 0.1.4'
167
231
  post.add_field('User-Agent', version + ';' + RUBY_VERSION + ';' + RUBY_PLATFORM)
168
232
 
169
233
  if not encoding.nil?
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-output-scalyr'
3
- s.version = '0.1.3'
3
+ s.version = '0.1.4'
4
4
  s.licenses = ['Apache-2.0']
5
5
  s.summary = "Scalyr output plugin for Logstash"
6
6
  s.description = "Sends log data collected by Logstash to Scalyr (https://www.scalyr.com)"
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "rake"
6
+ gem "test-unit"
@@ -0,0 +1,23 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ tempfile (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ power_assert (1.1.5)
10
+ rake (13.0.1)
11
+ test-unit (3.3.5)
12
+ power_assert
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ rake
19
+ tempfile!
20
+ test-unit
21
+
22
+ BUNDLED WITH
23
+ 2.1.4
@@ -0,0 +1,51 @@
1
+ # Tempfile
2
+
3
+ A utility class for managing temporary files. When you create a Tempfile
4
+ object, it will create a temporary file with a unique filename. A Tempfile
5
+ objects behaves just like a File object, and you can perform all the usual
6
+ file operations on it: reading data, writing data, changing its permissions,
7
+ etc. So although this class does not explicitly document all instance methods
8
+ supported by File, you can in fact call any File instance method on a
9
+ Tempfile object.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'tempfile'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle install
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install tempfile
26
+
27
+ ## Usage
28
+
29
+ ```ruby
30
+ require 'tempfile'
31
+
32
+ file = Tempfile.new('foo')
33
+ file.path # => A unique filename in the OS's temp directory,
34
+ # e.g.: "/tmp/foo.24722.0"
35
+ # This filename contains 'foo' in its basename.
36
+ file.write("hello world")
37
+ file.rewind
38
+ file.read # => "hello world"
39
+ file.close
40
+ file.unlink # deletes the temp file
41
+ ```
42
+
43
+ ## Development
44
+
45
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
46
+
47
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
48
+
49
+ ## Contributing
50
+
51
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/tempfile.
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test/lib"
6
+ t.ruby_opts << "-rhelper"
7
+ t.test_files = FileList["test/**/test_*.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "tempfile"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,350 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # tempfile - manipulates temporary files
4
+ #
5
+ # $Id$
6
+ #
7
+
8
+ require 'delegate'
9
+ require 'tmpdir'
10
+
11
+ # A utility class for managing temporary files. When you create a Tempfile
12
+ # object, it will create a temporary file with a unique filename. A Tempfile
13
+ # objects behaves just like a File object, and you can perform all the usual
14
+ # file operations on it: reading data, writing data, changing its permissions,
15
+ # etc. So although this class does not explicitly document all instance methods
16
+ # supported by File, you can in fact call any File instance method on a
17
+ # Tempfile object.
18
+ #
19
+ # == Synopsis
20
+ #
21
+ # require 'tempfile'
22
+ #
23
+ # file = Tempfile.new('foo')
24
+ # file.path # => A unique filename in the OS's temp directory,
25
+ # # e.g.: "/tmp/foo.24722.0"
26
+ # # This filename contains 'foo' in its basename.
27
+ # file.write("hello world")
28
+ # file.rewind
29
+ # file.read # => "hello world"
30
+ # file.close
31
+ # file.unlink # deletes the temp file
32
+ #
33
+ # == Good practices
34
+ #
35
+ # === Explicit close
36
+ #
37
+ # When a Tempfile object is garbage collected, or when the Ruby interpreter
38
+ # exits, its associated temporary file is automatically deleted. This means
39
+ # that's it's unnecessary to explicitly delete a Tempfile after use, though
40
+ # it's good practice to do so: not explicitly deleting unused Tempfiles can
41
+ # potentially leave behind large amounts of tempfiles on the filesystem
42
+ # until they're garbage collected. The existence of these temp files can make
43
+ # it harder to determine a new Tempfile filename.
44
+ #
45
+ # Therefore, one should always call #unlink or close in an ensure block, like
46
+ # this:
47
+ #
48
+ # file = Tempfile.new('foo')
49
+ # begin
50
+ # # ...do something with file...
51
+ # ensure
52
+ # file.close
53
+ # file.unlink # deletes the temp file
54
+ # end
55
+ #
56
+ # === Unlink after creation
57
+ #
58
+ # On POSIX systems, it's possible to unlink a file right after creating it,
59
+ # and before closing it. This removes the filesystem entry without closing
60
+ # the file handle, so it ensures that only the processes that already had
61
+ # the file handle open can access the file's contents. It's strongly
62
+ # recommended that you do this if you do not want any other processes to
63
+ # be able to read from or write to the Tempfile, and you do not need to
64
+ # know the Tempfile's filename either.
65
+ #
66
+ # For example, a practical use case for unlink-after-creation would be this:
67
+ # you need a large byte buffer that's too large to comfortably fit in RAM,
68
+ # e.g. when you're writing a web server and you want to buffer the client's
69
+ # file upload data.
70
+ #
71
+ # Please refer to #unlink for more information and a code example.
72
+ #
73
+ # == Minor notes
74
+ #
75
+ # Tempfile's filename picking method is both thread-safe and inter-process-safe:
76
+ # it guarantees that no other threads or processes will pick the same filename.
77
+ #
78
+ # Tempfile itself however may not be entirely thread-safe. If you access the
79
+ # same Tempfile object from multiple threads then you should protect it with a
80
+ # mutex.
81
+ class Tempfile < DelegateClass(File)
82
+ # Creates a temporary file with permissions 0600 (= only readable and
83
+ # writable by the owner) and opens it with mode "w+".
84
+ #
85
+ # The +basename+ parameter is used to determine the name of the
86
+ # temporary file. You can either pass a String or an Array with
87
+ # 2 String elements. In the former form, the temporary file's base
88
+ # name will begin with the given string. In the latter form,
89
+ # the temporary file's base name will begin with the array's first
90
+ # element, and end with the second element. For example:
91
+ #
92
+ # file = Tempfile.new('hello')
93
+ # file.path # => something like: "/tmp/hello2843-8392-92849382--0"
94
+ #
95
+ # # Use the Array form to enforce an extension in the filename:
96
+ # file = Tempfile.new(['hello', '.jpg'])
97
+ # file.path # => something like: "/tmp/hello2843-8392-92849382--0.jpg"
98
+ #
99
+ # The temporary file will be placed in the directory as specified
100
+ # by the +tmpdir+ parameter. By default, this is +Dir.tmpdir+.
101
+ #
102
+ # file = Tempfile.new('hello', '/home/aisaka')
103
+ # file.path # => something like: "/home/aisaka/hello2843-8392-92849382--0"
104
+ #
105
+ # You can also pass an options hash. Under the hood, Tempfile creates
106
+ # the temporary file using +File.open+. These options will be passed to
107
+ # +File.open+. This is mostly useful for specifying encoding
108
+ # options, e.g.:
109
+ #
110
+ # Tempfile.new('hello', '/home/aisaka', encoding: 'ascii-8bit')
111
+ #
112
+ # # You can also omit the 'tmpdir' parameter:
113
+ # Tempfile.new('hello', encoding: 'ascii-8bit')
114
+ #
115
+ # Note: +mode+ keyword argument, as accepted by Tempfile, can only be
116
+ # numeric, combination of the modes defined in File::Constants.
117
+ #
118
+ # === Exceptions
119
+ #
120
+ # If Tempfile.new cannot find a unique filename within a limited
121
+ # number of tries, then it will raise an exception.
122
+ def initialize(basename="", tmpdir=nil, mode: 0, **options)
123
+ warn "Tempfile.new doesn't call the given block.", uplevel: 1 if block_given?
124
+
125
+ @unlinked = false
126
+ @mode = mode|File::RDWR|File::CREAT|File::EXCL
127
+ ::Dir::Tmpname.create(basename, tmpdir, **options) do |tmpname, n, opts|
128
+ opts[:perm] = 0600
129
+ @tmpfile = File.open(tmpname, @mode, **opts)
130
+ @opts = opts.freeze
131
+ end
132
+ ObjectSpace.define_finalizer(self, Remover.new(@tmpfile))
133
+
134
+ super(@tmpfile)
135
+ end
136
+
137
+ # Opens or reopens the file with mode "r+".
138
+ def open
139
+ _close
140
+ mode = @mode & ~(File::CREAT|File::EXCL)
141
+ @tmpfile = File.open(@tmpfile.path, mode, **@opts)
142
+ __setobj__(@tmpfile)
143
+ end
144
+
145
+ def _close # :nodoc:
146
+ @tmpfile.close
147
+ end
148
+ protected :_close
149
+
150
+ # Closes the file. If +unlink_now+ is true, then the file will be unlinked
151
+ # (deleted) after closing. Of course, you can choose to later call #unlink
152
+ # if you do not unlink it now.
153
+ #
154
+ # If you don't explicitly unlink the temporary file, the removal
155
+ # will be delayed until the object is finalized.
156
+ def close(unlink_now=false)
157
+ _close
158
+ unlink if unlink_now
159
+ end
160
+
161
+ # Closes and unlinks (deletes) the file. Has the same effect as called
162
+ # <tt>close(true)</tt>.
163
+ def close!
164
+ close(true)
165
+ end
166
+
167
+ # Unlinks (deletes) the file from the filesystem. One should always unlink
168
+ # the file after using it, as is explained in the "Explicit close" good
169
+ # practice section in the Tempfile overview:
170
+ #
171
+ # file = Tempfile.new('foo')
172
+ # begin
173
+ # # ...do something with file...
174
+ # ensure
175
+ # file.close
176
+ # file.unlink # deletes the temp file
177
+ # end
178
+ #
179
+ # === Unlink-before-close
180
+ #
181
+ # On POSIX systems it's possible to unlink a file before closing it. This
182
+ # practice is explained in detail in the Tempfile overview (section
183
+ # "Unlink after creation"); please refer there for more information.
184
+ #
185
+ # However, unlink-before-close may not be supported on non-POSIX operating
186
+ # systems. Microsoft Windows is the most notable case: unlinking a non-closed
187
+ # file will result in an error, which this method will silently ignore. If
188
+ # you want to practice unlink-before-close whenever possible, then you should
189
+ # write code like this:
190
+ #
191
+ # file = Tempfile.new('foo')
192
+ # file.unlink # On Windows this silently fails.
193
+ # begin
194
+ # # ... do something with file ...
195
+ # ensure
196
+ # file.close! # Closes the file handle. If the file wasn't unlinked
197
+ # # because #unlink failed, then this method will attempt
198
+ # # to do so again.
199
+ # end
200
+ def unlink
201
+ return if @unlinked
202
+ begin
203
+ File.unlink(@tmpfile.path)
204
+ rescue Errno::ENOENT
205
+ rescue Errno::EACCES
206
+ # may not be able to unlink on Windows; just ignore
207
+ return
208
+ end
209
+ ObjectSpace.undefine_finalizer(self)
210
+ @unlinked = true
211
+ end
212
+ alias delete unlink
213
+
214
+ # Returns the full path name of the temporary file.
215
+ # This will be nil if #unlink has been called.
216
+ def path
217
+ @unlinked ? nil : @tmpfile.path
218
+ end
219
+
220
+ # Returns the size of the temporary file. As a side effect, the IO
221
+ # buffer is flushed before determining the size.
222
+ def size
223
+ if !@tmpfile.closed?
224
+ @tmpfile.size # File#size calls rb_io_flush_raw()
225
+ else
226
+ File.size(@tmpfile.path)
227
+ end
228
+ end
229
+ alias length size
230
+
231
+ # :stopdoc:
232
+ def inspect
233
+ if @tmpfile.closed?
234
+ "#<#{self.class}:#{path} (closed)>"
235
+ else
236
+ "#<#{self.class}:#{path}>"
237
+ end
238
+ end
239
+
240
+ class Remover # :nodoc:
241
+ def initialize(tmpfile)
242
+ @pid = Process.pid
243
+ @tmpfile = tmpfile
244
+ end
245
+
246
+ def call(*args)
247
+ return if @pid != Process.pid
248
+
249
+ $stderr.puts "removing #{@tmpfile.path}..." if $DEBUG
250
+
251
+ @tmpfile.close
252
+ begin
253
+ File.unlink(@tmpfile.path)
254
+ rescue Errno::ENOENT
255
+ end
256
+
257
+ $stderr.puts "done" if $DEBUG
258
+ end
259
+ end
260
+
261
+ class << self
262
+ # :startdoc:
263
+
264
+ # Creates a new Tempfile.
265
+ #
266
+ # If no block is given, this is a synonym for Tempfile.new.
267
+ #
268
+ # If a block is given, then a Tempfile object will be constructed,
269
+ # and the block is run with said object as argument. The Tempfile
270
+ # object will be automatically closed after the block terminates.
271
+ # The call returns the value of the block.
272
+ #
273
+ # In any case, all arguments (<code>*args</code>) will be passed to Tempfile.new.
274
+ #
275
+ # Tempfile.open('foo', '/home/temp') do |f|
276
+ # # ... do something with f ...
277
+ # end
278
+ #
279
+ # # Equivalent:
280
+ # f = Tempfile.open('foo', '/home/temp')
281
+ # begin
282
+ # # ... do something with f ...
283
+ # ensure
284
+ # f.close
285
+ # end
286
+ def open(*args, **kw)
287
+ tempfile = new(*args, **kw)
288
+
289
+ if block_given?
290
+ begin
291
+ yield(tempfile)
292
+ ensure
293
+ tempfile.close
294
+ end
295
+ else
296
+ tempfile
297
+ end
298
+ end
299
+ end
300
+ end
301
+
302
+ # Creates a temporary file as usual File object (not Tempfile).
303
+ # It doesn't use finalizer and delegation.
304
+ #
305
+ # If no block is given, this is similar to Tempfile.new except
306
+ # creating File instead of Tempfile.
307
+ # The created file is not removed automatically.
308
+ # You should use File.unlink to remove it.
309
+ #
310
+ # If a block is given, then a File object will be constructed,
311
+ # and the block is invoked with the object as the argument.
312
+ # The File object will be automatically closed and
313
+ # the temporary file is removed after the block terminates.
314
+ # The call returns the value of the block.
315
+ #
316
+ # In any case, all arguments (+basename+, +tmpdir+, +mode+, and
317
+ # <code>**options</code>) will be treated as Tempfile.new.
318
+ #
319
+ # Tempfile.create('foo', '/home/temp') do |f|
320
+ # # ... do something with f ...
321
+ # end
322
+ #
323
+ def Tempfile.create(basename="", tmpdir=nil, mode: 0, **options)
324
+ tmpfile = nil
325
+ Dir::Tmpname.create(basename, tmpdir, **options) do |tmpname, n, opts|
326
+ mode |= File::RDWR|File::CREAT|File::EXCL
327
+ opts[:perm] = 0600
328
+ tmpfile = File.open(tmpname, mode, **opts)
329
+ end
330
+ if block_given?
331
+ begin
332
+ yield tmpfile
333
+ ensure
334
+ unless tmpfile.closed?
335
+ if File.identical?(tmpfile, tmpfile.path)
336
+ unlinked = File.unlink tmpfile.path rescue nil
337
+ end
338
+ tmpfile.close
339
+ end
340
+ unless unlinked
341
+ begin
342
+ File.unlink tmpfile.path
343
+ rescue Errno::ENOENT
344
+ end
345
+ end
346
+ end
347
+ else
348
+ tmpfile
349
+ end
350
+ end
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = "tempfile"
3
+ spec.version = "0.1.0"
4
+ spec.authors = ["Yukihiro Matsumoto"]
5
+ spec.email = ["matz@ruby-lang.org"]
6
+
7
+ spec.summary = %q{A utility class for managing temporary files.}
8
+ spec.description = %q{A utility class for managing temporary files.}
9
+ spec.homepage = "https://github.com/ruby/tempfile"
10
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
11
+
12
+ spec.metadata["homepage_uri"] = spec.homepage
13
+ spec.metadata["source_code_uri"] = spec.homepage
14
+
15
+ # Specify which files should be added to the gem when it is released.
16
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
17
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # stub: tempfile 0.1.0 ruby lib
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "tempfile".freeze
6
+ s.version = "0.1.0"
7
+
8
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
+ s.metadata = { "homepage_uri" => "https://github.com/ruby/tempfile", "source_code_uri" => "https://github.com/ruby/tempfile" } if s.respond_to? :metadata=
10
+ s.require_paths = ["lib".freeze]
11
+ s.authors = ["Yukihiro Matsumoto".freeze]
12
+ s.bindir = "exe".freeze
13
+ s.date = "2020-04-01"
14
+ s.description = "A utility class for managing temporary files.".freeze
15
+ s.email = ["matz@ruby-lang.org".freeze]
16
+ s.homepage = "https://github.com/ruby/tempfile".freeze
17
+ s.required_ruby_version = Gem::Requirement.new(">= 2.5.0".freeze)
18
+ s.rubygems_version = "3.1.3".freeze
19
+ s.summary = "A utility class for managing temporary files.".freeze
20
+
21
+ s.installed_by_version = "3.1.3" if s.respond_to? :installed_by_version
22
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-output-scalyr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edward Chee
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-04 00:00:00.000000000 Z
11
+ date: 2020-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -200,6 +200,7 @@ files:
200
200
  - vendor/bundle/jruby/2.5.0/cache/slop-3.6.0.gem
201
201
  - vendor/bundle/jruby/2.5.0/cache/spoon-0.0.6.gem
202
202
  - vendor/bundle/jruby/2.5.0/cache/stud-0.0.23.gem
203
+ - vendor/bundle/jruby/2.5.0/cache/tempfile-0.1.0.gem
203
204
  - vendor/bundle/jruby/2.5.0/cache/thread_safe-0.3.6-java.gem
204
205
  - vendor/bundle/jruby/2.5.0/cache/tilt-2.0.10.gem
205
206
  - vendor/bundle/jruby/2.5.0/cache/tilt-2.0.9.gem
@@ -4030,6 +4031,14 @@ files:
4030
4031
  - vendor/bundle/jruby/2.5.0/gems/stud-0.0.23/lib/stud/trap.rb
4031
4032
  - vendor/bundle/jruby/2.5.0/gems/stud-0.0.23/lib/stud/try.rb
4032
4033
  - vendor/bundle/jruby/2.5.0/gems/stud-0.0.23/lib/stud/with.rb
4034
+ - vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/Gemfile
4035
+ - vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/Gemfile.lock
4036
+ - vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/README.md
4037
+ - vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/Rakefile
4038
+ - vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/bin/console
4039
+ - vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/bin/setup
4040
+ - vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/lib/tempfile.rb
4041
+ - vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/tempfile.gemspec
4033
4042
  - vendor/bundle/jruby/2.5.0/gems/thread_safe-0.3.6-java/Gemfile
4034
4043
  - vendor/bundle/jruby/2.5.0/gems/thread_safe-0.3.6-java/LICENSE
4035
4044
  - vendor/bundle/jruby/2.5.0/gems/thread_safe-0.3.6-java/README.md
@@ -4401,6 +4410,7 @@ files:
4401
4410
  - vendor/bundle/jruby/2.5.0/specifications/slop-3.6.0.gemspec
4402
4411
  - vendor/bundle/jruby/2.5.0/specifications/spoon-0.0.6.gemspec
4403
4412
  - vendor/bundle/jruby/2.5.0/specifications/stud-0.0.23.gemspec
4413
+ - vendor/bundle/jruby/2.5.0/specifications/tempfile-0.1.0.gemspec
4404
4414
  - vendor/bundle/jruby/2.5.0/specifications/thread_safe-0.3.6-java.gemspec
4405
4415
  - vendor/bundle/jruby/2.5.0/specifications/tilt-2.0.10.gemspec
4406
4416
  - vendor/bundle/jruby/2.5.0/specifications/tilt-2.0.9.gemspec