logstash-input-jmx 0.1.4 → 0.1.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 67673b34c4e945d059fcaa7e33a03ca2070b1bba
4
- data.tar.gz: 7f2d0ad1b534e028be342a40576e051fd5d5b55d
3
+ metadata.gz: 7086a6d48c28232b76bc569a275c3bb32a09c08e
4
+ data.tar.gz: b84125c9b177064bc94aa5b1379089fd3c931296
5
5
  SHA512:
6
- metadata.gz: 1880ae440dbc2769ac3f56a00cea10c256740992663ca0ef86050a715e5ed5838cf29571b0ba576383a1b8292f5a31b674f7a54ca76fc9c259e6de85756c566d
7
- data.tar.gz: 1680bf84de7847953ad9d98aab0144b60c37b1be82058680c0e045236c96e7ee25b16288320f8e81471668ca7e42582581f61b641d29ef451130118d4ffd497e
6
+ metadata.gz: db45a1f480c834c8b1d12e2648cf61b9d33eb6670abd356d966adf4406a7db7f1190a9b2d7098adfad75046d2fdd0961c07d6fad3ca128840228677739007f5a
7
+ data.tar.gz: b0d578838b8d9da72a0e6fe3e5e3c1815ee7faa4d2952688a217878f9e98dfddffd2fbf6e7115fa39baad7518caf0aee6d5ac55b86aeab9b906d7202fd7d1242
@@ -106,73 +106,55 @@ class LogStash::Inputs::Jmx < LogStash::Inputs::Base
106
106
  # Indicate number of thread launched to retrieve metrics
107
107
  config :nb_thread, :validate => :number, :default => 4
108
108
 
109
- # Read and parse json conf
110
- private
111
- def read_conf(file_conf)
112
- @logger.debug("Parse json #{file_conf} to ruby data structure")
113
- json = File.read(file_conf)
114
- LogStash::Json.load(json)
115
- end
116
-
109
+ #Error messages
110
+ MISSING_CONFIG_PARAMETER = "Missing parameter '%s'."
111
+ BAD_TYPE_CONFIG_PARAMETER = "Bad type for parameter '%{param}', expecting '%{expected}', found '%{actual}'."
112
+ MISSING_QUERY_PARAMETER = "Missing parameter '%s' in queries[%d]."
113
+ BAD_TYPE_QUERY = "Bad type for queries[%{index}], expecting '%{expected}', found '%{actual}'."
114
+ BAD_TYPE_QUERY_PARAMETER = "Bad type for parameter '%{param}' in queries[%{index}], expecting '%{expected}', found '%{actual}'."
117
115
  # Verify that all required parameter are present in the conf_hash
118
- private
119
- def check_conf(conf_hash,file_conf)
120
- #Check required parameters
121
- @logger.debug("Check that required parameters are define with good types in #{conf_hash}")
122
- parameter = {'host' => 'String'.class, 'port' => 1.class, 'queries' => [].class}
123
- parameter.each_key do |param|
124
- if conf_hash.has_key?(param)
125
- unless conf_hash[param].instance_of?(parameter[param])
126
- @logger.error("Bad syntax for conf file #{file_conf}. Bad types for parameter #{param}, expecting #{parameter[param]}, found #{conf_hash[param].class}.")
127
- return false
128
- end
129
- else
130
- @logger.error("Bad syntax for conf file #{file_conf}. Missing parameter #{param}.")
131
- return false
132
- end
116
+ public
117
+ def validate_configuration(conf_hash)
118
+ validation_errors = []
119
+ #Check required parameters in configuration
120
+ ["host", "port","queries"].each do |param|
121
+ validation_errors << MISSING_CONFIG_PARAMETER % param unless conf_hash.has_key?(param)
133
122
  end
134
123
 
135
- @logger.debug('Check optional parameters types')
136
- parameter = {'alias' => 'String'.class}
137
- parameter.each_key do |param|
138
- if conf_hash.has_key?(param)
139
- unless conf_hash[param].instance_of?(parameter[param])
140
- @logger.error("Bad syntax for conf file #{file_conf}. Bad types for parameter #{param}, expecting #{parameter[param]}, found #{conf_hash[param].class}.")
141
- return false
142
- end
124
+ #Validate parameters type in configuration
125
+ {"host" => String, "port" => Fixnum, "alias" => String }.each do |param, expected_type|
126
+ if conf_hash.has_key?(param) && !conf_hash[param].instance_of?(expected_type)
127
+ validation_errors << BAD_TYPE_CONFIG_PARAMETER % { :param => param, :expected => expected_type, :actual => conf_hash[param].class }
143
128
  end
144
129
  end
145
130
 
146
- @logger.debug('Check that required parameters are define with good types for queries')
147
- parameter = {'object_name' => 'String'.class}
148
- parameter.each_key do |param|
149
- conf_hash['queries'].each do |query|
150
- if query.has_key?(param)
151
- unless query[param].instance_of?(parameter[param])
152
- @logger.error("Bad syntax for conf file #{file_conf}. Bad types for parameter #{param} in query #{query}, expecting #{parameter[param]}, found #{conf_hash[param].class}.")
153
- return false
131
+ if conf_hash.has_key?("queries")
132
+ if !conf_hash["queries"].respond_to?(:each)
133
+ validation_errors << BAD_TYPE_CONFIG_PARAMETER % { :param => 'queries', :expected => Enumerable, :actual => conf_hash['queries'].class }
134
+ else
135
+ conf_hash['queries'].each_with_index do |query,index|
136
+ unless query.respond_to?(:[]) && query.respond_to?(:has_key?)
137
+ validation_errors << BAD_TYPE_QUERY % {:index => index, :expected => Hash, :actual => query.class}
138
+ next
139
+ end
140
+ #Check required parameters in each query
141
+ ["object_name"].each do |param|
142
+ validation_errors << MISSING_QUERY_PARAMETER % [param,index] unless query.has_key?(param)
143
+ end
144
+ #Validate parameters type in each query
145
+ {"object_name" => String, "object_alias" => String }.each do |param, expected_type|
146
+ if query.has_key?(param) && !query[param].instance_of?(expected_type)
147
+ validation_errors << BAD_TYPE_QUERY_PARAMETER % { :param => param, :index => index, :expected => expected_type, :actual => query[param].class }
148
+ end
154
149
  end
155
- else
156
- @logger.error("Bad syntax for conf file #{file_conf} in query #{query}. Missing parameter #{param}.")
157
- return false
158
- end
159
- end
160
- end
161
150
 
162
- @logger.debug('Check optional parameters types for queries')
163
- parameter = {'object_alias' => 'String'.class, 'attributes' => [].class}
164
- parameter.each_key do |param|
165
- conf_hash['queries'].each do |query|
166
- if query.has_key?(param)
167
- unless query[param].instance_of?(parameter[param])
168
- @logger.error("Bad syntax for conf file #{file_conf} in query #{query}. Bad types for parameter #{param}, expecting #{parameter[param]}, found #{conf_hash[param].class}.")
169
- return false
151
+ if query.has_key?("attributes") && !query["attributes"].respond_to?(:each)
152
+ validation_errors << BAD_TYPE_QUERY_PARAMETER % { :param => 'attributes', :index => index, :expected => Enumerable, :actual => query['attributes'].class }
170
153
  end
171
154
  end
172
155
  end
173
156
  end
174
-
175
- true
157
+ return validation_errors
176
158
  end
177
159
 
178
160
  private
@@ -215,8 +197,6 @@ class LogStash::Inputs::Jmx < LogStash::Inputs::Base
215
197
  # Thread function to retrieve metrics from JMX
216
198
  private
217
199
  def thread_jmx(queue_conf,queue)
218
- require 'jmx4r'
219
-
220
200
  while true
221
201
  begin
222
202
  @logger.debug('Wait config to retrieve from queue conf')
@@ -317,43 +297,45 @@ class LogStash::Inputs::Jmx < LogStash::Inputs::Base
317
297
 
318
298
  public
319
299
  def register
320
- @logger.info('Registering files in', :path => @path)
300
+ require 'thread'
301
+ require 'jmx4r'
321
302
 
322
- @logger.info('Create queue conf used to send jmx conf to jmx collector threads')
303
+ @logger.info("Create queue dispatching JMX requests to threads")
323
304
  @queue_conf = Queue.new
324
305
 
325
- @logger.info('Compile regexp for group alias object replacement')
306
+ @logger.info("Compile regexp for group alias object replacement")
326
307
  @regexp_group_alias_object = Regexp.new('(?:\${(.*?)})+')
327
308
  end
328
309
 
329
310
  public
330
311
  def run(queue)
331
- require 'thread'
332
-
333
312
  begin
334
313
  threads = []
335
- @logger.info("Init #{@nb_thread} jmx collector threads")
314
+ @logger.info("Initialize #{@nb_thread} threads for JMX metrics collection")
336
315
  @nb_thread.times do
337
316
  threads << Thread.new { thread_jmx(@queue_conf,queue) }
338
317
  end
339
318
 
340
319
  while true
341
- @logger.info("Load conf files in #{@path}")
320
+ @logger.info("Loading configuration files in path", :path => @path)
342
321
  Dir.foreach(@path) do |item|
322
+ next if item == '.' or item == '..'
343
323
  begin
344
- next if item == '.' or item == '..'
345
324
  file_conf = File.join(@path, item)
346
- @logger.debug("Load conf file #{file_conf}")
347
- conf_hash = read_conf(file_conf)
348
- if check_conf(conf_hash,file_conf)
349
- @logger.debug("Add conf #{conf_hash} to the queue conf")
325
+ @logger.debug? && @logger.debug("Loading configuration from file", :file => file_conf)
326
+ config_string = File.read(file_conf)
327
+ conf_hash = LogStash::Json.load(config_string)
328
+ validation_errors = validate_configuration(conf_hash)
329
+ if validation_errors.empty?
330
+ @logger.debug? && @logger.debug("Add configuration to the queue", :config => conf_hash)
350
331
  @queue_conf << conf_hash
332
+ else
333
+ @logger.warn("Issue with configuration file", :file => file_conf,
334
+ :validation_errors => validation_errors)
351
335
  end
352
336
  rescue Exception => ex
353
- @logger.warn("Issue parsing file #{file_conf}")
354
- @logger.warn(ex.message)
355
- @logger.warn(ex.backtrace.join("\n"))
356
- next
337
+ @logger.warn("Issue loading configuration from file", :file => file_conf,
338
+ :exception => ex.message, :backtrace => ex.backtrace)
357
339
  end
358
340
  end
359
341
  @logger.debug('Wait until the queue conf is empty')
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-input-jmx'
4
- s.version = '0.1.4'
4
+ s.version = '0.1.5'
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "Retrieve metrics from jmx."
7
7
  s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
@@ -25,5 +25,6 @@ Gem::Specification.new do |s|
25
25
  s.add_runtime_dependency 'jmx4r'
26
26
 
27
27
  s.add_development_dependency 'logstash-devutils'
28
+ s.add_development_dependency 'logstash-codec-plain'
28
29
  end
29
30
 
@@ -1 +1,82 @@
1
+ # encoding: utf-8
1
2
  require "logstash/devutils/rspec/spec_helper"
3
+ require "logstash/inputs/jmx"
4
+ require "logstash/codecs/plain"
5
+ require 'stud/temporary'
6
+
7
+ describe LogStash::Inputs::Jmx do
8
+
9
+ let(:jmx_config_path) { Stud::Temporary.directory }
10
+ after(:each) do
11
+ FileUtils.remove_dir(jmx_config_path)
12
+ end
13
+
14
+ subject { LogStash::Inputs::Jmx.new("path" => jmx_config_path)}
15
+
16
+ context "#validate_configuration(conf_hash)" do
17
+ #Reference to error messages
18
+ MISSING_CONFIG_PARAMETER = LogStash::Inputs::Jmx::MISSING_CONFIG_PARAMETER
19
+ BAD_TYPE_CONFIG_PARAMETER = LogStash::Inputs::Jmx::BAD_TYPE_CONFIG_PARAMETER
20
+ BAD_TYPE_QUERY = LogStash::Inputs::Jmx::BAD_TYPE_QUERY
21
+ MISSING_QUERY_PARAMETER = LogStash::Inputs::Jmx::MISSING_QUERY_PARAMETER
22
+ BAD_TYPE_QUERY_PARAMETER = LogStash::Inputs::Jmx::BAD_TYPE_QUERY_PARAMETER
23
+
24
+ let(:minimal_config) { {"host"=>"localhost","port"=>1234,"queries" => [] } }
25
+
26
+ context "global configuration" do
27
+ it "return [] for valid configuration" do
28
+ #Minimal configuration
29
+ expect(subject.validate_configuration(minimal_config)).to eq([])
30
+ # Re-test with java objects from JrJackson serialization
31
+ if LogStash::Environment.jruby?
32
+ require "java"
33
+ expect(subject.validate_configuration({"host"=>"localhost","port"=>1234,"queries" => java.util.ArrayList.new})).to eq([])
34
+ end
35
+ end
36
+
37
+ it "return error message for missing mandatory parameters" do
38
+ expect(subject.validate_configuration({})).to eq([MISSING_CONFIG_PARAMETER % "host", MISSING_CONFIG_PARAMETER % "port", MISSING_CONFIG_PARAMETER % "queries"])
39
+ end
40
+
41
+ it "return error message for invalid parameters type" do
42
+ expect(subject.validate_configuration({"host"=>1234,"port"=>1234,"queries" => []})).to eq([BAD_TYPE_CONFIG_PARAMETER % {:param => "host", :expected => String, :actual => Fixnum}])
43
+ expect(subject.validate_configuration({"host"=>"localhost","port"=>"1234","queries" => []})).to eq([BAD_TYPE_CONFIG_PARAMETER % {:param => "port", :expected => Fixnum, :actual => String}])
44
+ expect(subject.validate_configuration({"host"=>"localhost","port"=>1234,"queries" => "my_query"})).to eq([BAD_TYPE_CONFIG_PARAMETER % {:param => "queries", :expected => Enumerable, :actual => String}])
45
+ end
46
+ end
47
+
48
+ context "query objects in configuration" do
49
+ it "return [] for valid query message" do
50
+ #Minimal query object
51
+ minimal_config["queries"] = [{"object_name" => "minimal"}]
52
+ expect(subject.validate_configuration(minimal_config)).to eq([])
53
+ #Full query object
54
+ minimal_config["queries"] = [{
55
+ "object_name" => "java.lang:type=Runtime",
56
+ "attributes" => [ "Uptime", "StartTime" ],
57
+ "object_alias" => "Runtime"}]
58
+ expect(subject.validate_configuration(minimal_config)).to eq([])
59
+ end
60
+ it "return error message for invalid query object type" do
61
+ minimal_config["queries"] = [ "1234" ]
62
+ expect(subject.validate_configuration(minimal_config)).to eq([BAD_TYPE_QUERY % { :index => 0, :expected => Hash, :actual => String }])
63
+ end
64
+
65
+ it "return error message for missing mandatory query parameter" do
66
+ minimal_config["queries"] = [ {} ]
67
+ expect(subject.validate_configuration(minimal_config)).to eq([MISSING_QUERY_PARAMETER % ["object_name",0] ])
68
+ end
69
+
70
+ it "return error message for invalid query parameters type" do
71
+ minimal_config["queries"] = [ { "object_name" => 1234} ]
72
+ expect(subject.validate_configuration(minimal_config)).to eq([BAD_TYPE_QUERY_PARAMETER % {:param => "object_name", :index => 0, :expected => String, :actual => Fixnum} ])
73
+
74
+ minimal_config["queries"] = [ { "object_name" => "1234", "object_alias" => 1234} ]
75
+ expect(subject.validate_configuration(minimal_config)).to eq([BAD_TYPE_QUERY_PARAMETER % {:param => "object_alias", :index => 0, :expected => String, :actual => Fixnum} ])
76
+
77
+ minimal_config["queries"] = [ { "object_name" => "1234", "attributes" => 1234} ]
78
+ expect(subject.validate_configuration(minimal_config)).to eq([BAD_TYPE_QUERY_PARAMETER % {:param => "attributes", :index => 0, :expected => Enumerable, :actual => Fixnum} ])
79
+ end
80
+ end
81
+ end
82
+ end
metadata CHANGED
@@ -1,17 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-input-jmx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-20 00:00:00.000000000 Z
11
+ date: 2015-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- requirement: !ruby/object:Gem::Requirement
14
+ name: logstash-core
15
+ version_requirements: !ruby/object:Gem::Requirement
15
16
  requirements:
16
17
  - - '>='
17
18
  - !ruby/object:Gem::Version
@@ -19,10 +20,7 @@ dependencies:
19
20
  - - <
20
21
  - !ruby/object:Gem::Version
21
22
  version: 2.0.0
22
- name: logstash-core
23
- prerelease: false
24
- type: :runtime
25
- version_requirements: !ruby/object:Gem::Requirement
23
+ requirement: !ruby/object:Gem::Requirement
26
24
  requirements:
27
25
  - - '>='
28
26
  - !ruby/object:Gem::Version
@@ -30,34 +28,50 @@ dependencies:
30
28
  - - <
31
29
  - !ruby/object:Gem::Version
32
30
  version: 2.0.0
31
+ prerelease: false
32
+ type: :runtime
33
33
  - !ruby/object:Gem::Dependency
34
+ name: jmx4r
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
34
40
  requirement: !ruby/object:Gem::Requirement
35
41
  requirements:
36
42
  - - '>='
37
43
  - !ruby/object:Gem::Version
38
44
  version: '0'
39
- name: jmx4r
40
45
  prerelease: false
41
46
  type: :runtime
47
+ - !ruby/object:Gem::Dependency
48
+ name: logstash-devutils
42
49
  version_requirements: !ruby/object:Gem::Requirement
43
50
  requirements:
44
51
  - - '>='
45
52
  - !ruby/object:Gem::Version
46
53
  version: '0'
47
- - !ruby/object:Gem::Dependency
48
54
  requirement: !ruby/object:Gem::Requirement
49
55
  requirements:
50
56
  - - '>='
51
57
  - !ruby/object:Gem::Version
52
58
  version: '0'
53
- name: logstash-devutils
54
59
  prerelease: false
55
60
  type: :development
61
+ - !ruby/object:Gem::Dependency
62
+ name: logstash-codec-plain
56
63
  version_requirements: !ruby/object:Gem::Requirement
57
64
  requirements:
58
65
  - - '>='
59
66
  - !ruby/object:Gem::Version
60
67
  version: '0'
68
+ requirement: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ prerelease: false
74
+ type: :development
61
75
  description: This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program
62
76
  email: info@elastic.co
63
77
  executables: []