steno 0.0.3

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