logstash-input-jmx 0.1.4 → 0.1.5

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
  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: []