camayoc 0.1.0 → 0.2.0

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.
@@ -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