ruby-on-rails - rails - ruby rack web server
Redirigir la salida del registrador para un controlador especĂfico en Rails 4 (3)
Después de hackear el código de Rails por un día, creo que he encontrado una solución de hack-ish para su problema.
Debe editar el método de call
e initialize
método de la siguiente manera:
def initialize(app)
@app = app
@logger = Rails.instance_variable_get(:@logger)
@reports_api_controller_logger = Logger.new(
Rails.root.join(''log'', REPORTS_API_CONTROLLER_LOGFILE),
10, 1000000)
end
def call(env)
if env[''PATH_INFO''] =~ /api//v.*//reports.*/
Rails.instance_variable_set(:@logger, @reports_api_controller_logger)
ActionController::Base.logger = @reports_api_controller_logger
ActiveRecord::Base.logger = @reports_api_controller_logger
ActionView::Base.logger = @reports_api_controller_logger
else
Rails.instance_variable_set(:@logger, @logger)
ActionController::Base.logger = @logger
ActiveRecord::Base.logger = @logger
ActionView::Base.logger = @logger
end
@app.call(env)
end
Esta es realmente una solución pirata y modifica la expresión regular de acuerdo con sus necesidades.
Dime si esto no funciona para ti.
He creado una solución basada en la respuesta en mi pregunta anterior. Redirigir la salida del registrador para un controlador específico en Rails 3 para Rails 3. Sin embargo, ahora funciona bien. Estoy tratando de aplicar la misma solución basada en middleware a un proyecto de Rails 4, pero hay Hay algunas diferencias que impiden que la misma solución funcione.
La solución Rails 3:
module MyApp
class LoggerMiddleware
REPORTS_API_CONTROLLER_PATH = %r|/A/api/v.*/reports.*|
REPORTS_API_CONTROLLER_LOGFILE = "reports_controller.log"
def initialize(app)
@app = app
@logger = Rails::logger
.instance_variable_get(:@logger)
.instance_variable_get(:@log)
@reports_api_controller_logger = Logger.new(
Rails.root.join(''log'', REPORTS_API_CONTROLLER_LOGFILE),
10, 1000000)
end
def call(env)
Rails::logger
.instance_variable_get(:@logger)
.instance_variable_set(:@log,
case env[''PATH_INFO'']
when REPORTS_API_CONTROLLER_PATH then
@reports_api_controller_logger
else
@logger
end
)
@app.call(env)
end
end
end
Rails.application.middleware.insert_before Rails::Rack::Logger, MyApp::LoggerMiddleware
en lo anterior:
Captador de Rails 3 para Rails.logger = Rails::logger.instance_variable_get(:@logger).instance_variable_get(:@log)
El instalador de Rails 3 para Rails.logger (configurando a @my_logger) = Rails::logger.instance_variable_get(:@logger).instance_variable_set(:@log,@my_logger)
Una cosa que he notado de inmediato es que en Rails 4 el Rails::logger.instance_variable_get(:@logger).instance_variable_get(:@log)
devuelve nil.
Comprobando en la consola de Rails 4, veo que Rails.instance_variable_get(:@logger)
devuelve #<ActiveSupport::Logger:0x007f84ff503a08 ....>
He intentado reemplazar el getter con Rails.instance_variable_get(:@logger)
y el setter con Rails.instance_variable_set(:@logger,my_logger)
y casi parece funcionar. La primera parte de la actividad, "Comenzado ..." va al nuevo archivo de registro, pero todo lo que va después va al archivo de registro predeterminado (el Rails.logger antes de que el middleware lo cambiara).
Cualquiera de Rails.instance_variable_get(:@logger)
no es el nivel más bajo equivalente en Rails 4 a Rails 3 Rails::logger.instance_variable_get(:@logger).instance_variable_get(:@log)
para obtener / configurar Rails.logger o allí es algo más adelante en el proceso después de mi middleware que está sobrescribiendo esto después de configurarlo.
¿Alguna pista?
Actualizar:
Para aclarar, la solución publicada anteriormente funciona como se espera en Rails 3. Cualquier limitación que pueda tener o no en entornos especiales (por ejemplo, si la solución puede no funcionar en entornos de servidor de subprocesos si ese es el caso) está bien en este punto y no se experimentan como obstáculos en este momento, por lo tanto, estas mismas limitaciones también están bien en una solución de Rails 4 para esta pregunta.
El enfoque de utilizar una clase de registro diferente para 1 controlador tiene el inconveniente de que no funcionará en un servidor de subprocesos que está de moda en estos días, no solo con JRuby, sino también con MRI gracias a Heroku
La única idea que tengo hasta ahora después de una semana de reflexión es canalizar los registros a syslog y usar las instalaciones de syslog para dividirlos en archivos separados.
Seguiría siendo necesario parchear el Logger
para que incluya cadenas que permitan la división (como agregar una línea con formato desde la traza de #caller
a los archivos de registro).
El plan B sería introducir mi propio registrador y simplemente registrar lo que necesito en ese controlador. Podría fácilmente volcar parámetros y respuestas, por ejemplo, si eso es suficiente
No estoy seguro de si necesita enfocar la solución de la misma manera que lo hizo en Rails 3. Parece que puede haber otras formas de lograr su objetivo final. ¿Has considerado alguno de estos enfoques o gemas?
https://github.com/TwP/logging
¿Cómo registrar algo en Rails en un archivo de registro independiente?
A veces, intentar algo completamente diferente de lo que ya ha hecho puede ser útil en mi humilde opinión
Esto es un poco de conjetura, pero esta puede ser la razón por la que sus preparadores de obtención no funcionan como se esperaba: https://github.com/rails/rails/commit/6329d9fa8b2f86a178151be264cccdb805bfaaac
Con respecto a la solución de Jagjot y la necesidad de establecer un registro base para cada una de las Clases de Acción de MVC, Rails 4 establece estos por separado de forma predeterminada, lo que en definitiva ofrecerá más flexibilidad de forma inmediata. http://guides.rubyonrails.org/configuring.html#initializers