Use centralized Logger and add instrument methods

This commit is contained in:
Thomas Reynolds 2012-07-15 11:04:45 -07:00
parent 95339dad23
commit de6d7980ac
15 changed files with 126 additions and 61 deletions

View file

@ -1,6 +1,8 @@
Master Master
=== ===
* Use centralized Logger and add benchmark methods
3.0.0.rc.3 3.0.0.rc.3
==== ====
* Improve asset methods and link_to by making them more clever and aware of options such as relative_assets and http_prefix * Improve asset methods and link_to by making them more clever and aware of options such as relative_assets and http_prefix

View file

@ -4,6 +4,7 @@ require "tilt"
# Use ActiveSupport JSON # Use ActiveSupport JSON
require "active_support/json" require "active_support/json"
require "active_support/core_ext/integer/inflections" require "active_support/core_ext/integer/inflections"
require "active_support/core_ext/float/rounding"
# Simple callback library # Simple callback library
require "middleman-core/vendor/hooks-0.2.0/lib/hooks" require "middleman-core/vendor/hooks-0.2.0/lib/hooks"
@ -17,7 +18,7 @@ module Middleman
class Application class Application
# Uses callbacks # Uses callbacks
include Hooks include Hooks
# Before request hook # Before request hook
define_hook :before define_hook :before
@ -85,10 +86,6 @@ module Middleman
# @return [String] # @return [String]
set :environment, (ENV['MM_ENV'] && ENV['MM_ENV'].to_sym) || :development set :environment, (ENV['MM_ENV'] && ENV['MM_ENV'].to_sym) || :development
# Whether logging is active, disabled by default
# @return [String]
set :logging, false
# Which file should be used for directory indexes # Which file should be used for directory indexes
# @return [String] # @return [String]
set :index_file, "index.html" set :index_file, "index.html"
@ -227,13 +224,8 @@ module Middleman
def settings def settings
self self
end end
# Whether we're logging delegate :logger, :instrument, :to => ::Middleman::Util
#
# @return [Boolean] If we're logging
def logging?
logging
end
# Work around this bug: http://bugs.ruby-lang.org/issues/4521 # Work around this bug: http://bugs.ruby-lang.org/issues/4521
# where Ruby will call to_s/inspect while printing exception # where Ruby will call to_s/inspect while printing exception

View file

@ -28,6 +28,10 @@ module Middleman::Cli
:type => :boolean, :type => :boolean,
:default => false, :default => false,
:desc => 'Print debug messages' :desc => 'Print debug messages'
method_option :instrument,
:type => :string,
:default => false,
:desc => 'Print instrument messages'
# Core build Thor command # Core build Thor command
# @return [void] # @return [void]
@ -45,7 +49,7 @@ module Middleman::Cli
@debugging = Middleman::Cli::Base.respond_to?(:debugging) && Middleman::Cli::Base.debugging @debugging = Middleman::Cli::Base.respond_to?(:debugging) && Middleman::Cli::Base.debugging
@had_errors = false @had_errors = false
self.class.shared_instance(options["verbose"]) self.class.shared_instance(options["verbose"], options["instrument"])
self.class.shared_rack self.class.shared_rack
@ -73,10 +77,10 @@ module Middleman::Cli
# Middleman::Application singleton # Middleman::Application singleton
# #
# @return [Middleman::Application] # @return [Middleman::Application]
def shared_instance(verbose=false) def shared_instance(verbose=false, instrument=false)
@_shared_instance ||= ::Middleman::Application.server.inst do @_shared_instance ||= ::Middleman::Application.server.inst do
set :environment, :build set :environment, :build
set :logging, verbose logger(verbose ? 0 : 1, instrument)
end end
end end
@ -146,6 +150,7 @@ module Middleman::Cli
# A Thor Action, modular code, which does the majority of the work. # A Thor Action, modular code, which does the majority of the work.
class GlobAction < ::Thor::Actions::EmptyDirectory class GlobAction < ::Thor::Actions::EmptyDirectory
attr_reader :source attr_reader :source
attr_reader :logger
# Setup the action # Setup the action
# #
@ -158,6 +163,8 @@ module Middleman::Cli
@source = File.expand_path(base.find_in_source_paths(source.to_s)) @source = File.expand_path(base.find_in_source_paths(source.to_s))
@logger = Middleman::Cli::Build.shared_instance.logger
super(base, @destination, config) super(base, @destination, config)
end end
@ -221,7 +228,7 @@ module Middleman::Cli
sort_order = %w(.png .jpeg .jpg .gif .bmp .svg .svgz .ico .woff .otf .ttf .eot .js .css) sort_order = %w(.png .jpeg .jpg .gif .bmp .svg .svgz .ico .woff .otf .ttf .eot .js .css)
# Pre-request CSS to give Compass a chance to build sprites # Pre-request CSS to give Compass a chance to build sprites
puts "== Prerendering CSS" if @app.logging? logger.debug "== Prerendering CSS"
@app.sitemap.resources.select do |resource| @app.sitemap.resources.select do |resource|
resource.ext == ".css" resource.ext == ".css"
@ -229,7 +236,7 @@ module Middleman::Cli
Middleman::Cli::Build.shared_rack.get(URI.escape(resource.destination_path)) Middleman::Cli::Build.shared_rack.get(URI.escape(resource.destination_path))
end end
puts "== Checking for Compass sprites" if @app.logging? logger.debug "== Checking for Compass sprites"
# Double-check for compass sprites # Double-check for compass sprites
@app.files.find_new_files(Pathname.new(@app.source_dir) + @app.images_dir) @app.files.find_new_files(Pathname.new(@app.source_dir) + @app.images_dir)
@ -238,7 +245,7 @@ module Middleman::Cli
# find files in the build folder when it needs to generate sprites for the # find files in the build folder when it needs to generate sprites for the
# css files # css files
puts "== Building files" if @app.logging? logger.debug "== Building files"
resources = @app.sitemap.resources.sort do |a, b| resources = @app.sitemap.resources.sort do |a, b|
a_idx = sort_order.index(a.ext) || 100 a_idx = sort_order.index(a.ext) || 100

View file

@ -25,6 +25,10 @@ module Middleman::Cli
:type => :boolean, :type => :boolean,
:default => false, :default => false,
:desc => 'Print debug messages' :desc => 'Print debug messages'
method_option :instrument,
:type => :string,
:default => false,
:desc => 'Print instrument messages'
method_option "disable-watcher", method_option "disable-watcher",
:type => :boolean, :type => :boolean,
:default => false, :default => false,
@ -47,6 +51,7 @@ module Middleman::Cli
:host => options["host"], :host => options["host"],
:environment => options["environment"], :environment => options["environment"],
:debug => options["verbose"], :debug => options["verbose"],
:instrumenting => options["instrument"],
:"disable-watcher" => options["disable-watcher"] :"disable-watcher" => options["disable-watcher"]
} }

View file

@ -113,9 +113,9 @@ module Middleman
end end
if ext_module.nil? if ext_module.nil?
puts "== Unknown Extension: #{ext}" logger.warning "== Unknown Extension: #{ext}"
else else
puts "== Activating: #{ext}" if logging? logger.debug "== Activating: #{ext}"
self.class.register(ext_module, options, &block) self.class.register(ext_module, options, &block)
end end
end end
@ -133,7 +133,7 @@ module Middleman
# Check for and evaluate local configuration # Check for and evaluate local configuration
local_config = File.join(root, "config.rb") local_config = File.join(root, "config.rb")
if File.exists? local_config if File.exists? local_config
puts "== Reading: Local config" if logging? logger.debug "== Reading: Local config"
instance_eval File.read(local_config), local_config, 1 instance_eval File.read(local_config), local_config, 1
end end
@ -150,10 +150,9 @@ module Middleman
run_hook :after_configuration run_hook :after_configuration
if logging? logger.debug "Loaded extensions:"
self.class.extensions.each do |ext| self.class.extensions.each do |ext|
puts "== Extension: #{ext}" logger.debug "== Extension: #{ext}"
end
end end
end end
end end

View file

@ -53,6 +53,9 @@ module Middleman
# Core File Change API class # Core File Change API class
class API class API
attr_reader :app
delegate :logger, :to => :app
# Initialize api and internal path cache # Initialize api and internal path cache
def initialize(app) def initialize(app)
@app = app @app = app
@ -86,7 +89,7 @@ module Middleman
# @return [void] # @return [void]
def did_change(path) def did_change(path)
return if ignored?(path) return if ignored?(path)
puts "== File Change: #{path.relative_path_from(@app.root_path)}" if @app.logging? logger.debug "== File Change: #{path.relative_path_from(@app.root_path)}"
@known_paths << path @known_paths << path
self.run_callbacks(path, :changed) self.run_callbacks(path, :changed)
end end
@ -97,7 +100,7 @@ module Middleman
# @return [void] # @return [void]
def did_delete(path) def did_delete(path)
return if ignored?(path) return if ignored?(path)
puts "== File Deletion: #{path.relative_path_from(@app.root_path)}" if @app.logging? logger.debug "== File Deletion: #{path.relative_path_from(@app.root_path)}"
@known_paths.delete(path) @known_paths.delete(path)
self.run_callbacks(path, :deleted) self.run_callbacks(path, :deleted)
end end

View file

@ -46,6 +46,9 @@ module Middleman::CoreExtensions
end end
class FrontmatterManager class FrontmatterManager
attr_reader :app
delegate :logger, :to => :app
def initialize(app) def initialize(app)
@app = app @app = app
@cache = {} @cache = {}
@ -84,7 +87,7 @@ module Middleman::CoreExtensions
begin begin
data = YAML.load($1) data = YAML.load($1)
rescue *YAML_ERRORS => e rescue *YAML_ERRORS => e
puts "YAML Exception: #{e.message}" logger.error "YAML Exception: #{e.message}"
return false return false
end end
@ -107,7 +110,7 @@ module Middleman::CoreExtensions
json = ($1+$2).sub(";;;", "{").sub(";;;", "}") json = ($1+$2).sub(";;;", "{").sub(";;;", "}")
data = ActiveSupport::JSON.decode(json) data = ActiveSupport::JSON.decode(json)
rescue => e rescue => e
puts "JSON Exception: #{e.message}" logger.error "JSON Exception: #{e.message}"
return false return false
end end

View file

@ -197,7 +197,7 @@ module Middleman
self.req = req = ::Rack::Request.new(env) self.req = req = ::Rack::Request.new(env)
self.res = res = ::Rack::Response.new self.res = res = ::Rack::Response.new
puts "== Request: #{env["PATH_INFO"]}" if logging? logger.debug "== Request: #{env["PATH_INFO"]}"
# Catch :halt exceptions and use that response if given # Catch :halt exceptions and use that response if given
catch(:halt) do catch(:halt) do
@ -271,7 +271,7 @@ module Middleman
end end
# End the request # End the request
puts "== Finishing Request: #{request_path} (#{(Time.now - start_time).round(2)}s)" if logging? logger.debug "== Finishing Request: #{request_path} (#{(Time.now - start_time).round(2)}s)"
halt res.finish halt res.finish
end end

View file

@ -0,0 +1,29 @@
# Use the Ruby/Rails logger
require 'active_support/core_ext/logger'
require "securerandom"
module Middleman
# The Middleman Logger
class Logger < ::Logger
# Force output to STDOUT
def initialize(log_level=1, is_instrumenting=false, target=STDOUT)
super(STDOUT)
self.level = log_level
@instrumenting = is_instrumenting
if @instrumenting != false
::ActiveSupport::Notifications.subscribe(/\.middleman$/, self)
end
end
def call(message, *args)
return if @instrumenting.is_a?(String) && @instrumenting != "instrument" && !message.include?(@instrumenting)
evt = ActiveSupport::Notifications::Event.new(message, *args)
self.info "== Instrument (#{evt.name.sub(/.middleman$/, '')}): #{evt.duration}ms"
end
end
end

View file

@ -9,23 +9,23 @@ module Middleman
DEFAULT_PORT = 4567 DEFAULT_PORT = 4567
class << self class << self
attr_reader :app
delegate :logger, :to => :app
# Start an instance of Middleman::Application # Start an instance of Middleman::Application
# @return [void] # @return [void]
def start(options={}) def start(options={})
app = ::Middleman::Application.server.inst do @app = ::Middleman::Application.server.inst do
if options[:environment] if options[:environment]
set :environment, options[:environment].to_sym set :environment, options[:environment].to_sym
end end
if options[:debug] logger(options[:debug] ? 0 : 1, options[:instrumenting] || false)
set :logging, true
end
end end
port = options[:port] || DEFAULT_PORT port = options[:port] || DEFAULT_PORT
puts "== The Middleman is standing watch on port #{port}" logger.info "== The Middleman is standing watch on port #{port}"
@webrick ||= setup_webrick( @webrick ||= setup_webrick(
options[:host] || "0.0.0.0", options[:host] || "0.0.0.0",
@ -54,7 +54,7 @@ module Middleman
# Detach the current Middleman::Application instance # Detach the current Middleman::Application instance
# @return [void] # @return [void]
def stop def stop
puts "== The Middleman is shutting down" logger.info "== The Middleman is shutting down"
if @listener if @listener
@listener.stop @listener.stop
@listener = nil @listener = nil

View file

@ -43,7 +43,7 @@ module Middleman
::Tilt.prefer(markdown_engine_klass) ::Tilt.prefer(markdown_engine_klass)
end end
rescue LoadError rescue LoadError
$stderr.puts "Requested Markdown engine (#{markdown_engine}) not found. Maybe the gem needs to be installed and required?" logger.warn "Requested Markdown engine (#{markdown_engine}) not found. Maybe the gem needs to be installed and required?"
end end
end end
end end

View file

@ -11,6 +11,7 @@ module Middleman
# @return [Middleman::Application] # @return [Middleman::Application]
attr_reader :app attr_reader :app
delegate :logger, :instrument, :to => :app
# @return [Middleman::Sitemap::Store] # @return [Middleman::Sitemap::Store]
attr_reader :store attr_reader :store
@ -111,30 +112,28 @@ module Middleman
# @return [String] # @return [String]
def render(opts={}, locs={}, &block) def render(opts={}, locs={}, &block)
return File.open(source_file).read unless template? return File.open(source_file).read unless template?
start_time = Time.now
puts "== Render Start: #{source_file}" if app.logging?
md = metadata.dup relative_source = Pathname(source_file).relative_path_from(Pathname(app.root))
opts = md[:options].deep_merge(opts)
locs = md[:locals].deep_merge(locs)
# Forward remaining data to helpers
if md.has_key?(:page)
app.data.store("page", md[:page])
end
md[:blocks].each do |aBlock|
app.instance_eval(&aBlock)
end
app.instance_eval(&block) if block_given?
app.current_path ||= self.destination_path instrument "render.resource", :path => relative_source do
result = app.render_template(source_file, locs, opts) md = metadata.dup
opts = md[:options].deep_merge(opts)
locs = md[:locals].deep_merge(locs)
puts "== Render End: #{source_file} (#{(Time.now - start_time).round(2)}s)" if app.logging? # Forward remaining data to helpers
result if md.has_key?(:page)
app.data.store("page", md[:page])
end
md[:blocks].each do |aBlock|
app.instance_eval(&aBlock)
end
app.instance_eval(&block) if block_given?
app.current_path ||= self.destination_path
app.render_template(source_file, locs, opts)
end
end end
# A path without the directory index - so foo/index.html becomes # A path without the directory index - so foo/index.html becomes

View file

@ -1,3 +1,9 @@
# Our custom logger
require "middleman-core/logger"
# For instrumenting
require "active_support/notifications"
# Using Thor's indifferent hash access # Using Thor's indifferent hash access
require "thor" require "thor"
@ -6,6 +12,23 @@ require "pathname"
module Middleman module Middleman
module Util module Util
# The logger
#
# @return [Middleman::Logger] The logger
def self.logger(*args)
if !@_logger || args.length > 0
@_logger = ::Middleman::Logger.new(*args)
end
@_logger
end
# Facade for ActiveSupport/Notification
def self.instrument(name, payload={}, &block)
name << ".middleman" unless name =~ /\.middleman$/
::ActiveSupport::Notifications.instrument(name, payload, &block)
end
# Recursively convert a normal Hash into a HashWithIndifferentAccess # Recursively convert a normal Hash into a HashWithIndifferentAccess
# #

View file

@ -23,6 +23,9 @@ module Middleman
end end
class Localizer class Localizer
attr_reader :app
delegate :logger, :to => :app
def initialize(app, options={}) def initialize(app, options={})
@app = app @app = app
@maps = {} @maps = {}
@ -34,7 +37,7 @@ module Middleman
@mount_at_root = @options.has_key?(:mount_at_root) ? @options[:mount_at_root] : langs.first @mount_at_root = @options.has_key?(:mount_at_root) ? @options[:mount_at_root] : langs.first
if !@app.build? if !@app.build?
puts "== Locales: #{langs.join(", ")}" logger.info "== Locales: #{langs.join(", ")}"
end end
# Don't output localizable files # Don't output localizable files

View file

@ -21,7 +21,7 @@ module Middleman
if File.readable?(real_path) if File.readable?(real_path)
File.mtime(real_path).strftime("%s") File.mtime(real_path).strftime("%s")
else else
$stderr.puts "WARNING: '#{File.basename(path)}' was not found (or cannot be read) in #{File.dirname(real_path)}" logger.warn "WARNING: '#{File.basename(path)}' was not found (or cannot be read) in #{File.dirname(real_path)}"
end end
end end
end end