fluent-plugin-pgjson 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg
5
+ .DS_Store
6
+ *.tmproj
7
+ tmtags
8
+ *~
9
+ \#*
10
+ .\#*
11
+ *.swp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-pgjson.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,3 @@
1
+ Copyright (c) 2012 OKUNO Akihiro
2
+
3
+ Apache License, Version 2.0
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # Fluent::Plugin::PgJson
2
+
3
+ Output Plugin for PostgreSQL Json Type.
4
+
5
+ <b>Json type is availble in PostgreSQL version over 9.2</b>
6
+
7
+ ## Installation
8
+
9
+ `$ fluent-gem install fluent-plugin-pgjson`
10
+
11
+ ## Schema
12
+
13
+ Specified table must have this schema.
14
+
15
+ |col|type|
16
+ |---|---|
17
+ |{tag_col}|Text|
18
+ |{time_col}|Timestamp WITH TIME ZONE|
19
+ |{record_col}|Json|
20
+
21
+ ### Example
22
+
23
+ ```
24
+ CREATE TABLE fluentd (
25
+ tag Text
26
+ ,time Timestamptz
27
+ ,record Json
28
+ );
29
+ ```
30
+
31
+ ## Configuration
32
+
33
+ ### Example
34
+
35
+ ```
36
+ <match **>
37
+ type pgjson
38
+ host localhost
39
+ port 5432
40
+ database fluentd
41
+ table fluentd
42
+ user postgres
43
+ password postgres
44
+ time_col time
45
+ tag_col tag
46
+ record_col record
47
+ </match>
48
+ ```
49
+
50
+ ### Parameter
51
+
52
+ |parameter|description|default|
53
+ |---|---|---|
54
+ |host|postgres server hostname|localhost|
55
+ |port|postgres server port number|5432|
56
+ |database|database name to which records will be inserted||
57
+ |table|table name to which records will be inserted||
58
+ |user|user name used to connect database|nil|
59
+ |password|password uset to connect database|nil|
60
+ |time_col|column name to insert time|time|
61
+ |tag_col|column name to insert tag|tag|
62
+ |record_col|column name to insert record|record|
63
+
64
+ ## Copyright
65
+
66
+ <table>
67
+ <tr><td>Copyright</td><td>Copyright (c) 2012 OKUNO Akihiro</td></tr>
68
+ <tr><td>License</td><td>Apache License, Version 2.0</td></tr>
69
+ </table>
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => :test
data/example.conf ADDED
@@ -0,0 +1,16 @@
1
+ <source>
2
+ type forward
3
+ </source>
4
+
5
+ <match **>
6
+ type pgjson
7
+ host localhost
8
+ port 5432
9
+ database fluentd
10
+ table fluentd
11
+ user postgres
12
+ password postgres
13
+ time_col time
14
+ tag_col tag
15
+ record_col record
16
+ </match>
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "fluent-plugin-pgjson"
6
+ s.version = "0.0.1"
7
+ s.authors = ["OKUNO Akihiro"]
8
+ s.email = ["okuno.akihiro@gmail.com"]
9
+ s.homepage = "https://github.com/choplin/fluent-plugin-pgjson"
10
+ s.summary = %q{}
11
+ s.description = %q{}
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ s.require_paths = ["lib"]
17
+
18
+ s.add_runtime_dependency "fluentd"
19
+ s.add_runtime_dependency "pg"
20
+ end
@@ -0,0 +1,89 @@
1
+ module Fluent
2
+
3
+ class PgJsonOutput < Fluent::BufferedOutput
4
+ Fluent::Plugin.register_output('pgjson', self)
5
+
6
+ config_param :host , :string , :default => 'localhost'
7
+ config_param :port , :integer , :default => 5432
8
+ config_param :database , :string
9
+ config_param :table , :string
10
+ config_param :user , :string , :default => nil
11
+ config_param :password , :string , :default => nil
12
+ config_param :time_col , :string , :default => 'time'
13
+ config_param :tag_col , :string , :default => 'tag'
14
+ config_param :record_col , :string , :default => 'record'
15
+
16
+
17
+ def initialize
18
+ super
19
+ require 'pg'
20
+ end
21
+
22
+ def configure(conf)
23
+ super
24
+ @stmt_name = 'insert'
25
+ end
26
+
27
+ def start
28
+ super
29
+ init_connection
30
+ end
31
+
32
+ def shutdown
33
+ super
34
+ if !@conn.nil? and !@conn.finished?
35
+ @conn.close()
36
+ end
37
+ end
38
+
39
+ def format(tag, time, record)
40
+ [tag, time, record].to_msgpack
41
+ end
42
+
43
+ def write(chunk)
44
+ begin
45
+ sql = build_sql(chunk)
46
+ @conn.exec(sql)
47
+ rescue
48
+ #TODO
49
+ raise
50
+ end
51
+ end
52
+
53
+ private
54
+ def init_connection
55
+ begin
56
+ @conn = PGconn.new(:dbname => @database, :host => @host, :port => @port, :user => @user, :password => @password)
57
+ @conn.setnonblocking(true)
58
+ rescue
59
+ raise Fluent::ConfigError, "failed to connect PostgreSQL Server at #{@host}:#{@port}"
60
+ end
61
+ end
62
+
63
+ def prepare_statement
64
+ begin
65
+ @conn.prepare(@stmt_name, sql)
66
+ rescue
67
+ #TODO
68
+ raise
69
+ end
70
+ end
71
+
72
+ def build_sql(chunk)
73
+ values = build_values(chunk)
74
+ sql =<<"SQL"
75
+ INSERT INTO #{@table} (#{@tag_col}, #{@time_col}, #{@record_col})
76
+ VALUES #{values};
77
+ SQL
78
+ end
79
+
80
+ def build_values(chunk)
81
+ tmp = []
82
+ chunk.msgpack_each do |tag, time, record|
83
+ tmp << ("("+[tag, Time.at(time), record.to_json].map{|s| @conn.escape_literal(s.to_s)}.join(',')+")")
84
+ end
85
+ tmp.join(',')
86
+ end
87
+ end
88
+
89
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,27 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+
12
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
13
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
14
+ require 'fluent/test'
15
+ unless ENV.has_key?('VERBOSE')
16
+ nulllogger = Object.new
17
+ nulllogger.instance_eval {|obj|
18
+ def method_missing(method, *args)
19
+ # pass
20
+ end
21
+ }
22
+ $log = nulllogger
23
+ end
24
+ require 'fluent/plugin/out_pgjson'
25
+
26
+ class Test::Unit::TestCase
27
+ end
@@ -0,0 +1,46 @@
1
+ require 'helper'
2
+
3
+ class PgJsonOutputTest < Test::Unit::TestCase
4
+ def setup
5
+ Fluent::Test.setup
6
+ end
7
+
8
+ CONFIG = %[
9
+ type pgjson
10
+ host localhost
11
+ port 5432
12
+ database fluentd
13
+ table fluentd
14
+ user postgres
15
+ password postgres
16
+ time_col time
17
+ tag_col tag
18
+ record_col record
19
+ ]
20
+
21
+ def create_driver(conf = CONFIG, tag='test')
22
+ Fluent::Test::BufferedOutputTestDriver.new(Fluent::PgJsonOutput, tag).configure(conf)
23
+ end
24
+
25
+ def test_configure
26
+ d = create_driver
27
+
28
+ assert_equal "localhost", d.instance.host
29
+ assert_equal 5432, d.instance.port
30
+ assert_equal "fluentd", d.instance.database
31
+ assert_equal "fluentd", d.instance.table
32
+ assert_equal "postgres", d.instance.user
33
+ assert_equal "postgres", d.instance.password
34
+ assert_equal "time", d.instance.time_col
35
+ assert_equal "tag", d.instance.tag_col
36
+ assert_equal "record", d.instance.record_col
37
+ end
38
+
39
+ def test_format
40
+ d = create_driver
41
+ end
42
+
43
+ def test_write
44
+ d = create_driver
45
+ end
46
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-pgjson
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - OKUNO Akihiro
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: fluentd
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: pg
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: ''
47
+ email:
48
+ - okuno.akihiro@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - LICENSE
56
+ - README.md
57
+ - Rakefile
58
+ - example.conf
59
+ - fluent-plugin-pgjson.gemspec
60
+ - lib/fluent/plugin/out_pgjson.rb
61
+ - test/helper.rb
62
+ - test/plugin/test_out.rb
63
+ homepage: https://github.com/choplin/fluent-plugin-pgjson
64
+ licenses: []
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 1.8.23
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: ''
87
+ test_files:
88
+ - test/helper.rb
89
+ - test/plugin/test_out.rb
90
+ has_rdoc: