logstash-integration-jdbc 5.2.1 → 5.2.2

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 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