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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e083f992d750102e55064612775e4d03b188e50fa1d6f3585837124bd681ea90
4
- data.tar.gz: 5803786735463c1c29f47b608374926fc73106310ce5d8af8594fe909744f7ff
3
+ metadata.gz: ed837b9979b990f051238be99dac2c17ba2feb7b35c0f56910f706c3c426944a
4
+ data.tar.gz: 52628c53314f60215b6b97854103a3e99c0f313fe5a5031b1e6ed87e16cfc918
5
5
  SHA512:
6
- metadata.gz: 6bdb809393dae2de2e85ad36a2f0e745ade9cc12834f136e4081aced2bd56aae14d9ed0e9dbfd307d91f34336b0ec98ae2921cbfee2a3f07599878d120c8f026
7
- data.tar.gz: fa59faf530eb786320f0bf7a6f115b6b4db12e44334aba6bfcac56fa9b2e563d0e1efa499a7302e69a297ef98fc7e1ed3a73cd355a057c9a7b16dcf367b47dd5
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. Encryption/Decryption is not supported in this plugin but [fluent-plugin-jwt-filter](https://github.com/toyokazu/fluent-plugin-jwt-filter) can be used to encrypt/decrypt messages using JSON Web Token technology.
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.4.4"
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", "~> 1.14"
28
- spec.add_development_dependency "rake", "~> 12.0"
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 kill_thread
70
- @get_thread.kill if !@get_thread.nil?
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 after_disconnection
74
- kill_thread
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
- #@get_thread = thread_create(:in_mqtt_get) do
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
- @client.disconnect
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 @retry_interval if @retry_interval >= @max_retry_interval
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 retry_connect(e, message)
89
- if !@_retrying
90
- log.error "#{message},#{e.class},#{e.message}"
91
- log.error "Retry in #{@retry_interval} sec"
92
- timer_execute("#{current_plugin_name}_connect".to_sym, @retry_interval, repeat: false, &method(:connect))
93
- @_retrying = true
94
- increment_retry_interval
95
- after_disconnection
96
- @client.disconnect if @client.connected?
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 kill_connect_thread
101
- @connect_thread.kill if !@connect_thread.nil?
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 after_disconnection
128
+ def disconnect
105
129
  # should be implemented
106
- kill_connect_thread
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
- #@connect_thread = thread_create("#{current_plugin_name}_monitor".to_sym) do
152
- @_retrying = false
153
- @connect_thread = Thread.new do
154
- rescue_disconnection do
155
- @client.connect
156
- log.debug "connected to mqtt broker #{@host}:#{@port} for #{current_plugin_name}"
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
- kill_thread
92
+ exit_thread
93
93
  super
94
94
  end
95
95
 
96
- def kill_thread
97
- @dummy_thread.kill if !@dummy_thread.nil?
96
+ def exit_thread
97
+ @dummy_thread.exit if !@dummy_thread.nil?
98
98
  end
99
99
 
100
- def after_connection
101
- #@dummy_thread = thread_create(:out_mqtt_dummy) do
102
- @dummy_thread = Thread.new do
103
- Thread.stop
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
- @dummy_thread
106
+ exit_thread
106
107
  end
107
108
 
108
- def after_disconnection
109
- kill_thread
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(rewrite_tag(tag))}, #{time}, #{add_send_time(record)}"
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.4
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: 2019-12-19 00:00:00.000000000 Z
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: '12.0'
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: '12.0'
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.0.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