// ############################################################################################# // Constructor // ############################################################################################# /** **************************************************************************************** * Creates an AnsiLogger. * @param textWriter The TextWriter object to write into. * @param usesStdStreams Denotes whether this logger writes to the * <em>standard output streams</em>. * @param name The name of the \e Logger, defaults to what is provided with * parameter \p typeName. * @param typeName The type of the \e Logger, defaults to "ANSI". ******************************************************************************************/ public AnsiLogger( System.IO.TextWriter textWriter, bool usesStdStreams, String name= null, String typeName= "ANSI" ) : base( name, typeName, usesStdStreams ) { this.textWriter= textWriter; // evaluate environment variable "ALOX_CONSOLE_HAS_LIGHT_BACKGROUND" Variable variable= new Variable( ALox.CONSOLE_HAS_LIGHT_BACKGROUND ); variable.Load(); if ( variable.Size() > 0 ) IsBackgroundLight= variable.IsTrue(); else { // on ANSI terminals we can only guess. Our guess is: console windows have dark background IsBackgroundLight= false; } // remove verbosity information and colorize the whole line MetaInfo.Format.SearchAndReplace( "]%V[", "][" ); if ( IsBackgroundLight ) { MsgPrefixError = ANSI_RED; MsgPrefixWarning = ANSI_BLUE; MsgPrefixVerbose = ANSI_GRAY; } else { MsgPrefixError = ANSI_LIGHT_RED; MsgPrefixWarning = ANSI_LIGHT_BLUE; MsgPrefixVerbose = ANSI_LIGHT_GRAY; } // set source file background to gray AString ansiBGGray= new AString( ESC.BG_GRAY ); ansiBGGray._( "%SF(%SL):" )._( ANSI_BG_STD_COL ); MetaInfo.Format.SearchAndReplace( "%SF(%SL):", ansiBGGray.ToString() ); }
/** ******************************************************************************************** * Creates an AnsiConsoleLogger. * @param name (Optional) The name of the \e Logger, defaults to "ANSI_CONSOLE". **********************************************************************************************/ public AnsiConsoleLogger( String name= null ) : base( Console.Out, true, name, "ANSI_CONSOLE" ) { // evaluate environment variable "ALOX_CONSOLE_HAS_LIGHT_BACKGROUND" Variable variable= new Variable( ALox.CONSOLE_HAS_LIGHT_BACKGROUND ); variable.Load(); if ( variable.Size() > 0 ) IsBackgroundLight= variable.IsTrue(); else { ConsoleColor fgCol= Console.ForegroundColor; IsBackgroundLight= fgCol == ConsoleColor.Black || fgCol == ConsoleColor.DarkBlue || fgCol == ConsoleColor.DarkCyan || fgCol == ConsoleColor.DarkGray || fgCol == ConsoleColor.DarkGreen || fgCol == ConsoleColor.DarkMagenta || fgCol == ConsoleColor.DarkRed || fgCol == ConsoleColor.DarkYellow ; } }
/** **************************************************************************************** * This method must be called prior to using ALib, e.g. at the beginning of * the \c main() method of an application. It is OK, to call this method more than once, which * allows independent code blocks (e.g. libraries) to bootstrap %ALIB independently. * However, only the first invocation is effective with the exclamation that if * command line parameters are provided with a call, those are set. * Also, the very first invocation should not be interrupted by a parallel invocation of a * second thread. Consequently, it has to be assured that this method is invoked once on * the real bootstrap an app. * * In the C# version of the AWorx library, the invocation of this method is optional. * However, it is good practice to invoke this method in the main() method of a process * and provide the command line arguments. If no invocation is performed, no * configuration plug-ins are set. * * \note * If other, custom configuration data sources should be used already with this method * (in the current implementation, the only configuration variable read with this method * is \c WAIT_FOR_KEY_PRESS), then such plug-in(s) have to be added to * public, static field #Config prior to invoking this method. * * @param args Parameters taken from <em>standard C#</em> method \c main() * (the list of command line arguments). * Defaults to null. ******************************************************************************************/ public static void Init( String[] args= null ) { Config.SetCommandLineArgs( args ); if ( isInitialized ) return; isInitialized= true; // set the system's locale as the default for our static default number format NumberFormat.Global.SetFromLocale(); // --- determine if we want to wait for a keypress upon termination --- { Variable variable= new Variable( ALIB.WAIT_FOR_KEY_PRESS ); variable.Load(); if ( variable.Size() > 0 ) WaitForKeyPressOnTermination= variable.IsTrue(); else { #if ALIB_VSTUDIO WaitForKeyPressOnTermination= ALIB.SysInfo_HasConsoleWindow && System.Diagnostics.Debugger.IsAttached; #else WaitForKeyPressOnTermination= false; #endif // WIN32 } } }
public static void AddDebugLogger( Lox lox= null, [CallerLineNumber] int cln= 0,[CallerFilePath] String csf="",[CallerMemberName] String cmn="" ) { #if ALOX_DBG_LOG if ( lox == null ) lox= LOX; ALIB.ASSERT_ERROR( DebugLogger == null, "Illeagal repeated invocation." ); // add a CLR logger if this a debug session if( System.Diagnostics.Debugger.IsAttached ) { Variable variable= new Variable(ALox.NO_IDE_LOGGER); variable.Load(); if( !variable.IsTrue() ) { IDELogger= new CLRDebuggerLogger( "IDE_LOGGER" ); // add logger lox.SetVerbosity( IDELogger , Verbosity.Verbose, "/" , Configuration.PrioDefault ,cln,csf,cmn ); lox.SetVerbosity( IDELogger , Verbosity.Warning, ALox.InternalDomains, Configuration.PrioDefault ,cln,csf,cmn ); } } // add a default console logger DebugLogger= Lox.CreateConsoleLogger("DEBUG_LOGGER"); lox.SetVerbosity( DebugLogger, Verbosity.Verbose, "/" , Configuration.PrioDefault ,cln,csf,cmn ); lox.SetVerbosity( DebugLogger, Verbosity.Warning, ALox.InternalDomains, Configuration.PrioDefault ,cln,csf,cmn ); // replace the ReportWriter Log.AddALibReportWriter( lox ); #endif }
/** **************************************************************************************** * Invokes grand-parent's method and in addition, de-registers with * \ref cs::aworx::lib::ALIB::StdOutputStreamsLock "ALIB.StdOutputStreamsLock" * @param acquirer The acquirer to remove. * @return The new number of \e acquirers set. ******************************************************************************************/ public override int RemoveAcquirer( ThreadLock acquirer ) { // d-register with ALIB lockers (if not done yet) if ( usesStdStreams ) { ALIB.Lock.Acquire(); int stdStreamLockRegistrationCounter= --this.stdStreamLockRegistrationCounter; ALIB.Lock.Release(); if ( stdStreamLockRegistrationCounter == 0 ) ALIB.StdOutputStreamsLock.RemoveAcquirer( this ); } Variable variable= new Variable(); // export autosizes to configuration variable.Define( ALox.AUTO_SIZES, GetName() ); AutoSizes.Export( variable.AddString() ); variable.Store(); // export "max elapsed time" to configuration variable.Define( ALox.MAX_ELAPSED_TIME, GetName() ); AString destVal= variable.Load() != 0 ? variable.GetString() : variable.AddString(); destVal._()._( MetaInfo.MaxElapsedTime.InSeconds() ); variable.Store(); // call parents' implementation return base.RemoveAcquirer( acquirer ); }
/** ******************************************************************************************** * Creates a ConsoleLogger. * @param name (Optional) The name of the \e Logger, defaults to "COLOR_CONSOLE" **********************************************************************************************/ public ColorConsoleLogger( String name= null ) : base( name, "COLOR_CONSOLE", true ) { // get actual console foreground color ConsoleColor fgCol= Console.ForegroundColor; // evaluate environment variable "ALOX_CONSOLE_HAS_LIGHT_BACKGROUND" Variable variable= new Variable( ALox.CONSOLE_HAS_LIGHT_BACKGROUND ); variable.Load(); if ( variable.Size() > 0 ) IsBackgroundLight= variable.IsTrue(); else { IsBackgroundLight= fgCol == ConsoleColor.Black || fgCol == ConsoleColor.DarkBlue || fgCol == ConsoleColor.DarkCyan || fgCol == ConsoleColor.DarkGray || fgCol == ConsoleColor.DarkGreen || fgCol == ConsoleColor.DarkMagenta || fgCol == ConsoleColor.DarkRed || fgCol == ConsoleColor.DarkYellow ; } // remove verbosity information and colorize the whole line MetaInfo.Format.SearchAndReplace( " %V ", " " ); MsgColorInfo = fgCol; if ( IsBackgroundLight ) { MsgColorError = ConsoleColor.DarkRed; MsgColorWarning = ConsoleColor.DarkBlue; MsgColorVerbose = ConsoleColor.DarkGray; } else { MsgColorError = ConsoleColor.Red; MsgColorWarning = ConsoleColor.Blue; MsgColorVerbose = ConsoleColor.Gray; } }
public void SetVerbosity( Logger logger, Verbosity verbosity, String domain = "/", int priority = Configuration.PrioDefault, [CallerLineNumber] int cln=0,[CallerFilePath] String csf="",[CallerMemberName] String cmn="" ) { #if ALOX_DBG_LOG || ALOX_REL_LOG try { Acquire(); // initialize scope information scopeInfo.Set( cln,csf,cmn, owner ); // check if ( logger == null ) { logInternal( Verbosity.Error, "LGR", intMsg._() ._NC( "Given Logger is \"null\". Verbosity not set." ) ); return; } // this might create the (path of) domain(s) and set the \e Loggers' verbosity like their // first parent's or as given in configuration Domain dom= evaluateResultDomain( domain ); // search logger, insert if not found bool isNewLogger= false; int no= dom.GetLoggerNo( logger ); if( no < 0 ) { no= dom.AddLogger( logger ); // error, logger with same name already exists if( no < 0 ) { logInternal( Verbosity.Error, "LGR", intMsg._() ._NC( "Unable to add logger \"" )._NC(logger) ._NC("\". Logger with same name exists." ) ); logInternal( Verbosity.Verbose, "LGR", intMsg._() ._NC( " Request was: SetVerbosity( \"")._(logger)._NC("\", \"") ._(domain) ._NC("\", Verbosity.") ._NC(verbosity) ._NC("\", ") ._(priority) ._NC(" )." )); Logger existingLogger= dom.GetLogger( logger.GetName() ); logInternal( Verbosity.Verbose, "LGR", intMsg._() ._NC( " Existing Logger: \"")._NC(existingLogger)._('\"') ); return; } // We have to register with the SmartLock facility of the \e Logger. // But only if we have not done this yet, via the 'other' root domain tree if ( (dom.GetRoot() == domains ? internalDomains.GetLoggerNo( logger ) : domains.GetLoggerNo( logger ) ) < 0 ) logger.AddAcquirer( this ); // store size of name to support tabular internal log output String loggerName= logger.GetName(); if ( maxLoggerNameLength < loggerName.Length ) maxLoggerNameLength= loggerName.Length; // for internal log isNewLogger= true; // remember that a logger was set after the last removal // (for variable LOXNAME_DUMP_STATE_ON_EXIT) loggerAddedSinceLastDebugState= true; } // do dom.SetVerbosity( no, verbosity, priority ); // get verbosities from configuration if( isNewLogger ) { logInternal( Verbosity.Info, "LGR", intMsg._() ._("Logger \"")._( logger ) ._(domain.StartsWith(ALox.InternalDomains) ? "\" added for internal log messages." : "\" added." ) ); // we have to get all verbosities of already existing domains Variable variable= new Variable( ALox.VERBOSITY, GetName(), logger.GetName() ); if( 0 != variable.Load() ) { getAllVerbosities( logger, domains , variable ); getAllVerbosities( logger, internalDomains , variable ); } } intMsg._()._("Logger \"")._( logger.GetName() )._NC( "\":").Tab(11 + maxLoggerNameLength) ._('\'')._NC( dom.FullPath ) ._( '\'' ).InsertChars(' ', maxDomainPathLength - dom.FullPath.Length() + 1 ) ._( "= Verbosity." ); ALox.ToString( verbosity, priority, intMsg ).TrimEnd()._('.'); Verbosity actVerbosity= dom.GetVerbosity( no ); if( actVerbosity != verbosity ) intMsg._( " Lower priority (")._( priority ) ._(" < ")._(dom.GetPriority(no)) ._( "). Remains " )._NC( actVerbosity )._( '.' ); logInternal( Verbosity.Info, "LGR", intMsg ); } finally { Release(); } #endif }
public void ConfigDefaultAndProtected() { UT_INIT(); String[] args= { "COMMANDLINE", "--TEST_VARIABLE=fromCommandLine", }; Configuration cfg= new Configuration(); cfg.SetCommandLineArgs( args ); Variable var= new Variable(); // command line UT_EQ( Configuration.PrioCmdLine, cfg.Load ( var.Define( "TEST", "VARIABLE" ) ) ); UT_EQ( "fromCommandLine" ,var.GetString() ); // set default, does not overwrite cfg.DefaultValues.Store( var.Define("TEST", "VARIABLE"), "not overwriting" ); UT_EQ( Configuration.PrioCmdLine, cfg.Load ( var.Define( "TEST", "VARIABLE" ) ) ); UT_EQ( "fromCommandLine" ,var.GetString() ); // set protected, overwrites command line cfg.ProtectedValues.Store( var.Define("TEST", "VARIABLE"), "does overwrite" ); UT_EQ( Configuration.PrioProtected, cfg.Load ( var.Define( "TEST", "VARIABLE" ) ) ); UT_EQ( "does overwrite" ,var.GetString() ); // set default, something else cfg.DefaultValues.Store( var.Define("TEST", "VAR2"), "this is var 2" ); UT_EQ( Configuration.PrioDefault, cfg.Load ( var.Define( "TEST", "VAR2" ) ) ); UT_EQ( "this is var 2" ,var.GetString() ); // set and remove an entry using plugin interface var.Define( "TEST", "Remove" ); UT_EQ( 0, var.Size() ); UT_EQ( -1 ,var.Priority ); cfg.DefaultValues.Load( var ); UT_EQ( 0, var.Size() ); UT_EQ( -1 ,var.Priority ); var.AddString("To be deleted"); UT_EQ( 1, var.Size() ); UT_EQ( -1 ,var.Priority ); cfg.DefaultValues.Store( var ); UT_EQ( 1, var.Size() ); UT_EQ( -1 ,var.Priority ); var.Define( "TEST", "Remove" ); UT_EQ( 0, var.Size() ); UT_EQ( -1 ,var.Priority ); cfg.DefaultValues.Load( var ); UT_EQ( 1, var.Size() ); UT_EQ( -1 ,var.Priority ); var.ClearValues(); UT_EQ( 0, var.Size() ); UT_EQ( -1 ,var.Priority ); cfg.DefaultValues.Store( var ); UT_EQ( 0, var.Size() ); UT_EQ( -1 ,var.Priority ); var.Define( "TEST", "Remove" ); UT_EQ( 0, var.Size() ); UT_EQ( -1 ,var.Priority ); cfg.DefaultValues.Load( var ); UT_EQ( 0, var.Size() ); UT_EQ( -1 ,var.Priority ); // set and remove an entry using configuration interface cfg .Load ( var ); UT_EQ( 0, var.Size() ); UT_EQ( 0 ,var.Priority ); cfg .Store( var ); UT_EQ( 0, var.Size() ); UT_EQ( 0 ,var.Priority ); var.AddString("To be deleted"); UT_EQ( 1, var.Size() ); UT_EQ( 0 ,var.Priority ); cfg .Store( var ); UT_EQ( 1, var.Size() ); UT_EQ( Configuration.PrioDefault ,var.Priority ); var.Define( "TEST", "Remove" ); UT_EQ( 0, var.Size() ); UT_EQ( -1 ,var.Priority ); cfg .Load ( var ); UT_EQ( 1, var.Size() ); UT_EQ( Configuration.PrioDefault ,var.Priority ); var.Define( "TEST", "Remove" ); UT_EQ( 0, var.Size() ); UT_EQ( -1 ,var.Priority ); cfg .Store( var ); UT_EQ( 0, var.Size() ); UT_EQ( Configuration.PrioDefault ,var.Priority ); cfg .Load ( var ); UT_EQ( 0, var.Size() ); UT_EQ( 0 ,var.Priority ); var.Define( "TEST", "Remove" ); UT_EQ( 0, var.Size() ); UT_EQ( -1 ,var.Priority ); cfg .Load ( var ); UT_EQ( 0, var.Size() ); UT_EQ( 0 ,var.Priority ); // protected var.Define( "TEST", "Protected"); UT_EQ( 0, var.Size() ); UT_EQ( -1 ,var.Priority ); var.DefaultValue._( "Default" ); var.StoreDefault( "def par"); UT_EQ( "def par", var.GetString() ); UT_EQ( Configuration.PrioDefault ,var.Priority ); var.ClearValues(); var.AddString( "def var" ); var.StoreDefault(); UT_EQ( "def var", var.GetString() ); UT_EQ( Configuration.PrioDefault ,var.Priority ); var.ClearValues(); var.StoreDefault(); UT_EQ( "Default", var.GetString() ); UT_EQ( Configuration.PrioDefault ,var.Priority ); var.ClearValues(); var.AddString( "def var" ); var.Protect(); UT_EQ( "def var", var.GetString() ); UT_EQ( Configuration.PrioProtected ,var.Priority ); var.Protect("prot par"); UT_EQ( "prot par", var.GetString() ); UT_EQ( Configuration.PrioProtected ,var.Priority ); var.ClearValues(); var.Protect(); UT_EQ( "Default", var.GetString() ); UT_EQ( Configuration.PrioProtected ,var.Priority ); var.DefaultValue.SetNull(); var.ClearValues(); var.Protect(); UT_EQ( 0, var.Size() ); UT_EQ( Configuration.PrioProtected ,var.Priority ); var.Load(); UT_EQ( "Default", var.GetString() ); UT_EQ( Configuration.PrioDefault ,var.Priority ); }
/** **************************************************************************************** * Implements functionality for configuration variable \c LOXNAME_DUMP_STATE_ON_EXIT. * Is called when a logger is removed. ******************************************************************************************/ protected void dumpStateOnLoggerRemoval() { if( !loggerAddedSinceLastDebugState ) return; loggerAddedSinceLastDebugState= false; Variable variable= new Variable( ALox.DUMP_STATE_ON_EXIT, GetName() ); variable.Load(); String domain= null; Verbosity verbosity= Verbosity.Info; Substring tok= new Substring(); int flags= 0; for( int tokNo= 0; tokNo< variable.Size(); tokNo++ ) { tok.Set( variable.GetString( tokNo ) ); if( tok.IsEmpty() ) continue; // state flags if( tok.Equals( "NONE" , Case.Ignore ) ) { flags= 0; break; } else if( tok.Equals( "Basic" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.Basic ; else if( tok.Equals( "Version" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.Version ; else if( tok.Equals( "Loggers" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.Loggers ; else if( tok.Equals( "Domains" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.Domains ; else if( tok.Equals( "InternalDomains" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.InternalDomains ; else if( tok.Equals( "ScopeDomains" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.ScopeDomains ; else if( tok.Equals( "DSR" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.DSR ; else if( tok.Equals( "PrefixLogables" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.PrefixLogables ; else if( tok.Equals( "Once" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.Once ; else if( tok.Equals( "LogData" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.LogData ; else if( tok.Equals( "ThreadMappings" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.ThreadMappings ; else if( tok.Equals( "SPTR" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.SPTR ; else if( tok.Equals( "All" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.All ; // domain and verbosity else if( tok.Consume( "domain", Case.Ignore, Whitespaces.Trim ) ) { if( tok.Consume( '=', Case.Sensitive, Whitespaces.Trim ) ) domain= tok.Trim().ToString(); } else if( tok.Consume( "verbosity", Case.Ignore, Whitespaces.Trim ) ) { if( tok.Consume( '=', Case.Sensitive, Whitespaces.Trim ) ) verbosity= ALox.ReadVerbosity( tok.Trim() ); } // unknown argument else { logInternal( Verbosity.Error, "VAR", intMsg._() ._( "Unknown argument '" )._(tok) ._( "' in variable " )._(variable.Fullname)._( " = \"")._(variable.GetString())._('\"') ); } } if ( flags != 0 ) { State( domain, verbosity, "Auto dump state on exit requested: ", (Lox.StateInfo) flags ); } }
/** **************************************************************************************** * Implements functionality for configuration variable \c LOXNAME_LOGGERNAME_VERBOSITY. * Is called when a logger is removed. * @param logger The logger to write the verbosity for. ******************************************************************************************/ protected void writeVerbositiesOnLoggerRemoval( Logger logger ) { // When writing back we will use this priority as the maximum to write. This way, if this was // an automatic default value, we will not write back into the user's variable store. // As always, only if the app fetches new variables on termination, this is entry is copied. Variable variable= new Variable( ALox.VERBOSITY, GetName(), logger.GetName() ); variable.Load(); // first token is "writeback" ? if ( variable.Size() == 0 ) return; Substring firstArg= new Substring( variable.GetString() ); if ( !firstArg.Consume( "writeback", Case.Ignore, Whitespaces.Trim ) ) return; // optionally read a destination variable name Substring destVarCategory = new Substring(); Substring destVarName = new Substring(); if( firstArg.Trim().IsNotEmpty() ) { // separate category from variable name int catSeparatorIdx= firstArg.IndexOf( '_' ); if (catSeparatorIdx >= 0 ) { destVarCategory.Set( firstArg, 0 , catSeparatorIdx ); destVarName .Set( firstArg, catSeparatorIdx + 1); } else destVarName.Set( firstArg ); if ( destVarName.IsEmpty() ) { logInternal( Verbosity.Error, "VAR", intMsg._() ._( "Argument 'writeback' in variable " ) ._( variable.Fullname) ._( "\n Error: Wrong destination variable name format\"" ) ._( firstArg )._( "\"" ) ); return; } } // either write directly into LOX_LOGGER_VERBOSITY variable... Variable destVar= null; if( destVarName.IsEmpty() ) { variable.ClearValues( 1 ); destVar= variable; } // ...or into a new given variable else { destVar= new Variable( destVarCategory, destVarName, ALox.VERBOSITY.Delim ); destVar.FormatHints= variable.FormatHints; destVar.FormatAttrAlignment= variable.FormatAttrAlignment; destVar.Comments._("Created at runtime through config option 'writeback' in variable \"")._( variable.Fullname )._("\"."); } // collect verbosities { int loggerNoMainDom= domains .GetLoggerNo( logger ); int loggerNoIntDom= internalDomains.GetLoggerNo( logger ); if ( loggerNoMainDom >= 0 ) verbositySettingToVariable( domains , loggerNoMainDom, destVar ); if ( loggerNoIntDom >= 0 ) verbositySettingToVariable( internalDomains, loggerNoIntDom , destVar ); } // now store using the same plug-in as original variable has destVar.Priority= variable.Priority; destVar.Store(); // internal logging intMsg._()._( "Argument 'writeback' in variable " )._( variable.Fullname ) ._( ":\n Verbosities for logger \"" ) ._( logger.GetName() ) ._( "\" written " ); if( destVarName.IsEmpty() ) intMsg._( "(to source variable)." ); else intMsg._( "to variable \"" ) ._( destVar.Fullname ) ._("\".") ; logInternal( Verbosity.Info, "VAR", intMsg._( destVarName )._( "\"." ) ); // verbose logging of the value written intMsg._()._(" Value:"); for( int i= 0; i< destVar.Size() ; i++ ) intMsg._( "\n " )._( destVar.GetString(i) ); logInternal( Verbosity.Verbose, "VAR", intMsg ); }
/** ************************************************************************************ * This method creates an adequate/default console logger. 'Adequate' here means that * this function tries to detect what might be the best choice for the environment * that the ALox based process is running in. * This method is due to changes with the evolution of future ALox versions and * should be considered as a convenience method to shorten the bootstrap code needed * to use ALox. * * The current C# implementation takes the following approach: * * - check if configuration variable * [ALOX_CONSOLE_TYPE](../group__GrpALoxConfigVars.html) is set. This variable's * setting takes priority and if set, the according logger is created. * - check whether a console window is attached to the current process. * If not, then a plain text logger is chosen (class * \ref cs::aworx::lox::loggers::ConsoleLogger "ConsoleLogger"). * - Otherwise, on Unix like OS, class * \ref cs::aworx::lox::loggers::AnsiConsoleLogger "AnsiConsoleLogger" is chosen, * while on windows systems class * \ref cs::aworx::lox::loggers::ColorConsoleLogger "ColorConsoleLogger" * takes preference. * * For further information check out the source code. * * @param name (Optional) The name of the \e Logger. * Defaults to null, which implies standard logger names defined * in the \e Logger sub-classes. * @return The \b TextLogger chosen. **************************************************************************************/ public static TextLogger CreateConsoleLogger( String name= null ) { #if ALOX_DBG_LOG || ALOX_REL_LOG //--- first: check environment "ALOX_DBG_CONSOLE_TYPE". They have precedence --- Variable variable= new Variable(ALox.CONSOLE_TYPE); variable.Load(); AString val= variable.GetString().Trim(); if ( val.IsEmpty() || val.Equals( "DEFAULT", Case.Ignore ) || val.Equals( "PLAIN", Case.Ignore ) ) return new ConsoleLogger ( name ); if( val.Equals( "ANSI", Case.Ignore ) ) return new AnsiConsoleLogger ( name ); if( val.Equals( "WINDOWS", Case.Ignore ) ) return new ColorConsoleLogger( name ); ALIB.WARNING( "Unrecognized value in config variable \"" + variable.Fullname + "\"= " + variable.GetString() ); //--- second: check debug environment // .... this is not implemented in C#, yet ... // not detected: in windows, we choose ColorConsoleLogger, in Unix ANSI if( ALIB.SysInfo_HasConsoleWindow ) return ALIB.SysInfo_IsWindowsOS() ? (TextLogger) new ColorConsoleLogger( name ) : (TextLogger) new AnsiConsoleLogger ( name ); // default return new ConsoleLogger( name ); #else return null; #endif }
/** **************************************************************************************** * Reads a prefix string from the ALib configuration system. * This internal method is used when a new domain is created, * * @param dom The domain to set the verbosity for. ******************************************************************************************/ protected void getDomainPrefixFromConfig( Domain dom ) { Variable variable= new Variable( ALox.PREFIXES, GetName() ); if( 0 == variable.Load() ) return; Tokenizer prefixTok= new Tokenizer(); Tokenizer prefixTokInner= new Tokenizer(); Substring domainStr= new Substring(); AString domainStrBuf= new AString(); Substring prefixStr= new Substring(); for( int varNo= 0; varNo< variable.Size(); varNo++ ) { prefixTok.Set( variable.GetString( varNo ), '=' ); domainStr.Set( prefixTok.Next() ); if ( domainStr.StartsWith( "INTERNAL_DOMAINS", DomainSensitivity ) ) { domainStrBuf._()._( domainStr.Buf, domainStr.Start + 16, domainStr.Length() -16 ); while ( domainStrBuf.CharAtStart() == '/' ) domainStrBuf.DeleteStart( 1 ); domainStrBuf.InsertAt( ALox.InternalDomains, 0 ); domainStr.Set( domainStrBuf ); } prefixTokInner.Set( prefixTok.Next(), ',' ); prefixStr.Set( prefixTokInner.Next() ); if ( prefixStr.IsEmpty() ) continue; if ( prefixStr.Consume( '\"' ) ) prefixStr.ConsumeFromEnd( '\"' ); Inclusion otherPLs= Inclusion.Include; prefixTokInner.Next(); if ( prefixTokInner.Actual.IsNotEmpty() ) otherPLs= ALIB.ReadInclusion( prefixTokInner.Actual ); int searchMode= 0; if ( domainStr.Consume ( '*' ) ) searchMode+= 2; if ( domainStr.ConsumeFromEnd( '*' ) ) searchMode+= 1; if( ( searchMode == 0 && dom.FullPath.Equals ( domainStr, DomainSensitivity ) ) || ( searchMode == 1 && dom.FullPath.StartsWith ( domainStr, DomainSensitivity ) ) || ( searchMode == 2 && dom.FullPath.EndsWith ( domainStr, DomainSensitivity ) ) || ( searchMode == 3 && dom.FullPath.IndexOf ( domainStr, 0, DomainSensitivity ) >=0 ) ) { dom.PrefixLogables.Add( new Domain.PL( new AString( prefixStr ), otherPLs ) ); // log info on this intMsg._()._NC( "String \"" )._NC( prefixStr )._NC ( "\" added as prefix logable for domain \'" ) ._NC( dom.FullPath ) ._NC( "\'. (Retrieved from variable" ) ._NC( variable.Fullname )._( ".)" ); logInternal( Verbosity.Info, "PFX", intMsg ); } } }
// ############################################################################################# // Constructors // ############################################################################################# /** **************************************************************************************** * Constructs a new, empty Lox with the given \p name. * The name is immutable and all \b %Lox objects registered with ALox must be unique. * The name \c "Log" is reserved for the internal default singleton used for debug-logging. * In addition, name \c "GLOBAL" is not allowed. * * If parameter \p register is \c true (the default), static method * \ref cs::aworx::lox::ALox::Register "ALox.Register" is invoked and the object will be * retrievable with static method * \ref cs::aworx::lox::ALox::Get "ALox.Get". In some situations, such 'registration' * may not be wanted. * @param name The name of the Lox. Will be converted to upper case. * @param doRegister If \c true, this object is registered with static class * \ref cs::aworx::lox::ALox "ALox". * Optional and defaults to \c true. ******************************************************************************************/ public Lox( String name, bool doRegister = true ) : base() { // set recursion warning of log buffer lock to 1. Warnings are logged if recursively // acquired more than once #if ALOX_DBG_LOG || ALOX_REL_LOG logBufLock.RecursionWarningThreshold= 1; scopeInfo= new ScopeInfo( name, threadDictionary ); scopeDomains= new ScopeStore<AString >( scopeInfo, false ); scopePrefixes= new ScopeStore<Object >( scopeInfo, false ); scopeLogData= new ScopeStore<Dictionary<AString, LogData>>( scopeInfo, true ); scopeLogOnce= new ScopeStore<Dictionary<AString, int[]> >( scopeInfo, true ); // create domain trees domains = new Domain( null, new AString( "") ); internalDomains = new Domain( null, new AString( ALox.InternalDomains, 0, ALox.InternalDomains.Length - 1) ); // create internal sub-domains bool wasCreated= false; String[] internalDomainList= {"LGR", "DMN", "PFX", "THR", "LGD", "VAR" }; foreach ( String it in internalDomainList ) { resDomainInternal._()._NC( it ); internalDomains.Find( resDomainInternal, Case.Sensitive, 1, ref wasCreated ); } maxDomainPathLength= ALox.InternalDomains.Length + 3; // register with ALox if ( doRegister ) ALox.Register( this, ContainerOp.Insert ); // read domain substitution rules from configuration Variable variable= new Variable( ALox.DOMAIN_SUBSTITUTION, GetName() ); if ( variable.Load() != 0 ) { for( int ruleNo= 0; ruleNo< variable.Size(); ruleNo++ ) { AString rule= variable.GetString( ruleNo ); int idx= rule.IndexOf( "->" ); if ( idx > 0 ) { String domainPath= rule.ToString( 0, idx ).Trim(); String replacement= rule.ToString( idx + 2 ).Trim(); SetDomainSubstitutionRule( domainPath, replacement ); } else { // using alib warning here as we can't do internal logging in the constructor ALIB.WARNING( "Syntax error in variable \"" + variable.Fullname + "\"." ); } } } #endif }