2
0

consoleLogger.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "console/consoleLogger.h"
  23. #include "console/consoleTypes.h"
  24. #include "console/engineAPI.h"
  25. Vector<ConsoleLogger *> ConsoleLogger::mActiveLoggers;
  26. bool ConsoleLogger::smInitialized = false;
  27. IMPLEMENT_CONOBJECT( ConsoleLogger );
  28. ConsoleDocClass( ConsoleLogger,
  29. "A class designed to be used as a console consumer and log the data it receives to a file.\n\n"
  30. "@see dumpConsoleFunctions\n"
  31. "@see dumpConsoleClasses\n"
  32. "@ingroup Logging\n"
  33. );
  34. //-----------------------------------------------------------------------------
  35. ConsoleLogger::ConsoleLogger()
  36. {
  37. mFilename = NULL;
  38. mLogging = false;
  39. mAppend = false;
  40. mLevel = ConsoleLogEntry::Normal;
  41. }
  42. //-----------------------------------------------------------------------------
  43. ConsoleLogger::ConsoleLogger( const char *fileName, bool append )
  44. {
  45. mLogging = false;
  46. mLevel = ConsoleLogEntry::Normal;
  47. mFilename = StringTable->insert( fileName );
  48. mAppend = append;
  49. init();
  50. }
  51. //-----------------------------------------------------------------------------
  52. ImplementEnumType( LogLevel,
  53. "@brief Priority levels for logging entries\n\n"
  54. "@ingroup Logging")
  55. { ConsoleLogEntry::Normal, "normal", "Lowest priority level, no highlighting." },
  56. { ConsoleLogEntry::Warning, "warning", "Mid level priority, tags and highlights possible issues in blue." },
  57. { ConsoleLogEntry::Error, "error", "Highest priority level, extreme emphasis on this entry. Highlighted in red." },
  58. EndImplementEnumType;
  59. void ConsoleLogger::initPersistFields()
  60. {
  61. docsURL;
  62. addGroup( "Logging" );
  63. addField( "level", TYPEID< ConsoleLogEntry::Level >(), Offset( mLevel, ConsoleLogger ), "Determines the priority level and attention the logged entry gets when recorded\n\n" );
  64. endGroup( "Logging" );
  65. Parent::initPersistFields();
  66. }
  67. //-----------------------------------------------------------------------------
  68. bool ConsoleLogger::processArguments( S32 argc, ConsoleValue *argv )
  69. {
  70. if( argc == 0 )
  71. return false;
  72. bool append = false;
  73. if (argc == 2)
  74. append = argv[1].getBool();
  75. mAppend = append;
  76. mFilename = StringTable->insert( argv[0].getString() );
  77. if( init() )
  78. {
  79. attach();
  80. return true;
  81. }
  82. return false;
  83. }
  84. //-----------------------------------------------------------------------------
  85. ConsoleLogger::~ConsoleLogger()
  86. {
  87. detach();
  88. }
  89. //-----------------------------------------------------------------------------
  90. bool ConsoleLogger::init()
  91. {
  92. if( smInitialized )
  93. return true;
  94. Con::addConsumer( ConsoleLogger::logCallback );
  95. smInitialized = true;
  96. return true;
  97. }
  98. //-----------------------------------------------------------------------------
  99. bool ConsoleLogger::attach()
  100. {
  101. if( mFilename == NULL )
  102. {
  103. Con::errorf( "ConsoleLogger failed to attach: no filename supplied." );
  104. return false;
  105. }
  106. // Check to see if this is initialized before using it
  107. if( !smInitialized )
  108. {
  109. if( !init() )
  110. {
  111. Con::errorf( "ConsoleLogger failed to initalize." );
  112. return false;
  113. }
  114. }
  115. if( mLogging )
  116. return false;
  117. // Open the filestream
  118. mStream.open( mFilename, ( mAppend ? Torque::FS::File::WriteAppend : Torque::FS::File::Write ) );
  119. // Add this to list of active loggers
  120. mActiveLoggers.push_back( this );
  121. mLogging = true;
  122. return true;
  123. }
  124. //-----------------------------------------------------------------------------
  125. bool ConsoleLogger::detach()
  126. {
  127. // Make sure this is valid before messing with it
  128. if( !smInitialized )
  129. {
  130. if( !init() )
  131. {
  132. return false;
  133. }
  134. }
  135. if( !mLogging )
  136. return false;
  137. // Close filestream
  138. mStream.close();
  139. // Remove this object from the list of active loggers
  140. for( S32 i = 0; i < mActiveLoggers.size(); i++ )
  141. {
  142. if( mActiveLoggers[i] == this )
  143. {
  144. mActiveLoggers.erase( i );
  145. mLogging = false;
  146. return true;
  147. }
  148. }
  149. return false; // If this happens, it's bad...
  150. }
  151. //-----------------------------------------------------------------------------
  152. void ConsoleLogger::logCallback( U32 level, const char *consoleLine )
  153. {
  154. ConsoleLogger *curr;
  155. // Loop through active consumers and send them the message
  156. for( int i = 0; i < mActiveLoggers.size(); i++ )
  157. {
  158. curr = mActiveLoggers[i];
  159. // If the log level is within the log threshhold, log it
  160. if( curr->mLevel <= level )
  161. curr->log( consoleLine );
  162. }
  163. }
  164. //-----------------------------------------------------------------------------
  165. void ConsoleLogger::log( const char *consoleLine )
  166. {
  167. // Check to see if this is intalized before using it
  168. if( !smInitialized )
  169. {
  170. if( !init() )
  171. {
  172. Con::errorf( "I don't know how this happened, but log called on this without it being initialized" );
  173. return;
  174. }
  175. }
  176. mStream.writeLine( (U8 *)consoleLine );
  177. }
  178. //-----------------------------------------------------------------------------
  179. DefineEngineMethod( ConsoleLogger, attach, bool, (), , "() Attaches the logger to the console and begins writing to file"
  180. "@tsexample\n"
  181. "// Create the logger\n"
  182. "// Will automatically start writing to testLogging.txt with normal priority\n"
  183. "new ConsoleLogger(logger, \"testLogging.txt\", false);\n\n"
  184. "// Send something to the console, with the logger consumes and writes to file\n"
  185. "echo(\"This is logged to the file\");\n\n"
  186. "// Stop logging, but do not delete the logger\n"
  187. "logger.detach();\n\n"
  188. "echo(\"This is not logged to the file\");\n\n"
  189. "// Attach the logger to the console again\n"
  190. "logger.attach();\n\n"
  191. "// Logging has resumed\n"
  192. "echo(\"Logging has resumed\");"
  193. "@endtsexample\n\n")
  194. {
  195. ConsoleLogger *logger = static_cast<ConsoleLogger *>( object );
  196. return logger->attach();
  197. }
  198. //-----------------------------------------------------------------------------
  199. DefineEngineMethod( ConsoleLogger, detach, bool, (), , "() Detaches the logger from the console and stops writing to file"
  200. "@tsexample\n"
  201. "// Create the logger\n"
  202. "// Will automatically start writing to testLogging.txt with normal priority\n"
  203. "new ConsoleLogger(logger, \"testLogging.txt\", false);\n\n"
  204. "// Send something to the console, with the logger consumes and writes to file\n"
  205. "echo(\"This is logged to the file\");\n\n"
  206. "// Stop logging, but do not delete the logger\n"
  207. "logger.detach();\n\n"
  208. "echo(\"This is not logged to the file\");\n\n"
  209. "// Attach the logger to the console again\n"
  210. "logger.attach();\n\n"
  211. "// Logging has resumed\n"
  212. "echo(\"Logging has resumed\");"
  213. "@endtsexample\n\n")
  214. {
  215. ConsoleLogger *logger = static_cast<ConsoleLogger *>( object );
  216. return logger->detach();
  217. }