Capturing logger output inside a method
I've done this in several different ways, and the most convenient I've found is to build a delegation object that routes messages to two or more loggers:
require 'stringio'
require 'logger'
class LoggerTee
def initialize *loggers
@loggers = loggers
end
def method_missing meth, *args, &block
@loggers.each { |logger| logger.send(meth, *args, &block) }
end
end
capture_stringio = StringIO.new
console_log = Logger.new(STDOUT)
string_log = Logger.new(capture_stringio)
log = LoggerTee.new(console_log, string_log)
log.debug 'Hello world'
puts capture_stringio.string
Output:
D, [2013-04-30T18:59:18.026285 #14533] DEBUG -- : Hello world
D, [2013-04-30T18:59:18.026344 #14533] DEBUG -- : Hello world
In this example, the LoggerTee class is instantiated with two separate loggers, one that goes to the console, the other to a StringIO instance. The resulting LoggerTee instance is a drop-in replacement for any standard logger object.
How to overrider Logger class with method to select log level and output line of the log
If you would like to stick with your helper function approach, the logging methods accept kwarg stacklevel
that specifies the corresponding number of stack frames to skip when computing the line number and function name ref. The default is 1, so setting it to 2 should look to the frame above you helper function. For example:
import logging
logging.basicConfig(format="%(lineno)d")
logger = logging.getLogger(__name__)
def log():
logger.error("message", stacklevel=2)
log()
Capture logging output using subprocess.check_output in Python
I'm guessing is that logging does not write on the same stdout that subprocess.check_output is expecting?
logging
doesn't write to stdout at all (by default); it writes to stderr.
You will need to either redirect your stderr to stdout by adding the stderr
argument thus: subprocess.check_output(..., stderr=subprocess.STDOUT)
or you will need to use one of the other subprocess functions such as run
that gives access to stderr.
The docs do say:
The recommended approach to invoking subprocesses is to use the run() function for all use cases it can handle
Capture output from non-python third-party library with python logger
You can temporarily redirect stdout from your 3rd party function go to a logger.
Using the StreamToLogger class from the answer you linked: Redirect Python 'print' output to Logger
def wrap_third_party_function():
stdout = sys.stdout # save for restoring afterwards
# redirect stdout to use a logger, with INFO level
sys.stdout = StreamToLogger(logging.getLogger("mylogger.thirdparty"), logging.INFO)
print("start third_party_function; stdout to log")
third_party_function()
sys.stdout = stdout # restore stdout
print("done third_party_function; stdout restored")
def my_helper():
logger.debug("Inside of 'my_helper', before third party call.")
wrap_third_party_function()
logger.warning("Finished with third party call.")
On the console, you'll get this:
done third_party_function; stdout restored
Finished with third party call.
And progress.out will have:
Inside of 'my_helper', before third party call.
start third_party_function; stdout to log
Inside of 'third_party_function'.
Finished with third party call.
Adding a formatter makes it easier to see:
formatter = logging.Formatter("%(name)s %(levelname)-8s %(message)s")
stream_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)
With this configuration, progress.out shows:
mylogger DEBUG Inside of 'my_helper', before third party call.
mylogger.thirdparty INFO start third_party_function; stdout to log
mylogger.thirdparty INFO Inside of 'third_party_function'.
mylogger WARNING Finished with third party call.
Redirect Python 'print' output to Logger
You have two options:
Open a logfile and replace sys.stdout with it, not a function:
log = open("myprog.log", "a")
sys.stdout = log
>>> print("Hello")
>>> # nothing is printed because it goes to the log file instead.Replace print with your log function:
# If you're using python 2.x, uncomment the next line
#from __future__ import print_function
print = log.info
>>> print("Hello!")
>>> # nothing is printed because log.info is called instead of print
Related Topics
Ruby Method, Proc, and Block Confusion
Best Way to Use HTML5 Data Attributes with Rails Content_Tag Helper
Undefined Method 'Devise' When Including User Model Outside Rails
Gem Install Rails Does Not Install Rails
Rails Elasticsearch Aggregation
Count Records Created Within the Last 7 Days
How to Read an Ini File in Ruby
Preventing Delayed_Job Background Jobs from Consuming Too Much CPU on a Single Server
Rails 5, "Nil Is Not a Valid Asset Source"
Rvm Determine and Install Latest Version of Ruby
An Error Occurred While Installing Curb (0.8.5)
How to Get The Pty.Spawn Child Exit Code
Validate That a Value Is in a Certain Range, E.G. 1 <= Val <=2
Run Selenium with Chrome Driver on Heroku: 'Cannot Find Chrome Binary'
Rake: Logging Any Task Executing