fluent-plugin-flume 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +1 -0
- data/ChangeLog +1 -0
- data/README.rdoc +105 -0
- data/Rakefile +57 -0
- data/VERSION +1 -0
- data/bin/fluent-flume-remote +28 -0
- data/fluent-plugin-flume.gemspec +56 -0
- data/lib/fluent/plugin/in_flume.rb +164 -0
- data/lib/fluent/plugin/out_flume.rb +96 -0
- data/lib/fluent/plugin/thrift/flume.thrift +72 -0
- data/lib/fluent/plugin/thrift/flume.thrift.orig +72 -0
- data/lib/fluent/plugin/thrift/flume_constants.rb +8 -0
- data/lib/fluent/plugin/thrift/flume_types.rb +71 -0
- data/lib/fluent/plugin/thrift/thrift_flume_event_server.rb +220 -0
- data/test/plugin/test_in_flume.rb +209 -0
- data/test/plugin/test_out_flume.rb +177 -0
- metadata +87 -0
@@ -0,0 +1,72 @@
|
|
1
|
+
/**
|
2
|
+
* Licensed to Cloudera, Inc. under one
|
3
|
+
* or more contributor license agreements. See the NOTICE file
|
4
|
+
* distributed with this work for additional information
|
5
|
+
* regarding copyright ownership. Cloudera, Inc. licenses this file
|
6
|
+
* to you under the Apache License, Version 2.0 (the
|
7
|
+
* "License"); you may not use this file except in compliance
|
8
|
+
* with the License. You may obtain a copy of the License at
|
9
|
+
*
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
*
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
* See the License for the specific language governing permissions and
|
16
|
+
* limitations under the License.
|
17
|
+
*/
|
18
|
+
# flume.thrift
|
19
|
+
#
|
20
|
+
# This thrift interface and service defines a network transport mechanism to move events
|
21
|
+
# from one process/machine to another. At the moment this mirrors the fields of an event
|
22
|
+
# as defined in c.c.f.core.Event.java's code .
|
23
|
+
#
|
24
|
+
# This may change more fields are likely to be added, and the actual format is subject to change.
|
25
|
+
|
26
|
+
# The server has two rpc methods
|
27
|
+
# -- append: which sends an event to the server,
|
28
|
+
# -- close: shuts down this client's connection
|
29
|
+
#
|
30
|
+
# Currently append is oneway, requiring the thrift server to do flow control.
|
31
|
+
|
32
|
+
namespace java com.cloudera.flume.handlers.thrift
|
33
|
+
|
34
|
+
typedef i64 Timestamp
|
35
|
+
|
36
|
+
enum Priority {
|
37
|
+
FATAL = 0,
|
38
|
+
ERROR = 1,
|
39
|
+
WARN = 2,
|
40
|
+
INFO = 3,
|
41
|
+
DEBUG = 4,
|
42
|
+
TRACE = 5
|
43
|
+
}
|
44
|
+
|
45
|
+
enum EventStatus {
|
46
|
+
ACK = 0,
|
47
|
+
COMMITED = 1,
|
48
|
+
ERR = 2
|
49
|
+
}
|
50
|
+
|
51
|
+
struct ThriftFlumeEvent {
|
52
|
+
1: Timestamp timestamp,
|
53
|
+
2: Priority priority,
|
54
|
+
3: binary body,
|
55
|
+
4: i64 nanos,
|
56
|
+
5: string host,
|
57
|
+
6: map<string,binary> fieldss
|
58
|
+
}
|
59
|
+
|
60
|
+
# Instead of using thrift's serialization, we just assume the contents are serialized already.
|
61
|
+
struct RawEvent {
|
62
|
+
1: binary raw
|
63
|
+
}
|
64
|
+
|
65
|
+
service ThriftFlumeEventServer {
|
66
|
+
oneway void append( 1:ThriftFlumeEvent evt ),
|
67
|
+
oneway void rawAppend( 1:RawEvent evt),
|
68
|
+
EventStatus ackedAppend( 1: ThriftFlumeEvent evt ),
|
69
|
+
|
70
|
+
void close(),
|
71
|
+
}
|
72
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
/**
|
2
|
+
* Licensed to Cloudera, Inc. under one
|
3
|
+
* or more contributor license agreements. See the NOTICE file
|
4
|
+
* distributed with this work for additional information
|
5
|
+
* regarding copyright ownership. Cloudera, Inc. licenses this file
|
6
|
+
* to you under the Apache License, Version 2.0 (the
|
7
|
+
* "License"); you may not use this file except in compliance
|
8
|
+
* with the License. You may obtain a copy of the License at
|
9
|
+
*
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
*
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
* See the License for the specific language governing permissions and
|
16
|
+
* limitations under the License.
|
17
|
+
*/
|
18
|
+
# flume.thrift
|
19
|
+
#
|
20
|
+
# This thrift interface and service defines a network transport mechanism to move events
|
21
|
+
# from one process/machine to another. At the moment this mirrors the fields of an event
|
22
|
+
# as defined in c.c.f.core.Event.java's code .
|
23
|
+
#
|
24
|
+
# This may change more fields are likely to be added, and the actual format is subject to change.
|
25
|
+
|
26
|
+
# The server has two rpc methods
|
27
|
+
# -- append: which sends an event to the server,
|
28
|
+
# -- close: shuts down this client's connection
|
29
|
+
#
|
30
|
+
# Currently append is oneway, requiring the thrift server to do flow control.
|
31
|
+
|
32
|
+
namespace java com.cloudera.flume.handlers.thrift
|
33
|
+
|
34
|
+
typedef i64 Timestamp
|
35
|
+
|
36
|
+
enum Priority {
|
37
|
+
FATAL = 0,
|
38
|
+
ERROR = 1,
|
39
|
+
WARN = 2,
|
40
|
+
INFO = 3,
|
41
|
+
DEBUG = 4,
|
42
|
+
TRACE = 5
|
43
|
+
}
|
44
|
+
|
45
|
+
enum EventStatus {
|
46
|
+
ACK = 0,
|
47
|
+
COMMITED = 1,
|
48
|
+
ERR = 2
|
49
|
+
}
|
50
|
+
|
51
|
+
struct ThriftFlumeEvent {
|
52
|
+
1: Timestamp timestamp,
|
53
|
+
2: Priority priority,
|
54
|
+
3: binary body,
|
55
|
+
4: i64 nanos,
|
56
|
+
5: string host,
|
57
|
+
6: map<string,binary> fields
|
58
|
+
}
|
59
|
+
|
60
|
+
# Instead of using thrift's serialization, we just assume the contents are serialized already.
|
61
|
+
struct RawEvent {
|
62
|
+
1: binary raw
|
63
|
+
}
|
64
|
+
|
65
|
+
service ThriftFlumeEventServer {
|
66
|
+
oneway void append( 1:ThriftFlumeEvent evt ),
|
67
|
+
oneway void rawAppend( 1:RawEvent evt),
|
68
|
+
EventStatus ackedAppend( 1: ThriftFlumeEvent evt ),
|
69
|
+
|
70
|
+
void close(),
|
71
|
+
}
|
72
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#
|
2
|
+
# Autogenerated by Thrift
|
3
|
+
#
|
4
|
+
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
5
|
+
#
|
6
|
+
|
7
|
+
|
8
|
+
module Priority
|
9
|
+
FATAL = 0
|
10
|
+
ERROR = 1
|
11
|
+
WARN = 2
|
12
|
+
INFO = 3
|
13
|
+
DEBUG = 4
|
14
|
+
TRACE = 5
|
15
|
+
VALUE_MAP = {0 => "FATAL", 1 => "ERROR", 2 => "WARN", 3 => "INFO", 4 => "DEBUG", 5 => "TRACE"}
|
16
|
+
VALID_VALUES = Set.new([FATAL, ERROR, WARN, INFO, DEBUG, TRACE]).freeze
|
17
|
+
end
|
18
|
+
|
19
|
+
module EventStatus
|
20
|
+
ACK = 0
|
21
|
+
COMMITED = 1
|
22
|
+
ERR = 2
|
23
|
+
VALUE_MAP = {0 => "ACK", 1 => "COMMITED", 2 => "ERR"}
|
24
|
+
VALID_VALUES = Set.new([ACK, COMMITED, ERR]).freeze
|
25
|
+
end
|
26
|
+
|
27
|
+
class ThriftFlumeEvent
|
28
|
+
include ::Thrift::Struct, ::Thrift::Struct_Union
|
29
|
+
TIMESTAMP = 1
|
30
|
+
PRIORITY = 2
|
31
|
+
BODY = 3
|
32
|
+
NANOS = 4
|
33
|
+
HOST = 5
|
34
|
+
FIELDSS = 6
|
35
|
+
|
36
|
+
FIELDS = {
|
37
|
+
TIMESTAMP => {:type => ::Thrift::Types::I64, :name => 'timestamp'},
|
38
|
+
PRIORITY => {:type => ::Thrift::Types::I32, :name => 'priority', :enum_class => Priority},
|
39
|
+
BODY => {:type => ::Thrift::Types::STRING, :name => 'body', :binary => true},
|
40
|
+
NANOS => {:type => ::Thrift::Types::I64, :name => 'nanos'},
|
41
|
+
HOST => {:type => ::Thrift::Types::STRING, :name => 'host'},
|
42
|
+
FIELDSS => {:type => ::Thrift::Types::MAP, :name => 'fieldss', :key => {:type => ::Thrift::Types::STRING}, :value => {:type => ::Thrift::Types::STRING, :binary => true}}
|
43
|
+
}
|
44
|
+
|
45
|
+
def struct_fields; FIELDS; end
|
46
|
+
|
47
|
+
def validate
|
48
|
+
unless @priority.nil? || Priority::VALID_VALUES.include?(@priority)
|
49
|
+
raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Invalid value of field priority!')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
::Thrift::Struct.generate_accessors self
|
54
|
+
end
|
55
|
+
|
56
|
+
class RawEvent
|
57
|
+
include ::Thrift::Struct, ::Thrift::Struct_Union
|
58
|
+
RAW = 1
|
59
|
+
|
60
|
+
FIELDS = {
|
61
|
+
RAW => {:type => ::Thrift::Types::STRING, :name => 'raw', :binary => true}
|
62
|
+
}
|
63
|
+
|
64
|
+
def struct_fields; FIELDS; end
|
65
|
+
|
66
|
+
def validate
|
67
|
+
end
|
68
|
+
|
69
|
+
::Thrift::Struct.generate_accessors self
|
70
|
+
end
|
71
|
+
|
@@ -0,0 +1,220 @@
|
|
1
|
+
#
|
2
|
+
# Autogenerated by Thrift
|
3
|
+
#
|
4
|
+
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'thrift'
|
8
|
+
require 'flume_types'
|
9
|
+
|
10
|
+
module ThriftFlumeEventServer
|
11
|
+
class Client
|
12
|
+
include ::Thrift::Client
|
13
|
+
|
14
|
+
def append(evt)
|
15
|
+
send_append(evt)
|
16
|
+
end
|
17
|
+
|
18
|
+
def send_append(evt)
|
19
|
+
send_message('append', Append_args, :evt => evt)
|
20
|
+
end
|
21
|
+
def rawAppend(evt)
|
22
|
+
send_rawAppend(evt)
|
23
|
+
end
|
24
|
+
|
25
|
+
def send_rawAppend(evt)
|
26
|
+
send_message('rawAppend', RawAppend_args, :evt => evt)
|
27
|
+
end
|
28
|
+
def ackedAppend(evt)
|
29
|
+
send_ackedAppend(evt)
|
30
|
+
return recv_ackedAppend()
|
31
|
+
end
|
32
|
+
|
33
|
+
def send_ackedAppend(evt)
|
34
|
+
send_message('ackedAppend', AckedAppend_args, :evt => evt)
|
35
|
+
end
|
36
|
+
|
37
|
+
def recv_ackedAppend()
|
38
|
+
result = receive_message(AckedAppend_result)
|
39
|
+
return result.success unless result.success.nil?
|
40
|
+
raise ::Thrift::ApplicationException.new(::Thrift::ApplicationException::MISSING_RESULT, 'ackedAppend failed: unknown result')
|
41
|
+
end
|
42
|
+
|
43
|
+
def close()
|
44
|
+
send_close()
|
45
|
+
recv_close()
|
46
|
+
end
|
47
|
+
|
48
|
+
def send_close()
|
49
|
+
send_message('close', Close_args)
|
50
|
+
end
|
51
|
+
|
52
|
+
def recv_close()
|
53
|
+
result = receive_message(Close_result)
|
54
|
+
return
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
class Processor
|
60
|
+
include ::Thrift::Processor
|
61
|
+
|
62
|
+
def process_append(seqid, iprot, oprot)
|
63
|
+
args = read_args(iprot, Append_args)
|
64
|
+
@handler.append(args.evt)
|
65
|
+
return
|
66
|
+
end
|
67
|
+
|
68
|
+
def process_rawAppend(seqid, iprot, oprot)
|
69
|
+
args = read_args(iprot, RawAppend_args)
|
70
|
+
@handler.rawAppend(args.evt)
|
71
|
+
return
|
72
|
+
end
|
73
|
+
|
74
|
+
def process_ackedAppend(seqid, iprot, oprot)
|
75
|
+
args = read_args(iprot, AckedAppend_args)
|
76
|
+
result = AckedAppend_result.new()
|
77
|
+
result.success = @handler.ackedAppend(args.evt)
|
78
|
+
write_result(result, oprot, 'ackedAppend', seqid)
|
79
|
+
end
|
80
|
+
|
81
|
+
def process_close(seqid, iprot, oprot)
|
82
|
+
args = read_args(iprot, Close_args)
|
83
|
+
result = Close_result.new()
|
84
|
+
@handler.close()
|
85
|
+
write_result(result, oprot, 'close', seqid)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
# HELPER FUNCTIONS AND STRUCTURES
|
91
|
+
|
92
|
+
class Append_args
|
93
|
+
include ::Thrift::Struct, ::Thrift::Struct_Union
|
94
|
+
EVT = 1
|
95
|
+
|
96
|
+
FIELDS = {
|
97
|
+
EVT => {:type => ::Thrift::Types::STRUCT, :name => 'evt', :class => ThriftFlumeEvent}
|
98
|
+
}
|
99
|
+
|
100
|
+
def struct_fields; FIELDS; end
|
101
|
+
|
102
|
+
def validate
|
103
|
+
end
|
104
|
+
|
105
|
+
::Thrift::Struct.generate_accessors self
|
106
|
+
end
|
107
|
+
|
108
|
+
class Append_result
|
109
|
+
include ::Thrift::Struct, ::Thrift::Struct_Union
|
110
|
+
|
111
|
+
FIELDS = {
|
112
|
+
|
113
|
+
}
|
114
|
+
|
115
|
+
def struct_fields; FIELDS; end
|
116
|
+
|
117
|
+
def validate
|
118
|
+
end
|
119
|
+
|
120
|
+
::Thrift::Struct.generate_accessors self
|
121
|
+
end
|
122
|
+
|
123
|
+
class RawAppend_args
|
124
|
+
include ::Thrift::Struct, ::Thrift::Struct_Union
|
125
|
+
EVT = 1
|
126
|
+
|
127
|
+
FIELDS = {
|
128
|
+
EVT => {:type => ::Thrift::Types::STRUCT, :name => 'evt', :class => RawEvent}
|
129
|
+
}
|
130
|
+
|
131
|
+
def struct_fields; FIELDS; end
|
132
|
+
|
133
|
+
def validate
|
134
|
+
end
|
135
|
+
|
136
|
+
::Thrift::Struct.generate_accessors self
|
137
|
+
end
|
138
|
+
|
139
|
+
class RawAppend_result
|
140
|
+
include ::Thrift::Struct, ::Thrift::Struct_Union
|
141
|
+
|
142
|
+
FIELDS = {
|
143
|
+
|
144
|
+
}
|
145
|
+
|
146
|
+
def struct_fields; FIELDS; end
|
147
|
+
|
148
|
+
def validate
|
149
|
+
end
|
150
|
+
|
151
|
+
::Thrift::Struct.generate_accessors self
|
152
|
+
end
|
153
|
+
|
154
|
+
class AckedAppend_args
|
155
|
+
include ::Thrift::Struct, ::Thrift::Struct_Union
|
156
|
+
EVT = 1
|
157
|
+
|
158
|
+
FIELDS = {
|
159
|
+
EVT => {:type => ::Thrift::Types::STRUCT, :name => 'evt', :class => ThriftFlumeEvent}
|
160
|
+
}
|
161
|
+
|
162
|
+
def struct_fields; FIELDS; end
|
163
|
+
|
164
|
+
def validate
|
165
|
+
end
|
166
|
+
|
167
|
+
::Thrift::Struct.generate_accessors self
|
168
|
+
end
|
169
|
+
|
170
|
+
class AckedAppend_result
|
171
|
+
include ::Thrift::Struct, ::Thrift::Struct_Union
|
172
|
+
SUCCESS = 0
|
173
|
+
|
174
|
+
FIELDS = {
|
175
|
+
SUCCESS => {:type => ::Thrift::Types::I32, :name => 'success', :enum_class => EventStatus}
|
176
|
+
}
|
177
|
+
|
178
|
+
def struct_fields; FIELDS; end
|
179
|
+
|
180
|
+
def validate
|
181
|
+
unless @success.nil? || EventStatus::VALID_VALUES.include?(@success)
|
182
|
+
raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Invalid value of field success!')
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
::Thrift::Struct.generate_accessors self
|
187
|
+
end
|
188
|
+
|
189
|
+
class Close_args
|
190
|
+
include ::Thrift::Struct, ::Thrift::Struct_Union
|
191
|
+
|
192
|
+
FIELDS = {
|
193
|
+
|
194
|
+
}
|
195
|
+
|
196
|
+
def struct_fields; FIELDS; end
|
197
|
+
|
198
|
+
def validate
|
199
|
+
end
|
200
|
+
|
201
|
+
::Thrift::Struct.generate_accessors self
|
202
|
+
end
|
203
|
+
|
204
|
+
class Close_result
|
205
|
+
include ::Thrift::Struct, ::Thrift::Struct_Union
|
206
|
+
|
207
|
+
FIELDS = {
|
208
|
+
|
209
|
+
}
|
210
|
+
|
211
|
+
def struct_fields; FIELDS; end
|
212
|
+
|
213
|
+
def validate
|
214
|
+
end
|
215
|
+
|
216
|
+
::Thrift::Struct.generate_accessors self
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|
220
|
+
|
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'fluent/test'
|
3
|
+
require 'fluent/plugin/in_flume'
|
4
|
+
|
5
|
+
class FlumeInputTest < Test::Unit::TestCase
|
6
|
+
CONFIG = %[
|
7
|
+
port 56790
|
8
|
+
bind 127.0.0.1
|
9
|
+
]
|
10
|
+
|
11
|
+
def create_driver(conf=CONFIG)
|
12
|
+
Fluent::Test::InputTestDriver.new(Fluent::FlumeInput).configure(conf)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_configure
|
16
|
+
d = create_driver ''
|
17
|
+
assert_equal 56789, d.instance.port
|
18
|
+
assert_equal '0.0.0.0', d.instance.bind
|
19
|
+
|
20
|
+
d = create_driver
|
21
|
+
assert_equal 56790, d.instance.port
|
22
|
+
assert_equal '127.0.0.1', d.instance.bind
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_time
|
26
|
+
d = create_driver
|
27
|
+
|
28
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
29
|
+
Fluent::Engine.now = time
|
30
|
+
|
31
|
+
d.expect_emit "category", time, {"message"=>'aiueo'}
|
32
|
+
d.expect_emit "category", time, {"message"=>'aiueo'}
|
33
|
+
|
34
|
+
emits = [
|
35
|
+
['tag1', time, {"message"=>'aiueo'}],
|
36
|
+
['tag2', time, {"message"=>'aiueo'}]
|
37
|
+
]
|
38
|
+
|
39
|
+
d.run do
|
40
|
+
emits.each { |tag, time, record|
|
41
|
+
send('tag', tag, time, record['message'])
|
42
|
+
sleep 0.01
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
d2 = create_driver(CONFIG + %[
|
47
|
+
default_tag flume
|
48
|
+
])
|
49
|
+
|
50
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
51
|
+
Fluent::Engine.now = time
|
52
|
+
|
53
|
+
d2.expect_emit "flume", time, {"message"=>'aiueo'}
|
54
|
+
d2.expect_emit "flume", time, {"message"=>'aiueo'}
|
55
|
+
|
56
|
+
emits = [
|
57
|
+
['tag1', time, {"message"=>'aiueo'}],
|
58
|
+
['tag2', time, {"message"=>'aiueo'}]
|
59
|
+
]
|
60
|
+
|
61
|
+
d2.run do
|
62
|
+
emits.each { |tag, time, record|
|
63
|
+
send('tag', tag, time, record['message'])
|
64
|
+
sleep 0.01
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
d3 = create_driver(CONFIG + %[
|
69
|
+
tag_field flume
|
70
|
+
])
|
71
|
+
|
72
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
73
|
+
Fluent::Engine.now = time
|
74
|
+
|
75
|
+
d3.expect_emit "tag1", time, {"message"=>'aiueo'}
|
76
|
+
d3.expect_emit "tag2", time, {"message"=>'aiueo'}
|
77
|
+
|
78
|
+
emits = [
|
79
|
+
['tag1', time, {"message"=>'aiueo'}],
|
80
|
+
['tag2', time, {"message"=>'aiueo'}]
|
81
|
+
]
|
82
|
+
|
83
|
+
d3.run do
|
84
|
+
emits.each { |tag, time, record|
|
85
|
+
send('flume', tag, time, record['message'])
|
86
|
+
sleep 0.01
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
d4 = create_driver(CONFIG + %[
|
91
|
+
default_tag fluent
|
92
|
+
tag_field flume
|
93
|
+
])
|
94
|
+
|
95
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
96
|
+
Fluent::Engine.now = time
|
97
|
+
|
98
|
+
d4.expect_emit "tag1", time, {"message"=>'aiueo'}
|
99
|
+
d4.expect_emit "tag2", time, {"message"=>'aiueo'}
|
100
|
+
|
101
|
+
emits = [
|
102
|
+
['tag1', time, {"message"=>'aiueo'}],
|
103
|
+
['tag2', time, {"message"=>'aiueo'}]
|
104
|
+
]
|
105
|
+
|
106
|
+
d4.run do
|
107
|
+
emits.each { |tag, time, record|
|
108
|
+
send('flume', tag, time, record['message'])
|
109
|
+
sleep 0.01
|
110
|
+
}
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_add_prefix
|
115
|
+
d = create_driver(CONFIG + %[
|
116
|
+
add_prefix flume
|
117
|
+
tag_field category
|
118
|
+
])
|
119
|
+
|
120
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
121
|
+
Fluent::Engine.now = time
|
122
|
+
|
123
|
+
d.expect_emit "flume.tag1", time, {"message"=>'aiueo'}
|
124
|
+
d.expect_emit "flume.tag2", time, {"message"=>'aiueo'}
|
125
|
+
|
126
|
+
emits = [
|
127
|
+
['tag1', time, {"message"=>'aiueo'}],
|
128
|
+
['tag2', time, {"message"=>'aiueo'}],
|
129
|
+
]
|
130
|
+
d.run do
|
131
|
+
emits.each { |tag, time, record|
|
132
|
+
send('category', tag, time, record['message'])
|
133
|
+
sleep 0.01
|
134
|
+
}
|
135
|
+
end
|
136
|
+
|
137
|
+
d2 = create_driver(CONFIG + %[
|
138
|
+
add_prefix flume.input
|
139
|
+
tag_field category
|
140
|
+
])
|
141
|
+
|
142
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
143
|
+
Fluent::Engine.now = time
|
144
|
+
|
145
|
+
d2.expect_emit "flume.input.tag3", time, {"message"=>'aiueo'}
|
146
|
+
d2.expect_emit "flume.input.tag4", time, {"message"=>'aiueo'}
|
147
|
+
|
148
|
+
emits = [
|
149
|
+
['tag3', time, {"message"=>'aiueo'}],
|
150
|
+
['tag4', time, {"message"=>'aiueo'}],
|
151
|
+
]
|
152
|
+
d2.run do
|
153
|
+
emits.each { |tag, time, record|
|
154
|
+
send('category', tag, time, record['message'])
|
155
|
+
sleep 0.01
|
156
|
+
}
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_message_format_json
|
161
|
+
d = create_driver(CONFIG + %[
|
162
|
+
tag_field category
|
163
|
+
message_format json
|
164
|
+
])
|
165
|
+
assert_equal 'json', d.instance.message_format
|
166
|
+
|
167
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
168
|
+
Fluent::Engine.now = time
|
169
|
+
|
170
|
+
d.expect_emit "tag1", time, {"a"=>1}
|
171
|
+
d.expect_emit "tag2", time, {"a"=>1, "b"=>2}
|
172
|
+
d.expect_emit "tag3", time, {"a"=>1, "b"=>2, "c"=>3}
|
173
|
+
|
174
|
+
emits = [
|
175
|
+
['tag1', time, {"a"=>1}.to_json],
|
176
|
+
['tag2', time, {"a"=>1, "b"=>2}.to_json],
|
177
|
+
['tag3', time, {"a"=>1, "b"=>2, "c"=>3}.to_json],
|
178
|
+
]
|
179
|
+
d.run do
|
180
|
+
emits.each { |tag, time, message|
|
181
|
+
send('category', tag, time, message)
|
182
|
+
sleep 0.01
|
183
|
+
}
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def setup
|
188
|
+
Fluent::FlumeInput.new
|
189
|
+
Fluent::Test.setup
|
190
|
+
end
|
191
|
+
|
192
|
+
def send(tag_field, tag, time, msg)
|
193
|
+
socket = Thrift::Socket.new '127.0.0.1', 56790
|
194
|
+
#transport = Thrift::Socket.new '127.0.0.1', 56790
|
195
|
+
transport = Thrift::BufferedTransport.new socket
|
196
|
+
protocol = Thrift::BinaryProtocol.new transport
|
197
|
+
client = ThriftFlumeEventServer::Client.new protocol
|
198
|
+
transport.open
|
199
|
+
raw_sock = socket.to_io
|
200
|
+
raw_sock.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
|
201
|
+
|
202
|
+
entry = ThriftFlumeEvent.new(:body=>msg.to_s,
|
203
|
+
:priority=>Priority::INFO,
|
204
|
+
:timestamp=>time,
|
205
|
+
:fieldss=>{tag_field=>tag})
|
206
|
+
client.append entry
|
207
|
+
transport.close
|
208
|
+
end
|
209
|
+
end
|