ducksboard_reporter 0.0.7 → 0.1.0

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: d7f00fc8b81a969ebe5929f8ad0c425ff83c5db0
4
- data.tar.gz: ba5f182123e40a7631c60c7318c0c7c13cd8daba
3
+ metadata.gz: 2e9e37631f42cbb8f97861aba8f999a1d1f2e9ca
4
+ data.tar.gz: 23adcddf869c5325194a3d86822501437f6213ef
5
5
  SHA512:
6
- metadata.gz: 02447f41db7fcb8fa6f366fd127c9787da9296c61e579575f4e6cdc99399aeb7d991b7e202969641abc24fffabb41359b3b8e6ddf9017745c481ab96bb003b81
7
- data.tar.gz: 7ecd587c9dae113a7663af7e1319829174c9962e433a2e4010501b55e3d811dfe0a05c7c6187f3e6f4a4988d37936cf3a4d39d0422efd5d1d913bbc4a04b3d35
6
+ metadata.gz: 447a3fc6aa73461881fd04aeef2066b2cb060aae83eae61b2d46f2f5be2f8e8dfc43154ac926d9952ea16e085534d60bfc6695a8f832c28dfb314718ba2a8e92
7
+ data.tar.gz: 367a1f301afa96ed6484be68199dd76b52462ca7ba8a4c99683598d3dcd03888c29693b89ee215b25f063a098827323b493640963245d5c2f3ff3ad9a43413ce
@@ -3,10 +3,11 @@ $:.unshift File.expand_path("../../lib", __FILE__)
3
3
 
4
4
  require "ducksboard_reporter"
5
5
  require "trollop"
6
+ require "yaml"
6
7
 
7
8
  opts = Trollop::options do
8
- opt :config_file, "Define config file", short: 'f', type: :string, required: true
9
+ opt :config_file, "Path to config file", short: "f", type: :string, required: true
9
10
  end
10
11
 
11
- DucksboardReporter.config_file = opts[:config_file]
12
- DucksboardReporter.start
12
+ config = YAML.load_file(opts[:config_file])
13
+ DucksboardReporter::App.new(config).start
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
2
+ lib = File.expand_path("../lib", __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'ducksboard_reporter/version'
4
+ require "ducksboard_reporter/version"
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "ducksboard_reporter"
@@ -20,10 +20,13 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.6"
22
22
  spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "fuubar"
25
+ spec.add_development_dependency "byebug"
23
26
 
24
- spec.add_runtime_dependency "ducksboard"
25
- spec.add_runtime_dependency "hashie"
26
- spec.add_runtime_dependency "celluloid"
27
- spec.add_runtime_dependency "timers"
28
- spec.add_runtime_dependency "trollop"
27
+ spec.add_runtime_dependency "ducksboard", "~> 0.1.6"
28
+ spec.add_runtime_dependency "hashie", ">= 3.3.1"
29
+ spec.add_runtime_dependency "celluloid", "~> 0.16"
30
+ spec.add_runtime_dependency "timers", ">= 1.1.0"
31
+ spec.add_runtime_dependency "trollop", ">= 1.16.2"
29
32
  end
data/example_config.yml CHANGED
@@ -7,7 +7,8 @@ reporters:
7
7
 
8
8
  - name: haproxy_log_requests
9
9
  type: HaproxyLogRequests
10
- logfile: /var/log/haproxy.log
10
+ options:
11
+ log_file: /var/log/haproxy.log
11
12
 
12
13
  widgets:
13
14
  - type: Box
@@ -3,15 +3,15 @@ module DucksboardReporter
3
3
  include Celluloid
4
4
  include Celluloid::Logger
5
5
 
6
- attr_reader :options
7
- attr_accessor :value
6
+ attr_accessor :value, :timestamp, :name, :options
8
7
 
9
- def initialize(options = {})
8
+ def initialize(name, options = {})
9
+ @name = name
10
10
  @options = options
11
11
  end
12
12
 
13
13
  def start
14
- debug log_format("Started")
14
+ debug(log_format("Started"))
15
15
  async.collect
16
16
  end
17
17
 
@@ -21,14 +21,10 @@ module DucksboardReporter
21
21
  @timestamp || Time.now.to_i
22
22
  end
23
23
 
24
- def to_s
25
- options.name
26
- end
27
-
28
24
  private
29
25
 
30
26
  def log_format(msg)
31
- @log_prefix ||= "Reporter #{self.class.name.split("::").last}(#{to_s}): "
27
+ @log_prefix ||= "Reporter #{self.class.name.split("::").last}(#{@name}): "
32
28
  @log_prefix + msg
33
29
  end
34
30
  end
@@ -9,9 +9,9 @@ module DucksboardReporter
9
9
  nosrvs = 0
10
10
 
11
11
  begin
12
- file = File.open(options.logfile, "r")
12
+ file = File.open(options[:log_file], "r")
13
13
  rescue Errno::ENOENT
14
- error("HaproxyLogRequests: Cannot open #{options.logfile}")
14
+ error("HaproxyLogRequests: Cannot open #{options[:log_file]}")
15
15
  return
16
16
  end
17
17
 
@@ -1,3 +1,3 @@
1
1
  module DucksboardReporter
2
- VERSION = "0.0.7"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -3,35 +3,31 @@ module DucksboardReporter
3
3
  include Celluloid
4
4
  include Celluloid::Logger
5
5
 
6
- attr_reader :id, :reporter, :options
6
+ attr_reader :id, :reporter, :options, :updater
7
7
 
8
8
  def initialize(klass, id, reporter, options = {})
9
9
  @klass = klass
10
10
  @id = id
11
11
  @reporter = reporter
12
12
  @options = options
13
- @widget = instanciate_widget
13
+ @updater = instanciate_updater
14
14
  end
15
15
 
16
16
  def start
17
- debug log_format("Started with reporter #{reporter}")
17
+ debug log_format("Started using reporter #{reporter.name}")
18
18
 
19
19
  every(interval) do
20
- begin
21
- update
22
- rescue Net::OpenTimeout
23
- # ignore unseccessful updates
24
- end
20
+ update
25
21
  end
26
22
  end
27
23
 
28
24
  def update
29
25
  value = case value_method
30
26
  when Symbol
31
- reporter.public_send(value_method)
27
+ @reporter.public_send(value_method)
32
28
  when Hash
33
29
  value_method.inject({}) do |memo, (k, v)|
34
- memo[k] = (v.is_a?(Symbol) ? reporter.public_send(v) : v)
30
+ memo[k] = (v.is_a?(Symbol) ? @reporter.public_send(v) : v)
35
31
  memo
36
32
  end
37
33
  else
@@ -40,30 +36,30 @@ module DucksboardReporter
40
36
 
41
37
  debug log_format("Updating value #{value}")
42
38
 
43
- @widget.update(value)
44
- rescue Net::ReadTimeout
39
+ @updater.update(value)
40
+ rescue Net::ReadTimeout, Net::OpenTimeout
45
41
  # accept timeout errors
46
42
  end
47
43
 
48
44
  def interval
49
- options.interval || 10
45
+ options[:interval] || 10
50
46
  end
51
47
 
52
48
  private
53
49
 
54
50
  def log_format(msg)
55
- @log_prefix ||= "Widget #{self.class.name.split("::").last}(#{id}): "
51
+ @log_prefix ||= "Widget #{@klass}(#{id}): "
56
52
  @log_prefix + msg
57
53
  end
58
54
 
59
55
  def value_method
60
- options.value || :value
56
+ options[:value] || :value
61
57
  end
62
58
 
63
- def instanciate_widget
59
+ def instanciate_updater
64
60
  klass = Class.new(Ducksboard::Widget)
65
61
  klass.default_timeout(interval - 1)
66
- klass.new(id)
62
+ klass.new(@id)
67
63
  end
68
64
  end
69
65
  end
@@ -1,77 +1,89 @@
1
1
  require "rubygems"
2
2
 
3
3
  require "logger"
4
- require "hashie"
5
4
  require "celluloid"
6
5
  require "timers"
7
6
  require "ducksboard"
7
+ require "hashie/extensions/symbolize_keys"
8
+ Hash.include Hashie::Extensions::SymbolizeKeys
8
9
 
9
10
  require "ducksboard_reporter/version"
10
11
  require "ducksboard_reporter/reporter"
11
- require "ducksboard_reporter/reporters"
12
12
  require "ducksboard_reporter/widget"
13
13
 
14
+ require "ducksboard_reporter/reporters/random"
15
+ require "ducksboard_reporter/reporters/haproxy_log_requests"
16
+ require "ducksboard_reporter/reporters/cpu_usage"
17
+
14
18
  Thread.abort_on_exception = true
15
19
 
16
20
  module DucksboardReporter
17
21
  extend self
18
- include Celluloid::Logger
19
-
20
- def config
21
- @config ||= Hashie::Mash.load(config_file)
22
- end
23
22
 
24
- def config_file
25
- @config_file
26
- end
27
-
28
- def config_file=(file)
29
- @config_file = file
30
- end
23
+ include Celluloid::Logger
31
24
 
32
25
  def logger
33
26
  @logger ||= Celluloid.logger = Logger.new($stdout)
34
27
  end
35
28
 
36
- def reporters
37
- @reporters ||= {}
38
- end
29
+ class App
39
30
 
40
- def widgets
41
- @widgets ||= []
42
- end
31
+ attr_reader :config, :reporters, :widgets
43
32
 
44
- def start
45
- Signal.trap("INT") { exit }
33
+ def initialize(config)
34
+ @config = config.symbolize_keys!
35
+ register_reporters
36
+ register_widgets
37
+ end
46
38
 
47
- Ducksboard.api_key = config.api_key
39
+ def start
40
+ Signal.trap("INT") { exit }
48
41
 
49
- instanciate_reporters
50
- instanciate_widgets
42
+ Ducksboard.api_key = config[:api_key]
51
43
 
52
- sleep
53
- end
44
+ start_reporters
45
+ start_widgets
54
46
 
55
- def instanciate_reporters
56
- DucksboardReporter.config.reporters.each do |config|
57
- reporter = Reporters.const_get(config.type, false).new(config)
58
- reporters[config.name] = reporter
59
- reporter.start
47
+ sleep # let the actors continue their work
60
48
  end
61
- end
62
49
 
63
- def instanciate_widgets
64
- DucksboardReporter.config.widgets.each do |config|
65
- reporter = reporters[config.reporter]
50
+ def register_reporters
51
+ @reporters = {}
66
52
 
67
- unless reporter
68
- logger.error("Cannot find reporter #{config.reporter}")
69
- exit
53
+ @config[:reporters].each do |config|
54
+ reporter = Reporters.const_get(config[:type], false).new(config[:name], config[:options])
55
+ @reporters[reporter.name] = reporter
70
56
  end
57
+ end
58
+
59
+ def register_widgets
60
+ @widgets = []
61
+
62
+ @config[:widgets].each do |config|
63
+ reporter = @reporters.fetch(config[:reporter])
64
+
65
+ unless reporter
66
+ logger.error("Cannot find reporter #{config[:reporter]}")
67
+ exit
68
+ end
69
+
70
+ widget = Widget.new(config[:type], config[:id], reporter, config)
71
+ @widgets << widget
72
+ end
73
+ end
74
+
75
+ def start_reporters
76
+ @reporters.each {|_, reporter| reporter.start }
77
+ end
78
+
79
+ def start_widgets
80
+ @widgets.each(&:start)
81
+ end
82
+
83
+ private
71
84
 
72
- widget = Widget.new(config.type, config.id, reporter, config)
73
- widget.start
74
- widgets << widget
85
+ def logger
86
+ DucksboardReporter.logger
75
87
  end
76
88
  end
77
89
  end
@@ -0,0 +1,43 @@
1
+ require "spec_helper"
2
+
3
+ class DucksboardReporter::Reporters::FooBar < DucksboardReporter::Reporter
4
+ attr_accessor :log_file
5
+ end
6
+
7
+ describe DucksboardReporter::App do
8
+ let(:config) { YAML.load_file(File.expand_path("../config.yml", __FILE__)) }
9
+ let(:app) { DucksboardReporter::App.new(config) }
10
+ let(:reporter) { app.reporters["foo_bar"] }
11
+ let(:widget) { app.widgets.first }
12
+
13
+ it "registers reporters from config" do
14
+ expect(app.reporters.values.map(&:class)).to include(DucksboardReporter::Reporters::Random)
15
+ end
16
+
17
+ it "registers widgets from config" do
18
+ expect(app.widgets.map(&:class)).to include(DucksboardReporter::Widget)
19
+ end
20
+
21
+ describe "single reporter" do
22
+
23
+ it "sets name from config" do
24
+ expect(reporter.name).to eq("foo_bar")
25
+ end
26
+
27
+ it "applies options to reporters" do
28
+ expect(reporter.options[:log_file]).to eq("/var/log/haproxy.log")
29
+ end
30
+ end
31
+
32
+ describe "single widget" do
33
+
34
+ it "sets id from config" do
35
+ expect(widget.id).to eq(1234)
36
+ end
37
+
38
+ it "references reporter" do
39
+ expect(widget.reporter).to eq(reporter)
40
+ end
41
+ end
42
+ end
43
+
@@ -0,0 +1,46 @@
1
+ require "spec_helper"
2
+
3
+
4
+ class FooReporter < DucksboardReporter::Reporter
5
+ attr_accessor :log_file, :condition
6
+
7
+ def initialize(*args)
8
+ @condition = Celluloid::Condition.new
9
+ super
10
+ end
11
+
12
+ def collect
13
+ sleep 0.001
14
+ @condition.signal("called")
15
+ end
16
+
17
+ def collect_called
18
+ @condition.wait
19
+ true
20
+ end
21
+ end
22
+
23
+ describe DucksboardReporter::Reporter do
24
+
25
+ let(:reporter) { FooReporter.new("foo") }
26
+
27
+ describe "#collect" do
28
+ it "will be called on start" do
29
+ reporter.start
30
+ expect(reporter.collect_called).to be(true)
31
+ end
32
+ end
33
+
34
+ describe "#timestamp" do
35
+ it "returns current time" do
36
+ expect(reporter.timestamp).to be_within(1).of(Time.now.to_i)
37
+ end
38
+
39
+ it "returns set timestamp" do
40
+ time = Time.now.to_i + 10
41
+ reporter.timestamp = time
42
+ expect(reporter.timestamp).to eq(time)
43
+ end
44
+ end
45
+ end
46
+
@@ -0,0 +1,7 @@
1
+ require "ducksboard_reporter"
2
+ require "byebug"
3
+
4
+ DucksboardReporter.logger.level = Logger::FATAL
5
+
6
+ RSpec.configure do |config|
7
+ end
@@ -0,0 +1,73 @@
1
+ require "spec_helper"
2
+
3
+ class WidgetReporter < DucksboardReporter::Reporter
4
+ def value
5
+ 23
6
+ end
7
+
8
+ def other_value
9
+ 99
10
+ end
11
+ end
12
+
13
+ describe DucksboardReporter::Widget do
14
+
15
+ let(:reporter) { WidgetReporter.new("name") }
16
+ let(:widget) { DucksboardReporter::Widget.new("Box", 1234, reporter) }
17
+
18
+ describe "#update" do
19
+ it "updates value from reporter" do
20
+ expect(widget.updater).to receive(:update).with(23)
21
+ widget.update
22
+ end
23
+
24
+ it "will not crash on Net::ReadTimeout" do
25
+ expect(widget.updater).to receive(:update).and_raise(Net::ReadTimeout)
26
+ widget.update
27
+ end
28
+
29
+ it "will not crash on Net::OpenTimeout" do
30
+ expect(widget.updater).to receive(:update).and_raise(Net::OpenTimeout)
31
+ widget.update
32
+ end
33
+
34
+ it "uses static values for update" do
35
+ widget = DucksboardReporter::Widget.new("Box", 1234, reporter, value: "hello")
36
+ expect(widget.updater).to receive(:update).with("hello")
37
+ widget.update
38
+ end
39
+
40
+ it "uses Symbols for method reference" do
41
+ widget = DucksboardReporter::Widget.new("Box", 1234, reporter, value: :other_value)
42
+ expect(widget.updater).to receive(:update).with(99)
43
+ widget.update
44
+ end
45
+
46
+ it "uses a Hash for contructing complex values " do
47
+ widget = DucksboardReporter::Widget.new("Box", 1234, reporter, value: {current: :value, foo: "bar"})
48
+ expect(widget.updater).to receive(:update).with(current: 23, foo: "bar")
49
+ widget.update
50
+ end
51
+ end
52
+
53
+ describe "#interval" do
54
+ it "retuns default value" do
55
+ expect(widget.interval).to eq(10)
56
+ end
57
+
58
+ it "returns interval option" do
59
+ widget = DucksboardReporter::Widget.new("Box", 1234, reporter, interval: 20)
60
+ expect(widget.interval).to eq(20)
61
+ end
62
+ end
63
+
64
+ describe "#start" do
65
+ it "calls update every interval" do
66
+ widget = DucksboardReporter::Widget.new("Box", 1234, reporter, interval: 0.001)
67
+ expect(widget.updater).to receive(:update).at_least(:once)
68
+ widget.start
69
+ sleep 0.002
70
+ end
71
+ end
72
+ end
73
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ducksboard_reporter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - unnu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-28 00:00:00.000000000 Z
11
+ date: 2014-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -39,13 +39,13 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: ducksboard
42
+ name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
- type: :runtime
48
+ type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
@@ -53,13 +53,13 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: hashie
56
+ name: fuubar
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
- type: :runtime
62
+ type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
@@ -67,47 +67,89 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: celluloid
70
+ name: byebug
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
- type: :runtime
76
+ type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: ducksboard
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.1.6
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.1.6
97
+ - !ruby/object:Gem::Dependency
98
+ name: hashie
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 3.3.1
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 3.3.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: celluloid
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.16'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.16'
83
125
  - !ruby/object:Gem::Dependency
84
126
  name: timers
85
127
  requirement: !ruby/object:Gem::Requirement
86
128
  requirements:
87
129
  - - ">="
88
130
  - !ruby/object:Gem::Version
89
- version: '0'
131
+ version: 1.1.0
90
132
  type: :runtime
91
133
  prerelease: false
92
134
  version_requirements: !ruby/object:Gem::Requirement
93
135
  requirements:
94
136
  - - ">="
95
137
  - !ruby/object:Gem::Version
96
- version: '0'
138
+ version: 1.1.0
97
139
  - !ruby/object:Gem::Dependency
98
140
  name: trollop
99
141
  requirement: !ruby/object:Gem::Requirement
100
142
  requirements:
101
143
  - - ">="
102
144
  - !ruby/object:Gem::Version
103
- version: '0'
145
+ version: 1.16.2
104
146
  type: :runtime
105
147
  prerelease: false
106
148
  version_requirements: !ruby/object:Gem::Requirement
107
149
  requirements:
108
150
  - - ">="
109
151
  - !ruby/object:Gem::Version
110
- version: '0'
152
+ version: 1.16.2
111
153
  description: Report values to ducksboard
112
154
  email:
113
155
  - norman.timmler@gmail.com
@@ -126,13 +168,16 @@ files:
126
168
  - example_config.yml
127
169
  - lib/ducksboard_reporter.rb
128
170
  - lib/ducksboard_reporter/reporter.rb
129
- - lib/ducksboard_reporter/reporters.rb
130
171
  - lib/ducksboard_reporter/reporters/bandwidth.rb
131
172
  - lib/ducksboard_reporter/reporters/cpu_usage.rb
132
173
  - lib/ducksboard_reporter/reporters/haproxy_log_requests.rb
133
174
  - lib/ducksboard_reporter/reporters/random.rb
134
175
  - lib/ducksboard_reporter/version.rb
135
176
  - lib/ducksboard_reporter/widget.rb
177
+ - spec/ducksboard_reporter_spec.rb
178
+ - spec/reporter_spec.rb
179
+ - spec/spec_helper.rb
180
+ - spec/widget_spec.rb
136
181
  homepage: ''
137
182
  licenses:
138
183
  - MIT
@@ -157,4 +202,8 @@ rubygems_version: 2.2.2
157
202
  signing_key:
158
203
  specification_version: 4
159
204
  summary: Report values to ducksboard
160
- test_files: []
205
+ test_files:
206
+ - spec/ducksboard_reporter_spec.rb
207
+ - spec/reporter_spec.rb
208
+ - spec/spec_helper.rb
209
+ - spec/widget_spec.rb
@@ -1,6 +0,0 @@
1
- module DucksboardReporter
2
- module Reporters
3
- end
4
- end
5
-
6
- Dir[File.dirname(__FILE__) + '/reporters/*.rb'].each {|file| require file }