steno 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ require "rack/test"
2
+ require "rspec"
3
+
4
+ require "steno"
5
+
6
+ Dir["./spec/support/**/*.rb"].each { |file| require file }
@@ -0,0 +1,22 @@
1
+ require "thread"
2
+
3
+ class Barrier
4
+ def initialize
5
+ @lock = Mutex.new
6
+ @cvar = ConditionVariable.new
7
+ @done = false
8
+ end
9
+
10
+ def release
11
+ @lock.synchronize do
12
+ @done = true
13
+ @cvar.broadcast
14
+ end
15
+ end
16
+
17
+ def wait
18
+ @lock.synchronize do
19
+ @cvar.wait(@lock) if !@done
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ class NullSink
2
+ attr_accessor :records
3
+
4
+ def initialize
5
+ @records = []
6
+ end
7
+
8
+ def add_record(record)
9
+ @records << record
10
+
11
+ nil
12
+ end
13
+
14
+ def flush
15
+ nil
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ shared_context :steno_context do
2
+ it "should support clearing context local data" do
3
+ context.data["test"] = "value"
4
+ context.clear
5
+ context.data["test"].should be_nil
6
+ end
7
+ end
@@ -0,0 +1,62 @@
1
+ require "spec_helper"
2
+
3
+ describe Steno::Context::Null do
4
+ include_context :steno_context
5
+
6
+ let(:context) { Steno::Context::Null.new }
7
+
8
+ it "should store no data" do
9
+ context.data.should == {}
10
+ context.data["foo"] = "bar"
11
+ context.data.should == {}
12
+ end
13
+ end
14
+
15
+ describe Steno::Context::ThreadLocal do
16
+ include_context :steno_context
17
+
18
+ let (:context) { Steno::Context::ThreadLocal.new }
19
+
20
+ it "should store data local to threads" do
21
+ b1 = Barrier.new
22
+ b2 = Barrier.new
23
+
24
+ t1 = Thread.new do
25
+ context.data["thread"] = "t1"
26
+ b1.release
27
+ b2.wait
28
+ context.data["thread"].should == "t1"
29
+ end
30
+
31
+ t2 = Thread.new do
32
+ b1.wait
33
+ context.data["thread"].should be_nil
34
+ context.data["thread"] = "t2"
35
+ b2.release
36
+ end
37
+
38
+ t1.join
39
+ t2.join
40
+ end
41
+ end
42
+
43
+ describe Steno::Context::FiberLocal do
44
+ include_context :steno_context
45
+
46
+ let(:context) { Steno::Context::FiberLocal.new }
47
+
48
+ it "should store data local to fibers" do
49
+ f2 = Fiber.new do
50
+ context.data["fiber"].should be_nil
51
+ context.data["fiber"] = "f2"
52
+ end
53
+
54
+ f1 = Fiber.new do
55
+ context.data["fiber"] = "f1"
56
+ f2.resume
57
+ context.data["fiber"].should == "f1"
58
+ end
59
+
60
+ f1.resume
61
+ end
62
+ end
@@ -0,0 +1,73 @@
1
+ require "spec_helper"
2
+
3
+ require "steno/http_handler"
4
+
5
+ describe Steno::HttpHandler do
6
+ include Rack::Test::Methods
7
+
8
+ let(:config) { Steno::Config.new }
9
+
10
+ before :each do
11
+ Steno.init(config)
12
+ end
13
+
14
+ def app
15
+ Steno::HttpHandler
16
+ end
17
+
18
+ describe "GET /loggers/levels" do
19
+ it "returns a hash of logger name to level" do
20
+ get "/loggers/levels"
21
+ json_body.should == {}
22
+
23
+ foo = Steno.logger("foo")
24
+ foo.level = :debug
25
+
26
+ bar = Steno.logger("bar")
27
+ bar.level = :info
28
+
29
+ get "/loggers/levels"
30
+ json_body.should == { "foo" => "debug", "bar" => "info" }
31
+ end
32
+ end
33
+
34
+ describe "PUT /loggers/levels" do
35
+ it "returns an error on missing parameters" do
36
+ put "/loggers/levels"
37
+ last_response.status.should == 400
38
+ json_body["error"].should match(/Missing query parameters/)
39
+
40
+ put "/loggers/levels", :regexp => "hi"
41
+ last_response.status.should == 400
42
+ json_body["error"].should match(/Missing query parameters/)
43
+
44
+ put "/loggers/levels", :level => "debug"
45
+ last_response.status.should == 400
46
+ json_body["error"].should match(/Missing query parameters/)
47
+ end
48
+
49
+ it "returns an error on invalid log levels" do
50
+ put "/loggers/levels", :regexp => "hi", :level => "foobar"
51
+ last_response.status.should == 400
52
+ json_body["error"].should match(/Unknown level/)
53
+ end
54
+
55
+ it "updates log levels for loggers whose name matches the regexp" do
56
+ foo = Steno.logger("foo")
57
+ foo.level = :debug
58
+
59
+ bar = Steno.logger("bar")
60
+ bar.level = :warn
61
+
62
+ put "/loggers/levels", :regexp => "f", :level => "error"
63
+ last_response.status.should == 200
64
+
65
+ foo.level.should == :error
66
+ bar.level.should == :warn
67
+ end
68
+ end
69
+
70
+ def json_body
71
+ Yajl::Parser.parse(last_response.body)
72
+ end
73
+ end
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ describe Steno::Sink::IO do
4
+ let(:record) { { :data => "test" } }
5
+
6
+ describe "#add_record" do
7
+ it "should encode the record and write it to the underlying io object" do
8
+ codec = mock("codec")
9
+ codec.should_receive(:encode_record).with(record).and_return(record[:data])
10
+
11
+ io = mock("io")
12
+ io.should_receive(:write).with(record[:data])
13
+
14
+ Steno::Sink::IO.new(io, codec).add_record(record)
15
+ end
16
+ end
17
+
18
+ describe "#flush" do
19
+ it "should call flush on the underlying io object" do
20
+ io = mock("io")
21
+ io.should_receive(:flush)
22
+
23
+ Steno::Sink::IO.new(io).flush
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,48 @@
1
+ require "spec_helper"
2
+
3
+ describe Steno::Codec::Json do
4
+ let(:codec) { Steno::Codec::Json.new }
5
+ let(:record) { make_record(:data => { "user" => "data" }) }
6
+
7
+ describe "#encode_record" do
8
+ it "should encode records as json hashes" do
9
+ parsed = Yajl::Parser.parse(codec.encode_record(record))
10
+ parsed.class.should == Hash
11
+ end
12
+
13
+ it "should encode the timestamp as a float" do
14
+ parsed = Yajl::Parser.parse(codec.encode_record(record))
15
+ parsed["timestamp"].class.should == Float
16
+ end
17
+
18
+ it "should escape newlines" do
19
+ rec = make_record(:message => "newline\ntest")
20
+ codec.encode_record(rec).should match(/newline\\ntest/)
21
+ end
22
+
23
+ it "should escape carriage returns" do
24
+ rec = make_record(:message => "newline\rtest")
25
+ codec.encode_record(rec).should match(/newline\\rtest/)
26
+ end
27
+
28
+ it "should allow messages with valid encodings to pass through untouched" do
29
+ msg = "HI\u2600"
30
+ rec = make_record(:message => msg)
31
+ codec.encode_record(rec).should match(/#{msg}/)
32
+ end
33
+
34
+ it "should treat messages with invalid encodings as binary data" do
35
+ msg = "HI\u2026".force_encoding("US-ASCII")
36
+ rec = make_record(:message => msg)
37
+ codec.encode_record(rec).should match(/HI\\\\xe2\\\\x80\\\\xa6/)
38
+ end
39
+ end
40
+
41
+ def make_record(opts = {})
42
+ Steno::Record.new(opts[:source] || "my_source",
43
+ opts[:level] || Steno::LogLevel.new("debug", 0),
44
+ opts[:message] || "test message",
45
+ nil,
46
+ opts[:data] || {})
47
+ end
48
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ describe Steno::LogLevel do
4
+ let(:info_level) { Steno::LogLevel.new(:info, 2) }
5
+ let(:debug_level) { Steno::LogLevel.new(:debug, 1) }
6
+
7
+ it "should be comparable" do
8
+ (info_level > debug_level).should be_true
9
+ (debug_level > info_level).should be_false
10
+ (info_level == info_level).should be_true
11
+ end
12
+
13
+ describe "#to_s" do
14
+ it "should return the name of the level" do
15
+ info_level.to_s.should == "info"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,91 @@
1
+ require "spec_helper"
2
+
3
+ describe Steno::Logger do
4
+ let(:logger) { Steno::Logger.new("test", []) }
5
+
6
+ it "should provide #level, #levelf, and #level? methods for each log level" do
7
+ Steno::Logger::LEVELS.each do |name, _|
8
+ [name, name.to_s + "f", name.to_s + "?"].each do |meth|
9
+ logger.respond_to?(meth).should be_true
10
+ end
11
+ end
12
+ end
13
+
14
+ describe "#level_active?" do
15
+ it "should return a boolean indicating if the level is enabled" do
16
+ logger.level_active?(:error).should be_true
17
+ logger.level_active?(:info).should be_true
18
+ logger.level_active?(:debug).should be_false
19
+ end
20
+ end
21
+
22
+ describe "#<level>?" do
23
+ it "should return a boolean indiciating if <level> is enabled" do
24
+ logger.error?.should be_true
25
+ logger.info?.should be_true
26
+ logger.debug?.should be_false
27
+ end
28
+ end
29
+
30
+ describe "#level" do
31
+ it "should return the name of the currently active level" do
32
+ logger.level.should == :info
33
+ end
34
+ end
35
+
36
+ describe "#level=" do
37
+ it "should allow the level to be changed" do
38
+ logger.level = :warn
39
+ logger.level.should == :warn
40
+ logger.level_active?(:info).should be_false
41
+ logger.level_active?(:warn).should be_true
42
+ end
43
+ end
44
+
45
+ describe "#log" do
46
+ it "should not forward any messages for levels that are inactive" do
47
+ sink = mock("sink")
48
+ sink.should_not_receive(:add_record)
49
+
50
+ my_logger = Steno::Logger.new("test", [sink])
51
+
52
+ my_logger.debug("test")
53
+ end
54
+
55
+ it "should forward messages for levels that are active" do
56
+ sink = mock("sink")
57
+ sink.should_receive(:add_record).with(any_args())
58
+
59
+ my_logger = Steno::Logger.new("test", [sink])
60
+
61
+ my_logger.warn("test")
62
+ end
63
+
64
+ it "should not invoke a supplied block if the level is inactive" do
65
+ invoked = false
66
+ logger.debug { invoked = true }
67
+ invoked.should be_false
68
+ end
69
+
70
+ it "should invoke a supplied block if the level is active" do
71
+ invoked = false
72
+ logger.warn { invoked = true }
73
+ invoked.should be_true
74
+ end
75
+ end
76
+
77
+ describe "#logf" do
78
+ it "should format messages according to the supplied format string" do
79
+ logger.should_receive(:log).with(:debug, "test 1 2.20")
80
+ logger.debugf("test %d %0.2f", 1, 2.2)
81
+ end
82
+ end
83
+
84
+ describe "#tag" do
85
+ it "should return a tagged logger" do
86
+ tagged_logger = logger.tag("foo" => "bar")
87
+ tagged_logger.should_not be_nil
88
+ tagged_logger.user_data.should == { "foo" => "bar" }
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,21 @@
1
+ require "spec_helper"
2
+
3
+ describe Steno::Record do
4
+ let(:record) { Steno::Record.new("test", :info, "test message") }
5
+
6
+ it "should set the process id" do
7
+ record.process_id.should == Process.pid
8
+ end
9
+
10
+ it "should set the thread id" do
11
+ record.thread_id.should == Thread.current.object_id
12
+ end
13
+
14
+ it "should set the fiber id(if available)", :needs_fibers => true do
15
+ record.fiber_id.should == Fiber.current.object_id
16
+ end
17
+
18
+ it "should set the source" do
19
+ record.source.should == "test"
20
+ end
21
+ end
@@ -0,0 +1,86 @@
1
+ require "spec_helper"
2
+
3
+ describe Steno do
4
+ let(:config) { Steno::Config.new }
5
+
6
+ before :each do
7
+ Steno.init(config)
8
+ end
9
+
10
+ describe "#logger" do
11
+ it "should return a new Steno::Logger instance" do
12
+ logger = Steno.logger("test")
13
+ logger.should_not be_nil
14
+ logger.name.should == "test"
15
+ end
16
+
17
+ it "should memoize loggers by name" do
18
+ logger1 = Steno.logger("test")
19
+ logger2 = Steno.logger("test")
20
+
21
+ logger1.object_id.should == logger2.object_id
22
+ end
23
+ end
24
+
25
+ describe "#set_logger_regexp" do
26
+ it "should modify the levels of existing loggers that match the regex" do
27
+ logger = Steno.logger("test")
28
+
29
+ logger.level.should == :info
30
+
31
+ Steno.set_logger_regexp(/te/, :debug)
32
+
33
+ logger.level.should == :debug
34
+ end
35
+
36
+ it "should modify the levels of new loggers after a regexp has been set" do
37
+ Steno.set_logger_regexp(/te/, :debug)
38
+
39
+ Steno.logger("te").level.should == :debug
40
+ end
41
+
42
+ it "should reset the levels of previously matching loggers when changed" do
43
+ Steno.set_logger_regexp(/foo/, :debug)
44
+
45
+ logger = Steno.logger("foo")
46
+ logger.level.should == :debug
47
+
48
+ Steno.set_logger_regexp(/bar/, :debug)
49
+
50
+ logger.level.should == :info
51
+ end
52
+ end
53
+
54
+ describe "#clear_logger_regexp" do
55
+ it "should reset any loggers matching the existing regexp" do
56
+ Steno.set_logger_regexp(/te/, :debug)
57
+
58
+ logger = Steno.logger("test")
59
+ logger.level.should == :debug
60
+
61
+ Steno.clear_logger_regexp
62
+
63
+ logger.level.should == :info
64
+ Steno.logger_regexp.should be_nil
65
+ end
66
+ end
67
+
68
+ describe "#logger_level_snapshot" do
69
+ it "should return a hash mapping logger name to level" do
70
+ loggers = []
71
+
72
+ expected = {
73
+ "foo" => :debug,
74
+ "bar" => :warn,
75
+ }
76
+
77
+ expected.each do |name, level|
78
+ # Prevent GC
79
+ loggers << Steno.logger(name)
80
+ loggers.last.level = level
81
+ end
82
+
83
+ Steno.logger_level_snapshot.should == expected
84
+ end
85
+ end
86
+ end