3

$stdoutRubyのスレッド環境での出力をどのようにキャプチャするのだろうか。

いくつかの詳細。ロギング目的でキャプチャを使用sidekiqし、バックグラウンドでジョブを処理してスレッドを処理する必要があります。私はコーディングしました:

@previous_stdout, $stdout = $stdout, StringIO.new
self.stdout = $stdout.string

それは私をスローします(特定のスレッドの場合):

WARN: undefined method `string' for #<IO:<STDOUT>>
4

1 に答える 1

4

自分でログを記録している場合は、ジョブごとに StringIO ログを保持し、それに書き込みます。

@log = StringIO.new
@log.write 'debug message'

Sidekiq には、ロギング オプションも用意されています。

https://github.com/mperham/sidekiq/wiki/Logging

それ以外の場合は、カーネルの印刷メソッドを上書きして同期するなど、本当にハックなことを試して、誤って間違った $stdout に書き込むことがないようにすることができます。何かのようなもの:

require 'stringio'

module Kernel
  @@io_semaphore = Mutex.new

  [ :printf, :p, :print, :puts ].each do |io_write|
    hidden_io_write = "__#{io_write}__"

    alias_method hidden_io_write, io_write

    define_method(io_write) do |*args|
      @@io_semaphore.synchronize do
        $stdout = Thread.current[:log] || STDOUT
        self.__send__(hidden_io_write, *args)
        $stdout = STDOUT
      end
    end
  end
end

threads = 3.times.map do
  Thread.new do
    Thread.current[:log] = log = StringIO.new
    sleep(rand)
    puts "testing..."
    log.string
  end
end

logs = threads.map(&:value)
p logs
# => ["testing...\n", "testing...\n", "testing...\n"]
于 2013-04-24T05:52:03.383 に答える