The old version of gLogger¶
This is the old version of gLogger. Please, go to gLogger to find the documentation on the current version. You can also see the different changes in the Changes.
Logger creation¶
Get a sublogger¶
gLogger is considered like the root logger. From it, we can create a child logger with the command:
gLogger.getSubLogger("logger")
This child logger can be used like gLogger and from it we can also get a sublogger and so on. We recommend you to not create a sublogger from a sublogger because there is no particular interest. Otherwise, note that the created sublogger is identified by its name and can be used again with the getSubLogger() method. For instance :
logger = gLogger.getSubLogger("logger")
newLogger = gLogger.getSubLogger("logger")
#logger is the same object as newLogger
child attribute in sublogger¶
gLogger and its children are owned by a system by default. It means that the name of the logger is preceded by the system and component name in the display. To prevent this feature, we can notify the program changing a boolean value : child in parameter of the getSubLogger() method like this :
gLogger.getSubLogger("logger", child=False)
This allows us to remove the system and component name. However, this feature seems buggy and should be used carefully. We recommend you to use only with a direct sublogger of gLogger and only if you execute a service, an agent or a script.
Levels¶
Level names and numbers¶
There are 9 different levels in DIRAC :
Level name |
Level number |
---|---|
Always |
40 |
Notice |
30 |
Info |
20 |
Verbose |
10 |
Debug |
0 |
Warn |
-20 |
Error |
-30 |
Exception |
-30 |
Fatal |
-40 |
They are numbered from 40 to -40. We use them according to the context attaching a certain level to a logger or to a message.
Set a level to a logger¶
We can set a certain level to a logger to hide some logs. It is a V system, which means that it functions with absolute values. For instance, if you set the level of gLogger to Always, only always and fatal logs will appear because their absolute values are superiors or equals to 40. To set a level, we use the setLevel() method like this :
logger.setLevel("notice")
Here, we set a notice level to this logger. However, once we have set a level to gLogger, these children will have the same level restriction, even if we try to change its level. In this way, the example logger will not send messages inferior to the absolute value of the gLogger level.
Get a logger level¶
We can obviously get a level associate to a logger via the getLevel() method.
Message¶
Naturally, it exists some functions to send a message. These methods take level names. In this way, we have :
always(msg, varMsg=’’)
notice(msg, varMsg=’’)
info(msg, varMsg=’’)
verbose(msg, varMsg=’’)
debug(msg, varMsg=’’)
warn(msg, varMsg=’’)
error(msg, varMsg=’’)
exception(msg, varMsg=’’, lException=False, lExcInfo=False)
fatal(msg, varMsg=’’)
There are a Msg and varMsg where you can put any string you want in. There is no real difference between the two parameters.
The exception function contains two more parameters. The first has no effect on the message and should stay at False. Otherwise, the second parameter is more interesting because it allows or not the display of the file and the line where the exception occurs in the stack trace. We warn you that this method works only if an exception occurs.
try:
1/0
except Exception:
gLogger.exception("Division by 0", lExcInfo=True)
gLogger.exception("Division by 0")
#will display:
#Division by 0
#== EXCEPTION == ZeroDivisionError
# File "toto.py", line 132, in test_exception
# 1/0
#
#ZeroDivisionError: integer division or modulo by zero
#===============
#
#Division by 0
#== EXCEPTION == ZeroDivisionError
#
#ZeroDivisionError: integer division or modulo by zero
#===============
These methods attach a certain level to the message, and as we seen above, if the absolute value of the gLogger level is superior to the absolute value of the message level, the log is not created.
glogger.setLevel("notice")
glogger.debug("this message will not be displayed")
#the last line will return False
Display¶
Basic display¶
The basic display for log message is:
- ::
[Year]-[Month]-[Day] [Hour]:[Minute]:[Second] UTC /[Component]/[Logname] [Levelname] : [Message]
Example:
2017-04-25 15:51:01 UTC Framework/logMultipleLines ALWAYS: this is a message
The date is UTC formatted and the system and the component names come from the configuration file. This display can vary according to the component, the backend and different option parameters.
Component¶
Client component¶
All messages from a client , wherever located, are displayed like:
[Year]-[Month]-[Day] [Hour]:[Minute]:[Second] UTC Framework/[Logname][Levelname] : [Message]
The component name disappears and the system name becomes Framework. That is because there are no Client component in configuration files and Framework is the default system name.
Script Component¶
All messages from a script are displayed like:
[Message]
That is because the parseCommandLine() method modify one option parameter in gLogger : showHeaders to False. Let is talk more about these options.
Optional Parameter¶
showHeader option¶
showHeader is a boolean variable inside gLogger which allow us to hide or not the prefix of the message from the log. It can be changed via the showHeader(val) method and its default value is obviously True.
showThreads option¶
As the previous option, showThreads is a boolean variable inside gLogger which allow us to hide or not the thread ID in the log. This thread ID is created from the original thread ID of Python and modified by the backend to become a word. It is positioned between the log name and the level name like this:
2017-04-25 15:51:01 UTC Framework/logMultipleLines [PokJl] ALWAYS: this is a message
Its default value is False and we can set it via showThreadIDs(val) method. Nevertheless, if the showHeaders option is False, this option will have no effect on the display.
LogShowLine option¶
This option is only available from the cfg file and allows us to add extra information about the logger call between the logger name and the level of the message, like this:
2017-04-28 14:56:54 UTC TestLogger/SimplestAgent[opt/dirac/DIRAC/FrameworkSystem/private/logging/Logger.py:160] INFO: Result
It is composed by the caller object path and the line in the file. As the previous option, it has no effect on the display if the showHeaders option is False.
LogColor option¶
This option is only available from the cfg file too, and only for PrintBackend. It allows us to add some colors according to the message level in the standard output like this:
2017-04-28 14:56:54 UTC TestLogger/SimplestAgent DEBUG: Result
2017-04-28 14:56:54 UTC TestLogger/SimplestAgent WARN: Result
2017-04-28 14:56:54 UTC TestLogger/SimplestAgent ERROR: Result
child attribute from getSubLogger() method¶
Previously, we saw the basic use of the child attribute from the getSubLogger() method. Actually, this attribute is considerably more complex and can modify the display in several ways but it seems to be illogic and buggy, so be careful using this attribute with a sublogger of a sublogger. Here is a simple example of its use with an agent running:
child = True: 2017-05-04 08:37:10 UTC TestLogger/SimplestAgent/log ALWAYS: LoggingChildTrue
child = False: 2017-05-04 08:37:10 UTC log ALWAYS: LoggingChildFalse
Backends¶
Currently, there are four different backends inherited from a base which build the message according to the options seen above and another called LogShowLine. These four backends just write the message at associated place. There are :
Backend |
Output |
---|---|
PrintBackend |
standard output |
StdErrBackend |
error output |
RemoteBackend |
logserver output |
FileBackend |
file output |
They need some information according to their nature. The PrintBackend needs a color option while the FileBackend needs a file name. In addition, the RemoteBackend needs a sleep time, an interactivity option and a site name. These information are collected from the cfg file.
Configuration¶
Configuration via the cfg file¶
Logger configuration¶
It is possible to configure some options of the logger via the cfg file. These options are :
Option |
Description |
Excpected value(s) |
---|---|---|
LogLevel |
Set a level to gLogger |
All the level names |
LogBackends |
Add backends to gLogger backend list |
stdout, stderr, file, server |
LogShowLine |
Add information about the logger call |
True, False |
LogColor |
Add color on messages, only for PrintBackend |
True, False |
Backend configuration¶
We also have the possibility to configure backend options via this file. To do a such operation, we just have to create a BackendsOptions section inside the component. Inside, we can add these following options:
Option |
Description |
Excpected value(s) |
---|---|---|
FileName |
Set a file name for FileBackend |
String value |
SleepTime |
Set a sleep time for RemoteBackend |
Int value |
Interactivity |
Flush messages or not, for Remote Backend |
True, False |
cfg file example¶
Here is a component section which contains logger and backend configuration:
Agents
{
SimplestAgent
{
LogLevel = INFO
LogBackends = stdout,stderr,file
LogColor = True
LogShowLine = True
PollingTime = 60
Message = still working...
BackendsOptions
{
FileName = /tmp/logtmp.log
}
}
}
Configuration via command line argument¶
Moreover, it is possible to change the display via one program argument which is picked up by gLogger at its initalization. According to the number of d in the argument, the logger active or not different options and set a certain level. Here is a table explaining the working:
Argument |
ShowHeader |
showThread |
Level |
---|---|---|---|
Default(Client/Agent/Services) |
True |
False |
Notice |
Default(Script) |
False |
False |
Notice |
-d |
DefaultValue |
DefaultValue |
Verbose |
-dd |
True |
DefaultValue |
Verbose |
-ddd |
True |
True |
Debug |
Multiple processes and threads¶
Multiple processes¶
DIRAC is composed by many micro services running in multiple processes. gLogger object is naturally different for two distinct processes and can not save the application from process conflicts. Indeed, gLogger is not process-safe, that means that two processes can encounter conflicts if they try to write on a same file at the same time. So, be careful to avoid the case.
Multiple threads¶
gLogger does not contain any safety against thread conflicts too, so be careful to not write on one file at the same time with two distinct threads.