logstash-integration-jdbc 5.4.0 → 5.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/docs/filter-jdbc_static.asciidoc +14 -2
- data/lib/logstash/inputs/jdbc.rb +14 -3
- data/lib/logstash/plugin_mixins/jdbc/jdbc.rb +18 -17
- data/logstash-integration-jdbc.gemspec +1 -1
- data/spec/inputs/integration/integ_spec.rb +3 -9
- data/spec/inputs/jdbc_spec.rb +29 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c54f1c22363c2d0637b44a2b68a98e22a1b2f07bc68927a4cc9bd6788a6fc009
|
4
|
+
data.tar.gz: 3ea76ee4fcdde152e43af6c0aab53be50dc022a8c31fce8ebac36669370a4875
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d31cef0d20064897337825bcf7ff491d3b64295c47b644d527974f458ac2c8a180d930b84b55fac6601a5f76faa10754b8975af681c4e0718ec2711e08a0d571
|
7
|
+
data.tar.gz: 6434512f2b958b976a12a7c4afe3d584066cb505c4818d8e340e363a7db4327a433785fc9ddfddc6c67eb2d719fc3f518346974760003873250895cb396d36e1
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## 5.4.2
|
2
|
+
- Doc: described default_hash and tag_on_default_use interaction filter plugin [#122](https://github.com/logstash-plugins/logstash-integration-jdbc/pull/122)
|
3
|
+
- Added new settings `statement_retry_attempts` and `statement_retry_attempts_wait_time` for retry of failed sql statement execution [#123](https://github.com/logstash-plugins/logstash-integration-jdbc/pull/123)
|
4
|
+
|
5
|
+
## 5.4.1
|
6
|
+
- Bugfix leak which happened in creating a new Database pool for every query. The pool is now crated on registration and closed on plugin's `stop` [#119](https://github.com/logstash-plugins/logstash-integration-jdbc/pull/119)
|
7
|
+
|
1
8
|
## 5.4.0
|
2
9
|
- Ambiguous Timestamp Support [#92](https://github.com/logstash-plugins/logstash-integration-jdbc/pull/92)
|
3
10
|
- FIX: when encountering an ambiguous timestamp, the JDBC Input no longer crashes
|
@@ -111,10 +111,14 @@ filter {
|
|
111
111
|
query => "SELECT firstname, lastname FROM users WHERE userid = ? AND country = ?"
|
112
112
|
prepared_parameters => ["[loggedin_userid]", "[user_nation]"] <4>
|
113
113
|
target => "user" <5>
|
114
|
+
default_hash => { <6>
|
115
|
+
firstname => nil
|
116
|
+
lastname => nil
|
117
|
+
}
|
114
118
|
}
|
115
119
|
]
|
116
120
|
# using add_field here to add & rename values to the event root
|
117
|
-
add_field => { server_name => "%{[server][0][description]}" } <
|
121
|
+
add_field => { server_name => "%{[server][0][description]}" } <7>
|
118
122
|
add_field => { user_firstname => "%{[user][0][firstname]}" }
|
119
123
|
add_field => { user_lastname => "%{[user][0][lastname]}" }
|
120
124
|
remove_field => ["server", "user"]
|
@@ -127,6 +131,13 @@ filter {
|
|
127
131
|
jdbc_connection_string => "jdbc:postgresql://remotedb:5432/ls_test_2"
|
128
132
|
}
|
129
133
|
}
|
134
|
+
|
135
|
+
output {
|
136
|
+
if "_jdbcstaticdefaultsused" in [tags] {
|
137
|
+
# Print all the not found users
|
138
|
+
stdout { }
|
139
|
+
}
|
140
|
+
}
|
130
141
|
-----
|
131
142
|
<1> Queries an external database to fetch the dataset that will be cached
|
132
143
|
locally.
|
@@ -139,7 +150,8 @@ See <<plugins-{type}s-{plugin}-object_order>>.
|
|
139
150
|
follow the positional ordering.
|
140
151
|
<5> Specifies the event field that will store the looked-up data. If the lookup
|
141
152
|
returns multiple columns, the data is stored as a JSON object within the field.
|
142
|
-
<6>
|
153
|
+
<6> When the user is not found in the database, an event is created using data from the <<plugins-{type}s-{plugin}-local_lookups>> `default hash` setting, and the event is tagged with the list set in <<plugins-{type}s-{plugin}-tag_on_default_use>>.
|
154
|
+
<7> Takes data from the JSON object and stores it in top-level event fields for
|
143
155
|
easier analysis in Kibana.
|
144
156
|
|
145
157
|
Here's a full example:
|
data/lib/logstash/inputs/jdbc.rb
CHANGED
@@ -261,8 +261,6 @@ module LogStash module Inputs class Jdbc < LogStash::Inputs::Base
|
|
261
261
|
end
|
262
262
|
end
|
263
263
|
|
264
|
-
prepare_jdbc_connection
|
265
|
-
|
266
264
|
if @use_column_value
|
267
265
|
# Raise an error if @use_column_value is true, but no @tracking_column is set
|
268
266
|
if @tracking_column.nil?
|
@@ -305,6 +303,20 @@ module LogStash module Inputs class Jdbc < LogStash::Inputs::Base
|
|
305
303
|
converters[encoding] = converter
|
306
304
|
end
|
307
305
|
end
|
306
|
+
|
307
|
+
load_driver
|
308
|
+
begin
|
309
|
+
open_jdbc_connection
|
310
|
+
rescue Sequel::DatabaseConnectionError,
|
311
|
+
Sequel::DatabaseError,
|
312
|
+
Sequel::InvalidValue,
|
313
|
+
Java::JavaSql::SQLException => e
|
314
|
+
details = { exception: e.class, message: e.message }
|
315
|
+
details[:cause] = e.cause.inspect if e.cause
|
316
|
+
details[:backtrace] = e.backtrace if @logger.debug?
|
317
|
+
@logger.warn("Exception when executing JDBC query", details)
|
318
|
+
raise(LogStash::ConfigurationError, "Can't create a connection pool to the database")
|
319
|
+
end
|
308
320
|
end # def register
|
309
321
|
|
310
322
|
# test injection points
|
@@ -317,7 +329,6 @@ module LogStash module Inputs class Jdbc < LogStash::Inputs::Base
|
|
317
329
|
end
|
318
330
|
|
319
331
|
def run(queue)
|
320
|
-
load_driver
|
321
332
|
if @schedule
|
322
333
|
# scheduler input thread name example: "[my-oracle]|input|jdbc|scheduler"
|
323
334
|
scheduler.cron(@schedule) { execute_query(queue) }
|
@@ -104,6 +104,11 @@ module LogStash module PluginMixins module Jdbc
|
|
104
104
|
# Number of seconds to sleep between connection attempts
|
105
105
|
config :connection_retry_attempts_wait_time, :validate => :number, :default => 0.5
|
106
106
|
|
107
|
+
# Maximum number of times to try running statement
|
108
|
+
config :statement_retry_attempts, :validate => :number, :default => 1
|
109
|
+
# Number of seconds to sleep between statement execution
|
110
|
+
config :statement_retry_attempts_wait_time, :validate => :number, :default => 0.5
|
111
|
+
|
107
112
|
# give users the ability to force Sequel application side into using local timezone
|
108
113
|
config :plugin_timezone, :validate => ["local", "utc"], :default => "utc"
|
109
114
|
end
|
@@ -188,31 +193,24 @@ module LogStash module PluginMixins module Jdbc
|
|
188
193
|
end
|
189
194
|
end
|
190
195
|
|
191
|
-
public
|
192
|
-
def prepare_jdbc_connection
|
193
|
-
@connection_lock = ReentrantLock.new
|
194
|
-
end
|
195
|
-
|
196
196
|
public
|
197
197
|
def close_jdbc_connection
|
198
198
|
begin
|
199
199
|
# pipeline restarts can also close the jdbc connection, block until the current executing statement is finished to avoid leaking connections
|
200
200
|
# connections in use won't really get closed
|
201
|
-
@connection_lock.lock
|
202
201
|
@database.disconnect if @database
|
203
202
|
rescue => e
|
204
203
|
@logger.warn("Failed to close connection", :exception => e)
|
205
|
-
ensure
|
206
|
-
@connection_lock.unlock
|
207
204
|
end
|
208
205
|
end
|
209
206
|
|
210
207
|
public
|
211
208
|
def execute_statement
|
212
209
|
success = false
|
210
|
+
retry_attempts = @statement_retry_attempts
|
211
|
+
|
213
212
|
begin
|
214
|
-
|
215
|
-
open_jdbc_connection
|
213
|
+
retry_attempts -= 1
|
216
214
|
sql_last_value = @use_column_value ? @value_tracker.value : Time.now.utc
|
217
215
|
@tracking_column_warning_sent = false
|
218
216
|
@statement_handler.perform_query(@database, @value_tracker.value) do |row|
|
@@ -220,20 +218,23 @@ module LogStash module PluginMixins module Jdbc
|
|
220
218
|
yield extract_values_from(row)
|
221
219
|
end
|
222
220
|
success = true
|
223
|
-
rescue Sequel::
|
224
|
-
Sequel::DatabaseError,
|
225
|
-
Sequel::InvalidValue,
|
226
|
-
Java::JavaSql::SQLException => e
|
221
|
+
rescue Sequel::Error, Java::JavaSql::SQLException => e
|
227
222
|
details = { exception: e.class, message: e.message }
|
228
223
|
details[:cause] = e.cause.inspect if e.cause
|
229
224
|
details[:backtrace] = e.backtrace if @logger.debug?
|
230
225
|
@logger.warn("Exception when executing JDBC query", details)
|
226
|
+
|
227
|
+
if retry_attempts == 0
|
228
|
+
@logger.error("Unable to execute statement. Tried #{@statement_retry_attempts} times.")
|
229
|
+
else
|
230
|
+
@logger.error("Unable to execute statement. Trying again.")
|
231
|
+
sleep(@statement_retry_attempts_wait_time)
|
232
|
+
retry
|
233
|
+
end
|
231
234
|
else
|
232
235
|
@value_tracker.set_value(sql_last_value)
|
233
|
-
ensure
|
234
|
-
close_jdbc_connection
|
235
|
-
@connection_lock.unlock
|
236
236
|
end
|
237
|
+
|
237
238
|
return success
|
238
239
|
end
|
239
240
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-integration-jdbc'
|
3
|
-
s.version = '5.4.
|
3
|
+
s.version = '5.4.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"
|
@@ -76,10 +76,8 @@ describe LogStash::Inputs::Jdbc, :integration => true do
|
|
76
76
|
end
|
77
77
|
|
78
78
|
it "should not register correctly" do
|
79
|
-
plugin.register
|
80
|
-
q = Queue.new
|
81
79
|
expect do
|
82
|
-
plugin.
|
80
|
+
plugin.register
|
83
81
|
end.to raise_error(::LogStash::PluginLoadingError)
|
84
82
|
end
|
85
83
|
end
|
@@ -92,16 +90,13 @@ describe LogStash::Inputs::Jdbc, :integration => true do
|
|
92
90
|
end
|
93
91
|
|
94
92
|
it "log warning msg when plugin run" do
|
95
|
-
plugin.register
|
96
93
|
expect( plugin ).to receive(:log_java_exception)
|
97
94
|
expect(plugin.logger).to receive(:warn).once.with("Exception when executing JDBC query",
|
98
95
|
hash_including(:message => instance_of(String)))
|
99
|
-
|
100
|
-
expect{ plugin.run(q) }.not_to raise_error
|
96
|
+
expect{ plugin.register }.to raise_error(::LogStash::ConfigurationError)
|
101
97
|
end
|
102
98
|
|
103
99
|
it "should log (native) Java driver error" do
|
104
|
-
plugin.register
|
105
100
|
expect( org.apache.logging.log4j.LogManager ).to receive(:getLogger).and_wrap_original do |m, *args|
|
106
101
|
logger = m.call(*args)
|
107
102
|
expect( logger ).to receive(:error) do |_, e|
|
@@ -109,8 +104,7 @@ describe LogStash::Inputs::Jdbc, :integration => true do
|
|
109
104
|
end.and_call_original
|
110
105
|
logger
|
111
106
|
end
|
112
|
-
|
113
|
-
expect{ plugin.run(q) }.not_to raise_error
|
107
|
+
expect{ plugin.register }.to raise_error(::LogStash::ConfigurationError)
|
114
108
|
end
|
115
109
|
end
|
116
110
|
end
|
data/spec/inputs/jdbc_spec.rb
CHANGED
@@ -1352,6 +1352,34 @@ describe LogStash::Inputs::Jdbc do
|
|
1352
1352
|
expect { plugin.register }.to_not raise_error
|
1353
1353
|
plugin.stop
|
1354
1354
|
end
|
1355
|
+
|
1356
|
+
it "does retry when query execution fails" do
|
1357
|
+
mixin_settings['statement_retry_attempts'] = 2
|
1358
|
+
mixin_settings['statement_retry_attempts_wait_time'] = 0.5
|
1359
|
+
queue = Queue.new
|
1360
|
+
plugin.register
|
1361
|
+
|
1362
|
+
handler = plugin.instance_variable_get(:@statement_handler)
|
1363
|
+
allow(handler).to receive(:perform_query).with(instance_of(Sequel::JDBC::Database), instance_of(Time)).and_raise(Sequel::PoolTimeout)
|
1364
|
+
expect(plugin.logger).to receive(:error).with("Unable to execute statement. Trying again.")
|
1365
|
+
expect(plugin.logger).to receive(:error).with("Unable to execute statement. Tried 2 times.")
|
1366
|
+
|
1367
|
+
plugin.run(queue)
|
1368
|
+
plugin.stop
|
1369
|
+
end
|
1370
|
+
|
1371
|
+
it "does not retry when query execution succeeds" do
|
1372
|
+
mixin_settings['connection_retry_attempts'] = 2
|
1373
|
+
queue = Queue.new
|
1374
|
+
plugin.register
|
1375
|
+
|
1376
|
+
handler = plugin.instance_variable_get(:@statement_handler)
|
1377
|
+
allow(handler).to receive(:perform_query).with(instance_of(Sequel::JDBC::Database), instance_of(Time)).and_call_original
|
1378
|
+
expect(plugin.logger).not_to receive(:error)
|
1379
|
+
|
1380
|
+
plugin.run(queue)
|
1381
|
+
plugin.stop
|
1382
|
+
end
|
1355
1383
|
end
|
1356
1384
|
|
1357
1385
|
context "when encoding of some columns need to be changed" do
|
@@ -1565,16 +1593,12 @@ describe LogStash::Inputs::Jdbc do
|
|
1565
1593
|
{ "statement" => "SELECT * from types_table", "jdbc_driver_library" => invalid_driver_jar_path }
|
1566
1594
|
end
|
1567
1595
|
|
1568
|
-
before do
|
1569
|
-
plugin.register
|
1570
|
-
end
|
1571
|
-
|
1572
1596
|
after do
|
1573
1597
|
plugin.stop
|
1574
1598
|
end
|
1575
1599
|
|
1576
1600
|
it "raise a loading error" do
|
1577
|
-
expect { plugin.
|
1601
|
+
expect { plugin.register }.
|
1578
1602
|
to raise_error(LogStash::PluginLoadingError, /unable to load .*? from :jdbc_driver_library, file not readable/)
|
1579
1603
|
end
|
1580
1604
|
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.4.
|
4
|
+
version: 5.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|