camayoc 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  require 'socket'
2
2
 
3
- # This class is a port of the code in https://github.com/reinh/statsd to fit
3
+ # This class is a port of the code in https://github.com/reinh/statsd to fit
4
4
  # with the Camayoc handler interface.
5
5
  module Camayoc
6
6
  module Handlers
@@ -9,7 +9,7 @@ module Camayoc
9
9
  include ThreadSafety
10
10
 
11
11
  attr_accessor :namespace
12
-
12
+
13
13
  def initialize(options={})
14
14
  self.namespace = options[:namespace]
15
15
  @host = options[:host]
@@ -18,15 +18,28 @@ module Camayoc
18
18
  self.thread_safe = Camayoc.thread_safe?
19
19
  end
20
20
 
21
- def count(event)
22
- send(event.ns_stat,event.value,'c',event.options[:sample_rate]||1)
23
- end
24
-
25
- def timing(event)
26
- send(event.ns_stat, event.value, 'ms', event.options[:sample_rate]||1)
21
+ def event(ev)
22
+ case ev.type
23
+ when :timing then timing(ev)
24
+ when :count then count(ev)
25
+ else other(ev)
26
+ end
27
27
  end
28
28
 
29
29
  private
30
+ def other(ev)
31
+ value = Integer(ev.value) rescue 1
32
+ send(ev.ns_stat,value,'c',ev.options[:sample_rate]||1)
33
+ end
34
+
35
+ def count(ev)
36
+ send(ev.ns_stat,ev.value,'c',ev.options[:sample_rate]||1)
37
+ end
38
+
39
+ def timing(ev)
40
+ send(ev.ns_stat,ev.value,'ms',ev.options[:sample_rate]||1)
41
+ end
42
+
30
43
  def sampled(sample_rate)
31
44
  yield unless sample_rate < 1 and rand > sample_rate
32
45
  end
@@ -41,7 +54,6 @@ module Camayoc
41
54
  end
42
55
  end
43
56
  end
44
-
45
57
  end
46
58
  end
47
- end
59
+ end
@@ -1,9 +1,16 @@
1
1
  module Camayoc
2
2
  class StatEvent
3
3
 
4
- attr_accessor :source, :stat, :value, :options
4
+ attr_accessor :type, :source, :stat, :value, :options
5
5
 
6
- def initialize(source,stat,value,options={})
6
+ # Constructor
7
+ # * +type+ :: Symbol of stat type: count, timing, or generic
8
+ # * +source+ :: Source of stat
9
+ # * +stat+ :: Name of stat
10
+ # * +value+ :: Value of stat
11
+ # * +options+ :: Optionals options
12
+ def initialize(type,source,stat,value,options={})
13
+ self.type = type
7
14
  self.source = source
8
15
  self.stat = stat
9
16
  self.value = value
@@ -15,4 +22,4 @@ module Camayoc
15
22
  end
16
23
 
17
24
  end
18
- end
25
+ end
@@ -3,12 +3,23 @@ module Camayoc
3
3
 
4
4
  attr_accessor :name, :parent, :handlers
5
5
 
6
+ # Constructor
7
+ # * +name+ :: Name of stat
8
+ # * +parent+ :: Optional parent stat (default: nil)
6
9
  def initialize(name,parent=nil)
7
10
  self.name = name
8
11
  self.parent = parent
9
12
  self.handlers = []
10
13
  end
11
-
14
+
15
+ def [](descendant_name)
16
+ Camayoc[Camayoc.join(name,descendant_name)]
17
+ end
18
+
19
+ # Add handler with filter options
20
+ # * +handler+ :: Handler instance
21
+ # * +filter_opts+ :: Options for a new Handlers::Filter
22
+ # instance (optional)
12
23
  def add(handler,filter_opts={})
13
24
  if !filter_opts.empty?
14
25
  handler = Handlers::Filter.new(handler,filter_opts)
@@ -17,49 +28,76 @@ module Camayoc
17
28
  self
18
29
  end
19
30
 
31
+ # Quick alias for adding a handler
20
32
  def <<(handler)
21
33
  self.add(handler)
22
34
  end
23
35
 
36
+ # Timing stat
37
+ def timing(stat,value,options={})
38
+ propagate(:timing,stat,value,options)
39
+ end
40
+
41
+ # Generic event
42
+ def event(stat,value,options={})
43
+ propagate(:generic,stat,value,options)
44
+ end
45
+
46
+ # Count and incr/decr convenience methods
47
+ def count(stat,value,options={})
48
+ propagate(:count,stat,value,options)
49
+ end
50
+
24
51
  def increment(stat,options={})
25
- count(stat,1,options)
52
+ count(stat,1,options)
26
53
  end
27
54
 
28
55
  def decrement(stat,options={})
29
56
  count(stat,-1,options)
30
57
  end
31
58
 
32
- def count(stat,value,options={})
33
- count_event(StatEvent.new(name,stat,value,options))
59
+ # Executes a block, stores the timing information in the specified stat
60
+ # and returns the value of the block. Use this to wrap existing code with
61
+ # timing information without worrying about return values.
62
+ def benchmark(stat,options={})
63
+ result = nil
64
+ realtime(stat,options) do
65
+ result = yield
66
+ end
67
+ result
34
68
  end
35
69
 
36
- def timing(stat,ms,options={})
37
- timing_event(StatEvent.new(name,stat,ms,options))
70
+ # Executes a block, stores the timing information in the specified stat
71
+ # and returns the time **in seconds** that the execution took. This is
72
+ # basically a drop-in replacement for calls to Benchmark.realtime
73
+ def realtime(stat,options={})
74
+ start_time = Time.now
75
+ yield
76
+ duration = (Time.now.to_f - start_time.to_f)
77
+ # Convert to ms for timing call
78
+ timing(stat,(duration*1000).round,options)
79
+ duration
38
80
  end
39
-
81
+
40
82
  protected
41
- def count_event(event)
42
- each_handler do |handler|
43
- handler.count(event)
44
- end
45
- if parent
46
- parent.count_event(event)
47
- end
48
- self
83
+ # Creates new StatEvent and passes to +#propagate_event+
84
+ def propagate(type,stat,value,options)
85
+ propagate_event(StatEvent.new(type,name,stat,value,options))
49
86
  end
50
87
 
51
- def timing_event(event)
88
+ # Propagates event to all handlers and parent Stat
89
+ def propagate_event(ev)
52
90
  each_handler do |handler|
53
- handler.timing(event)
91
+ handler.event(ev)
54
92
  end
55
93
  if parent
56
- parent.timing_event(event)
94
+ parent.propagate_event(ev)
57
95
  end
58
96
  self
59
97
  end
60
98
 
61
99
  private
62
- def each_handler
100
+ def each_handler
63
101
  handlers.each do |handler|
64
102
  begin
65
103
  yield(handler)
@@ -74,4 +112,4 @@ module Camayoc
74
112
  end
75
113
 
76
114
  end
77
- end
115
+ end
@@ -0,0 +1,41 @@
1
+ module Camayoc
2
+ class Timer
3
+
4
+ attr_accessor :stats, :name, :start_time, :stop_time
5
+
6
+ def initialize(stats,name)
7
+ self.stats = stats
8
+ self.name = name
9
+ end
10
+
11
+ def start
12
+ self.start_time = Time.now.to_f
13
+ end
14
+
15
+ def stop
16
+ self.stop_time = Time.now.to_f
17
+ duration
18
+ end
19
+
20
+ def duration
21
+ (duration_seconds*1000).round
22
+ end
23
+
24
+ def duration_seconds
25
+ stop_time - start_time
26
+ end
27
+
28
+ def save(options={})
29
+ stats.timing(name,duration,options)
30
+ end
31
+
32
+ def realtime
33
+ start
34
+ yield
35
+ stop
36
+ save
37
+ duration_seconds
38
+ end
39
+
40
+ end
41
+ end
@@ -1,3 +1,3 @@
1
1
  module Camayoc
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,53 +1,57 @@
1
1
  class FilterTest < Test::Unit::TestCase
2
-
2
+
3
+ include EventTestHelper
4
+
3
5
  def setup
4
6
  @handler = mock("handler")
5
7
  end
6
8
 
7
- def test_constructor_block_used_as_filter
8
- filter = Camayoc::Handlers::Filter.new(@handler) do |type,event|
9
+ with_event_types("test_constructor_block_used_as_filter") do
10
+ filter = Camayoc::Handlers::Filter.new(@handler) do |event|
9
11
  event.stat.length > 5
10
12
  end
11
- @handler.expects(:count).once
12
- @handler.expects(:timing).once
13
- filter.count(Camayoc::StatEvent.new("foo:bar","short",500))
14
- filter.count(Camayoc::StatEvent.new("foo:bar","very_long",500))
15
- filter.timing(Camayoc::StatEvent.new("foo:bar","short",500))
16
- filter.timing(Camayoc::StatEvent.new("foo:bar","very_long",500))
13
+
14
+ @handler.expects(:event).once
15
+ filter.event(Camayoc::StatEvent.new(@event_type,"foo:bar","short",500))
16
+ filter.event(Camayoc::StatEvent.new(@event_type,"foo:bar","very_long",500))
17
17
  end
18
18
 
19
- def test_with_filters_on_namespaced_stat
19
+ with_event_types("test_with_filters_on_namespaced_stat") do
20
20
  filter = Camayoc::Handlers::Filter.new(@handler,:with=>/a{2}/)
21
- @handler.expects(:count).once
22
- @handler.expects(:timing).once
23
- filter.count(Camayoc::StatEvent.new("foo:bar","aa_blah",500))
24
- filter.count(Camayoc::StatEvent.new("foo:bar","bb_blah",500))
25
- filter.timing(Camayoc::StatEvent.new("foo:bar","aa_blah",500))
26
- filter.timing(Camayoc::StatEvent.new("foo:bar","bb_blah",500))
21
+
22
+ evt = stat_event_match(@event_type,"foo:bar","aa_blah",500)
23
+ @handler.expects(:event).with(&evt).once
24
+ filter.event(Camayoc::StatEvent.new(@event_type,"foo:bar","aa_blah",500))
25
+ filter.event(Camayoc::StatEvent.new(@event_type,"foo:bar","bb_blah",500))
27
26
  end
28
27
 
29
- def test_constructor_block_used_as_filter
28
+ def test_constructor_block_used_as_filter_with_if_condition
30
29
  filter = Camayoc::Handlers::Filter.new(@handler,
31
- :if=>Proc.new{|type,event| type == :timing && event.value > 1000 })
32
-
33
- @handler.expects(:count).never
34
- @handler.expects(:timing).once
35
- filter.count(Camayoc::StatEvent.new("foo:bar","short",500))
36
- filter.timing(Camayoc::StatEvent.new("foo:bar","short",500))
37
- filter.timing(Camayoc::StatEvent.new("foo:bar","very_long",1500))
30
+ :if=>Proc.new{|event| event.type == :timing && event.value > 1000 })
31
+
32
+ evt = stat_event_match(:timing,"foo:bar","very_long",1500)
33
+ @handler.expects(:event).with(&evt).once
34
+ filter.event(Camayoc::StatEvent.new(:count,"foo:bar","short",500))
35
+ filter.event(Camayoc::StatEvent.new(:timing,"foo:bar","short",500))
36
+ filter.event(Camayoc::StatEvent.new(:timing,"foo:bar","very_long",1500))
38
37
  end
39
38
 
40
- def test_constructor_block_used_as_filter
39
+ def test_constructor_block_used_as_filter_with_unless_condition
41
40
  filter = Camayoc::Handlers::Filter.new(@handler,
42
- :unless=>Proc.new{|type,event| type == :count })
43
-
44
- @handler.expects(:count).never
45
- @handler.expects(:timing).twice
46
- filter.count(Camayoc::StatEvent.new("foo:bar","short",500))
47
- filter.count(Camayoc::StatEvent.new("foo:bar","very_long",500))
48
- filter.timing(Camayoc::StatEvent.new("foo:bar","short",500))
49
- filter.timing(Camayoc::StatEvent.new("foo:bar","very_long",1500))
41
+ :unless=>Proc.new{|event| event.type == :count })
42
+
43
+ evt = stat_event_match(:timing,"foo:bar","short",500)
44
+ @handler.expects(:event).with(&evt).once
45
+ filter.event(Camayoc::StatEvent.new(:timing,"foo:bar","short",500))
46
+ filter.event(Camayoc::StatEvent.new(:count,"foo:bar","short",500))
47
+ filter.event(Camayoc::StatEvent.new(:count,"foo:bar","very_long",500))
48
+ end
49
+
50
+ def test_default_filter_is_always_true
51
+ filter = Camayoc::Handlers::Filter.new(@handler)
52
+
53
+ @handler.expects(:event).once
54
+ filter.event(Camayoc::StatEvent.new(:counting,"foo:bar","short",500))
50
55
  end
51
56
 
52
-
53
- end
57
+ end
@@ -1,5 +1,5 @@
1
1
  class IOTest < Test::Unit::TestCase
2
-
2
+
3
3
  def setup
4
4
  # Hack to get around weird Mocha issue with expecting :puts
5
5
  @io = []
@@ -10,24 +10,38 @@ class IOTest < Test::Unit::TestCase
10
10
  end
11
11
 
12
12
  def test_count_sends_correct_log_message
13
- expect_message(/count foo:bar:baz 500/)
14
- @handler.count(Camayoc::StatEvent.new("foo:bar","baz",500))
13
+ @handler.event(Camayoc::StatEvent.new(:count,"foo:bar","baz",500))
14
+ assert_message(/count foo:bar:baz 500/)
15
15
  end
16
16
 
17
17
  def test_timing_sends_correct_log_message
18
- expect_message(/timing foo:bar:time 100/)
19
- @handler.timing(Camayoc::StatEvent.new("foo:bar","time",100))
18
+ @handler.event(Camayoc::StatEvent.new(:timing,"foo:bar","time",100))
19
+ assert_message(/timing foo:bar:time 100/)
20
20
  end
21
21
 
22
22
  def test_formatter_changes_format_of_message
23
- @handler.formatter = Proc.new{|type,event| "#{type}: #{event.ns_stat}"}
24
- expect_message(/timing: foo:bar:time/)
25
- @handler.timing(Camayoc::StatEvent.new("foo:bar","time",100))
23
+ @handler.formatter = Proc.new{|event| "#{event.type}: #{event.ns_stat}"}
24
+ @handler.event(Camayoc::StatEvent.new(:timing,"foo:bar","time",100))
25
+ assert_message(/timing: foo:bar:time/)
26
+ end
27
+
28
+ def test_formatter_can_be_set_with_constructor_block
29
+ @handler = Camayoc::Handlers::IO.new(@io) do |event|
30
+ "#{event.type}: #{event.ns_stat} #{event.value}"
31
+ end
32
+ @handler.event(Camayoc::StatEvent.new(:timing,"foo:bar","time",100))
33
+ assert_message(/timing: foo:bar:time 100/)
34
+ end
35
+
36
+ def test_logs_any_event_type
37
+ @handler.event(Camayoc::StatEvent.new(:baz,"foo:bar","time",500))
38
+ assert_message(/baz foo:bar:time 500/)
26
39
  end
27
40
 
28
41
  private
29
- def expect_message(*messages)
30
- assert(@io.zip(messages).all?{ |actual,patt| actual =~ patt })
42
+ def assert_message(*messages)
43
+ pairs = messages.zip(@io)
44
+ assert(pairs.all?{ |actual,patt| actual =~ patt },pairs.join("\n"))
31
45
  end
32
46
 
33
- end
47
+ end
@@ -1,32 +1,37 @@
1
1
  class LoggerTest < Test::Unit::TestCase
2
-
2
+
3
3
  def setup
4
4
  @dest_logger = mock("logger")
5
5
  @handler = Camayoc::Handlers::Logger.new(@dest_logger)
6
6
  end
7
-
7
+
8
8
  def test_count_sends_correct_log_message
9
9
  expect_message(:debug, /count foo:bar:baz 500/)
10
- @handler.count(Camayoc::StatEvent.new("foo:bar","baz",500))
10
+ @handler.event(Camayoc::StatEvent.new(:count,"foo:bar","baz",500))
11
11
  end
12
12
 
13
13
  def test_timing_sends_correct_log_message
14
14
  expect_message(:debug,/timing foo:bar:time 100/)
15
- @handler.timing(Camayoc::StatEvent.new("foo:bar","time",100))
15
+ @handler.event(Camayoc::StatEvent.new(:timing,"foo:bar","time",100))
16
16
  end
17
17
 
18
18
  def test_method_option_changes_method_called_on_logger
19
19
  @handler.method = :info
20
20
  expect_message(:info,/timing foo:bar:time 100/)
21
- @handler.timing(Camayoc::StatEvent.new("foo:bar","time",100))
21
+ @handler.event(Camayoc::StatEvent.new(:timing,"foo:bar","time",100))
22
22
  expect_message(:info, /count foo:bar:baz 5000/)
23
- @handler.count(Camayoc::StatEvent.new("foo:bar","baz",5000))
23
+ @handler.event(Camayoc::StatEvent.new(:count,"foo:bar","baz",5000))
24
24
  end
25
25
 
26
26
  def test_formatter_changes_format_of_message
27
- @handler.formatter = Proc.new{|type,event| "#{type}: #{event.ns_stat}"}
27
+ @handler.formatter = Proc.new{|event| "#{event.type}: #{event.ns_stat}"}
28
28
  expect_message(:debug,/timing: foo:bar:time/)
29
- @handler.timing(Camayoc::StatEvent.new("foo:bar","time",100))
29
+ @handler.event(Camayoc::StatEvent.new(:timing,"foo:bar","time",100))
30
+ end
31
+
32
+ def test_logs_unknown_event_type
33
+ expect_message(:debug,/throwaway foo:bar:time 500/)
34
+ @handler.event(Camayoc::StatEvent.new(:throwaway,"foo:bar","time",500))
30
35
  end
31
36
 
32
37
  private
@@ -34,4 +39,4 @@ class LoggerTest < Test::Unit::TestCase
34
39
  @dest_logger.expects(method).with(regexp_matches(message))
35
40
  end
36
41
 
37
- end
42
+ end