fluent-plugin-dynamodb 0.1.5
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/ChangeLog +8 -0
- data/Gemfile +3 -0
- data/README.md +50 -0
- data/Rakefile +14 -0
- data/VERSION +1 -0
- data/fluent-plugin-dynamodb.gemspec +23 -0
- data/lib/fluent/plugin/out_dynamodb.rb +101 -0
- data/test/out_dynamodb.rb +59 -0
- metadata +104 -0
data/ChangeLog
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# Amazon DynamoDB output plugin for Fluent event collector
|
2
|
+
|
3
|
+
##Installation
|
4
|
+
|
5
|
+
$ fluent-gem install fluent-plugin-dynamodb
|
6
|
+
|
7
|
+
##Configuration
|
8
|
+
|
9
|
+
|
10
|
+
###DynamoDB
|
11
|
+
|
12
|
+
First of all, you need to create a table in DynamoDB. It's easy to create via Management Console.
|
13
|
+
|
14
|
+
Specify table name, hash attribute name and throughput as you like. fluent-plugin-dynamodb will load your table schema and write event-stream out to your table.
|
15
|
+
|
16
|
+
*currently supports only table with a primary key which has a string hash-key. (hash and range key is not supported.)*
|
17
|
+
|
18
|
+
### Fluentd
|
19
|
+
|
20
|
+
<match dynamodb.**>
|
21
|
+
type dynamodb
|
22
|
+
aws_key_id AWS_ACCESS_KEY
|
23
|
+
aws_sec_key AWS_SECRET_ACCESS_KEY
|
24
|
+
proxy_uri http://user:password@192.168.0.250:3128/
|
25
|
+
dynamo_db_endpoint dynamodb.ap-northeast-1.amazonaws.com
|
26
|
+
dynamo_db_table access_log
|
27
|
+
</match>
|
28
|
+
|
29
|
+
* **aws\_key\_id (required)** - AWS access key id.
|
30
|
+
* **aws\_sec\_key (required)** - AWS secret key.
|
31
|
+
* **proxy_uri (optional)** - your proxy url.
|
32
|
+
* **dynamo\_db\_endpoint (required)** - end point of dynamodb. see [Regions and Endpoints](http://docs.amazonwebservices.com/general/latest/gr/rande.html#ddb_region)
|
33
|
+
* **dynamo\_db\_table (required)** - table name of dynamodb.
|
34
|
+
|
35
|
+
##TODO
|
36
|
+
|
37
|
+
* auto-create table
|
38
|
+
* tag_mapped
|
39
|
+
* Multiprocessing
|
40
|
+
|
41
|
+
##Copyright
|
42
|
+
|
43
|
+
<table>
|
44
|
+
<tr>
|
45
|
+
<td>Copyright</td><td>Copyright (c) 2012- Takashi Matsuno</td>
|
46
|
+
</tr>
|
47
|
+
<tr>
|
48
|
+
<td>License</td><td>Apache License, Version 2.0</td>
|
49
|
+
</tr>
|
50
|
+
</table>
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
require 'bundler'
|
3
|
+
Bundler::GemHelper.install_tasks
|
4
|
+
|
5
|
+
require 'rake/testtask'
|
6
|
+
|
7
|
+
Rake::TestTask.new(:test) do |test|
|
8
|
+
test.libs << 'lib' << 'test'
|
9
|
+
test.test_files = FileList['test/*.rb']
|
10
|
+
test.verbose = true
|
11
|
+
end
|
12
|
+
|
13
|
+
task :default => [:build]
|
14
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.5
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "fluent-plugin-dynamodb"
|
6
|
+
gem.description = "Amazon DynamoDB output plugin for Fluent event collector"
|
7
|
+
gem.homepage = "https://github.com/fluent/fluent-plugin-dynamodb"
|
8
|
+
gem.summary = gem.description
|
9
|
+
gem.version = File.read("VERSION").strip
|
10
|
+
gem.authors = ["Takashi Matsuno"]
|
11
|
+
gem.email = "g0n5uk3@gmail.com"
|
12
|
+
gem.has_rdoc = false
|
13
|
+
#gem.platform = Gem::Platform::RUBY
|
14
|
+
gem.files = `git ls-files`.split("\n")
|
15
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
gem.require_paths = ['lib']
|
18
|
+
|
19
|
+
gem.add_dependency "fluentd", "~> 0.10.0"
|
20
|
+
gem.add_dependency "aws-sdk", "~> 1.5.2"
|
21
|
+
gem.add_dependency "uuidtools", "~> 2.1.0"
|
22
|
+
gem.add_development_dependency "rake", ">= 0.9.2"
|
23
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module Fluent
|
3
|
+
|
4
|
+
|
5
|
+
class DynamoDBOutput < Fluent::BufferedOutput
|
6
|
+
Fluent::Plugin.register_output('dynamodb', self)
|
7
|
+
|
8
|
+
BATCHWRITE_ITEM_LIMIT = 25
|
9
|
+
BATCHWRITE_CONTENT_SIZE_LIMIT = 1024*1024
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
super
|
13
|
+
require 'aws-sdk'
|
14
|
+
require 'msgpack'
|
15
|
+
require 'time'
|
16
|
+
require 'uuidtools'
|
17
|
+
end
|
18
|
+
|
19
|
+
config_param :aws_key_id, :string
|
20
|
+
config_param :aws_sec_key, :string
|
21
|
+
config_param :proxy_uri, :string, :default => nil
|
22
|
+
config_param :dynamo_db_table, :string
|
23
|
+
config_param :dynamo_db_endpoint, :string, :default => nil
|
24
|
+
config_param :time_format, :string, :default => nil
|
25
|
+
|
26
|
+
def configure(conf)
|
27
|
+
super
|
28
|
+
|
29
|
+
@timef = TimeFormatter.new(@time_format, @localtime)
|
30
|
+
end
|
31
|
+
|
32
|
+
def start
|
33
|
+
super
|
34
|
+
options = {
|
35
|
+
:access_key_id => @aws_key_id,
|
36
|
+
:secret_access_key => @aws_sec_key,
|
37
|
+
:dynamo_db_endpoint => @dynamo_db_endpoint,
|
38
|
+
}
|
39
|
+
options[:proxy_uri] = @proxy_uri if @proxy_uri
|
40
|
+
|
41
|
+
begin
|
42
|
+
restart_session(options)
|
43
|
+
valid_table(@dynamo_db_table)
|
44
|
+
rescue ConfigError => e
|
45
|
+
$log.fatal "ConfigError: Please check your configuration, then restart fluentd. '#{e}'"
|
46
|
+
exit!
|
47
|
+
rescue Exception => e
|
48
|
+
$log.fatal "UnknownError: '#{e}'"
|
49
|
+
exit!
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def restart_session(options)
|
54
|
+
config = AWS.config(options)
|
55
|
+
@batch = AWS::DynamoDB::BatchWrite.new(config)
|
56
|
+
@dynamo_db = AWS::DynamoDB.new(options)
|
57
|
+
end
|
58
|
+
|
59
|
+
def valid_table(table_name)
|
60
|
+
table = @dynamo_db.tables[table_name]
|
61
|
+
table.load_schema
|
62
|
+
raise ConfigError, "Currently composite table is not supported." if table.has_range_key?
|
63
|
+
@hash_key_value = table.hash_key.name
|
64
|
+
end
|
65
|
+
|
66
|
+
def format(tag, time, record)
|
67
|
+
if !record.key?(@hash_key_value)
|
68
|
+
record[@hash_key_value] = UUIDTools::UUID.timestamp_create.to_s
|
69
|
+
end
|
70
|
+
|
71
|
+
[time, record].to_msgpack
|
72
|
+
end
|
73
|
+
|
74
|
+
def write(chunk)
|
75
|
+
records = collect_records(chunk)
|
76
|
+
item_num = item_size = 0
|
77
|
+
records.each {|record|
|
78
|
+
item_num += 1
|
79
|
+
item_size += record.to_json.length # FIXME: heuristic
|
80
|
+
if item_num >= BATCHWRITE_ITEM_LIMIT || item_size >= BATCHWRITE_CONTENT_SIZE_LIMIT
|
81
|
+
@batch.process!
|
82
|
+
item_num = item_size = 0
|
83
|
+
end
|
84
|
+
@batch.put(@dynamo_db_table, [record])
|
85
|
+
}
|
86
|
+
@batch.process!
|
87
|
+
end
|
88
|
+
|
89
|
+
def collect_records(chunk)
|
90
|
+
records = []
|
91
|
+
chunk.msgpack_each { |time, record|
|
92
|
+
record['time'] = @timef.format(time)
|
93
|
+
records << record
|
94
|
+
}
|
95
|
+
records
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'fluent/test'
|
2
|
+
require 'fluent/plugin/out_dynamodb'
|
3
|
+
|
4
|
+
class DynamoDBOutputTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
Fluent::Test.setup
|
7
|
+
end
|
8
|
+
|
9
|
+
CONFIG = %[
|
10
|
+
aws_key_id test_key_id
|
11
|
+
aws_sec_key test_sec_key
|
12
|
+
dynamo_db_table test_table
|
13
|
+
dynamo_db_endpoint test.endpoint
|
14
|
+
utc
|
15
|
+
buffer_type memory
|
16
|
+
]
|
17
|
+
|
18
|
+
def create_driver(conf = CONFIG)
|
19
|
+
Fluent::Test::BufferedOutputTestDriver.new(Fluent::DynamoDBOutput) do
|
20
|
+
def write(chunk)
|
21
|
+
chunk.read
|
22
|
+
end
|
23
|
+
end.configure(conf)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_configure
|
27
|
+
d = create_driver
|
28
|
+
assert_equal 'test_key_id', d.instance.aws_key_id
|
29
|
+
assert_equal 'test_sec_key', d.instance.aws_sec_key
|
30
|
+
assert_equal 'test_table', d.instance.dynamo_db_table
|
31
|
+
assert_equal 'test.endpoint', d.instance.dynamo_db_endpoint
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_format
|
35
|
+
d = create_driver
|
36
|
+
|
37
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
38
|
+
d.emit({"a"=>1}, time)
|
39
|
+
d.emit({"a"=>2}, time)
|
40
|
+
|
41
|
+
d.expect_format([time, {'a' => 1}].to_msgpack)
|
42
|
+
d.expect_format([time, {'a' => 2}].to_msgpack)
|
43
|
+
|
44
|
+
d.run
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_write
|
48
|
+
d = create_driver
|
49
|
+
|
50
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
51
|
+
d.emit({"a"=>1}, time)
|
52
|
+
d.emit({"a"=>2}, time)
|
53
|
+
|
54
|
+
data = d.run
|
55
|
+
|
56
|
+
assert_equal [time, {'a' => 1}].to_msgpack + [time, {'a' => 2}].to_msgpack, data
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fluent-plugin-dynamodb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.5
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Takashi Matsuno
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2012-06-10 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: fluentd
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.10.0
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: aws-sdk
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 1.5.2
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: uuidtools
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.1.0
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id003
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rake
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 0.9.2
|
57
|
+
type: :development
|
58
|
+
version_requirements: *id004
|
59
|
+
description: Amazon DynamoDB output plugin for Fluent event collector
|
60
|
+
email: g0n5uk3@gmail.com
|
61
|
+
executables: []
|
62
|
+
|
63
|
+
extensions: []
|
64
|
+
|
65
|
+
extra_rdoc_files: []
|
66
|
+
|
67
|
+
files:
|
68
|
+
- ChangeLog
|
69
|
+
- Gemfile
|
70
|
+
- README.md
|
71
|
+
- Rakefile
|
72
|
+
- VERSION
|
73
|
+
- fluent-plugin-dynamodb.gemspec
|
74
|
+
- lib/fluent/plugin/out_dynamodb.rb
|
75
|
+
- test/out_dynamodb.rb
|
76
|
+
homepage: https://github.com/fluent/fluent-plugin-dynamodb
|
77
|
+
licenses: []
|
78
|
+
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: "0"
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: "0"
|
96
|
+
requirements: []
|
97
|
+
|
98
|
+
rubyforge_project:
|
99
|
+
rubygems_version: 1.8.10
|
100
|
+
signing_key:
|
101
|
+
specification_version: 3
|
102
|
+
summary: Amazon DynamoDB output plugin for Fluent event collector
|
103
|
+
test_files:
|
104
|
+
- test/out_dynamodb.rb
|