observed 0.1.1
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 +15 -0
- data/.gitignore +20 -0
- data/.travis.yml +11 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +204 -0
- data/Rakefile +4 -0
- data/examples/00readme/Gemfile +5 -0
- data/examples/00readme/clockwork.rb +16 -0
- data/examples/00readme/observed.rb +17 -0
- data/examples/observed.rb +10 -0
- data/exe/observed-oneshot +11 -0
- data/features/oneshot.feature +24 -0
- data/features/support/env.rb +8 -0
- data/features/test_in_single_ruby_source.feature +32 -0
- data/integrations/observed-clockwork/.gitignore +17 -0
- data/integrations/observed-clockwork/Gemfile +4 -0
- data/integrations/observed-clockwork/LICENSE.txt +22 -0
- data/integrations/observed-clockwork/README.md +53 -0
- data/integrations/observed-clockwork/Rakefile +1 -0
- data/integrations/observed-clockwork/bin/clockwork +16 -0
- data/integrations/observed-clockwork/bin/clockworkd +16 -0
- data/integrations/observed-clockwork/bin/observed-clockwork +16 -0
- data/integrations/observed-clockwork/bin/rake +16 -0
- data/integrations/observed-clockwork/examples/clockwork/clockwork.rb +9 -0
- data/integrations/observed-clockwork/examples/clockwork/foo_plugin.rb +19 -0
- data/integrations/observed-clockwork/examples/clockwork/observed.conf +6 -0
- data/integrations/observed-clockwork/features/run_observed_inside_clockwork.feature +59 -0
- data/integrations/observed-clockwork/features/support/env.rb +8 -0
- data/integrations/observed-clockwork/lib/observed/clockwork/version.rb +5 -0
- data/integrations/observed-clockwork/lib/observed/clockwork.rb +20 -0
- data/integrations/observed-clockwork/observed-clockwork.gemspec +29 -0
- data/lib/observed/application/oneshot.rb +114 -0
- data/lib/observed/application.rb +1 -0
- data/lib/observed/builtin_plugins/file.rb +49 -0
- data/lib/observed/builtin_plugins/stdout.rb +35 -0
- data/lib/observed/builtin_plugins.rb +2 -0
- data/lib/observed/config.rb +27 -0
- data/lib/observed/config_builder.rb +167 -0
- data/lib/observed/config_dsl.rb +77 -0
- data/lib/observed/configurable.rb +56 -0
- data/lib/observed/default/observer.rb +16 -0
- data/lib/observed/default/reporter.rb +17 -0
- data/lib/observed/default.rb +2 -0
- data/lib/observed/hash/builder.rb +24 -0
- data/lib/observed/hash/fetcher.rb +19 -0
- data/lib/observed/hash/key_path_encoding.rb +62 -0
- data/lib/observed/hash.rb +3 -0
- data/lib/observed/observer.rb +18 -0
- data/lib/observed/observer_helpers/timer.rb +37 -0
- data/lib/observed/pluggable.rb +34 -0
- data/lib/observed/reader.rb +14 -0
- data/lib/observed/reporter/regexp_matching.rb +11 -0
- data/lib/observed/reporter.rb +25 -0
- data/lib/observed/system.rb +109 -0
- data/lib/observed/version.rb +3 -0
- data/lib/observed/writer.rb +14 -0
- data/lib/observed.rb +77 -0
- data/observed.gemspec +30 -0
- data/plugins/observed-fluentd/.gitignore +20 -0
- data/plugins/observed-fluentd/Gemfile +12 -0
- data/plugins/observed-fluentd/LICENSE.txt +22 -0
- data/plugins/observed-fluentd/README.md +99 -0
- data/plugins/observed-fluentd/Rakefile +1 -0
- data/plugins/observed-fluentd/features/plugin.feature +61 -0
- data/plugins/observed-fluentd/features/support/env.rb +32 -0
- data/plugins/observed-fluentd/fluent.d/fluent.conf +93 -0
- data/plugins/observed-fluentd/fluentd.pid +1 -0
- data/plugins/observed-fluentd/lib/observed/fluentd/version.rb +5 -0
- data/plugins/observed-fluentd/lib/observed/fluentd.rb +30 -0
- data/plugins/observed-fluentd/observe.d/clockwork.rb +9 -0
- data/plugins/observed-fluentd/observe.d/observed.conf +17 -0
- data/plugins/observed-fluentd/observed-fluentd.gemspec +26 -0
- data/plugins/observed-gauge/.gitignore +18 -0
- data/plugins/observed-gauge/Gemfile +4 -0
- data/plugins/observed-gauge/LICENSE.txt +22 -0
- data/plugins/observed-gauge/README.md +29 -0
- data/plugins/observed-gauge/Rakefile +1 -0
- data/plugins/observed-gauge/lib/observed/gauge/version.rb +5 -0
- data/plugins/observed-gauge/lib/observed/gauge.rb +117 -0
- data/plugins/observed-gauge/observed-gauge.gemspec +30 -0
- data/plugins/observed-gauge/spec/gauge_spec.rb +195 -0
- data/plugins/observed-gauge/spec/spec_helper.rb +25 -0
- data/plugins/observed-http/.gitignore +17 -0
- data/plugins/observed-http/Gemfile +4 -0
- data/plugins/observed-http/LICENSE.txt +22 -0
- data/plugins/observed-http/README.md +37 -0
- data/plugins/observed-http/Rakefile +1 -0
- data/plugins/observed-http/features/observe_web_services_via_http.feature +32 -0
- data/plugins/observed-http/features/support/env.rb +8 -0
- data/plugins/observed-http/lib/observed/http/version.rb +5 -0
- data/plugins/observed-http/lib/observed/http.rb +60 -0
- data/plugins/observed-http/observed-http.gemspec +31 -0
- data/plugins/observed-http/spec/fixtures/observed.conf +10 -0
- data/plugins/observed-http/spec/http_spec.rb +14 -0
- data/plugins/observed-http/spec/spec_helper.rb +25 -0
- data/spec/builtin_plugins/file_spec.rb +145 -0
- data/spec/builtin_plugins/stdout_spec.rb +56 -0
- data/spec/config_builder_spec.rb +146 -0
- data/spec/config_dsl_spec.rb +50 -0
- data/spec/configurable_spec.rb +65 -0
- data/spec/fixtures/configure_by_conf/foo_plugin.rb +12 -0
- data/spec/fixtures/configure_by_conf/observed.conf +6 -0
- data/spec/fixtures/configure_by_conf_dot_d/foo_plugin.rb +18 -0
- data/spec/fixtures/configure_by_conf_dot_d/observed.conf.d/check_foo_1.rb +1 -0
- data/spec/fixtures/configure_by_conf_dot_d/observed.conf.d/plugins.rb +1 -0
- data/spec/fixtures/configure_by_require/observed_conf.rb +6 -0
- data/spec/hash/builder_spec.rb +36 -0
- data/spec/hash/fetcher_spec.rb +29 -0
- data/spec/input_helpers/timer_spec.rb +54 -0
- data/spec/observed_spec.rb +79 -0
- data/spec/observer_spec.rb +123 -0
- data/spec/oneshot_spec.rb +58 -0
- data/spec/reader_spec.rb +15 -0
- data/spec/reporter_spec.rb +19 -0
- data/spec/spec_helper.rb +65 -0
- data/spec/system_spec.rb +75 -0
- data/spec/writer_spec.rb +16 -0
- metadata +299 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'observed/reporter'
|
|
2
|
+
require 'observed/reporter/regexp_matching'
|
|
3
|
+
|
|
4
|
+
module Observed
|
|
5
|
+
module Default
|
|
6
|
+
class Reporter < Observed::Reporter
|
|
7
|
+
include Observed::Reporter::RegexpMatching
|
|
8
|
+
|
|
9
|
+
attribute :writer
|
|
10
|
+
|
|
11
|
+
def report(tag, time, data)
|
|
12
|
+
writer.write tag, time, data
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'observed/hash/key_path_encoding'
|
|
2
|
+
|
|
3
|
+
module Observed
|
|
4
|
+
module Hash
|
|
5
|
+
class Builder
|
|
6
|
+
include Observed::Hash::KeyPathEncoding
|
|
7
|
+
|
|
8
|
+
def initialize(defaults={})
|
|
9
|
+
@hash = defaults.dup
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def []=(key_path, value)
|
|
13
|
+
at_key_path_on_hash @hash, key_path, create_if_missing: true do |h, k|
|
|
14
|
+
h[k] = value
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def build
|
|
19
|
+
@hash
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'observed/hash/key_path_encoding'
|
|
2
|
+
|
|
3
|
+
module Observed
|
|
4
|
+
module Hash
|
|
5
|
+
class Fetcher
|
|
6
|
+
include Observed::Hash::KeyPathEncoding
|
|
7
|
+
|
|
8
|
+
def initialize(hash)
|
|
9
|
+
@hash = hash || fail('The hash must not be nil')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def [](key_path)
|
|
13
|
+
at_key_path_on_hash @hash, key_path, create_if_missing: false do |h, k|
|
|
14
|
+
h[k]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module Observed
|
|
2
|
+
module Hash
|
|
3
|
+
module KeyPathEncoding
|
|
4
|
+
|
|
5
|
+
# Decodes the key path such as 'foo.bar' to dig into the hash and returns `hash[:foo][:bar]`
|
|
6
|
+
# @param [Hash] hash The hash to be dug
|
|
7
|
+
# @param [String] key_path The key path which is consisted of one or more keys from the parent-to-child order,
|
|
8
|
+
# e.g. 'foo.bar' which is consisted of the keys 'foo' and 'bar' where
|
|
9
|
+
# the former is the key for the root hash and the latter if is the key for
|
|
10
|
+
# the nested hash in `{foo: {bar: 'the_value'}}`
|
|
11
|
+
# @param [Hash<Symbol,Boolean>] options
|
|
12
|
+
# @option options [Boolean] :create_if_missing when `true` the intermediate hash objects under the consisting keys
|
|
13
|
+
# in the key path is created automatically.
|
|
14
|
+
# In other words, you automatically get `{foo:bar:{}}` when the
|
|
15
|
+
# hash is `{}` and the key_path is `foo.bar.baz`
|
|
16
|
+
# @yield yields the hash to be updated or read and the last key to reach the value at the specified key path
|
|
17
|
+
# @yieldparam [Hash] hash The hash which has the second to the last key in the key_path. e.g. `{bar:1}` where the
|
|
18
|
+
# input hash object is `{foo:{bar:1}}` and the key path is 'foo.bar'
|
|
19
|
+
# @yieldparam [String|Symbol] key 'bar' in the example for the parameter `hash` immediately above.
|
|
20
|
+
# @yieldreturn [Object] The return value of this method is the return value of the given block
|
|
21
|
+
# @returns The result of the given block
|
|
22
|
+
def at_key_path_on_hash(hash, key_path, options = {}, &block)
|
|
23
|
+
create_if_missing = options[:create_if_missing]
|
|
24
|
+
|
|
25
|
+
if create_if_missing.nil?
|
|
26
|
+
fail "The key :create_if_missing must be exist in #{options}"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
if hash.nil?
|
|
30
|
+
fail 'The hash must not be nil'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
first, *rest = case key_path
|
|
34
|
+
when Array
|
|
35
|
+
key_path
|
|
36
|
+
when String
|
|
37
|
+
key_path.split(".")
|
|
38
|
+
when Symbol
|
|
39
|
+
key_path
|
|
40
|
+
end
|
|
41
|
+
key_str = first.to_s
|
|
42
|
+
key_sym = first.intern
|
|
43
|
+
key = if hash.key? key_str
|
|
44
|
+
key_str
|
|
45
|
+
else
|
|
46
|
+
key_sym
|
|
47
|
+
end
|
|
48
|
+
if rest.empty?
|
|
49
|
+
block.call hash, key
|
|
50
|
+
else
|
|
51
|
+
child = hash[key]
|
|
52
|
+
if child
|
|
53
|
+
at_key_path_on_hash(child, rest, options, &block)
|
|
54
|
+
elsif create_if_missing
|
|
55
|
+
hash[key] = created = {}
|
|
56
|
+
at_key_path_on_hash(created, rest, options, &block)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'observed/configurable'
|
|
2
|
+
require 'observed/pluggable'
|
|
3
|
+
|
|
4
|
+
module Observed
|
|
5
|
+
|
|
6
|
+
class Observer
|
|
7
|
+
include Pluggable
|
|
8
|
+
include Configurable
|
|
9
|
+
|
|
10
|
+
attribute :tag
|
|
11
|
+
attribute :system
|
|
12
|
+
|
|
13
|
+
def observe
|
|
14
|
+
raise NotImplementedError.new
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Observed
|
|
2
|
+
module ObserverHelpers
|
|
3
|
+
module Timer
|
|
4
|
+
|
|
5
|
+
require 'timeout'
|
|
6
|
+
|
|
7
|
+
def time(options={}, &block)
|
|
8
|
+
timeout_in_seconds = options[:timeout_in_seconds] ||
|
|
9
|
+
fail("The key `:timeout_in_seconds` must be exist in the options: #{options}")
|
|
10
|
+
|
|
11
|
+
begin
|
|
12
|
+
before = system.now
|
|
13
|
+
r = Timeout::timeout(timeout_in_seconds) do
|
|
14
|
+
{ status: :success, result: block.call }
|
|
15
|
+
end
|
|
16
|
+
after = system.now
|
|
17
|
+
elapsed_time = after - before
|
|
18
|
+
r[:elapsed_time] = elapsed_time
|
|
19
|
+
r
|
|
20
|
+
rescue Timeout::Error => e1
|
|
21
|
+
{ status: :error, error: {message: "#{e2.message}\n#{e2.backtrace}"}, timed_out: true }
|
|
22
|
+
rescue => e2
|
|
23
|
+
{ status: :error, error: {message: "#{e2.message}\n#{e2.backtrace}"} }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def time_and_report(options={}, &block)
|
|
28
|
+
tag = options[:tag] || (self.respond_to?(:tag) && self.tag) || fail("The key `:tag` must be exist in the options: #{options}")
|
|
29
|
+
format = options[:format] || ->(r){ r }
|
|
30
|
+
result = time(options, &block)
|
|
31
|
+
|
|
32
|
+
system.report("#{tag}.#{result[:status]}", format.call(result))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Observed
|
|
2
|
+
module Pluggable
|
|
3
|
+
|
|
4
|
+
module ClassMethods
|
|
5
|
+
def plugins
|
|
6
|
+
@plugins ||= []
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def inherited(klass)
|
|
10
|
+
plugins << klass
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def plugin_name(plugin_name=nil)
|
|
14
|
+
@plugin_name = plugin_name if plugin_name
|
|
15
|
+
@plugin_name
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def find_plugin_named(plugin_name)
|
|
19
|
+
plugins.find { |plugin| plugin.plugin_name == plugin_name }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def select_named_plugins
|
|
23
|
+
plugins.select(&:plugin_name)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class << self
|
|
28
|
+
def included(klass)
|
|
29
|
+
klass.extend ClassMethods
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'observed/configurable'
|
|
2
|
+
require 'observed/pluggable'
|
|
3
|
+
|
|
4
|
+
module Observed
|
|
5
|
+
class Reporter
|
|
6
|
+
include Configurable
|
|
7
|
+
include Pluggable
|
|
8
|
+
|
|
9
|
+
# !@attribute [r] tag_pattern
|
|
10
|
+
# @return [Regexp]
|
|
11
|
+
attribute :tag_pattern
|
|
12
|
+
|
|
13
|
+
attribute :system
|
|
14
|
+
|
|
15
|
+
# @param [String] tag
|
|
16
|
+
def match(tag)
|
|
17
|
+
raise NotImplementedError.new
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def report(tag, time, data)
|
|
21
|
+
raise NotImplementedError.new
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
require 'observed/observer'
|
|
2
|
+
require 'observed/reporter'
|
|
3
|
+
|
|
4
|
+
module Observed
|
|
5
|
+
class System
|
|
6
|
+
|
|
7
|
+
def initialize(args={})
|
|
8
|
+
@config = args[:config] if args[:config]
|
|
9
|
+
@logger = args[:logger] if args[:logger]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def config=(config)
|
|
13
|
+
@config = config
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def config
|
|
17
|
+
@config
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def report(tag, time, data=nil)
|
|
21
|
+
if data.nil?
|
|
22
|
+
data = time
|
|
23
|
+
time = self.now
|
|
24
|
+
end
|
|
25
|
+
reporters.each do |reporter|
|
|
26
|
+
if reporter.match(tag)
|
|
27
|
+
reporter.report(tag, time, data)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def run(observation_name=nil)
|
|
33
|
+
|
|
34
|
+
if observation_name
|
|
35
|
+
observers_to_run = observers.reject { |o| o.tag != observation_name }
|
|
36
|
+
fail "No configuration found for observation name '#{observation_name}'" if observers_to_run.empty?
|
|
37
|
+
else
|
|
38
|
+
observers_to_run = observers
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
observers_to_run.map do |input|
|
|
42
|
+
input.observe
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def now
|
|
48
|
+
Time.now
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def logger
|
|
52
|
+
@logger ||= Logger.new(STDOUT)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def observers
|
|
58
|
+
config.observers
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def reporters
|
|
62
|
+
config.reporters
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class YAML
|
|
68
|
+
def observers
|
|
69
|
+
config.observers
|
|
70
|
+
@observers ||= begin
|
|
71
|
+
|
|
72
|
+
observer_configs = config.observers
|
|
73
|
+
|
|
74
|
+
observers = {}
|
|
75
|
+
|
|
76
|
+
observer_configs.each do |tag, input_config|
|
|
77
|
+
plugin_name = input_config[:plugin] || fail(RuntimeError, %Q|Missing plugin name for the tag "#{tag}" in "#{input_config}" in "#{config}".|)
|
|
78
|
+
plugin = observer_plugins[plugin_name] || fail(RuntimeError, %Q|The plugin named "#{plugin_name}" is not found in plugins list "#{observer_plugins}".|)
|
|
79
|
+
updated_config = input_config.merge(tag: tag)
|
|
80
|
+
observer = plugin.new(updated_config)
|
|
81
|
+
observer.configure(system: self, logger: logger)
|
|
82
|
+
observers[tag] = observer
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
observers
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def reporters
|
|
90
|
+
@reporters ||= begin
|
|
91
|
+
|
|
92
|
+
reporter_configs = config.reporters
|
|
93
|
+
|
|
94
|
+
reporters = {}
|
|
95
|
+
|
|
96
|
+
reporter_configs.each do |tag_pattern, output_config|
|
|
97
|
+
plugin_name = output_config[:plugin] || fail(RuntimeError, %Q|Missing plugin name for the output for "#{tag_pattern}" in "#{output_config}" in #{config}.|)
|
|
98
|
+
plugin = reporter_plugins[plugin_name] || fail(RuntimeError, %Q|The plugin named "#{plugin_name}" is not found in plugins list "#{reporter_plugins}".|)
|
|
99
|
+
updated_config = output_config.merge(tag_pattern: Regexp.new(tag_pattern))
|
|
100
|
+
reporter = plugin.new(updated_config)
|
|
101
|
+
reporter.configure(system: self, logger: logger)
|
|
102
|
+
reporters[tag_pattern] = reporter
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
reporters
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
data/lib/observed.rb
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
require 'observed/version'
|
|
2
|
+
require 'observed/config_builder'
|
|
3
|
+
require 'observed/system'
|
|
4
|
+
require 'observed/config_dsl'
|
|
5
|
+
require 'observed/builtin_plugins'
|
|
6
|
+
require 'forwardable'
|
|
7
|
+
|
|
8
|
+
# The module to provide DSL to describe Observed configuration, intended to be used by including to Ruby's `main` object
|
|
9
|
+
# like Clockwork(https://github.com/tomykaira/clockwork) does in their configuration file(a.k.a `clockwork.rb`).
|
|
10
|
+
#
|
|
11
|
+
# Take this as the `Builder` for Observed's configuration which is has global state.
|
|
12
|
+
# As it has global state, we have to call `Observed#init!` before building multiple Observed configurations through
|
|
13
|
+
# this module.
|
|
14
|
+
#
|
|
15
|
+
# @example
|
|
16
|
+
# require 'observed'
|
|
17
|
+
# include Observed
|
|
18
|
+
#
|
|
19
|
+
# require 'observed/http'
|
|
20
|
+
# require_relative 'your_plugin'
|
|
21
|
+
#
|
|
22
|
+
# observe 'myservice.response', { plugin: 'http', method: 'get', url: 'http://localhost:3000' }
|
|
23
|
+
# report /myservice.response/, { plugin: 'stdout' }
|
|
24
|
+
#
|
|
25
|
+
# #=> Now we can obtain the described configuration by calling `Observed.config`
|
|
26
|
+
module Observed
|
|
27
|
+
|
|
28
|
+
class Singleton
|
|
29
|
+
extend Forwardable
|
|
30
|
+
|
|
31
|
+
def_delegators :@observed, :require_relative, :observe, :report, :write, :read, :config, :load!, :working_directory
|
|
32
|
+
|
|
33
|
+
# Call this method before you are going to build 2nd or later Observed configuration using this module.
|
|
34
|
+
# Refrain that `Observed` object is a builder for Observed configuration and it has global state.
|
|
35
|
+
# We have to reset its state via this `init!` method before building next configurations after the first one.
|
|
36
|
+
def init!
|
|
37
|
+
@sys = Observed::System.new
|
|
38
|
+
config_builder = Observed::ConfigBuilder.new(system: @sys)
|
|
39
|
+
@observed = Observed::ConfigDSL.new(builder: config_builder)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def run(tag=nil)
|
|
43
|
+
@sys.config = self.config
|
|
44
|
+
@sys.run(tag)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def configure(*args)
|
|
48
|
+
@observed.send :configure, *args
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class << self
|
|
53
|
+
def included(klass)
|
|
54
|
+
ensure_singleton_initialized
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def extended(klass)
|
|
58
|
+
ensure_singleton_initialized
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def ensure_singleton_initialized
|
|
62
|
+
@@singleton ||= begin
|
|
63
|
+
s = Singleton.new
|
|
64
|
+
s.init!
|
|
65
|
+
s
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
extend Forwardable
|
|
71
|
+
|
|
72
|
+
def_delegators :@@singleton, :run, :init!, :configure, :require_relative, :observe, :report, :write, :read, :config,
|
|
73
|
+
:load!, :working_directory
|
|
74
|
+
|
|
75
|
+
extend self
|
|
76
|
+
|
|
77
|
+
end
|
data/observed.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 'observed/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "observed"
|
|
8
|
+
spec.version = Observed::VERSION
|
|
9
|
+
spec.authors = ["KUOKA Yusuke"]
|
|
10
|
+
spec.email = ["yusuke.kuoka@gree.net"]
|
|
11
|
+
spec.description = %q{Observed}
|
|
12
|
+
spec.summary = %q{Observed is a health-check framework for various services}
|
|
13
|
+
spec.homepage = ""
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files`.split($/)
|
|
17
|
+
spec.bindir = 'exe'
|
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
20
|
+
spec.require_paths = ["lib"]
|
|
21
|
+
|
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
|
23
|
+
spec.add_development_dependency "rake"
|
|
24
|
+
spec.add_development_dependency "rspec"
|
|
25
|
+
spec.add_development_dependency "fakefs"
|
|
26
|
+
spec.add_development_dependency "mocha"
|
|
27
|
+
spec.add_development_dependency "simplecov"
|
|
28
|
+
spec.add_development_dependency "cucumber"
|
|
29
|
+
spec.add_development_dependency "aruba"
|
|
30
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
source 'https://rubygems.org'
|
|
2
|
+
|
|
3
|
+
# Specify your gem's dependencies in observed-fluentd.gemspec
|
|
4
|
+
gemspec
|
|
5
|
+
|
|
6
|
+
gem 'clockwork', :group => :test
|
|
7
|
+
gem 'fluentd', :group => :test
|
|
8
|
+
gem 'cucumber', :group => :test
|
|
9
|
+
gem 'aruba', :group => :test
|
|
10
|
+
gem 'observed', :group => :test
|
|
11
|
+
gem 'observed-http', :group => :test
|
|
12
|
+
gem 'observed-clockwork', :group => :test
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2013 GREE, Inc.
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Observed::Fluentd
|
|
2
|
+
|
|
3
|
+
TODO: Write a gem description
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
gem 'observed-fluentd'
|
|
10
|
+
|
|
11
|
+
And then execute:
|
|
12
|
+
|
|
13
|
+
$ bundle
|
|
14
|
+
|
|
15
|
+
Or install it yourself as:
|
|
16
|
+
|
|
17
|
+
$ gem install observed-fluentd
|
|
18
|
+
|
|
19
|
+
Or `git clone` the sources and install by using rake:
|
|
20
|
+
|
|
21
|
+
$ rake install
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
First of all, we need to install the fluentd to which we send observed data:
|
|
26
|
+
|
|
27
|
+
$ gem install fluentd
|
|
28
|
+
|
|
29
|
+
Then we should configure Fluentd to see data which will be sent from observed-fluentd:
|
|
30
|
+
|
|
31
|
+
$ fluentd --setup fluent.d
|
|
32
|
+
Installed fluent.d/fluent.conf.
|
|
33
|
+
|
|
34
|
+
Ensure that the following 2 parts exist in the generated fluent.conf:
|
|
35
|
+
|
|
36
|
+
<source>
|
|
37
|
+
type forward
|
|
38
|
+
</source>
|
|
39
|
+
|
|
40
|
+
<match debug.**>
|
|
41
|
+
type stdout
|
|
42
|
+
</match>
|
|
43
|
+
|
|
44
|
+
Now we can run Fluentd:
|
|
45
|
+
|
|
46
|
+
$ fluentd -c fluent.d/fluent.conf
|
|
47
|
+
|
|
48
|
+
Install observed-fluentd:
|
|
49
|
+
|
|
50
|
+
$ gem build observed-fluentd.gemspec
|
|
51
|
+
$ gem install observed-fluentd
|
|
52
|
+
$ gem install observed-http
|
|
53
|
+
$ gem install observed-clockwork
|
|
54
|
+
|
|
55
|
+
Create the observed.conf like:
|
|
56
|
+
|
|
57
|
+
require 'observed/builtin_plugins'
|
|
58
|
+
require 'observed/http'
|
|
59
|
+
require 'observed/fluentd'
|
|
60
|
+
|
|
61
|
+
observe 'myservice', {
|
|
62
|
+
plugin: 'http',
|
|
63
|
+
method: 'get',
|
|
64
|
+
url: 'http://localhost/',
|
|
65
|
+
timeout_in_milliseconds: 3000,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
match /myservice.*/, {
|
|
69
|
+
plugin: 'fluentd',
|
|
70
|
+
host: 'localhost',
|
|
71
|
+
port: 24224,
|
|
72
|
+
tag: 'debug.myservice'
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
Run clockwork and trigger observed:
|
|
76
|
+
|
|
77
|
+
$ cd observe.d/
|
|
78
|
+
$ clockwork clockwork.rb
|
|
79
|
+
|
|
80
|
+
Find data sent from Observed in the Fluentd output:
|
|
81
|
+
|
|
82
|
+
2013-11-01T07:55:09Z debug.myservice {"status":"success","result":"Get http://localhost/","elapsed_time":0.013686}
|
|
83
|
+
|
|
84
|
+
Now you can do anything utilizing Fluent's rich features and plugins.
|
|
85
|
+
|
|
86
|
+
## Developping
|
|
87
|
+
|
|
88
|
+
To run cucumber tests, execute:
|
|
89
|
+
|
|
90
|
+
$ bundle install --binstubs
|
|
91
|
+
$ bin/cucumber features
|
|
92
|
+
|
|
93
|
+
## Contributing
|
|
94
|
+
|
|
95
|
+
1. Fork it
|
|
96
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
97
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
98
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
99
|
+
5. Create new Pull Request
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|