logstash-output-azure 0.3.0 → 1.0.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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +4 -1
- data/CONTRIBUTORS +1 -0
- data/lib/logstash/outputs/azure.rb +59 -81
- data/lib/logstash/outputs/blob/file_repository.rb +33 -18
- data/lib/logstash/outputs/blob/path_validator.rb +3 -3
- data/lib/logstash/outputs/blob/size_and_time_rotation_policy.rb +6 -4
- data/lib/logstash/outputs/blob/size_rotation_policy.rb +5 -4
- data/lib/logstash/outputs/blob/temporary_file.rb +28 -19
- data/lib/logstash/outputs/blob/temporary_file_factory.rb +28 -16
- data/lib/logstash/outputs/blob/time_rotation_policy.rb +5 -4
- data/lib/logstash/outputs/blob/uploader.rb +29 -22
- data/lib/logstash/outputs/blob/writable_directory_validator.rb +6 -7
- data/logstash-output-azure.gemspec +10 -10
- data/spec/outputs/azure_spec.rb +16 -18
- data/spec/outputs/blob/file_repository_spec.rb +35 -38
- data/spec/outputs/blob/size_and_time_rotation_policy_spec.rb +20 -21
- data/spec/outputs/blob/size_rotation_policy_spec.rb +13 -15
- data/spec/outputs/blob/temporary_file_factory_spec.rb +27 -28
- data/spec/outputs/blob/temporary_file_spec.rb +14 -15
- data/spec/outputs/blob/time_rotation_policy_spec.rb +17 -18
- data/spec/outputs/blob/uploader_spec.rb +28 -32
- data/spec/outputs/blob/writable_directory_validator_spec.rb +8 -9
- data/spec/spec_helper.rb +4 -5
- data/spec/supports/helpers.rb +12 -15
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a0957c333ee69df3b98978bda9a84c26d0d2752f1904fbd104d7d4d58e249095
|
4
|
+
data.tar.gz: dc9b4e1a009d29a98183bcc984825e41680ba83bd51f5968e7933097f532619e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65aa1e9eba3e573294306710165a91f06b4f5c304a8020f8f1abd5ce5dde5c3c45d6931665baad8a014a66eec52fe0a81b190e752ce23dedca26aa0d9f724f3b
|
7
|
+
data.tar.gz: 5fcdca862617607b619586f854331aa1eda6a47af66f508d3f04bcd9fb5f953d9a2e966a5cfb141763aab0e5d590f4e15d5b7c3678c71c505c9cc1ad2f902ac2
|
data/CHANGELOG.md
CHANGED
data/CONTRIBUTORS
CHANGED
@@ -3,6 +3,7 @@ reports, or in general have helped logstash along its way.
|
|
3
3
|
|
4
4
|
Contributors:
|
5
5
|
* Tuffk - tuffkmulhall@gmail.com
|
6
|
+
* BrunoLerner - bru.lerner@gmail.com
|
6
7
|
|
7
8
|
Note: If you've sent us patches, bug reports, or otherwise contributed to
|
8
9
|
Logstash, and you aren't on the list above and want to be, please let us know
|
@@ -1,10 +1,7 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
require 'logstash/outputs/base'
|
4
2
|
require 'logstash/namespace'
|
5
3
|
require 'azure'
|
6
4
|
require 'tmpdir'
|
7
|
-
require 'pry'
|
8
5
|
|
9
6
|
# Logstash outout plugin that uploads the logs to Azure blobs.
|
10
7
|
# The logs are stored on local temporary file which is uploaded as a blob
|
@@ -32,7 +29,7 @@ require 'pry'
|
|
32
29
|
# upload que size
|
33
30
|
# @!attribute upload workers count
|
34
31
|
# how much workers for uplaod
|
35
|
-
# @!attribute
|
32
|
+
# @!attribute rotation_strategy_val
|
36
33
|
# what will be considered to do the tmeporary file rotation
|
37
34
|
# @!attribute tags
|
38
35
|
# tags for the files
|
@@ -40,10 +37,10 @@ require 'pry'
|
|
40
37
|
# the encoding of the files
|
41
38
|
# @example basic configuration
|
42
39
|
# output {
|
43
|
-
#
|
44
|
-
# storage_account_name => "my-azure-account" #
|
45
|
-
# storage_access_key => "my-super-secret-key" #
|
46
|
-
# contianer_name => "my-contianer" #
|
40
|
+
# azure {
|
41
|
+
# storage_account_name => "my-azure-account" # required
|
42
|
+
# storage_access_key => "my-super-secret-key" # required
|
43
|
+
# contianer_name => "my-contianer" # required
|
47
44
|
# size_file => 1024*1024*5 # optional
|
48
45
|
# time_file => 10 # optional
|
49
46
|
# restore => true # optional
|
@@ -51,15 +48,14 @@ require 'pry'
|
|
51
48
|
# prefix => "a_prefix" # optional
|
52
49
|
# upload_queue_size => 2 # optional
|
53
50
|
# upload_workers_count => 1 # optional
|
54
|
-
#
|
51
|
+
# rotation_strategy_val => "size_and_time" # optional
|
55
52
|
# tags => [] # optional
|
56
53
|
# encoding => "none" # optional
|
57
54
|
# }
|
58
55
|
# }
|
59
56
|
class LogStash::Outputs::LogstashAzureBlobOutput < LogStash::Outputs::Base
|
60
57
|
# name for the namespace under output for logstash configuration
|
61
|
-
config_name
|
62
|
-
|
58
|
+
config_name 'azure'
|
63
59
|
|
64
60
|
require 'logstash/outputs/blob/writable_directory_validator'
|
65
61
|
require 'logstash/outputs/blob/path_validator'
|
@@ -71,14 +67,11 @@ class LogStash::Outputs::LogstashAzureBlobOutput < LogStash::Outputs::Base
|
|
71
67
|
require 'logstash/outputs/blob/uploader'
|
72
68
|
require 'logstash/outputs/blob/file_repository'
|
73
69
|
|
74
|
-
PREFIX_KEY_NORMALIZE_CHARACTER =
|
70
|
+
PREFIX_KEY_NORMALIZE_CHARACTER = '_'.freeze
|
75
71
|
PERIODIC_CHECK_INTERVAL_IN_SECONDS = 15
|
76
|
-
CRASH_RECOVERY_THREADPOOL = Concurrent::ThreadPoolExecutor.new(
|
77
|
-
|
78
|
-
|
79
|
-
:fallback_policy => :caller_runs
|
80
|
-
})
|
81
|
-
|
72
|
+
CRASH_RECOVERY_THREADPOOL = Concurrent::ThreadPoolExecutor.new(min_threads: 1,
|
73
|
+
max_threads: 2,
|
74
|
+
fallback_policy: :caller_runs)
|
82
75
|
|
83
76
|
# azure contianer
|
84
77
|
config :storage_account_name, validate: :string, required: false
|
@@ -97,32 +90,30 @@ class LogStash::Outputs::LogstashAzureBlobOutput < LogStash::Outputs::Base
|
|
97
90
|
config :prefix, validate: :string, default: ''
|
98
91
|
config :upload_queue_size, validate: :number, default: 2 * (Concurrent.processor_count * 0.25).ceil
|
99
92
|
config :upload_workers_count, validate: :number, default: (Concurrent.processor_count * 0.5).ceil
|
100
|
-
config :
|
101
|
-
config :tags, :
|
102
|
-
config :encoding, :
|
93
|
+
config :rotation_strategy_val, validate: %w[size_and_time size time], default: 'size_and_time'
|
94
|
+
config :tags, validate: :array, default: []
|
95
|
+
config :encoding, validate: %w[none gzip], default: 'none'
|
103
96
|
|
104
|
-
attr_accessor :storage_account_name, :storage_access_key
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
public
|
97
|
+
attr_accessor :storage_account_name, :storage_access_key, :container_name,
|
98
|
+
:size_file, :time_file, :restore, :temporary_directory, :prefix, :upload_queue_size,
|
99
|
+
:upload_workers_count, :rotation_strategy_val, :tags, :encoding
|
109
100
|
|
110
101
|
# initializes the +LogstashAzureBlobOutput+ instances
|
111
|
-
# validates all
|
102
|
+
# validates all config parameters
|
112
103
|
# initializes the uploader
|
113
104
|
def register
|
114
105
|
unless @prefix.empty?
|
115
106
|
unless PathValidator.valid?(prefix)
|
116
|
-
raise LogStash::ConfigurationError
|
107
|
+
raise LogStash::ConfigurationError.new("Prefix must not contains: #{PathValidator::INVALID_CHARACTERS}")
|
117
108
|
end
|
118
109
|
end
|
119
110
|
|
120
111
|
unless WritableDirectoryValidator.valid?(@temporary_directory)
|
121
|
-
raise LogStash::ConfigurationError
|
112
|
+
raise LogStash::ConfigurationError.new("Logstash must have the permissions to write to the temporary directory: #{@temporary_directory}")
|
122
113
|
end
|
123
114
|
|
124
|
-
if @time_file.nil? && @size_file.nil? || @size_file
|
125
|
-
raise LogStash::ConfigurationError
|
115
|
+
if @time_file.nil? && @size_file.nil? || @size_file.zero? && @time_file.zero?
|
116
|
+
raise LogStash::ConfigurationError.new('at least one of time_file or size_file set to a value greater than 0')
|
126
117
|
end
|
127
118
|
|
128
119
|
@file_repository = FileRepository.new(@tags, @encoding, @temporary_directory)
|
@@ -138,8 +129,10 @@ class LogStash::Outputs::LogstashAzureBlobOutput < LogStash::Outputs::Base
|
|
138
129
|
|
139
130
|
restore_from_crash if @restore
|
140
131
|
start_periodic_check if @rotation.needs_periodic?
|
141
|
-
end
|
132
|
+
end
|
142
133
|
|
134
|
+
# Receives multiple events and check if there is space in temporary directory
|
135
|
+
# @param events_and_encoded [Object]
|
143
136
|
def multi_receive_encoded(events_and_encoded)
|
144
137
|
prefix_written_to = Set.new
|
145
138
|
|
@@ -152,7 +145,7 @@ class LogStash::Outputs::LogstashAzureBlobOutput < LogStash::Outputs::Base
|
|
152
145
|
# The output should stop accepting new events coming in, since it cannot do anything with them anymore.
|
153
146
|
# Log the error and rethrow it.
|
154
147
|
rescue Errno::ENOSPC => e
|
155
|
-
@logger.error('
|
148
|
+
@logger.error('Azure: No space left in temporary directory', temporary_directory: @temporary_directory)
|
156
149
|
raise e
|
157
150
|
end
|
158
151
|
end
|
@@ -161,7 +154,7 @@ class LogStash::Outputs::LogstashAzureBlobOutput < LogStash::Outputs::Base
|
|
161
154
|
rotate_if_needed(prefix_written_to)
|
162
155
|
end
|
163
156
|
|
164
|
-
# close the
|
157
|
+
# close the temporary file and uploads the content to Azure
|
165
158
|
def close
|
166
159
|
stop_periodic_check if @rotation.needs_periodic?
|
167
160
|
|
@@ -182,21 +175,18 @@ class LogStash::Outputs::LogstashAzureBlobOutput < LogStash::Outputs::Base
|
|
182
175
|
@crash_uploader.stop if @restore # we might have still work to do for recovery so wait until we are done
|
183
176
|
end
|
184
177
|
|
178
|
+
# Validates and normalize prefix key
|
179
|
+
# @param prefix_key [String]
|
185
180
|
def normalize_key(prefix_key)
|
186
181
|
prefix_key.gsub(PathValidator.matches_re, PREFIX_KEY_NORMALIZE_CHARACTER)
|
187
182
|
end
|
188
183
|
|
189
|
-
def upload_options
|
190
|
-
{
|
191
|
-
}
|
192
|
-
end
|
193
|
-
|
194
184
|
# checks periodically the tmeporary file if it needs to be rotated
|
195
185
|
def start_periodic_check
|
196
|
-
@logger.debug(
|
186
|
+
@logger.debug('Start periodic rotation check')
|
197
187
|
|
198
|
-
@periodic_check = Concurrent::TimerTask.new(:
|
199
|
-
@logger.debug(
|
188
|
+
@periodic_check = Concurrent::TimerTask.new(execution_interval: PERIODIC_CHECK_INTERVAL_IN_SECONDS) do
|
189
|
+
@logger.debug('Periodic check for stale files')
|
200
190
|
|
201
191
|
rotate_if_needed(@file_repository.keys)
|
202
192
|
end
|
@@ -208,21 +198,23 @@ class LogStash::Outputs::LogstashAzureBlobOutput < LogStash::Outputs::Base
|
|
208
198
|
@periodic_check.shutdown
|
209
199
|
end
|
210
200
|
|
211
|
-
# login to azure cloud using azure gem and
|
212
|
-
# the
|
201
|
+
# login to azure cloud using azure gem and create the contianer if it doesn't exist
|
202
|
+
# @return [Object] the azure_blob_service object, which is the endpoint to azure gem
|
213
203
|
def blob_container_resource
|
214
204
|
Azure.config.storage_account_name = storage_account_name
|
215
205
|
Azure.config.storage_access_key = storage_access_key
|
216
206
|
azure_blob_service = Azure::Blob::BlobService.new
|
217
|
-
list = azure_blob_service.list_containers
|
207
|
+
list = azure_blob_service.list_containers
|
218
208
|
list.each do |item|
|
219
209
|
@container = item if item.name == container_name
|
220
210
|
end
|
221
211
|
|
222
212
|
azure_blob_service.create_container(container_name) unless @container
|
223
|
-
|
213
|
+
azure_blob_service
|
224
214
|
end
|
225
215
|
|
216
|
+
# check if it needs to rotate according to rotation policy and rotates it if it needs
|
217
|
+
# @param prefixes [String]
|
226
218
|
def rotate_if_needed(prefixes)
|
227
219
|
prefixes.each do |prefix|
|
228
220
|
# Each file access is thread safe,
|
@@ -232,10 +224,10 @@ class LogStash::Outputs::LogstashAzureBlobOutput < LogStash::Outputs::Base
|
|
232
224
|
temp_file = factory.current
|
233
225
|
|
234
226
|
if @rotation.rotate?(temp_file)
|
235
|
-
@logger.debug(
|
236
|
-
:
|
237
|
-
:
|
238
|
-
:
|
227
|
+
@logger.debug('Rotate file',
|
228
|
+
strategy: @rotation.class.name,
|
229
|
+
key: temp_file.key,
|
230
|
+
path: temp_file.path)
|
239
231
|
|
240
232
|
upload_file(temp_file)
|
241
233
|
factory.rotate!
|
@@ -246,60 +238,46 @@ class LogStash::Outputs::LogstashAzureBlobOutput < LogStash::Outputs::Base
|
|
246
238
|
|
247
239
|
# uploads the file using the +Uploader+
|
248
240
|
def upload_file(temp_file)
|
249
|
-
@logger.debug(
|
241
|
+
@logger.debug('Queue for upload', path: temp_file.path)
|
250
242
|
|
251
243
|
# if the queue is full the calling thread will be used to upload
|
252
244
|
temp_file.close # make sure the content is on disk
|
253
|
-
|
245
|
+
unless temp_file.empty? # rubocop:disable GuardClause
|
254
246
|
@uploader.upload_async(temp_file,
|
255
|
-
:
|
256
|
-
:
|
247
|
+
on_complete: method(:clean_temporary_file),
|
248
|
+
upload_options: upload_options)
|
257
249
|
end
|
258
250
|
end
|
259
251
|
|
260
252
|
# creates an instance for the rotation strategy
|
261
253
|
def rotation_strategy
|
262
|
-
case @
|
263
|
-
when
|
254
|
+
case @rotation_strategy_val
|
255
|
+
when 'size'
|
264
256
|
SizeRotationPolicy.new(size_file)
|
265
|
-
when
|
257
|
+
when 'time'
|
266
258
|
TimeRotationPolicy.new(time_file)
|
267
|
-
when
|
259
|
+
when 'size_and_time'
|
268
260
|
SizeAndTimeRotationPolicy.new(size_file, time_file)
|
269
261
|
end
|
270
262
|
end
|
271
263
|
|
264
|
+
# Cleans the temporary files after it is uploaded to azure blob
|
272
265
|
def clean_temporary_file(file)
|
273
|
-
@logger.debug(
|
266
|
+
@logger.debug('Removing temporary file', file: file.path)
|
274
267
|
file.delete!
|
275
268
|
end
|
276
269
|
|
270
|
+
# uploads files if there was a crash before
|
277
271
|
def restore_from_crash
|
278
272
|
@crash_uploader = Uploader.new(blob_container_resource, container_name, @logger, CRASH_RECOVERY_THREADPOOL)
|
279
273
|
|
280
274
|
temp_folder_path = Pathname.new(@temporary_directory)
|
281
|
-
Dir.glob(::File.join(@temporary_directory,
|
282
|
-
|
283
|
-
|
275
|
+
Dir.glob(::File.join(@temporary_directory, '**/*'))
|
276
|
+
.select { |file| ::File.file?(file) }
|
277
|
+
.each do |file|
|
284
278
|
temp_file = TemporaryFile.create_from_existing_file(file, temp_folder_path)
|
285
|
-
@logger.debug(
|
286
|
-
@crash_uploader.upload_async(temp_file, :
|
279
|
+
@logger.debug('Recovering from crash and uploading', file: temp_file.path)
|
280
|
+
@crash_uploader.upload_async(temp_file, on_complete: method(:clean_temporary_file), upload_options: upload_options)
|
287
281
|
end
|
288
282
|
end
|
289
|
-
|
290
|
-
|
291
|
-
public
|
292
|
-
|
293
|
-
def receive(event)
|
294
|
-
azure_login
|
295
|
-
azure_blob_service = Azure::Blob::BlobService.new
|
296
|
-
containers = azure_blob_service.list_containers
|
297
|
-
blob = azure_blob_service.create_block_blob(containers[0].name, event.timestamp.to_s, event.to_json)
|
298
|
-
end # def event
|
299
|
-
|
300
|
-
# inputs the credentials to the azure gem to log in and use azure API
|
301
|
-
def azure_login
|
302
|
-
Azure.config.storage_account_name ||= storage_account_name
|
303
|
-
Azure.config.storage_access_key ||= storage_access_key
|
304
|
-
end # def azure_login
|
305
|
-
end # class LogStash::Outputs::LogstashAzureBlobOutput
|
283
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
|
2
|
+
require 'java'
|
3
|
+
require 'concurrent'
|
4
|
+
require 'concurrent/timer_task'
|
5
|
+
require 'logstash/util'
|
6
6
|
|
7
7
|
ConcurrentHashMap = java.util.concurrent.ConcurrentHashMap
|
8
8
|
|
@@ -10,40 +10,46 @@ module LogStash
|
|
10
10
|
module Outputs
|
11
11
|
class LogstashAzureBlobOutput
|
12
12
|
# sub class for +LogstashAzureBlobOutput+
|
13
|
-
# this class manages the
|
13
|
+
# this class manages the temporary directory for the temporary files
|
14
14
|
class FileRepository
|
15
15
|
DEFAULT_STATE_SWEEPER_INTERVAL_SECS = 60
|
16
16
|
DEFAULT_STALE_TIME_SECS = 15 * 60
|
17
17
|
# Ensure that all access or work done
|
18
18
|
# on a factory is threadsafe
|
19
19
|
class PrefixedValue
|
20
|
+
# initialize the factory
|
20
21
|
def initialize(file_factory, stale_time)
|
21
22
|
@file_factory = file_factory
|
22
23
|
@lock = Mutex.new
|
23
24
|
@stale_time = stale_time
|
24
25
|
end
|
25
26
|
|
27
|
+
# activate the lock
|
26
28
|
def with_lock
|
27
|
-
@lock.synchronize
|
29
|
+
@lock.synchronize do
|
28
30
|
yield @file_factory
|
29
|
-
|
31
|
+
end
|
30
32
|
end
|
31
33
|
|
34
|
+
# boolean method
|
32
35
|
def stale?
|
33
|
-
with_lock { |factory| factory.current.size
|
36
|
+
with_lock { |factory| factory.current.size.zero? && (Time.now - factory.current.ctime > @stale_time) }
|
34
37
|
end
|
35
38
|
|
36
|
-
|
37
|
-
|
39
|
+
# return this class
|
40
|
+
def apply(_prefix)
|
41
|
+
self
|
38
42
|
end
|
39
43
|
|
44
|
+
# delete the current factory
|
40
45
|
def delete!
|
41
|
-
with_lock{ |factory| factory.current.delete! }
|
46
|
+
with_lock { |factory| factory.current.delete! }
|
42
47
|
end
|
43
48
|
end
|
44
49
|
|
45
50
|
# class for initializing the repo manager
|
46
51
|
class FactoryInitializer
|
52
|
+
# initializes the class
|
47
53
|
def initialize(tags, encoding, temporary_directory, stale_time)
|
48
54
|
@tags = tags
|
49
55
|
@encoding = encoding
|
@@ -51,17 +57,18 @@ module LogStash
|
|
51
57
|
@stale_time = stale_time
|
52
58
|
end
|
53
59
|
|
60
|
+
# applies the prefix key
|
54
61
|
def apply(prefix_key)
|
55
62
|
PrefixedValue.new(TemporaryFileFactory.new(prefix_key, @tags, @encoding, @temporary_directory), @stale_time)
|
56
63
|
end
|
57
64
|
end
|
58
|
-
|
65
|
+
# initializes the class with more variables
|
59
66
|
def initialize(tags, encoding, temporary_directory,
|
60
67
|
stale_time = DEFAULT_STALE_TIME_SECS,
|
61
68
|
sweeper_interval = DEFAULT_STATE_SWEEPER_INTERVAL_SECS)
|
62
69
|
# The path need to contains the prefix so when we start
|
63
70
|
# logtash after a crash we keep the remote structure
|
64
|
-
@prefixed_factories =
|
71
|
+
@prefixed_factories = ConcurrentHashMap.new
|
65
72
|
|
66
73
|
@sweeper_interval = sweeper_interval
|
67
74
|
|
@@ -70,10 +77,12 @@ module LogStash
|
|
70
77
|
start_stale_sweeper
|
71
78
|
end
|
72
79
|
|
80
|
+
# gets the key set
|
73
81
|
def keys
|
74
82
|
@prefixed_factories.keySet
|
75
83
|
end
|
76
84
|
|
85
|
+
# with lock for each file
|
77
86
|
def each_files
|
78
87
|
@prefixed_factories.elements.each do |prefixed_file|
|
79
88
|
prefixed_file.with_lock { |factory| yield factory.current }
|
@@ -85,35 +94,41 @@ module LogStash
|
|
85
94
|
@prefixed_factories.computeIfAbsent(prefix_key, @factory_initializer).with_lock { |factory| yield factory }
|
86
95
|
end
|
87
96
|
|
97
|
+
# gets file from prefix_key
|
88
98
|
def get_file(prefix_key)
|
89
99
|
get_factory(prefix_key) { |factory| yield factory.current }
|
90
100
|
end
|
91
101
|
|
102
|
+
# stops. shutdown
|
92
103
|
def shutdown
|
93
104
|
stop_stale_sweeper
|
94
105
|
end
|
95
106
|
|
107
|
+
# gets factory's size
|
96
108
|
def size
|
97
109
|
@prefixed_factories.size
|
98
110
|
end
|
99
111
|
|
112
|
+
# remove the stale given key and value
|
100
113
|
def remove_stale(k, v)
|
101
|
-
if v.stale?
|
114
|
+
if v.stale? # rubocop:disable Style/GuardClause
|
102
115
|
@prefixed_factories.remove(k, v)
|
103
116
|
v.delete!
|
104
117
|
end
|
105
118
|
end
|
106
119
|
|
120
|
+
# starts the stale sweeper
|
107
121
|
def start_stale_sweeper
|
108
|
-
@stale_sweeper = Concurrent::TimerTask.new(:
|
109
|
-
LogStash::Util.set_thread_name(
|
122
|
+
@stale_sweeper = Concurrent::TimerTask.new(execution_interval: @sweeper_interval) do
|
123
|
+
LogStash::Util.set_thread_name('LogstashAzureBlobOutput, Stale factory sweeper')
|
110
124
|
|
111
|
-
@prefixed_factories.forEach{|k,v| remove_stale(k,v)}
|
125
|
+
@prefixed_factories.forEach { |k, v| remove_stale(k, v) }
|
112
126
|
end
|
113
127
|
|
114
128
|
@stale_sweeper.execute
|
115
129
|
end
|
116
130
|
|
131
|
+
# stops the stale sweeper
|
117
132
|
def stop_stale_sweeper
|
118
133
|
@stale_sweeper.shutdown
|
119
134
|
end
|