fluent-plugin-kafka 0.0.18 → 0.1.0
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 +4 -4
- data/README.md +28 -1
- data/fluent-plugin-kafka.gemspec +2 -2
- data/lib/fluent/plugin/in_kafka_group.rb +160 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 498665d29438e6b21a3425138b42d0d69fa9bc95
|
4
|
+
data.tar.gz: 20c8b8bc1458035a52aa9492bb83fe4f5beee0d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c5c1ab553c03c001dd80b471d9c6b30a9356750c12e464b232728e54574e4e68a9e9f6f041ea995b1f6a0c3670d96040c2219df3b02e42e4ab93e285c8a302df
|
7
|
+
data.tar.gz: fbfa49c138e08b3dc5a988b932e20e9a33afc993fc7baa6336fd92412f3136bea11a9b42f8d40176eb8b877387545383fe8701af6d9a28202f75f41aa593504a
|
data/README.md
CHANGED
@@ -19,7 +19,7 @@ Or install it yourself as:
|
|
19
19
|
|
20
20
|
## Usage
|
21
21
|
|
22
|
-
### Input plugin
|
22
|
+
### Input plugin (type 'kafka')
|
23
23
|
|
24
24
|
<source>
|
25
25
|
type kafka
|
@@ -64,6 +64,33 @@ Supports a start of processing from the assigned offset for specific topics.
|
|
64
64
|
|
65
65
|
See also [Poseidon::PartitionConsumer](http://www.rubydoc.info/github/bpot/poseidon/Poseidon/PartitionConsumer) for more detailed documentation about Poseidon.
|
66
66
|
|
67
|
+
### Input plugin (type 'kafka_group', supports kafka group)
|
68
|
+
|
69
|
+
<source>
|
70
|
+
type kafka_group
|
71
|
+
brokers <list of broker-host:port, separate with comma, must set>
|
72
|
+
zookeepers <list of broker-host:port, separate with comma, must set>
|
73
|
+
consumer_group <consumer group name, must set>
|
74
|
+
topics <listening topics(separate with comma',')>
|
75
|
+
format <input text type (text|json|ltsv|msgpack)>
|
76
|
+
message_key <key (Optional, for text format only, default is message)>
|
77
|
+
add_prefix <tag prefix (Optional)>
|
78
|
+
add_suffix <tag suffix (Optional)>
|
79
|
+
max_bytes (integer) :default => nil (Use default of Poseidon)
|
80
|
+
max_wait_ms (integer) :default => nil (Use default of Poseidon)
|
81
|
+
min_bytes (integer) :default => nil (Use default of Poseidon)
|
82
|
+
socket_timeout_ms (integer) :default => nil (Use default of Poseidon)
|
83
|
+
</source>
|
84
|
+
|
85
|
+
Supports following Poseidon::PartitionConsumer options.
|
86
|
+
|
87
|
+
- max_bytes — default: 1048576 (1MB) — Maximum number of bytes to fetch
|
88
|
+
- max_wait_ms — default: 100 (100ms) — How long to block until the server sends us data.
|
89
|
+
- min_bytes — default: 1 (Send us data as soon as it is ready) — Smallest amount of data the server should send us.
|
90
|
+
- socket_timeout_ms - default: 10000 (10s) - How long to wait for reply from server. Should be higher than max_wait_ms.
|
91
|
+
|
92
|
+
See also [Poseidon::PartitionConsumer](http://www.rubydoc.info/github/bpot/poseidon/Poseidon/PartitionConsumer) for more detailed documentation about Poseidon.
|
93
|
+
|
67
94
|
### Output plugin (non-buffered)
|
68
95
|
|
69
96
|
<match *.**>
|
data/fluent-plugin-kafka.gemspec
CHANGED
@@ -12,9 +12,9 @@ Gem::Specification.new do |gem|
|
|
12
12
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
13
13
|
gem.name = "fluent-plugin-kafka"
|
14
14
|
gem.require_paths = ["lib"]
|
15
|
-
gem.version = '0.0
|
15
|
+
gem.version = '0.1.0'
|
16
16
|
gem.add_dependency 'fluentd'
|
17
|
-
gem.add_dependency '
|
17
|
+
gem.add_dependency 'poseidon_cluster'
|
18
18
|
gem.add_dependency 'ltsv'
|
19
19
|
gem.add_dependency 'yajl-ruby'
|
20
20
|
gem.add_dependency 'msgpack'
|
@@ -0,0 +1,160 @@
|
|
1
|
+
module Fluent
|
2
|
+
|
3
|
+
class KafkaInput < Input
|
4
|
+
Plugin.register_input('kafka_group', self)
|
5
|
+
|
6
|
+
config_param :brokers, :string
|
7
|
+
config_param :zookeepers, :string
|
8
|
+
config_param :consumer_group, :string, :default => nil
|
9
|
+
config_param :topics, :string
|
10
|
+
config_param :interval, :integer, :default => 1 # seconds
|
11
|
+
config_param :format, :string, :default => 'json' # (json|text|ltsv)
|
12
|
+
config_param :message_key, :string, :default => 'message' # for 'text' format only
|
13
|
+
config_param :add_prefix, :string, :default => nil
|
14
|
+
config_param :add_suffix, :string, :default => nil
|
15
|
+
|
16
|
+
# poseidon PartitionConsumer options
|
17
|
+
config_param :max_bytes, :integer, :default => nil
|
18
|
+
config_param :max_wait_ms, :integer, :default => nil
|
19
|
+
config_param :min_bytes, :integer, :default => nil
|
20
|
+
config_param :socket_timeout_ms, :integer, :default => nil
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
super
|
24
|
+
require 'poseidon_cluster'
|
25
|
+
end
|
26
|
+
|
27
|
+
def _config_to_array(config)
|
28
|
+
config_array = config.split(',').map {|k| k.strip }
|
29
|
+
if config_array.empty?
|
30
|
+
raise ConfigError, "kafka_group: '#{config}' is a required parameter"
|
31
|
+
end
|
32
|
+
config_array
|
33
|
+
end
|
34
|
+
|
35
|
+
private :_config_to_array
|
36
|
+
|
37
|
+
def configure(conf)
|
38
|
+
super
|
39
|
+
@broker_list = _config_to_array(@brokers)
|
40
|
+
@zookeeper_list = _config_to_array(@zookeepers)
|
41
|
+
@topic_list = _config_to_array(@topics)
|
42
|
+
|
43
|
+
unless @consumer_group
|
44
|
+
raise ConfigError, "kafka_group: 'consumer_group' is a required parameter"
|
45
|
+
end
|
46
|
+
$log.info "Will watch for topics #{@topic_list} at brokers " \
|
47
|
+
"#{@broker_list}, zookeepers #{@zookeeper_list} and group " \
|
48
|
+
"'#{@consumer_group}'"
|
49
|
+
|
50
|
+
case @format
|
51
|
+
when 'json'
|
52
|
+
require 'yajl'
|
53
|
+
when 'ltsv'
|
54
|
+
require 'ltsv'
|
55
|
+
when 'msgpack'
|
56
|
+
require 'msgpack'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def start
|
61
|
+
@loop = Coolio::Loop.new
|
62
|
+
opt = {}
|
63
|
+
opt[:max_bytes] = @max_bytes if @max_bytes
|
64
|
+
opt[:max_wait_ms] = @max_wait_ms if @max_wait_ms
|
65
|
+
opt[:min_bytes] = @min_bytes if @min_bytes
|
66
|
+
opt[:socket_timeout_ms] = @socket_timeout_ms if @socket_timeout_ms
|
67
|
+
|
68
|
+
@topic_watchers = @topic_list.map {|topic|
|
69
|
+
TopicWatcher.new(topic, @broker_list, @zookeeper_list, @consumer_group,
|
70
|
+
interval, @format, @message_key, @add_prefix,
|
71
|
+
@add_suffix, opt)
|
72
|
+
}
|
73
|
+
@topic_watchers.each {|tw|
|
74
|
+
tw.attach(@loop)
|
75
|
+
}
|
76
|
+
@thread = Thread.new(&method(:run))
|
77
|
+
end
|
78
|
+
|
79
|
+
def shutdown
|
80
|
+
@loop.stop
|
81
|
+
end
|
82
|
+
|
83
|
+
def run
|
84
|
+
@loop.run
|
85
|
+
rescue
|
86
|
+
$log.error "unexpected error", :error=>$!.to_s
|
87
|
+
$log.error_backtrace
|
88
|
+
end
|
89
|
+
|
90
|
+
class TopicWatcher < Coolio::TimerWatcher
|
91
|
+
def initialize(topic, broker_list, zookeeper_list, consumer_group,
|
92
|
+
interval, format, message_key, add_prefix, add_suffix,
|
93
|
+
options)
|
94
|
+
@topic = topic
|
95
|
+
@callback = method(:consume)
|
96
|
+
@format = format
|
97
|
+
@message_key = message_key
|
98
|
+
@add_prefix = add_prefix
|
99
|
+
@add_suffix = add_suffix
|
100
|
+
|
101
|
+
@consumer = Poseidon::ConsumerGroup.new(
|
102
|
+
consumer_group,
|
103
|
+
broker_list,
|
104
|
+
zookeeper_list,
|
105
|
+
topic,
|
106
|
+
options
|
107
|
+
)
|
108
|
+
|
109
|
+
super(interval, true)
|
110
|
+
end
|
111
|
+
|
112
|
+
def on_timer
|
113
|
+
@callback.call
|
114
|
+
rescue
|
115
|
+
# TODO log?
|
116
|
+
$log.error $!.to_s
|
117
|
+
$log.error_backtrace
|
118
|
+
end
|
119
|
+
|
120
|
+
def consume
|
121
|
+
es = MultiEventStream.new
|
122
|
+
tag = @topic
|
123
|
+
tag = @add_prefix + "." + tag if @add_prefix
|
124
|
+
tag = tag + "." + @add_suffix if @add_suffix
|
125
|
+
|
126
|
+
@consumer.fetch do |partition, bulk|
|
127
|
+
bulk.each do |msg|
|
128
|
+
begin
|
129
|
+
msg_record = parse_line(msg.value)
|
130
|
+
es.add(Time.now.to_i, msg_record)
|
131
|
+
rescue
|
132
|
+
$log.warn msg_record.to_s, :error=>$!.to_s
|
133
|
+
$log.debug_backtrace
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
unless es.empty?
|
139
|
+
Engine.emit_stream(tag, es)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def parse_line(record)
|
144
|
+
parsed_record = {}
|
145
|
+
case @format
|
146
|
+
when 'json'
|
147
|
+
parsed_record = Yajl::Parser.parse(record)
|
148
|
+
when 'ltsv'
|
149
|
+
parsed_record = LTSV.parse(record)
|
150
|
+
when 'msgpack'
|
151
|
+
parsed_record = MessagePack.unpack(record)
|
152
|
+
when 'text'
|
153
|
+
parsed_record[@message_key] = record
|
154
|
+
end
|
155
|
+
parsed_record
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-kafka
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hidemasa Togashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: poseidon_cluster
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '>='
|
@@ -107,6 +107,7 @@ files:
|
|
107
107
|
- Rakefile
|
108
108
|
- fluent-plugin-kafka.gemspec
|
109
109
|
- lib/fluent/plugin/in_kafka.rb
|
110
|
+
- lib/fluent/plugin/in_kafka_group.rb
|
110
111
|
- lib/fluent/plugin/out_kafka.rb
|
111
112
|
- lib/fluent/plugin/out_kafka_buffered.rb
|
112
113
|
- test/helper.rb
|