public static void ReleaseLogging()
    {
        // create a lox for release logging
        Lox lox= new Lox( "ReleaseLox" );

        // let the system choose an appropriate console logger
        TextLogger releaseLogger=  Lox.CreateConsoleLogger();

        // In debug compilations, we still install a report writer.
        Log.AddALibReportWriter( lox );
        #if ALOX_DBG_LOG
            lox.SetVerbosity( releaseLogger, Verbosity.Verbose, ALoxReportWriter.LogDomain() );
        #endif

        // we set a format string without scope information (as this is of-course not available in release logging)
        #if ALOX_DBG_LOG || ALOX_REL_LOG
            releaseLogger.MetaInfo.Format= new AString( "[%TC +%TL][%tN]%V[%D]%A1(%#): " );
        #endif
        lox.SetVerbosity( releaseLogger, Verbosity.Info, "A_DOMAIN" );

        lox.Info ( "A_DOMAIN", "Hello ALox, this is release logging" );

        // cleanup
        Log.RemoveALibReportWriter();
        lox.RemoveLogger( releaseLogger );
    }
    public static void PerformanceTestRL()
    {
        // create a lox for release logging
        Lox lox= new Lox( "ReleaseLox" );
        TextLogger   relLogger= Lox.CreateConsoleLogger();
        MemoryLogger ml       = new MemoryLogger();


        lox.SetVerbosity( relLogger, Verbosity.Verbose, "/CON" );
        lox.SetVerbosity( ml       , Verbosity.Verbose, "/MEM" );


        lox.Info( "/CON", "Logging simple info lines into a memory logger" );

        AString  msgBuf=  new AString( );
        long     fastest= long.MaxValue;
        Ticks    timer=     new Ticks();
        int      qtyLines=   100;
        int      qtyLoops=  1000;
        if( System.Diagnostics.Debugger.IsAttached )
            qtyLines= qtyLoops= 10;

        for ( int i= 0 ; i < qtyLoops ; i++ )
        {
            #if ALOX_DBG_LOG || ALOX_REL_LOG
                ml.MemoryLog.Clear();
            #endif

            timer.Set();
                for ( int ii= 0 ; ii < qtyLines ; ii++ )
                {
                    lox.Info( "/MEM", "Test Line" );
                    if( i== 0 && ii == 0) Console.WriteLine( ml.MemoryLog.ToString() );
                }
            long t= timer.Age().Raw();

            if ( fastest > t )
            {
                fastest= t;
                lox.Info( "/CON", msgBuf.Clear()._( "Pass " )._( i, 3)._( " is new fastest:  ")
                                       ._( (int) (new Ticks( fastest)).InMicros(), 0)
                                       ._( " micros per ")._(qtyLines)._(" logs.") );
            }
        }

        double microsPerLog=  ( (double) (new Ticks(fastest)).InMicros() ) / qtyLines;
        int    logsPerSecond= (int)( 1000000.0 / microsPerLog);
        lox.Info( "/CON", msgBuf._()._( "  " )._( ESC.MAGENTA )._( "Fastest Release Logging: " )
                                    ._( microsPerLog  )._( " micros per log (resp " )
                                    ._( logsPerSecond )._( " logs per second) " ) );

        lox.RemoveLogger( ml );
        lox.RemoveLogger( relLogger );
    }
 /** ********************************************************************************************
 * Log_TextLogger_FormatConfig
 **********************************************************************************************/
 void testFormatConfig( String testFormat,
                        String expFmt,
                        String expFmtError    = null,
                        String expFmtWarning  = null,
                        String expFmtInfo     = null,
                        String expFmtVerbose  = null
                      )
 {
     Variable var= new Variable();
     var.Define(ALox.ConfigCategoryName, "TESTML_FORMAT", ',').Store( testFormat  );
 
     Lox lox= new Lox("TEST");   
     MemoryLogger ml= new MemoryLogger("TESTML");
     lox.SetVerbosity( ml, Verbosity.Info );
     lox.RemoveLogger( ml );
     ALox.Register( lox, ContainerOp.Remove );
 
                                  UT_EQ( expFmt       , ml.MetaInfo.Format );
     if( expFmtError  != null ) { UT_EQ( expFmtError  , ml.MetaInfo.VerbosityError   ); }
     if( expFmtWarning!= null ) { UT_EQ( expFmtWarning, ml.MetaInfo.VerbosityWarning ); }
     if( expFmtInfo   != null ) { UT_EQ( expFmtInfo   , ml.MetaInfo.VerbosityInfo    ); }
     if( expFmtVerbose!= null ) { UT_EQ( expFmtVerbose, ml.MetaInfo.VerbosityVerbose ); }
 }
Beispiel #4
0
        public static void RemoveDebugLogger( Lox lox= null,
        [CallerLineNumber] int cln= 0,[CallerFilePath] String csf="",[CallerMemberName] String cmn="" )
        {
            #if ALOX_DBG_LOG
                // replace the report writer (if we replaced it before)
                Log.RemoveALibReportWriter();

                // remove debug logger(s)
                ALIB.ASSERT_WARNING( DebugLogger != null, "No debug logger to remove." );

                if ( lox == null )
                    lox= LOX;

                if ( DebugLogger != null )
                {
                    lox.RemoveLogger( DebugLogger,  cln,csf,cmn );
                    DebugLogger= null;
                }

                if ( IDELogger != null )
                {
                    lox.RemoveLogger( IDELogger,  cln,csf,cmn );
                    IDELogger= null;
                }

            #endif
        }
    public void Log_Domain_IniFile()
    {
        UT_INIT();

        // Without priorities
        {
            // create iniFile
            IniFile iniFile= new IniFile("*"); // don't read
            Variable var= new Variable();
            iniFile.Store( var.Define( ALox.ConfigCategoryName, "TESTML_FORMAT"),  "%Sp" );
            iniFile.Store( var.Define( ALox.ConfigCategoryName, "T_LOX_TESTML_VERBOSITY",';'),
                             "/DOM_VERB  = VerboseXX  ;" // xx is allowed!
                          +  "/DOM_INFO  = Info       ;"
                          +  "/DOM_WARN  = WARNING    ;"
                          +  "/DOM_ERR   = erRor      ;"
                          +  "/DOM_OFF   = off        ;"
                          +  "/DOM_OFF2  = xxx        ;"
                          +  "/ATSTART*  = Info       ;"
                          +  "*ATEND     = Info       ;"
                          +  "*SUBSTR*   = Info       ;"
                          +  "/OVERWRITE = Info       ;"
                        );
            ALIB.Config.InsertPlugin( iniFile, Configuration.PrioIniFile );


            // test
            Lox lox= new Lox("T_LOX", false);

            lox.SetVerbosity( Lox.CreateConsoleLogger("CONSOLE") , Verbosity.Verbose );
            lox.SetVerbosity( "CONSOLE"                          , Verbosity.Verbose, ALox.InternalDomains );

            // pre-create one of the domains to test if loggers added later get config for existing domains
            lox.Verbose( "DOM_INFO"     , "test" );

            MemoryLogger ml= new MemoryLogger("TESTML");
            lox.SetVerbosity( ml, Verbosity.Off );
            lox.Info   (                  "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Error  ( "NOSETTING"    , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;

            lox.Verbose( "DOM_VERB"     , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.Verbose( "DOM_INFO"     , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "DOM_INFO"     , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.Info   ( "DOM_WARN"     , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Warning( "DOM_WARN"     , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.Warning( "DOM_ERR"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Error  ( "DOM_ERR"      , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.Error  ( "DOM_OFF"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Error  ( "DOM_OFF2"     , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;

            lox.Verbose( "ATSTART"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "ATSTART"      , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "ATSTARTXX"    , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "ATSTARTXX"    , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "XXATSTART"    , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "XXATSTART"    , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "XATSTARTX"    , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "XATSTARTX"    , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;

            lox.Verbose( "ATEND"        , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "ATEND"        , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "ATENDXX"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "ATENDXX"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "XXATEND"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "XXATEND"      , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "XATENDX"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "XATENDX"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;

            lox.Verbose( "SUBSTR"       , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "SUBSTR"       , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "SUBSTRXX"     , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "SUBSTRXX"     , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "XXSUBSTR"     , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "XXSUBSTR"     , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "XSUBSTRX"     , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "XSUBSTRX"     , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            // overwrite config
            lox.Verbose( "/OVERWRITE"   , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "/OVERWRITE"   , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.SetVerbosity( ml , Verbosity.Warning, "/OVERWRITE" ); // does not overwrite
            lox.Verbose( "/OVERWRITE"   , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "/OVERWRITE"   , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.SetVerbosity( ml , Verbosity.Warning, "/OVERWRITE", 1000 ); // does overwrite
            lox.Verbose( "/OVERWRITE"   , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "/OVERWRITE"   , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Warning( "/OVERWRITE"   , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            // overwrite non-config
            lox.Error  ( "/A"           , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Error  ( "/A/B"         , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Error  ( "/A/C"         , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;

            lox.SetVerbosity( ml , Verbosity.Info, "/A/B", Configuration.PrioDefault -1 ); // does not overwrite
            lox.Verbose( "/A/B"         , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "/A/B"         , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;

            lox.SetVerbosity( ml , Verbosity.Info, "/A/B", Configuration.PrioDefault ); // does overwrite
            lox.Verbose( "/A/B"         , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "/A/B"         , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.SetVerbosity( ml , Verbosity.Info, "/A/B", Configuration.PrioDefault + 1 ); // one higher
            lox.Verbose( "/A/B"         , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "/A/B"         , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.SetVerbosity( ml , Verbosity.Verbose, "/A" );
            lox.Verbose( "/A"           , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "/A/B"         , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "/A/B"         , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "/A/C"         , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            //lox.State( "", Verbosity.Info, "Configuration now is:" ); ml.MemoryLog._(); ml.AutoSizes.Reset();

            ALIB.Config.RemovePlugin( iniFile );
            lox.RemoveLogger( ml );
            lox.RemoveLogger( "CONSOLE" );
        }


    }
    public void Lox_LogLevelSetting()
    {
        UT_INIT();
        Lox lox= new Lox( "ReleaseLox" );
        TextLogger logger= Lox.CreateConsoleLogger( null );
        lox.SetDomain( "TLLS_DF", Scope.Method );
        int logLinesBefore= logger.CntLogs;

        // Test Verbosity setting

        lox.SetVerbosity( logger, Verbosity.Verbose, "" );
        lox.Verbose  (         "This Verbose line should be logged" );
        lox.Info     (         "This Info    line should be logged" );
        lox.Warning  (         "This WARN    line should be logged" );
        lox.Error    (         "This Error   line should be logged" );

        lox.SetVerbosity( logger, Verbosity.Info, "" );
        lox.Verbose  (         "This Verbose line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Info     (         "This Info    line should be logged" );
        lox.Warning  (         "This Warning line should be logged" );
        lox.Error    (         "This Error   line should be logged" );

        lox.SetVerbosity( logger, Verbosity.Warning, "" );
        lox.Verbose  (         "This Verbose line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Info     (         "This Info    line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Warning  (         "This Warning line should be logged" );
        lox.Error    (         "This Error   line should be logged" );

        lox.SetVerbosity( logger, Verbosity.Error, "" );
        lox.Verbose  (         "This Verbose line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Info     (         "This Info    line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Warning  (         "This Warning line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Error    (         "This Error   line should be logged" );

        lox.SetVerbosity( logger, Verbosity.Off, "" );
        lox.Verbose  (         "This Verbose line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Info     (         "This Info    line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Warning  (         "This Warning line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Error    (         "This Error   line should NOT be logged. !!!!!Test Error!!!!!" );

        lox.SetVerbosity( logger, Verbosity.Verbose, "/TLLS" );
        lox.Verbose  ( "/TLLS", "This Verbose line should be logged" );
        lox.Info     ( "/TLLS", "This Info    line should be logged" );
        lox.Warning  ( "/TLLS", "This WARN    line should be logged" );
        lox.Error    ( "/TLLS", "This Error   line should be logged" );

        lox.SetVerbosity( logger, Verbosity.Info, "/TLLS" );
        lox.Verbose  ( "/TLLS", "This Verbose line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Info     ( "/TLLS", "This Info    line should be logged" );
        lox.Warning  ( "/TLLS", "This Warning line should be logged" );
        lox.Error    ( "/TLLS", "This Error   line should be logged" );


        lox.SetVerbosity( logger, Verbosity.Warning, "/TLLS" );
        lox.Verbose  ( "/TLLS", "This Verbose line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Info     ( "/TLLS", "This Info    line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Warning  ( "/TLLS", "This Warning line should be logged" );
        lox.Error    ( "/TLLS", "This Error   line should be logged" );

        lox.SetVerbosity( logger, Verbosity.Error, "/TLLS" );
        lox.Verbose  ( "/TLLS", "This Verbose line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Info     ( "/TLLS", "This Info    line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Warning  ( "/TLLS", "This Warning line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Error    ( "/TLLS", "This Error   line should be logged" );

        lox.SetVerbosity( logger, Verbosity.Off, "/TLLS" );
        lox.Verbose  ( "/TLLS", "This Verbose line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Info     ( "/TLLS", "This Info    line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Warning  ( "/TLLS", "This Warning line should NOT be logged. !!!!!Test Error!!!!!" );
        lox.Error    ( "/TLLS", "This Error   line should NOT be logged. !!!!!Test Error!!!!!" );

        UT_EQ ( (uint) 20, logger.CntLogs - logLinesBefore );

        lox.RemoveLogger( logger );
    }
    public void Log_DomainSubstitutions_IniFile()
    {
        UT_INIT();

        // create INI file
        String iniFileContents=
             "[ALOX]\n"
            +"TESTMEMLOGGER_FORMAT= \"<%D>\"  \n"

            +"MYLOX_DOMAIN_SUBSTITUTION = /A_DOM -> /BETTER_NAME   ;\\ \n"
                         +"    /UI    -> /LIBS/UI    \n"

            +"x\n"
           ;
/* SNIPPIT FOR Dox
//! [Man_DomSubst_Config]
[ALOX]
MYLOX_DOMAIN_SUBSTITUTION= /A_DOM -> /BETTER_NAME   ; \
                           /UI    -> /LIBS/UI
//! [Man_DomSubst_Config]
*/
        String fileName= Environment.CurrentDirectory + "/Log_DomainSubstitutions_IniFile.ini";
        StreamWriter file= new StreamWriter( fileName );
        file.Write( iniFileContents );
        file.Close();

        IniFile iniFile= new IniFile( fileName );
        iniFile.ReadFile();
        //iniFile.WriteFile(); // temporarily enable to see what we have written above

        // add to config
        ALIB.Config.InsertPlugin( iniFile, Configuration.PrioIniFile );

        // create lox, loggers
        Lox myLox= new Lox( "MyLox" ); // name will be upper case
        myLox.SetVerbosity( Lox.CreateConsoleLogger("CONSOLE") , Verbosity.Verbose );
        myLox.SetVerbosity( "CONSOLE"                          , Verbosity.Verbose, ALox.InternalDomains );

// SNIPPIT FOR Dox
#if NEVER_DEFINED
//! [Man_DomSubst_Config_Prevent]
myLox= new Lox( "MyLox" );                      // name will be converted to upper case
myLox.SetDomainSubstitutionRule( null, null );  // clear rules eventually read in constructor
//! [Man_DomSubst_Config_Prevent]
#endif


        MemoryLogger ml= new MemoryLogger("TESTMEMLOGGER");
        myLox.SetVerbosity ( ml, Verbosity.Verbose );

        LOG_CHECK( "DOM"    , "</DOM>"              , ml,myLox);
        LOG_CHECK( "A_DOM"  , "</BETTER_NAME>"      , ml,myLox);
        LOG_CHECK( "UI"     , "</LIBS/UI>"          , ml,myLox);

        //Log.State( "", Verbosity.Info, "Configuration now is:" );

        ALIB.Config.RemovePlugin( iniFile );
        myLox.RemoveLogger( ml );
        myLox.RemoveLogger( "CONSOLE" );
    }
    public void Log_RelativeDomains()
    {
        UT_INIT();

        Lox lox= new Lox( "ReleaseLox" );
        MemoryLogger ml= new MemoryLogger();

        lox.SetVerbosity ( ml, Verbosity.Verbose );
        ml.MetaInfo.Format._()._("@%D#");
        lox.SetDomain( "/D1/D2/D3", Scope.Method );

        lox.Info( "D4"                 , "" ); UT_EQ( "@/D1/D2/D3/D4#"        , ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();
        lox.Info( "./D4"               , "" ); UT_EQ( "@/D1/D2/D3/D4#"        , ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();
        lox.Info( "../D4"              , "" ); UT_EQ( "@/D1/D2/D4#"           , ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();
        lox.Info( ".././.././D4"       , "" ); UT_EQ( "@/D1/D4#"              , ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();
        lox.Info( "../../../../../D4"  , "" ); UT_EQ( "@/D4#"                 , ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();
        lox.Info( "../D4/../D5"        , "" ); UT_EQ( "@/D1/D2/D5#"           , ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();


        lox.RemoveLogger( ml );
    }
    public void Lox_ScopeDomains()
    {
        UT_INIT();

        // we have tell alox to include more directories in the scope path
        Log.ClearSourcePathTrimRules( Reach.Global, false);
        Log.SetSourcePathTrimRule( "*/alox/src.cs/", Inclusion.Exclude );

        Lox lox= new Lox( "ReleaseLox" );
        TextLogger consoleLogger= Lox.CreateConsoleLogger();
        MemoryLogger ml= new MemoryLogger();
        ml.MetaInfo.Format._()._("@%D#");
        lox.SetVerbosity(ml, Verbosity.Verbose );

        lox.SetVerbosity(consoleLogger, Verbosity.Verbose );
        lox.SetVerbosity(consoleLogger, Verbosity.Verbose, ALox.InternalDomains );

        // scope global
        lox.SetDomain( "REPLACE",    Scope.Global   );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/REPLACE#"                     ,ml );
        lox.SetDomain( "GLOBAL",     Scope.Global   );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/GLOBAL#"                      ,ml );

        lox.SetDomain( null,         Scope.Global   );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/#"                            ,ml );

        // scope source
        lox.SetDomain( "REPLACE",    Scope.Filename );  lox.Info(  ""   , "" ); CICHECK_RL( "@/REPLACE#"                     ,ml );
        lox.SetDomain( "FILE",       Scope.Filename );  lox.Info(  ""   , "" ); CICHECK_RL( "@/FILE#"                        ,ml );

        // scope method
        lox.SetDomain( "REPLACE",    Scope.Method   );  lox.Info(  ""   , "" ); CICHECK_RL( "@/FILE/REPLACE#"                ,ml );
        lox.SetDomain( "Method",     Scope.Method   );  lox.Info(  ""   , "" ); CICHECK_RL( "@/FILE/METHOD#"                 ,ml );
        lox.SetDomain( "/ABS",       Scope.Method   );  lox.Info(  ""   , "" ); CICHECK_RL( "@/ABS#"                         ,ml );

        // unset method with null
        lox.SetDomain( null,         Scope.Method   );  lox.Info(  ""   , "" ); CICHECK_RL( "@/FILE#"                        ,ml );

        // unset method with ""
        lox.SetDomain( "/METHOD",    Scope.Method   );  lox.Info(  ""   , "" ); CICHECK_RL( "@/METHOD#"                      ,ml );
        lox.SetDomain( "",           Scope.Method   );  lox.Info(  ""   , "" ); CICHECK_RL( "@/FILE#"                        ,ml );
        lox.SetDomain( "Method",     Scope.Method   );  lox.Info(  ""   , "" ); CICHECK_RL( "@/FILE/METHOD#"                 ,ml );

        // source path
        lox.SetDomain( "REPLACE",    Scope.Path     );  lox.Info(  ""   , "" ); CICHECK_RL( "@/REPLACE/FILE/METHOD#"         ,ml );
        lox.SetDomain( "PATH",       Scope.Path     );  lox.Info(  ""   , "" ); CICHECK_RL( "@/PATH/FILE/METHOD#"            ,ml );
        lox.SetDomain( "REPLACE",    Scope.Path, 1  );  lox.Info(  ""   , "" ); CICHECK_RL( "@/REPLACE/PATH/FILE/METHOD#"    ,ml );
        lox.SetDomain( "PO1",        Scope.Path, 1  );  lox.Info(  ""   , "" ); CICHECK_RL( "@/PO1/PATH/FILE/METHOD#"        ,ml );
        lox.SetDomain( "REPLACE",    Scope.Path, 2  );  lox.Info(  ""   , "" ); CICHECK_RL( "@/REPLACE/PO1/PATH/FILE/METHOD#",ml );
        lox.SetDomain( "PO2",        Scope.Path, 2  );  lox.Info(  ""   , "" ); CICHECK_RL( "@/PO2/PO1/PATH/FILE/METHOD#"    ,ml );

        lox.SetDomain( "GLOBAL",     Scope.Global   );  lox.Info(  ""   , "" ); CICHECK_RL( "@/GLOBAL/PO2/PO1/PATH/FILE/METHOD#"  , ml );


        // remove all previous scope domains
        lox.SetDomain( "",     Scope.Global      );
        lox.SetDomain( "",     Scope.Path        );
        lox.SetDomain( "",     Scope.Path    ,1  );
        lox.SetDomain( "",     Scope.Path    ,2  );
        lox.SetDomain( "",     Scope.Filename    );
        lox.SetDomain( "",     Scope.Method      );  lox.Info(  "LOC", "" ); SDCHECK_RL(  "@/LOC#"                ,ml );

        // Thread-related
        lox.SetDomain( "T_O",  Scope.ThreadOuter );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/T_O#"                 ,ml );
        lox.SetDomain( "GL",   Scope.Global      );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/GL/T_O#"              ,ml );
        lox.SetDomain( "MET",  Scope.Method      );  lox.Info(  ""   , "" ); CICHECK_RL( "@/GL/T_O/MET#"          ,ml );
                                                              lox.Info(  "LOC", "" ); CICHECK_RL( "@/GL/T_O/MET/LOC#"      ,ml );
        lox.SetDomain( "T_I",  Scope.ThreadInner );  lox.Info(  ""   , "" ); CICHECK_RL( "@/GL/T_O/MET/T_I#"      ,ml );
                                                              lox.Info(  "LOC", "" ); CICHECK_RL( "@/GL/T_O/MET/LOC/T_I#"  ,ml );
        lox.SetDomain( "T_O2", Scope.ThreadOuter );  lox.Info(  ""   , "" ); CICHECK_RL( "@/GL/T_O/T_O2/MET/T_I#" ,ml );
        lox.SetDomain( "T_I2", Scope.ThreadInner );  lox.Info(  ""   , "" ); CICHECK_RL( "@/GL/T_O/T_O2/MET/T_I/T_I2#" ,ml );

        lox.SetDomain( "/T_O3",Scope.ThreadOuter );  lox.Info(  ""   , "" ); CICHECK_RL( "@/T_O3/MET/T_I/T_I2#"   ,ml );
        lox.SetDomain( "/T_I3",Scope.ThreadInner );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/T_I3#"                ,ml );
        lox.SetDomain( "",     Scope.Method      );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/T_I3#"                ,ml );

        lox.SetDomain         ( ""     ,Scope.ThreadInner );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/T_O3/T_I/T_I2#"   ,ml );
        lox.RemoveThreadDomain( "T_IXX",Scope.ThreadInner );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/T_O3/T_I/T_I2#"   ,ml );
        lox.RemoveThreadDomain( "T_I"  ,Scope.ThreadInner );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/T_O3/T_I2#"       ,ml );
        lox.RemoveThreadDomain( ""     ,Scope.ThreadInner );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/T_O3/T_I2#"       ,ml );
        lox.SetDomain         ( ""     ,Scope.ThreadInner );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/T_O3#"            ,ml );
        lox.SetDomain         ( ""     ,Scope.ThreadOuter );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/GL/T_O/T_O2#"     ,ml );
        lox.SetDomain         ( "T_O3", Scope.ThreadOuter );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/GL/T_O/T_O2/T_O3#",ml );
        lox.RemoveThreadDomain( "T_O2" ,Scope.ThreadOuter );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/GL/T_O/T_O3#"     ,ml );
        lox.RemoveThreadDomain( "T_O"  ,Scope.ThreadOuter );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/GL/T_O3#"         ,ml );
        lox.SetDomain         ( ""     ,Scope.ThreadOuter );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/GL#"              ,ml );
        lox.SetDomain         ( ""     ,Scope.Global      );  lox.Info(  ""   , "" ); SDCHECK_RL( "@/#"                 ,ml );


        // second thread
        Thread thread= new Thread( new ParameterizedThreadStart( DomainTestThreadRun_RL ) );
        lox.SetDomain( "THIS_THREAD",   Scope.ThreadOuter );
        lox.SetDomain( "OTHER_THREAD",  Scope.ThreadOuter, thread );
        thread.Start( lox );
        while( thread.IsAlive )
            ALIB.SleepMillis(1);
                               UT_EQ( "@/OTHER_THREAD/DTT#", ml.MemoryLog );  ml.MemoryLog._(); ml.AutoSizes.Reset();
        lox.Info( "ME", "" );  UT_EQ( "@/THIS_THREAD/ME#"  , ml.MemoryLog );  ml.MemoryLog._(); ml.AutoSizes.Reset();

        // cleanup
        lox.RemoveLogger( consoleLogger );
        lox.RemoveLogger( ml );
    }
    public void Lox_AddLogger()
    {
        UT_INIT();

        // twice
        {
            ConsoleLogger con=      new ConsoleLogger();
            Log.SetVerbosity( con,      Verbosity.Verbose, ALox.InternalDomains );

            MemoryLogger checkCnt=  new MemoryLogger( "CHECK");
            Log.SetVerbosity( checkCnt, Verbosity.Warning, ALox.InternalDomains );

            MemoryLogger mem1= new MemoryLogger( "MEM" );
            MemoryLogger mem2= new MemoryLogger( "MEM" );

            Log.SetVerbosity( mem1,     Verbosity.Info ); UT_EQ( 0, checkCnt.CntLogs );
            Log.SetVerbosity( mem2,     Verbosity.Info ); UT_EQ( 1, checkCnt.CntLogs );
            Log.SetVerbosity( "XYZ",    Verbosity.Info ); UT_EQ( 2, checkCnt.CntLogs );

            Log.RemoveLogger( mem2     );                 UT_EQ( 3, checkCnt.CntLogs );
            Log.RemoveLogger( mem1     );                 UT_EQ( 3, checkCnt.CntLogs );
            Log.RemoveLogger( mem1     );                 UT_EQ( 4, checkCnt.CntLogs );
            Log.RemoveLogger( "XYZ"    );                 UT_EQ( 5, checkCnt.CntLogs );
            Log.RemoveLogger( con      );                 UT_EQ( 5, checkCnt.CntLogs );
            Log.RemoveLogger( con      );                 UT_EQ( 6, checkCnt.CntLogs );
            Log.RemoveLogger( checkCnt );                 UT_EQ( 6, checkCnt.CntLogs );
        }

        // one logger in two loxes
        {
            Log.AddDebugLogger();
            Lox lox= new Lox( "ReleaseLox" );

            UT_TRUE( Log.DebugLogger.GetSafeness() == Safeness.Unsafe );

            lox.SetVerbosity( Log.DebugLogger , Verbosity.Verbose );

            UT_TRUE( Log.DebugLogger.GetSafeness() == Safeness.Safe );

            lox.RemoveLogger( Log.DebugLogger );

            UT_TRUE( Log.DebugLogger.GetSafeness() == Safeness.Unsafe );

            Log.RemoveDebugLogger();
        }
    }
    public void Log_SetSourcePathTrimRuleExternal()
    {
        UT_INIT();

        // for the unit tests to reset, we need an extra lox to be able to clear the global rules
        // beforewe initialize our main lox
        Lox clearLox= new Lox("ClearingRules");

        // global rule
        clearLox.ClearSourcePathTrimRules( Reach.Global, false);
        {
            // create iniFile
            String iniFileContents=
                 "[ALOX]\n"
                +"TESTML_FORMAT= \"%Sp\"  \n"

                +"GLOBAL_SOURCE_PATH_TRIM_RULES=  *src.cs/   , true  ;     \\   \n"
                             +"    /usr/local/lib/  , false, 9, true, /usr/lib/"
                +"\n"
               ;
/* SNIPPIT FOR Dox
//! [Man_SourcePathTrimming]
[ALOX]
GLOBAL_SOURCE_PATH_TRIM_RULES= *src.cs/                  , true                ; \
                               /usr/local/lib/  , false, 9, true, /usr/lib/
//! [Man_SourcePathTrimming]
*/
            String fileName= Environment.CurrentDirectory + "/Log_ConfigTrimRules.ini";
            StreamWriter file= new StreamWriter( fileName );
            file.Write( iniFileContents );
            file.Close();

            IniFile iniFile= new IniFile( fileName );
            iniFile.ReadFile();
            //iniFile.WriteFile(); // temporarily enable to see what we have written above

            ALIB.Config.InsertPlugin( iniFile, Configuration.PrioIniFile );

            // test
            Lox lox= new Lox("T_LOX", false );

            lox.SetVerbosity( Lox.CreateConsoleLogger("CONSOLE") , Verbosity.Verbose );
            lox.SetVerbosity( "CONSOLE"                          , Verbosity.Verbose, ALox.InternalDomains );

            MemoryLogger ml= new MemoryLogger("TESTML");

            lox.SetVerbosity(ml, Verbosity.Verbose );

            lox.Info( "" );  UT_EQ("alox.unittests", ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();

            ALIB.Config.RemovePlugin( iniFile );
            lox.RemoveLogger( ml );
            lox.RemoveLogger( "CONSOLE" );
        }

        // local rule
        clearLox.ClearSourcePathTrimRules( Reach.Global, false);
        ALIB.Config.DefaultValues.Reset();
        {
            // store default values
            Variable var= new Variable();
            var.Define( ALox.ConfigCategoryName, "TESTML_FORMAT" ).Store( "%Sp" );
            var.Define( ALox.ConfigCategoryName, "T_LOX_SOURCE_PATH_TRIM_RULES",';')
            .Store( "*;**; *alox.u*, include ;*;**" // default values, 0, ignore"
                                                    // the * will be removed
                                                    // two illegal rules before and after
                                 );

            // test
            Lox lox= new Lox("T_LOX", false );

            lox.SetVerbosity( Lox.CreateConsoleLogger("CONSOLE") , Verbosity.Verbose );
            lox.SetVerbosity( "CONSOLE"                          , Verbosity.Verbose, ALox.InternalDomains );

            MemoryLogger ml= new MemoryLogger("TESTML");

            lox.SetVerbosity(ml, Verbosity.Verbose );

            lox.Info( "" ); UT_EQ( "nittests"  , ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();

            lox.RemoveLogger( ml );
            lox.RemoveLogger( "CONSOLE" );
        }

        clearLox.ClearSourcePathTrimRules( Reach.Global, false);
        ALIB.Config.DefaultValues.Reset();
        {
            // create iniFile
            IniFile iniFile= new IniFile("*"); // don't read
            Variable var= new Variable();
            iniFile.Store( var.Define( ALox.ConfigCategoryName, "TESTML_FORMAT" ),  "%Sp" );
            iniFile.Store( var.Define( ALox.ConfigCategoryName, "T_LOX_SOURCE_PATH_TRIM_RULES",';'),
                           "*alox.u, excl, 2, sens" );

            ALIB.Config.InsertPlugin( iniFile, Configuration.PrioIniFile );


            // test
            Lox lox= new Lox("T_LOX", false );

            lox.SetVerbosity( Lox.CreateConsoleLogger("CONSOLE") , Verbosity.Verbose );
            lox.SetVerbosity( "CONSOLE"                          , Verbosity.Verbose, ALox.InternalDomains );

            MemoryLogger ml= new MemoryLogger("TESTML");

            lox.SetVerbosity(ml, Verbosity.Verbose );

            lox.Info( "" ); UT_EQ( "ox.unittests"  , ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();

            // overwrite with source priority
            lox.SetSourcePathTrimRule( "*alox.u", Inclusion.Exclude, 0, Case.Ignore, "REPLACE_1/", Reach.Local );
            lox.Info( "" ); UT_EQ( "ox.unittests"  , ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();
            lox.SetSourcePathTrimRule( "*alox.u", Inclusion.Exclude, 0, Case.Ignore, "REPLACE_2/", Reach.Local, Configuration.PrioProtected );
            lox.Info( "" ); UT_TRUE( ml.MemoryLog.StartsWith( "REPLACE_2/" ) ); ml.MemoryLog._(); ml.AutoSizes.Reset();

            ALIB.Config.RemovePlugin( iniFile );
            lox.RemoveLogger( ml );
            lox.RemoveLogger( "CONSOLE" );
        }

        // ignore case
        clearLox.ClearSourcePathTrimRules( Reach.Global, false);
        ALIB.Config.DefaultValues.Reset();
        {
            // store default values
            Variable var= new Variable();
            var.Define( ALox.ConfigCategoryName, "TESTML_FORMAT" ).Store( "%Sp" );
            var.Define( ALox.ConfigCategoryName, "T_LOX_SOURCE_PATH_TRIM_RULES",';')
               .Store( "*aLOX.U, exc, 2, ign"   );


            // test
            Lox lox= new Lox("T_LOX", false );

            lox.SetVerbosity( Lox.CreateConsoleLogger("CONSOLE") , Verbosity.Verbose );
            lox.SetVerbosity( "CONSOLE"                          , Verbosity.Verbose, ALox.InternalDomains );

            MemoryLogger ml= new MemoryLogger("TESTML");

            lox.SetVerbosity(ml, Verbosity.Verbose );

            lox.Info( "" ); UT_EQ( "ox.unittests"  , ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();

            lox.RemoveLogger( ml );
            lox.RemoveLogger( "CONSOLE" );
        }

        clearLox.ClearSourcePathTrimRules( Reach.Global, false);
        ALIB.Config.DefaultValues.Reset();
        {
            // store default values
            Variable var= new Variable();
            var.Define( ALox.ConfigCategoryName, "TESTML_FORMAT" ).Store( "%Sp" );
            var.Define( ALox.ConfigCategoryName, "T_LOX_SOURCE_PATH_TRIM_RULES",';')
               .Store( "*aLOX.U, excl, 2, sens"  );



            // test
            Lox lox= new Lox("T_LOX", false );

            lox.SetVerbosity( Lox.CreateConsoleLogger("CONSOLE") , Verbosity.Verbose );
            lox.SetVerbosity( "CONSOLE"                          , Verbosity.Verbose, ALox.InternalDomains );

            MemoryLogger ml= new MemoryLogger("TESTML");

            lox.SetVerbosity(ml, Verbosity.Verbose );

            lox.Info( "" );
            if( Path.DirectorySeparatorChar == '/' )
                UT_EQ( "src.cs/alox.unittests"  , ml.MemoryLog );
            else
                UT_EQ( "src.cs\\alox.unittests"  , ml.MemoryLog );

            ml.MemoryLog._(); ml.AutoSizes.Reset();
            lox.RemoveLogger( ml );
            lox.RemoveLogger( "CONSOLE" );
        }
    }