Disabling @traced
at runtime¶
Release: | 1.3.0 |
---|
New in version 1.1.0.
- Recommended approach: Let Autologging install the @traced no-op automatically
- Install the @traced no-op directly
When a class or a function is decorated with autologging.traced
,
Autologging replaces a method (or function) with a tracing “proxy”
function that intercepts any invocation to perform the CALL/RETURN
tracing. (See How does autologging work? for a more in-depth explanation.)
Autologging is careful to minimize the overhead imposed by these tracing
proxy functions, but there will always be some overhead - even when
the autologging.TRACE
log level is disabled, the tracing proxy
function must still (a) check the log level and then (b) delegate to
the original method/function.
In some cases, it may be desirable to completely eliminate any tracing
overhead. Running the application in a production environment, or
executing a performance test, are the two most obvious examples. For
these cases, Autologging now provides a “killswitch” for the @traced
decorator that effectively turns it into a no-op.
When the autologging.install_traced_noop
function is called
before the traced decorator is imported and any classes or functions
have been decorated, then the @traced
decorator will function as an
“identity” decorator, simply returning the decorated class or function
unmodified. In this way, tracing can be completely “removed” from an
application without having to comment-out the @traced
decorator
(or conditionally apply it).
Warning
Calling autologging.install_traced_noop()
after any class or
function has been decorated will not uninstall the tracing proxy
function. It is imperative that
autologging.install_traced_noop()
be called before
autologging.traced
is imported and before any class or
function is decorated.
The process is irreversible in the running Python interpreter. Once
autologging.install_traced_noop()
has been called, the only way
to reinstate tracing functionality is to restart the interpreter (and
not install the no-op).
Consider a simple application consisting of two modules - a bootstrap module that is responsible for launching the application, and the application module itself:
# bootstrap.py
import app
if __name__ == "__main__":
app.launch()
# app.py
from autologging import traced
@traced
class Application:
def __init__(self):
self._prepare_connections()
# other initialization
def _prepare_connections(self):
# prepare the connections
def run(self):
while True:
# listen for events, then handle them
def handle(self, event):
# handle the event
@traced
def launch():
Application().run()
As written, the “__init__”, “_prepare_connections”, “run”, and “handle”
methods of the application object, and the “launch” function in the
app
module, will be replaced by tracing proxies.
Note
Whether or not any tracing info is emitted to logs can be controlled simply by configuring the logging system appropriately.
Let’s suppose that for this particular application we wish to completely
remove tracing capability when running in a production or performance
testing environment. To accomplish this, we need to call the
autologging.install_traced_noop
function before any class or
function is decorated with @traced
.
Recommended approach: Let Autologging install the @traced
no-op automatically¶
The recommended approach is to instruct Autologging to install the no-op
automatically. This can be accomplished by setting the
AUTOLOGGING_TRACED_NOOP
environment variable to any non-empty value.
For example, we would run the application in a production or performance testing environment like so:
$ export AUTOLOGGING_TRACED_NOOP=1
$ python bootstrap.py
Note
This is the recommended approach because it requires no change to the application or bootstrap source code.
If the conditions under which tracing should be deactivated are more
complex, then direct installation of the @traced
no-op may be
necessary.
Install the @traced
no-op directly¶
If automatic installation of the @traced
no-op is not possible (or
not preferred), then the application bootstrap code can be modified to
install the no-op directly.
The following modification to bootstrap.py accomplishes the goal:
# bootstrap.py
import os
import autologging
# MUST happen before importing app!
if os.getenv("APP_ENV") in ("PRODUCTION", "PERFORMACE_TEST"):
autologging.install_traced_noop()
import app
if __name__ == "__main__":
app.launch()