cabin 0.3.8 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/examples/metrics.rb +41 -0
- data/lib/cabin/channel.rb +3 -0
- data/lib/cabin/inspectable.rb +1 -1
- data/lib/cabin/metric.rb +22 -0
- data/lib/cabin/metrics.rb +18 -4
- data/lib/cabin/metrics/counter.rb +4 -2
- data/lib/cabin/metrics/gauge.rb +2 -2
- data/lib/cabin/metrics/histogram.rb +11 -6
- data/lib/cabin/metrics/meter.rb +3 -2
- data/lib/cabin/metrics/timer.rb +0 -2
- data/lib/cabin/namespace.rb +1 -0
- data/lib/cabin/publisher.rb +20 -0
- data/test/test_metrics.rb +7 -0
- metadata +7 -4
data/examples/metrics.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "cabin"
|
3
|
+
require "logger"
|
4
|
+
|
5
|
+
# Logging::... is something I'm implemented and experimenting with.
|
6
|
+
@logger = Cabin::Channel.new
|
7
|
+
|
8
|
+
# Metrics can be subscribed-to as well.
|
9
|
+
@logger.subscribe(Logger.new(STDOUT))
|
10
|
+
|
11
|
+
counter = @logger.metrics.counter("mycounter")
|
12
|
+
counter.incr
|
13
|
+
counter.incr
|
14
|
+
counter.incr
|
15
|
+
counter.decr
|
16
|
+
|
17
|
+
meter = @logger.metrics.meter("something", "hello-world")
|
18
|
+
meter.mark
|
19
|
+
meter.mark
|
20
|
+
meter.mark
|
21
|
+
|
22
|
+
# If nil is passed as the 'instance' then the metric class name will be
|
23
|
+
# used instead.
|
24
|
+
timer = @logger.metrics.timer("ticktock")
|
25
|
+
5.times do
|
26
|
+
timer.time do
|
27
|
+
sleep rand * 2
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
3.times do
|
32
|
+
# Another way to do timing.
|
33
|
+
clock = timer.time
|
34
|
+
sleep rand * 2
|
35
|
+
clock.stop
|
36
|
+
end
|
37
|
+
|
38
|
+
# Loop through all metrics:
|
39
|
+
@logger.metrics.each do |metric|
|
40
|
+
@logger.info(metric.inspect)
|
41
|
+
end
|
data/lib/cabin/channel.rb
CHANGED
@@ -45,6 +45,8 @@ require "logger"
|
|
45
45
|
#
|
46
46
|
class Cabin::Channel
|
47
47
|
include Cabin::Mixins::Logger
|
48
|
+
|
49
|
+
# All channels come with a metrics provider.
|
48
50
|
attr_accessor :metrics
|
49
51
|
|
50
52
|
# Get a channel for a given identifier. If this identifier has never been
|
@@ -67,6 +69,7 @@ class Cabin::Channel
|
|
67
69
|
@data = {}
|
68
70
|
@level = :info
|
69
71
|
@metrics = Cabin::Metrics.new
|
72
|
+
@metrics.channel = self
|
70
73
|
end # def initialize
|
71
74
|
|
72
75
|
# Subscribe a new input
|
data/lib/cabin/inspectable.rb
CHANGED
@@ -22,7 +22,7 @@ module Cabin
|
|
22
22
|
# foo = Foo.new
|
23
23
|
# foo.inspect == '<Foo(1) @foo=123 @bar="hello" >'
|
24
24
|
def inspect
|
25
|
-
if instance_variable_defined?(
|
25
|
+
if instance_variable_defined?(:@inspectables)
|
26
26
|
ivars = @inspectables
|
27
27
|
else
|
28
28
|
ivars = instance_variables
|
data/lib/cabin/metric.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require "cabin/namespace"
|
2
|
+
require "cabin/publisher"
|
3
|
+
require "cabin/inspectable"
|
4
|
+
|
5
|
+
module Cabin::Metric
|
6
|
+
include Cabin::Inspectable
|
7
|
+
include Cabin::Publisher
|
8
|
+
|
9
|
+
def instance=(instance)
|
10
|
+
@instance = instance
|
11
|
+
end # def instance=
|
12
|
+
|
13
|
+
def instance
|
14
|
+
return @instance
|
15
|
+
end # def instance
|
16
|
+
|
17
|
+
def emit
|
18
|
+
if !@channel.nil?
|
19
|
+
@channel.publish({ :metric => instance }.merge(to_hash))
|
20
|
+
end
|
21
|
+
end # def emit
|
22
|
+
end # module Cabin::Metric
|
data/lib/cabin/metrics.rb
CHANGED
@@ -4,6 +4,8 @@ require "cabin/metrics/meter"
|
|
4
4
|
require "cabin/metrics/counter"
|
5
5
|
require "cabin/metrics/timer"
|
6
6
|
require "cabin/metrics/histogram"
|
7
|
+
require "cabin/publisher"
|
8
|
+
require "cabin/channel"
|
7
9
|
|
8
10
|
# What type of metrics do we want?
|
9
11
|
#
|
@@ -44,13 +46,14 @@ require "cabin/metrics/histogram"
|
|
44
46
|
# and management tools.
|
45
47
|
class Cabin::Metrics
|
46
48
|
include Enumerable
|
49
|
+
include Cabin::Publisher
|
47
50
|
|
48
51
|
# Get us a new metrics container.
|
49
52
|
public
|
50
53
|
def initialize
|
51
54
|
@metrics = {}
|
52
55
|
end # def initialize
|
53
|
-
|
56
|
+
|
54
57
|
private
|
55
58
|
def create(instance, name, metric_object)
|
56
59
|
if !instance.is_a?(String)
|
@@ -58,11 +61,22 @@ class Cabin::Metrics
|
|
58
61
|
end
|
59
62
|
|
60
63
|
if name.nil?
|
61
|
-
|
64
|
+
# If no name is given, use the class name of the metric.
|
65
|
+
# For example, if we invoke Metrics#timer("foo"), the metric
|
66
|
+
# name will be "foo/timer"
|
67
|
+
metric_name = "#{instance}/#{metric_object.class.name.split("::").last.downcase}"
|
62
68
|
else
|
63
|
-
|
69
|
+
# Otherwise, use "instance/name" as the name.
|
70
|
+
metric_name = "#{instance}/#{name}"
|
71
|
+
end
|
72
|
+
|
73
|
+
metric_object.channel = @channel
|
74
|
+
metric_object.instance = metric_name
|
75
|
+
|
76
|
+
if @channel
|
77
|
+
@channel.debug("Created metric", :instance => instance, :type => metric_object.class)
|
64
78
|
end
|
65
|
-
return @metrics[
|
79
|
+
return @metrics[metric_name] = metric_object
|
66
80
|
end # def create
|
67
81
|
|
68
82
|
# Create a new Counter metric
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require "cabin/namespace"
|
2
|
-
require "cabin/
|
2
|
+
require "cabin/metric"
|
3
3
|
require "thread"
|
4
4
|
|
5
5
|
class Cabin::Metrics::Counter
|
6
|
-
include Cabin::
|
6
|
+
include Cabin::Metric
|
7
7
|
|
8
8
|
# A new Counter.
|
9
9
|
#
|
@@ -18,11 +18,13 @@ class Cabin::Metrics::Counter
|
|
18
18
|
# increment this counter
|
19
19
|
def incr
|
20
20
|
@lock.synchronize { @value += 1 }
|
21
|
+
emit
|
21
22
|
end # def incr
|
22
23
|
|
23
24
|
# decrement this counter
|
24
25
|
def decr
|
25
26
|
@lock.synchronize { @value -= 1 }
|
27
|
+
emit
|
26
28
|
end # def decr
|
27
29
|
|
28
30
|
# Get the value of this metric.
|
data/lib/cabin/metrics/gauge.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
require "cabin/namespace"
|
2
|
-
require "cabin/
|
2
|
+
require "cabin/metric"
|
3
3
|
require "thread"
|
4
4
|
|
5
5
|
class Cabin::Metrics::Histogram
|
6
|
-
include Cabin::
|
6
|
+
include Cabin::Metric
|
7
7
|
|
8
8
|
# A new Histogram.
|
9
9
|
public
|
@@ -20,8 +20,8 @@ class Cabin::Metrics::Histogram
|
|
20
20
|
#
|
21
21
|
# Sliding values of all of these?
|
22
22
|
@total = 0
|
23
|
-
@min =
|
24
|
-
@max =
|
23
|
+
@min = nil
|
24
|
+
@max = nil
|
25
25
|
@count = 0
|
26
26
|
@mean = 0.0
|
27
27
|
end # def initialize
|
@@ -31,12 +31,17 @@ class Cabin::Metrics::Histogram
|
|
31
31
|
@lock.synchronize do
|
32
32
|
@count += 1
|
33
33
|
@total += value
|
34
|
-
@min
|
35
|
-
|
34
|
+
if @min.nil? or value < @min
|
35
|
+
@min = value
|
36
|
+
end
|
37
|
+
if @max.nil? or value > @max
|
38
|
+
@max = value
|
39
|
+
end
|
36
40
|
@mean = @total / @count
|
37
41
|
# TODO(sissel): median
|
38
42
|
# TODO(sissel): percentiles
|
39
43
|
end
|
44
|
+
emit
|
40
45
|
end # def record
|
41
46
|
|
42
47
|
# This is a very poor way to access the metric data.
|
data/lib/cabin/metrics/meter.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
require "cabin/namespace"
|
2
|
-
require "cabin/
|
2
|
+
require "cabin/metric"
|
3
3
|
require "thread"
|
4
4
|
|
5
5
|
class Cabin::Metrics::Meter
|
6
|
-
include Cabin::
|
6
|
+
include Cabin::Metric
|
7
7
|
|
8
8
|
# A new Meter
|
9
9
|
#
|
@@ -21,6 +21,7 @@ class Cabin::Metrics::Meter
|
|
21
21
|
@value += 1
|
22
22
|
# TODO(sissel): Keep some moving averages?
|
23
23
|
end
|
24
|
+
emit
|
24
25
|
end # def mark
|
25
26
|
|
26
27
|
# Get the value of this metric.
|
data/lib/cabin/metrics/timer.rb
CHANGED
data/lib/cabin/namespace.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "cabin/namespace"
|
2
|
+
|
3
|
+
# This mixin allows you to easily give channel and publish features
|
4
|
+
# to a class.
|
5
|
+
module Cabin::Publisher
|
6
|
+
# Set the channel
|
7
|
+
def channel=(channel)
|
8
|
+
@channel = channel
|
9
|
+
end # def channel=
|
10
|
+
|
11
|
+
# Get the channel
|
12
|
+
def channel
|
13
|
+
return @channel
|
14
|
+
end # def channel
|
15
|
+
|
16
|
+
# Publish to the channel
|
17
|
+
def publish(object)
|
18
|
+
@channel << object
|
19
|
+
end # def publish
|
20
|
+
end # module Cabin::Publisher
|
data/test/test_metrics.rb
CHANGED
@@ -44,6 +44,13 @@ describe Cabin::Metrics do
|
|
44
44
|
|
45
45
|
test "meter time-based averages" # TODO(sissel): implement
|
46
46
|
|
47
|
+
test "timer first-run has max == min" do
|
48
|
+
timer = @metrics.timer(self)
|
49
|
+
timer.time { true }
|
50
|
+
assert_equal(timer.to_hash[:min], timer.to_hash[:max],
|
51
|
+
"With a single event, min and max must be equal")
|
52
|
+
end
|
53
|
+
|
47
54
|
test "timer counter" do
|
48
55
|
timer = @metrics.timer(self)
|
49
56
|
30.times do |i|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cabin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
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: 2012-02-
|
12
|
+
date: 2012-02-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
16
|
-
requirement: &
|
16
|
+
requirement: &5144860 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *5144860
|
25
25
|
description: This is an experiment to try and make logging more flexible and more
|
26
26
|
consumable. Plain text logs are bullshit, let's emit structured and contextual logs.
|
27
27
|
Metrics, too!
|
@@ -34,6 +34,7 @@ extra_rdoc_files: []
|
|
34
34
|
files:
|
35
35
|
- lib/cabin/inspectable.rb
|
36
36
|
- lib/cabin/context.rb
|
37
|
+
- lib/cabin/metric.rb
|
37
38
|
- lib/cabin/timer.rb
|
38
39
|
- lib/cabin/outputs/stdlib-logger.rb
|
39
40
|
- lib/cabin/outputs/em/stdlib-logger.rb
|
@@ -47,11 +48,13 @@ files:
|
|
47
48
|
- lib/cabin/metrics/meter.rb
|
48
49
|
- lib/cabin/metrics/counter.rb
|
49
50
|
- lib/cabin/metrics.rb
|
51
|
+
- lib/cabin/publisher.rb
|
50
52
|
- lib/cabin/channel.rb
|
51
53
|
- lib/cabin.rb
|
52
54
|
- examples/fibonacci-timing.rb
|
53
55
|
- examples/sinatra-logging.rb
|
54
56
|
- examples/sample.rb
|
57
|
+
- examples/metrics.rb
|
55
58
|
- test/test_logging.rb
|
56
59
|
- test/minitest-patch.rb
|
57
60
|
- test/test_metrics.rb
|