logstash-integration-jdbc 5.4.11 → 5.5.1

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: 7604bb8967c9d63f585d14622ab18b70bc0d9e9b34e43bca6b6c59c9d05a6b76
4
- data.tar.gz: 2e9d142376d12bbd1313142e79174d540d53e098e481330262e784c8177e4898
3
+ metadata.gz: 4ba7e1b0f0a043e0b58ff727a16decd9f5fb63ac5cc68a1c935af2d59c0235a3
4
+ data.tar.gz: fa9178574ca2acce0b1f8f0bab0823649e202af2d3911985fb9368a8c3f60c11
5
5
  SHA512:
6
- metadata.gz: 165749e33fed7d98b9635f6a1d74cdb05623563a3942d34c093ef761cd8e4f4784e6eb467a699909e5420ceef8fb4779c00e1b154845838052aa278a592ddc2a
7
- data.tar.gz: b9a4e7822ea60c3dde25edd6a1a6e72837069a993046a050a05aa32e92172d4689624df12e85c31b79f62c40fd0f45f98700e07a678a7ea2656d9730f2f14a8e
6
+ metadata.gz: 681d44e0f888cd9c7e87cd33551aa62c5aba9524e714af9db334286b41947c0683dcda15b3fb0e8a8b903976599e261dd0c805666db977ed16f6a145f966c507
7
+ data.tar.gz: d7fb56739d0e2db3751b2956f0e47dfc585173ff7703cb5b9c0d52b438b10358a6678c72267fa3103cd92ef6137da5376c7398bbe89289a665b7a224a2e9a2d8
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 5.5.1
2
+ - Document `statement_retry_attempts` and `statement_retry_attempts_wait_time` options
3
+
4
+ ## 5.5.0
5
+ - Feat: add support for SQL `DATE` columns to jdbc static and streaming filters [#171](https://github.com/logstash-plugins/logstash-integration-jdbc/pull/171)
6
+
1
7
  ## 5.4.11
2
8
  - Fixes an issue in which any one instance of a JDBC input plugin using `jdbc_default_timezone` changes the behaviour of plugin instances that do _not_ use `jdbc_default_timezone`, ensuring that timezone offsets remain consistent for each instance of the plugin _as configured_ [#151](https://github.com/logstash-plugins/logstash-integration-jdbc/pull/151)
3
9
  - Fixes an exception that could occur while reloading `jdbc_static` databases when the underlying connection to the remote has been broken [#165](https://github.com/logstash-plugins/logstash-integration-jdbc/pull/165)
@@ -238,6 +238,8 @@ This plugin supports the following configuration options plus the <<plugins-{typ
238
238
  | <<plugins-{type}s-{plugin}-sql_log_level>> |<<string,string>>, one of `["fatal", "error", "warn", "info", "debug"]`|No
239
239
  | <<plugins-{type}s-{plugin}-statement>> |<<string,string>>|No
240
240
  | <<plugins-{type}s-{plugin}-statement_filepath>> |a valid filesystem path|No
241
+ | <<plugins-{type}s-{plugin}-statement_retry_attempts>> |<<number,number>>|No
242
+ | <<plugins-{type}s-{plugin}-statement_retry_attempts_wait_time>> |<<number,number>>|No
241
243
  | <<plugins-{type}s-{plugin}-target>> | {logstash-ref}/field-references-deepdive.html[field reference] | No
242
244
  | <<plugins-{type}s-{plugin}-tracking_column>> |<<string,string>>|No
243
245
  | <<plugins-{type}s-{plugin}-tracking_column_type>> |<<string,string>>, one of `["numeric", "timestamp"]`|No
@@ -623,6 +625,22 @@ with the `parameters` setting.
623
625
 
624
626
  Path of file containing statement to execute
625
627
 
628
+ [id="plugins-{type}s-{plugin}-statement_retry_attempts"]
629
+ ===== `statement_retry_attempts`
630
+
631
+ * Value type is <<number,number>>
632
+ * Default value is `1`
633
+
634
+ Maximum number of times to try executing a statement.
635
+
636
+ [id="plugins-{type}s-{plugin}-statement_retry_attempts_wait_time"]
637
+ ===== `statement_retry_attempts_wait_time`
638
+
639
+ * Value type is <<number,number>>
640
+ * Default value is `0.5`
641
+
642
+ Number of seconds to sleep between statement execution attempts.
643
+
626
644
  [id="plugins-{type}s-{plugin}-target"]
627
645
  ===== `target`
628
646
 
@@ -1,10 +1,12 @@
1
1
  # encoding: utf-8
2
2
  require_relative "lookup_result"
3
3
  require "logstash/util/loggable"
4
+ require "logstash/plugin_mixins/jdbc/value_handler"
4
5
 
5
6
  module LogStash module Filters module Jdbc
6
7
  class Lookup
7
8
  include LogStash::Util::Loggable
9
+ include LogStash::PluginMixins::Jdbc::ValueHandler
8
10
 
9
11
  class Sprintfier
10
12
  def initialize(param)
@@ -134,15 +136,13 @@ module LogStash module Filters module Jdbc
134
136
 
135
137
  def load_data_from_local(local, query, params, result)
136
138
  local.fetch(query, params).each do |row|
137
- stringified = row.inject({}){|hash,(k,v)| hash[k.to_s] = v; hash} #Stringify row keys
138
- result.push(stringified)
139
+ result.push(extract_values_from(row))
139
140
  end
140
141
  end
141
142
 
142
143
  def load_data_from_prepared(_local, _query, params, result)
143
144
  @prepared_statement.call(params).each do |row|
144
- stringified = row.inject({}){|hash,(k,v)| hash[k.to_s] = v; hash} #Stringify row keys
145
- result.push(stringified)
145
+ result.push(extract_values_from(row))
146
146
  end
147
147
  end
148
148
 
@@ -6,6 +6,7 @@ require "date"
6
6
  require_relative "value_tracking"
7
7
  require_relative "timezone_proxy"
8
8
  require_relative "statement_handler"
9
+ require_relative "value_handler"
9
10
 
10
11
  java_import java.util.concurrent.locks.ReentrantLock
11
12
 
@@ -13,6 +14,7 @@ java_import java.util.concurrent.locks.ReentrantLock
13
14
  # for potential reuse in other plugins (input/output)
14
15
  module LogStash module PluginMixins module Jdbc
15
16
  module Jdbc
17
+ include LogStash::PluginMixins::Jdbc::ValueHandler
16
18
  # This method is called when someone includes this module
17
19
  def self.included(base)
18
20
  # Add these methods to the 'base' given.
@@ -252,25 +254,6 @@ module LogStash module PluginMixins module Jdbc
252
254
  row[@tracking_column.to_sym]
253
255
  end
254
256
  end
255
-
256
- private
257
- #Stringify row keys and decorate values when necessary
258
- def extract_values_from(row)
259
- Hash[row.map { |k, v| [k.to_s, decorate_value(v)] }]
260
- end
261
-
262
- private
263
- def decorate_value(value)
264
- case value
265
- when Time
266
- # transform it to LogStash::Timestamp as required by LS
267
- LogStash::Timestamp.new(value)
268
- when Date, DateTime
269
- LogStash::Timestamp.new(value.to_time)
270
- else
271
- value
272
- end
273
- end
274
257
  end
275
258
  end end end
276
259
 
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ require "time"
3
+ require "date"
4
+
5
+ module LogStash module PluginMixins module Jdbc
6
+ # Provides functions to extract the row's values, ensuring column types
7
+ # are properly decorated to become coercible to a LogStash::Event.
8
+ module ValueHandler
9
+ # Stringify the row keys and decorate values when necessary
10
+ def extract_values_from(row)
11
+ Hash[row.map { |k, v| [k.to_s, decorate_value(v)] }]
12
+ end
13
+
14
+ # Decorate the value so it can be used as a LogStash::Event field
15
+ def decorate_value(value)
16
+ case value
17
+ when Date, DateTime
18
+ value.to_time
19
+ else
20
+ value
21
+ end
22
+ end
23
+ end
24
+ end end end
@@ -1,5 +1,6 @@
1
1
  # encoding: utf-8
2
2
  require "logstash/util/loggable"
3
+ require "logstash/plugin_mixins/jdbc/value_handler"
3
4
 
4
5
  module LogStash module PluginMixins module JdbcStreaming
5
6
  # so as to not clash with the class of the same name and function in the jdbc input
@@ -7,6 +8,8 @@ module LogStash module PluginMixins module JdbcStreaming
7
8
  # this duplication can be removed in a universal plugin
8
9
 
9
10
  class StatementHandler
11
+ include LogStash::PluginMixins::Jdbc::ValueHandler
12
+
10
13
  def self.build_statement_handler(plugin)
11
14
  klass = plugin.use_prepared_statements ? PreparedStatementHandler : NormalStatementHandler
12
15
  klass.new(plugin)
@@ -86,7 +89,7 @@ module LogStash module PluginMixins module JdbcStreaming
86
89
  def execute_extract_records(db, params, result)
87
90
  dataset = db[statement, params] # returns a Sequel dataset
88
91
  dataset.all do |row|
89
- result.push row.inject({}){|hash,(k,v)| hash[k.to_s] = v; hash} # Stringify row keys
92
+ result.push extract_values_from(row)
90
93
  end
91
94
  end
92
95
 
@@ -113,7 +116,7 @@ module LogStash module PluginMixins module JdbcStreaming
113
116
  def execute_extract_records(db, params, result)
114
117
  records = db.call(name, params) # returns an array of hashes
115
118
  records.each do |row|
116
- result.push row.inject({}){|hash,(k,v)| hash[k.to_s] = v; hash} #Stringify row keys
119
+ result.push extract_values_from(row)
117
120
  end
118
121
  end
119
122
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-integration-jdbc'
3
- s.version = '5.4.11'
3
+ s.version = '5.5.1'
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"
@@ -23,7 +23,6 @@ Gem::Specification.new do |s|
23
23
  }
24
24
 
25
25
  # Gem dependencies
26
- s.add_development_dependency 'jar-dependencies', '~> 0.3'
27
26
 
28
27
  s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
29
28
  # Restrict use of this plugin to versions of Logstash where support for integration plugins is present.
@@ -116,6 +116,45 @@ module LogStash module Filters
116
116
  plugin.filter(event)
117
117
  expect(event.get("server")).to eq([{"ip"=>"10.3.1.1", "name"=>"mv-server-1", "location"=>"MV-9-6-4"}])
118
118
  end
119
+
120
+ context 'and record with temporal columns' do
121
+ let(:loader_statement) { "SELECT ip, name, location, entry_date, entry_time, timestamp FROM reference_table" }
122
+ let(:local_db_objects) do
123
+ [
124
+ {
125
+ "name" => "servers",
126
+ "columns" => [
127
+ %w[ip varchar(64)],
128
+ %w[name varchar(64)],
129
+ %w[location varchar(64)],
130
+ %w[entry_date date],
131
+ %w[entry_time time],
132
+ %w[timestamp timestamp]
133
+ ]
134
+ },
135
+ ]
136
+ end
137
+
138
+ before(:each) { plugin.register }
139
+
140
+ subject { event.get("server").first }
141
+
142
+ it "maps the DATE to a Logstash Timestamp" do
143
+ plugin.filter(event)
144
+ expect(subject['entry_date']).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1)))
145
+ end
146
+
147
+ it "maps the TIME field to a Logstash Timestamp" do
148
+ plugin.filter(event)
149
+ now = DateTime.now
150
+ expect(subject['entry_time']).to eq(LogStash::Timestamp.new(Time.new(now.year, now.month, now.day, 10, 5, 0)))
151
+ end
152
+
153
+ it "maps the TIMESTAMP to a Logstash Timestamp" do
154
+ plugin.filter(event)
155
+ expect(subject['timestamp']).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1, 1, 2, 3)))
156
+ end
157
+ end
119
158
  end
120
159
 
121
160
  context "under normal conditions when index_columns is not specified" do
@@ -63,7 +63,32 @@ module LogStash module Filters
63
63
  end
64
64
  end
65
65
 
66
- describe "In Prepared Statement mode, found record - uses row" do
66
+ describe 'found record with temporal columns' do
67
+ let(:idx) { 200 }
68
+ let(:statement) { "SELECT entry_date, entry_time, timestamp FROM reference_table WHERE ip = :ip" }
69
+
70
+ before(:each) { plugin.register }
71
+
72
+ subject { event.get("server").first }
73
+
74
+ it "maps the DATE to a Logstash Timestamp" do
75
+ plugin.filter(event)
76
+ expect(subject['entry_date']).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1)))
77
+ end
78
+
79
+ it "maps the TIME field to a Logstash Timestamp" do
80
+ plugin.filter(event)
81
+ now = DateTime.now
82
+ expect(subject['entry_time']).to eq(LogStash::Timestamp.new(Time.new(now.year, now.month, now.day, 10, 5, 0)))
83
+ end
84
+
85
+ it "maps the TIMESTAMP to a Logstash Timestamp" do
86
+ plugin.filter(event)
87
+ expect(subject['timestamp']).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1, 1, 2, 3)))
88
+ end
89
+ end
90
+
91
+ context 'prepared statement mode' do
67
92
  let(:idx) { 200 }
68
93
  let(:statement) { "SELECT name, location FROM reference_table WHERE ip = ?" }
69
94
  let(:settings) do
@@ -82,10 +107,37 @@ module LogStash module Filters
82
107
  "sequel_opts" => {"pool_timeout" => 600}
83
108
  }
84
109
  end
85
- it "fills in the target" do
86
- plugin.filter(event)
87
- expect(event.get("server")).to eq([{"name" => "ldn-server-#{idx}", "location" => "LDN-#{idx}-2-3"}])
88
- expect((event.get("tags") || []) & ["lookup_failed", "default_used_instead"]).to be_empty
110
+
111
+ describe "found record - uses row" do
112
+ it "fills in the target" do
113
+ plugin.filter(event)
114
+ expect(event.get("server")).to eq([{"name" => "ldn-server-#{idx}", "location" => "LDN-#{idx}-2-3"}])
115
+ expect((event.get("tags") || []) & ["lookup_failed", "default_used_instead"]).to be_empty
116
+ end
117
+ end
118
+
119
+ describe 'found record with temporal columns' do
120
+ let(:statement) { "SELECT entry_date, entry_time, timestamp FROM reference_table WHERE ip = ?" }
121
+
122
+ before(:each) { plugin.register }
123
+
124
+ subject { event.get("server").first }
125
+
126
+ it "maps the DATE to a Logstash Timestamp" do
127
+ plugin.filter(event)
128
+ expect(subject['entry_date']).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1)))
129
+ end
130
+
131
+ it "maps the TIME field to a Logstash Timestamp" do
132
+ plugin.filter(event)
133
+ now = DateTime.now
134
+ expect(subject['entry_time']).to eq(LogStash::Timestamp.new(Time.new(now.year, now.month, now.day, 10, 5, 0)))
135
+ end
136
+
137
+ it "maps the TIMESTAMP to a Logstash Timestamp" do
138
+ plugin.filter(event)
139
+ expect(subject['timestamp']).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1, 1, 2, 3)))
140
+ end
89
141
  end
90
142
  end
91
143
 
@@ -66,6 +66,29 @@ describe LogStash::Inputs::Jdbc, :integration => true do
66
66
  expect(event.get('first_name')).to eq('David')
67
67
  end
68
68
  end
69
+
70
+ context 'with temporal columns' do
71
+ let(:settings) do
72
+ super().merge("statement" => 'SELECT ENTRY_DATE, ENTRY_TIME, TIMESTAMP FROM "employee" WHERE EMP_NO = 2')
73
+ end
74
+
75
+ before(:each) { plugin.run(queue) }
76
+
77
+ subject(:event) { queue.pop }
78
+
79
+ it "maps the DATE to a Logstash Timestamp" do
80
+ expect(event.get('entry_date')).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1)))
81
+ end
82
+
83
+ it "maps the TIME field to a Logstash Timestamp" do
84
+ now = DateTime.now
85
+ expect(event.get('entry_time')).to eq(LogStash::Timestamp.new(Time.new(now.year, now.month, now.day, 10, 5, 0)))
86
+ end
87
+
88
+ it "maps the TIMESTAMP to a Logstash Timestamp" do
89
+ expect(event.get('timestamp')).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1, 1, 2, 3)))
90
+ end
91
+ end
69
92
  end
70
93
 
71
94
  context "when supplying a non-existent library" do
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-integration-jdbc
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.4.11
4
+ version: 5.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-23 00:00:00.000000000 Z
11
+ date: 2024-12-03 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- requirement: !ruby/object:Gem::Requirement
15
- requirements:
16
- - - "~>"
17
- - !ruby/object:Gem::Version
18
- version: '0.3'
19
- name: jar-dependencies
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '0.3'
27
13
  - !ruby/object:Gem::Dependency
28
14
  requirement: !ruby/object:Gem::Requirement
29
15
  requirements:
@@ -266,6 +252,7 @@ files:
266
252
  - lib/logstash/plugin_mixins/jdbc/sequel_bootstrap.rb
267
253
  - lib/logstash/plugin_mixins/jdbc/statement_handler.rb
268
254
  - lib/logstash/plugin_mixins/jdbc/timezone_proxy.rb
255
+ - lib/logstash/plugin_mixins/jdbc/value_handler.rb
269
256
  - lib/logstash/plugin_mixins/jdbc/value_tracking.rb
270
257
  - lib/logstash/plugin_mixins/jdbc_streaming.rb
271
258
  - lib/logstash/plugin_mixins/jdbc_streaming/cache_payload.rb