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 +4 -4
- data/README.md +2 -2
- data/lib/logstash/outputs/scalyr.rb +17 -11
- data/lib/scalyr/common/client.rb +68 -4
- data/logstash-output-scalyr.gemspec +1 -1
- data/vendor/bundle/jruby/2.5.0/cache/tempfile-0.1.0.gem +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/Gemfile +6 -0
- data/vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/Gemfile.lock +23 -0
- data/vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/README.md +51 -0
- data/vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/Rakefile +10 -0
- data/vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/bin/console +14 -0
- data/vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/bin/setup +8 -0
- data/vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/lib/tempfile.rb +350 -0
- data/vendor/bundle/jruby/2.5.0/gems/tempfile-0.1.0/tempfile.gemspec +23 -0
- data/vendor/bundle/jruby/2.5.0/specifications/tempfile-0.1.0.gemspec +22 -0
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f02a9ffc8738ad5eef45acc94337eaa36f3e567883429b761691318f40de5eda
|
4
|
+
data.tar.gz: 124d1ced3db2cbf8ad6a38b196f1697f75b2852bc9b55585c19dc6a87a72469a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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 =>
|
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 =>
|
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
|
-
|
216
|
-
|
217
|
-
|
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.
|
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
|
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
|
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) {
|
600
|
+
Stud.stoppable_sleep(sleep_interval) { !@running }
|
595
601
|
get_sleep_sec(sleep_interval)
|
596
602
|
end
|
597
603
|
|
data/lib/scalyr/common/client.rb
CHANGED
@@ -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
|
-
@
|
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.
|
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
|
+
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)"
|
Binary file
|
@@ -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,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,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.
|
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-
|
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
|