logstash-integration-jdbc 5.2.1 → 5.2.2

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: 5826d365fd1f0f71ef3562e40e51d68b9bf76585bbd536eb5868a56c5bb6aacb
4
- data.tar.gz: 5ae08858db8043a0840d7a8578eae295e99b6a1da4ca3ec9239ee0730298188e
3
+ metadata.gz: 2f43be09f1996c0e4effd6914055fa643549925433ab4512f4e3a0ed1fa1933c
4
+ data.tar.gz: 346cb42a27eaaa3f51e7cf1ba3d52fb332f278dfe8cecf7d1aa200af42ba4f5b
5
5
  SHA512:
6
- metadata.gz: 685637b889432ff5378e6c9873a90b183a90337a011d9719c17b6928721fbef01e393b111f35d2d4d19e7a8bc62eeffd98d93964e46494f486b93f7a9b45bff3
7
- data.tar.gz: 30f804b0e420b7485da98805e80902ae2d8b33417256938706ba79f0f20fe62d8da2bec9a6c716e50a30f3455f0cb86f6757eef9811e631685f3e620c8c6a604
6
+ metadata.gz: 3a75a4a4165e04178384a66740de3bce2981c2d019a8bd2192519a725bfe88d5ddf7469cf2a2aebda12b1b48b2117817171da2f459d283c3e3e16d86422c4c06
7
+ data.tar.gz: ae15ead4d5efd52cc67bf58ad1d994bde11443bbc0e083d56f695ddc7163be44454ee1db1a95b81ec884c51a790f2e7582733df4f5faf6b9d4715a0685a31c92
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## 5.2.2
2
+ - Feat: name scheduler threads + redirect error logging [#102](https://github.com/logstash-plugins/logstash-integration-jdbc/pull/102)
3
+
1
4
  ## 5.2.1
2
5
  - Refactor: isolate paginated normal statement algorithm in a separate handler [#101](https://github.com/logstash-plugins/logstash-integration-jdbc/pull/101)
3
6
 
@@ -3,6 +3,7 @@ require "logstash/inputs/base"
3
3
  require "logstash/namespace"
4
4
  require "logstash/plugin_mixins/jdbc/common"
5
5
  require "logstash/plugin_mixins/jdbc/jdbc"
6
+ require "logstash/plugin_mixins/jdbc/scheduler"
6
7
  require "logstash/plugin_mixins/ecs_compatibility_support"
7
8
  require "logstash/plugin_mixins/ecs_compatibility_support/target_check"
8
9
  require "logstash/plugin_mixins/validator_support/field_reference_validation_adapter"
@@ -293,8 +294,11 @@ module LogStash module Inputs class Jdbc < LogStash::Inputs::Base
293
294
  def run(queue)
294
295
  load_driver
295
296
  if @schedule
296
- @scheduler = Rufus::Scheduler.new(:max_work_threads => 1)
297
- @scheduler.cron @schedule do
297
+ # input thread (Java) name example "[my-oracle]<jdbc"
298
+ @scheduler = LogStash::PluginMixins::Jdbc::Scheduler.new(
299
+ :max_work_threads => 1, :thread_name => "[#{id}]<jdbc__scheduler"
300
+ )
301
+ @scheduler.schedule_cron @schedule do
298
302
  execute_query(queue)
299
303
  end
300
304
 
@@ -220,7 +220,8 @@ module LogStash module PluginMixins module Jdbc
220
220
  end
221
221
  success = true
222
222
  rescue Sequel::DatabaseConnectionError, Sequel::DatabaseError, Java::JavaSql::SQLException => e
223
- details = { :exception => e.message }
223
+ details = { exception: e.class, message: e.message }
224
+ details[:cause] = e.cause.inspect if e.cause
224
225
  details[:backtrace] = e.backtrace if @logger.debug?
225
226
  @logger.warn("Exception when executing JDBC query", details)
226
227
  else
@@ -0,0 +1,111 @@
1
+ require 'rufus/scheduler'
2
+
3
+ require 'logstash/util/loggable'
4
+
5
+ module LogStash module PluginMixins module Jdbc
6
+ class Scheduler < Rufus::Scheduler
7
+
8
+ include LogStash::Util::Loggable
9
+
10
+ # Rufus::Scheduler >= 3.4 moved the Time impl into a gem EoTime = ::EtOrbi::EoTime`
11
+ # Rufus::Scheduler 3.1 - 3.3 using it's own Time impl `Rufus::Scheduler::ZoTime`
12
+ TimeImpl = defined?(Rufus::Scheduler::EoTime) ? Rufus::Scheduler::EoTime :
13
+ (defined?(Rufus::Scheduler::ZoTime) ? Rufus::Scheduler::ZoTime : ::Time)
14
+
15
+ # @overload
16
+ def on_error(job, err)
17
+ details = { exception: err.class, message: err.message, backtrace: err.backtrace }
18
+ details[:cause] = err.cause if err.cause
19
+
20
+ details[:now] = debug_format_time(TimeImpl.now)
21
+ details[:last_time] = (debug_format_time(job.last_time) rescue nil)
22
+ details[:next_time] = (debug_format_time(job.next_time) rescue nil)
23
+ details[:job] = job
24
+
25
+ details[:opts] = @opts
26
+ details[:started_at] = started_at
27
+ details[:thread] = thread.inspect
28
+ details[:jobs_size] = @jobs.size
29
+ details[:work_threads_size] = work_threads.size
30
+ details[:work_queue_size] = work_queue.size
31
+
32
+ logger.error("Scheduler intercepted an error:", details)
33
+
34
+ rescue => e
35
+ logger.error("Scheduler failed in #on_error #{e.inspect}")
36
+ end
37
+
38
+ def debug_format_time(time)
39
+ # EtOrbi::EoTime used by (newer) Rufus::Scheduler has to_debug_s https://git.io/JyiPj
40
+ time.respond_to?(:to_debug_s) ? time.to_debug_s : time.strftime("%Y-%m-%dT%H:%M:%S.%L")
41
+ end
42
+ private :debug_format_time
43
+
44
+ # @private helper used by JobDecorator
45
+ def work_thread_name_prefix
46
+ ( @opts[:thread_name] || "#{@thread_key}_scheduler" ) + '_worker-'
47
+ end
48
+
49
+ protected
50
+
51
+ # @overload
52
+ def start
53
+ ret = super() # @thread[:name] = @opts[:thread_name] || "#{@thread_key}_scheduler"
54
+
55
+ # at least set thread.name for easier thread dump analysis
56
+ if @thread.is_a?(Thread) && @thread.respond_to?(:name=)
57
+ @thread.name = @thread[:name] if @thread[:name]
58
+ end
59
+
60
+ ret
61
+ end
62
+
63
+ # @overload
64
+ def do_schedule(job_type, t, callable, opts, return_job_instance, block)
65
+ job_or_id = super
66
+
67
+ job_or_id.extend JobDecorator if return_job_instance
68
+
69
+ job_or_id
70
+ end
71
+
72
+ module JobDecorator
73
+
74
+ def start_work_thread
75
+ prev_thread_count = @scheduler.work_threads.size
76
+
77
+ ret = super() # does not return Thread instance in 3.0
78
+
79
+ work_threads = @scheduler.work_threads
80
+ while prev_thread_count == work_threads.size # very unlikely
81
+ Thread.pass
82
+ work_threads = @scheduler.work_threads
83
+ end
84
+
85
+ work_thread_name_prefix = @scheduler.work_thread_name_prefix
86
+
87
+ work_threads.sort! do |t1, t2|
88
+ if t1[:name].nil?
89
+ t2[:name].nil? ? 0 : +1 # nils at the end
90
+ elsif t2[:name].nil?
91
+ t1[:name].nil? ? 0 : -1
92
+ else
93
+ t1[:name] <=> t2[:name]
94
+ end
95
+ end
96
+
97
+ work_threads.each_with_index do |thread, i|
98
+ unless thread[:name]
99
+ thread[:name] = "#{work_thread_name_prefix}#{sprintf('%02i', i)}"
100
+ thread.name = thread[:name] if thread.respond_to?(:name=)
101
+ # e.g. "[oracle]<jdbc_scheduler_worker-00"
102
+ end
103
+ end
104
+
105
+ ret
106
+ end
107
+
108
+ end
109
+
110
+ end
111
+ end end end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-integration-jdbc'
3
- s.version = '5.2.1'
3
+ s.version = '5.2.2'
4
4
  s.licenses = ['Apache License (2.0)']
5
5
  s.summary = "Integration with JDBC - input and filter plugins"
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"
@@ -34,8 +34,7 @@ Gem::Specification.new do |s|
34
34
 
35
35
  s.add_runtime_dependency 'tzinfo'
36
36
  s.add_runtime_dependency 'tzinfo-data'
37
- # 3.5 limitation is required for jdbc-static loading schedule
38
- s.add_runtime_dependency 'rufus-scheduler', '< 3.5'
37
+ s.add_runtime_dependency 'rufus-scheduler', '~> 3.0.9'
39
38
  s.add_runtime_dependency 'logstash-mixin-ecs_compatibility_support', '~>1.3'
40
39
  s.add_runtime_dependency "logstash-mixin-validator_support", '~> 1.0'
41
40
  s.add_runtime_dependency "logstash-mixin-event_support", '~> 1.0'
@@ -70,7 +70,7 @@ describe LogStash::Inputs::Jdbc, :integration => true do
70
70
  plugin.register
71
71
  expect( plugin ).to receive(:log_java_exception)
72
72
  expect(plugin.logger).to receive(:warn).once.with("Exception when executing JDBC query",
73
- hash_including(:exception => instance_of(String)))
73
+ hash_including(:message => instance_of(String)))
74
74
  q = Queue.new
75
75
  expect{ plugin.run(q) }.not_to raise_error
76
76
  end
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
3
+ require "logstash/plugin_mixins/jdbc/scheduler"
4
+
5
+ describe LogStash::PluginMixins::Jdbc::Scheduler do
6
+
7
+ let(:thread_name) { '[test]<jdbc_scheduler' }
8
+
9
+ let(:opts) do
10
+ { :max_work_threads => 2, :thread_name => thread_name }
11
+ end
12
+
13
+ subject(:scheduler) { LogStash::PluginMixins::Jdbc::Scheduler.new(opts) }
14
+
15
+ after { scheduler.stop(:wait) }
16
+
17
+ it "sets scheduler thread name" do
18
+ expect( scheduler.thread.name ).to include thread_name
19
+ end
20
+
21
+ context 'cron schedule' do
22
+
23
+ before do
24
+ scheduler.schedule_cron('* * * * * *') { sleep 1.25 } # every second
25
+ end
26
+
27
+ it "sets worker thread names" do
28
+ sleep 3.0
29
+ threads = scheduler.work_threads
30
+ threads.sort! { |t1, t2| (t1.name || '') <=> (t2.name || '') }
31
+
32
+ expect( threads.size ).to eql 2
33
+ expect( threads.first.name ).to eql "#{thread_name}_worker-00"
34
+ expect( threads.last.name ).to eql "#{thread_name}_worker-01"
35
+ end
36
+
37
+ end
38
+
39
+ context 'every 1s' do
40
+
41
+ before do
42
+ scheduler.schedule_in('1s') { raise 'TEST' } # every second
43
+ end
44
+
45
+ it "logs errors handled" do
46
+ expect( scheduler.logger ).to receive(:error).with /Scheduler intercepted an error/, hash_including(:message => 'TEST')
47
+ sleep 1.5
48
+ end
49
+
50
+ end
51
+
52
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-integration-jdbc
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.1
4
+ version: 5.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-22 00:00:00.000000000 Z
11
+ date: 2022-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -131,17 +131,17 @@ dependencies:
131
131
  - !ruby/object:Gem::Dependency
132
132
  requirement: !ruby/object:Gem::Requirement
133
133
  requirements:
134
- - - "<"
134
+ - - "~>"
135
135
  - !ruby/object:Gem::Version
136
- version: '3.5'
136
+ version: 3.0.9
137
137
  name: rufus-scheduler
138
138
  prerelease: false
139
139
  type: :runtime
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
- - - "<"
142
+ - - "~>"
143
143
  - !ruby/object:Gem::Version
144
- version: '3.5'
144
+ version: 3.0.9
145
145
  - !ruby/object:Gem::Dependency
146
146
  requirement: !ruby/object:Gem::Requirement
147
147
  requirements:
@@ -278,6 +278,7 @@ files:
278
278
  - lib/logstash/plugin_mixins/jdbc/checked_count_logger.rb
279
279
  - lib/logstash/plugin_mixins/jdbc/common.rb
280
280
  - lib/logstash/plugin_mixins/jdbc/jdbc.rb
281
+ - lib/logstash/plugin_mixins/jdbc/scheduler.rb
281
282
  - lib/logstash/plugin_mixins/jdbc/statement_handler.rb
282
283
  - lib/logstash/plugin_mixins/jdbc/value_tracking.rb
283
284
  - lib/logstash/plugin_mixins/jdbc_streaming.rb
@@ -306,6 +307,7 @@ files:
306
307
  - spec/helpers/derbyrun.jar
307
308
  - spec/inputs/integration/integ_spec.rb
308
309
  - spec/inputs/jdbc_spec.rb
310
+ - spec/plugin_mixins/jdbc/scheduler_spec.rb
309
311
  - spec/plugin_mixins/jdbc_streaming/parameter_handler_spec.rb
310
312
  - vendor/jar-dependencies/org/apache/derby/derby/10.14.1.0/derby-10.14.1.0.jar
311
313
  - vendor/jar-dependencies/org/apache/derby/derbyclient/10.14.1.0/derbyclient-10.14.1.0.jar
@@ -358,4 +360,5 @@ test_files:
358
360
  - spec/helpers/derbyrun.jar
359
361
  - spec/inputs/integration/integ_spec.rb
360
362
  - spec/inputs/jdbc_spec.rb
363
+ - spec/plugin_mixins/jdbc/scheduler_spec.rb
361
364
  - spec/plugin_mixins/jdbc_streaming/parameter_handler_spec.rb