fluent-plugin-mqtt-io 0.4.4 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/fluent-plugin-mqtt-io.gemspec +3 -3
- data/lib/fluent/plugin/in_mqtt.rb +14 -11
- data/lib/fluent/plugin/mqtt_proxy.rb +49 -36
- data/lib/fluent/plugin/out_mqtt.rb +19 -11
- metadata +13 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed837b9979b990f051238be99dac2c17ba2feb7b35c0f56910f706c3c426944a
|
4
|
+
data.tar.gz: 52628c53314f60215b6b97854103a3e99c0f313fe5a5031b1e6ed87e16cfc918
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2b38c5196fa566997d647fe63d3b2af44b323d218b5ec2c8e613cfa6662bd64401fbc99a68935950ddeb9b1b128f7571357e885276dfae5c6fbaaab62c088e9
|
7
|
+
data.tar.gz: 2d96a742d31d3b638f989999ea5c4919c95f61c64156d46d2dc01263842b036cf584bccc596c11634a3b95f358e84c112ce7b4c64b9eafc6fe48c367f0518381
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@ Mqtt::IO Plugin is deeply inspired by Fluent::Plugin::Mqtt.
|
|
5
5
|
|
6
6
|
https://github.com/yuuna/fluent-plugin-mqtt
|
7
7
|
|
8
|
-
Mqtt::IO plugin focus on federating components, e.g. sensors, messaging platform and databases.
|
8
|
+
Mqtt::IO plugin focus on federating components, e.g. sensors, messaging platform and databases. Connection encryption/decryption (TLS) is supported by ruby-mqtt but end-to-end encryption/decryption is not supported in this plugin. [fluent-plugin-jwt-filter](https://github.com/toyokazu/fluent-plugin-jwt-filter) can be used to encrypt/decrypt messages using JSON Web Token technology.
|
9
9
|
|
10
10
|
## Installation
|
11
11
|
|
@@ -83,6 +83,7 @@ The default MQTT topic is "#". Configurable options are the following:
|
|
83
83
|
- **initial_interval**: An initial value of retry interval (s) (default 1)
|
84
84
|
- **retry_inc_ratio**: An increase ratio of retry interval per connection failure (default 2 (double)). It may be better to set the value to 1 in a mobile environment for eager reconnection.
|
85
85
|
- **max_retry_interval**: Maximum value of retry interval (default 300)
|
86
|
+
- **max_retry_freq**: Threshold of retry frequency described by a number of retries per minutes. This option is provided for detecting failure via proxy services, e.g. ssh port forwarding. When the thresold is exceeded, MqttProxy::ExceedRetryFrequencyThresholdException is raised and the fluentd will be restarted. So, it is enough to be specified once for a MQTT server at a source/match directive in your configuration (default 10)
|
86
87
|
|
87
88
|
Input Plugin supports @label directive.
|
88
89
|
|
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "fluent-plugin-mqtt-io"
|
7
|
-
spec.version = "0.
|
7
|
+
spec.version = "0.5.0"
|
8
8
|
spec.authors = ["Toyokazu Akiyama"]
|
9
9
|
spec.email = ["toyokazu@gmail.com"]
|
10
10
|
|
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_dependency 'fluentd', [">= 0.14.0", "< 2"]
|
25
25
|
spec.add_dependency "mqtt", "~> 0.5"
|
26
26
|
|
27
|
-
spec.add_development_dependency "bundler", "
|
28
|
-
spec.add_development_dependency "rake", "~>
|
27
|
+
spec.add_development_dependency "bundler", [">= 1.14", "< 2.3"]
|
28
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
29
29
|
spec.add_development_dependency "test-unit"
|
30
30
|
end
|
@@ -20,11 +20,6 @@ module Fluent::Plugin
|
|
20
20
|
config_param :@type, :string, default: 'none'
|
21
21
|
end
|
22
22
|
|
23
|
-
# bulk_trans is deprecated
|
24
|
-
# multiple entries must be inputted as an Array
|
25
|
-
#config_param :bulk_trans, :bool, default: true
|
26
|
-
#config_param :bulk_trans_sep, :string, default: "\t"
|
27
|
-
|
28
23
|
config_section :monitor, required: false, multi: false do
|
29
24
|
desc 'Record received time into message or not.'
|
30
25
|
config_param :recv_time, :bool, default: false
|
@@ -66,20 +61,28 @@ module Fluent::Plugin
|
|
66
61
|
:in_mqtt
|
67
62
|
end
|
68
63
|
|
69
|
-
def
|
70
|
-
@get_thread.
|
64
|
+
def exit_thread
|
65
|
+
@get_thread.exit if !@get_thread.nil?
|
66
|
+
end
|
67
|
+
|
68
|
+
def disconnect
|
69
|
+
begin
|
70
|
+
@client.disconnect if @client.connected?
|
71
|
+
rescue => e
|
72
|
+
log.error "Error in in_mqtt#disconnect,#{e.class},#{e.message}"
|
73
|
+
end
|
74
|
+
exit_thread
|
71
75
|
end
|
72
76
|
|
73
|
-
def
|
74
|
-
|
77
|
+
def terminate
|
78
|
+
exit_thread
|
75
79
|
super
|
76
80
|
end
|
77
81
|
|
78
82
|
def after_connection
|
79
83
|
if @client.connected?
|
80
84
|
@client.subscribe(@topic)
|
81
|
-
|
82
|
-
@get_thread = Thread.new do
|
85
|
+
@get_thread = thread_create(:in_mqtt_get) do
|
83
86
|
@client.get do |topic, message|
|
84
87
|
emit(topic, message)
|
85
88
|
end
|
@@ -20,8 +20,10 @@ module Fluent::Plugin
|
|
20
20
|
base.config_param :initial_interval, :integer, default: 1
|
21
21
|
base.desc 'Specify increasing ratio of connection retry interval.'
|
22
22
|
base.config_param :retry_inc_ratio, :integer, default: 2
|
23
|
-
base.desc 'Specify maximum connection retry interval.'
|
23
|
+
base.desc 'Specify the maximum connection retry interval.'
|
24
24
|
base.config_param :max_retry_interval, :integer, default: 300
|
25
|
+
base.desc 'Specify threshold of retry frequency as number of retries per minutes. Frequency is monitored per retry.'
|
26
|
+
base.config_param :max_retry_freq, :integer, default: 10
|
25
27
|
|
26
28
|
base.config_section :security, required: false, multi: false do
|
27
29
|
### User based authentication
|
@@ -44,11 +46,20 @@ module Fluent::Plugin
|
|
44
46
|
|
45
47
|
class MqttError < StandardError; end
|
46
48
|
|
49
|
+
class ExceedRetryFrequencyThresholdException < StandardError; end
|
50
|
+
|
47
51
|
def current_plugin_name
|
48
52
|
# should be implemented
|
49
53
|
end
|
50
54
|
|
51
55
|
def start_proxy
|
56
|
+
# Start a thread from main thread for handling a thread generated
|
57
|
+
# by MQTT::Client#get (in_mqtt). Dummy thread is used for out_mqtt
|
58
|
+
# to keep the same implementation style.
|
59
|
+
@proxy_thread = thread_create("#{current_plugin_name}_proxy".to_sym, &method(:proxy))
|
60
|
+
end
|
61
|
+
|
62
|
+
def proxy
|
52
63
|
log.debug "start mqtt proxy for #{current_plugin_name}"
|
53
64
|
log.debug "start to connect mqtt broker #{@host}:#{@port}"
|
54
65
|
opts = {
|
@@ -68,12 +79,13 @@ module Fluent::Plugin
|
|
68
79
|
end
|
69
80
|
|
70
81
|
init_retry_interval
|
82
|
+
@retry_sequence = []
|
71
83
|
@client = MQTT::Client.new(opts)
|
72
84
|
connect
|
73
85
|
end
|
74
86
|
|
75
87
|
def shutdown_proxy
|
76
|
-
|
88
|
+
disconnect
|
77
89
|
end
|
78
90
|
|
79
91
|
def init_retry_interval
|
@@ -81,29 +93,43 @@ module Fluent::Plugin
|
|
81
93
|
end
|
82
94
|
|
83
95
|
def increment_retry_interval
|
84
|
-
return @
|
96
|
+
return @max_retry_interval if @retry_interval >= @max_retry_interval
|
85
97
|
@retry_interval = @retry_interval * @retry_inc_ratio
|
86
98
|
end
|
87
99
|
|
88
|
-
def
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
100
|
+
def update_retry_sequence(e)
|
101
|
+
@retry_sequence << {time: Time.now, error: "#{e.class}: #{e.message}"}
|
102
|
+
# delete old retry records
|
103
|
+
while @retry_sequence[0][:time] < Time.now - 60
|
104
|
+
@retry_sequence.shift
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def check_retry_frequency
|
109
|
+
return if @retry_sequence.size <= 1
|
110
|
+
if @retry_sequence.size > @max_retry_freq
|
111
|
+
log.error "Retry frequency threshold is exceeded: #{@retry_sequence}"
|
112
|
+
raise ExceedRetryFrequencyThresholdException
|
97
113
|
end
|
98
114
|
end
|
99
115
|
|
100
|
-
def
|
101
|
-
|
116
|
+
def retry_connect(e, message)
|
117
|
+
log.error "#{message},#{e.class},#{e.message}"
|
118
|
+
log.error "Retry in #{@retry_interval} sec"
|
119
|
+
update_retry_sequence(e)
|
120
|
+
check_retry_frequency
|
121
|
+
disconnect
|
122
|
+
sleep @retry_interval
|
123
|
+
increment_retry_interval
|
124
|
+
connect
|
125
|
+
# never reach here
|
102
126
|
end
|
103
127
|
|
104
|
-
def
|
128
|
+
def disconnect
|
105
129
|
# should be implemented
|
106
|
-
|
130
|
+
end
|
131
|
+
|
132
|
+
def terminate
|
107
133
|
end
|
108
134
|
|
109
135
|
def rescue_disconnection
|
@@ -114,22 +140,13 @@ module Fluent::Plugin
|
|
114
140
|
begin
|
115
141
|
yield
|
116
142
|
rescue MQTT::ProtocolException => e
|
117
|
-
# TODO:
|
118
|
-
# Thread created via fluentd thread API, e.g. thread_create,
|
119
|
-
# cannot catch MQTT::ProtocolException raised from @read_thread
|
120
|
-
# in ruby-mqtt. So, the current version uses plugin local thread
|
121
|
-
# @connect_thread to catch it.
|
122
143
|
retry_connect(e, "Protocol error occurs in #{current_plugin_name}.")
|
123
|
-
raise MqttError, "Protocol error occurs."
|
124
144
|
rescue Timeout::Error => e
|
125
145
|
retry_connect(e, "Timeout error occurs in #{current_plugin_name}.")
|
126
|
-
raise Timeout::Error, "Timeout error occurs."
|
127
146
|
rescue SystemCallError => e
|
128
147
|
retry_connect(e, "System call error occurs in #{current_plugin_name}.")
|
129
|
-
raise SystemCallError, "System call error occurs."
|
130
148
|
rescue StandardError=> e
|
131
149
|
retry_connect(e, "The other error occurs in #{current_plugin_name}.")
|
132
|
-
raise StandardError, "The other error occurs."
|
133
150
|
rescue MQTT::NotConnectedException=> e
|
134
151
|
# Since MQTT::NotConnectedException is raised only on publish,
|
135
152
|
# connection error should be catched before this error.
|
@@ -137,7 +154,7 @@ module Fluent::Plugin
|
|
137
154
|
# to prevent waistful increment of retry interval.
|
138
155
|
#log.error "MQTT not connected exception occurs.,#{e.class},#{e.message}"
|
139
156
|
#retry_connect(e, "MQTT not connected exception occurs.")
|
140
|
-
raise MqttError, "MQTT not connected exception occurs in #{current_plugin_name}."
|
157
|
+
#raise MqttError, "MQTT not connected exception occurs in #{current_plugin_name}."
|
141
158
|
end
|
142
159
|
end
|
143
160
|
|
@@ -148,16 +165,12 @@ module Fluent::Plugin
|
|
148
165
|
end
|
149
166
|
|
150
167
|
def connect
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
init_retry_interval
|
158
|
-
thread = after_connection
|
159
|
-
thread.join
|
160
|
-
end
|
168
|
+
rescue_disconnection do
|
169
|
+
@client.connect
|
170
|
+
log.debug "connected to mqtt broker #{@host}:#{@port} for #{current_plugin_name}"
|
171
|
+
init_retry_interval
|
172
|
+
thread = after_connection
|
173
|
+
thread.join
|
161
174
|
end
|
162
175
|
end
|
163
176
|
end
|
@@ -89,27 +89,35 @@ module Fluent::Plugin
|
|
89
89
|
# Shutdown the thread and close sockets or files here.
|
90
90
|
def shutdown
|
91
91
|
shutdown_proxy
|
92
|
-
|
92
|
+
exit_thread
|
93
93
|
super
|
94
94
|
end
|
95
95
|
|
96
|
-
def
|
97
|
-
@dummy_thread.
|
96
|
+
def exit_thread
|
97
|
+
@dummy_thread.exit if !@dummy_thread.nil?
|
98
98
|
end
|
99
99
|
|
100
|
-
def
|
101
|
-
|
102
|
-
|
103
|
-
|
100
|
+
def disconnect
|
101
|
+
begin
|
102
|
+
@client.disconnect if @client.connected?
|
103
|
+
rescue => e
|
104
|
+
log.error "Error in out_mqtt#disconnect,#{e.class},#{e.message}"
|
104
105
|
end
|
105
|
-
|
106
|
+
exit_thread
|
106
107
|
end
|
107
108
|
|
108
|
-
def
|
109
|
-
|
109
|
+
def terminate
|
110
|
+
exit_thread
|
110
111
|
super
|
111
112
|
end
|
112
113
|
|
114
|
+
def after_connection
|
115
|
+
@dummy_thread = thread_create(:out_mqtt_dummy) do
|
116
|
+
Thread.stop
|
117
|
+
end
|
118
|
+
@dummy_thread
|
119
|
+
end
|
120
|
+
|
113
121
|
def current_plugin_name
|
114
122
|
:out_mqtt
|
115
123
|
end
|
@@ -148,7 +156,7 @@ module Fluent::Plugin
|
|
148
156
|
end
|
149
157
|
|
150
158
|
def publish(tag, time, record)
|
151
|
-
log.debug "MqttOutput::#{caller_locations(1,1)[0].label}: #{rewrite_tag(
|
159
|
+
log.debug "MqttOutput::#{caller_locations(1,1)[0].label}: #{rewrite_tag(tag)}, #{time}, #{add_send_time(record)}"
|
152
160
|
@client.publish(
|
153
161
|
rewrite_tag(tag),
|
154
162
|
@formatter.format(tag, time, add_send_time(record)),
|
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.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Toyokazu Akiyama
|
8
8
|
autorequire:
|
9
9
|
bindir: []
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -48,30 +48,36 @@ dependencies:
|
|
48
48
|
name: bundler
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
|
-
- - "
|
51
|
+
- - ">="
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: '1.14'
|
54
|
+
- - "<"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '2.3'
|
54
57
|
type: :development
|
55
58
|
prerelease: false
|
56
59
|
version_requirements: !ruby/object:Gem::Requirement
|
57
60
|
requirements:
|
58
|
-
- - "
|
61
|
+
- - ">="
|
59
62
|
- !ruby/object:Gem::Version
|
60
63
|
version: '1.14'
|
64
|
+
- - "<"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '2.3'
|
61
67
|
- !ruby/object:Gem::Dependency
|
62
68
|
name: rake
|
63
69
|
requirement: !ruby/object:Gem::Requirement
|
64
70
|
requirements:
|
65
71
|
- - "~>"
|
66
72
|
- !ruby/object:Gem::Version
|
67
|
-
version: '
|
73
|
+
version: '13.0'
|
68
74
|
type: :development
|
69
75
|
prerelease: false
|
70
76
|
version_requirements: !ruby/object:Gem::Requirement
|
71
77
|
requirements:
|
72
78
|
- - "~>"
|
73
79
|
- !ruby/object:Gem::Version
|
74
|
-
version: '
|
80
|
+
version: '13.0'
|
75
81
|
- !ruby/object:Gem::Dependency
|
76
82
|
name: test-unit
|
77
83
|
requirement: !ruby/object:Gem::Requirement
|
@@ -127,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
127
133
|
- !ruby/object:Gem::Version
|
128
134
|
version: '0'
|
129
135
|
requirements: []
|
130
|
-
rubygems_version: 3.
|
136
|
+
rubygems_version: 3.1.4
|
131
137
|
signing_key:
|
132
138
|
specification_version: 4
|
133
139
|
summary: fluentd input/output plugin for mqtt broker
|