Użyj Rack:: CommonLogger in Sinatra

Mam mały serwer WWW, który napisałem z Sinatrą. Chcę móc rejestrować Wiadomości do pliku dziennika. Przeczytałem http://www.sinatrarb.com/api/index.html oraz www.sinatrarb.com/intro.html i widzę, że Rack ma coś o nazwie Rack:: CommonLogger, ale nie mogę znaleźć żadnych przykładów, jak można go uzyskać i użyć do logowania wiadomości. Moja aplikacja jest prosta, więc napisałem ją jako najwyższego poziomu DSL, ale mogę przełączyć się na podkategorię z SinatraBase, jeśli to część tego, co jest wymagane.

Author: Lawrence I. Siden, 2010-02-10

5 answers

Rack::CommonLogger nie dostarczy rejestratora do głównej aplikacji, po prostu zarejestruje żądanie, tak jak zrobiłby to Apache.

Sprawdź sam kod: https://github.com/rack/rack/blob/master/lib/rack/common_logger.rb

Wszystkie Rack aplikacje mają metodę wywołania, która jest wywoływana z żądaniem HTTP env, jeśli zaznaczysz metodę wywołania tego middleware, dzieje się tak:

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 w tym przypadku jest to główna aplikacja, middleware jest tylko rejestrowanie czasu żądanie zaczęło się od, a następnie klasuje oprogramowanie pośredniczące, otrzymując potrójne [status, header, body], a następnie wywołuje prywatną metodę dziennika z tymi parametrami, zwracając to samo potrójne, co Twoja aplikacja.

Metoda logger wygląda następująco:

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

Jak widać, metoda log po prostu pobiera pewne informacje z żądania env i loguje się do loggera, który jest określony w wywołaniu konstruktora, jeśli nie ma instancji loggera, to przechodzi do rack.errors logger (it wygląda na to, że domyślnie istnieje jeden)

Sposób użycia (w Twoim config.ru):

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

use Rack::CommonLogger, logger
run YourApp
Jeśli chcesz mieć wspólny logger w całej swojej aplikacji, możesz utworzyć proste oprogramowanie pośrednie loggera:]}
class MyLoggerMiddleware

  def initialize(app, logger)
    @app, @logger = app, logger
  end

  def call(env)
    env['mylogger'] = @logger
    @app.call(env)
  end

end

Aby go użyć, na Twoim config.ru:

logger = Logger.new('log/app.log')
use Rack::CommonLogger, logger
use MyLoggerMiddleware, logger
run MyApp
Mam nadzieję, że to pomoże.
 41
Author: Roman Gonzalez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-02 19:34:22

W Twoim 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
Author: Phrogz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-17 00:02:28

Śledziłem to, co znalazłem na tym blogu Post-fragment poniżej

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

Następnie użyj puts lub print. U mnie zadziałało.

 2
Author: dbrown0708,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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
Author: davidhq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-14 15:10:21

Ponowne otwarcie STDOUT i przekierowanie go do pliku nie jest dobrym pomysłem, jeśli używasz pasażera. Powoduje to w moim przypadku, że pasażer nie uruchamia się. Czytaj https://github.com/phusion/passenger/wiki/Debugging-application-startup-problems#stdout-redirection{[3]za ten problem.

To byłaby właściwa droga zamiast:

logger = ::File.open('log/sinatra.log', 'a+')
Sinatra::Application.use Rack::CommonLogger, logger
 0
Author: Dirk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-25 08:18:50