Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

695 lines
21 KiB

  1. //============ Copyright (c) Valve Corporation, All rights reserved. ============
  2. //
  3. // Logging system definitions.
  4. //
  5. //===============================================================================
  6. #include "pch_tier0.h"
  7. #include "logging.h"
  8. #include <string.h>
  9. #include "dbg.h"
  10. #include "threadtools.h"
  11. #include "tier0_strtools.h" // this is from tier1, but only included for inline definition of V_isspace
  12. #ifdef _PS3
  13. #include <sys/tty.h>
  14. #endif
  15. #define DBG_SPEW_ALL_WARNINGS_AND_ERRORS_ASSERT false
  16. //////////////////////////////////////////////////////////////////////////
  17. // Define commonly used channels here
  18. //////////////////////////////////////////////////////////////////////////
  19. DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_GENERAL, "General" );
  20. DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_ASSERT, "Assert" );
  21. // Corresponds to ConMsg/ConWarning/etc. with a level <= 1.
  22. // Only errors are spewed by default.
  23. BEGIN_DEFINE_LOGGING_CHANNEL( LOG_CONSOLE, "Console", LCF_CONSOLE_ONLY, LS_ERROR );
  24. ADD_LOGGING_CHANNEL_TAG( "Console" );
  25. END_DEFINE_LOGGING_CHANNEL();
  26. // Corresponds to DevMsg/DevWarning/etc. with a level <= 1.
  27. // Only errors are spewed by default.
  28. BEGIN_DEFINE_LOGGING_CHANNEL( LOG_DEVELOPER, "Developer", LCF_CONSOLE_ONLY, LS_ERROR );
  29. ADD_LOGGING_CHANNEL_TAG( "Developer" );
  30. END_DEFINE_LOGGING_CHANNEL();
  31. // Corresponds to ConMsg/ConWarning/etc. with a level >= 2.
  32. // Only errors are spewed by default.
  33. BEGIN_DEFINE_LOGGING_CHANNEL( LOG_DEVELOPER_CONSOLE, "DeveloperConsole", LCF_CONSOLE_ONLY, LS_ERROR );
  34. ADD_LOGGING_CHANNEL_TAG( "DeveloperVerbose" );
  35. ADD_LOGGING_CHANNEL_TAG( "Console" );
  36. END_DEFINE_LOGGING_CHANNEL();
  37. // Corresponds to DevMsg/DevWarning/etc, with a level >= 2.
  38. // Only errors are spewed by default.
  39. BEGIN_DEFINE_LOGGING_CHANNEL( LOG_DEVELOPER_VERBOSE, "DeveloperVerbose", LCF_CONSOLE_ONLY, LS_ERROR, Color( 192, 128, 192, 255 ) );
  40. ADD_LOGGING_CHANNEL_TAG( "DeveloperVerbose" );
  41. END_DEFINE_LOGGING_CHANNEL();
  42. //////////////////////////////////////////////////////////////////////////
  43. // Globals
  44. //////////////////////////////////////////////////////////////////////////
  45. // The index of the logging state used by the current thread. This defaults to 0 across all threads,
  46. // which indicates that the global listener set should be used (CLoggingSystem::m_nGlobalStateIndex).
  47. //
  48. // NOTE:
  49. // Because our linux TLS implementation does not support embedding a thread local
  50. // integer in a class, the logging system must use a global thread-local integer.
  51. // This means that we can only have one instance of CLoggingSystem, although
  52. // we could support additional instances if we are willing to lose support for
  53. // thread-local spew handling.
  54. // There is no other reason why this class must be a singleton, except
  55. // for the fact that there's no reason to have more than one in existence.
  56. bool g_bEnforceLoggingSystemSingleton = false;
  57. #ifdef _PS3
  58. #include "tls_ps3.h"
  59. #else // _PS3
  60. CTHREADLOCALINT g_nThreadLocalStateIndex;
  61. #endif // _PS3
  62. //////////////////////////////////////////////////////////////////////////
  63. // Implementation
  64. //////////////////////////////////////////////////////////////////////////
  65. CLoggingSystem *g_pGlobalLoggingSystem = NULL;
  66. // This function does not get inlined due to the static variable :(
  67. CLoggingSystem *GetGlobalLoggingSystem_Internal()
  68. {
  69. static CLoggingSystem globalLoggingSystem;
  70. g_pGlobalLoggingSystem = &globalLoggingSystem;
  71. return &globalLoggingSystem;
  72. }
  73. // This function can get inlined
  74. CLoggingSystem *GetGlobalLoggingSystem()
  75. {
  76. return ( g_pGlobalLoggingSystem == NULL ) ? GetGlobalLoggingSystem_Internal() : g_pGlobalLoggingSystem;
  77. }
  78. CLoggingSystem::CLoggingSystem() :
  79. m_nChannelCount( 0 ),
  80. m_nChannelTagCount( 0 ),
  81. m_nTagNamePoolIndex( 0 ),
  82. m_nGlobalStateIndex( 0 )
  83. {
  84. Assert( !g_bEnforceLoggingSystemSingleton );
  85. g_bEnforceLoggingSystemSingleton = true;
  86. #if !defined( _PS3 ) && !defined(POSIX) && !defined(PLATFORM_WINDOWS)
  87. // Due to uncertain constructor ordering (g_nThreadLocalStateIndex
  88. // may not be constructed yet so TLS index may not be available yet)
  89. // we cannot initialize the state index here without risking
  90. // AppVerifier errors and undefined behavior. Luckily TlsAlloc values
  91. // are guaranteed to be zero-initialized so we don't need to zero-init,
  92. // this, and in fact we can't for all threads.
  93. // TLS on PS3 is zero-initialized in global ELF section
  94. // TLS is also not accessible at this point before PRX entry point runs
  95. g_nThreadLocalStateIndex = 0;
  96. #endif
  97. m_LoggingStates[0].m_nPreviousStackEntry = -1;
  98. m_LoggingStates[0].m_nListenerCount = 1;
  99. m_LoggingStates[0].m_RegisteredListeners[0] = &m_DefaultLoggingListener;
  100. m_LoggingStates[0].m_pLoggingResponse = &m_DefaultLoggingResponse;
  101. // Mark all other logging state blocks as unused.
  102. for ( int i = 1; i < MAX_LOGGING_STATE_COUNT; ++ i )
  103. {
  104. m_LoggingStates[i].m_nListenerCount = -1;
  105. }
  106. m_pStateMutex = NULL;
  107. }
  108. CLoggingSystem::~CLoggingSystem()
  109. {
  110. g_bEnforceLoggingSystemSingleton = false;
  111. delete m_pStateMutex;
  112. }
  113. LoggingChannelID_t CLoggingSystem::RegisterLoggingChannel( const char *pChannelName, RegisterTagsFunc registerTagsFunc, int flags, LoggingSeverity_t severity, Color spewColor )
  114. {
  115. if ( m_nChannelCount >= MAX_LOGGING_CHANNEL_COUNT )
  116. {
  117. // Out of logging channels... catastrophic fail!
  118. Log_Error( LOG_GENERAL, "Out of logging channels.\n" );
  119. Assert( 0 );
  120. return INVALID_LOGGING_CHANNEL_ID;
  121. }
  122. else
  123. {
  124. // Channels can be multiply defined, in which case return the ID of the existing channel.
  125. for ( int i = 0; i < m_nChannelCount; ++ i )
  126. {
  127. if ( V_tier0_stricmp( m_RegisteredChannels[i].m_Name, pChannelName ) == 0 )
  128. {
  129. // OK to call the tag registration callback; duplicates will be culled away.
  130. // This allows multiple people to register a logging channel, and the union of all tags will be registered.
  131. if ( registerTagsFunc != NULL )
  132. {
  133. registerTagsFunc();
  134. }
  135. // If a logging channel is registered multiple times, only one of the registrations should specify flags/severity/color.
  136. if ( m_RegisteredChannels[i].m_Flags == 0 && m_RegisteredChannels[i].m_MinimumSeverity == LS_MESSAGE && m_RegisteredChannels[i].m_SpewColor == UNSPECIFIED_LOGGING_COLOR )
  137. {
  138. m_RegisteredChannels[i].m_Flags = ( LoggingChannelFlags_t )flags;
  139. m_RegisteredChannels[i].m_MinimumSeverity = severity;
  140. m_RegisteredChannels[i].m_SpewColor = spewColor;
  141. }
  142. else
  143. {
  144. AssertMsg( flags == 0 || flags == m_RegisteredChannels[i].m_Flags, "Non-zero or mismatched flags specified in logging channel re-registration!" );
  145. AssertMsg( severity == LS_MESSAGE || severity == m_RegisteredChannels[i].m_MinimumSeverity, "Non-default or mismatched severity specified in logging channel re-registration!" );
  146. AssertMsg( spewColor == UNSPECIFIED_LOGGING_COLOR || spewColor == m_RegisteredChannels[i].m_SpewColor, "Non-default or mismatched color specified in logging channel re-registration!" );
  147. }
  148. return m_RegisteredChannels[i].m_ID;
  149. }
  150. }
  151. m_RegisteredChannels[m_nChannelCount].m_ID = m_nChannelCount;
  152. m_RegisteredChannels[m_nChannelCount].m_Flags = ( LoggingChannelFlags_t )flags;
  153. m_RegisteredChannels[m_nChannelCount].m_MinimumSeverity = severity;
  154. m_RegisteredChannels[m_nChannelCount].m_SpewColor = spewColor;
  155. strncpy( m_RegisteredChannels[m_nChannelCount].m_Name, pChannelName, MAX_LOGGING_IDENTIFIER_LENGTH );
  156. if ( registerTagsFunc != NULL )
  157. {
  158. registerTagsFunc();
  159. }
  160. return m_nChannelCount ++;
  161. }
  162. }
  163. LoggingChannelID_t CLoggingSystem::FindChannel( const char *pChannelName ) const
  164. {
  165. for ( int i = 0; i < m_nChannelCount; ++ i )
  166. {
  167. if ( V_tier0_stricmp( m_RegisteredChannels[i].m_Name, pChannelName ) == 0 )
  168. {
  169. return i;
  170. }
  171. }
  172. return INVALID_LOGGING_CHANNEL_ID;
  173. }
  174. void CLoggingSystem::AddTagToCurrentChannel( const char *pTagName )
  175. {
  176. // Add tags at the head of the tag-list of the most recently added channel.
  177. LoggingChannel_t *pChannel = &m_RegisteredChannels[m_nChannelCount];
  178. // First check for duplicates
  179. if ( pChannel->HasTag( pTagName ) )
  180. {
  181. return;
  182. }
  183. LoggingTag_t *pTag = AllocTag( pTagName );
  184. pTag->m_pNextTag = pChannel->m_pFirstTag;
  185. pChannel->m_pFirstTag = pTag;
  186. }
  187. void CLoggingSystem::SetChannelSpewLevel( LoggingChannelID_t channelID, LoggingSeverity_t minimumSeverity )
  188. {
  189. GetChannel( channelID )->SetSpewLevel( minimumSeverity );
  190. }
  191. void CLoggingSystem::SetChannelSpewLevelByName( const char *pName, LoggingSeverity_t minimumSeverity )
  192. {
  193. for ( int i = 0; i < m_nChannelCount; ++ i )
  194. {
  195. if ( V_tier0_stricmp( m_RegisteredChannels[i].m_Name, pName ) == 0 )
  196. {
  197. m_RegisteredChannels[i].SetSpewLevel( minimumSeverity );
  198. }
  199. }
  200. }
  201. void CLoggingSystem::SetChannelSpewLevelByTag( const char *pTag, LoggingSeverity_t minimumSeverity )
  202. {
  203. for ( int i = 0; i < m_nChannelCount; ++ i )
  204. {
  205. if ( m_RegisteredChannels[i].HasTag( pTag ) )
  206. {
  207. m_RegisteredChannels[i].SetSpewLevel( minimumSeverity );
  208. }
  209. }
  210. }
  211. void CLoggingSystem::SetGlobalSpewLevel( LoggingSeverity_t minimumSeverity )
  212. {
  213. for ( int i = 0; i < m_nChannelCount; ++ i )
  214. {
  215. m_RegisteredChannels[i].SetSpewLevel( minimumSeverity );
  216. }
  217. }
  218. void CLoggingSystem::PushLoggingState( bool bThreadLocal, bool bClearState )
  219. {
  220. if ( !m_pStateMutex )
  221. m_pStateMutex = new CThreadFastMutex();
  222. m_pStateMutex->Lock();
  223. int nNewState = FindUnusedStateIndex();
  224. // Ensure we're not out of state blocks.
  225. Assert( nNewState != -1 );
  226. int nCurrentState = bThreadLocal ? (int)g_nThreadLocalStateIndex : m_nGlobalStateIndex;
  227. if ( bClearState )
  228. {
  229. m_LoggingStates[nNewState].m_nListenerCount = 0;
  230. m_LoggingStates[nNewState].m_pLoggingResponse = &m_DefaultLoggingResponse;
  231. }
  232. else
  233. {
  234. m_LoggingStates[nNewState] = m_LoggingStates[nCurrentState];
  235. }
  236. m_LoggingStates[nNewState].m_nPreviousStackEntry = nCurrentState;
  237. if ( bThreadLocal )
  238. {
  239. g_nThreadLocalStateIndex = nNewState;
  240. }
  241. else
  242. {
  243. m_nGlobalStateIndex = nNewState;
  244. }
  245. m_pStateMutex->Unlock();
  246. }
  247. void CLoggingSystem::PopLoggingState( bool bThreadLocal )
  248. {
  249. if ( !m_pStateMutex )
  250. m_pStateMutex = new CThreadFastMutex();
  251. m_pStateMutex->Lock();
  252. int nCurrentState = bThreadLocal ? (int)g_nThreadLocalStateIndex : m_nGlobalStateIndex;
  253. // Shouldn't be less than 0 (implies error during Push()) or 0 (implies that Push() was never called)
  254. Assert( nCurrentState > 0 );
  255. // Mark the current state as unused.
  256. m_LoggingStates[nCurrentState].m_nListenerCount = -1;
  257. if ( bThreadLocal )
  258. {
  259. g_nThreadLocalStateIndex = m_LoggingStates[nCurrentState].m_nPreviousStackEntry;
  260. }
  261. else
  262. {
  263. m_nGlobalStateIndex = m_LoggingStates[nCurrentState].m_nPreviousStackEntry;
  264. }
  265. m_pStateMutex->Unlock();
  266. }
  267. void CLoggingSystem::RegisterLoggingListener( ILoggingListener *pListener )
  268. {
  269. if ( !m_pStateMutex )
  270. m_pStateMutex = new CThreadFastMutex();
  271. m_pStateMutex->Lock();
  272. LoggingState_t *pState = GetCurrentState();
  273. if ( pState->m_nListenerCount >= ARRAYSIZE(pState->m_RegisteredListeners) )
  274. {
  275. // Out of logging listener slots... catastrophic fail!
  276. Assert( 0 );
  277. }
  278. else
  279. {
  280. pState->m_RegisteredListeners[pState->m_nListenerCount] = pListener;
  281. ++ pState->m_nListenerCount;
  282. }
  283. m_pStateMutex->Unlock();
  284. }
  285. bool CLoggingSystem::IsListenerRegistered( ILoggingListener *pListener )
  286. {
  287. if ( !m_pStateMutex )
  288. m_pStateMutex = new CThreadFastMutex();
  289. m_pStateMutex->Lock();
  290. const LoggingState_t *pState = GetCurrentState();
  291. bool bFound = false;
  292. for ( int i = 0; i < pState->m_nListenerCount; ++ i )
  293. {
  294. if ( pState->m_RegisteredListeners[i] == pListener )
  295. {
  296. bFound = true;
  297. break;
  298. }
  299. }
  300. m_pStateMutex->Unlock();
  301. return bFound;
  302. }
  303. void CLoggingSystem::ResetCurrentLoggingState()
  304. {
  305. if ( !m_pStateMutex )
  306. m_pStateMutex = new CThreadFastMutex();
  307. m_pStateMutex->Lock();
  308. LoggingState_t *pState = GetCurrentState();
  309. pState->m_nListenerCount = 0;
  310. pState->m_pLoggingResponse = &m_DefaultLoggingResponse;
  311. m_pStateMutex->Unlock();
  312. }
  313. void CLoggingSystem::SetLoggingResponsePolicy( ILoggingResponsePolicy *pLoggingResponse )
  314. {
  315. if ( !m_pStateMutex )
  316. m_pStateMutex = new CThreadFastMutex();
  317. m_pStateMutex->Lock();
  318. LoggingState_t *pState = GetCurrentState();
  319. if ( pLoggingResponse == NULL )
  320. {
  321. pState->m_pLoggingResponse = &m_DefaultLoggingResponse;
  322. }
  323. else
  324. {
  325. pState->m_pLoggingResponse = pLoggingResponse;
  326. }
  327. m_pStateMutex->Unlock();
  328. }
  329. LoggingResponse_t CLoggingSystem::LogDirect( LoggingChannelID_t channelID, LoggingSeverity_t severity, Color color, const tchar *pMessage )
  330. {
  331. Assert( IsValidChannelID( channelID ) );
  332. if ( !IsValidChannelID( channelID ) )
  333. return LR_CONTINUE;
  334. LoggingContext_t context;
  335. context.m_ChannelID = channelID;
  336. context.m_Flags = m_RegisteredChannels[channelID].m_Flags;
  337. context.m_Severity = severity;
  338. context.m_Color = ( color == UNSPECIFIED_LOGGING_COLOR ) ? m_RegisteredChannels[channelID].m_SpewColor : color;
  339. // It is assumed that the mutex is reentrant safe on all platforms.
  340. if ( !m_pStateMutex )
  341. m_pStateMutex = new CThreadFastMutex();
  342. m_pStateMutex->Lock();
  343. LoggingState_t *pState = GetCurrentState();
  344. for ( int i = 0; i < pState->m_nListenerCount; ++ i )
  345. {
  346. pState->m_RegisteredListeners[i]->Log( &context, pMessage );
  347. }
  348. #if defined( _PS3 ) && !defined( _CERT )
  349. if ( !pState->m_nListenerCount )
  350. {
  351. unsigned int unBytesWritten;
  352. sys_tty_write( SYS_TTYP15, pMessage, strlen( pMessage ), &unBytesWritten );
  353. }
  354. #endif
  355. LoggingResponse_t response = pState->m_pLoggingResponse->OnLog( &context );
  356. if ( DBG_SPEW_ALL_WARNINGS_AND_ERRORS_ASSERT && severity != LS_MESSAGE )
  357. {
  358. response = LR_DEBUGGER;
  359. }
  360. m_pStateMutex->Unlock();
  361. switch( response )
  362. {
  363. case LR_DEBUGGER:
  364. // Asserts put the debug break in the macro itself so the code breaks at the failure point.
  365. if ( severity != LS_ASSERT )
  366. {
  367. DebuggerBreakIfDebugging();
  368. }
  369. break;
  370. case LR_ABORT:
  371. Log_Msg( LOG_DEVELOPER_VERBOSE, "Exiting due to logging LR_ABORT request.\n" );
  372. Plat_ExitProcess( EXIT_FAILURE );
  373. break;
  374. }
  375. return response;
  376. }
  377. CLoggingSystem::LoggingChannel_t *CLoggingSystem::GetChannel( LoggingChannelID_t channelID )
  378. {
  379. Assert( IsValidChannelID( channelID ) );
  380. return &m_RegisteredChannels[channelID];
  381. }
  382. const CLoggingSystem::LoggingChannel_t *CLoggingSystem::GetChannel( LoggingChannelID_t channelID ) const
  383. {
  384. Assert( IsValidChannelID( channelID ) );
  385. return &m_RegisteredChannels[channelID];
  386. }
  387. CLoggingSystem::LoggingState_t *CLoggingSystem::GetCurrentState()
  388. {
  389. // Assume the caller grabbed the mutex.
  390. int nState = g_nThreadLocalStateIndex;
  391. if ( nState != 0 )
  392. {
  393. Assert( nState > 0 && nState < MAX_LOGGING_STATE_COUNT );
  394. return &m_LoggingStates[nState];
  395. }
  396. else
  397. {
  398. Assert( m_nGlobalStateIndex >= 0 && m_nGlobalStateIndex < MAX_LOGGING_STATE_COUNT );
  399. return &m_LoggingStates[m_nGlobalStateIndex];
  400. }
  401. }
  402. const CLoggingSystem::LoggingState_t *CLoggingSystem::GetCurrentState() const
  403. {
  404. // Assume the caller grabbed the mutex.
  405. int nState = g_nThreadLocalStateIndex;
  406. if ( nState != 0 )
  407. {
  408. Assert( nState > 0 && nState < MAX_LOGGING_STATE_COUNT );
  409. return &m_LoggingStates[nState];
  410. }
  411. else
  412. {
  413. Assert( m_nGlobalStateIndex >= 0 && m_nGlobalStateIndex < MAX_LOGGING_STATE_COUNT );
  414. return &m_LoggingStates[m_nGlobalStateIndex];
  415. }
  416. }
  417. int CLoggingSystem::FindUnusedStateIndex()
  418. {
  419. for ( int i = 0; i < MAX_LOGGING_STATE_COUNT; ++ i )
  420. {
  421. if ( m_LoggingStates[i].m_nListenerCount < 0 )
  422. {
  423. return i;
  424. }
  425. }
  426. return -1;
  427. }
  428. CLoggingSystem::LoggingTag_t *CLoggingSystem::AllocTag( const char *pTagName )
  429. {
  430. Assert( m_nChannelTagCount < MAX_LOGGING_TAG_COUNT );
  431. LoggingTag_t *pTag = &m_ChannelTags[m_nChannelTagCount ++];
  432. pTag->m_pNextTag = NULL;
  433. pTag->m_pTagName = m_TagNamePool + m_nTagNamePoolIndex;
  434. // Copy string into pool.
  435. size_t nTagLength = strlen( pTagName );
  436. Assert( m_nTagNamePoolIndex + nTagLength + 1 <= MAX_LOGGING_TAG_CHARACTER_COUNT );
  437. strcpy( m_TagNamePool + m_nTagNamePoolIndex, pTagName );
  438. m_nTagNamePoolIndex += ( int )nTagLength + 1;
  439. return pTag;
  440. }
  441. LoggingChannelID_t LoggingSystem_RegisterLoggingChannel( const char *pName, RegisterTagsFunc registerTagsFunc, int flags, LoggingSeverity_t severity, Color color )
  442. {
  443. return GetGlobalLoggingSystem()->RegisterLoggingChannel( pName, registerTagsFunc, flags, severity, color );
  444. }
  445. void LoggingSystem_ResetCurrentLoggingState()
  446. {
  447. GetGlobalLoggingSystem()->ResetCurrentLoggingState();
  448. }
  449. void LoggingSystem_RegisterLoggingListener( ILoggingListener *pListener )
  450. {
  451. GetGlobalLoggingSystem()->RegisterLoggingListener( pListener );
  452. }
  453. void LoggingSystem_UnregisterLoggingListener(ILoggingListener *pListener)
  454. {
  455. }
  456. void LoggingSystem_SetLoggingResponsePolicy( ILoggingResponsePolicy *pResponsePolicy )
  457. {
  458. GetGlobalLoggingSystem()->SetLoggingResponsePolicy( pResponsePolicy );
  459. }
  460. void LoggingSystem_PushLoggingState( bool bThreadLocal, bool bClearState )
  461. {
  462. GetGlobalLoggingSystem()->PushLoggingState( bThreadLocal, bClearState );
  463. }
  464. void LoggingSystem_PopLoggingState( bool bThreadLocal )
  465. {
  466. GetGlobalLoggingSystem()->PopLoggingState( bThreadLocal );
  467. }
  468. void LoggingSystem_AddTagToCurrentChannel( const char *pTagName )
  469. {
  470. GetGlobalLoggingSystem()->AddTagToCurrentChannel( pTagName );
  471. }
  472. LoggingChannelID_t LoggingSystem_FindChannel( const char *pChannelName )
  473. {
  474. return GetGlobalLoggingSystem()->FindChannel( pChannelName );
  475. }
  476. int LoggingSystem_GetChannelCount()
  477. {
  478. return GetGlobalLoggingSystem()->GetChannelCount();
  479. }
  480. LoggingChannelID_t LoggingSystem_GetFirstChannelID()
  481. {
  482. return ( GetGlobalLoggingSystem()->GetChannelCount() > 0 ) ? 0 : INVALID_LOGGING_CHANNEL_ID;
  483. }
  484. LoggingChannelID_t LoggingSystem_GetNextChannelID( LoggingChannelID_t channelID )
  485. {
  486. int nChannelCount = GetGlobalLoggingSystem()->GetChannelCount();
  487. int nNextChannel = channelID + 1;
  488. return ( nNextChannel < nChannelCount ) ? nNextChannel : INVALID_LOGGING_CHANNEL_ID;
  489. }
  490. const CLoggingSystem::LoggingChannel_t *LoggingSystem_GetChannel( LoggingChannelID_t channelIndex )
  491. {
  492. return GetGlobalLoggingSystem()->GetChannel( channelIndex );
  493. }
  494. bool LoggingSystem_HasTag( LoggingChannelID_t channelID, const char *pTag )
  495. {
  496. return GetGlobalLoggingSystem()->HasTag( channelID, pTag );
  497. }
  498. bool LoggingSystem_IsChannelEnabled( LoggingChannelID_t channelID, LoggingSeverity_t severity )
  499. {
  500. return GetGlobalLoggingSystem()->IsChannelEnabled( channelID, severity );
  501. }
  502. void LoggingSystem_SetChannelSpewLevel( LoggingChannelID_t channelID, LoggingSeverity_t minimumSeverity )
  503. {
  504. GetGlobalLoggingSystem()->SetChannelSpewLevel( channelID, minimumSeverity );
  505. }
  506. void LoggingSystem_SetChannelSpewLevelByName( const char *pName, LoggingSeverity_t minimumSeverity )
  507. {
  508. GetGlobalLoggingSystem()->SetChannelSpewLevelByName( pName, minimumSeverity );
  509. }
  510. void LoggingSystem_SetChannelSpewLevelByTag( const char *pTag, LoggingSeverity_t minimumSeverity )
  511. {
  512. GetGlobalLoggingSystem()->SetChannelSpewLevelByTag( pTag, minimumSeverity );
  513. }
  514. void LoggingSystem_SetGlobalSpewLevel( LoggingSeverity_t minimumSeverity )
  515. {
  516. GetGlobalLoggingSystem()->SetGlobalSpewLevel( minimumSeverity );
  517. }
  518. int32 LoggingSystem_GetChannelColor( LoggingChannelID_t channelID )
  519. {
  520. return GetGlobalLoggingSystem()->GetChannelColor( channelID ).GetRawColor();
  521. }
  522. void LoggingSystem_SetChannelColor( LoggingChannelID_t channelID, int color )
  523. {
  524. Color c;
  525. c.SetRawColor( color );
  526. GetGlobalLoggingSystem()->SetChannelColor( channelID, c );
  527. }
  528. LoggingChannelFlags_t LoggingSystem_GetChannelFlags( LoggingChannelID_t channelID )
  529. {
  530. return GetGlobalLoggingSystem()->GetChannelFlags( channelID );
  531. }
  532. void LoggingSystem_SetChannelFlags( LoggingChannelID_t channelID, LoggingChannelFlags_t flags )
  533. {
  534. GetGlobalLoggingSystem()->SetChannelFlags( channelID, flags );
  535. }
  536. LoggingResponse_t LoggingSystem_Log( LoggingChannelID_t channelID, LoggingSeverity_t severity, const char *pMessageFormat, ... )
  537. {
  538. if ( !GetGlobalLoggingSystem()->IsChannelEnabled( channelID, severity ) )
  539. return LR_CONTINUE;
  540. tchar formattedMessage[MAX_LOGGING_MESSAGE_LENGTH];
  541. va_list args;
  542. va_start( args, pMessageFormat );
  543. Tier0Internal_vsntprintf( formattedMessage, MAX_LOGGING_MESSAGE_LENGTH, pMessageFormat, args );
  544. va_end( args );
  545. return GetGlobalLoggingSystem()->LogDirect( channelID, severity, UNSPECIFIED_LOGGING_COLOR, formattedMessage );
  546. }
  547. LoggingResponse_t LoggingSystem_Log( LoggingChannelID_t channelID, LoggingSeverity_t severity, Color spewColor, const char *pMessageFormat, ... )
  548. {
  549. if ( !GetGlobalLoggingSystem()->IsChannelEnabled( channelID, severity ) )
  550. return LR_CONTINUE;
  551. tchar formattedMessage[MAX_LOGGING_MESSAGE_LENGTH];
  552. va_list args;
  553. va_start( args, pMessageFormat );
  554. Tier0Internal_vsntprintf( formattedMessage, MAX_LOGGING_MESSAGE_LENGTH, pMessageFormat, args );
  555. va_end( args );
  556. return GetGlobalLoggingSystem()->LogDirect( channelID, severity, spewColor, formattedMessage );
  557. }
  558. LoggingResponse_t LoggingSystem_LogDirect( LoggingChannelID_t channelID, LoggingSeverity_t severity, Color spewColor, const char *pMessage )
  559. {
  560. if ( !GetGlobalLoggingSystem()->IsChannelEnabled( channelID, severity ) )
  561. return LR_CONTINUE;
  562. return GetGlobalLoggingSystem()->LogDirect( channelID, severity, spewColor, pMessage );
  563. }
  564. LoggingResponse_t LoggingSystem_LogAssert( const char *pMessageFormat, ... )
  565. {
  566. if ( !GetGlobalLoggingSystem()->IsChannelEnabled( LOG_ASSERT, LS_ASSERT ) )
  567. return LR_CONTINUE;
  568. tchar formattedMessage[MAX_LOGGING_MESSAGE_LENGTH];
  569. va_list args;
  570. va_start( args, pMessageFormat );
  571. Tier0Internal_vsntprintf( formattedMessage, MAX_LOGGING_MESSAGE_LENGTH, pMessageFormat, args );
  572. va_end( args );
  573. return GetGlobalLoggingSystem()->LogDirect( LOG_ASSERT, LS_ASSERT, UNSPECIFIED_LOGGING_COLOR, formattedMessage );
  574. }