ruby grape example
Utilice Rack:: CommonLogger en Sinatra (5)
Tengo un pequeño servidor web que escribí con Sinatra. Quiero poder registrar mensajes en un archivo de registro. He leído http://www.sinatrarb.com/api/index.html y www.sinatrarb.com/intro.html, y veo que Rack tiene algo llamado Rack :: CommonLogger, pero no puedo encontrar cualquier ejemplo de cómo se puede acceder y usar para registrar mensajes. Mi aplicación es simple, así que la escribí como una DSL de nivel superior, pero puedo pasar a una subclasificación de SinatraBase si eso es parte de lo que se requiere.
En tu 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
Seguí lo que encontré en esta blog - fragmento a continuación
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
luego usa puts
o print
. Funcionó para mí
Volver a abrir STDOUT y redirigirlo a un archivo no es una buena idea si usa Passenger. Causa en mi caso que el Pasajero no comienza. Lea https://github.com/phusion/passenger/wiki/Debugging-application-startup-problems#stdout-redirection para este problema.
Esta sería la manera correcta en su lugar:
logger = ::File.open(''log/sinatra.log'', ''a+'')
Sinatra::Application.use Rack::CommonLogger, logger
Rack::CommonLogger
no proporcionará un registrador a su aplicación principal, solo registrará la solicitud como haría Apache.
Verifique el código usted mismo: https://github.com/rack/rack/blob/master/lib/rack/common_logger.rb
Todas las aplicaciones de Rack
tienen el método de llamada invocado get con HTTP Request env, si comprueba el método de llamada de este middleware, esto es lo que sucede:
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
El @app
en este caso es la aplicación principal, el middleware solo está registrando el momento en que comenzó la solicitud, luego clasifica su middleware obteniendo el triple [estado, encabezado, cuerpo] y luego invoca un método de registro privado con esos parámetros, devolver el mismo triple que su aplicación devuelta en primer lugar.
El método de logger
es como:
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
Como puede ver, el método de log
simplemente toma algo de la información del env de la solicitud, y se registra en un registrador que se especifica en la llamada del constructor, si no hay una instancia del registrador, entonces va al registrador rack.errors
(parece que hay es uno por defecto)
La forma de usarlo (en tu config.ru
):
logger = Logger.new(''log/app.log'')
use Rack::CommonLogger, logger
run YourApp
Si desea tener un registrador común en toda su aplicación, puede crear un middleware de registrador simple:
class MyLoggerMiddleware
def initialize(app, logger)
@app, @logger = app, logger
end
def call(env)
env[''mylogger''] = @logger
@app.call(env)
end
end
Para usarlo, en tu config.ru
:
logger = Logger.new(''log/app.log'')
use Rack::CommonLogger, logger
use MyLoggerMiddleware, logger
run MyApp
Espero que esto ayude.
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