Utiliser Rack:: CommonLogger dans Sinatra

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 le Rack a quelque chose qui s'appelle Rack::CommonLogger, mais je ne peux pas trouver des exemples de la façon dont il peut être consulté et utilisé pour l'enregistrement des messages. Mon application est simple donc je l'ai écrit comme un DSL de haut niveau, mais je peux passer à la sous-classification de SinatraBase si cela fait partie de ce qui est requis.

26
demandé sur Lawrence I. Siden 2010-02-10 21:10:57

5 réponses

Rack::CommonLogger ne fournira pas d'enregistreur à votre application principale, il enregistrera simplement la requête comme Apache le ferait.

Vérifier le code par vous-même: https://github.com/rack/rack/blob/master/lib/rack/common_logger.rb

Rack les applis ont la méthode d'appel qui est invoquée avec la requête HTTP env, si vous vérifiez la méthode d'appel de cet middleware c'est ce qui se passe:

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

@app dans ce cas est l'application principale, la middleware enregistre juste l'heure à laquelle la requête a commencé, puis Classe votre middleware en obtenant le triple [status, header, body], et puis invoquez une méthode de log privé avec ces paramètres, en retournant le même triple que votre application a retourné en premier lieu.

logger méthode 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 dire, le log la méthode saisit juste quelques informations de la requête env, et se connecte sur un logger qui est spécifié sur l'appel du constructeur, si il n'y a pas d'instance logger alors elle va à rack.errors logger (il semble qu'il y en a un par défaut)

La manière de l'utiliser (dans votre config.ru):

logger = Logger.new('log/app.log')

use Rack::CommonLogger, logger
run YourApp

si vous voulez avoir un logger commun dans toute votre application, vous pouvez créer un middleware logger 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 vous aidera.

41
répondu Roman Gonzalez 2018-03-02 19:34:22

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
15
répondu Phrogz 2010-11-17 00:02:28

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

puis utilisez puts ou print. Il a travaillé pour moi.

2
répondu dbrown0708 2010-02-10 19:32:01
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
1
répondu davidhq 2014-11-14 15:10:21

rouvrir STDOUT et le rediriger vers un fichier n'est pas une bonne idée si vous utilisez Passenger. Il provoque dans mon cas, le Passager ne démarre pas. Lire https://github.com/phusion/passenger/wiki/Debugging-application-startup-problems#stdout-redirection pour ce numéro.

Ce serait la bonne façon au lieu de:

logger = ::File.open('log/sinatra.log', 'a+')
Sinatra::Application.use Rack::CommonLogger, logger
0
répondu Dirk 2016-05-25 08:18:50