apolo 0.0.3
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.
- data/.gitignore +34 -0
- data/.rubocop.yml +93 -0
- data/.travis.yml +26 -0
- data/Gemfile +32 -0
- data/LICENSE +202 -0
- data/LICENSE.txt +201 -0
- data/README.md +47 -0
- data/Rakefile +2 -0
- data/Thorfile +29 -0
- data/apolo.gemspec +30 -0
- data/bin/apolo_cpu_socket +50 -0
- data/bin/apolo_cups +51 -0
- data/bin/apolo_tcp_sockets +49 -0
- data/lib/apolo.rb +6 -0
- data/lib/apolo/domains.rb +3 -0
- data/lib/apolo/domains/cpu_socket.rb +97 -0
- data/lib/apolo/domains/cups.rb +35 -0
- data/lib/apolo/domains/tcp_sockets.rb +13 -0
- data/lib/apolo/monitor.rb +143 -0
- data/lib/apolo/notifiers.rb +3 -0
- data/lib/apolo/notifiers/console.rb +19 -0
- data/lib/apolo/notifiers/nagios.rb +64 -0
- data/lib/apolo/notifiers/sqlite.rb +33 -0
- data/lib/apolo/reader.rb +32 -0
- data/lib/apolo/reader_config.rb +18 -0
- data/lib/apolo/readers.rb +0 -0
- data/lib/apolo/version.rb +3 -0
- metadata +189 -0
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Apolo
|
2
|
+
|
3
|
+
A lightweight framework based on a hexagonal architecture for building automation, monitoring, and metrics plugins in ruby.
|
4
|
+
|
5
|
+
The goals of the framework:
|
6
|
+
1. Ruby is an object-oriented language with great support for functional programming, and I want to make the most of that to keep apolo's code easy to change.
|
7
|
+
2. Clean and well-organised
|
8
|
+
I want a structure that communicates what each part of the system is doing.
|
9
|
+
3. DRY - The focus is on the domain classes so I can re-use them for Chef, Nagios, collectd, and what ever else I come across.
|
10
|
+
|
11
|
+
[][gem]
|
12
|
+
[][travis]
|
13
|
+
[][gemnasium]
|
14
|
+
[][codeclimate]
|
15
|
+
|
16
|
+
[gem]: https://rubygems.org/gems/apolo
|
17
|
+
[travis]: http://travis-ci.org/SteelHouseLabs/apolo
|
18
|
+
[gemnasium]: https://gemnasium.com/SteelHouseLabs/apolo
|
19
|
+
[codeclimate]: https://codeclimate.com/github/SteelHouseLabs/apolo
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
23
|
+
Add this line to your application's Gemfile:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
gem 'apolo'
|
27
|
+
```
|
28
|
+
|
29
|
+
And then execute:
|
30
|
+
|
31
|
+
$ bundle
|
32
|
+
|
33
|
+
Or install it yourself as:
|
34
|
+
|
35
|
+
$ gem install apolo
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
TODO: Write usage instructions here
|
40
|
+
|
41
|
+
## Contributing
|
42
|
+
|
43
|
+
1. Fork it ( https://github.com/[my-github-username]/apolo/fork )
|
44
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
45
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
46
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
47
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/Thorfile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
require "bundler"
|
4
|
+
require "thor/rake_compat"
|
5
|
+
|
6
|
+
class Default < Thor
|
7
|
+
include Thor::RakeCompat
|
8
|
+
Bundler::GemHelper.install_tasks
|
9
|
+
|
10
|
+
desc "build", "Build apolo-#{Apolo::VERSION}.gem into the pkg directory"
|
11
|
+
def build
|
12
|
+
Rake::Task["build"].execute
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "install", "Build and install apolo-#{Apolo::VERSION}.gem into system gems"
|
16
|
+
def install
|
17
|
+
Rake::Task["install"].execute
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "release", "Create tag v#{Apolo::VERSION} and build and push apolo-#{Apolo::VERSION}.gem to Rubygems"
|
21
|
+
def release
|
22
|
+
Rake::Task["release"].execute
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "spec", "Run RSpec code examples"
|
26
|
+
def spec
|
27
|
+
exec "rspec spec"
|
28
|
+
end
|
29
|
+
end
|
data/apolo.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'apolo/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'apolo'
|
8
|
+
spec.version = Apolo::VERSION
|
9
|
+
spec.authors = ['Efrén Fuentes', 'Thomas Vincent']
|
10
|
+
spec.email = ['thomasvincent@steelhouselabs.com']
|
11
|
+
spec.summary = %q{Metric, Monitoring & automation services framework.}
|
12
|
+
spec.description = %q{Metric, Monitoring & automation services framework.}
|
13
|
+
spec.homepage = ''
|
14
|
+
spec.license = 'Apache 2.0'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = %w[lib]
|
20
|
+
spec.required_rubygems_version = ">= 1.3.5"
|
21
|
+
spec.summary = spec.description
|
22
|
+
spec.test_files = Dir.glob("spec/**/*")
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
25
|
+
spec.add_dependency 'sequel', '~> 4.14'
|
26
|
+
spec.add_dependency 'sqlite3', '~> 1.3'
|
27
|
+
spec.add_dependency 'cupsffi', '~> 0.1'
|
28
|
+
spec.add_dependency "logger-better"
|
29
|
+
spec.add_dependency "tnt"
|
30
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'apolo'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
options = { critical: 101, warning: 101 }
|
6
|
+
|
7
|
+
begin
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.on('-c', '--critical MAX', 'Max cpu usage percentage for critical') { |v| options[:critical] = v }
|
10
|
+
opts.on('-w', '--warning MAX', 'Max cpu usage percentage for warning') { |v| options[:warning] = v }
|
11
|
+
end.parse!
|
12
|
+
rescue Exception => msg
|
13
|
+
puts msg
|
14
|
+
exit
|
15
|
+
end
|
16
|
+
|
17
|
+
# Supress warning messages.
|
18
|
+
original_verbose, $VERBOSE = $VERBOSE, nil
|
19
|
+
@@options = options
|
20
|
+
# Activate warning messages again.
|
21
|
+
$VERBOSE = original_verbose
|
22
|
+
|
23
|
+
class CheckCpuSocket < Apolo::Monitor
|
24
|
+
name 'CPU_Socket'
|
25
|
+
|
26
|
+
# Nagios notifier
|
27
|
+
notify Apolo::Notifiers::Nagios, file: 'nagios.cmd',\
|
28
|
+
host: 'localhost',\
|
29
|
+
service: 'CPU_Socket',\
|
30
|
+
warning: @@options[:warning].to_i,\
|
31
|
+
critical: @@options[:critical].to_i
|
32
|
+
|
33
|
+
run do
|
34
|
+
# create new CpuSocket for calculations
|
35
|
+
cpu_socket = Apolo::Domains::CpuSocket.new
|
36
|
+
|
37
|
+
# get percentage of usage for each socket
|
38
|
+
cpu_usage = cpu_socket.cpu_usage
|
39
|
+
|
40
|
+
# send notify to nagios
|
41
|
+
(0..cpu_socket.sockets).each do |socket|
|
42
|
+
notify message: "Socket #{socket} usage #{cpu_usage[socket]}", value: cpu_usage[socket]
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# create monitor and run it
|
49
|
+
monitor = CheckCpuSocket.new
|
50
|
+
monitor.run
|
data/bin/apolo_cups
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'apolo'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
options = { critical: 120, warning: 120 }
|
6
|
+
|
7
|
+
begin
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.on('-c', '--critical MAX', 'Max numbers of minutes on queue for critical') { |v| options[:critical] = v }
|
10
|
+
opts.on('-w', '--warning MAX', 'Max numbers of minutes on queue for warning') { |v| options[:warning] = v }
|
11
|
+
opts.on('-p' '--printer name', 'Printer name to check for jobs') { |v| options[:printer] = v }
|
12
|
+
end.parse!
|
13
|
+
rescue Exception => msg
|
14
|
+
puts msg
|
15
|
+
exit
|
16
|
+
end
|
17
|
+
|
18
|
+
# Supress warning messages.
|
19
|
+
original_verbose, $VERBOSE = $VERBOSE, nil
|
20
|
+
@@options = options
|
21
|
+
# Activate warning messages again.
|
22
|
+
$VERBOSE = original_verbose
|
23
|
+
|
24
|
+
|
25
|
+
class CheckCups < Apolo::Monitor
|
26
|
+
name 'CUPS'
|
27
|
+
|
28
|
+
# Notifiers
|
29
|
+
notify Apolo::Notifiers::Nagios, file: 'nagios.cmd',\
|
30
|
+
host: 'localhost',\
|
31
|
+
service: 'CUPS',\
|
32
|
+
warning: @@options[:warning].to_i,\
|
33
|
+
critical: @@options[:critical].to_i
|
34
|
+
|
35
|
+
run do
|
36
|
+
# create new Cups instance
|
37
|
+
cups = Apolo::Domains::Cups.new(@@options[:printer_name])
|
38
|
+
|
39
|
+
# send notify to nagios
|
40
|
+
if cups.jobs_count > 0
|
41
|
+
notify message: "Last job #{cups.minutes} minutes ago: #{cups.job[:id]} - #{cups.job[:dest]} - #{cups.job[:user]} - #{Time.at(cups.job[:creation_time])}", value: cups.minutes
|
42
|
+
else
|
43
|
+
notify message: 'Not jobs found', value: cups.minutes
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# create monitor and run it
|
50
|
+
monitor = CheckCups.new
|
51
|
+
monitor.run
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'apolo'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
options = { critical: 120, warning: 120, ipv6: false }
|
6
|
+
|
7
|
+
begin
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.on('-c', '--critical MAX', 'Max numbers of open sockets for critical') { |v| options[:critical] = v }
|
10
|
+
opts.on('-w', '--warning MAX', 'Max numbers of open sockets for warning') { |v| options[:warning] = v }
|
11
|
+
opts.on('-6' '--ipv6 (true|false)', 'Use IP6 or not') { options[:ipv6] = true }
|
12
|
+
end.parse!
|
13
|
+
rescue Exception => msg
|
14
|
+
puts msg
|
15
|
+
exit
|
16
|
+
end
|
17
|
+
|
18
|
+
# Supress warning messages.
|
19
|
+
original_verbose, $VERBOSE = $VERBOSE, nil
|
20
|
+
@@options = options
|
21
|
+
# Activate warning messages again.
|
22
|
+
$VERBOSE = original_verbose
|
23
|
+
|
24
|
+
|
25
|
+
class CheckTCPSockets < Apolo::Monitor
|
26
|
+
name 'TCP_Sockets'
|
27
|
+
|
28
|
+
# Notifiers
|
29
|
+
notify Apolo::Notifiers::Nagios, file: 'nagios.cmd',\
|
30
|
+
host: 'localhost',\
|
31
|
+
service: 'TCP_Sockets',\
|
32
|
+
warning: @@options[:warning].to_i,\
|
33
|
+
critical: @@options[:critical].to_i
|
34
|
+
|
35
|
+
run do
|
36
|
+
# get family options
|
37
|
+
family = @@options[:ipv6] ? :INET6 : :INET
|
38
|
+
|
39
|
+
sockets = Apolo::Domains::TCPSockets.connections(family)
|
40
|
+
|
41
|
+
# send notify to nagios
|
42
|
+
notify message: "#{sockets.count} connections #{family}", value: sockets.count
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# create monitor and run it
|
48
|
+
monitor = CheckTCPSockets.new
|
49
|
+
monitor.run
|
data/lib/apolo.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
module Apolo
|
2
|
+
module Domains
|
3
|
+
# CpuSocket
|
4
|
+
#
|
5
|
+
# Get information about percentage of usage for each cpu on all sockets
|
6
|
+
class CpuSocket
|
7
|
+
def initialize
|
8
|
+
@init_stats = statistics_of_process
|
9
|
+
sleep 1
|
10
|
+
@end_stats = statistics_of_process
|
11
|
+
end
|
12
|
+
|
13
|
+
# Get number of cpus for each socket
|
14
|
+
#
|
15
|
+
# @return [Integer] the number of cpus for sockets
|
16
|
+
def cpu_socket
|
17
|
+
cpus / (sockets + 1)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Get usage for cpus
|
21
|
+
#
|
22
|
+
# @return [Integer] the usage for cpus
|
23
|
+
def usage_sum(cores, stats)
|
24
|
+
usage_sum = 0
|
25
|
+
|
26
|
+
cores.each do |core|
|
27
|
+
line = stats[core + 1].split(' ')
|
28
|
+
usage_sum = line[1].to_i + line[2].to_i + line[3].to_i
|
29
|
+
end
|
30
|
+
|
31
|
+
usage_sum
|
32
|
+
end
|
33
|
+
|
34
|
+
# Get total of process
|
35
|
+
#
|
36
|
+
# @return [Integer] the total of process
|
37
|
+
def proc_total(cores, stats)
|
38
|
+
proc_total = 0
|
39
|
+
(1..4).each do |i|
|
40
|
+
cores.each do |core|
|
41
|
+
line = stats[core + 1].split(' ')
|
42
|
+
proc_total += line[i].to_i
|
43
|
+
end
|
44
|
+
end
|
45
|
+
proc_total
|
46
|
+
end
|
47
|
+
|
48
|
+
# Get usage for each cpu
|
49
|
+
#
|
50
|
+
# @return [Array] the percentage of usage for each cpu
|
51
|
+
def cpu_usage
|
52
|
+
cpu_usage = []
|
53
|
+
(0..sockets).each do |socket|
|
54
|
+
cores = (socket * cpu_socket..socket * cpu_socket + (cpu_socket - 1))
|
55
|
+
|
56
|
+
init_usage = usage_sum(cores, @init_stats)
|
57
|
+
end_usage = usage_sum(cores, @end_stats)
|
58
|
+
|
59
|
+
proc_usage = end_usage - init_usage
|
60
|
+
|
61
|
+
init_total = proc_total(cores, @init_stats)
|
62
|
+
end_total = proc_total(cores, @end_stats)
|
63
|
+
|
64
|
+
proctotal = (end_total - init_total)
|
65
|
+
|
66
|
+
usage = (proc_usage.to_f / proctotal.to_f)
|
67
|
+
|
68
|
+
cpu_usage[socket] = (100 * usage).to_f
|
69
|
+
end
|
70
|
+
cpu_usage
|
71
|
+
end
|
72
|
+
|
73
|
+
# Get number of sockets
|
74
|
+
#
|
75
|
+
# @return [Integer] the number of sockets on system
|
76
|
+
def sockets
|
77
|
+
File.readlines('/proc/cpuinfo').grep(/^physical id/).last.split(' ')[3].to_i
|
78
|
+
end
|
79
|
+
|
80
|
+
# Get number of cpus
|
81
|
+
#
|
82
|
+
# @return [Integer] the number of cpus on system
|
83
|
+
def cpus
|
84
|
+
File.readlines('/proc/cpuinfo').grep(/^processor/).count
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
# Get statistics of process
|
90
|
+
#
|
91
|
+
# @return [Array] the statistics of process
|
92
|
+
def statistics_of_process
|
93
|
+
File.readlines('/proc/stat')
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'cupsffi'
|
2
|
+
|
3
|
+
module Apolo
|
4
|
+
module Domains
|
5
|
+
class Cups
|
6
|
+
attr_accessor :jobs_count, :minutes, :job
|
7
|
+
def initialize(printer_name)
|
8
|
+
if printer_name.nil?
|
9
|
+
printer = CupsPrinter.new(printers.first)
|
10
|
+
@printer_name = printer.name
|
11
|
+
else
|
12
|
+
@printer_name = printer_name
|
13
|
+
end
|
14
|
+
|
15
|
+
get_data
|
16
|
+
end
|
17
|
+
|
18
|
+
def printers
|
19
|
+
CupsPrinter.get_all_printer_names
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_data
|
23
|
+
pointer = FFI::MemoryPointer.new :pointer
|
24
|
+
@jobs_count = CupsFFI::cupsGetJobs(pointer, @printer_name, 0, CupsFFI::CUPS_WHICHJOBS_ACTIVE)
|
25
|
+
@job = CupsFFI::CupsJobS.new(pointer.get_pointer(0))
|
26
|
+
|
27
|
+
if @jobs_count > 0
|
28
|
+
@minutes = (Time.now - Time.at(@job[:creation_time])).to_i / 60
|
29
|
+
else
|
30
|
+
@minutes = 0
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
module Apolo
|
2
|
+
class Monitor
|
3
|
+
class << self
|
4
|
+
def reader_templates
|
5
|
+
@reader_templates || []
|
6
|
+
end
|
7
|
+
|
8
|
+
def notifier_templates
|
9
|
+
@notifier_templates || []
|
10
|
+
end
|
11
|
+
|
12
|
+
def name_template
|
13
|
+
@name_template || self.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def running_template
|
17
|
+
@running_template
|
18
|
+
end
|
19
|
+
|
20
|
+
# Set the name of the app. Can be used by notifiers in order to have
|
21
|
+
# a better description of the service in question.
|
22
|
+
#
|
23
|
+
# @param [String, #read] name The name to be given to a Apolo-based
|
24
|
+
# class.
|
25
|
+
def name(val = nil)
|
26
|
+
@name_template = val if val
|
27
|
+
@name_template
|
28
|
+
end
|
29
|
+
|
30
|
+
# Register a reader in the list of readers.
|
31
|
+
#
|
32
|
+
# @param [Hash{Scout => String}, #read] reader_description A hash
|
33
|
+
# containing Reader class as key and its description as a value.
|
34
|
+
#
|
35
|
+
# @yield Block to be evaluated to configure the current {Reader}.
|
36
|
+
def using(reader_description, &block)
|
37
|
+
@reader_templates ||= []
|
38
|
+
@reader_templates << {
|
39
|
+
:reader_description => reader_description,
|
40
|
+
:block => block
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
# Register a notifier class in the list of notifications.
|
45
|
+
#
|
46
|
+
# @param [Class, #read] class A class that will be used to issue
|
47
|
+
# a notification. The class must accept a configuration hash in the
|
48
|
+
# constructor and also implement a #notify method that will receive an
|
49
|
+
# outpost instance. See {Apolo::Notifiers::Console} for an example.
|
50
|
+
#
|
51
|
+
# @param [Hash, #read] options Options that will be used to configure the
|
52
|
+
# notification class.
|
53
|
+
def notify(notifier, options={})
|
54
|
+
@notifier_templates ||= []
|
55
|
+
@notifier_templates << {:notifier => notifier, :options => options}
|
56
|
+
end
|
57
|
+
|
58
|
+
def run(&block)
|
59
|
+
@running_template = block
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns all the registered readers.
|
64
|
+
attr_reader :readers
|
65
|
+
|
66
|
+
# Returns all the registered notifiers.
|
67
|
+
attr_reader :notifiers
|
68
|
+
|
69
|
+
# Reader/setter for the name of this monitor
|
70
|
+
attr_accessor :name
|
71
|
+
|
72
|
+
# New instance of a Application-based class.
|
73
|
+
def initialize
|
74
|
+
@readers = Hash.new { |h, k| h[k] = [] }
|
75
|
+
@notifiers = {}
|
76
|
+
@name = self.class.name_template
|
77
|
+
@running = self.class.running_template
|
78
|
+
|
79
|
+
# Register readers
|
80
|
+
self.class.reader_templates.each do |template|
|
81
|
+
add_reader(template[:reader_description], &template[:block])
|
82
|
+
end
|
83
|
+
|
84
|
+
self.class.notifier_templates.each do |template|
|
85
|
+
add_notifier(template[:notifier], template[:options])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# @see Monitor#using
|
90
|
+
def add_reader(reader_description, &block)
|
91
|
+
config = ReaderConfig.new
|
92
|
+
config.instance_exec(&block) if block
|
93
|
+
|
94
|
+
reader_description.each do |reader, description|
|
95
|
+
@readers[reader] << {
|
96
|
+
:description => description,
|
97
|
+
:config => config
|
98
|
+
}
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# @see Monitor#notify
|
103
|
+
def add_notifier(notifier_name, options)
|
104
|
+
@notifiers[notifier_name] = options
|
105
|
+
end
|
106
|
+
|
107
|
+
def run
|
108
|
+
instance_exec &@running
|
109
|
+
end
|
110
|
+
|
111
|
+
def notify(data)
|
112
|
+
message = data[:message]
|
113
|
+
value = data[:value]
|
114
|
+
|
115
|
+
unless message && value
|
116
|
+
raise ArgumentError, 'You need to set :message and :value to send notify.'
|
117
|
+
end
|
118
|
+
|
119
|
+
@notifiers.each do |notifier, options|
|
120
|
+
# .dup is NOT reliable
|
121
|
+
options_copy = Marshal.load(Marshal.dump(options))
|
122
|
+
notifier.new(options_copy).notify(@name, message, value)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def get_data(reader_exec)
|
127
|
+
@readers.each do |reader, configurations|
|
128
|
+
if configurations.first[:description] == reader_exec
|
129
|
+
return run_reader(reader, configurations.last[:config])
|
130
|
+
end
|
131
|
+
end
|
132
|
+
raise ArgumentError, "Can't found #{reader_exec} reader."
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
def run_reader(reader, config)
|
138
|
+
reader_instance = reader.new(config)
|
139
|
+
|
140
|
+
reader_instance.execute
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|