logstash-integration-jdbc 5.4.11 → 5.5.1

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