fluent-plugin-mqtt-io 0.0.6 → 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 +14 -5
- data/fluent-plugin-mqtt-io.gemspec +1 -1
- data/lib/fluent/plugin/in_mqtt.rb +49 -15
- data/lib/fluent/plugin/mqtt_output_mixin.rb +30 -4
- data/lib/fluent/plugin/out_mqtt.rb +1 -1
- data/lib/fluent/plugin/out_mqtt_buf.rb +17 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d296aa7e9f2bf32ab247b8f99ad7bdaf972cf763
|
4
|
+
data.tar.gz: 669477119ff620c36cb45bf2ed63ae2ed238b1d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a105c66f6dd6e4e11a6e7f118c34295590da1c10ec0bd31e6393aafc21cceef2274dc3f2468c1d6a5c6105a4a44e6c53eb79e48d27fde883e866bbebd6e89d7e
|
7
|
+
data.tar.gz: 04fd6db671975fb44c8ba536fc10e31c43503d1d20eb0d76bda5a41bfc6a5657dedea25f9489d44495f22f76b5ec4b2158ca9b563c583c9f5b05391691f56fb7
|
data/README.md
CHANGED
@@ -26,6 +26,8 @@ Or install it yourself as:
|
|
26
26
|
|
27
27
|
fluent-plugin-mqtt-io provides Input and Output Plugins for MQTT.
|
28
28
|
|
29
|
+
### Input Plugin (Fluet::MqttInput)
|
30
|
+
|
29
31
|
Input Plugin can be used via source directive in the configuration.
|
30
32
|
|
31
33
|
```
|
@@ -44,9 +46,11 @@ The default MQTT topic is "#". Configurable options are the following:
|
|
44
46
|
- bind: IP address of MQTT broker
|
45
47
|
- port: Port number of MQTT broker
|
46
48
|
- format (mandatory): Input parser can be chosen, e.g. json, xml
|
47
|
-
-
|
48
|
-
-
|
49
|
+
- In order to use xml format, you need to install [fluent-plugin-xml-parser](https://github.com/toyokazu/fluent-plugin-xml-parser).
|
50
|
+
- Default time_key field for json format is 'time'
|
49
51
|
- topic: Topic name to be subscribed
|
52
|
+
- bulk_trans: Enable bulk transfer to support buffered output (mqtt_buf, Fluent::MqttBufferedOutput, defaut: true)
|
53
|
+
- bulk_trans_sep: A message separator for bulk transfer. The default separator is "\t".
|
50
54
|
- username: User name for authentication
|
51
55
|
- password: Password for authentication
|
52
56
|
- ssl: set true if you want to use SSL/TLS. If set to true, the following parameter must be provided
|
@@ -56,6 +60,8 @@ The default MQTT topic is "#". Configurable options are the following:
|
|
56
60
|
|
57
61
|
Input Plugin supports @label directive.
|
58
62
|
|
63
|
+
### Output Plugin (Fluent::MqttOutput, Fluent::MqttBufferedOutput)
|
64
|
+
|
59
65
|
Output Plugin can be used via match directive.
|
60
66
|
|
61
67
|
```
|
@@ -68,7 +74,7 @@ Output Plugin can be used via match directive.
|
|
68
74
|
|
69
75
|
```
|
70
76
|
|
71
|
-
The options are basically the same as Input Plugin.
|
77
|
+
The options are basically the same as Input Plugin except for "format" and "bulk_trans". Additional options for Output Plugin are the following.
|
72
78
|
|
73
79
|
- time_key: An attribute name used for timestamp field genarated from fluentd time field. Default is nil (omitted).
|
74
80
|
If this option is omitted, timestamp field is not appended to the output record.
|
@@ -93,7 +99,7 @@ The topic name or tag name, e.g. "topic", received from an event can not be publ
|
|
93
99
|
|
94
100
|
```
|
95
101
|
|
96
|
-
You can also use mqtt_buf type which is implemented as
|
102
|
+
You can also use mqtt_buf type which is implemented as Fluent::MqttBufferedOutput.
|
97
103
|
|
98
104
|
```
|
99
105
|
|
@@ -110,10 +116,13 @@ You can also use mqtt_buf type which is implemented as BufferedOutput.
|
|
110
116
|
|
111
117
|
```
|
112
118
|
|
119
|
+
When a plugin implemented as Fluent::BufferedOutput, fluentd stores the received messages into buffers (Fluent::MemoryBuffer is used as default) separated by tag names. Writer Threads emit those stored messages periodically in the specified interval. In MqttBufferedOutput, the stored messages are concatenated with 'bulk_trans_sep' (default: "\t"). This function reduces the number of messages sent via MQTT if data producing interval of sensors are smaller than publish interval (flush_interval). The concatinated messages can be properly handled by Fluent::MqttInput plugin by specifying 'bulk_trans' option.
|
113
120
|
|
114
121
|
## Use case examples
|
115
122
|
|
116
|
-
###
|
123
|
+
### Sensor data collection (not for Libelium now)
|
124
|
+
|
125
|
+
*additional description (2015-12-25)*: Thanks to the updates by Libelium, Meshlium farmware now supports flexible output format configuration including JSON. As a result, data conversion by XmlParser is not required for this use case. The following description is kept just for sharing know-how of data conversion in fluentd.
|
117
126
|
|
118
127
|
There are many kinds of commercial sensor products on the market, e.g. [Libelium](http://www.libelium.com/). Major sensor products support MQTT to upload sensor data. The following example shows how to store uploaded Libelium sensor data into ElasticSearch.
|
119
128
|
|
@@ -6,6 +6,8 @@ module Fluent
|
|
6
6
|
config_param :bind, :string, :default => '127.0.0.1'
|
7
7
|
config_param :topic, :string, :default => '#'
|
8
8
|
config_param :format, :string, :default => 'json'
|
9
|
+
config_param :bulk_trans, :bool, :default => true
|
10
|
+
config_param :bulk_trans_sep, :string, :default => "\t"
|
9
11
|
config_param :username, :string, :default => nil
|
10
12
|
config_param :password, :string, :default => nil
|
11
13
|
config_param :ssl, :bool, :default => nil
|
@@ -24,6 +26,8 @@ module Fluent
|
|
24
26
|
super
|
25
27
|
@bind ||= conf['bind']
|
26
28
|
@topic ||= conf['topic']
|
29
|
+
@bulk_trans ||= conf['bulk_trans']
|
30
|
+
@bulk_trans_sep ||= conf['bulk_trans_sep']
|
27
31
|
@port ||= conf['port']
|
28
32
|
@username ||= conf['username']
|
29
33
|
@password ||= conf['password']
|
@@ -47,27 +51,56 @@ module Fluent
|
|
47
51
|
opts[:ca_file] = @ca_file if @ca_file
|
48
52
|
opts[:cert_file] = @cert_file if @cert_file
|
49
53
|
opts[:key_file] = @key_file if @key_file
|
50
|
-
@connect = MQTT::Client.connect(opts)
|
51
|
-
@connect.subscribe(@topic)
|
52
54
|
|
53
|
-
|
54
|
-
|
55
|
-
|
55
|
+
# In order to handle Exception raised from reading Thread
|
56
|
+
# in MQTT::Client caused by network disconnection (during read_byte),
|
57
|
+
# @connect_thread generates connection.
|
58
|
+
@client = MQTT::Client.new(opts)
|
59
|
+
@connect_thread = Thread.new do
|
60
|
+
while (true)
|
61
|
+
begin
|
62
|
+
@client.disconnect if @client.connected?
|
63
|
+
@client.connect
|
64
|
+
@client.subscribe(@topic)
|
65
|
+
@get_thread.kill if !@get_thread.nil? && @get_thread.alive?
|
66
|
+
@get_thread = Thread.new do
|
67
|
+
@client.get do |topic, message|
|
68
|
+
emit(topic, message)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
sleep
|
72
|
+
rescue MQTT::ProtocolException => pe
|
73
|
+
$log.debug "Handling #{pe.class}: #{pe.message}"
|
74
|
+
next
|
75
|
+
rescue Timeout::Error => te
|
76
|
+
$log.debug "Handling #{te.class}: #{te.message}"
|
77
|
+
next
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def parse(message)
|
84
|
+
@parser.parse(message) do |time, record|
|
85
|
+
if time.nil?
|
86
|
+
$log.debug "Since time_key field is nil, Fluent::Engine.now is used."
|
87
|
+
time = Fluent::Engine.now
|
56
88
|
end
|
89
|
+
$log.debug "#{topic}, #{time}, #{record}"
|
90
|
+
return [time, record]
|
57
91
|
end
|
58
92
|
end
|
59
93
|
|
60
|
-
def emit
|
94
|
+
def emit(topic, message)
|
61
95
|
begin
|
62
96
|
topic.gsub!("/","\.")
|
63
|
-
@
|
64
|
-
|
65
|
-
|
66
|
-
time = Fluent::Engine.now
|
97
|
+
if @bulk_trans
|
98
|
+
message.split(@bulk_trans_sep).each do |m|
|
99
|
+
router.emit(topic, *parse(m))
|
67
100
|
end
|
68
|
-
|
69
|
-
router.emit(topic,
|
70
|
-
|
101
|
+
else
|
102
|
+
router.emit(topic, *parse(message))
|
103
|
+
end
|
71
104
|
rescue Exception => e
|
72
105
|
$log.error :error => e.to_s
|
73
106
|
$log.debug_backtrace(e.backtrace)
|
@@ -75,8 +108,9 @@ module Fluent
|
|
75
108
|
end
|
76
109
|
|
77
110
|
def shutdown
|
78
|
-
@
|
79
|
-
@
|
111
|
+
@get_thread.kill
|
112
|
+
@connect_thread.kill
|
113
|
+
@client.disconnect
|
80
114
|
end
|
81
115
|
end
|
82
116
|
end
|
@@ -12,10 +12,11 @@ module Fluent
|
|
12
12
|
base.config_param :ca_file, :string, :default => nil
|
13
13
|
base.config_param :key_file, :string, :default => nil
|
14
14
|
base.config_param :cert_file, :string, :default => nil
|
15
|
-
base.config_param :time_key, :string, :default =>
|
15
|
+
base.config_param :time_key, :string, :default => 'time'
|
16
16
|
base.config_param :time_format, :string, :default => nil
|
17
17
|
base.config_param :topic_rewrite_pattern, :string, :default => nil
|
18
18
|
base.config_param :topic_rewrite_replacement, :string, :default => nil
|
19
|
+
base.config_param :bulk_trans_sep, :string, :default => "\t"
|
19
20
|
end
|
20
21
|
|
21
22
|
require 'mqtt'
|
@@ -35,6 +36,7 @@ module Fluent
|
|
35
36
|
@time_format ||= conf['time_format']
|
36
37
|
@topic_rewrite_pattern ||= conf['topic_rewrite_pattern']
|
37
38
|
@topic_rewrite_replacement ||= conf['topic_rewrite_replacement']
|
39
|
+
@bulk_trans_sep ||= conf['bulk_trans_sep']
|
38
40
|
end
|
39
41
|
|
40
42
|
# This method is called when starting.
|
@@ -53,7 +55,25 @@ module Fluent
|
|
53
55
|
opts[:ca_file] = @ca_file if @ca_file
|
54
56
|
opts[:cert_file] = @cert_file if @cert_file
|
55
57
|
opts[:key_file] = @key_file if @key_file
|
56
|
-
|
58
|
+
# In order to handle Exception raised from reading Thread
|
59
|
+
# in MQTT::Client caused by network disconnection (during read_byte),
|
60
|
+
# @connect_thread generates connection.
|
61
|
+
@client = MQTT::Client.new(opts)
|
62
|
+
@connect_thread = Thread.new do
|
63
|
+
while (true)
|
64
|
+
begin
|
65
|
+
@client.disconnect if @client.connected?
|
66
|
+
@client.connect
|
67
|
+
sleep
|
68
|
+
rescue MQTT::ProtocolException => pe
|
69
|
+
$log.debug "Handling #{pe.class}: #{pe.message}"
|
70
|
+
next
|
71
|
+
rescue Timeout::Error => te
|
72
|
+
$log.debug "Handling #{te.class}: #{te.message}"
|
73
|
+
next
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
57
77
|
end
|
58
78
|
|
59
79
|
# This method is called when shutting down.
|
@@ -61,13 +81,19 @@ module Fluent
|
|
61
81
|
def shutdown
|
62
82
|
super
|
63
83
|
|
64
|
-
@
|
84
|
+
@client.disconnect
|
65
85
|
end
|
66
86
|
|
67
87
|
def format_time(time)
|
68
|
-
|
88
|
+
case @time_format
|
89
|
+
when nil then
|
90
|
+
# default format is integer value
|
91
|
+
time
|
92
|
+
when "iso8601" then
|
93
|
+
# iso8601 format
|
69
94
|
Time.at(time).iso8601
|
70
95
|
else
|
96
|
+
# specified strftime format
|
71
97
|
Time.at(time).strftime(@time_format)
|
72
98
|
end
|
73
99
|
end
|
@@ -10,7 +10,7 @@ module Fluent
|
|
10
10
|
def emit(tag, es, chain)
|
11
11
|
es.each {|time,record|
|
12
12
|
$log.debug "#{tag}, #{format_time(time)}, #{record}"
|
13
|
-
@
|
13
|
+
@client.publish(rewrite_tag(tag), record.merge(timestamp_hash(time)).to_json)
|
14
14
|
}
|
15
15
|
$log.flush
|
16
16
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Fluent
|
2
|
-
class
|
2
|
+
class MqttBufferedOutput < BufferedOutput
|
3
3
|
require 'fluent/plugin/mqtt_output_mixin'
|
4
4
|
include Fluent::MqttOutputMixin
|
5
5
|
|
@@ -10,7 +10,8 @@ module Fluent
|
|
10
10
|
# This method is called when an event reaches to Fluentd.
|
11
11
|
# Convert the event to a raw string.
|
12
12
|
def format(tag, time, record)
|
13
|
-
[tag, time, record].
|
13
|
+
[tag, time, record].to_msgpack
|
14
|
+
#[tag, time, record].to_json + "\n"
|
14
15
|
end
|
15
16
|
|
16
17
|
# This method is called every flush interval. Write the buffer chunk
|
@@ -21,10 +22,21 @@ module Fluent
|
|
21
22
|
#
|
22
23
|
# NOTE! This method is called by internal thread, not Fluentd's main thread. So IO wait doesn't affect other plugins.
|
23
24
|
def write(chunk)
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
messages = {}
|
26
|
+
chunk.msgpack_each do |tag, time, record|
|
27
|
+
#$log.debug "Thread ID: #{Thread.current.object_id}, tag: #{tag}, time: #{format_time(time)}, record: #{record}"
|
28
|
+
messages[tag] = [] if messages[tag].nil?
|
29
|
+
messages[tag] << record.merge(timestamp_hash(time))
|
30
|
+
end
|
31
|
+
messages.keys.each do |tag|
|
32
|
+
$log.debug "Thread ID: #{Thread.current.object_id}, topic: #{rewrite_tag(tag)}, message: #{messages[tag]}"
|
33
|
+
@client.publish(rewrite_tag(tag), messages[tag].map {|m| m.to_json}.join(@bulk_trans_sep))
|
34
|
+
end
|
27
35
|
$log.flush
|
36
|
+
#json = json_parse(chunk.open {|io| io.readline})
|
37
|
+
#$log.debug "#{json[0]}, #{format_time(json[1])}, #{json[2]}"
|
38
|
+
#@client.publish(rewrite_tag(json[0]), (json[2].merge(timestamp_hash(json[1]))).to_json)
|
39
|
+
#$log.flush
|
28
40
|
end
|
29
41
|
end
|
30
42
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-mqtt-io
|
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
|
- Toyokazu Akiyama
|
8
8
|
autorequire:
|
9
9
|
bindir: []
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-12-
|
11
|
+
date: 2015-12-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|