fluent-plugin-elasticsearch-stats 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.
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fluent
4
+ module Plugin
5
+ module ElasticsearchStats
6
+ module Utils
7
+ def self.hash_flatten_keys(hash, overwite: false, separator: nil)
8
+ return nil unless hash.is_a?(Hash)
9
+
10
+ flattened = {}
11
+ stack = [hash.each]
12
+ keys = []
13
+
14
+ while stack.any?
15
+ current = stack.pop
16
+
17
+ begin
18
+ child_k, child_v = current.next
19
+ stack.push current
20
+
21
+ if child_v.is_a?(Hash)
22
+ stack.push child_v.each
23
+ keys.push child_k
24
+ else
25
+ flattened_key = keys + [child_k]
26
+ flattened_key = flattened_key.join(separator) if separator
27
+ raise KeyError, "key #{flattened_key} already present" if !overwite && flattened.key?(flattened_key)
28
+
29
+ flattened[flattened_key] = child_v
30
+ end
31
+ rescue StopIteration
32
+ keys.pop
33
+ next
34
+ end
35
+ end
36
+
37
+ flattened
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'elasticsearch_stats/client'
4
+ require_relative 'elasticsearch_stats/metadata'
5
+ require_relative 'elasticsearch_stats/metric'
6
+ require_relative 'elasticsearch_stats/collector'
7
+ require_relative 'elasticsearch_stats/base_data'
8
+ require_relative 'elasticsearch_stats/cluster_health_data'
9
+ require_relative 'elasticsearch_stats/cluster_stats_data'
10
+ require_relative 'elasticsearch_stats/nodes_stats_data'
11
+ require_relative 'elasticsearch_stats/indices_stats_data'
12
+ require_relative 'elasticsearch_stats/dangling_data'
13
+ require_relative 'elasticsearch_stats/utils'
@@ -0,0 +1,191 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2024- Thomas Tych
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # 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
+ require 'fluent/plugin/input'
19
+
20
+ require_relative 'elasticsearch_stats'
21
+
22
+ module Fluent
23
+ module Plugin
24
+ class ElasticsearchStatsInput < Fluent::Plugin::Input
25
+ NAME = 'elasticsearch_stats'
26
+ Fluent::Plugin.register_input(NAME, self)
27
+
28
+ helpers :event_emitter, :timer
29
+
30
+ DEFAULT_TAG = NAME
31
+ DEFAULT_URLS = ['http://localhost:9200'].freeze
32
+ DEFAULT_TIMEOUT = 10
33
+ DEFAULT_USER_AGENT = NAME
34
+
35
+ DEFAULT_INTERVAL = 300
36
+
37
+ DEFAULT_TIMESTAMP_FORMAT = :iso
38
+
39
+ DEFAULT_CLUSTER_HEALTH = true
40
+ DEFAULT_CLUSTER_HEALTH_LEVEL = :cluster
41
+ DEFAULT_CLUSTER_HEALTH_LOCAL = false
42
+ DEFAULT_CLUSTER_STATS = true
43
+ DEFAULT_NODES_STATS = true
44
+ DEFAULT_NODES_STATS_LEVEL = :node
45
+ DEFAULT_NODES_STATS_METRICS = nil
46
+ DEFAULT_INDICES_STATS = true
47
+ DEFAULT_INDICES_STATS_LEVEL = :indices
48
+ DEFAULT_INDICES = nil
49
+ DEFAULT_SHARDS_STATS = true
50
+ DEFAULT_DANGLING = false
51
+ DEFAULT_INDEX_BASE_PATTERN = nil # '/(.*)/'
52
+ DEFAULT_INDEX_BASE_REPLACEMENT = '\1'
53
+ DEFAULT_EVENT_NAME_SEPARATOR = '/'
54
+ DEFAULT_SKIP_SYSTEM_INDICES = true
55
+
56
+ ALLOWED_CLUSTER_HEALTH_LEVELS = Fluent::Plugin::ElasticsearchStats::Client::ALLOWED_CLUSTER_HEALTH_LEVELS
57
+ ALLOWED_NODES_STATS_LEVELS = Fluent::Plugin::ElasticsearchStats::Client::ALLOWED_NODES_STATS_LEVELS
58
+ ALLOWED_INDICES_STATS_LEVELS = Fluent::Plugin::ElasticsearchStats::Client::ALLOWED_INDICES_LEVELS
59
+
60
+ desc 'tag to emit events on'
61
+ config_param :tag, :string, default: DEFAULT_TAG
62
+ desc 'list or urls to poll'
63
+ config_param :urls, :array, value_type: :string, default: DEFAULT_URLS
64
+ desc 'request timeout'
65
+ config_param :timeout, :integer, default: DEFAULT_TIMEOUT
66
+ desc 'username for basic auth'
67
+ config_param :username, :string, default: nil
68
+ desc 'password for basic auth'
69
+ config_param :password, :string, default: nil
70
+ desc 'request user agent'
71
+ config_param :user_agent, :string, default: DEFAULT_USER_AGENT
72
+ desc 'CA cert file to use for request'
73
+ config_param :ca_file, :string, default: nil
74
+ desc 'option to verify certificate/host'
75
+ config_param :verify_ssl, :bool, default: true
76
+
77
+ desc 'interval for probe execution'
78
+ config_param :interval, :time, default: DEFAULT_INTERVAL
79
+
80
+ desc 'prefix for metric fields'
81
+ config_param :metric_prefix, :string, default: nil
82
+ desc 'prefix for metadata fields'
83
+ config_param :metadata_prefix, :string, default: nil
84
+ desc 'event timestamp format'
85
+ config_param :timestamp_format, :enum, list: %i[iso epochmillis], default: DEFAULT_TIMESTAMP_FORMAT
86
+ desc 'event name separator'
87
+ config_param :event_name_separator, :string, default: DEFAULT_EVENT_NAME_SEPARATOR
88
+
89
+ desc 'collect cluster health events'
90
+ config_param :cluster_health, :bool, default: DEFAULT_CLUSTER_HEALTH
91
+ desc 'details level of the health information'
92
+ config_param :cluster_health_level, :enum, list: ALLOWED_CLUSTER_HEALTH_LEVELS,
93
+ default: DEFAULT_CLUSTER_HEALTH_LEVEL
94
+ desc 'retrieves information from the local node only'
95
+ config_param :cluster_health_local, :bool, default: DEFAULT_CLUSTER_HEALTH_LOCAL
96
+
97
+ desc 'collect cluster stats events'
98
+ config_param :cluster_stats, :bool, default: DEFAULT_CLUSTER_STATS
99
+
100
+ desc 'collect nodes stats events'
101
+ config_param :nodes_stats, :bool, default: DEFAULT_NODES_STATS
102
+ desc 'details level for the nodes stats'
103
+ config_param :nodes_stats_level, :enum, list: ALLOWED_NODES_STATS_LEVELS, default: DEFAULT_NODES_STATS_LEVEL
104
+ desc 'limits information to specific metrics for nodes stats'
105
+ config_param :nodes_stats_metrics, :array, value_type: :string, default: DEFAULT_NODES_STATS_METRICS
106
+
107
+ desc 'enable indices_stats collect'
108
+ config_param :indices_stats, :bool, default: DEFAULT_INDICES_STATS
109
+ desc 'indices_stats indices to collect'
110
+ config_param :indices, :array, value_type: :string, default: DEFAULT_INDICES
111
+ desc 'indices_stats details level'
112
+ config_param :indices_stats_level, :enum, list: ALLOWED_INDICES_STATS_LEVELS, default: DEFAULT_INDICES_STATS_LEVEL
113
+
114
+ desc 'collect dangling events'
115
+ config_param :dangling, :bool, default: DEFAULT_DANGLING
116
+
117
+ desc 'base index pattern to generate aggregated index metrics'
118
+ config_param :index_base_pattern, :regexp, default: DEFAULT_INDEX_BASE_PATTERN
119
+ desc 'base index pattern replacement to generate aggregated index metrics'
120
+ config_param :index_base_replacement, :string, default: DEFAULT_INDEX_BASE_REPLACEMENT
121
+
122
+ # desc 'skip system indices'
123
+ # config_param :skip_system_indices, :bool, default: DEFAULT_SKIP_SYSTEM_INDICES
124
+
125
+ def configure(conf)
126
+ super
127
+
128
+ raise Fluent::ConfigError, 'tag should not be empty' if tag.empty?
129
+ raise Fluent::ConfigError, 'urls should not be empty' if urls.empty?
130
+
131
+ @mutex_emit = Mutex.new
132
+
133
+ ElasticsearchStats::Metadata.metadata_prefix = metadata_prefix
134
+ ElasticsearchStats::Metric.metric_prefix = metric_prefix
135
+ ElasticsearchStats::Metric.timestamp_format = timestamp_format
136
+ ElasticsearchStats::Metric.index_base_pattern = index_base_pattern
137
+ ElasticsearchStats::Metric.index_base_replacement = index_base_replacement
138
+ ElasticsearchStats::Metric.name_separator = event_name_separator
139
+
140
+ configure_elasticsearchs
141
+ end
142
+
143
+ def configure_elasticsearchs
144
+ @elasticsearchs = []
145
+ urls.each do |url|
146
+ client = ElasticsearchStats::Client.new(
147
+ url: url, timeout: timeout, username: username, password: password,
148
+ user_agent: user_agent, ca_file: ca_file, verify_ssl: verify_ssl,
149
+ log: log
150
+ )
151
+ @elasticsearchs << ElasticsearchStats::Collector.new(
152
+ client: client,
153
+ stats_config: self,
154
+ log: log
155
+ )
156
+ end
157
+ end
158
+
159
+ def start
160
+ super
161
+
162
+ timer_execute(:execute_collect_first, 1, repeat: false, &method(:execute_collect)) if interval > 60
163
+
164
+ timer_execute(:execute_collect, interval, repeat: true, &method(:execute_collect))
165
+ end
166
+
167
+ def execute_collect
168
+ threads = []
169
+ @elasticsearchs.each do |elasticsearch|
170
+ threads << Thread.new do
171
+ metrics = elasticsearch.collect_stats_metrics
172
+ events = MultiEventStream.new(
173
+ [Fluent::EventTime.now] * metrics.size,
174
+ metrics
175
+ )
176
+ emit_events(events)
177
+ end
178
+ end
179
+ threads.each(&:join)
180
+ end
181
+
182
+ def emit_events(events)
183
+ return if !events || events.empty?
184
+
185
+ @mutex_emit.synchronize do
186
+ router.emit_stream(tag, events)
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
metadata ADDED
@@ -0,0 +1,253 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-elasticsearch-stats
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Thomas Tych
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-03-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bump
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.10.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.10.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.5.6
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.5.6
41
+ - !ruby/object:Gem::Dependency
42
+ name: byebug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '11.1'
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 11.1.3
51
+ type: :development
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '11.1'
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 11.1.3
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 13.1.0
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: 13.1.0
75
+ - !ruby/object:Gem::Dependency
76
+ name: reek
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '6.1'
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 6.1.4
85
+ type: :development
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - "~>"
90
+ - !ruby/object:Gem::Version
91
+ version: '6.1'
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 6.1.4
95
+ - !ruby/object:Gem::Dependency
96
+ name: rubocop
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: '1.56'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: '1.56'
109
+ - !ruby/object:Gem::Dependency
110
+ name: rubocop-rake
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: 0.6.0
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: 0.6.0
123
+ - !ruby/object:Gem::Dependency
124
+ name: simplecov
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: 0.22.0
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: 0.22.0
137
+ - !ruby/object:Gem::Dependency
138
+ name: test-unit
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: 3.6.1
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: 3.6.1
151
+ - !ruby/object:Gem::Dependency
152
+ name: timecop
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - "~>"
156
+ - !ruby/object:Gem::Version
157
+ version: 0.9.6
158
+ type: :development
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: 0.9.6
165
+ - !ruby/object:Gem::Dependency
166
+ name: faraday
167
+ requirement: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - "~>"
170
+ - !ruby/object:Gem::Version
171
+ version: '2.9'
172
+ type: :runtime
173
+ prerelease: false
174
+ version_requirements: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - "~>"
177
+ - !ruby/object:Gem::Version
178
+ version: '2.9'
179
+ - !ruby/object:Gem::Dependency
180
+ name: fluentd
181
+ requirement: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: 0.14.10
186
+ - - "<"
187
+ - !ruby/object:Gem::Version
188
+ version: '2'
189
+ type: :runtime
190
+ prerelease: false
191
+ version_requirements: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: 0.14.10
196
+ - - "<"
197
+ - !ruby/object:Gem::Version
198
+ version: '2'
199
+ description:
200
+ email:
201
+ - thomas.tych@gmail.com
202
+ executables: []
203
+ extensions: []
204
+ extra_rdoc_files: []
205
+ files:
206
+ - ".gitignore"
207
+ - ".gitlab-ci.yml"
208
+ - ".rubocop.yml"
209
+ - ".ruby-version"
210
+ - Gemfile
211
+ - Gemfile.lock
212
+ - LICENSE
213
+ - README.md
214
+ - Rakefile
215
+ - fluent-plugin-elasticsearch-stats.gemspec
216
+ - lib/fluent/plugin/elasticsearch_stats.rb
217
+ - lib/fluent/plugin/elasticsearch_stats/base_data.rb
218
+ - lib/fluent/plugin/elasticsearch_stats/client.rb
219
+ - lib/fluent/plugin/elasticsearch_stats/cluster_health_data.rb
220
+ - lib/fluent/plugin/elasticsearch_stats/cluster_stats_data.rb
221
+ - lib/fluent/plugin/elasticsearch_stats/collector.rb
222
+ - lib/fluent/plugin/elasticsearch_stats/dangling_data.rb
223
+ - lib/fluent/plugin/elasticsearch_stats/indices_stats_data.rb
224
+ - lib/fluent/plugin/elasticsearch_stats/metadata.rb
225
+ - lib/fluent/plugin/elasticsearch_stats/metric.rb
226
+ - lib/fluent/plugin/elasticsearch_stats/nodes_stats_data.rb
227
+ - lib/fluent/plugin/elasticsearch_stats/utils.rb
228
+ - lib/fluent/plugin/in_elasticsearch_stats.rb
229
+ homepage: https://gitlab.com/ttych/fluent-plugin-elasticsearch-status
230
+ licenses:
231
+ - Apache-2.0
232
+ metadata:
233
+ rubygems_mfa_required: 'true'
234
+ post_install_message:
235
+ rdoc_options: []
236
+ require_paths:
237
+ - lib
238
+ required_ruby_version: !ruby/object:Gem::Requirement
239
+ requirements:
240
+ - - ">="
241
+ - !ruby/object:Gem::Version
242
+ version: 2.4.0
243
+ required_rubygems_version: !ruby/object:Gem::Requirement
244
+ requirements:
245
+ - - ">="
246
+ - !ruby/object:Gem::Version
247
+ version: '0'
248
+ requirements: []
249
+ rubygems_version: 3.5.6
250
+ signing_key:
251
+ specification_version: 4
252
+ summary: fluentd plugin to generate elasticsearch cluster stats events.
253
+ test_files: []