observed 0.1.1 → 0.2.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +9 -9
- data/.travis.yml +4 -0
- data/README.md +53 -78
- data/examples/observed.rb +1 -1
- data/exe/observed-oneshot +3 -1
- data/features/explicit_routing.feature +33 -0
- data/features/oneshot.feature +4 -0
- data/features/test_in_single_ruby_source.feature +4 -0
- data/integrations/observed-clockwork/features/run_observed_inside_clockwork.feature +6 -7
- data/integrations/observed-clockwork/lib/observed/clockwork/version.rb +1 -1
- data/integrations/observed-clockwork/lib/observed/clockwork.rb +0 -1
- data/integrations/observed-clockwork/observed-clockwork.gemspec +1 -1
- data/integrations/observed-eventmachine/.gitignore +17 -0
- data/integrations/observed-eventmachine/Gemfile +8 -0
- data/integrations/observed-eventmachine/LICENSE.txt +22 -0
- data/integrations/observed-eventmachine/README.md +29 -0
- data/integrations/observed-eventmachine/Rakefile +1 -0
- data/integrations/observed-eventmachine/examples/observed.rb +30 -0
- data/integrations/observed-eventmachine/features/integration_via_single_ruby_source.feature +48 -0
- data/integrations/observed-eventmachine/features/support/env.rb +8 -0
- data/integrations/observed-eventmachine/lib/observed/eventmachine/version.rb +5 -0
- data/integrations/observed-eventmachine/lib/observed/eventmachine.rb +70 -0
- data/integrations/observed-eventmachine/observed-eventmachine.gemspec +28 -0
- data/lib/observed/application/oneshot.rb +14 -37
- data/lib/observed/builtin_plugins/file.rb +5 -14
- data/lib/observed/builtin_plugins/stdout.rb +7 -14
- data/lib/observed/config.rb +4 -4
- data/lib/observed/config_builder.rb +154 -87
- data/lib/observed/config_dsl.rb +2 -8
- data/lib/observed/configurable.rb +61 -3
- data/lib/observed/context.rb +90 -0
- data/lib/observed/default/observer.rb +2 -5
- data/lib/observed/default.rb +0 -1
- data/lib/observed/event_bus.rb +31 -0
- data/lib/observed/execution_job_factory.rb +95 -0
- data/lib/observed/job.rb +163 -0
- data/lib/observed/jobbed_event_bus.rb +33 -0
- data/lib/observed/logging.rb +40 -0
- data/lib/observed/observer.rb +1 -0
- data/lib/observed/observer_helpers/timer.rb +13 -5
- data/lib/observed/pluggable.rb +11 -0
- data/lib/observed/reporter/regexp_matching.rb +2 -1
- data/lib/observed/reporter/report_formatting.rb +57 -0
- data/lib/observed/reporter.rb +0 -2
- data/lib/observed/system.rb +11 -78
- data/lib/observed/translator.rb +22 -0
- data/lib/observed/version.rb +1 -1
- data/lib/observed.rb +10 -12
- data/omnibus-observed/.gitignore +9 -0
- data/omnibus-observed/Berksfile +3 -0
- data/omnibus-observed/Berksfile.lock +52 -0
- data/omnibus-observed/Gemfile +4 -0
- data/omnibus-observed/README.md +102 -0
- data/omnibus-observed/Vagrantfile +93 -0
- data/omnibus-observed/config/projects/observed.rb +20 -0
- data/omnibus-observed/config/software/observed.rb +19 -0
- data/omnibus-observed/package-scripts/observed/makeselfinst +27 -0
- data/omnibus-observed/package-scripts/observed/postinst +17 -0
- data/omnibus-observed/package-scripts/observed/postrm +9 -0
- data/plugins/observed-fluentd/lib/observed/fluentd/version.rb +1 -1
- data/plugins/observed-gauge/README.md +5 -0
- data/plugins/observed-gauge/lib/observed/gauge/version.rb +1 -1
- data/plugins/observed-gauge/lib/observed/gauge.rb +11 -13
- data/plugins/observed-gauge/observed-gauge.gemspec +1 -1
- data/plugins/observed-gauge/spec/gauge_spec.rb +7 -7
- data/plugins/observed-growl/Gemfile +6 -0
- data/plugins/observed-growl/lib/observed/growl.rb +80 -0
- data/plugins/observed-http/lib/observed/http/version.rb +1 -1
- data/plugins/observed-http/lib/observed/http.rb +10 -8
- data/plugins/observed-http/observed-http.gemspec +1 -1
- data/plugins/observed-http/spec/http_spec.rb +62 -7
- data/plugins/observed-http/spec/integration_spec.rb +14 -0
- data/plugins/observed-shell/Gemfile +5 -0
- data/plugins/observed-shell/lib/observed/shell.rb +54 -0
- data/run-integration-tests +81 -0
- data/spec/builtin_plugins/stdout_spec.rb +7 -3
- data/spec/config_builder_spec.rb +42 -59
- data/spec/config_dsl_spec.rb +4 -0
- data/spec/configurable_spec.rb +141 -31
- data/spec/event_bus_spec.rb +16 -0
- data/spec/execution_job_factory_spec.rb +35 -0
- data/spec/job_factory_spec.rb +16 -0
- data/spec/job_spec.rb +228 -0
- data/spec/jobbed_event_bus_spec.rb +38 -0
- data/spec/observed_spec.rb +203 -0
- data/spec/observer_helpers/timer_spec.rb +187 -0
- data/spec/oneshot_spec.rb +7 -2
- data/spec/system_spec.rb +5 -39
- metadata +55 -12
- data/lib/observed/default/reporter.rb +0 -17
- data/lib/observed/reader.rb +0 -14
- data/lib/observed/writer.rb +0 -14
- data/spec/reader_spec.rb +0 -15
- data/spec/writer_spec.rb +0 -16
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'observed/eventmachine/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "observed-eventmachine"
|
8
|
+
spec.version = Observed::EM::VERSION
|
9
|
+
spec.authors = ["KUOKA Yusuke"]
|
10
|
+
spec.email = ["yusuke.kuoka@gree.net"]
|
11
|
+
spec.description = %q{An integration of Observed with EventMachine}
|
12
|
+
spec.summary = %q{observed-eventmachine allows running Observed observations on EventMachine to achieve scalability}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
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 = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'eventmachine', '~> 1.0.3'
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
spec.add_development_dependency "cucumber"
|
27
|
+
spec.add_development_dependency "aruba"
|
28
|
+
end
|
@@ -3,10 +3,7 @@ require 'optparse'
|
|
3
3
|
require 'pathname'
|
4
4
|
|
5
5
|
require 'observed/config'
|
6
|
-
require 'observed/
|
7
|
-
require 'observed/config_dsl'
|
8
|
-
require 'observed/observer'
|
9
|
-
require 'observed/system'
|
6
|
+
require 'observed/context'
|
10
7
|
|
11
8
|
module Observed
|
12
9
|
|
@@ -28,17 +25,12 @@ module Observed
|
|
28
25
|
end
|
29
26
|
|
30
27
|
def run(observation_name=nil)
|
31
|
-
system.run(observation_name)
|
32
|
-
end
|
33
|
-
|
34
|
-
def logger
|
35
|
-
@logger ||= Logger.new(STDOUT)
|
28
|
+
@system.run(observation_name)
|
36
29
|
end
|
37
30
|
|
38
31
|
class << self
|
39
|
-
def
|
40
|
-
|
41
|
-
command_line_args = argv.dup
|
32
|
+
def parse_argv!(argv)
|
33
|
+
command_line_args = argv
|
42
34
|
|
43
35
|
args = {}
|
44
36
|
|
@@ -55,38 +47,29 @@ module Observed
|
|
55
47
|
|
56
48
|
opts.parse!(command_line_args)
|
57
49
|
|
58
|
-
|
50
|
+
unless command_line_args.size == 1 || command_line_args.size == 2
|
59
51
|
fail InvalidArgumentError, "Invalid number of arguments #{command_line_args.size} where arguments are #{command_line_args}"
|
60
52
|
end
|
61
53
|
|
62
|
-
args[:config_file] = command_line_args.
|
54
|
+
args[:config_file] = command_line_args.shift
|
55
|
+
|
56
|
+
args
|
57
|
+
end
|
63
58
|
|
59
|
+
def from_argv(argv)
|
60
|
+
args = parse_argv!(argv.dup)
|
64
61
|
create(args)
|
65
62
|
end
|
66
63
|
|
67
64
|
# @param [Hash<Symbol,String>] args
|
68
65
|
# @option args [Array<String>] :argv The Ruby's `ARGV` like object which is treated as intialization parameters for Oneshoft application.
|
69
66
|
def create(args)
|
70
|
-
|
71
|
-
|
72
|
-
else
|
73
|
-
STDOUT
|
74
|
-
end
|
75
|
-
logger = Logger.new(logger_out)
|
76
|
-
logger.level = if args[:debug]
|
77
|
-
Logger::DEBUG
|
78
|
-
else
|
79
|
-
Logger::INFO
|
80
|
-
end
|
81
|
-
sys = Observed::System.new(logger: logger)
|
67
|
+
ctx = Observed::Context.new(args)
|
68
|
+
sys = ctx.system
|
82
69
|
config = if args[:yaml_file]
|
83
70
|
YAML.load_file(args[:yaml_file])
|
84
71
|
elsif args[:config_file]
|
85
|
-
|
86
|
-
config_builder = Observed::ConfigBuilder.new(system: sys, logger: logger)
|
87
|
-
config_dsl = Observed::ConfigDSL.new(builder: config_builder, logger: logger)
|
88
|
-
config_dsl.eval_file(path)
|
89
|
-
config_dsl.config
|
72
|
+
sys.config
|
90
73
|
elsif args[:config]
|
91
74
|
c = args[:config]
|
92
75
|
c
|
@@ -103,12 +86,6 @@ module Observed
|
|
103
86
|
end
|
104
87
|
end
|
105
88
|
|
106
|
-
private
|
107
|
-
|
108
|
-
def system
|
109
|
-
@system
|
110
|
-
end
|
111
|
-
|
112
89
|
end
|
113
90
|
end
|
114
91
|
end
|
@@ -1,16 +1,17 @@
|
|
1
1
|
require 'observed/hash/fetcher'
|
2
2
|
require 'observed/reporter'
|
3
3
|
require 'observed/reporter/regexp_matching'
|
4
|
+
require 'observed/reporter/report_formatting'
|
4
5
|
|
5
6
|
module Observed
|
6
7
|
module BuiltinPlugins
|
7
8
|
class File < Observed::Reporter
|
8
9
|
|
9
10
|
include Observed::Reporter::RegexpMatching
|
11
|
+
include Observed::Reporter::ReportFormatting
|
10
12
|
|
11
13
|
UNDEFINED = Object.new
|
12
14
|
|
13
|
-
attribute :format, default: -> tag, time, data { "#{Time.at(time)} #{tag} #{data}" }
|
14
15
|
attribute :path
|
15
16
|
attribute :mode, default: :append
|
16
17
|
|
@@ -18,15 +19,7 @@ module Observed
|
|
18
19
|
# @param [Time] time
|
19
20
|
# @param [Hash] data
|
20
21
|
def report(tag, time, data)
|
21
|
-
|
22
|
-
formatted_data = case num_params
|
23
|
-
when 3
|
24
|
-
format.call(tag, time, data)
|
25
|
-
when 4
|
26
|
-
format.call(tag, time, data, Observed::Hash::Fetcher.new(data))
|
27
|
-
else
|
28
|
-
fail "Number of parameters for the function for the key :format must be 3 or 4, but was #{num_params}(#{format.parameters}"
|
29
|
-
end
|
22
|
+
formatted_data = format_report(tag, time, data)
|
30
23
|
mode = case self.mode
|
31
24
|
when :append, 'a'
|
32
25
|
'a'
|
@@ -34,16 +27,14 @@ module Observed
|
|
34
27
|
'w'
|
35
28
|
else
|
36
29
|
fail "Unsupported value for the parameter `:mode`: Supported values are :append, :overwrite, " +
|
37
|
-
|
30
|
+
"'a', 'w'. The specified value is #{self.mode.inspect}"
|
38
31
|
end
|
39
32
|
::File.open(path, mode) do |f|
|
40
33
|
f.puts formatted_data
|
41
34
|
end
|
42
35
|
end
|
43
36
|
|
44
|
-
|
45
|
-
'file'
|
46
|
-
end
|
37
|
+
plugin_name 'file'
|
47
38
|
end
|
48
39
|
end
|
49
40
|
end
|
@@ -2,34 +2,27 @@ require 'observed/hash/fetcher'
|
|
2
2
|
require 'observed/observer'
|
3
3
|
require 'observed/reporter'
|
4
4
|
require 'observed/reporter/regexp_matching'
|
5
|
+
require 'observed/reporter/report_formatting'
|
5
6
|
|
6
7
|
module Observed
|
7
8
|
module BuiltinPlugins
|
8
9
|
class Stdout < Observed::Reporter
|
9
10
|
|
10
11
|
include Observed::Reporter::RegexpMatching
|
12
|
+
include Observed::Reporter::ReportFormatting
|
11
13
|
|
12
|
-
attribute :
|
14
|
+
attribute :output, default: STDOUT
|
13
15
|
|
14
16
|
# @param [String] tag
|
15
17
|
# @param [Time] time
|
16
18
|
# @param [Hash] data
|
19
|
+
# @param [Object] format_result
|
17
20
|
def report(tag, time, data)
|
18
|
-
|
19
|
-
formatted_data
|
20
|
-
when 3
|
21
|
-
format.call(tag, time, data)
|
22
|
-
when 4
|
23
|
-
format.call(tag, time, data, Observed::Hash::Fetcher.new(data))
|
24
|
-
else
|
25
|
-
fail "Number of parameters for the function for the key :format must be 3 or 4, but was #{num_params}(#{format.parameters}"
|
26
|
-
end
|
27
|
-
puts formatted_data
|
21
|
+
formatted_data = format_report(tag, time, data)
|
22
|
+
output.puts formatted_data
|
28
23
|
end
|
29
24
|
|
30
|
-
|
31
|
-
'stdout'
|
32
|
-
end
|
25
|
+
plugin_name 'stdout'
|
33
26
|
end
|
34
27
|
end
|
35
28
|
end
|
data/lib/observed/config.rb
CHANGED
@@ -7,10 +7,6 @@ module Observed
|
|
7
7
|
|
8
8
|
include Observed::Configurable
|
9
9
|
|
10
|
-
# !@attribute [rw] writers
|
11
|
-
# @return [Array<Observed::Writer>]
|
12
|
-
attribute :writers
|
13
|
-
|
14
10
|
# !@attribute [rw] readers
|
15
11
|
# @return [Array<Observed::Reader>]
|
16
12
|
attribute :readers
|
@@ -23,5 +19,9 @@ module Observed
|
|
23
19
|
# @return [Array<Observed::Observer>]
|
24
20
|
attribute :observers
|
25
21
|
|
22
|
+
# !@attribuet [rw] translators
|
23
|
+
# @return [Array<Observed::Translator]
|
24
|
+
attribute :translators
|
25
|
+
|
26
26
|
end
|
27
27
|
end
|
@@ -1,36 +1,65 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'thread'
|
3
|
+
|
1
4
|
require 'observed/config'
|
2
5
|
require 'observed/configurable'
|
3
6
|
require 'observed/default'
|
4
7
|
require 'observed/hash'
|
5
|
-
require 'observed/
|
6
|
-
require 'observed/
|
8
|
+
require 'observed/translator'
|
9
|
+
require 'observed/execution_job_factory'
|
7
10
|
|
8
11
|
module Observed
|
9
12
|
|
13
|
+
class ProcObserver < Observed::Observer
|
14
|
+
def initialize(&block)
|
15
|
+
@block = block
|
16
|
+
end
|
17
|
+
def observe(data=nil, options=nil)
|
18
|
+
@block.call data, options
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class ProcTranslator < Observed::Translator
|
23
|
+
def initialize(&block)
|
24
|
+
@block = block
|
25
|
+
end
|
26
|
+
def translate(tag, time, data)
|
27
|
+
@block.call data, {tag: tag, time: time}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class ProcReporter < Observed::Reporter
|
32
|
+
def initialize(tag_pattern, &block)
|
33
|
+
@tag_pattern = tag_pattern
|
34
|
+
@block = block
|
35
|
+
end
|
36
|
+
def match(tag)
|
37
|
+
tag.match(@tag_pattern) if tag && @tag_pattern
|
38
|
+
end
|
39
|
+
def report(tag, time, data)
|
40
|
+
@block.call data, {tag: tag, time: time}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
10
44
|
class ConfigBuilder
|
11
45
|
include Observed::Configurable
|
12
46
|
|
47
|
+
attribute :logger, default: Logger.new(STDOUT, Logger::DEBUG)
|
48
|
+
|
13
49
|
def initialize(args)
|
14
|
-
@
|
15
|
-
@
|
50
|
+
@group_mutex = ::Mutex.new
|
51
|
+
@context = args[:context]
|
16
52
|
@observer_plugins = args[:observer_plugins] if args[:observer_plugins]
|
17
53
|
@reporter_plugins = args[:reporter_plugins] if args[:reporter_plugins]
|
54
|
+
@translator_plugins = args[:translator_plugins] if args[:translator_plugins]
|
18
55
|
@system = args[:system] || fail("The key :system must be in #{args}")
|
19
|
-
|
56
|
+
configure args
|
20
57
|
end
|
21
58
|
|
22
59
|
def system
|
23
60
|
@system
|
24
61
|
end
|
25
62
|
|
26
|
-
def writer_plugins
|
27
|
-
@writer_plugins || select_named_plugins_of(Observed::Writer)
|
28
|
-
end
|
29
|
-
|
30
|
-
def reader_plugins
|
31
|
-
@reader_plugins || select_named_plugins_of(Observed::Reader)
|
32
|
-
end
|
33
|
-
|
34
63
|
def observer_plugins
|
35
64
|
@observer_plugins || select_named_plugins_of(Observed::Observer)
|
36
65
|
end
|
@@ -39,6 +68,10 @@ module Observed
|
|
39
68
|
@reporter_plugins || select_named_plugins_of(Observed::Reporter)
|
40
69
|
end
|
41
70
|
|
71
|
+
def translator_plugins
|
72
|
+
@translator_plugins || select_named_plugins_of(Observed::Translator)
|
73
|
+
end
|
74
|
+
|
42
75
|
def select_named_plugins_of(klass)
|
43
76
|
plugins = {}
|
44
77
|
klass.select_named_plugins.each do |plugin|
|
@@ -49,8 +82,6 @@ module Observed
|
|
49
82
|
|
50
83
|
def build
|
51
84
|
Observed::Config.new(
|
52
|
-
writers: writers,
|
53
|
-
readers: readers,
|
54
85
|
observers: observers,
|
55
86
|
reporters: reporters
|
56
87
|
)
|
@@ -60,31 +91,53 @@ module Observed
|
|
60
91
|
# @param [Hash] args The configuration for each reporter which may or may not contain (1) which reporter plugin to
|
61
92
|
# use or which writer plugin to use (in combination with the default reporter plugin) (2) initialization parameters
|
62
93
|
# to instantiate the reporter/writer plugin
|
63
|
-
def report(tag_pattern, args)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
94
|
+
def report(tag_pattern=nil, args={}, &block)
|
95
|
+
if tag_pattern.is_a? ::Hash
|
96
|
+
args = tag_pattern
|
97
|
+
tag_pattern = nil
|
98
|
+
end
|
99
|
+
reporter = if args[:via] || args[:using]
|
69
100
|
via = args[:via] || args[:using]
|
70
101
|
with = args[:with] || args[:which] || {}
|
71
|
-
with = ({logger: @logger}).merge(with).merge({tag_pattern: tag_pattern})
|
102
|
+
with = ({logger: @logger}).merge(with).merge({tag_pattern: tag_pattern, system: system})
|
72
103
|
plugin = reporter_plugins[via] ||
|
73
104
|
fail(RuntimeError, %Q|The reporter plugin named "#{via}" is not found in "#{reporter_plugins}"|)
|
74
105
|
plugin.new(with)
|
106
|
+
elsif block_given?
|
107
|
+
Observed::ProcReporter.new tag_pattern, &block
|
108
|
+
else
|
109
|
+
fail "Invalid combination of arguments: #{tag_pattern} #{args}"
|
75
110
|
end
|
76
|
-
begin
|
77
|
-
reporter.match('test')
|
78
|
-
rescue => e
|
79
|
-
fail "A mis-configured reporter plugin found: #{reporter}"
|
80
|
-
rescue NotImplementedError => e
|
81
|
-
builtin_methods = Object.methods
|
82
|
-
info = (reporter.methods - builtin_methods).map {|sym| reporter.method(sym) }.map(&:source_location).compact
|
83
|
-
fail "Incomplete reporter plugin found: #{reporter}, defined in: #{info}"
|
84
|
-
end
|
85
111
|
|
86
112
|
reporters << reporter
|
87
|
-
reporter
|
113
|
+
report_it = convert_to_job(reporter)
|
114
|
+
if tag_pattern
|
115
|
+
receive(tag_pattern).then(report_it)
|
116
|
+
end
|
117
|
+
report_it
|
118
|
+
end
|
119
|
+
|
120
|
+
class ObserverCompatibilityAdapter < Observed::Observer
|
121
|
+
include Observed::Configurable
|
122
|
+
attribute :observer
|
123
|
+
attribute :system
|
124
|
+
attribute :tag
|
125
|
+
|
126
|
+
def configure(args)
|
127
|
+
super
|
128
|
+
observer.configure(args)
|
129
|
+
end
|
130
|
+
|
131
|
+
def observe(data=nil, options=nil)
|
132
|
+
case observer.method(:observe).parameters.size
|
133
|
+
when 0
|
134
|
+
observer.observe
|
135
|
+
when 1
|
136
|
+
observer.observe data
|
137
|
+
when 2
|
138
|
+
observer.observe data, options
|
139
|
+
end
|
140
|
+
end
|
88
141
|
end
|
89
142
|
|
90
143
|
# @param [String] tag The tag which is assigned to data which is generated from this observer, and is sent to
|
@@ -92,67 +145,74 @@ module Observed
|
|
92
145
|
# @param [Hash] args The configuration for each observer which may or may not contain (1) which observer plugin to
|
93
146
|
# use or which reader plugin to use (in combination with the default observer plugin) (2) initialization parameters
|
94
147
|
# to instantiate the observer/reader plugin
|
95
|
-
def observe(tag, args)
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
148
|
+
def observe(tag=nil, args={}, &block)
|
149
|
+
if tag.is_a? ::Hash
|
150
|
+
args = tag
|
151
|
+
tag = nil
|
152
|
+
end
|
153
|
+
observer = if args[:via] || args[:using]
|
100
154
|
via = args[:via] || args[:using] ||
|
101
155
|
fail(RuntimeError, %Q|Missing observer plugin name for the tag "#{tag}" in "#{args}"|)
|
102
156
|
with = args[:with] || args[:which] || {}
|
103
157
|
plugin = observer_plugins[via] ||
|
104
158
|
fail(RuntimeError, %Q|The observer plugin named "#{via}" is not found in "#{observer_plugins}"|)
|
105
|
-
plugin.new(({logger:
|
159
|
+
observer = plugin.new(({logger: logger}).merge(with).merge(tag: tag, system: system))
|
160
|
+
ObserverCompatibilityAdapter.new(
|
161
|
+
system: system,
|
162
|
+
observer: observer,
|
163
|
+
tag: tag
|
164
|
+
)
|
165
|
+
elsif block_given?
|
166
|
+
Observed::ProcObserver.new &block
|
167
|
+
else
|
168
|
+
fail "No args valid args (in args=#{args}) or a block given"
|
169
|
+
end
|
170
|
+
observe_that = convert_to_job(observer)
|
171
|
+
result = if tag
|
172
|
+
a = observe_that.then(emit(tag))
|
173
|
+
group tag, (group(tag) + [a])
|
174
|
+
a
|
175
|
+
else
|
176
|
+
observe_that
|
177
|
+
end
|
178
|
+
observers << result
|
179
|
+
result
|
180
|
+
end
|
181
|
+
|
182
|
+
def translate(args={}, &block)
|
183
|
+
translator = if args[:via] || args[:using]
|
184
|
+
#tag_pattern || fail("Tag pattern missing: #{tag_pattern} where args: #{args}")
|
185
|
+
via = args[:via] || args[:using]
|
186
|
+
with = args[:with] || args[:which] || {}
|
187
|
+
with = ({logger: logger}).merge(with).merge({system: system})
|
188
|
+
plugin = translator_plugins[via] ||
|
189
|
+
fail(RuntimeError, %Q|The reporter plugin named "#{via}" is not found in "#{translator_plugins}"|)
|
190
|
+
plugin.new(with)
|
191
|
+
else
|
192
|
+
Observed::ProcTranslator.new &block
|
106
193
|
end
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
end
|
130
|
-
|
131
|
-
def read(args)
|
132
|
-
from = args[:from]
|
133
|
-
with = args[:with] || [:which]
|
134
|
-
reader = case from
|
135
|
-
when String
|
136
|
-
plugin = reader_plugins[from] || fail(RuntimeError, %Q|The reader plugin named "#{from}" is not found in "#{reader_plugins}"|)
|
137
|
-
with = ({logger: @logger}).merge(with)
|
138
|
-
plugin.new(with)
|
139
|
-
when Observed::Reader
|
140
|
-
from
|
141
|
-
when nil
|
142
|
-
nil
|
143
|
-
else
|
144
|
-
fail "Unexpected type of value for the key :from in: #{args}"
|
145
|
-
end
|
146
|
-
readers << reader if reader
|
147
|
-
reader
|
148
|
-
end
|
149
|
-
|
150
|
-
def writers
|
151
|
-
@writers ||= []
|
152
|
-
end
|
153
|
-
|
154
|
-
def readers
|
155
|
-
@readers ||= []
|
194
|
+
convert_to_job(translator)
|
195
|
+
end
|
196
|
+
|
197
|
+
def emit(tag)
|
198
|
+
@context.jobbed_event_bus.pipe_to_emit(tag)
|
199
|
+
end
|
200
|
+
|
201
|
+
def receive(pattern)
|
202
|
+
@context.jobbed_event_bus.receive(pattern)
|
203
|
+
end
|
204
|
+
|
205
|
+
# Updates or get the observations belongs to the group named `name`
|
206
|
+
def group(name, observations=nil)
|
207
|
+
@group_mutex.synchronize do
|
208
|
+
@observations ||= {}
|
209
|
+
@observations[name] = observations if observations
|
210
|
+
@observations[name] || []
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def run_group(name)
|
215
|
+
@context.job_factory.parallel(group(name))
|
156
216
|
end
|
157
217
|
|
158
218
|
def reporters
|
@@ -162,6 +222,13 @@ module Observed
|
|
162
222
|
def observers
|
163
223
|
@observers ||= []
|
164
224
|
end
|
225
|
+
|
226
|
+
private
|
227
|
+
|
228
|
+
def convert_to_job(underlying)
|
229
|
+
@execution_job_factory ||= @context.execution_job_factory
|
230
|
+
@execution_job_factory.convert_to_job(underlying)
|
231
|
+
end
|
165
232
|
end
|
166
233
|
|
167
234
|
end
|
data/lib/observed/config_dsl.rb
CHANGED
@@ -15,16 +15,15 @@ module Observed
|
|
15
15
|
|
16
16
|
include Observed::Configurable
|
17
17
|
|
18
|
-
def_delegators :@builder, :observe, :report, :read, :write
|
18
|
+
def_delegators :@builder, :observe, :translate, :report, :read, :write, :emit, :group, :run_group, :receive
|
19
19
|
|
20
20
|
attribute :builder
|
21
|
+
attribute :logger, default: Logger.new(STDOUT)
|
21
22
|
|
22
23
|
def initialize(args)
|
23
24
|
args[:builder] || fail("The key :builder must exist in #{args}")
|
24
25
|
@builder = args[:builder]
|
25
26
|
|
26
|
-
@logger = args[:logger] if args[:logger]
|
27
|
-
|
28
27
|
configure(args)
|
29
28
|
end
|
30
29
|
|
@@ -68,10 +67,5 @@ module Observed
|
|
68
67
|
eval_file file
|
69
68
|
end
|
70
69
|
|
71
|
-
private
|
72
|
-
|
73
|
-
def logger
|
74
|
-
@logger ||= Logger.new(STDOUT)
|
75
|
-
end
|
76
70
|
end
|
77
71
|
end
|
@@ -1,4 +1,7 @@
|
|
1
1
|
module Observed
|
2
|
+
# Indicates that classes included this module to have attributes which are configurable.
|
3
|
+
# `configurable` means that the attributes can be configured via named parameters of
|
4
|
+
# the constructor and the `configure` instance method of the class included this module.
|
2
5
|
module Configurable
|
3
6
|
|
4
7
|
def initialize(args={})
|
@@ -14,11 +17,25 @@ module Observed
|
|
14
17
|
self
|
15
18
|
end
|
16
19
|
|
20
|
+
# @param [String|Symbol] name
|
21
|
+
def has_attribute_value?(name)
|
22
|
+
!! get_attribute_value(name)
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [String|Symbol] name
|
26
|
+
# @return [Object] In order of precedence, the value of the instance variable named `"@" + name`,
|
27
|
+
# or the value `@attributes[name]`, or the default value for the attribute named `name`
|
28
|
+
def get_attribute_value(name)
|
29
|
+
instance_variable_get("@#{name.to_s}") || @attributes[name] || self.class.defaults[name]
|
30
|
+
end
|
31
|
+
|
17
32
|
module ClassMethods
|
18
33
|
# @param [String|Symbol] name
|
19
34
|
def attribute(name, options={})
|
20
|
-
|
21
|
-
|
35
|
+
unless instance_methods.include? name.intern
|
36
|
+
define_method(name) do
|
37
|
+
get_attribute_value(name) || fail_for_not_configured_parameter(name)
|
38
|
+
end
|
22
39
|
end
|
23
40
|
default_value = options && options[:default]
|
24
41
|
default name => default_value if default_value
|
@@ -36,13 +53,54 @@ module Observed
|
|
36
53
|
self.new(args)
|
37
54
|
end
|
38
55
|
|
56
|
+
# Inherits the default values stored in @defaults to the sub-class
|
57
|
+
def inherited(klass)
|
58
|
+
super if defined? super
|
59
|
+
klass.default defaults
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
module ModuleMethods
|
65
|
+
# @param [String|Symbol] name
|
66
|
+
def attribute(name, options={})
|
67
|
+
@attributes ||= {}
|
68
|
+
@attributes = @attributes.merge(name => options)
|
69
|
+
end
|
70
|
+
|
71
|
+
def attributes
|
72
|
+
@attributes ||
|
73
|
+
fail(<<EOS
|
74
|
+
#{self} includes Observed::Configurable. Though, no attributes are configured for #{self}.
|
75
|
+
We don't need to include Observed::Configurable, or it might be a bug?
|
76
|
+
EOS
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
def included(klass)
|
81
|
+
ensure_configurable klass
|
82
|
+
|
83
|
+
attributes.each do |name, options|
|
84
|
+
klass.attribute name, options
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def ensure_configurable(klass)
|
89
|
+
unless klass.include? Configurable
|
90
|
+
fail "The class #{klass} must include Observed::Configurable to include #{self}"
|
91
|
+
end
|
92
|
+
end
|
39
93
|
end
|
40
94
|
|
41
95
|
class NotConfiguredError < RuntimeError; end
|
42
96
|
|
43
97
|
class << self
|
44
98
|
def included(klass)
|
45
|
-
klass.
|
99
|
+
if klass.is_a? Class
|
100
|
+
klass.extend ClassMethods
|
101
|
+
else
|
102
|
+
klass.extend ModuleMethods
|
103
|
+
end
|
46
104
|
end
|
47
105
|
end
|
48
106
|
|