nosey 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,4 +9,8 @@ Nosey::Munin.graph do
9
9
  category 'App'
10
10
  title 'My Cool Chart'
11
11
  vertical_label 'Response Time (seconds)'
12
+ filter do |name|
13
+ # Only show these 3 dudes
14
+ %w[min max avg].include? name
15
+ end
12
16
  end
@@ -13,7 +13,7 @@ EM.run {
13
13
  puts "Starting nosey test server"
14
14
  EventMachine::Nosey::SocketServer.start(probes.report, '/tmp/nosey_test.socket')
15
15
 
16
- EM::add_periodic_timer(1) do
16
+ EM::add_periodic_timer(2) do
17
17
  probes.increment 'ticks'
18
18
  probes.avg 'avg', rand
19
19
  probes.min 'min', rand
@@ -13,15 +13,23 @@ module EventMachine
13
13
  @report = report
14
14
  end
15
15
 
16
- # Dump out the stats and close down the connection
17
- def post_init
18
- begin
16
+ def receive_data(data)
17
+ buffer << data
18
+ # Stop buffering if a newline is detected and process command
19
+ process_command buffer.strip if data =~ /\n/
20
+ end
21
+
22
+ def process_command(command)
23
+ case command
24
+ when 'READ' # This is for more normal uses cases where you want to watch stats
25
+ send_data report.to_s
26
+ when 'RESET' # This is used primarly by munin, or other tools that can't track state.
19
27
  send_data report.to_s
20
- rescue => e
21
- send_data "Exception! #{e}\n#{e.backtrace}"
22
- ensure
23
- close_connection
28
+ report.reset
29
+ else
30
+ send_data "No Comprende. send 'read' to see stats or 'reset' to read and reset."
24
31
  end
32
+ close_connection_after_writing
25
33
  end
26
34
 
27
35
  # A nice short-cut for peeps who aren't familar with EM to fire up
@@ -29,6 +37,11 @@ module EventMachine
29
37
  def self.start(report, host=SocketServer::Host, port=SocketServer::Port)
30
38
  EventMachine::start_server(host, port, self, report)
31
39
  end
40
+
41
+ private
42
+ def buffer
43
+ @buffer ||= ""
44
+ end
32
45
  end
33
46
  end
34
47
  end
data/lib/nosey/munin.rb CHANGED
@@ -24,7 +24,7 @@ module Nosey
24
24
 
25
25
  # Parse a Nosey socket for Munin
26
26
  class Graph
27
- attr_accessor :data, :title, :vertical_label, :category
27
+ attr_accessor :data, :title, :vertical_label, :category, :filter
28
28
  attr_writer :probe_set
29
29
 
30
30
  def initialize(data=nil)
@@ -67,13 +67,16 @@ module Nosey
67
67
  def munin_hash(root_key=nil,hash=self.probe_set)
68
68
  # TODO perform processing for more complicated probes, like samplers, etc
69
69
  hash.reduce({}) do |memo, (name, value)|
70
- case value
71
- when Hash # Its nested, go deep! Oooo yeah!
72
- munin_hash(format_field(root_key, name), value).each do |name, value|
73
- memo[format_field(root_key, name)] = value.to_a
70
+ # If there's NOt a filter OR we have a filter and it filters...
71
+ if !filter or (filter and filter.call(name))
72
+ case value
73
+ when Hash # Its nested, go deep! Oooo yeah!
74
+ munin_hash(format_field(root_key, name), value).each do |name, value|
75
+ memo[format_field(root_key, name)] = value.to_a
76
+ end
77
+ else # Its cool, return this mmmkay? Sheesh man
78
+ memo[format_field(root_key, name)] = [name, value]
74
79
  end
75
- else # Its cool, return this mmmkay? Sheesh man
76
- memo[format_field(root_key, name)] = [name, value]
77
80
  end
78
81
  memo
79
82
  end
@@ -88,10 +91,12 @@ module Nosey
88
91
  @title ||= probe_set
89
92
  end
90
93
 
91
- private
92
- def process_filter(hash)
93
- hash.select{}
94
+ # Setup a filter from the graphing DSL so that we can grep out specific probes
95
+ def filter(&block)
96
+ block_given? ? @filter = block : @filter
94
97
  end
98
+
99
+ private
95
100
  # http://munin-monitoring.org/wiki/notes_on_datasource_names
96
101
  # Notes on field names
97
102
  # Each data source in a plugin must be identified by a field name. The following describes the name of the field:
@@ -114,6 +119,12 @@ module Nosey
114
119
 
115
120
  # A little DSL that lets us set the socket and report name we'll read
116
121
  class Graph::DSL
122
+ # We use this command to read Nosey data from the socket, but more
123
+ # importantly, reset it so that when we come back around the next time
124
+ # we can grab all the data that's occured since that time.
125
+ ResetCommand = "RESET\n"
126
+
127
+ # Default munin category. Zie app!
117
128
  Category = 'App'
118
129
 
119
130
  def initialize(&block)
@@ -147,6 +158,11 @@ module Nosey
147
158
  self
148
159
  end
149
160
 
161
+ def filter(&block)
162
+ @filter = block
163
+ self
164
+ end
165
+
150
166
  # Category this thing will be in
151
167
  def category(category=Category)
152
168
  @category = category
@@ -160,6 +176,7 @@ module Nosey
160
176
  c.category = @category
161
177
  c.title = @title
162
178
  c.vertical_label = @vertical_label
179
+ c.filter = @filter
163
180
  end
164
181
  end
165
182
 
@@ -171,7 +188,10 @@ module Nosey
171
188
 
172
189
  # Read the report YAML data from the socket
173
190
  def read_socket
174
- UNIXSocket.new(@host).gets("\n\n")
191
+ p ResetCommand
192
+ socket = UNIXSocket.new(@host)
193
+ socket.puts(ResetCommand)
194
+ socket.gets("\n\n")
175
195
  end
176
196
  end
177
197
  end
data/lib/nosey/probe.rb CHANGED
@@ -27,9 +27,12 @@ module Nosey
27
27
  end
28
28
 
29
29
  class Average < Base
30
+ def initialize(*args)
31
+ super(*args)
32
+ reset
33
+ end
34
+
30
35
  def sample(value)
31
- @sum ||= 0
32
- @count ||= 0
33
36
  @sum += value
34
37
  @count += 1
35
38
  end
@@ -37,6 +40,12 @@ module Nosey
37
40
  def value
38
41
  @sum.to_f / @count.to_f if @sum and @count > 0
39
42
  end
43
+
44
+ def reset
45
+ @sum = 0
46
+ @count = 0
47
+ @count = 0
48
+ end
40
49
  end
41
50
 
42
51
  class Minimum < Base
@@ -147,6 +156,11 @@ module Nosey
147
156
  end
148
157
  end
149
158
 
159
+ # Reset the values in all the probes
160
+ def reset
161
+ probes.each{|_, probe| probe.reset }
162
+ end
163
+
150
164
  private
151
165
  # This factory creates probes based on the methods called from
152
166
  # the instrumentation. If a probe doesn't exist, we create an instance
data/lib/nosey/report.rb CHANGED
@@ -29,6 +29,11 @@ module Nosey
29
29
  }
30
30
  end
31
31
 
32
+ # Reset all the counters in each probe.
33
+ def reset
34
+ probe_sets.each(&:reset)
35
+ end
36
+
32
37
  # String representation of all the probe_sets that's suitable for
33
38
  # flushing out over a socket.
34
39
  def to_s
data/lib/nosey/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Nosey
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
data/nosey.gemspec CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.require_paths = ["lib"]
20
20
 
21
21
  s.add_runtime_dependency "eventmachine"
22
+ s.add_runtime_dependency "thor"
22
23
 
23
24
  s.add_development_dependency 'rspec'
24
25
  s.add_development_dependency 'guard-rspec'
@@ -27,4 +28,4 @@ Gem::Specification.new do |s|
27
28
  s.add_development_dependency 'rb-fsevent'
28
29
  s.add_development_dependency 'em-ventually'
29
30
  s.add_development_dependency 'ruby-debug19'
30
- end
31
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+ require 'yaml'
3
+
4
+ describe EventMachine::Nosey::SocketServer do
5
+ include EM::Ventually
6
+
7
+ before(:each) do
8
+ @report = Nosey::Report.new do |r|
9
+ 3.times do |n|
10
+ r.probe_sets << Nosey::Probe::Set.new("Group #{n}") do |set|
11
+ set.increment 'hit'
12
+ set.increment 'hit'
13
+ set.touch 'generated-at'
14
+ set.avg 'zie-number-avg', 1
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ it "should read report data with READ command" do
21
+ EventMachine::Nosey::SocketServer.start @report
22
+ socket = Nosey::Test::ReadSocket.start('/tmp/nosey.socket')
23
+ socket.callback{|data|
24
+ @resp = data
25
+ }
26
+ socket.send_data("READ\n")
27
+
28
+ ly{2}.test{|count| YAML.load(@resp)['Group 0']['hit'] == count }
29
+ end
30
+
31
+ it "should reset report and read data with RESET command" do
32
+ @r1 = @r2 = nil
33
+
34
+ EventMachine::Nosey::SocketServer.start @report
35
+
36
+ s1 = Nosey::Test::ReadSocket.start('/tmp/nosey.socket')
37
+ s2 = Nosey::Test::ReadSocket.start('/tmp/nosey.socket')
38
+
39
+ s1.send_data("RESET\n")
40
+ s1.callback{|data|
41
+ @r1 = data
42
+ s2.send_data("READ\n")
43
+ s2.callback{|data|
44
+ @r2 = data
45
+ }
46
+ }
47
+
48
+ ly{nil}.test{|count| YAML.load(@r2)['Group 0']['hit'] == count }
49
+ end
50
+ end
@@ -43,6 +43,13 @@ describe Nosey::Munin::Graph do
43
43
  end
44
44
  end
45
45
 
46
+ it "should filter" do
47
+ @graph.filter do |name|
48
+ name =~ /chopper-sum|chopper-avg/
49
+ end
50
+ @graph.munin_hash.should have(2).items
51
+ end
52
+
46
53
  context "sample" do
47
54
  before(:each) do
48
55
  @text = @graph.sample
@@ -42,38 +42,88 @@ describe Nosey::Probe::Set do
42
42
  @probes.probe('barf').should be_instance_of(Nosey::Probe::Touch)
43
43
  end
44
44
 
45
+ it "should reset" do
46
+ @probes.touch('barf')
47
+ @probes.reset
48
+ @probes.probe('barf').value.should be_nil
49
+ end
50
+
45
51
  it "should return report" do
46
52
  @probes.report.probe_sets.first.should eql(@probes)
47
53
  end
48
54
  end
49
55
 
50
- describe Nosey::Probe do
51
- it "should calculate sum" do
52
- sum = Nosey::Probe::Sum.new
53
- sum.sample(1)
54
- sum.sample(2)
55
- sum.value.should eql(3)
56
+ describe Nosey::Probe::Sum do
57
+ before(:all) do
58
+ @sum = Nosey::Probe::Sum.new
59
+ end
60
+
61
+ it "should sum" do
62
+ @sum.sample(1)
63
+ @sum.sample(2)
64
+ @sum.value.should eql(3)
65
+ end
66
+
67
+ it "should reset" do
68
+ @sum.sample(1)
69
+ @sum.sample(2)
70
+ @sum.reset
71
+ @sum.value.should be_nil
72
+ end
73
+ end
74
+
75
+ describe Nosey::Probe::Maximum do
76
+ before(:all) do
77
+ @max = Nosey::Probe::Maximum.new
78
+ end
79
+
80
+ it "should know max" do
81
+ @max.sample(1)
82
+ @max.sample(3)
83
+ @max.value.should eql(3)
84
+ end
85
+
86
+ it "should reset" do
87
+ @max.sample(1)
88
+ @max.reset
89
+ @max.value.should be_nil
90
+ end
91
+ end
92
+
93
+ describe Nosey::Probe::Minimum do
94
+ before(:all) do
95
+ @min = Nosey::Probe::Minimum.new
56
96
  end
57
97
 
58
- it "should calculate max" do
59
- max = Nosey::Probe::Maximum.new
60
- max.sample(1)
61
- max.sample(3)
62
- max.value.should eql(3)
98
+ it "should know max" do
99
+ @min.sample(1)
100
+ @min.sample(2)
101
+ @min.value.should eql(1)
63
102
  end
64
103
 
65
- it "should calculate minimum" do
66
- min = Nosey::Probe::Minimum.new
67
- min.sample(1)
68
- min.sample(2)
69
- min.value.should eql(1)
104
+ it "should reset" do
105
+ @min.sample(2)
106
+ @min.reset
107
+ @min.value.should be_nil
70
108
  end
109
+ end
71
110
 
72
- it "should calculate average" do
73
- avg = Nosey::Probe::Average.new
74
- avg.sample(1)
75
- avg.sample(2)
76
- avg.value.should eql(1.5)
111
+ describe Nosey::Probe::Average do
112
+ before(:all) do
113
+ @avg = Nosey::Probe::Average.new
114
+ end
115
+
116
+ it "should know avg" do
117
+ @avg.sample(1)
118
+ @avg.sample(2)
119
+ @avg.value.should eql(1.5)
120
+ end
121
+
122
+ it "should reset" do
123
+ @avg.sample(1)
124
+ @avg.sample(2)
125
+ @avg.reset
126
+ @avg.value.should be_nil
77
127
  end
78
128
  end
79
129
 
@@ -97,6 +147,12 @@ describe Nosey::Probe::Count do
97
147
  it "should set" do
98
148
  @counter.set(0).should eql(0)
99
149
  end
150
+
151
+ it "should reset" do
152
+ @counter.increment(1)
153
+ @counter.reset
154
+ @counter.value.should be_nil
155
+ end
100
156
  end
101
157
 
102
158
  describe Nosey::Probe::Touch do
@@ -1,25 +1 @@
1
- require 'spec_helper'
2
-
3
- describe EventMachine::Nosey::SocketServer do
4
- include EM::Ventually
5
-
6
- before(:each) do
7
- @report = Nosey::Report.new do |r|
8
- 3.times do |n|
9
- r.probe_sets << Nosey::Probe::Set.new("Group #{n}") do |set|
10
- set.increment 'hit'
11
- set.touch 'generated-at'
12
- set.avg 'zie-number-avg', 1
13
- end
14
- end
15
- end
16
- end
17
-
18
- it "should write report to socket" do
19
- EventMachine::Nosey::SocketServer.start @report
20
- Nosey::Test::ReadSocket.start('/tmp/nosey.socket').callback{|data|
21
- @response = data
22
- }
23
- ly{ @response }.test{|response| YAML.load(response).is_a?(Hash) }
24
- end
25
- end
1
+ require 'spec_helper'
data/spec/spec_helper.rb CHANGED
@@ -29,7 +29,7 @@ module Nosey
29
29
  end
30
30
 
31
31
  def self.start(host,port=nil)
32
- EventMachine::connect host, port, self
32
+ EventMachine::connect(host, port, self)
33
33
  end
34
34
 
35
35
  private
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nosey
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-16 00:00:00.000000000Z
12
+ date: 2011-09-19 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
16
- requirement: &70339837952660 !ruby/object:Gem::Requirement
16
+ requirement: &70234556114360 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,21 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70339837952660
24
+ version_requirements: *70234556114360
25
+ - !ruby/object:Gem::Dependency
26
+ name: thor
27
+ requirement: &70234556113540 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70234556113540
25
36
  - !ruby/object:Gem::Dependency
26
37
  name: rspec
27
- requirement: &70339837952240 !ruby/object:Gem::Requirement
38
+ requirement: &70234556112860 !ruby/object:Gem::Requirement
28
39
  none: false
29
40
  requirements:
30
41
  - - ! '>='
@@ -32,10 +43,10 @@ dependencies:
32
43
  version: '0'
33
44
  type: :development
34
45
  prerelease: false
35
- version_requirements: *70339837952240
46
+ version_requirements: *70234556112860
36
47
  - !ruby/object:Gem::Dependency
37
48
  name: guard-rspec
38
- requirement: &70339837951820 !ruby/object:Gem::Requirement
49
+ requirement: &70234556110900 !ruby/object:Gem::Requirement
39
50
  none: false
40
51
  requirements:
41
52
  - - ! '>='
@@ -43,10 +54,10 @@ dependencies:
43
54
  version: '0'
44
55
  type: :development
45
56
  prerelease: false
46
- version_requirements: *70339837951820
57
+ version_requirements: *70234556110900
47
58
  - !ruby/object:Gem::Dependency
48
59
  name: guard-bundler
49
- requirement: &70339837951340 !ruby/object:Gem::Requirement
60
+ requirement: &70234556110300 !ruby/object:Gem::Requirement
50
61
  none: false
51
62
  requirements:
52
63
  - - ! '>='
@@ -54,10 +65,10 @@ dependencies:
54
65
  version: '0'
55
66
  type: :development
56
67
  prerelease: false
57
- version_requirements: *70339837951340
68
+ version_requirements: *70234556110300
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: growl
60
- requirement: &70339837950920 !ruby/object:Gem::Requirement
71
+ requirement: &70234556109540 !ruby/object:Gem::Requirement
61
72
  none: false
62
73
  requirements:
63
74
  - - ! '>='
@@ -65,10 +76,10 @@ dependencies:
65
76
  version: '0'
66
77
  type: :development
67
78
  prerelease: false
68
- version_requirements: *70339837950920
79
+ version_requirements: *70234556109540
69
80
  - !ruby/object:Gem::Dependency
70
81
  name: rb-fsevent
71
- requirement: &70339837950360 !ruby/object:Gem::Requirement
82
+ requirement: &70234556108520 !ruby/object:Gem::Requirement
72
83
  none: false
73
84
  requirements:
74
85
  - - ! '>='
@@ -76,10 +87,10 @@ dependencies:
76
87
  version: '0'
77
88
  type: :development
78
89
  prerelease: false
79
- version_requirements: *70339837950360
90
+ version_requirements: *70234556108520
80
91
  - !ruby/object:Gem::Dependency
81
92
  name: em-ventually
82
- requirement: &70339837949880 !ruby/object:Gem::Requirement
93
+ requirement: &70234556107600 !ruby/object:Gem::Requirement
83
94
  none: false
84
95
  requirements:
85
96
  - - ! '>='
@@ -87,10 +98,10 @@ dependencies:
87
98
  version: '0'
88
99
  type: :development
89
100
  prerelease: false
90
- version_requirements: *70339837949880
101
+ version_requirements: *70234556107600
91
102
  - !ruby/object:Gem::Dependency
92
103
  name: ruby-debug19
93
- requirement: &70339837949240 !ruby/object:Gem::Requirement
104
+ requirement: &70234556106180 !ruby/object:Gem::Requirement
94
105
  none: false
95
106
  requirements:
96
107
  - - ! '>='
@@ -98,7 +109,7 @@ dependencies:
98
109
  version: '0'
99
110
  type: :development
100
111
  prerelease: false
101
- version_requirements: *70339837949240
112
+ version_requirements: *70234556106180
102
113
  description: Nosey is a way to instrument your Evented Ruby applications to track
103
114
  counts, aggregates, etc. It was built a Poll Everywhere because we need a way to
104
115
  peer into our Evented apps and grab some basic statistics so that we could graph
@@ -127,6 +138,7 @@ files:
127
138
  - lib/nosey/report.rb
128
139
  - lib/nosey/version.rb
129
140
  - nosey.gemspec
141
+ - spec/lib/eventmachine_spec.rb
130
142
  - spec/lib/nosey/instrumentation_spec.rb
131
143
  - spec/lib/nosey/munin_spec.rb
132
144
  - spec/lib/nosey/probe_spec.rb
@@ -158,6 +170,7 @@ signing_key:
158
170
  specification_version: 3
159
171
  summary: Instrument Ruby EventMachine applications
160
172
  test_files:
173
+ - spec/lib/eventmachine_spec.rb
161
174
  - spec/lib/nosey/instrumentation_spec.rb
162
175
  - spec/lib/nosey/munin_spec.rb
163
176
  - spec/lib/nosey/probe_spec.rb