J'ai un petit serveur web que j'ai écrit avec Sinatra. Je veux pouvoir enregistrer des messages dans un fichier journal. J'ai lu http://www.sinatrarb.com/api/index.html et www.sinatrarb.com/intro.html, et je vois que Rack a quelque chose qui s'appelle Rack :: CommonLogger, mais je ne trouve aucun exemple de la façon dont il peut être consulté et utilisé pour enregistrer les messages. Mon application est simple, alors je l'ai écrite en tant que DSL de niveau supérieur, mais je peux passer à SinatraBase si elle en fait partie.
Rack::CommonLogger
ne fournira pas d'enregistreur à votre application principale, il enregistrera simplement la demande comme le ferait Apache.
Vérifiez le code vous-même: https://github.com/rack/rack/blob/master/lib/rack/common_logger.rb
Toutes les applications Rack
ont la méthode call qui est invoquée avec l'en-tête de requête HTTP. Si vous vérifiez la méthode call de ce middleware, voici ce qui se produit:
def call(env)
began_at = Time.now
status, header, body = @app.call(env)
header = Utils::HeaderHash.new(header)
log(env, status, header, began_at)
[status, header, body]
end
Le @app
dans ce cas est l’application principale, le middleware enregistre simplement l’heure à laquelle la requête a commencé, puis il classe le middleware qui obtient le triple [statut, en-tête, corps], puis invoque une méthode de journal privé avec ces paramètres, en renvoyant le même triple que votre application est retournée en premier lieu.
La méthode logger
va comme ceci:
def log(env, status, header, began_at)
now = Time.now
length = extract_content_length(header)
logger = @logger || env['rack.errors']
logger.write FORMAT % [
env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-",
env["REMOTE_USER"] || "-",
now.strftime("%d/%b/%Y %H:%M:%S"),
env["REQUEST_METHOD"],
env["PATH_INFO"],
env["QUERY_STRING"].empty? ? "" : "?"+env["QUERY_STRING"],
env["HTTP_VERSION"],
status.to_s[0..3],
length,
now - began_at ]
end
Comme vous pouvez le constater, la méthode log
récupère simplement certaines informations de l’env de la demande et se connecte à un consignateur spécifié dans l’appel du constructeur. S'il n’y a pas d’instance de consignation, elle passe au consignateur rack.errors
par défaut)
La façon de l'utiliser (dans votre config.ru
):
logger = Logger.new('log/app.log')
use Rack::CommonLogger, logger
run YourApp
Si vous souhaitez avoir un enregistreur commun dans toute votre application, vous pouvez créer un middleware d'enregistreur simple:
class MyLoggerMiddleware
def initialize(app, logger)
@app, @logger = app, logger
end
def call(env)
env['mylogger'] = @logger
@app.call(env)
end
end
Pour l'utiliser, sur votre config.ru
:
logger = Logger.new('log/app.log')
use Rack::CommonLogger, logger
use MyLoggerMiddleware, logger
run MyApp
J'espère que cela t'aides.
Dans votre config.ru
:
root = ::File.dirname(__FILE__)
logfile = ::File.join(root,'logs','requests.log')
require 'logger'
class ::Logger; alias_method :write, :<<; end
logger = ::Logger.new(logfile,'weekly')
use Rack::CommonLogger, logger
require ::File.join(root,'myapp')
run MySinatraApp.new # Subclassed from Sinatra::Application
J'ai suivi ce que j'ai trouvé sur ce blog post - extrait ci-dessous
require 'rubygems'
require 'sinatra'
disable :run
set :env, :production
set :raise_errors, true
set :views, File.dirname(__FILE__) + '/views'
set :public, File.dirname(__FILE__) + '/public'
set :app_file, __FILE__
log = File.new("log/sinatra.log", "a")
STDOUT.reopen(log)
STDERR.reopen(log)
require 'app'
run Sinatra.application
utilisez ensuite puts
ou print
. Cela a fonctionné pour moi.
class ErrorLogger
def initialize(file)
@file = ::File.new(file, "a+")
@file.sync = true
end
def puts(msg)
@file.puts
@file.write("-- ERROR -- #{Time.now.strftime("%d %b %Y %H:%M:%S %z")}: ")
@file.puts(msg)
end
end
class App < Sinatra::Base
if production?
error_logger = ErrorLogger.new('log/error.log')
before {
env["rack.errors"] = error_logger
}
end
...
end
Réouvrir STDOUT et le rediriger vers un fichier n'est pas une bonne idée si vous utilisez Passenger. Cela provoque dans mon cas que Passager ne démarre pas. Lisez https://github.com/phusion/passenger/wiki/Debugging-application-startup-problems#stdout-redirection pour ce problème.
Ce serait la bonne façon à la place:
logger = ::File.open('log/sinatra.log', 'a+')
Sinatra::Application.use Rack::CommonLogger, logger