Skip to content
Browse files

Added Logger extension with Specs.

  • Loading branch information...
1 parent 0bb6a45 commit c1c82b0fab0deb243a871e9f816c7e9309581fcd @kematzy committed
Showing with 434 additions and 3 deletions.
  1. +185 −0 lib/sinatra/logger.rb
  2. +194 −0 spec/sinatra/logger_spec.rb
  3. +55 −3 spec/spec_helper.rb
View
185 lib/sinatra/logger.rb
@@ -0,0 +1,185 @@
+
+require 'sinatra/base'
+require 'logger'
+
+module Sinatra
+
+ # = Sinatra::Logger
+ #
+ # A Sinatra extension that makes logging within Your apps easy.
+ #
+ #
+ # == Installation
+ #
+ # # Add Gemcutter to your RubyGems sources
+ # $ gem sources -a http://gemcutter.com
+ #
+ # $ (sudo)? gem install sinatra-logger
+ #
+ # == Dependencies
+ #
+ # This Gem depends upon the following:
+ #
+ # === Runtime:
+ #
+ # * sinatra ( >= 1.0.a )
+ # * logger
+ #
+ # === Development & Tests:
+ #
+ # * rspec (>= 1.3.0 )
+ # * rack-test (>= 0.5.3)
+ # * rspec_hpricot_matchers (>= 0.1.0)
+ # * sinatra-tests (>= 0.1.6)
+ #
+ #
+ # == Getting Started
+ #
+ # To get logging in your app, just register the extension
+ # in your sub-classed Sinatra app:
+ #
+ # class YourApp < Sinatra::Base
+ #
+ # register(Sinatra::Logger)
+ # <snip...>
+ # end
+ #
+ # Then in your App's route or helper method declarations, just use the <tt>#logger</tt>...
+ #
+ # get '/some/route' do
+ # logger.debug("some informative message goes here")
+ # <snip...>
+ # end
+ #
+ # helpers do
+ # def some_helper_method
+ # logger.info("some equally informative message goes here")
+ # <snip...>
+ # end
+ # end
+ #
+ #
+ # That's pretty painless, no?
+ #
+ #
+ # === Logging Levels
+ #
+ # The <b>default Log level</b> is <tt>:warn</tt>.
+ #
+ # All the available logging levels are those of Logger[http://ruby-doc.org/stdlib/libdoc/logger/rdoc/classes/Logger.html], which are:
+ #
+ # * <tt>logger.fatal(msg)</tt> - - (FATAL) - an unhandleable error that results in a program crash
+ #
+ # * <tt>logger.error(msg)</tt> - - (ERROR) - a handleable error condition
+ #
+ # * <tt>logger.warn(msg)</tt> - - (WARN) - a warning
+ #
+ # * <tt>logger.info(msg)</tt> - - (INFO) - generic (useful) information about system operation
+ #
+ # * <tt>logger.debug(msg)</tt> - - (DEBUG) - low-level information for developers
+ #
+ #
+ # OK, by now you might be asking yourself,
+ #
+ # <em>"So where does the log messages go then ?"</em>.
+ #
+ #
+ # === Logging Locations
+ #
+ # By default the logger will log it's message to the following path:
+ #
+ # < the root of your app >/log/< environment >.log
+ #
+ # In other words if your app's root is [ <tt>/home/www/your-great-app/</tt> ] and it's
+ # running in <tt>:production</tt> mode, then the log location would become:
+ #
+ # /home/www/your-great-app/log/production.log
+ #
+ # <b>NB!</b> this extension takes for granted that you have a ../log/ directory with write access at the root of your app.
+ #
+ #
+ # === Custom Logging Location
+ #
+ # If the defaults are NOT for you, then just do...
+ #
+ # class YourApp < Sinatra::Base
+ #
+ # register(Sinatra::Logger)
+ #
+ # set: :logger_log_file, lambda { "/path/2/your/log/file.ext" }
+ #
+ # <snip...>
+ #
+ # end
+ #
+ #
+ # # the lambda { } is required, especially if you have variables in the path
+ #
+ # ..., now your log messages will be written to that log file.
+ #
+ #
+ # === Setting Log Level
+ #
+ # Finally, to use a different Log level for your app, other than the default <tt>:warn</tt> just...
+ #
+ # class YourApp < Sinatra::Base
+ #
+ # register(Sinatra::Logger)
+ #
+ # set: :logger_level, :fatal # or :error, :warn, :info, :debug
+ # <snip...>
+ # end
+ #
+ #
+ # That's it. I hope that's easy enough.
+ #
+ module Logger
+
+ VERSION = '0.1.0'
+ ##
+ # Returns the version string for this extension
+ #
+ # ==== Examples
+ #
+ # Sinatra::Logger.version => 'Sinatra::Logger v0.1.0'
+ #
+ def self.version; "Sinatra::Logger v#{VERSION}"; end
+
+
+ module Helpers
+
+ ##
+ # Provides easy access to the Logger object throughout your
+ # application
+ #
+ # ==== Examples
+ #
+ # logger.warn("messsage")
+ #
+ #
+ # @api public
+ def logger
+ @logger ||= begin
+ @logger = ::Logger.new(self.class.logger_log_file)
+ @logger.level = ::Logger.const_get((self.class.logger_level || :warn).to_s.upcase)
+ @logger.datetime_format = "%Y-%m-%d %H:%M:%S"
+ @logger
+ end
+ end
+
+ end #/module Helpers
+
+
+ def self.registered(app)
+ app.helpers Sinatra::Logger::Helpers
+
+ # set the output log level
+ app.set :logger_level, :warn
+ # set the full path to the log file
+ app.set :logger_log_file, lambda { File.join(root, 'log', "#{environment}.log") }
+
+ end #/ self.registered
+
+ end #/module Logger
+
+end #/ Sinatra
View
194 spec/sinatra/logger_spec.rb
@@ -0,0 +1,194 @@
+
+require File.expand_path(File.dirname(File.dirname(__FILE__)) + '/spec_helper')
+
+describe "Sinatra" do
+
+ class MyTestApp
+ register Sinatra::Logger
+
+ helpers do
+
+ def dummy_helper(level, message)
+ logger.send(level, message)
+ "Level: #{level}, Message: #{message}"
+ end
+ end
+
+ get '/logger/:msg' do
+ logger.warn("Message: #{params[:msg]}")
+ erb("Message: #{params[:msg]}", :layout => false )
+ end
+
+ end
+
+ it_should_behave_like "MyTestApp"
+
+ describe "Logger" do
+
+ describe "with Default Settings" do
+
+ before(:each) do
+ FileUtils.mkdir_p "#{fixtures_path}/log"
+ @log_file = "#{fixtures_path}/log/#{MyTestApp.environment}.log"
+ `touch #{@log_file}`
+ end
+
+ after(:each) do
+ `echo '' > #{@log_file}`
+ end
+
+ describe "Configuration" do
+
+ it "should set :logger_level to :warn" do
+ app.settings.logger_level.should == :warn
+ end
+
+ it "should set :logger_log_file to [../log/< environment >.log]" do
+ app.settings.logger_log_file.should == "#{fixtures_path}/log/test.log"
+ end
+
+ end #/ Configuration
+
+ describe "Helpers" do
+
+ describe "#logger" do
+
+ it "should create a #{MyTestApp.environment}.log file when initialized" do
+ test(?f, @log_file).should == true
+ end
+
+ it "should return an instance of Logger" do
+ app.should respond_to(:logger)
+ app.logger.should be_a_kind_of(::Logger)
+ end
+
+ it "should log when called from within a route" do
+ get('/logger/this-works')
+ body.should == "Message: this-works"
+ IO.read(@log_file).should match(/WARN -- : Message: this-works/)
+ end
+
+ it "should log when called from within helper methods" do
+ erb_app '<%= dummy_helper(:warn, "works too") %>'
+ IO.read(@log_file).should match(/WARN -- : works too/)
+ body.should == "Level: warn, Message: works too"
+ end
+
+ it "should NOT log lower levels" do
+ erb_app '<%= dummy_helper(:info, "default-info") %>'
+ IO.read(@log_file).should_not match(/INFO -- : default-info/)
+ body.should == "Level: info, Message: default-info"
+
+ erb_app '<%= dummy_helper(:debug, "default-debug") %>'
+ IO.read(@log_file).should_not match(/DEBUG -- : default-debug/)
+ body.should == "Level: debug, Message: default-debug"
+ end
+
+ end #/ #logger
+
+ end #/ Helpers
+
+ end #/ with Default Settings
+
+ describe "with Custom Settings" do
+
+ class MyCustomTestApp
+ register Sinatra::Logger
+
+ set :logger_level, :debug
+ set :logger_log_file, lambda { "#{fixtures_path}/log/custom.log" }
+
+ helpers do
+
+ def dummy_helper(level, message)
+ logger.send(level, message)
+ "Level: #{level}, Message: #{message}"
+ end
+ end
+
+ get '/customlogger/:msg' do
+ logger.warn("Message: #{params[:msg]}")
+ erb("CustomMessage: #{params[:msg]}", :layout => false )
+ end
+
+ end
+
+ before(:each) do
+ class ::Test::Unit::TestCase
+ def app; ::MyCustomTestApp.new ; end
+ end
+ @app = app
+
+ FileUtils.mkdir_p "#{fixtures_path}/log"
+ @custom_log_file = "#{fixtures_path}/log/custom.log"
+ `touch #{@custom_log_file}`
+ end
+
+ after(:each) do
+ class ::Test::Unit::TestCase
+ def app; nil ; end
+ end
+ @app = nil
+
+ `echo '' > #{@custom_log_file}`
+ end
+
+ describe "Configuration" do
+
+ it "should set :logger_level to :debug" do
+ app.settings.logger_level.should == :debug
+ end
+
+ it "should set :logger_log_file to [../log/custom.log]" do
+ app.settings.logger_log_file.should == "#{fixtures_path}/log/custom.log"
+ end
+
+ end #/ Configuration
+
+ describe "Helpers" do
+
+ describe "#logger" do
+
+ it "should create a custom.log file when initialised" do
+ test(?f, @custom_log_file).should == true
+ end
+
+ it "should return an instance of Logger" do
+ app.logger.should be_a_kind_of(::Logger)
+ end
+
+ it "should log when called from within a route" do
+ get('/customlogger/this-works')
+ body.should == "CustomMessage: this-works"
+ IO.read(@custom_log_file).should match(/WARN -- : Message: this-works/)
+ end
+
+ it "should log when called from within helper methods" do
+ erb_app '<%= dummy_helper(:info, "works as well") %>'
+ IO.read(@custom_log_file).should match(/INFO -- : works as well/)
+ body.should == "Level: info, Message: works as well"
+
+ erb_app '<%= dummy_helper(:warn, "works too") %>'
+ IO.read(@custom_log_file).should match(/WARN -- : works too/)
+ body.should == "Level: warn, Message: works too"
+ end
+
+ it "should log higher levels" do
+ erb_app '<%= dummy_helper(:info, "custom-info") %>'
+ IO.read(@custom_log_file).should match(/INFO -- : custom-info/)
+ body.should == "Level: info, Message: custom-info"
+
+ erb_app '<%= dummy_helper(:debug, "custom-debug") %>'
+ IO.read(@custom_log_file).should match(/DEBUG -- : custom-debug/)
+ body.should == "Level: debug, Message: custom-debug"
+ end
+
+ end #/ #logger
+
+ end #/ Helpers
+
+ end #/ with Custom Settings
+
+ end #/ Logger
+
+end #/ Sinatra
View
58 spec/spec_helper.rb
@@ -1,9 +1,61 @@
+
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
-require 'sinatra-logger'
-require 'spec'
-require 'spec/autorun'
+
+
+#--
+# DEPENDENCIES
+#++
+%w(
+sinatra/base
+fileutils
+).each {|lib| require lib }
+
+#--
+## SINATRA EXTENSIONS
+#++
+%w(
+sinatra/tests
+sinatra/logger
+).each {|ext| require ext }
+
+
+ENV['RACK_ENV'] = 'test'
Spec::Runner.configure do |config|
+ config.include RspecHpricotMatchers
+ config.include Sinatra::Tests::TestCase
+ config.include Sinatra::Tests::RSpec::SharedSpecs
+end
+
+def fixtures_path
+ "#{File.dirname(File.expand_path(__FILE__))}/fixtures"
+end
+
+class MyTestApp < Sinatra::Base
+ set :root, "#{fixtures_path}"
+ set :app_dir, "#{fixtures_path}/app"
+ set :public, "#{fixtures_path}/public"
+ set :views, "#{app_dir}/views"
+ enable :raise_errors
+
+ register(Sinatra::Tests)
+
+end #/class MyTestApp
+
+class MyCustomTestApp < Sinatra::Base
+ set :root, "#{fixtures_path}"
+ set :app_dir, "#{fixtures_path}/app"
+ set :public, "#{fixtures_path}/public"
+ set :views, "#{app_dir}/views"
+ enable :raise_errors
+
+ register(Sinatra::Tests)
+end #/class MyCustomTestApp
+
+
+class Test::Unit::TestCase
+ Sinatra::Base.set :environment, :test
end

0 comments on commit c1c82b0

Please sign in to comment.
Something went wrong with that request. Please try again.