Menu

TEP8

Title: Remove from Taurus objects the direct Logger dependence.
TEP: 8
State: CANDIDATE
Date: 2013-10-30
Drivers: Carlos Falcon Torres cfalcon@cells.es; Tiago Coutinho Macara tiago.coutinho@esrf.fr
URL: https://sourceforge.net/p/sardana/wiki/TEP8
License: http://www.jclark.com/xml/copying.txt
Abstract:
This document describes the process to remove from Taurus objects the direct Logger dependence.

Introduction

Nowadays, the most of Taurus objects inherited from Logger. This inheritance provide to those objects unnecessary functions and attributes that are using for internal Logger business. Moreover the current Logger design does not allow integrate Taurus with others libraries.

The goal of TEP8 is simplify the Taurus objects inheritance, abstracting the Taurus Logger control functions and attributes, and adapt Taurus Logger API to be able to use external logger system.

We propose to transfer of the the control Logger functions and attributes to a new intermediate class, using a Delegation pattern. With it we will move part of the inherited features to an inherited (private) object. Besides we propose separate into two step the Logger system: Initialization and Instantiation, doing this second part optional.

Motivation

The main reason for this change is solve the mixed feature. For the one hand, these changes will simplify the objects, doing their more "light" and easy to understand. For example, a Tango device will reduce the number of attributes and functions visible by a third. For the other hand, removing the direct dependence of Taurus Logger and not assuming the automatically instantiation we could use an external logger, doing Taurus more friendly and compatible with other libraries.

Requirements

Taurus [TEP8] and Sardana SEP8 classes must be backward compatibility. For this reason, the evolution of every change will be prove in a high level, through the cross checking with the current Sardana's applications: Sardana, spock, taurusdesigner, taurusgui, ...

Taurus Logger has to be created in two steps: Taurus Logger initialization and Taurus Logger instantiation. Moreover, to have a Logger system more standard is convenient to use the python logging module as much as possible.

The gross of changes have to be done in log.py file but also the Logger dependencies have to be removed from other files:

src/sardana/macroserver/macro.py
src/sardana/macroserver/macros/examples/hooks.py
src/sardana/macroserver/macros/standard.py
src/sardana/macroserver/msdoor.py
src/sardana/macroserver/scan/recorder/output.py
src/sardana/pool/controller.py
src/sardana/pool/pool.py
src/sardana/pool/poolacquisition.py
src/sardana/pool/poolcontroller.py
src/sardana/spock/ipython_00_11/genutils.py
src/sardana/tango/core/util.py
src/sardana/tango/macroserver/Door.py
src/sardana/tango/macroserver/init.py
taurus/lib/taurus/core/taurusconfiguration.py
taurus/lib/taurus/core/taurushelper.py
taurus/lib/taurus/core/taurusmanager.py
taurus/lib/taurus/core/taurusmodel.py
taurus/lib/taurus/core/util/log.py
taurus/lib/taurus/core/util/threadpool.py
taurus/lib/taurus/qt/qtcore/util/emitter.py
taurus/lib/taurus/qt/qtdesigner/tauruspluginplugin.py
taurus/lib/taurus/qt/qtgui/application/taurusapplication.py
taurus/lib/taurus/qt/qtgui/base/taurusbase.py
taurus/lib/taurus/qt/qtgui/display/taurusvaluelabel.py
taurus/lib/taurus/qt/qtgui/graphic/taurusgraphic.py
taurus/lib/taurus/qt/qtgui/table/qlogtable.py
taurus/lib/taurus/qt/qtgui/taurusgui/taurusgui.py
taurus/lib/taurus/qt/qtgui/tree/taurusdevicetree.py

This is the current Taurus Logger API.

Current Taurus Logger API
Logger.Critical Logger.addLogHandler Logger.error
Logger.getParent Logger.root_inited Logger.exception
Logger.Debug Logger.addRootLogHandler Logger.root_init_lock
Logger.getRootLog Logger.setLogFormat Logger.resetLogLevel
Logger.DftLogFormat Logger.callinit Logger.fatal
Logger.info Logger.setLogLevel Logger.DftLogLevel
Logger.callinitwo_kw Logger.flushOutput Logger.initRoot
Logger.stack Logger.DftLogMessageFormat Logger.changeLogName
Logger.getAttrDict Logger.log Logger.stream_handler
Logger.Error Logger.cleanUp Logger.getChildren
Logger.log_format Logger.syncLog Logger.Fatal
Logger.copyLogHandlers Logger.getLogFormat Logger.log_level
Logger.trace Logger.Info Logger.critical
Logger.getLogFullName Logger.mro Logger.traceback
Logger.Trace Logger.debug Logger.getLogLevel
Logger.removeRootLogHandler Logger.updateAttrDict Logger.Warning
Logger.deprecated Logger.getLogName Logger.resetLogFormat
Logger.warning Logger.addChild Logger.disableLogOutput
Logger.getLogObj Logger.addLevelName Logger.enableLogOutput
Logger.getLogger

Implementation

The main changes have been done in taurus/lib/taurus/core/util/log.py.
If we compare fork version with the current version you can see a new class LoggingHelper where was moved the control functions and attributes of Logger class. This solution is 99.99% backward compatible.

Following the patter design, the rest of changes corresponding to change the code for access to the new class members. Logger was replaced by _LoggerHelper and obj.FUNCTION_OR_ATTRIBUTE by obj._logger.FUNCTION_OR_ATTRIBUTE

The Logger functions flushOutput and syncLog were considered deprecated. Them were used internally and were removed from the code.

The Taurus Logger Trace level was market as deprecated. Right now the Tace level was setting to Debug. The callings of trace function were remplaced by debug.

To uncouple the Taurus Logger initialization and instantiation, The old function initRoot was split in init and initLogger functions.

Following one of the requirement Taurus Logger uses internally logging.getLogger instead of getLogger function to access to logger.

To be backward compatible, the variable ENABLE_TAURUS_LOGGER was added to TaurusCustomSettings. This variable is used in the functions, getrootlogger , and in the init__ of _LoggerHelper class, both defined in taurus.core.util.log. Allowing instantiate the logger class when the variable is equal True or does not defined. In the other case Taurus Logger asume an external logger system.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/usr/bin/python
# Code goes here ...
# Use Taurus Logger API: 
# True (or commented out) enables the initiatialization of Taurus logger.
# False Taurus assumed an external Logger system; If it does not exist, 
#       the Logger API will not work. Showing the following message 
#       the first time that any Logger message (warning, debug, info, etc)
#       was executed.
#
#    i.e.    Logger.warning('asd')
#            No handlers could be found for logger "TaurusRootLogger"

ENABLE_TAURUS_LOGGER = True

This is the new Taurus Logger API after the changes:

New Taurus Logger API
Logger.callinit Logger.debug Logger.exception
Logger.log Logger.traceback Logger.callinitwo_kw
Logger.deprecated Logger.getAttrDict Logger.mro
Logger.updateAttrDict Logger.critical Logger.error
Logger.info Logger.trace Logger.warning

Recommendations

Nowadays Taurus can work with an external Logger, but if we assumed that Taurus will use its own Logger we recommend manage it from Taurus API instead of the Logger API. This last option was removed (hide) in the new API.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#!/usr/bin/python
# Code goes here ...
import taurus
taurus.getLogLevel()
taurus.setLogLevel(LEVEL)
taurus.getLogFormat()
taurus.setLogFormat(FORMAT)
taurus.resetLogLevel()
taurus.resetLogFormat()
taurus.enableLogOutput() 
taurus.disableLogOutput()

How to use the new API

The code below show how Taurus Logger could be used:

1-If ENABLE_TAURUS_LOGGER = True or does not exist (backward compatibility)

1
2
3
4
5
#!/usr/bin/python
# Code goes here ...
import taurus
taurus.warning('asd')
MainThread     WARNING  2014-04-24 17:11:03,511 TaurusRootLogger: asd

2-If ENABLE_TAURUS_LOGGER = True and exists external Logger.

1
2
3
4
5
6
7
8
9
#!/usr/bin/python
# Code goes here ...
import taurus
# External logger
import logging
logging.basicConfig()
taurus.warning('asd')
WARNING:TaurusRootLogger:asd
MainThread     WARNING  2014-04-24 17:15:01,619 TaurusRootLogger: asd

3-If ENABLE_TAURUS_LOGGER = False and does not exist external Logger.

1
2
3
4
5
#!/usr/bin/python
# Code goes here ...
import taurus
taurus.warning('asd')
No handlers could be found for logger "TaurusRootLogger"

4-If ENABLE_TAURUS_LOGGER = False and exists external Logger.

1
2
3
4
5
6
7
#!/usr/bin/python
# Code goes here ...
import taurus
import logging             # External logger module
logging.basicConfig()
taurus.warning('asd')
WARNING:TaurusRootLogger:asd

5-If ENABLE_TAURUS_LOGGER = False and manual initialization:

1
2
3
4
5
6
#!/usr/bin/python
# Code goes here ...
import taurus
taurus.taurus.initLogger()
taurus.warning('asd')
MainThread     WARNING  2014-04-24 17:02:03,881 TaurusRootLogger: asd

License

The following copyright statement and license apply to TEP8 (this
document).

Copyright (c) 2013 Carlos Falcon Torres - Tiago Coutinho Macara

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Changes

2015-05-15 Change SEP by TEP and move to CANDIDATE
2014-04-24 Code review and SEP documentation
2013-10-30
cmft Creation of SEP8


Related

Wiki: TEP8