Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Changes between Version 10 and Version 11 of TutLogging

Show
Ignore:
Author:
kris (IP: 17.228.23.90)
Timestamp:
05/09/09 02:19:51 (15 years ago)
Comment:

updated to recent changes

Legend:

Unmodified
Added
Removed
Modified
  • TutLogging

    v10 v11  
    2525import tango.util.log.Log; 
    2626 
    27 Logger mymoduleLogger = Log.getLogger("mypackage.mymodule"); 
     27auto mymoduleLogger = Log.lookup("mypackage.mymodule"); 
    2828}}} 
    2929 
    30 There are a few items of note in the above example. First, the tango.util.log.Log module publicly imports tango.util.log.Logger, so it need not be imported separately. Second, Logger instances are never instantiated directly. When Log.getLogger is called, it attempts to find the Logger instance associated with the given name. If no Logger is found, it creates and returns a new instance. Finally, the name of the new Logger is "mypackage.mymodule". In terms of the hierarchy, if another Logger named "mypackage" has been configured, the new Logger will inherit its properties. 
     30There are a few items of note in the above example. First, the tango.util.log.Log module publicly imports tango.util.log.Logger, so it need not be imported separately. Second, Logger instances are never instantiated directly. When Log.lookup is called, it attempts to find the Logger instance associated with the given name. If no Logger is found, it creates and returns a new instance. Finally, the name of the new Logger is "mypackage.mymodule". In terms of the hierarchy, if another Logger named "mypackage" has been configured, the new Logger will inherit its properties. 
    3131 
    3232When new Loggers are created and no Logger has been created above them in the hierarchy, they are attached to a special Logger called "root". The root Logger is the parent of every Logger in the hierarchy. In the above example, if no Logger named "mypackage" had yet been created, then the "mypackage.mymodule" Logger would have inherited the properties of the root Logger. 
    3333 
    34 The root Logger can be accessed directly in the special Log.getRootLogger method: 
     34The root Logger can be accessed directly in the special Log.root method: 
    3535 
    3636{{{ 
    3838import tango.util.log.Log; 
    3939 
    40 Logger root = Log.getRootLogger()
     40auto root = Log.root
    4141}}} 
    4242 
    6262The intent behind each level, with the exclusion of None, is a guideline for tango.util.log users. What each level means in practice is entirely up to the programmer, though it is a good idea to follow the general guidelines above for consistency. 
    6363 
    64 To set the level of a Logger, the Logger.setLevel method is used. To determine the level of a Logger, either Logger.getLevel or Logger.isEnabled can be used. Passing any level value to a Logger means that logging will be enabled for all messages matching that level's rank and lower. So enabling the Trace level means that all levels are enabled, while enabling the Error level means only the Error and Fatal levels are enabled. 
     64To set the level of a Logger, the Logger.level method is used. To determine the level of a Logger, either Logger.level or Logger.enabled can be used. Passing any level value to a Logger means that logging will be enabled for all messages matching that level's rank and lower. So enabling the Trace level means that all levels are enabled, while enabling the Error level means only the Error and Fatal levels are enabled. 
    6565 
    6666The level of a message can be specified in two ways, either via the Logger.append method, or by using one of the shorthand methods named for each level. The following code illustrates how to manipulate logging levels. 
    7474void testLogger() 
    7575{ 
    76         Logger logger = Log.getLogger("mylogger"); 
     76        auto logger = Log.lookup("mylogger"); 
    7777 
    7878        // Enable Info, Warn, Error, and Fatal levels 
    79         logger.setLevel(Logger.Level.Info);  
     79        logger.level = logger.Info;  
    8080         
    81         logger.append(Logger.Level.Info, "This is an info message."); 
     81        logger.append(logger.Info, "This is an info message."); 
    8282        logger.info("This is an info message, too."); 
    8383         
    8484        logger.trace("This is a trace message and won't be printed."); 
    85         logger.append(Logger.Level.Trace, "This is a trace message, too, and also won't be printed."); 
     85        logger.append(logger.Trace, "This is a trace message, too, and also won't be printed."); 
    8686         
    87         logger.setLevel(Logger.Level.Error); // enable logging only for Error and Fatal levels 
     87        logger.level = logger.Error; // enable logging only for Error and Fatal levels 
    8888         
    8989        logger.trace("This message won't be printed."); 
    9494         
    9595        // This turns logging off completely for logger 
    96         logger.setLevel(Logger.Level.None);    
     96        logger.level = logger.None;    
    9797} 
    9898}}} 
    102102Every Logger needs to know where to send its output. In tango.util.log, Appenders handle the task of sending the output to its final destination. No Appenders are configured by default. If the above example were to be used as-is in an actual program, it wouldn't print any output since no Appender is configured. tango.util.log includes a handful of useful Appenders that are ready for use. 
    103103 
    104 '''!ConsoleAppender''' - prints output to the system console. 
     104'''!AppendConsole''' - prints output to the system console. 
    105105 
    106 '''!FileAppender''' - prints output to a file. 
     106'''!AppendFile''' - prints output to a file. 
    107107 
    108 '''!RollingFileAppender''' - prints output to one of a group of files, moving on to the next file in the group when the current one reaches a maximum size. 
     108'''!AppendFiles''' - prints output to one of a group of files, moving on to the next file in the group when the current one reaches a maximum size. 
    109109 
    110 '''!SocketAppender''' - prints output to a network socket. 
     110'''!AppendSocket''' - prints output to a network socket. 
    111111 
    112 '''!MailAppender''' - sends output to an email server. 
     112'''!AppendMail''' - sends output to an email server. 
    113113 
    114 '''!NullAppender''' - sends output nowhere. Useful as a placeholder or for benchmarking. 
     114'''!AppendNull''' - sends output nowhere. Useful as a placeholder or for benchmarking. 
    115115 
    116 !ConsoleAppender is the only Appender we will consider, as the others rely on packages other than tango.util.log and are beyond the scope of this basic tutorial. 
     116!AppendConsole is the only Appender we will consider, as the others rely on packages other than tango.util.log and are beyond the scope of this basic tutorial. 
    117117 
    118 To assign an Appender to a Logger, the Logger.addAppender method should be used. As the name suggests, this method does not replace any existing Appenders already assigned to the Logger, meaning multiple Appenders can be assigned to one Logger. By default, the Logger will output to all Appenders assigned to it. It will also pass output to the Logger above it in hierarchy. This latter behavior can be changed by a call to Logger.setAdditive. Calling Logger.isAdditive will give the current state, returning false if the Logger is configured to not pass output up the hierarchy. 
     118To assign an Appender to a Logger, the Logger.add method should be used. As the name suggests, this method does not replace any existing Appenders already assigned to the Logger, meaning multiple Appenders can be assigned to one Logger. By default, the Logger will output to all Appenders assigned to it. It will also pass output to the Logger above it in hierarchy. This latter behavior can be changed by a call to Logger.additive. Calling Logger.additive will give the current state, returning false if the Logger is configured to not pass output up the hierarchy. 
    119119 
    120120The following example demonstrates how to configure an Appender and print text using a Logger. It is a working program that can be compiled and executed. 
    125125 
    126126import tango.util.log.Log; 
    127 import tango.util.log.ConsoleAppender
     127import tango.util.log.AppendConsole
    128128 
    129129void main() 
    130130{ 
    131         Logger logger = Log.getLogger("mylogger"); 
    132         logger.addAppender(new ConsoleAppender()); 
     131        auto logger = Log.lookup("mylogger"); 
     132        logger.add(new AppendConsole); 
    133133        logger.info("Hello Tango.Log!");         
    134134} 
    142142{{{ 
    143143#!d 
    144 if(logger.isEnabled(Logger.Level.Trace)
     144if(logger.trace
    145145{ 
    146146        char[] output = doExpensiveOutputConstruction(); 
    148148} 
    149149}}} 
    150 ==== The Configurator ==== 
     150==== The Config ==== 
    151151 
    152 tango.util.log includes a special class that will automatically configure the root Logger to append to the system console. Doing so means that every Logger object created will have the ability to log to the system console by default. The class is called Configurator and can be found in tango.util.log.Configurator
     152tango.util.log includes a special nodule that will automatically configure the root Logger to append to the system console. Doing so means that every Logger object created will have the ability to log to the system console by default. Just import it to make it operate
    153153 
    154154{{{ 
    155155#!d 
    156156import tango.util.log.Log; 
    157 import tango.util.log.Configurator
     157import tango.util.log.Config
    158158 
    159159void main() 
    160160{ 
    161         // configure the root Logger for console output 
    162         Configurator.configure(); 
    163          
    164161        // test it 
    165         Log.getRootLogger().info("Hello Root Logger!");    
    166 
    167 }}} 
    168  
    169 Additionally, Configurator takes advantage of D's opCall override and allows the call to Configurator.configure to be condensed: 
    170  
    171 {{{ 
    172 #!d 
    173 import tango.util.log.Log; 
    174 import tango.util.log.Configurator; 
    175  
    176 void main() 
    177 
    178         // configure the root Logger for console output 
    179         Configurator(); 
    180          
    181         // test it 
    182         Log.getRootLogger().info("Hello Root Logger!");    
     162        Log.root.info("Hello Root Logger!");    
    183163} 
    184164}}} 
    186166==== Layouts ==== 
    187167 
    188 Anyone running the logtest example from the Appenders section of this tutorial and comparing its output to that of the Configurator examples just above will notice that the output is different -- the latter examples have output a number just before the Logger name. That is because the Configurator uses an advanced feature of the tango.util.log called Layouts. In tango.util.log, the final format of the output text is configured independently of the Appenders. Configurator uses a special Layout called !SimpleTimeLayout. This and two other Layout implementations, !SpartanLayout and !SimpleLayout, can be found in tango.util.log.Layout. Additionally, tango.util.log.!DateLayout and tango.util.log.!XmlLayout define two layouts that are more complex. 
     168Anyone running the logtest example from the Appenders section of this tutorial and comparing its output to that of the Config examples just above will notice that the output is different -- the latter examples have output a number just before the Logger name. That is because the Config uses an advanced feature of the tango.util.log called Layouts. In tango.util.log, the final format of the output text is configured independently of the Appenders. Config uses a special Layout called !LayoutTimer, which can be found in tango.util.log.Log. Additionally, tango.util.log.!LayoutDate and tango.util.log.!LayoutChainsaw define two layouts that are more complex. 
    189169 
    190170Layouts are a powerful feature and are mentioned here for completeness, though the details are beyond the scope of this basic tutorial.