Skip to content

Commit

Permalink
Inject verbose logging into the application if requested.
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix committed Feb 13, 2018
1 parent 397a3a4 commit c53f41c
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 23 deletions.
19 changes: 1 addition & 18 deletions examples/sinatra/config.ru
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env falcon serve -c
#!/usr/bin/env falcon --verbose serve -c

# Save this as `config.ru`, make it executable and then run it (or run falcon serve by hand)

Expand All @@ -10,23 +10,6 @@ class MyApp < Sinatra::Base
end
end

# Middleware that performs logging:
require 'async/logger'
Async.logger.level = Logger::DEBUG # Set log level to debug

class MyLogger
def initialize(app)
@app = app
end

def call(env)
Async.logger.info "#{env['REQUEST_METHOD']} #{env['PATH_INFO']}"

return @app.call(env)
end
end

# Build the middleware stack:
use MyLogger # First, a request will pass through MyLogger#call.
use MyApp # Then, it will get to Sinatra.
run lambda {|env| [404, {}, []]} # Bottom of the stack, give 404.
35 changes: 30 additions & 5 deletions lib/falcon/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
# THE SOFTWARE.

require_relative 'server'
require_relative 'verbose'

require 'async/container'

Expand Down Expand Up @@ -63,9 +64,21 @@ def container_class
end
end

def run
def load_app(verbose)
app, options = Rack::Builder.parse_file(@options[:config])

if verbose
app = Verbose.new(app)
end

return app, options
end

def run(verbose)
app, options = load_app(verbose)

Async.logger.info "Falcon taking flight! Binding to #{@options[:bind]} [#{container_class} with concurrency: #{@options[:concurrency]}]"

container_class.new(concurrency: @options[:concurrency]) do
server = Falcon::Server.new(app, [
Async::IO::Endpoint.parse(@options[:bind], reuse_port: true)
Expand All @@ -75,8 +88,8 @@ def run
end
end

def invoke
run
def invoke(parent)
run(parent.verbose?)

sleep
end
Expand All @@ -85,17 +98,29 @@ def invoke
class Top < Samovar::Command
self.description = "An asynchronous HTTP client/server toolset."

options do
option '--verbose', 'Increase the log output', default: false
end

nested '<command>',
'serve' => Serve
# 'get' => Get
# 'post' => Post
# 'head' => Head,
# 'put' => Put,
# 'delete' => Delete


def verbose?
options[:verbose]
end

def invoke(program_name: File.basename($0))
if options[:verbose]
Async.logger.level = Logger::INFO
end

if @command
@command.invoke
@command.invoke(self)
else
print_usage(program_name)
end
Expand Down
52 changes: 52 additions & 0 deletions lib/falcon/verbose.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

require 'async/logger'

module Falcon
class Verbose
def initialize(app, logger = Async.logger)
@app = app
@logger = logger
end

def log(start_time, env, response, error)
duration = Time.now - start_time

request_method = env['REQUEST_METHOD']
request_path = env['PATH_INFO']

if response
status, headers, body = response
@logger.info "#{request_method} #{request_path} -> #{status}; Content length #{headers.fetch('Content-Length', '-')} bytes; took #{duration} seconds"
else
@logger.info "#{request_method} #{request_path} -> #{error}; took #{duration} seconds"
end
end

def call(env)
start_time = Time.now

response = @app.call(env)
ensure
log(start_time, env, response, $!)
end
end
end

0 comments on commit c53f41c

Please sign in to comment.