fluent-plugin-flume 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.
- 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
|