coloca vs logger em tarefas rails rake

108

Em uma tarefa rake, se eu usar o comando puts, então vejo a saída no console. No entanto, não verei essa mensagem no arquivo de log quando o aplicativo for implantado na produção.

No entanto, se digo Rails.logger.info, no modo de desenvolvimento, não vejo nada no console. Eu preciso ir para o arquivo de log e rastreá-lo.

Eu gostaria de usar Rails.logger.info e no modo de desenvolvimento dentro da tarefa rake, a saída do logger também deve ser enviada ao console.

Existe uma maneira de conseguir isso?

Nick Vanderbilt
fonte

Respostas:

57

Coloque isso application.rbou em um código de inicialização de tarefa de rake

if defined?(Rails) && (Rails.env == 'development')
  Rails.logger = Logger.new(STDOUT)
end

Este é o código do Rails 3. Observe que isso substituirá o registro em development.log. Se você quiser os dois STDOUTe development.logprecisará de uma função de wrapper.

Se você gostaria desse comportamento apenas no console Rails, coloque o mesmo bloco de código em seu ~/.irbrc.

shmichael
fonte
26
Não seria mais fácil apenas colocar Rails.logger = Logger.new(STDOUT)em development.rb?
ghempton
Para o rails 2, coloque isso em seu development.rb:config.logger = Logger.new(STDOUT)
jsarma
38

Você pode criar uma nova tarefa de rake para fazer isso funcionar.

desc "switch logger to stdout"
task :to_stdout => [:environment] do
 Rails.logger = Logger.new(STDOUT)
end

Desta forma, quando você executa sua tarefa rake você pode adicionar to_stdout primeiro para obter as mensagens de log do stdout ou não incluí-lo para que as mensagens sejam enviadas para o arquivo de log padrão

rake to_stdout some_task
Pete Brumm
fonte
11

As tarefas Rake são executadas por um usuário, em uma linha de comando. Tudo o que eles precisam saber imediatamente ("5 linhas processadas") deve ser enviado ao terminal com puts.

Qualquer coisa que precise ser mantida para a posteridade ("enviado email de aviso para [email protected]") deve ser enviada para Rails.logger.

Jonathan Julian
fonte
17
Não é incomum executar tarefas rake com o cron.
Johannes Gorset,
2
Verdade. Se quiser que as mensagens de log sejam enviadas por e-mail quando o cron job for concluído, envie-as para $ stdout ou $ stderr.
Jonathan Julian
10

Eu diria que usar Rails.logger.infoé o caminho a percorrer.

Você não poderá vê-lo no console do servidor porque ele não será executado por meio do servidor. Basta abrir um novo console e tail -fo arquivo de log para resolver o problema.

Muitos usuários estão cientes do comando UNIX® 'tail', que pode ser usado para exibir as últimas linhas de um arquivo grande. Isso pode ser útil para visualizar arquivos de log, etc.

Ainda mais útil em algumas situações, é o parâmetro '-f' para o comando 'tail'. Isso faz com que o tail 'siga' a saída do arquivo. Inicialmente, a resposta será a mesma para 'cauda' sozinha - as últimas linhas do arquivo serão exibidas. No entanto, o comando não retorna ao prompt e, em vez disso, continua a 'seguir' o arquivo. Quando linhas adicionais são adicionadas ao arquivo, elas serão exibidas no terminal. Isso é muito útil para monitorar arquivos de log ou qualquer outro arquivo que possa ser anexado ao longo do tempo. Digite 'cauda do homem' para obter mais detalhes sobre esta e outras opções de cauda.

( via )

marcgg
fonte
Mas não é muito confortável trabalhar na máquina local, pois você não vê a saída na mesma janela em que chamou a tarefa. Especialmente se você não tiver uma tela grande para acomodar várias janelas lado a lado.
Tomas Markauskas
10
Ainda melhor é usar tailf"É semelhante a tail -f, mas não acessa o arquivo quando ele não está crescendo" (da página de manual). É mais curto também
MBO
@tomas por que não minimizar o console de log do servidor e ter apenas um console com o tail-f em execução? De qualquer forma, não é um problema real ... Estou executando cerca de 8 consoles rastreando o que está acontecendo no meu aplicativo, apenas alterne entre as guias quando estiver trabalhando em uma parte específica do sistema, sem problemas imho
marcgg
@mbo nice :) halas, parece que não está disponível na minha máquina (mac os @ leopard)
marcgg
1
@marcgg: Eu não tenho um "console de servidor" (eu uso o passageiro), mas a questão é sobre tarefas de rake e se você executar uma tarefa de uma janela de terminal, você não verá nada do logger nessa janela. Você precisa ter outra janela com o development.log para ver a saída. Idealmente, eu adicionaria de alguma forma stdout como outro fluxo de saída para Rails.logger, mas não removeria o original.
Tomas Markauskas
9

Código

Para Rails 4 e mais recentes, você pode usar a transmissão do Logger .

Se você deseja obter STDOUT e registro de arquivos para tarefas rake no modo de desenvolvimento, pode adicionar este código em config/environments/development.rb:

  if File.basename($0) == 'rake'
    # http://stackoverflow.com/questions/2246141/puts-vs-logger-in-rails-rake-tasks
    log_file     = Rails.root.join("log", "#{Rails.env}.log")
    Rails.logger = ActiveSupport::Logger.new(log_file)
    Rails.logger.extend(ActiveSupport::Logger.broadcast(ActiveSupport::Logger.new(STDOUT)))
  end

Teste

Aqui está uma pequena tarefa Rake para testar o código acima:

# lib/tasks/stdout_and_log.rake
namespace :stdout_and_log do
  desc "Test if Rails.logger outputs to STDOUT and log file"
  task :test => :environment do
    puts "HELLO FROM PUTS"
    Rails.logger.info "HELLO FROM LOGGER"
  end
end

Executando rake stdout_and_log:testsaídas

HELLO FROM PUTS
HELLO FROM LOGGER

enquanto

HELLO FROM LOGGER

foi adicionado a log/development.log.

Executando rake stdout_and_log:test RAILS_ENV=productionsaídas

HELLO FROM PUTS

enquanto

HELLO FROM LOGGER

foi adicionado a log/production.log.

Eric Duminil
fonte
No Rails 5, o basename($0) == 'rake'truque não funciona mais, porque o railspróprio comando é executado rake. Eu adoraria encontrar um bom substituto para ele, além de depender de uma tarefa que configure o broadcast. (Essa parte, pelo menos, ainda funciona bem.)
Brent Royal-Gordon
@ BrentRoyal-Gordon Não há necessidade desta condicional no desenvolvimento, você pode apenas adicionar o código Rakefilena raiz do seu projeto
Mauricio Pasquier Juan
4

Que tal criar um auxiliar de aplicativo que detecta qual ambiente está sendo executado e faz a coisa certa?

def output_debug(info)
   if RAILS_ENV == "development"
      puts info
   else
      logger.info info
   end
end

Em seguida, chame output_debug em vez de puts ou logger.info

naven87
fonte
5
Não acho que seja uma boa ideia. O Rails logger deve ser configurável, mas ao invés de usar essa configurabilidade, você está apenas empilhando mais camadas sobre ele aqui.
Sijmen Mulder
Sim, não é uma boa ideia, pois a mesma verificação será feita sempre que você quiser registrar algo.
furiabhavesh
3

No Rails 2.X para redirecionar o logger para STDOUT nos modelos:

ActiveRecord::Base.logger = Logger.new(STDOUT)

Para redirecionar o logger nos controladores:

ActionController::Base.logger = Logger.new(STDOUT)
Tania R
fonte
Também achei este artigo muito útil sepcot.com/blog/2009/08/rails-logging-to-stdout
Tania R
2

Execute um trabalho em segundo plano com '&' e abra o script / console ou qualquer outra coisa. Dessa forma, você pode executar vários comandos na mesma janela.

tail -f log/development.log &
script/console
Loading development environment (Rails 2.3.5)
>> Product.all
2011-03-10 11:56:00 18062 DEBUG  Product Load (6.0ms)  SELECT * FROM "products"
[<Product.1>,<Product.2>]

note Pode ficar desleixado rapidamente quando há muita saída de registro.

Tom Maeckelberghe
fonte