22 Commits

Author SHA1 Message Date
Karl Southern
8e73958359 Release 5.3.0 2017-11-08 14:09:09 +00:00
Karl Southern
f48c12a8da Bumps Vagrant env. Bumps jar deps. Bumps version number, ready for tagging after tests 2017-11-08 13:45:29 +00:00
Karl Southern
7a2996e985 Fix the broken test 2017-11-08 13:24:23 +00:00
Karl
4c04b8c24d Update jdbc_derby_spec.rb 2017-11-08 13:17:55 +00:00
Karl
fe982c95aa Update jdbc_spec_helper.rb 2017-11-08 13:17:36 +00:00
Karl
d1a733d195 Update jdbc.rb
Provisionally adds whole event encoding. Attempts to give an escape plan for users who may have the same key in their event data (to preserve backwards compatibility this is disabled by default). Address #83

Also adds provisional support for BigDecimal. This is untested.
2017-11-08 13:06:02 +00:00
Karl
21217f7b03 Update THANKS.md
Adds mlkmhd
2017-11-08 12:49:11 +00:00
Karl
2bdb75f1b7 Merge pull request #97 from mlkmhd/master
log event instead of insert query
2017-11-08 12:48:45 +00:00
Karl
6b5398b152 Update jdbc.rb
Update plugin so that the max_pool_size matches documentation.
2017-11-08 12:47:55 +00:00
Your Name
daebe44f32 add event in jdbc exception log instead of statement query. because some jdbc drivers (like oracle jdbc) not implemented toString() method in PreparedStatement class and it print java object hashcode instead of actual query. but in some jdbc implemention like postgresql and mysql and ... this has no problem 2017-10-23 11:24:28 +03:30
Karl
079c3a6c78 Merge pull request #96 from mlkmhd/master
Adding more sql exception detail in log
2017-10-19 09:56:21 +01:00
Your Name
3804eb59d2 adding more sql exception detail in log 2017-10-18 12:41:14 +03:30
Karl
ef6ed66cdd Update THANKS.md 2017-04-12 12:44:08 +01:00
Karl
147cd3d67b Create THANKS.md 2017-04-12 12:43:08 +01:00
Karl
6affac0a0c Update sql-server.md
Add a with thanks.
2017-04-12 12:35:56 +01:00
Karl
508c769650 Merge pull request #81 from MassimoSporchia/master
Added new example and driver_jar_path parameter
2017-04-12 12:35:00 +01:00
Massimo Sporchia
d36d659e16 Added new example and driver_jar_path parameter
Maybe it's just me, but I kept wondering how to add static strings.
Added the driver_jar_path, just in case
2017-04-12 12:59:15 +02:00
Karl Southern
51a04faca3 Fix JDK issue with backports. Bump version 2017-04-09 09:40:49 +01:00
Karl Southern
cdd88fe322 Adds JSON support with non-sprintf syntax 2017-04-09 09:17:05 +01:00
Karl
e74d67b477 Update CHANGELOG.md 2017-04-01 12:17:42 +01:00
Karl Southern
710791c3aa Initial commit for 5.2.0 - addresses HikariCP logging issues 2017-04-01 12:01:27 +01:00
Karl
ccb30c7edd Fix #71 2017-01-25 19:34:56 +00:00
8 changed files with 84 additions and 24 deletions

View File

@@ -1,6 +1,13 @@
# Change Log # Change Log
All notable changes to this project will be documented in this file, from 0.2.0. All notable changes to this project will be documented in this file, from 0.2.0.
## [5.2.1] - 2017-04-09
- Adds Array and Hash to_json support for non-sprintf syntax
## [5.2.0] - 2017-04-01
- Upgrades HikariCP to latest
- Fixes HikariCP logging integration issues
## [5.1.0] - 2016-12-17 ## [5.1.0] - 2016-12-17
- phoenix-thin fixes for issue #60 - phoenix-thin fixes for issue #60

18
THANKS.md Normal file
View File

@@ -0,0 +1,18 @@
logstash-output-jdbc is a project originally created by Karl Southern
(the_angry_angel), but there are a number of people that have contributed
or implemented key features over time. We do our best to keep this list
up-to-date, but you can also have a look at the nice contributor graphs
produced by GitHub: https://github.com/theangryangel/logstash-output-jdbc/graphs/contributors
* [hordijk](https://github.com/hordijk)
* [dmitryakadiamond](https://github.com/dmitryakadiamond)
* [MassimoSporchia](https://github.com/MassimoSporchia)
* [ebuildy](https://github.com/ebuildy)
* [kushtrimjunuzi](https://github.com/kushtrimjunuzi)
* [josemazo](https://github.com/josemazo)
* [aceoliver](https://github.com/aceoliver)
* [roflmao](https://github.com/roflmao)
* [onesuper](https://github.com/onesuper)
* [phr0gz](https://github.com/phr0gz)
* [jMonsinjon](https://github.com/jMonsinjon)
* [mlkmhd](https://github.com/mlkmhd)

17
Vagrantfile vendored
View File

@@ -1,20 +1,19 @@
# -*- mode: ruby -*- # -*- mode: ruby -*-
# vi: set ft=ruby : # vi: set ft=ruby :
JRUBY_VERSION = "jruby-1.7"
Vagrant.configure(2) do |config| Vagrant.configure(2) do |config|
config.vm.define "debian" do |deb| config.vm.define "debian" do |deb|
deb.vm.box = 'debian/jessie64' deb.vm.box = 'debian/stretch64'
deb.vm.synced_folder '.', '/vagrant', type: :virtualbox deb.vm.synced_folder '.', '/vagrant', type: :virtualbox
deb.vm.provision 'shell', inline: <<-EOP deb.vm.provision 'shell', inline: <<-EOP
echo "deb http://ftp.debian.org/debian jessie-backports main" | tee --append /etc/apt/sources.list > /dev/null
sed -i 's/main/main contrib non-free/g' /etc/apt/sources.list
apt-get update apt-get update
apt-get remove openjdk-7-jre-headless -y -q apt-get install openjdk-8-jre ca-certificates-java git curl -y -q
apt-get install git openjdk-8-jre curl -y -q curl -sSL https://rvm.io/mpapis.asc | sudo gpg --import -
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 curl -sSL https://get.rvm.io | bash -s stable --ruby=#{JRUBY_VERSION}
curl -sSL https://get.rvm.io | bash -s stable --ruby=jruby-1.7
usermod -a -G rvm vagrant usermod -a -G rvm vagrant
EOP EOP
end end
@@ -27,8 +26,8 @@ Vagrant.configure(2) do |config|
centos.vm.provision 'shell', inline: <<-EOP centos.vm.provision 'shell', inline: <<-EOP
yum update yum update
yum install java-1.7.0-openjdk yum install java-1.7.0-openjdk
gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 curl -sSL https://rvm.io/mpapis.asc | sudo gpg --import -
curl -sSL https://get.rvm.io | bash -s stable --ruby=jruby-1.7 curl -sSL https://get.rvm.io | bash -s stable --ruby=#{JRUBY_VERSION}
usermod -a -G rvm vagrant usermod -a -G rvm vagrant
EOP EOP
end end

View File

@@ -8,8 +8,25 @@ input
} }
output { output {
jdbc { jdbc {
driver_jar_path => '/opt/sqljdbc42.jar'
connection_string => "jdbc:sqlserver://server:1433;databaseName=databasename;user=username;password=password" connection_string => "jdbc:sqlserver://server:1433;databaseName=databasename;user=username;password=password"
statement => [ "INSERT INTO log (host, timestamp, message) VALUES(?, ?, ?)", "host", "@timestamp", "message" ] statement => [ "INSERT INTO log (host, timestamp, message) VALUES(?, ?, ?)", "host", "@timestamp", "message" ]
} }
}
```
Another example, with mixed static strings and parameters, with thanks to [@MassimoSporchia](https://github.com/MassimoSporchia)
```
input
{
stdin { }
}
output {
jdbc {
driver_jar_path => '/opt/sqljdbc42.jar'
connection_string => "jdbc:sqlserver://server:1433;databaseName=databasename;user=username;password=password"
statement => [ "INSERT INTO log (host, timestamp, message, comment) VALUES(?, ?, ?, 'static string')", "host", "@timestamp", "message" ]
}
} }
``` ```

View File

@@ -5,6 +5,8 @@ require 'concurrent'
require 'stud/interval' require 'stud/interval'
require 'java' require 'java'
require 'logstash-output-jdbc_jars' require 'logstash-output-jdbc_jars'
require 'json'
require 'bigdecimal'
# Write events to a SQL engine, using JDBC. # Write events to a SQL engine, using JDBC.
# #
@@ -63,7 +65,7 @@ class LogStash::Outputs::Jdbc < LogStash::Outputs::Base
config :unsafe_statement, validate: :boolean, default: false config :unsafe_statement, validate: :boolean, default: false
# Number of connections in the pool to maintain # Number of connections in the pool to maintain
config :max_pool_size, validate: :number, default: 24 config :max_pool_size, validate: :number, default: 5
# Connection timeout # Connection timeout
config :connection_timeout, validate: :number, default: 10000 config :connection_timeout, validate: :number, default: 10000
@@ -98,6 +100,12 @@ class LogStash::Outputs::Jdbc < LogStash::Outputs::Base
config :max_repeat_exceptions, obsolete: 'This has been replaced by max_flush_exceptions - which behaves slightly differently. Please check the documentation.' config :max_repeat_exceptions, obsolete: 'This has been replaced by max_flush_exceptions - which behaves slightly differently. Please check the documentation.'
config :max_repeat_exceptions_time, obsolete: 'This is no longer required' config :max_repeat_exceptions_time, obsolete: 'This is no longer required'
config :idle_flush_time, obsolete: 'No longer necessary under Logstash v5' config :idle_flush_time, obsolete: 'No longer necessary under Logstash v5'
# Allows the whole event to be converted to JSON
config :enable_event_as_json_keyword, validate: :boolean, default: false
# The magic key used to convert the whole event to JSON. If you need this, and you have the default in your events, you can use this to change your magic keyword.
config :event_as_json_keyword, validate: :string, default: '@event'
def register def register
@logger.info('JDBC - Starting up') @logger.info('JDBC - Starting up')
@@ -200,7 +208,7 @@ class LogStash::Outputs::Jdbc < LogStash::Outputs::Base
begin begin
connection = @pool.getConnection connection = @pool.getConnection
rescue => e rescue => e
log_jdbc_exception(e, true) log_jdbc_exception(e, true, nil)
# If a connection is not available, then the server has gone away # If a connection is not available, then the server has gone away
# We're not counting that towards our retry count. # We're not counting that towards our retry count.
return events, false return events, false
@@ -214,7 +222,7 @@ class LogStash::Outputs::Jdbc < LogStash::Outputs::Base
statement = add_statement_event_params(statement, event) if @statement.length > 1 statement = add_statement_event_params(statement, event) if @statement.length > 1
statement.execute statement.execute
rescue => e rescue => e
if retry_exception?(e) if retry_exception?(e, event.to_json())
events_to_retry.push(event) events_to_retry.push(event)
end end
ensure ensure
@@ -261,7 +269,9 @@ class LogStash::Outputs::Jdbc < LogStash::Outputs::Base
def add_statement_event_params(statement, event) def add_statement_event_params(statement, event)
@statement[1..-1].each_with_index do |i, idx| @statement[1..-1].each_with_index do |i, idx|
if i.is_a? String if @enable_event_as_json_keyword and i.is_a? String and i == @event_as_json_keyword
value = event.to_json
elsif i.is_a? String
value = event.get(i) value = event.get(i)
if value.nil? and i =~ /%\{/ if value.nil? and i =~ /%\{/
value = event.sprintf(i) value = event.sprintf(i)
@@ -289,10 +299,14 @@ class LogStash::Outputs::Jdbc < LogStash::Outputs::Base
else else
statement.setInt(idx + 1, value) statement.setInt(idx + 1, value)
end end
when BigDecimal
statement.setBigDecimal(idx + 1, value)
when Float when Float
statement.setFloat(idx + 1, value) statement.setFloat(idx + 1, value)
when String when String
statement.setString(idx + 1, value) statement.setString(idx + 1, value)
when Array, Hash
statement.setString(idx + 1, value.to_json)
when true, false when true, false
statement.setBoolean(idx + 1, value) statement.setBoolean(idx + 1, value)
else else
@@ -303,16 +317,21 @@ class LogStash::Outputs::Jdbc < LogStash::Outputs::Base
statement statement
end end
def retry_exception?(exception) def retry_exception?(exception, event)
retrying = (exception.respond_to? 'getSQLState' and (RETRYABLE_SQLSTATE_CLASSES.include?(exception.getSQLState.to_s[0,2]) or @retry_sql_states.include?(exception.getSQLState))) retrying = (exception.respond_to? 'getSQLState' and (RETRYABLE_SQLSTATE_CLASSES.include?(exception.getSQLState.to_s[0,2]) or @retry_sql_states.include?(exception.getSQLState)))
log_jdbc_exception(exception, retrying) log_jdbc_exception(exception, retrying, event)
retrying retrying
end end
def log_jdbc_exception(exception, retrying) def log_jdbc_exception(exception, retrying, event)
current_exception = exception current_exception = exception
log_text = 'JDBC - Exception. ' + (retrying ? 'Retrying' : 'Not retrying') + '.' log_text = 'JDBC - Exception. ' + (retrying ? 'Retrying' : 'Not retrying') + '.'
if(event != nil)
log_text += ' event: "' + event + '".'
end
log_method = (retrying ? 'warn' : 'error') log_method = (retrying ? 'warn' : 'error')
loop do loop do

View File

@@ -1,6 +1,6 @@
Gem::Specification.new do |s| Gem::Specification.new do |s|
s.name = 'logstash-output-jdbc' s.name = 'logstash-output-jdbc'
s.version = '5.1.0' s.version = '5.3.0'
s.licenses = ['Apache License (2.0)'] s.licenses = ['Apache License (2.0)']
s.summary = 'This plugin allows you to output to SQL, via JDBC' s.summary = 'This plugin allows you to output to SQL, via JDBC'
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 'logstash-output-jdbc'. This gem is not a stand-alone program" 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 'logstash-output-jdbc'. This gem is not a stand-alone program"
@@ -22,17 +22,17 @@ Gem::Specification.new do |s|
s.metadata = { 'logstash_plugin' => 'true', 'logstash_group' => 'output' } s.metadata = { 'logstash_plugin' => 'true', 'logstash_group' => 'output' }
# Gem dependencies # Gem dependencies
s.add_runtime_dependency 'logstash-core-plugin-api', '>= 1.60', '<= 2.99' s.add_runtime_dependency 'logstash-core-plugin-api', '~> 2'
s.add_runtime_dependency 'stud' s.add_runtime_dependency 'stud'
s.add_runtime_dependency 'logstash-codec-plain' s.add_runtime_dependency 'logstash-codec-plain'
s.requirements << "jar 'com.zaxxer:HikariCP', '2.4.7'" s.requirements << "jar 'com.zaxxer:HikariCP', '2.7.2'"
s.requirements << "jar 'org.slf4j:slf4j-log4j12', '1.7.21'" s.requirements << "jar 'org.apache.logging.log4j:log4j-slf4j-impl', '2.6.2'"
s.add_development_dependency 'jar-dependencies' s.add_development_dependency 'jar-dependencies'
s.add_development_dependency 'ruby-maven', '~> 3.3' s.add_development_dependency 'ruby-maven', '~> 3.3'
s.add_development_dependency 'logstash-devutils' s.add_development_dependency "logstash-devutils", "~> 1.3", ">= 1.3.1"
s.add_development_dependency 'rubocop', '0.41.2' s.add_development_dependency 'rubocop', '0.41.2'
end end

View File

@@ -59,11 +59,11 @@ RSpec.shared_context 'when outputting messages' do
end end
let(:jdbc_create_table) do let(:jdbc_create_table) do
"CREATE table #{jdbc_test_table} (created_at datetime not null, message varchar(512) not null, message_sprintf varchar(512) not null, static_int int not null, static_bit bit not null, static_bigint bigint not null)" "CREATE table #{jdbc_test_table} (created_at datetime not null, message varchar(512) not null, message_sprintf varchar(512) not null, static_int int not null, static_bit bit not null, static_bigint bigint not null, static_float float not null)"
end end
let(:jdbc_statement) do let(:jdbc_statement) do
["insert into #{jdbc_test_table} (created_at, message, message_sprintf, static_int, static_bit, static_bigint) values(?, ?, ?, ?, ?, ?)", '@timestamp', 'message', 'sprintf-%{message}', 1, true, 4000881632477184] ["insert into #{jdbc_test_table} (created_at, message, message_sprintf, static_int, static_bit, static_bigint, static_float) values(?, ?, ?, ?, ?, ?, ?)", '@timestamp', 'message', 'sprintf-%{message}', 1, true, 4000881632477184, 12.1]
end end
let(:systemd_database_service) do let(:systemd_database_service) do

View File

@@ -10,7 +10,7 @@ describe 'logstash-output-jdbc: derby', if: ENV['JDBC_DERBY_JAR'] do
end end
let(:jdbc_create_table) do let(:jdbc_create_table) do
"CREATE table #{jdbc_test_table} (created_at timestamp not null, message varchar(512) not null, message_sprintf varchar(512) not null, static_int int not null, static_bit boolean not null, static_bigint bigint not null)" "CREATE table #{jdbc_test_table} (created_at timestamp not null, message varchar(512) not null, message_sprintf varchar(512) not null, static_int int not null, static_bit boolean not null, static_bigint bigint not null, static_float float not null)"
end end
let(:jdbc_settings) do let(:jdbc_settings) do