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.

767 lines
34 KiB

  1. //============ Copyright (c) Valve Corporation, All rights reserved. ============
  2. //
  3. // Logging system declarations.
  4. //
  5. // The logging system is a channel-based output mechanism which allows
  6. // subsystems to route their text/diagnostic output to various listeners
  7. //
  8. //===============================================================================
  9. #ifndef LOGGING_H
  10. #define LOGGING_H
  11. #if !defined(__SPU__)
  12. #if defined( COMPILER_MSVC )
  13. #pragma once
  14. #endif
  15. #include "color.h"
  16. #include "icommandline.h"
  17. #include <stdio.h>
  18. // For XBX_** functions
  19. #if defined( _X360 )
  20. #include "xbox/xbox_console.h"
  21. #endif
  22. // Used by CColorizedLoggingListener
  23. #if defined( _WIN32 ) || (defined(POSIX) && !defined(_GAMECONSOLE))
  24. #include "tier0/win32consoleio.h"
  25. #endif
  26. /*
  27. ---- Logging System ----
  28. The logging system is a channel-based mechanism for all code (engine,
  29. mod, tool) across all platforms to output information, warnings,
  30. errors, etc.
  31. This system supersedes the existing Msg(), Warning(), Error(), DevMsg(), ConMsg() etc. functions.
  32. There are channels defined in the new system through which all old messages are routed;
  33. see LOG_GENERAL, LOG_CONSOLE, LOG_DEVELOPER, etc.
  34. To use the system, simply call one of the predefined macros:
  35. Log_Msg( ChannelID, [Color], Message, ... )
  36. Log_Warning( ChannelID, [Color], Message, ... )
  37. Log_Error( ChannelID, [Color], Message, ... )
  38. A ChannelID is typically created by defining a logging channel with the
  39. log channel macros:
  40. DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_ChannelName, "ChannelName", [Flags], [MinimumSeverity], [Color] );
  41. or
  42. BEGIN_DEFINE_LOGGING_CHANNEL( LOG_ChannelName, "ChannelName", [Flags], [MinimumSeverity], [Color] );
  43. ADD_LOGGING_CHANNEL_TAG( "Tag1" );
  44. ADD_LOGGING_CHANNEL_TAG( "Tag2" );
  45. END_DEFINE_LOGGING_CHANNEL();
  46. These macros create a global channel ID variable with the name specified
  47. by the first parameter (in this example, LOG_ChannelName). This channel ID
  48. can be used by various LoggingSystem_** functions to manipulate the channel settings.
  49. The optional [Flags] parameter is an OR'd together set of LoggingChannelFlags_t
  50. values (default: 0).
  51. The optional [MinimumSeverity] parameter is the lowest threshold
  52. above which messages will be processed (inclusive). The default is LS_MESSAGE,
  53. which results in all messages, warnings, and errors being logged.
  54. Variadic parameters to the Log_** functions will be ignored if a channel
  55. is not enabled for a given severity (for performance reasons).
  56. Logging channels can have their minimum severity modified by name, ID, or tag.
  57. Logging channels are not hierarchical since there are situations in which
  58. a channel needs to belong to multiple hierarchies. Use tags to create
  59. categories or shallow hierarchies.
  60. @TODO (Feature wishlist):
  61. 1) Callstack logging support
  62. 2) Registering dynamic channels and unregistering channels at runtime
  63. 3) Sentient robot to clean up the thousands of places using the old/legacy logging system.
  64. */
  65. //////////////////////////////////////////////////////////////////////////
  66. // Constants, Types, Forward Declares
  67. //////////////////////////////////////////////////////////////////////////
  68. class CLoggingSystem;
  69. class CThreadFastMutex;
  70. //-----------------------------------------------------------------------------
  71. // Maximum length of a sprintf'ed logging message.
  72. //-----------------------------------------------------------------------------
  73. const int MAX_LOGGING_MESSAGE_LENGTH = 2048;
  74. //-----------------------------------------------------------------------------
  75. // Maximum length of a channel or tag name.
  76. //-----------------------------------------------------------------------------
  77. const int MAX_LOGGING_IDENTIFIER_LENGTH = 32;
  78. //-----------------------------------------------------------------------------
  79. // Maximum number of logging channels. Increase if needed.
  80. //-----------------------------------------------------------------------------
  81. const int MAX_LOGGING_CHANNEL_COUNT = 256;
  82. //-----------------------------------------------------------------------------
  83. // Maximum number of logging tags across all channels. Increase if needed.
  84. //-----------------------------------------------------------------------------
  85. const int MAX_LOGGING_TAG_COUNT = 1024;
  86. //-----------------------------------------------------------------------------
  87. // Maximum number of characters across all logging tags. Increase if needed.
  88. //-----------------------------------------------------------------------------
  89. const int MAX_LOGGING_TAG_CHARACTER_COUNT = 8192;
  90. //-----------------------------------------------------------------------------
  91. // Maximum number of concurrent logging listeners in a given logging state.
  92. //-----------------------------------------------------------------------------
  93. const int MAX_LOGGING_LISTENER_COUNT = 16;
  94. //-----------------------------------------------------------------------------
  95. // An invalid color set on a channel to imply that it should use
  96. // a device-dependent default color where applicable.
  97. //-----------------------------------------------------------------------------
  98. const Color UNSPECIFIED_LOGGING_COLOR( 0, 0, 0, 0 );
  99. //-----------------------------------------------------------------------------
  100. // An ID returned by the logging system to refer to a logging channel.
  101. //-----------------------------------------------------------------------------
  102. typedef int LoggingChannelID_t;
  103. //-----------------------------------------------------------------------------
  104. // A sentinel value indicating an invalid logging channel ID.
  105. //-----------------------------------------------------------------------------
  106. const LoggingChannelID_t INVALID_LOGGING_CHANNEL_ID = -1;
  107. //-----------------------------------------------------------------------------
  108. // The severity of a logging operation.
  109. //-----------------------------------------------------------------------------
  110. enum LoggingSeverity_t
  111. {
  112. //-----------------------------------------------------------------------------
  113. // An informative logging message.
  114. //-----------------------------------------------------------------------------
  115. LS_MESSAGE = 0,
  116. //-----------------------------------------------------------------------------
  117. // A warning, typically non-fatal
  118. //-----------------------------------------------------------------------------
  119. LS_WARNING = 1,
  120. //-----------------------------------------------------------------------------
  121. // A message caused by an Assert**() operation.
  122. //-----------------------------------------------------------------------------
  123. LS_ASSERT = 2,
  124. //-----------------------------------------------------------------------------
  125. // An error, typically fatal/unrecoverable.
  126. //-----------------------------------------------------------------------------
  127. LS_ERROR = 3,
  128. //-----------------------------------------------------------------------------
  129. // A placeholder level, higher than any legal value.
  130. // Not a real severity value!
  131. //-----------------------------------------------------------------------------
  132. LS_HIGHEST_SEVERITY = 4,
  133. };
  134. //-----------------------------------------------------------------------------
  135. // Action which should be taken by logging system as a result of
  136. // a given logged message.
  137. //
  138. // The logging system invokes ILoggingResponsePolicy::OnLog() on
  139. // the specified policy object, which returns a LoggingResponse_t.
  140. //-----------------------------------------------------------------------------
  141. enum LoggingResponse_t
  142. {
  143. LR_CONTINUE,
  144. LR_DEBUGGER,
  145. LR_ABORT,
  146. };
  147. //-----------------------------------------------------------------------------
  148. // Logging channel behavior flags, set on channel creation.
  149. //-----------------------------------------------------------------------------
  150. enum LoggingChannelFlags_t
  151. {
  152. //-----------------------------------------------------------------------------
  153. // Indicates that the spew is only relevant to interactive consoles.
  154. //-----------------------------------------------------------------------------
  155. LCF_CONSOLE_ONLY = 0x00000001,
  156. //-----------------------------------------------------------------------------
  157. // Indicates that spew should not be echoed to any output devices.
  158. // A suitable logging listener must be registered which respects this flag
  159. // (e.g. a file logger).
  160. //-----------------------------------------------------------------------------
  161. LCF_DO_NOT_ECHO = 0x00000002,
  162. };
  163. //-----------------------------------------------------------------------------
  164. // A callback function used to register tags on a logging channel
  165. // during initialization.
  166. //-----------------------------------------------------------------------------
  167. typedef void ( *RegisterTagsFunc )();
  168. //-----------------------------------------------------------------------------
  169. // A context structure passed to logging listeners and response policy classes.
  170. //-----------------------------------------------------------------------------
  171. struct LoggingContext_t
  172. {
  173. // ID of the channel being logged to.
  174. LoggingChannelID_t m_ChannelID;
  175. // Flags associated with the channel.
  176. LoggingChannelFlags_t m_Flags;
  177. // Severity of the logging event.
  178. LoggingSeverity_t m_Severity;
  179. // Color of logging message if one was specified to Log_****() macro.
  180. // If not specified, falls back to channel color.
  181. // If channel color is not specified, this value is UNSPECIFIED_LOGGING_COLOR
  182. // and indicates that a suitable default should be chosen.
  183. Color m_Color;
  184. };
  185. //-----------------------------------------------------------------------------
  186. // Interface for classes to handle logging output.
  187. //
  188. // The Log() function of this class is called synchronously and serially
  189. // by the logging system on all registered instances of ILoggingListener
  190. // in the current "logging state".
  191. //
  192. // Derived classes may do whatever they want with the message (write to disk,
  193. // write to console, send over the network, drop on the floor, etc.).
  194. //
  195. // In general, derived classes should do one, simple thing with the output
  196. // to allow callers to register multiple, orthogonal logging listener classes.
  197. //-----------------------------------------------------------------------------
  198. class ILoggingListener
  199. {
  200. public:
  201. virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage ) = 0;
  202. };
  203. //-----------------------------------------------------------------------------
  204. // Interface for policy classes which determine how to behave when a
  205. // message is logged.
  206. //
  207. // Can return:
  208. // LR_CONTINUE (continue execution)
  209. // LR_DEBUGGER (break into debugger if one is present, otherwise continue)
  210. // LR_ABORT (terminate process immediately with a failure code of 1)
  211. //-----------------------------------------------------------------------------
  212. class ILoggingResponsePolicy
  213. {
  214. public:
  215. virtual LoggingResponse_t OnLog( const LoggingContext_t *pContext ) = 0;
  216. };
  217. //////////////////////////////////////////////////////////////////////////
  218. // Common Logging Listeners & Logging Response Policies
  219. //////////////////////////////////////////////////////////////////////////
  220. //-----------------------------------------------------------------------------
  221. // A basic logging listener which prints to stdout and the debug channel.
  222. //-----------------------------------------------------------------------------
  223. class CSimpleLoggingListener : public ILoggingListener
  224. {
  225. public:
  226. CSimpleLoggingListener( bool bQuietPrintf = false, bool bQuietDebugger = false ) :
  227. m_bQuietPrintf( bQuietPrintf ),
  228. m_bQuietDebugger( bQuietDebugger )
  229. {
  230. }
  231. virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage )
  232. {
  233. #ifdef _X360
  234. if ( !m_bQuietDebugger && XBX_IsConsoleConnected() )
  235. {
  236. // send to console
  237. XBX_DebugString( XMAKECOLOR( 0,0,0 ), pMessage );
  238. }
  239. else
  240. #endif
  241. {
  242. #if !defined( _CERT ) && !defined( DBGFLAG_STRINGS_STRIP )
  243. if ( !m_bQuietPrintf )
  244. {
  245. _tprintf( _T("%s"), pMessage );
  246. }
  247. #endif
  248. #ifdef _WIN32
  249. if ( !m_bQuietDebugger && Plat_IsInDebugSession() )
  250. {
  251. Plat_DebugString( pMessage );
  252. }
  253. #endif
  254. }
  255. }
  256. // If set to true, does not print anything to stdout.
  257. bool m_bQuietPrintf;
  258. // If set to true, does not print anything to debugger.
  259. bool m_bQuietDebugger;
  260. };
  261. //-----------------------------------------------------------------------------
  262. // A basic logging listener for GUI applications
  263. //-----------------------------------------------------------------------------
  264. class CSimpleWindowsLoggingListener : public ILoggingListener
  265. {
  266. public:
  267. virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage )
  268. {
  269. if ( Plat_IsInDebugSession() )
  270. {
  271. Plat_DebugString( pMessage );
  272. }
  273. if ( pContext->m_Severity == LS_ERROR )
  274. {
  275. if ( Plat_IsInDebugSession() )
  276. DebuggerBreak();
  277. Plat_MessageBox( "Error", pMessage );
  278. }
  279. }
  280. };
  281. //-----------------------------------------------------------------------------
  282. // ** NOTE FOR INTEGRATION **
  283. // This was copied over from source 2 rather than integrated because
  284. // source 2 has more significantly refactored tier0 logging.
  285. //
  286. // A logging listener with Win32 console API color support which which prints
  287. // to stdout and the debug channel.
  288. //-----------------------------------------------------------------------------
  289. #if !defined(_GAMECONSOLE)
  290. class CColorizedLoggingListener : public CSimpleLoggingListener
  291. {
  292. public:
  293. CColorizedLoggingListener( bool bQuietPrintf = false, bool bQuietDebugger = false ) : CSimpleLoggingListener( bQuietPrintf, bQuietDebugger )
  294. {
  295. InitWin32ConsoleColorContext( &m_ColorContext );
  296. }
  297. virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage )
  298. {
  299. if ( !m_bQuietPrintf )
  300. {
  301. int nPrevColor = -1;
  302. if ( pContext->m_Color != UNSPECIFIED_LOGGING_COLOR )
  303. {
  304. nPrevColor = SetWin32ConsoleColor( &m_ColorContext,
  305. pContext->m_Color.r(), pContext->m_Color.g(), pContext->m_Color.b(),
  306. MAX( MAX( pContext->m_Color.r(), pContext->m_Color.g() ), pContext->m_Color.b() ) > 128 );
  307. }
  308. _tprintf( _T("%s"), pMessage );
  309. if ( nPrevColor >= 0 )
  310. {
  311. RestoreWin32ConsoleColor( &m_ColorContext, nPrevColor );
  312. }
  313. }
  314. #ifdef _WIN32
  315. if ( !m_bQuietDebugger && Plat_IsInDebugSession() )
  316. {
  317. Plat_DebugString( pMessage );
  318. }
  319. #endif
  320. }
  321. Win32ConsoleColorContext_t m_ColorContext;
  322. };
  323. #endif // !_GAMECONSOLE
  324. //-----------------------------------------------------------------------------
  325. // Default logging response policy used when one is not specified.
  326. //-----------------------------------------------------------------------------
  327. class CDefaultLoggingResponsePolicy : public ILoggingResponsePolicy
  328. {
  329. public:
  330. virtual LoggingResponse_t OnLog( const LoggingContext_t *pContext )
  331. {
  332. if ( pContext->m_Severity == LS_ASSERT && !CommandLine()->FindParm( "-noassert" ) )
  333. {
  334. return LR_DEBUGGER;
  335. }
  336. else if ( pContext->m_Severity == LS_ERROR )
  337. {
  338. return LR_ABORT;
  339. }
  340. else
  341. {
  342. return LR_CONTINUE;
  343. }
  344. }
  345. };
  346. //-----------------------------------------------------------------------------
  347. // A logging response policy which never terminates the process, even on error.
  348. //-----------------------------------------------------------------------------
  349. class CNonFatalLoggingResponsePolicy : public ILoggingResponsePolicy
  350. {
  351. public:
  352. virtual LoggingResponse_t OnLog( const LoggingContext_t *pContext )
  353. {
  354. if ( ( pContext->m_Severity == LS_ASSERT && !CommandLine()->FindParm( "-noassert" ) ) || pContext->m_Severity == LS_ERROR )
  355. {
  356. return LR_DEBUGGER;
  357. }
  358. else
  359. {
  360. return LR_CONTINUE;
  361. }
  362. }
  363. };
  364. //////////////////////////////////////////////////////////////////////////
  365. // Central Logging System
  366. //////////////////////////////////////////////////////////////////////////
  367. //-----------------------------------------------------------------------------
  368. // The central logging system.
  369. //
  370. // Multiple instances can exist, though all exported tier0 functionality
  371. // specifically works with a single global instance
  372. // (via GetGlobalLoggingSystem()).
  373. //-----------------------------------------------------------------------------
  374. class CLoggingSystem
  375. {
  376. public:
  377. struct LoggingChannel_t;
  378. CLoggingSystem();
  379. ~CLoggingSystem();
  380. //-----------------------------------------------------------------------------
  381. // Register a logging channel with the logging system.
  382. // The same channel can be registered multiple times, but the parameters
  383. // in each call to RegisterLoggingChannel must either match across all calls
  384. // or be set to defaults on any given call
  385. //
  386. // This function is not thread-safe and should generally only be called
  387. // by a single thread. Using the logging channel definition macros ensures
  388. // that this is called on the static initialization thread.
  389. //-----------------------------------------------------------------------------
  390. LoggingChannelID_t RegisterLoggingChannel( const char *pChannelName, RegisterTagsFunc registerTagsFunc, int flags = 0, LoggingSeverity_t minimumSeverity = LS_MESSAGE, Color spewColor = UNSPECIFIED_LOGGING_COLOR );
  391. //-----------------------------------------------------------------------------
  392. // Gets a channel ID from a string name.
  393. // Performs a simple linear search; cache the value whenever possible
  394. // or re-register the logging channel to get a global ID.
  395. //-----------------------------------------------------------------------------
  396. LoggingChannelID_t FindChannel( const char *pChannelName ) const;
  397. int GetChannelCount() const { return m_nChannelCount; }
  398. //-----------------------------------------------------------------------------
  399. // Gets a pointer to the logging channel description.
  400. //-----------------------------------------------------------------------------
  401. LoggingChannel_t *GetChannel( LoggingChannelID_t channelID );
  402. const LoggingChannel_t *GetChannel( LoggingChannelID_t channelID ) const;
  403. //-----------------------------------------------------------------------------
  404. // Returns true if the given channel has the specified tag.
  405. //-----------------------------------------------------------------------------
  406. bool HasTag( LoggingChannelID_t channelID, const char *pTag ) const { return GetChannel( channelID )->HasTag( pTag ); }
  407. //-----------------------------------------------------------------------------
  408. // Returns true if the given channel has been initialized.
  409. // The main purpose is catching m_nChannelCount being zero because no channels have been registered.
  410. //-----------------------------------------------------------------------------
  411. bool IsValidChannelID( LoggingChannelID_t channelID ) const { return ( channelID >= 0 ) && ( channelID < m_nChannelCount ); }
  412. //-----------------------------------------------------------------------------
  413. // Returns true if the given channel will spew at the given severity level.
  414. //-----------------------------------------------------------------------------
  415. bool IsChannelEnabled( LoggingChannelID_t channelID, LoggingSeverity_t severity ) const { return IsValidChannelID( channelID ) && GetChannel( channelID )->IsEnabled( severity ); }
  416. //-----------------------------------------------------------------------------
  417. // Functions to set the spew level of a channel either directly by ID or
  418. // string name, or for all channels with a given tag.
  419. //
  420. // These functions are not technically thread-safe but calling them across
  421. // multiple threads should cause no significant problems
  422. // (the underlying data types being changed are 32-bit/atomic).
  423. //-----------------------------------------------------------------------------
  424. void SetChannelSpewLevel( LoggingChannelID_t channelID, LoggingSeverity_t minimumSeverity );
  425. void SetChannelSpewLevelByName( const char *pName, LoggingSeverity_t minimumSeverity );
  426. void SetChannelSpewLevelByTag( const char *pTag, LoggingSeverity_t minimumSeverity );
  427. void SetGlobalSpewLevel( LoggingSeverity_t minimumSeverity );
  428. //-----------------------------------------------------------------------------
  429. // Gets or sets the color of a logging channel.
  430. // (The functions are not thread-safe, but the consequences are not
  431. // significant.)
  432. //-----------------------------------------------------------------------------
  433. Color GetChannelColor( LoggingChannelID_t channelID ) const { return GetChannel( channelID )->m_SpewColor; }
  434. void SetChannelColor( LoggingChannelID_t channelID, Color color ) { GetChannel( channelID )->m_SpewColor = color; }
  435. //-----------------------------------------------------------------------------
  436. // Gets or sets the flags on a logging channel.
  437. // (The functions are not thread-safe, but the consequences are not
  438. // significant.)
  439. //-----------------------------------------------------------------------------
  440. LoggingChannelFlags_t GetChannelFlags( LoggingChannelID_t channelID ) const { return GetChannel( channelID )->m_Flags; }
  441. void SetChannelFlags( LoggingChannelID_t channelID, LoggingChannelFlags_t flags ) { GetChannel( channelID )->m_Flags = flags; }
  442. //-----------------------------------------------------------------------------
  443. // Adds a string tag to a channel.
  444. // This is not thread-safe and should only be called by a RegisterTagsFunc
  445. // callback passed in to RegisterLoggingChannel (via the
  446. // channel definition macros).
  447. //-----------------------------------------------------------------------------
  448. void AddTagToCurrentChannel( const char *pTagName );
  449. //-----------------------------------------------------------------------------
  450. // Functions to save/restore the current logging state.
  451. // Set bThreadLocal to true on a matching Push/Pop call if the intent
  452. // is to override the logging listeners on the current thread only.
  453. //
  454. // Pushing the current logging state onto the state stack results
  455. // in the current state being cleared by default (no listeners, default logging response policy).
  456. // Set bClearState to false to copy the existing listener pointers to the new state.
  457. //
  458. // These functions which mutate logging state ARE thread-safe and are
  459. // guarded by m_StateMutex.
  460. //-----------------------------------------------------------------------------
  461. void PushLoggingState( bool bThreadLocal = false, bool bClearState = true );
  462. void PopLoggingState( bool bThreadLocal = false );
  463. //-----------------------------------------------------------------------------
  464. // Registers a logging listener (a class which handles logged messages).
  465. //-----------------------------------------------------------------------------
  466. void RegisterLoggingListener( ILoggingListener *pListener );
  467. //-----------------------------------------------------------------------------
  468. // Returns whether the specified logging listener is registered.
  469. //-----------------------------------------------------------------------------
  470. bool IsListenerRegistered( ILoggingListener *pListener );
  471. //-----------------------------------------------------------------------------
  472. // Clears out all of the current logging state (removes all listeners,
  473. // sets the response policy to the default).
  474. //-----------------------------------------------------------------------------
  475. void ResetCurrentLoggingState();
  476. //-----------------------------------------------------------------------------
  477. // Sets a policy class to decide what should happen when messages of a
  478. // particular severity are logged
  479. // (e.g. exit on error, break into debugger).
  480. // If pLoggingResponse is NULL, uses the default response policy class.
  481. //-----------------------------------------------------------------------------
  482. void SetLoggingResponsePolicy( ILoggingResponsePolicy *pLoggingResponse );
  483. //-----------------------------------------------------------------------------
  484. // Logs a message to the specified channel using a given severity and
  485. // spew color. Passing in UNSPECIFIED_LOGGING_COLOR for 'color' allows
  486. // the logging listeners to provide a default.
  487. // NOTE: test 'IsChannelEnabled(channelID,severity)' before calling this!
  488. //-----------------------------------------------------------------------------
  489. LoggingResponse_t LogDirect( LoggingChannelID_t channelID, LoggingSeverity_t severity, Color color, const tchar *pMessage );
  490. // Internal data to represent a logging tag
  491. struct LoggingTag_t
  492. {
  493. const char *m_pTagName;
  494. LoggingTag_t *m_pNextTag;
  495. };
  496. // Internal data to represent a logging channel.
  497. struct LoggingChannel_t
  498. {
  499. bool HasTag( const char *pTag ) const
  500. {
  501. LoggingTag_t *pCurrentTag = m_pFirstTag;
  502. while( pCurrentTag != NULL )
  503. {
  504. if ( stricmp( pCurrentTag->m_pTagName, pTag ) == 0 )
  505. {
  506. return true;
  507. }
  508. pCurrentTag = pCurrentTag->m_pNextTag;
  509. }
  510. return false;
  511. }
  512. bool IsEnabled( LoggingSeverity_t severity ) const { return severity >= m_MinimumSeverity; }
  513. void SetSpewLevel( LoggingSeverity_t severity ) { m_MinimumSeverity = severity; }
  514. LoggingChannelID_t m_ID;
  515. LoggingChannelFlags_t m_Flags; // an OR'd combination of LoggingChannelFlags_t
  516. LoggingSeverity_t m_MinimumSeverity; // The minimum severity level required to activate this channel.
  517. Color m_SpewColor;
  518. char m_Name[MAX_LOGGING_IDENTIFIER_LENGTH];
  519. LoggingTag_t *m_pFirstTag;
  520. };
  521. private:
  522. // Represents the current state of the logger (registered listeners, response policy class, etc.) and can
  523. // vary from thread-to-thread. It can also be pushed/popped to save/restore listener/response state.
  524. struct LoggingState_t
  525. {
  526. // Index of the previous entry on the listener set stack.
  527. int m_nPreviousStackEntry;
  528. // Number of active listeners in this set. Cannot exceed MAX_LOGGING_LISTENER_COUNT.
  529. // If set to -1, implies that this state structure is not in use.
  530. int m_nListenerCount;
  531. // Array of registered logging listener objects.
  532. ILoggingListener *m_RegisteredListeners[MAX_LOGGING_LISTENER_COUNT];
  533. // Specific policy class to determine behavior of logging system under specific message types.
  534. ILoggingResponsePolicy *m_pLoggingResponse;
  535. };
  536. // These state functions to assume the caller has already grabbed the mutex.
  537. LoggingState_t *GetCurrentState();
  538. const LoggingState_t *GetCurrentState() const;
  539. int FindUnusedStateIndex();
  540. LoggingTag_t *AllocTag( const char *pTagName );
  541. int m_nChannelCount;
  542. LoggingChannel_t m_RegisteredChannels[MAX_LOGGING_CHANNEL_COUNT];
  543. int m_nChannelTagCount;
  544. LoggingTag_t m_ChannelTags[MAX_LOGGING_TAG_COUNT];
  545. // Index to first free character in name pool.
  546. int m_nTagNamePoolIndex;
  547. // Pool of character data used for tag names.
  548. char m_TagNamePool[MAX_LOGGING_TAG_CHARACTER_COUNT];
  549. // Protects all data in this class except the registered channels
  550. // (which are supposed to be registered using the macros at static/global init time).
  551. // It is assumed that this mutex is reentrant safe on all platforms.
  552. CThreadFastMutex *m_pStateMutex;
  553. // The index of the current "global" state of the logging system. By default, all threads use this state
  554. // for logging unless a given thread has pushed the logging state with bThreadLocal == true.
  555. // If a thread-local state has been pushed, g_nThreadLocalStateIndex (a global thread-local integer) will be non-zero.
  556. // By default, g_nThreadLocalStateIndex is 0 for all threads.
  557. int m_nGlobalStateIndex;
  558. // A pool of logging states used to store a stack (potentially per-thread).
  559. static const int MAX_LOGGING_STATE_COUNT = 16;
  560. LoggingState_t m_LoggingStates[MAX_LOGGING_STATE_COUNT];
  561. // Default policy class which determines behavior.
  562. CDefaultLoggingResponsePolicy m_DefaultLoggingResponse;
  563. // Default spew function.
  564. CSimpleLoggingListener m_DefaultLoggingListener;
  565. };
  566. //////////////////////////////////////////////////////////////////////////
  567. // Logging Macros
  568. //////////////////////////////////////////////////////////////////////////
  569. // This macro will resolve to the most appropriate overload of LoggingSystem_Log() depending on the number of parameters passed in.
  570. #ifdef DBGFLAG_STRINGS_STRIP
  571. #define InternalMsg( Channel, Severity, /* [Color], Message, */ ... ) do { if ( Severity == LS_ERROR && LoggingSystem_IsChannelEnabled( Channel, Severity ) ) LoggingSystem_Log( Channel, Severity, /* [Color], Message, */ ##__VA_ARGS__ ); } while( 0 )
  572. #else
  573. #define InternalMsg( Channel, Severity, /* [Color], Message, */ ... ) do { if ( LoggingSystem_IsChannelEnabled( Channel, Severity ) ) LoggingSystem_Log( Channel, Severity, /* [Color], Message, */ ##__VA_ARGS__ ); } while( 0 )
  574. #endif
  575. //-----------------------------------------------------------------------------
  576. // New macros, use these!
  577. //
  578. // The macros take an optional Color parameter followed by the message
  579. // and the message formatting.
  580. // We rely on the variadic macro (__VA_ARGS__) operator to paste in the
  581. // extra parameters and resolve to the appropriate overload.
  582. //-----------------------------------------------------------------------------
  583. #define Log_Msg( Channel, /* [Color], Message, */ ... ) InternalMsg( Channel, LS_MESSAGE, /* [Color], Message, */ ##__VA_ARGS__ )
  584. #define Log_Warning( Channel, /* [Color], Message, */ ... ) InternalMsg( Channel, LS_WARNING, /* [Color], Message, */ ##__VA_ARGS__ )
  585. #define Log_Error( Channel, /* [Color], Message, */ ... ) InternalMsg( Channel, LS_ERROR, /* [Color], Message, */ ##__VA_ARGS__ )
  586. #ifdef DBGFLAG_STRINGS_STRIP
  587. #define Log_Assert( ... ) LR_CONTINUE
  588. #else
  589. #define Log_Assert( Message, ... ) LoggingSystem_LogAssert( Message, ##__VA_ARGS__ )
  590. #endif
  591. #define DECLARE_LOGGING_CHANNEL( Channel ) extern LoggingChannelID_t Channel
  592. #define DEFINE_LOGGING_CHANNEL_NO_TAGS( Channel, ChannelName, /* [Flags], [Severity], [Color] */ ... ) \
  593. LoggingChannelID_t Channel = LoggingSystem_RegisterLoggingChannel( ChannelName, NULL, ##__VA_ARGS__ )
  594. #define BEGIN_DEFINE_LOGGING_CHANNEL( Channel, ChannelName, /* [Flags], [Severity], [Color] */ ... ) \
  595. static void Register_##Channel##_Tags(); \
  596. LoggingChannelID_t Channel = LoggingSystem_RegisterLoggingChannel( ChannelName, Register_##Channel##_Tags, ##__VA_ARGS__ ); \
  597. void Register_##Channel##_Tags() \
  598. {
  599. #define ADD_LOGGING_CHANNEL_TAG( Tag ) LoggingSystem_AddTagToCurrentChannel( Tag )
  600. #define END_DEFINE_LOGGING_CHANNEL() \
  601. }
  602. //////////////////////////////////////////////////////////////////////////
  603. // DLL Exports
  604. //////////////////////////////////////////////////////////////////////////
  605. // For documentation on these functions, please look at the corresponding function
  606. // in CLoggingSystem (unless otherwise specified).
  607. PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_RegisterLoggingChannel( const char *pName, RegisterTagsFunc registerTagsFunc, int flags = 0, LoggingSeverity_t severity = LS_MESSAGE, Color color = UNSPECIFIED_LOGGING_COLOR );
  608. PLATFORM_INTERFACE void LoggingSystem_RegisterLoggingListener( ILoggingListener *pListener );
  609. PLATFORM_INTERFACE void LoggingSystem_UnregisterLoggingListener(ILoggingListener *pListener);
  610. PLATFORM_INTERFACE void LoggingSystem_ResetCurrentLoggingState();
  611. PLATFORM_INTERFACE void LoggingSystem_SetLoggingResponsePolicy( ILoggingResponsePolicy *pResponsePolicy );
  612. // NOTE: PushLoggingState() saves the current logging state on a stack and results in a new clear state
  613. // (no listeners, default logging response policy).
  614. PLATFORM_INTERFACE void LoggingSystem_PushLoggingState( bool bThreadLocal = false, bool bClearState = true );
  615. PLATFORM_INTERFACE void LoggingSystem_PopLoggingState( bool bThreadLocal = false );
  616. PLATFORM_INTERFACE void LoggingSystem_AddTagToCurrentChannel( const char *pTagName );
  617. // Returns INVALID_LOGGING_CHANNEL_ID if not found
  618. PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_FindChannel( const char *pChannelName );
  619. PLATFORM_INTERFACE int LoggingSystem_GetChannelCount();
  620. PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_GetFirstChannelID();
  621. // Returns INVALID_LOGGING_CHANNEL_ID when there are no channels remaining.
  622. PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_GetNextChannelID( LoggingChannelID_t channelID );
  623. PLATFORM_INTERFACE const CLoggingSystem::LoggingChannel_t *LoggingSystem_GetChannel( LoggingChannelID_t channelID );
  624. PLATFORM_INTERFACE bool LoggingSystem_HasTag( LoggingChannelID_t channelID, const char *pTag );
  625. PLATFORM_INTERFACE bool LoggingSystem_IsChannelEnabled( LoggingChannelID_t channelID, LoggingSeverity_t severity );
  626. PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevel( LoggingChannelID_t channelID, LoggingSeverity_t minimumSeverity );
  627. PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevelByName( const char *pName, LoggingSeverity_t minimumSeverity );
  628. PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevelByTag( const char *pTag, LoggingSeverity_t minimumSeverity );
  629. PLATFORM_INTERFACE void LoggingSystem_SetGlobalSpewLevel( LoggingSeverity_t minimumSeverity );
  630. // Color is represented as an int32 due to C-linkage restrictions
  631. PLATFORM_INTERFACE int32 LoggingSystem_GetChannelColor( LoggingChannelID_t channelID );
  632. PLATFORM_INTERFACE void LoggingSystem_SetChannelColor( LoggingChannelID_t channelID, int color );
  633. PLATFORM_INTERFACE LoggingChannelFlags_t LoggingSystem_GetChannelFlags( LoggingChannelID_t channelID );
  634. PLATFORM_INTERFACE void LoggingSystem_SetChannelFlags( LoggingChannelID_t channelID, LoggingChannelFlags_t flags );
  635. //-----------------------------------------------------------------------------
  636. // Logs a variable-argument to a given channel with the specified severity.
  637. // NOTE: if adding overloads to this function, remember that the Log_***
  638. // macros simply pass their variadic parameters through to LoggingSystem_Log().
  639. // Therefore, you need to ensure that the parameters are in the same general
  640. // order and that there are no ambiguities with the overload.
  641. //-----------------------------------------------------------------------------
  642. PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_Log( LoggingChannelID_t channelID, LoggingSeverity_t severity, PRINTF_FORMAT_STRING const char *pMessageFormat, ... ) FMTFUNCTION( 3, 4 );
  643. PLATFORM_OVERLOAD LoggingResponse_t LoggingSystem_Log( LoggingChannelID_t channelID, LoggingSeverity_t severity, Color spewColor, PRINTF_FORMAT_STRING const char *pMessageFormat, ... ) FMTFUNCTION( 4, 5 );
  644. PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_LogDirect( LoggingChannelID_t channelID, LoggingSeverity_t severity, Color spewColor, const char *pMessage );
  645. PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_LogAssert( PRINTF_FORMAT_STRING const char *pMessageFormat, ... ) FMTFUNCTION( 1, 2 );
  646. #endif //#if !defined(__SPU__)
  647. #endif // LOGGING_H