8#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
9# error "Symbol ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
48#if !ALIB_SINGLE_THREADED
49# define UNDEFINED_THREAD threads::UNDEFINED
51# define UNDEFINED_THREAD 0
59# include "ALib.Lang.CIFunctions.H"
64struct DomainSubstitutionRule
67 public:
enum class Type
83 DomainSubstitutionRule(
const NString& s,
const NString& r )
85 Search .DbgDisableBufferReplacementWarning();
86 Replacement.DbgDisableBufferReplacementWarning();
91 if ( s.CharAtStart() ==
'*' )
95 if ( s.CharAtEnd() ==
'*' )
97 type= Type::Substring;
101 type= Type::EndsWith;
105 if ( s.CharAtEnd() ==
'*' )
107 type= Type::StartsWith;
113 Search._( s, startPos, length );
116 if ( ( ( type == Type::Exact
117 || type == Type::StartsWith )
118 &&
Search.CharAtStart() !=
'/'
120 || ( type == Type::EndsWith
121 &&
Search.CharAtEnd() ==
'/'
145 monomem::Snapshot beforeLox;
147 #if !ALIB_SINGLE_THREADED
149 threads::RecursiveLock
Lock;
153 int AcquirementsCount;
160 StdVectorMono<BoxesMA*> logableContainers;
163 StdVectorMono<BoxesMA*> internalLogables;
166 integer internalLogRecursionCounter = 0;
177 Domain* internalDomains;
180 ScopeStore<NString , true > scopeDomains;
183 ScopeStore<PrefixLogable*, true > scopePrefixes;
186 ScopeStore<SSMap<int>* ,
false> scopeLogOnce;
189 ScopeStore<SSMap<Box>* ,
false> scopeLogData;
192 integer maxLoggerNameLength =0;
198 const NString noKeyHashKey =
"$";
203 DomainSubstitutionRule> domainSubstitutions;
206 bool oneTimeWarningCircularDS =
false;
209 bool loggerAddedSinceLastDebugState =
false;
215 LoxImpl( MonoAllocator* ma,
const NString& name )
216 : monoAllocator ( *ma )
217 , poolAllocator ( monoAllocator )
218 , AcquirementsCount ( 0 )
219 , logableContainers ( monoAllocator )
220 , internalLogables ( monoAllocator )
221 , scopeInfo ( name , monoAllocator )
222 , scopeDomains ( scopeInfo, monoAllocator )
223 , scopePrefixes ( scopeInfo, monoAllocator )
224 , scopeLogOnce ( scopeInfo, monoAllocator )
225 , scopeLogData ( scopeInfo, monoAllocator )
226 , domainSubstitutions( monoAllocator )
236 for (
int i= domains->CountLoggers() - 1 ; i >= 0 ; --i )
238 Logger* logger= domains->GetLogger( i );
239 int ii= internalDomains->GetLoggerNo( logger );
241 internalDomains->RemoveLogger( ii );
242 logger->AcknowledgeLox( this, lang::ContainerOp::Remove );
246 for (
int i= internalDomains->CountLoggers() - 1 ; i >= 0 ; --i )
248 Logger* logger= internalDomains->GetLogger( i );
249 logger->AcknowledgeLox( this, lang::ContainerOp::Remove );
258 int CountAcquirements() const noexcept {
return AcquirementsCount; }
266 template<
typename T,
typename... TArgs>
267 T* newPO(TArgs&&... args) {
return poolAllocator().New<T>(std::forward<TArgs>(args)...); }
273 void deletePO(T* o) { poolAllocator().Delete<T>(o); }
278#define ASSERT_ACQUIRED ALIB_ASSERT_ERROR( impl->CountAcquirements() >0,"ALOX","Lox not acquired" )
283LoxImpl* LI::Construct(
const NString& name)
285 lang::HeapAllocator ha;
288 auto snapShot= selfContainedMA->TakeSnapshot();
289 LoxImpl* result= (*selfContainedMA)().New<LoxImpl>( selfContainedMA, name );
290 result->beforeLox= snapShot;
294void LI::Destruct( LoxImpl* impl )
296 auto& ma= impl->monoAllocator;
301const NString& LI::GetName(LoxImpl* impl)
303 return impl->scopeInfo.loxName;
306integer& LI::GetLogCounter(LoxImpl* impl)
308 return impl->CntLogCalls;
311#if !ALIB_SINGLE_THREADED
314 ALIB_DBG( assert::SingleThreaded(); )
319void LI::Acquire(LoxImpl* impl,
const lang::CallerInfo& ci )
321 #if !ALIB_SINGLE_THREADED
323 , impl->Lock.AcquireRecursive(ci); )
325 ALIB_DBG( assert::SingleThreaded());
327 ++impl->AcquirementsCount;
328 impl->scopeInfo.Set( ci );
331void LI::Release(LoxImpl* impl)
333 impl->scopeInfo.PopNestedScope();
334 --impl->AcquirementsCount;
335 #if !ALIB_SINGLE_THREADED
340void LI::init(LoxImpl* impl)
342 impl->logableContainers.reserve(5);
345 impl->domains = impl->monoAllocator().New<Domain>(impl->monoAllocator, impl->poolAllocator,
"" );
346 impl->internalDomains= impl->monoAllocator().New<Domain>(impl->monoAllocator, impl->poolAllocator,
"$" );
349 const NString internalDomainList[]= {
"LGR",
"DMN",
"PFX",
"THR",
"LGD",
"VAR" };
350 for (
auto& it : internalDomainList )
351 impl->internalDomains->Find( it, 1,
nullptr );
352 impl->maxDomainPathLength= Lox::InternalDomains.Length() + 3;
355 Variable var= variables::CampVariable(ALOX);
358 var.Declare( Variables::DOMAIN_SUBSTITUTION,
359 #if !ALIB_CHARACTERS_WIDE
366 if ( var.IsDefined() )
368 for(
int ruleNo= 0 ; ruleNo < var.Size() ; ++ruleNo )
371 if( rule.Trim().IsEmpty() )
377 NString64 domainPath ( rule.Substring<NC>( 0, idx ) ); domainPath .Trim();
378 NString64 replacement( rule.Substring<NC>( idx + 2, rule.Length() - idx - 2 ) ); replacement.Trim();
379 SetDomainSubstitutionRule( impl, domainPath, replacement );
384 ALIB_WARNING(
"ALOX",
"Syntax error in variable \"{}\".", var )
391void LI::Reset(LoxImpl* impl)
394 if( impl == Log::Get()->impl && Log::DebugLogger !=
nullptr )
397 Log::RemoveDebugLogger( Log::Get() );
403 SetSourcePathTrimRule( impl,
nullptr, lang::Inclusion::Include,
405 lang::Case::Ignore, NULL_NSTRING, lang::Reach::Global, Priority::NONE );
409 auto snapshot = impl->beforeLox;
411 (*loxMA)().Delete(impl);
412 loxMA->Reset(snapshot);
414 (*loxMA)().New<LoxImpl>(loxMA, name );
416 ALIB_ASSERT_ERROR( impl == dbgNewAddress,
"ALOX",
"Internal error. This must never happen." )
417 impl->beforeLox= snapshot;
420void LI::SetFileNameCacheCapacity( LoxImpl* impl, integer numberOfLists, integer entriesPerList )
422 impl->scopeInfo.SetFileNameCacheCapacity( numberOfLists, entriesPerList );
426MonoAllocator& LI::DbgGetMonoAllocator( LoxImpl* impl ) {
return impl->monoAllocator; }
429void LI::SetSourcePathTrimRule( LoxImpl* impl,
430 const NCString& path,
431 lang::Inclusion includeString ,
433 lang::Case sensitivity ,
434 const NString& trimReplacement,
439 impl->scopeInfo.SetSourcePathTrimRule( path, includeString, trimOffset, sensitivity,
440 trimReplacement, reach, priority );
443void LI::SetDomain( LoxImpl* impl,
const NString& scopeDomain, Scope scope, threads::Thread* thread )
445 if ( !isThreadRelatedScope( impl, scope ) )
447 setDomain( impl, scopeDomain, scope,
false, thread );
453Logger* LI::GetLogger(LoxImpl* impl,
const NString& loggerName )
459 if ( (logger= impl->domains ->GetLogger( loggerName ) ) !=
nullptr )
return logger;
460 if ( (logger= impl->internalDomains->GetLogger( loggerName ) ) !=
nullptr )
return logger;
463 BoxesMA& logables= acquireInternalLogables(impl);
464 logables.Add(
"No logger named {!Q} found.", loggerName );
465 logInternal( impl, Verbosity::Warning,
"LGR", logables );
471void writeVerbVarRecursive( Domain& domain,
int loggerNo, CVVerbosities& verbosities,
472 Verbosity parentVerbosity )
474 auto verbosity= domain.GetVerbosity( loggerNo );
475 if( parentVerbosity != verbosity || verbosities.ExportAll )
476 verbosities.Add(
String256(domain.FullPath) <<
'=' << verbosity );
479 for ( Domain& subDomain : domain.SubDomains )
480 writeVerbVarRecursive( subDomain, loggerNo, verbosities, verbosity );
485void LI::writeVerbositiesOnLoggerRemoval( LoxImpl* impl, Logger* logger )
487DOX_MARKER([DOX_VARIABLES_REPLACEMENTS2])
488Variable var= variables::CampVariable(ALOX);
498 var.Declare( Variables::VERBOSITY, replacements );
500DOX_MARKER( [DOX_VARIABLES_REPLACEMENTS2])
503 auto& cvVerb= var.Get<CVVerbosities>();
508 int loggerNoMainDom= impl->domains ->GetLoggerNo( logger );
509 int loggerNoIntDom= impl->internalDomains->GetLoggerNo( logger );
511 if ( loggerNoMainDom >= 0 ) writeVerbVarRecursive( *impl->domains , loggerNoMainDom, cvVerb,
Verbosity(-1) );
512 if ( loggerNoIntDom >= 0 ) writeVerbVarRecursive( *impl->internalDomains, loggerNoIntDom , cvVerb,
Verbosity(-1) );
522 BoxesMA& logables= acquireInternalLogables(impl);
523 logables.Add(
"Verbosities for logger {!Q} written to variable {!Q}",
524 logger->GetName(), varName );
525 logInternal( impl, Verbosity::Info,
"VAR", logables );
530 BoxesMA& logables= acquireInternalLogables(impl);
531 logables.Add(
" Value:");
532 for(
auto& it : cvVerb )
533 logables.Add(
"\n ", it );
534 logInternal( impl, Verbosity::Verbose,
"VAR", logables );
538void LI::dumpStateOnLoggerRemoval(LoxImpl* impl)
540 if( !impl->loggerAddedSinceLastDebugState )
542 impl->loggerAddedSinceLastDebugState=
false;
545 Variable variable= variables::CampVariable(ALOX, Variables::DUMP_STATE_ON_EXIT,
552 if( !variable.IsDefined() )
560 tknzr.
Set(variable,
',',
true);
561 while( tknzr.HasNext() )
566 if( tok.IndexOf(
'=' ) > 0 )
568 if( tok.ConsumePartOf<lang::Case::Ignore, lang::Whitespaces::Trim>(
A_CHAR(
"verbosity"), 1) )
570 if( tok.ConsumeChar<lang::Case::Sensitive, lang::Whitespaces::Trim>(
'=' ) )
571 enumrecords::Parse<Verbosity>( tok, verbosity );
574 if( tok.ConsumePartOf<lang::Case::Ignore, lang::Whitespaces::Trim>(
A_CHAR(
"domain"), 1) )
576 if( tok.ConsumeChar<lang::Case::Sensitive, lang::Whitespaces::Trim>(
'=' ) )
586 if( !enumrecords::Parse<StateInfo>( tok, stateInfo ) )
593 if( stateInfo == StateInfo::NONE )
594 flags= StateInfo::NONE;
600 BoxesMA& logables= acquireInternalLogables(impl);
601 logables.Add(
"Unknown argument {!Q} in variable {} = {!Q}.",
602 tok, variable, variable.GetString() );
603 logInternal( impl, Verbosity::Error,
"VAR", logables);
606 if ( flags != StateInfo::NONE )
608 State( impl, domain, verbosity,
A_CHAR(
"Auto dump state on exit requested: "), flags );
613bool LI::RemoveLogger( LoxImpl* impl, Logger* logger )
617 int noMainDom= impl->domains ->GetLoggerNo( logger );
618 int noIntDom= impl->internalDomains->GetLoggerNo( logger );
620 if( noMainDom >= 0 || noIntDom >= 0 )
622 dumpStateOnLoggerRemoval(impl);
623 writeVerbositiesOnLoggerRemoval( impl, logger );
626 impl->domains->RemoveLogger( noMainDom );
629 impl->internalDomains->RemoveLogger( noIntDom );
631 logger->AcknowledgeLox( impl, lang::ContainerOp::Remove );
637 BoxesMA& logables= acquireInternalLogables(impl);
638 logables.Add(
"Logger {!Q} not found. Nothing removed.", logger );
639 logInternal( impl, Verbosity::Warning,
"LGR", logables );
643Logger* LI::RemoveLogger(LoxImpl* impl,
const NString& loggerName )
647 int noMainDom= impl->domains ->GetLoggerNo( loggerName );
648 int noIntDom= impl->internalDomains->GetLoggerNo( loggerName );
650 if( noMainDom >= 0 || noIntDom >= 0 )
652 Logger* logger= impl->domains->GetLogger( noMainDom );
653 if( logger ==
nullptr ) logger= impl->internalDomains->GetLogger( noIntDom );
655 dumpStateOnLoggerRemoval(impl);
656 writeVerbositiesOnLoggerRemoval( impl, logger );
659 impl->domains->RemoveLogger( noMainDom );
662 impl->internalDomains->RemoveLogger( noIntDom );
664 logger->AcknowledgeLox( impl, lang::ContainerOp::Remove );
666 BoxesMA& logables= acquireInternalLogables(impl);
667 logables.Add(
"Logger {!Q} removed.", logger );
668 logInternal( impl, Verbosity::Info,
"LGR", logables );
673 BoxesMA& logables= acquireInternalLogables(impl);
674 logables.Add(
"Logger {!Q} not found. Nothing removed.", loggerName );
675 logInternal( impl, Verbosity::Warning,
"LGR", logables );
680void LI::SetVerbosity(LoxImpl* impl, Logger* logger, Verbosity verbosity,
const NString& domain, Priority priority )
684 if ( logger ==
nullptr )
686 BoxesMA& logables= acquireInternalLogables(impl);
687 logables.Add(
"Given Logger is \"null\". Verbosity not set." );
688 logInternal( impl, Verbosity::Error,
"LGR", logables );
694 Domain* dom= evaluateResultDomain( impl, domain );
697 bool isNewLogger=
false;
698 int no= dom->GetLoggerNo( logger );
701 no= dom->AddLogger( logger );
706 logInternal( impl, Verbosity::Error,
"LGR", acquireInternalLogables(impl)
707 .
Add(
"Unable to add logger {!Q}. Logger with same name exists.", logger ) );
710 logInternal( impl, Verbosity::Verbose,
"LGR",
711 acquireInternalLogables(impl).
Add(
712 " Request was: SetVerbosity({!Q}, {!Q}, Verbosity::{}, {}). ",
713 logger, dom->FullPath, verbosity, priority ) );
715 Logger* existingLogger= dom->GetLogger( logger->GetName() );
716 logInternal( impl, Verbosity::Verbose,
"LGR", acquireInternalLogables(impl)
717 .
Add(
" Existing Logger: {!Q}.", existingLogger ) );
724 if ( ( dom->GetRoot() == impl->domains ? impl->internalDomains->GetLoggerNo( logger )
725 : impl->domains->GetLoggerNo( logger )
728 logger->AcknowledgeLox( impl, lang::ContainerOp::Insert );
732 if ( impl->maxLoggerNameLength < logger->GetName().Length() )
733 impl->maxLoggerNameLength= logger->GetName().Length();
740 impl->loggerAddedSinceLastDebugState=
true;
746 BoxesMA& logables= acquireInternalLogables(impl);
747 logables.Add(
"Logger {!Q}.", logger );
748 if( domain.StartsWith(Lox::InternalDomains) )
749 logables.Add(
" added for internal log messages.");
751 logables.Add(
" added.");
752 logInternal( impl, Verbosity::Info,
"LGR", logables );
755 Box replacements[2]= { GetName( impl ), logger->GetName() };
756 Variable varVerbosities= variables::CampVariable(ALOX, Variables::VERBOSITY, replacements );
757 if( varVerbosities.IsDefined() )
759 getAllVerbosities( impl, varVerbosities, logger, *impl->domains );
760 getAllVerbosities( impl, varVerbosities, logger, *impl->internalDomains );
765 dom->SetVerbosity( no, verbosity, priority );
767 BoxesMA& logables= acquireInternalLogables(impl);
769 logables.Add(
"Logger {!Q}: {!Fill}{!Q'}{!Fill}= Verbosity::{}.",
771 impl->maxLoggerNameLength - logger->GetName().Length(),
773 impl->maxDomainPathLength - dom->FullPath.Length() + 1,
774 boxing::MakePair(verbosity, priority) );
776 Verbosity actVerbosity= dom->GetVerbosity( no );
777 if( actVerbosity != verbosity )
778 logables.Add(
" Lower priority ({} < {}). Remains {}.",
779 priority, dom->GetPriority(no), actVerbosity );
781 logInternal( impl, Verbosity::Info,
"LGR", logables );
784void LI::SetVerbosity(LoxImpl* impl,
const NString& loggerName, Verbosity verbosity,
const NString& domain, Priority priority )
791 Domain* dom= evaluateResultDomain( impl, domain );
793 int no= dom->GetLoggerNo( loggerName );
795 logger= dom->GetLogger( no );
799 Domain* otherTree= dom->GetRoot() == impl->domains ? impl->internalDomains
801 no= otherTree->GetLoggerNo( loggerName );
805 BoxesMA& logables= acquireInternalLogables(impl);
806 logables.Add(
"Logger not found. Request was: SetVerbosity({!Q}, {!Q}, Verbosity::{}, {}).",
807 loggerName, dom->FullPath, verbosity, priority );
808 logInternal( impl, Verbosity::Warning,
"LGR", logables );
812 logger= otherTree->GetLogger( no );
816 SetVerbosity( impl, logger, verbosity, domain, priority );
819void LI::setDomain( LoxImpl* impl,
820 const NString& scopeDomain, Scope scope,
821 bool removeNTRSD, threads::Thread* thread )
829 int pathLevel= checkScopeInformation( impl, scope,
"DMN" );
833 #if !ALIB_SINGLE_THREADED
834 ThreadID threadID= thread !=
nullptr ? thread->GetID() : UNDEFINED_THREAD;
836 threads::ThreadID threadID= UNDEFINED_THREAD;
842 impl->scopeDomains.InitAccess( scope, pathLevel, threadID );
845 previousScopeDomain= impl->scopeDomains.Remove( scopeDomain );
849 if ( scopeDomain.IsNotEmpty() )
852 previousScopeDomain= impl->scopeDomains.Store(
NString(impl->poolAllocator, trimmable.Trim() ) );
855 previousScopeDomain= impl->scopeDomains.Remove(
nullptr );
859 BoxesMA& logables= acquireInternalLogables(impl);
860 if ( !removeNTRSD && scopeDomain.IsNotEmpty() )
862 logables.Add(
"{!Q'} set as default for {}.", scopeDomain, (scope + pathLevel) );
864 if ( previousScopeDomain.IsNull() )
865 logInternal( impl, Verbosity::Info,
"DMN", logables );
868 if ( previousScopeDomain.Equals<NC>( scopeDomain ) )
870 logables.Add(
" (Was already set.)" );
871 logInternal( impl, Verbosity::Verbose,
"DMN", logables );
875 logables.Add(
" Replacing previous default {!Q'}.", previousScopeDomain );
876 logInternal( impl, Verbosity::Warning,
"DMN", logables );
883 if ( previousScopeDomain.IsNotNull() )
885 logables.Add(
"{!Q'} removed from {}.", previousScopeDomain, (scope + pathLevel) );
886 logInternal( impl, Verbosity::Info,
"DMN", logables );
891 logables.Add(
"{!Q'} not found. Nothing removed for {}.", scopeDomain );
893 logables.Add(
"Empty Scope Domain given, nothing registered for {}.", scopeDomain);
895 logables.Add( scope + pathLevel);
896 logInternal( impl, Verbosity::Warning,
"DMN", logables );
901 if ( previousScopeDomain.IsNotNull() )
902 previousScopeDomain.Free(impl->poolAllocator);
905void LI::RemoveThreadDomain(LoxImpl* impl,
const NString& scopeDomain, Scope scope, threads::Thread* thread )
907 if ( !isThreadRelatedScope( impl, scope ) )
911 if ( scopeDomain.IsEmpty() )
913 BoxesMA& logables= acquireInternalLogables(impl);
914 logables.Add(
"Illegal parameter. No scope domain path given. Nothing removed for {}.",
916 logInternal( impl, Verbosity::Warning,
"DMN", logables );
923 setDomain( impl, scopeDomain, scope,
true, thread);
926void LI::SetDomainSubstitutionRule(LoxImpl* impl,
const NString& domainPath,
const NString& replacement )
929 if ( domainPath.IsEmpty() )
931 impl->oneTimeWarningCircularDS=
false;
932 impl->domainSubstitutions.Clear();
933 logInternal( impl, Verbosity::Info,
"DMN",
"Domain substitution rules removed.");
939 DomainSubstitutionRule newRule( domainPath, replacement );
940 if ( newRule.Search.IsEmpty() )
942 logInternal( impl, Verbosity::Warning,
"DMN",
"Illegal domain substitution rule. Nothing stored." );
947 List<MonoAllocator, DomainSubstitutionRule>::iterator it;
948 for( it= impl->domainSubstitutions.begin(); it != impl->domainSubstitutions.end() ; ++it )
950 if ( (*it).type == newRule.type
951 && (*it).Search.Equals<NC>( newRule.Search ) )
956 if ( replacement.IsEmpty() )
958 BoxesMA& logables= acquireInternalLogables(impl);
959 if ( it == impl->domainSubstitutions.end() )
961 logables.Add(
"Domain substitution rule {!Q} not found. Nothing to remove.", domainPath );
962 logInternal( impl, Verbosity::Warning,
"DMN", logables );
966 logables.Add(
"Domain substitution rule {!Q} -> {!Q} removed.", domainPath, (*it).Replacement );
967 logInternal( impl, Verbosity::Info,
"DMN", logables );
968 (void) impl->domainSubstitutions.erase( it );
972 BoxesMA& logables= acquireInternalLogables(impl);
973 logables.Add(
"Domain substitution rule {!Q} -> {!Q} set.", domainPath, newRule.Replacement );
977 if ( it != impl->domainSubstitutions.end() )
979 msg <<
" Replacing previous -> \"" << (*it).Replacement <<
"\".";
981 (*it).Replacement.Reset( newRule.Replacement );
984 impl->domainSubstitutions.emplace_back( newRule );
987 logInternal( impl, Verbosity::Info,
"DMN", logables );
990void LI::setPrefix(LoxImpl* impl,
const Box& prefix, Scope scope, threads::Thread* thread )
995 int pathLevel= checkScopeInformation( impl, scope,
"PFX" );
999 #if !ALIB_SINGLE_THREADED
1000 ThreadID threadID= thread !=
nullptr ? thread->GetID() : UNDEFINED_THREAD;
1002 threads::ThreadID threadID= UNDEFINED_THREAD;
1006 impl->scopePrefixes.InitAccess( scope, pathLevel, threadID );
1007 bool isVoidOrEmpty= prefix.IsType<
void>()
1009 || ( prefix.IsArray() && !prefix.UnboxLength() );
1011 Box* previousLogable= !isVoidOrEmpty ? impl->scopePrefixes.Store( impl->newPO<PrefixLogable>( impl->poolAllocator, prefix ) )
1012 : impl->scopePrefixes.Remove(
nullptr );
1015 BoxesMA& logables= acquireInternalLogables(impl);
1016 logables.Add(
"Object ");
1017 Verbosity intMsgVerbosity= Verbosity::Info;
1018 if ( !isVoidOrEmpty )
1020 logables.Add( prefix,
" added as prefix logable for {}.", (scope + pathLevel) );
1022 if ( previousLogable !=
nullptr )
1024 if ( previousLogable->Call<FEquals>( prefix ) )
1026 logables.Add(
" (Same as before.)");
1027 intMsgVerbosity= Verbosity::Verbose;
1030 logables.Add(
" Replacing previous {}.", *previousLogable );
1035 if ( previousLogable !=
nullptr )
1036 logables.Add(
"{!Q} removed from list of prefix logables for {}.", *previousLogable);
1039 logables.Add(
"<nullptr> given but no prefix logable to remove for {}.");
1040 intMsgVerbosity= Verbosity::Warning;
1042 logables.Add( scope + pathLevel );
1045 logInternal( impl, intMsgVerbosity,
"PFX", logables );
1048 if ( previousLogable !=
nullptr )
1049 impl->deletePO(
static_cast<PrefixLogable*
>( previousLogable ));
1053void LI::SetPrefix(LoxImpl* impl,
const Box& prefix,
const NString& domain, lang::Inclusion otherPLs )
1058 Domain* dom= evaluateResultDomain( impl, domain );
1060 bool isVoidOrEmpty= prefix.IsType<
void>()
1062 || ( prefix.IsArray() && !prefix.UnboxLength() );
1064 BoxesMA& logables= acquireInternalLogables(impl);
1065 Verbosity intLogVerbosity= Verbosity::Info;
1066 PrefixLogable* removedLogable=
nullptr;
1068 if ( !isVoidOrEmpty )
1071 logables.Add(
"Object {} added as prefix logable for ", prefix );
1073 dom->PrefixLogables.emplace_back( impl->newPO<PrefixLogable>( impl->poolAllocator, prefix ), otherPLs );
1077 auto cntPLs= dom->PrefixLogables.size();
1080 removedLogable= dom->PrefixLogables.back().first;
1081 dom->PrefixLogables.pop_back();
1082 logables.Add(
"Object {} removed from list of prefix logables for",
1083 *
static_cast<Box*
>(removedLogable) );
1087 logables.Add(
"No prefix logables to remove for" );
1088 intLogVerbosity= Verbosity::Warning;
1092 logables.Add(
" domain {!Q'}.", dom->FullPath);
1093 logInternal( impl, intLogVerbosity,
"PFX", logables );
1095 if( removedLogable )
1096 impl->deletePO(removedLogable);
1100#if defined (__GLIBCXX__) || defined(_LIBCPP_VERSION) || defined(__APPLE__) || defined(__ANDROID_NDK__)
1101 void LI::SetStartTime(LoxImpl* impl, time_t startTime,
const NString& loggerName )
1104 SetStartTime( impl, converter.ToTicks( DateTime::FromEpochSeconds( startTime ) ), loggerName );
1107#elif defined( _WIN32 )
1108 void LI::SetStartTime(LoxImpl* impl,
const FILETIME& startTime,
const NString& loggerName )
1111 SetStartTime( impl, converter.ToTicks( DateTime::FromFileTime( startTime ) ), loggerName );
1114 #pragma message "Unknown Platform in file: " __FILE__ )
1117void LI::SetStartTime(LoxImpl* impl, Ticks startTime,
const NString& loggerName )
1121 bool foundOne=
false;
1122 for(
int loggerNo= 0; loggerNo < impl->domains->CountLoggers(); ++loggerNo )
1125 Logger* logger= impl->domains->GetLogger( loggerNo );
1126 if( loggerName.IsNotEmpty() && !loggerName.Equals<NC, lang::Case::Ignore>( logger->GetName()) )
1131 BoxesMA& logables= acquireInternalLogables(impl);
1132 logables.Add(
"Logger {!Q}: Start time set to ", logger->GetName() );
1133 if ( !startTime.IsSet() )
1135 startTime= Ticks::Now();
1136 logables.Add(
"'now'" );
1142 if( asTextLogger !=
nullptr )
1146 logables.Add(
"{:yyyy-MM-dd HH:mm:ss}", asDateTime );
1149 logger->TimeOfCreation.SetAs( startTime );
1150 logger->TimeOfLastLog .SetAs( startTime );
1152 logInternal( impl, Verbosity::Info,
"LGR", logables );
1155 if ( loggerName.IsNotEmpty() && !foundOne )
1157 BoxesMA& logables= acquireInternalLogables(impl);
1158 logables.Add(
"Logger {!Q}: not found. Start time not set.", loggerName );
1159 logInternal( impl, Verbosity::Error,
"LGR", logables );
1165void LI::MapThreadName(LoxImpl* impl,
const String& threadName, threads::ThreadID
id )
1167 #if !ALIB_SINGLE_THREADED
1175 Thread* t= Thread::GetCurrent();
1177 origThreadName= t->GetName();
1180 origThreadName=
nullptr;
1183 impl->scopeInfo.threadDictionary.EmplaceOrAssign(
id, threadName);
1186 BoxesMA& logables= acquireInternalLogables(impl);
1187 logables.Add(
"Mapped thread ID {} to {!Q}.",
id, threadName);
1188 if ( origThreadName.IsNotEmpty() )
1189 logables.Add(
" Original thread name: {!Q}.", origThreadName );
1190 logInternal( impl, Verbosity::Info,
"THR", logables );
1198void LI::once( LoxImpl* impl,
1199 const NString& domain, Verbosity verbosity,
1201 const String& pGroup,
1205 int pathLevel= checkScopeInformation( impl, scope,
"DMN" );
1211 bool groupWasEmtpy= group.IsEmpty();
1212 if ( groupWasEmtpy )
1215 if ( scope == Scope::Global )
1217 scope= Scope::Filename;
1218 group._(
'#')._( impl->scopeInfo.GetLineNumber() );
1224 group._( impl->noKeyHashKey );
1229 impl->scopeLogOnce.InitAccess( scope, pathLevel, UNDEFINED_THREAD );
1231 SSMap<int>* map= impl->scopeLogOnce.Get();
1232 if( map ==
nullptr )
1234 map= impl->newPO<SSMap<int>>(impl->poolAllocator);
1235 impl->scopeLogOnce.Store( map );
1239 auto it= map->Find( group );
1240 if (it == map->end() )
1241 it= map->InsertUnique( std::make_pair(
NString(impl->poolAllocator, group), 0) );
1244 if ( quantity >= 0 )
1246 if ( it->second < quantity )
1251 GetLogableContainer(impl) .Add( std::forward<const Box&>( logable ) );
1252 Entry( impl, domain, verbosity );
1255 if( it->second == quantity )
1257 BoxesMA& logables= acquireInternalLogables(impl);
1258 logables.Add(
"Once() reached limit of {} logs. No further logs for ", quantity );
1260 if ( groupWasEmtpy )
1261 logables.Add( scope == Scope::Global ?
Box(
"this line" )
1262 :
Box(scope + pathLevel) );
1265 logables.Add(
"group {!Q}", group );
1266 if ( scope != Scope::Global )
1267 logables.Add(
" in ", (scope + pathLevel) );
1271 logInternal( impl, Verbosity::Info,
"", logables );
1279 if ( it->second++ % -quantity == 0 )
1281 GetLogableContainer(impl) .Add( std::forward<const Box&>( logable ) );
1282 Entry( impl, domain, verbosity );
1287void LI::store( LoxImpl* impl,
const Box& data,
const NString& pKey, Scope scope )
1292 bool keyWasEmtpy= key.IsEmpty();
1294 key= impl->noKeyHashKey;
1298 if ( scope > Scope::Path )
1300 pathLevel= int( scope - Scope::Path );
1305 impl->scopeLogData.InitAccess( scope, pathLevel, UNDEFINED_THREAD );
1306 SSMap<Box>* map= impl->scopeLogData.Get();
1307 if( map ==
nullptr )
1309 map= impl->newPO<SSMap<Box>>(impl->poolAllocator);
1310 impl->scopeLogData.Store( map );
1313 BoxesMA& logables= acquireInternalLogables(impl);
1316 auto it= map->Find( key );
1317 if ( !data.IsType<
void>() )
1319 bool replacedPrevious=
false;
1320 if ( it == map->end() )
1321 map->InsertUnique( std::make_pair(
NString(impl->poolAllocator, key), data ) );
1324 replacedPrevious=
true;
1329 logables.Add(
"Stored data " );
1332 logables.Add(
" with key {!Q} ", key );
1333 logables.Add(
"in {}.", (scope + pathLevel) );
1334 if ( replacedPrevious )
1335 logables.Add(
" (Replaced and deleted previous.)" );
1341 if ( it != map->end() )
1343 auto keyString= it->first;
1345 if ( map->Size() == 0 )
1347 impl->deletePO(map);
1348 impl->scopeLogData.Remove(
nullptr );
1350 keyString.Free(impl->poolAllocator);
1351 logables.Add(
"Deleted map data " );
1354 logables.Add(
"No map data found to delete " );
1357 logables.Add(
" with key {!Q} ", key );
1358 logables.Add(
"in {}.", (scope + pathLevel) );
1361 LI::logInternal( impl, Verbosity::Info,
"LGD", logables );
1365Box LI::retrieve( LoxImpl* impl,
const NString& pKey, Scope scope )
1370 bool keyWasEmtpy= key.IsEmpty();
1372 key= impl->noKeyHashKey;
1375 if ( scope > Scope::Path )
1377 pathLevel= int( scope - Scope::Path );
1382 impl->scopeLogData.InitAccess( scope, pathLevel, UNDEFINED_THREAD );
1384 SSMap<Box>* map= impl->scopeLogData.Get();
1385 if( map !=
nullptr )
1387 auto it= map->Find( key );
1388 if ( it != map->end() )
1389 returnValue= it->second;
1392 if ( returnValue.IsType<
void>() )
1393 store( impl,
Box(), pKey, scope + pathLevel );
1396 BoxesMA& logables= acquireInternalLogables(impl);
1397 logables.Add(
"Data " );
1400 logables.Add(
" with key {!Q} ", key );
1401 logables.Add(
"in ", (scope + pathLevel), ( !returnValue.IsType<
void>() ?
" received."
1402 :
" not found." ) );
1404 logInternal( impl, Verbosity::Info,
"LGD", logables );
1409void LI::State( LoxImpl* impl,
1410 const NString& domain,
1411 Verbosity verbosity,
1412 const String& headLine,
1419 if ( headLine.IsNotEmpty() )
1420 buf._<NC>( headLine ).NewLine();
1422 GetState( impl, buf, flags );
1424 GetLogableContainer(impl) .Add( buf );
1425 Entry( impl, domain, verbosity );
1428BoxesMA& LI::GetLogableContainer(LoxImpl* impl)
1430 auto cntAcquirements= impl->CountAcquirements();
1433 while(
int(impl->logableContainers.size()) < cntAcquirements )
1434 impl->logableContainers.emplace_back( impl->monoAllocator().New<BoxesMA>(impl->monoAllocator) );
1435 BoxesMA& logables= *impl->logableContainers[
size_t(cntAcquirements - 1)];
1440void LI::Entry(LoxImpl* impl, const NString& domain, Verbosity verbosity )
1446 if( impl == Log::Get()->impl
1447 && impl->domains->CountLoggers() == 0
1448 && Log::DebugLogger ==
nullptr )
1449 Log::AddDebugLogger( Log::Get() );
1454 ++impl->CntLogCalls;
1456 if ( impl->domains->CountLoggers() == 0 )
1460 evaluateResultDomain( impl, domain ),
1462 *impl->logableContainers[
size_t(impl->CountAcquirements() - 1)],
1463 lang::Inclusion::Include );
1466int LI::IsActive( LoxImpl* impl, Verbosity verbosity,
const NString& domain )
1472 if( impl == Log::Get()->impl
1473 && impl->domains->CountLoggers() == 0
1474 && Log::DebugLogger ==
nullptr )
1475 Log::AddDebugLogger( Log::Get() );
1480 if ( impl->domains->CountLoggers() == 0 )
1483 Domain* dom= evaluateResultDomain( impl, domain );
1486 for (
int i= 0; i < dom->CountLoggers() ; ++i )
1487 if( dom->IsActive( i, verbosity ) )
1492void LI::IncreaseLogCounter( LoxImpl* impl)
1494 ++impl->CntLogCalls;
1497void LI::entryDetectDomainImpl(LoxImpl* impl, Verbosity verbosity )
1499 BoxesMA& logables= *impl->logableContainers[size_t(impl->CountAcquirements() - 1)];
1500 if ( logables.Size() > 1 && logables[0].IsArrayOf<nchar>() )
1506 if( firstArg.StartsWith( Lox::InternalDomains ) )
1507 idx+= Lox::InternalDomains.Length();
1510 bool illegalCharacterFound=
false;
1511 for( ; idx< firstArg.Length() ; ++idx )
1513 char c= firstArg[idx];
1514 if (! ( isdigit( c )
1515 || ( c >=
'A' && c <=
'Z' )
1522 illegalCharacterFound=
true;
1527 if ( illegalCharacterFound )
1529 Entry( impl,
nullptr, verbosity );
1533 logables.erase( logables.begin() );
1534 Entry( impl, firstArg, verbosity );
1538 Entry( impl,
nullptr, verbosity );
1545Domain* LI::evaluateResultDomain(LoxImpl* impl,
const NString& domainPath )
1550 if ( domainPath.StartsWith( Lox::InternalDomains ) )
1553 resDomain._( domainPath, Lox::InternalDomains.
Length() );
1554 return findDomain( impl, *impl->internalDomains, resDomain );
1558 NString64 localPath; localPath.DbgDisableBufferReplacementWarning();
1559 impl->scopeDomains.InitWalk( Scope::ThreadInner,
1561 domainPath.IsNotEmpty() ? localPath._(domainPath)
1565 while( (nextDefault= impl->scopeDomains.Walk() ).IsNotNull() )
1569 if ( resDomain.IsNotEmpty() )
1570 resDomain.InsertAt(
"/", 0);
1571 resDomain.InsertAt( nextDefault, 0 );
1574 if ( resDomain.CharAtStart() == Domain::Separator() )
1577 return findDomain( impl, *impl->domains, resDomain );
1580void LI::getVerbosityFromConfig(LoxImpl* impl, Variable& v, Logger* logger, Domain& dom )
1583 int loggerNo= dom.GetLoggerNo( logger ) ;
1587 auto& cvVerb = v.Get<alib::lox::CVVerbosities>();
1589 for (
auto it : cvVerb)
1594 Substring domainStrParser= verbosityTknzr.Next();
1595 if ( domainStrParser.ConsumeString<lang::Case::Ignore>(
A_CHAR(
"INTERNAL_DOMAINS")) )
1597 while ( domainStrParser.ConsumeChar(
'/') )
1599 domainStrBuf << Lox::InternalDomains << domainStrParser;
1602 domainStrBuf._( domainStrParser );
1606 Substring verbosityStr= verbosityTknzr.Next();
1607 if ( verbosityStr.IsEmpty() )
1611 if ( domainStr.ConsumeChar (
'*' ) ) searchMode+= 2;
1612 if ( domainStr.ConsumeCharFromEnd(
'*' ) ) searchMode+= 1;
1613 if( ( searchMode == 0 && dom.FullPath.Equals <NC ,lang::Case::Ignore>( domainStr ) )
1614 || ( searchMode == 1 && dom.FullPath.StartsWith<CHK,lang::Case::Ignore>( domainStr ) )
1615 || ( searchMode == 2 && dom.FullPath.EndsWith <CHK,lang::Case::Ignore>( domainStr ) )
1616 || ( searchMode == 3 && dom.FullPath.IndexOf <CHK,lang::Case::Ignore>( domainStr ) >=0 )
1620 enumrecords::Parse<Verbosity>(verbosityStr, verbosity );
1621 dom.SetVerbosity( loggerNo, verbosity, v.GetPriority() );
1625 msg._<NC>(
"Logger \"" )._<NC>( logger->GetName() ) ._<NC>(
"\":" )._(
NTab(11 + impl->maxLoggerNameLength))
1626 ._<NC>(
'\'' )._<NC>( dom.FullPath )
1627 ._(
'\'' ).InsertChars(
' ', impl->maxDomainPathLength - dom.FullPath.Length() + 1 )
1628 ._(
"= Verbosity::" )
1629 ._( boxing::MakePair(verbosity, dom.GetPriority( loggerNo )) ).TrimEnd()
1632 logInternal( impl, Verbosity::Info,
"LGR", msg );
1637void LI::getDomainPrefixFromConfig(LoxImpl* impl, Domain& dom )
1639 Variable variable= variables::CampVariable(ALOX);
1641 const Declaration* decl= Declaration::Get( Variables::PREFIXES);
1642 decl= ALOX.GetConfig()->StoreDeclaration( decl,
1643 #if !ALIB_CHARACTERS_WIDE
1649 if( !variable.Try(decl) )
1654 prefixTokOuter.
Set(variable,
';',
true);
1655 while(prefixTokOuter.HasNext())
1657 Tokenizer prefixTok( prefixTokOuter.Next(),
'=' );
1660 Substring domainStrParser= prefixTok.Next();
1661 if ( domainStrParser.ConsumeString<lang::Case::Ignore>(
A_CHAR(
"INTERNAL_DOMAINS")) )
1663 while ( domainStrParser.ConsumeChar(
'/') )
1665 domainStrBuf << Lox::InternalDomains << domainStrParser;
1668 domainStrBuf._( domainStrParser );
1672 Tokenizer prefixTokInner( prefixTok.Next(),
',' );
1673 Substring prefixStr= prefixTokInner.Next();
1674 if ( prefixStr.IsEmpty() )
1676 if ( prefixStr.ConsumeChar(
'\"' ) )
1679 lang::Inclusion otherPLs= lang::Inclusion::Include;
1680 prefixTokInner.Next();
1681 if ( prefixTokInner.Actual.IsNotEmpty() )
1682 enumrecords::ParseEnumOrTypeBool( prefixTokInner.Actual, otherPLs, lang::Inclusion::Exclude, lang::Inclusion::Include );
1685 if ( domainStr.ConsumeChar (
'*' ) ) searchMode+= 2;
1686 if ( domainStr.ConsumeCharFromEnd(
'*' ) ) searchMode+= 1;
1687 if( ( searchMode == 0 && dom.FullPath.Equals <NC ,lang::Case::Ignore>( domainStr ) )
1688 || ( searchMode == 1 && dom.FullPath.StartsWith<CHK,lang::Case::Ignore>( domainStr ) )
1689 || ( searchMode == 2 && dom.FullPath.EndsWith <CHK,lang::Case::Ignore>( domainStr ) )
1690 || ( searchMode == 3 && dom.FullPath.IndexOf <CHK,lang::Case::Ignore>( domainStr ) >=0 )
1693 dom.PrefixLogables.emplace_back( impl->newPO<PrefixLogable>( impl->poolAllocator, prefixStr ), otherPLs );
1696 NString128 msg; msg._<NC>(
"String \"" )._<NC>( prefixStr )._<NC>(
"\" added as prefix logable for domain \'" )
1697 ._<NC>( dom.FullPath )
1698 ._<NC>(
"\'. (Retrieved from configuration variable \'" )._<NC>(variable)._(
"\'.)" );
1700 logInternal( impl, Verbosity::Info,
"PFX", msg );
1705void LI::getAllVerbosities(LoxImpl* impl, Variable& varVerbosities, Logger* logger, Domain& dom )
1708 getVerbosityFromConfig( impl, varVerbosities, logger, dom );
1711 for ( Domain& subDomain : dom.SubDomains )
1712 getAllVerbosities( impl, varVerbosities, logger, subDomain );
1716Domain* LI::findDomain(LoxImpl* impl, Domain& rootDomain, NString domainPath )
1718 int maxSubstitutions= 10;
1723 Domain* dom=
nullptr;
1727 dom= rootDomain.Find( domainPath, 1, &wasCreated );
1731 if ( impl->maxDomainPathLength < dom->FullPath.Length() )
1732 impl->maxDomainPathLength= dom->FullPath.Length();
1735 BoxesMA& logables= acquireInternalLogables(impl);
1736 logables.Add(
"{!Q} registered.", dom->FullPath );
1737 logInternal( impl, Verbosity::Info,
"DMN", logables );
1741 if ( !dom->ConfigurationAlreadyRead )
1742 { dom->ConfigurationAlreadyRead=
true;
1744 Box replacements[2];
1745 for (
int i= 0; i < dom->CountLoggers(); ++i )
1747 Logger* logger= dom->GetLogger(i);
1748 replacements[0]= GetName( impl );
1749 replacements[1]= logger->GetName();
1750 Variable varVerbosities= variables::CampVariable(ALOX, Variables::VERBOSITY, replacements );
1751 if ( varVerbosities.IsDefined() )
1752 getVerbosityFromConfig( impl, varVerbosities, logger, *dom );
1755 getDomainPrefixFromConfig( impl, *dom );
1760 if ( dom->CountLoggers() == 0 )
1761 logInternal( impl, Verbosity::Verbose,
"DMN",
" No loggers set, yet." );
1764 for (
int i= 0; i < dom->CountLoggers(); ++i )
1766 NString256 msg; msg._(
" \"")._( dom->GetLogger(i)->GetName() )._(
"\": ");
1767 msg.InsertChars(
' ', impl->maxLoggerNameLength + 6 - msg.Length() );
1768 msg._( dom->FullPath )._(
" = " )
1769 ._(boxing::MakePair(dom->GetVerbosity(i), dom->GetPriority(i)));
1770 logInternal( impl, Verbosity::Verbose,
"DMN", msg );
1779 if( !impl->domainSubstitutions.empty() )
1783 if ( domFullPath.CharAtStart<NC>() ==
'$' )
1786 while( maxSubstitutions-- > 0 )
1789 bool substituted=
false;
1790 for(
auto& rule : impl->domainSubstitutions )
1794 case DomainSubstitutionRule::Type::StartsWith:
1795 if( substPath.IsEmpty() )
1797 if ( domFullPath.StartsWith( rule.Search ) )
1799 substPath._( rule.Replacement )._( domFullPath, rule.Search.Length() );
1806 if ( substPath.StartsWith( rule.Search ) )
1808 substPath.ReplaceSubstring<NC>( rule.Replacement, 0, rule.Search.Length() );
1815 case DomainSubstitutionRule::Type::EndsWith:
1816 if( substPath.IsEmpty() )
1818 if ( domFullPath.EndsWith( rule.Search ) )
1820 substPath._( domFullPath, 0, domFullPath.Length() - rule.Search.Length() )._( rule.Replacement );
1827 if ( substPath.EndsWith( rule.Search ) )
1829 substPath.DeleteEnd( rule.Search.Length() )._( rule.Replacement );
1837 case DomainSubstitutionRule::Type::Substring:
1839 if( substPath.IsEmpty() )
1841 integer idx= domFullPath.IndexOf( rule.Search );
1844 substPath._( domFullPath, 0, idx )._( rule.Replacement)._( domFullPath, idx + rule.Search.Length() );
1851 integer idx= substPath.IndexOf( rule.Search, 0 );
1854 substPath.ReplaceSubstring<NC>( rule.Replacement, idx, rule.Search.Length() );
1863 case DomainSubstitutionRule::Type::Exact:
1865 if( substPath.IsEmpty() )
1867 if ( domFullPath.Equals<NC>( rule.Search ) )
1869 substPath._( rule.Replacement);
1873 if ( domFullPath.CharAtStart<NC>() ==
'$' )
1875 substPath._( rule.Replacement);
1882 if ( substPath.Equals<NC>( rule.Search) )
1884 substPath.Reset( rule.Replacement );
1892 default:
ALIB_ERROR(
"ALOX",
"Illegal switch state." ) break;
1903 if ( maxSubstitutions <= 0 && !impl->oneTimeWarningCircularDS )
1905 impl->oneTimeWarningCircularDS=
true;
1906 logInternal( impl, Verbosity::Error,
"DMN",
1907 "The Limit of 10 domain substitutions was reached. Circular substitution assumed!"
1908 " (This error is only reported once!)" );
1912 if( substPath.Length() > 0 )
1914 domainPath= substPath;
1923int LI::checkScopeInformation(LoxImpl* impl, Scope& scope,
const NString& internalDomain )
1926 if ( scope > Scope::Path )
1928 pathLevel= int( scope - Scope::Path );
1932 if ( ( scope == Scope::Path && impl->scopeInfo.GetFullPath().IsEmpty() )
1933 || ( scope == Scope::Filename && impl->scopeInfo.GetFileName().IsEmpty() )
1934 || ( scope == Scope::Method && impl->scopeInfo.GetMethod() .IsEmpty() ) )
1936 BoxesMA& logables= acquireInternalLogables(impl);
1937 logables.Add(
"Missing scope information. Cant use {}.", (scope + pathLevel) );
1938 logInternal( impl, Verbosity::Error, internalDomain, logables );
1944bool LI::isThreadRelatedScope(LoxImpl* impl, Scope scope )
1947 if ( scope == Scope::ThreadOuter
1948 || scope == Scope::ThreadInner )
1951 BoxesMA& logables= acquireInternalLogables(impl);
1952 logables.Add(
"Illegal parameter, only Scope::ThreadOuter and Scope::ThreadInner allowed."
1953 " Given: {}.", scope );
1954 logInternal( impl, Verbosity::Error,
"DMN", logables );
1958 impl->scopeInfo.GetLineNumber(),
1959 impl->scopeInfo.GetMethod(),
1960 #if !ALIB_SINGLE_THREADED
1961 impl->scopeInfo.GetThreadNativeID(),
1962 #elif ALIB_EXT_LIB_THREADS_AVAILABLE
1965 impl->scopeInfo.GetTypeInfo()
1967 0,
"Illegal scope type \"{}\" given. Only Scope::ThreadOuter and "
1968 "Scope::ThreadInner allowed.", scope );
1974void LI::log(LoxImpl* impl, Domain* dom, Verbosity verbosity, BoxesMA& logables, lang::Inclusion includePrefixes )
1977 bool logablesCollected=
false;
1978 PrefixLogable marker(impl->poolAllocator,
nullptr);
1979 for (
int i= 0; i < dom->CountLoggers() ; ++i )
1980 if( dom->IsActive( i, verbosity ) )
1983 if ( !logablesCollected )
1985 logablesCollected=
true;
1986 impl->scopePrefixes.InitWalk( Scope::ThreadInner, &marker );
1988 int userLogablesSize= int( logables.Size() );
1989 int threadInnersSize= -1;
1991 while( (next= impl->scopePrefixes.Walk() ) !=
nullptr )
1993 if( next != &marker )
1996 if ( includePrefixes == lang::Inclusion::Include )
2000 if ( next->IsType<BoxesMA*>() )
2002 auto* boxes= next->Unbox<
BoxesMA*>();
2003 for (
auto pfxI= boxes->Size() - 1 ; pfxI >= 0 ; --pfxI )
2004 logables.emplace( logables.begin() + ( threadInnersSize < 0 ? userLogablesSize : 0 ),
2005 (*boxes)[
size_t(pfxI)] );
2007 else if ( next->IsType<BoxesHA*>() )
2009 auto* boxes= next->Unbox<
BoxesHA*>();
2010 for (
auto pfxI= boxes->Size() - 1 ; pfxI >= 0 ; --pfxI )
2011 logables.emplace( logables.begin() + ( threadInnersSize < 0 ? userLogablesSize : 0 ),
2012 (*boxes)[
size_t(pfxI)] );
2014 else if ( next->IsType<BoxesPA*>() )
2016 auto* boxes= next->Unbox<
BoxesPA*>();
2017 for (
auto pfxI= boxes->Size() - 1 ; pfxI >= 0 ; --pfxI )
2018 logables.emplace( logables.begin() + ( threadInnersSize < 0 ? userLogablesSize : 0 ),
2019 (*boxes)[
size_t(pfxI)] );
2022 logables.emplace( logables.begin() + ( threadInnersSize < 0 ? userLogablesSize : 0 ), *next );
2029 bool excludeOthers=
false;
2030 threadInnersSize= int( logables.Size() ) - userLogablesSize;
2031 Domain* pflDom= dom;
2032 while ( pflDom !=
nullptr )
2034 for(
auto it= pflDom->PrefixLogables.rbegin() ; it != pflDom->PrefixLogables.rend() ; ++it )
2037 PrefixLogable& prefix= *it->first;
2038 if ( prefix.IsType<BoxesHA*>() )
2040 auto* boxes= prefix.Unbox<
BoxesHA*>();
2041 for (
auto pfxI= boxes->Size() - 1 ; pfxI >= 0 ; --pfxI )
2042 logables.emplace( logables.begin(),
2043 (*boxes)[
size_t(pfxI)] );
2045 else if ( prefix.IsType<BoxesMA*>() )
2047 auto* boxes= prefix.Unbox<
BoxesMA*>();
2048 for (
auto pfxI= boxes->Size() - 1 ; pfxI >= 0 ; --pfxI )
2049 logables.emplace( logables.begin(),
2050 (*boxes)[
size_t(pfxI)] );
2052 else if ( prefix.IsType<BoxesPA*>() )
2054 auto* boxes= prefix.Unbox<
BoxesPA*>();
2055 for (
auto pfxI= boxes->Size() - 1 ; pfxI >= 0 ; --pfxI )
2056 logables.emplace( logables.begin(),
2057 (*boxes)[
size_t(pfxI)] );
2060 logables.emplace( logables.begin(), prefix );
2063 if ( it->second == lang::Inclusion::Exclude )
2065 excludeOthers=
true;
2070 pflDom= excludeOthers ? nullptr : pflDom->Parent;
2076 for (
int ii= 0; ii < threadInnersSize ; ++ii )
2077 logables.pop_back();
2084 Logger* logger= dom->GetLogger(i);
2087 logger->Log( *dom, verbosity, logables, impl->scopeInfo );
2088 logger->TimeOfLastLog= Ticks::Now();
2093BoxesMA& LI::acquireInternalLogables(LoxImpl* impl)
2095 if(
integer(impl->internalLogables.size()) == impl->internalLogRecursionCounter )
2097 BoxesMA* newLogables= impl->monoAllocator().New<
BoxesMA>(impl->monoAllocator);
2098 impl->internalLogables.emplace_back( newLogables );
2101 return *impl->internalLogables[size_t(impl->internalLogRecursionCounter++)];
2104void LI::logInternal(LoxImpl* impl, Verbosity verbosity,
const NString& subDomain, BoxesMA& msg )
2107 log( impl, findDomain( impl, *impl->internalDomains, subDomain ), verbosity, msg, lang::Inclusion::Exclude );
2109 impl->internalLogables[
size_t(--impl->internalLogRecursionCounter)]->clear();
2112void LI::logInternal(LoxImpl* impl, Verbosity verbosity, const NString& subDomain, const NString& msg )
2114 BoxesMA& logables= acquireInternalLogables(impl);
2115 logables.Add( msg );
2116 logInternal( impl, verbosity, subDomain, logables );
2122void getStateDomainRecursive( Domain& domain, integer maxDomainPathLength, NAString& buf );
2123void getStateDomainRecursive( Domain& domain, integer maxDomainPathLength, NAString& buf )
2125 integer reference= buf.Length();
2126 buf._(
" "); domain.ToString( buf );
2127 integer idx= buf.IndexOf(
'[', reference );
2128 buf.InsertChars(
' ', maxDomainPathLength + 5 - idx + reference, idx);
2132 for ( Domain& subDomain : domain.SubDomains )
2133 getStateDomainRecursive( subDomain, maxDomainPathLength, buf );
2136void getStateDomainsWithDiffVerb( Domain& dom,
int loggerNo, std::vector<Domain*>& results );
2137void getStateDomainsWithDiffVerb( Domain& dom,
int loggerNo, std::vector<Domain*>& results )
2139 if ( dom.Parent ==
nullptr
2140 || dom.Parent->GetVerbosity(loggerNo) != dom.GetVerbosity(loggerNo) )
2141 results.emplace_back( &dom );
2143 for(
auto& it : dom.SubDomains )
2144 getStateDomainsWithDiffVerb( it, loggerNo, results );
2147void getStateCollectPrefixes( Domain& dom, integer indentSpaces, NAString& target );
2148void getStateCollectPrefixes( Domain& dom, integer indentSpaces, NAString& target )
2151 for (
auto& pfl : dom.PrefixLogables )
2153 buffer.InsertChars(
' ', indentSpaces );
2155 integer actLen= buffer.Length();
2156 buffer._( *
static_cast<Box*
>(pfl.first) );
2157 ESC::ReplaceToReadable( buffer, actLen );
2158 buffer <<
Escape( lang::Switch::On, actLen );
2160 if ( pfl.second == lang::Inclusion::Exclude )
2161 buffer._<NC>(
" (Excl.)" );
2162 buffer._<NC>(
Tab( 25, -1 ) );
2163 buffer._<NC>(
"<domain> [" )._<NC>( dom.FullPath )._<NC>(
']').NewLine();
2167 for(
auto& subDom : dom.SubDomains )
2168 getStateCollectPrefixes( subDom, indentSpaces, target );
2176void LI::GetState( LoxImpl* impl, NAString& buf, StateInfo flags )
2180 ScopeDump scopeDump(
IF_ALIB_THREADS( impl->scopeInfo.threadDictionary, )
2181 impl->noKeyHashKey, buf );
2183 if (
HasBits( flags, StateInfo::CompilationFlags ) )
2187 buf._<NC>(
"ALib Compiler Symbols:" ).NewLine();
2191 buf <<
" " <<
NField( p.Name, 41, lang::Alignment::Left ) <<
':'
2202 if( alib::HasBits( flags, StateInfo::Basic ) )
2203 buf._<NC>(
"Name: \"" )._( impl->scopeInfo.GetLoxName() )._(
'\"').NewLine();
2205 if(
HasBits( flags, StateInfo::Version ) )
2211 if(
HasBits( flags, StateInfo::Basic ) )
2212 buf._<NC>(
"#Log Calls: " )._<NC>( impl->CntLogCalls ).NewLine();
2214 if(
HasBits( flags, StateInfo::Basic )
2215 ||
HasBits( flags, StateInfo::Version ) )
2219 if(
HasBits( flags, StateInfo::SPTR ) )
2221 buf._<NC>(
"Source Path Trimming Rules: " ).NewLine();
2225 for(
int trimInfoNo= 0; trimInfoNo < 2 ; ++trimInfoNo )
2228 std::vector<ScopeInfo::SourcePathTrimRule>* trimInfoList=
2229 trimInfoNo == 0 ? &ScopeInfo::GlobalSPTRs
2230 : &impl->scopeInfo.LocalSPTRs;
2234 for (
auto& ti : *trimInfoList )
2237 buf._<NC>( trimInfoNo == 0 ?
" Global: "
2239 buf._<NC>( ti.IsPrefix ?
"\"" :
"\"*");
2240 buf._<NC>( ti.Path )._<NC>(
"\", " );
2241 buf._<NC>( ti.IncludeString );
2242 if ( ti.TrimOffset != 0 )
2243 buf._<NC>( ti.Path )._<NC>(
"\", Offset: " )._<NC>( ti.TrimOffset );
2244 buf._<NC>(
", Priority: " )._( ti.Priority );
2251 buf._<NC>(
" <no rules set>" ).NewLine();
2256 if(
HasBits( flags, StateInfo::DSR ) )
2258 buf._<NC>(
"Domain Substitution Rules: " ).NewLine();
2259 if( !impl->domainSubstitutions.empty() )
2263 for (
auto& it : impl->domainSubstitutions )
2264 if ( maxWidth < it.Search.Length() )
2265 maxWidth = it.Search.Length();
2269 for (
auto& it : impl->domainSubstitutions )
2272 if ( it.type == DomainSubstitutionRule::Type::EndsWith
2273 || it.type == DomainSubstitutionRule::Type::Substring )
2276 buf._<NC>( it.Search );
2277 if ( it.type == DomainSubstitutionRule::Type::StartsWith
2278 || it.type == DomainSubstitutionRule::Type::Substring )
2281 buf._<NC>(
NTab( maxWidth, -1, 0 ) )
2283 ._<NC>( it.Replacement );
2288 buf._<NC>(
" <no rules set>" ).NewLine();
2293 if(
HasBits( flags, StateInfo::Once ) )
2295 buf._<NC>(
"Once() Counters: " ).NewLine();
2296 if ( scopeDump.writeStoreMap( &impl->scopeLogOnce ) == 0 )
2297 buf._<NC>(
" <no Once() counters set>" ).NewLine();
2302 if(
HasBits( flags, StateInfo::LogData ) )
2304 buf._<NC>(
"Log Data: " ).NewLine();
2305 if ( scopeDump.writeStoreMap( &impl->scopeLogData ) == 0 )
2306 buf._<NC>(
" <no data objects stored>" ).NewLine();
2311 if(
HasBits( flags, StateInfo::PrefixLogables ) )
2313 buf._<NC>(
"Prefix Logables: " ).NewLine();
2314 integer oldLength= buf.Length();
2315 scopeDump.writeStore( &impl->scopePrefixes, 2 );
2316 getStateCollectPrefixes( *impl->domains, 2, buf );
2317 if ( oldLength == buf.Length() )
2318 buf._<NC>(
" <no prefix logables set>" ).NewLine();
2323 if(
HasBits( flags, StateInfo::ThreadMappings ) )
2325 #if !ALIB_SINGLE_THREADED
2326 buf._<NC>(
"Named Threads: " ).NewLine();
2327 if ( impl->scopeInfo.threadDictionary.Size() == 0 )
2328 buf._<NC>(
" <no thread name mappings set>" ).NewLine();
2330 for (
auto& pair : impl->scopeInfo.threadDictionary )
2332 buf._<NC>(
" " ) <<
NField(
String32() <<
'(' << pair.first <<
"):", 7, lang::Alignment::Left )
2333 <<
'\"' << pair.second <<
'\"';
2341 if(
HasBits( flags, StateInfo::ScopeDomains ) )
2343 buf._<NC>(
"Scope Domains: " ).NewLine();
2344 if ( scopeDump.writeStore( &impl->scopeDomains, 2 ) == 0 )
2345 buf._<NC>(
" <no scope domains set>" ).NewLine();
2350 if(
HasBits( flags, StateInfo::Loggers ) )
2353 std::vector<Domain*> domainsWithDiffVerb;
2354 for (
int treeNo= 0; treeNo < 2; ++treeNo )
2360 domTree= impl->domains;
2361 buf._<NC>(
"Loggers:" ).NewLine();
2365 domTree= impl->internalDomains;
2366 buf._<NC>(
"Loggers on Internal Domains:" ).NewLine();
2369 for (
int loggerNo= 0; loggerNo< domTree->CountLoggers(); ++loggerNo )
2375 Logger* logger= domTree->GetLogger(loggerNo);
2376 buf._<NC>(
" " )._<NC>( *logger ).NewLine();
2377 buf._<NC>(
" Lines logged: " )._<NC>( logger->CntLogs ).NewLine();
2379 ct.Set( dateTimeConverter.ToDateTime(logger->TimeOfCreation) );
2380 buf._<NC>(
" Creation time: " )._<NC>( ct.Format(
A_CHAR(
"yyyy-MM-dd HH:mm:ss"), as64.Reset()) ).NewLine();
2382 ct.Set( dateTimeConverter.ToDateTime(logger->TimeOfLastLog) );
2383 buf._<NC>(
" Last log time: " )._<NC>( ct.Format(
A_CHAR(
"yyyy-MM-dd HH:mm:ss"), as64.Reset()) ).NewLine();
2385 domainsWithDiffVerb.clear();
2386 getStateDomainsWithDiffVerb( *domTree, loggerNo, domainsWithDiffVerb);
2387 for ( Domain* dom : domainsWithDiffVerb )
2390 ._( dom == *domainsWithDiffVerb.begin() ?
"Verbosities: "
2394 buf << dom->FullPath <<
NTab( impl->maxDomainPathLength +1, tabRef);
2396 buf <<
"= " << boxing::MakePair(dom->GetVerbosity( loggerNo ), dom->GetPriority(loggerNo) )
2401 buf._<NC>(
" <no loggers attached>" ).NewLine();
2407 if(
HasBits( flags, StateInfo::InternalDomains ) )
2409 buf._<NC>(
"Internal Domains:" ).NewLine();
2410 getStateDomainRecursive( *impl->internalDomains, impl->maxDomainPathLength, buf );
2415 if(
HasBits( flags, StateInfo::Domains ) )
2417 buf._<NC>(
"Domains:" ).NewLine();
2418 getStateDomainRecursive( *impl->domains , impl->maxDomainPathLength, buf );
2430#undef UNDEFINED_THREAD
2431#undef ASSERT_ACQUIRED
SharedConfiguration & GetConfig()
TickConverter DateConverter
ALIB_DLL void SetBuffer(integer newCapacity)
bool ConsumeCharFromEnd(TChar consumable)
void Set(const TString< TChar > &src, TChar delimiter, bool skipEmptyTokens=false)
DbgLockAsserter Dbg
The debug tool instance.
DateTime ToDateTime(Ticks ticks)
#define ALIB_BOXING_VTABLE_DEFINE(TMapped, Identifier)
#define ALIB_LOCK_SHARED_WITH(lock)
#define IF_ALIB_THREADS(...)
#define ALIB_ASSERT(cond, domain)
#define ALIB_WARNING(domain,...)
#define ALIB_ASSERT_WARNING(cond, domain,...)
#define ALIB_ERROR(domain,...)
#define ALIB_LOCK_RECURSIVE_WITH(lock)
#define ALIB_ASSERT_ERROR(cond, domain,...)
#define ALIB_CALLER_PRUNED
#define ALIB_LOCK_WITH(lock)
#define ALIB_REL_DBG(releaseCode,...)
#define ALIB_CHARACTERS_WIDE
void Raise(const lang::CallerInfo &ci, int type, std::string_view domain, TArgs &&... args)
const TChar * Search(const TChar *haystack, integer haystackLength, TChar needle)
integer Length(const TChar *cstring)
std::conditional_t< ArrayTraits< T, nchar >::Access !=Policy::NONE, nchar, std::conditional_t< ArrayTraits< T, wchar >::Access !=Policy::NONE, wchar, std::conditional_t< ArrayTraits< T, xchar >::Access !=Policy::NONE, xchar, void > > > Type
constexpr bool HasBits(TEnum element, TEnum selection) noexcept
@ Add
Arithmetic addition ('+'). Precedence 800.
platform_specific integer
integer ThreadID
The ALib thread identifier type.
strings::TEscape< character > Escape
Type alias in namespace alib.
threads::Lock Lock
Type alias in namespace alib.
NLocalString< 128 > NString128
Type alias name for TLocalString<nchar,128>.
CompilationFlagMeaningsEntry COMPILATION_FLAG_MEANINGS[40]
NLocalString< 64 > NString64
Type alias name for TLocalString<nchar,64>.
strings::TTab< character > Tab
Type alias in namespace alib.
LocalString< 256 > String256
Type alias name for TLocalString<character,256>.
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
strings::util::TTokenizer< character > Tokenizer
Type alias in namespace alib.
variables::Variable Variable
Type alias in namespace alib.
LocalString< 128 > String128
Type alias name for TLocalString<character,128>.
time::DateTime DateTime
Type alias in namespace alib.
LocalString< 64 > String64
Type alias name for TLocalString<character,64>.
constexpr CString NEW_LINE
A zero-terminated string containing the new-line character sequence.
strings::TSubstring< nchar > NSubstring
Type alias in namespace alib.
monomem::TPoolAllocator< MonoAllocator > PoolAllocator
strings::TString< nchar > NString
Type alias in namespace alib.
strings::TAString< nchar, lang::HeapAllocator > NAString
Type alias in namespace alib.
boxing::TBoxes< PoolAllocator > BoxesPA
Type alias in namespace alib.
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
threads::Thread Thread
Type alias in namespace alib.
strings::TTab< nchar > NTab
Type alias in namespace alib.
strings::TCString< nchar > NCString
Type alias in namespace alib.
strings::util::CalendarDateTime CalendarDateTime
Type alias in namespace alib.
LocalString< 32 > String32
Type alias name for TLocalString<character,32>.
lox::ALoxCamp ALOX
The singleton instance of ALib Camp class ALoxCamp.
boxing::Box Box
Type alias in namespace alib.
threads::RecursiveLock RecursiveLock
Type alias in namespace alib.
boxing::TBoxes< MonoAllocator > BoxesMA
Type alias in namespace alib.
strings::TField< nchar > NField
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
NLocalString< 512 > NString512
Type alias name for TLocalString<nchar,512>.
boxing::TBoxes< lang::HeapAllocator > BoxesHA
Type alias in namespace alib.
NLocalString< 256 > NString256
Type alias name for TLocalString<nchar,256>.
TCompilationFlags COMPILATION_FLAGS
NLocalString< 32 > NString32
Type alias name for TLocalString<nchar,32>.
time::TickConverter TickConverter
Type alias in namespace alib.
strings::TSubstring< character > Substring
Type alias in namespace alib.
lox::detail::Logger Logger
Type alias in namespace alib.
containers::List< TAllocator, T, TRecycling > List
Type alias in namespace alib.
lox::textlogger::TextLogger TextLogger
Type alias in namespace alib.