fluent-plugin-pgjson 0.0.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.
- data/.gitignore +11 -0
- data/Gemfile +4 -0
- data/LICENSE +3 -0
- data/README.md +69 -0
- data/Rakefile +11 -0
- data/example.conf +16 -0
- data/fluent-plugin-pgjson.gemspec +20 -0
- data/lib/fluent/plugin/out_pgjson.rb +89 -0
- data/test/helper.rb +27 -0
- data/test/plugin/test_out.rb +46 -0
- metadata +90 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
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
data/example.conf
ADDED
@@ -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:
|