Team Fortress 2 Source Code as on 22/4/2020
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.

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