00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "CeylanLogAggregatorHTML.h"
00028
00029
00030 #include "CeylanOperators.h"
00031 #include "CeylanFile.h"
00032 #include "CeylanHolder.h"
00033 #include "CeylanDirectory.h"
00034 #include "CeylanTimestamp.h"
00035 #include "CeylanStringUtils.h"
00036
00037 #include "CeylanLogPlug.h"
00038 #include "CeylanLogChannel.h"
00039 #include "CeylanLogMessage.h"
00040 #include "CeylanLogLight.h"
00041
00042
00043 #ifdef CEYLAN_USES_CONFIG_H
00044 #include "CeylanConfig.h"
00045 #endif // CEYLAN_USES_CONFIG_H
00046
00047
00048
00049 #include <iostream>
00050
00051
00052 using std::string ;
00053 using std::list ;
00054
00055 using namespace Ceylan::Log ;
00056 using namespace Ceylan::System ;
00057
00058
00059 #include "CeylanLogAggregatorHTMLFragments.h"
00060
00061
00062
00063 const LevelOfDetail LogAggregatorHTML::DefaultGlobalLevelOfDetail
00064 = MaximumLevelOfDetailForMessage ;
00065
00066 const string LogAggregatorHTML::HTMLPageSuffix = ".html" ;
00067
00068
00069
00070 LogAggregatorHTML::LogAggregatorHTML(
00071 const string & callerDescription,
00072 const string & logDirectoryName,
00073 bool useGlobalLevelOfDetail,
00074 bool beSmart ) :
00075 LogAggregator( beSmart, useGlobalLevelOfDetail ),
00076 _callerDescription( callerDescription ),
00077 _logDirectoryName( logDirectoryName ),
00078 _outputDirectory( 0 )
00079 {
00080
00081
00082 try
00083 {
00084
00085
00086
00087
00088
00089
00090
00091 CEYLAN_LOG( "LogAggregatorHTML constructor: creating directory '"
00092 + _logDirectoryName + "'" ) ;
00093
00094 _outputDirectory = & System::Directory::Create( _logDirectoryName ) ;
00095
00096 }
00097 catch( const System::DirectoryException & e )
00098 {
00099 throw LogAggregatorException( "LogAggregatorHTML constructor: "
00100 "could not create LogAggregatorHTML output directory, "
00101 + _logDirectoryName + ": " + e.toString() ) ;
00102 }
00103
00104 }
00105
00106
00107
00108 LogAggregatorHTML::~LogAggregatorHTML() throw()
00109 {
00110
00111 CEYLAN_LOG( "LogAggregatorHTML destructor called" ) ;
00112
00113 if ( _beSmart )
00114 {
00115
00116 CEYLAN_LOG( "LogAggregatorHTML is smart, "
00117 "therefore automatically triggers log aggregation on exit." ) ;
00118
00119 try
00120 {
00121 aggregate() ;
00122 }
00123 catch( const LogAggregatorException & e )
00124 {
00125
00126 std::cerr << "Error while aggregating logs "
00127 "in LogAggregatorHTML destructor: "
00128 << e.toString() << std::endl ;
00129
00130 }
00131
00132 }
00133
00134 if ( _outputDirectory != 0 )
00135 delete _outputDirectory ;
00136
00137 }
00138
00139
00140
00141 void LogAggregatorHTML::aggregate()
00142 {
00143
00144 CEYLAN_LOG( "LogAggregatorHTML aggregation started" ) ;
00145
00146 #if CEYLAN_DEBUG
00147 if ( _outputDirectory == 0 )
00148 throw LogAggregatorException( "LogAggregatorHTML::aggregate: "
00149 "null output directory pointer." ) ;
00150 #endif // CEYLAN_DEBUG
00151
00152 try
00153 {
00154
00155 Timestamp stampBegin ;
00156
00157
00158
00159 File & framesetPage = File::Create(
00160 Directory::JoinPath( _outputDirectory->getPath(),
00161 "index" + HTMLPageSuffix ) ) ;
00162
00163 string newFrameset = FrameSet ;
00164
00165 Ceylan::substituteInString( newFrameset, "ST_CALLER_DESCRIPTION",
00166 Ceylan::encodeToHTML( _callerDescription ) ) ;
00167
00168 framesetPage.write( newFrameset ) ;
00169
00170 delete & framesetPage ;
00171
00172
00173
00174
00175
00176
00177
00178 Holder<File> defaultPageFileHolder( File::Create(
00179 Directory::JoinPath( _outputDirectory->getPath(),
00180 "MainLog" + HTMLPageSuffix ) ) ) ;
00181
00182
00183 defaultPageFileHolder->write( DefaultPageHeader ) ;
00184
00185 defaultPageFileHolder->write( "Log plug session initiated for source "
00186 + LogPlug::GetSourceName() ) ;
00187
00188 defaultPageFileHolder->write( "<p>" + stampBegin.toString()
00189 + " Aggregation of Log messages started.</p>\n" ) ;
00190
00191
00192
00193
00194
00195
00196
00197 Holder<File> logBrowserMenuFileHolder( File::Create(
00198 Directory::JoinPath( _outputDirectory->getPath(),
00199 "LogSystem" + HTMLPageSuffix ) ) ) ;
00200
00201 logBrowserMenuFileHolder->write( MenuHeader ) ;
00202
00203
00204 CEYLAN_LOG( "####### Writing channels now." ) ;
00205
00206 for ( list<LogChannel *>::const_iterator it = _channelList.begin() ;
00207 it != _channelList.end(); it++ )
00208 {
00209
00210 CEYLAN_LOG( "Creating menu entry for channel " + (*it)->getName()
00211 + " which has " + Ceylan::toString( (*it)->getMessageCount() )
00212 + " message(s)." ) ;
00213
00214
00215 logBrowserMenuFileHolder->write(
00216 "<tr><td>[<a href=\""
00217 + File::TransformIntoValidFilename( (*it)->getName() )
00218 + ".html\" target=\"mainFrame\">"
00219 + Ceylan::toString( (*it)->getMessageCount() )
00220 + "</a>]</td><td><a href=\""
00221 + File::TransformIntoValidFilename( (*it)->getName() )
00222 + ".html\" target=\"mainFrame\">"
00223 + Ceylan::encodeToHTML( (*it)->getName() ) + "</a></td></tr>\n"
00224 ) ;
00225
00226 CEYLAN_LOG( "Creating channel page for channel " + (*it)->getName()
00227 + " which has " + Ceylan::toString( (*it)->getMessageCount() )
00228 + " message(s)." ) ;
00229
00230
00231 write( * (*it) ) ;
00232
00233 CEYLAN_LOG( "Channel " + (*it)->getName() + " managed." ) ;
00234
00235 }
00236
00237 CEYLAN_LOG( "####### Channels written." ) ;
00238
00239 logBrowserMenuFileHolder->write( MenuFooter ) ;
00240
00241
00242
00243 Timestamp stampEnd ;
00244 defaultPageFileHolder->write( "<p>" + stampEnd.toString()
00245 + " Aggregation of Log messages ended.</p>\n" ) ;
00246 defaultPageFileHolder->write( DefaultPageFooter ) ;
00247
00248 std::cout << std::endl << "Logs can be inspected from file://"
00249 << _outputDirectory->getPath() << "/index.html" << std::endl ;
00250
00251
00252
00253 }
00254 catch( const SystemException & e )
00255 {
00256
00257
00258
00259 throw LogAggregatorException( "LogAggregatorHTML::aggregate: "
00260 "file-related operation failed: " + e.toString() ) ;
00261
00262 }
00263
00264 }
00265
00266
00267
00268 void LogAggregatorHTML::store( LogMessage & message )
00269 {
00270
00271 CEYLAN_LOG( "Storing a new message " + message.toString() ) ;
00272
00273
00274 LogAggregator::store( message ) ;
00275
00276 }
00277
00278
00279
00280 const string LogAggregatorHTML::toString( Ceylan::VerbosityLevels level ) const
00281 {
00282
00283 return "This is an HTML log aggregator. "
00284 + LogAggregator::toString( level ) ;
00285
00286 }
00287
00288
00289
00290
00291
00292
00293
00294
00295 void LogAggregatorHTML::write( const LogChannel & channel ) const
00296 {
00297
00298 CEYLAN_LOG( "Writing on disk channel '" + Ceylan::toString( & channel )
00299 + "': " + channel.toString( Ceylan::high ) ) ;
00300
00301 Holder<File> logChannelPageHolderFile( File::Create(
00302 Directory::JoinPath( _outputDirectory->getPath(),
00303 File::TransformIntoValidFilename( channel.getName() )
00304 + HTMLPageSuffix ) ) ) ;
00305
00306 LevelOfDetail sourceLevelOfDetail ;
00307
00308 WriteChannelHeader( channel, logChannelPageHolderFile.get() ) ;
00309
00310
00311 if ( _useGlobalLevelOfDetail )
00312 sourceLevelOfDetail = _globalLevelOfDetail ;
00313 else
00314 sourceLevelOfDetail = MaximumLevelOfDetailForMessage ;
00315
00316 for ( list<LogMessage *>::const_iterator it =
00317 channel._messages.begin(); it != channel._messages.end() ; it++ )
00318 {
00319
00320 #if CEYLAN_DEBUG
00321 if ( (*it) == 0 )
00322 {
00323 CEYLAN_LOG( "Error, LogAggregatorHTML::write: "
00324 "null pointer in message list, skipping." ) ;
00325 break ;
00326 }
00327 #endif // CEYLAN_DEBUG
00328
00329 write( * (*it), logChannelPageHolderFile.get() ) ;
00330
00331 }
00332
00333 WriteChannelFooter( channel, logChannelPageHolderFile.get() ) ;
00334
00335
00336 }
00337
00338
00339
00340 void LogAggregatorHTML::write( const LogMessage & message,
00341 Ceylan::System::File & targetFile ) const
00342 {
00343
00344 CEYLAN_LOG( "Writing on disk message " + message.toString() ) ;
00345
00346 try
00347 {
00348
00349
00350
00351
00352
00353
00354 targetFile.write( "<li>"
00355 + message.getPreformattedText()
00356 + "</li>\n" ) ;
00357
00358 }
00359 catch( const OutputStream::WriteFailedException & e )
00360 {
00361
00362 throw LogException( "LogAggregatorHTML::write failed: "
00363 + e.toString() ) ;
00364
00365 }
00366
00367 }
00368
00369
00370
00371 void LogAggregatorHTML::WriteChannelHeader( const LogChannel & channel,
00372 Ceylan::System::File & targetFile )
00373 {
00374
00375 string newHeader = ChannelHeader ;
00376
00377 Ceylan::substituteInString( newHeader, "ST_CHANNEL_NAME",
00378 Ceylan::encodeToHTML( channel.getName() ) ) ;
00379
00380 try
00381 {
00382
00383 targetFile.write( newHeader ) ;
00384
00385 }
00386 catch( const OutputStream::WriteFailedException & e )
00387 {
00388 throw LogException( "LogAggregatorHTML::WriteChannelHeader failed: "
00389 + e.toString() ) ;
00390 }
00391
00392
00393 }
00394
00395
00396
00397 void LogAggregatorHTML::WriteChannelFooter( const LogChannel & channel,
00398 Ceylan::System::File & targetFile )
00399 {
00400
00401 string newFooter = ChannelFooter ;
00402
00403 Ceylan::substituteInString( newFooter, "ST_AGGREGATION_DATE",
00404 Ceylan::encodeToHTML( timeToString( getTime() ) ) ) ;
00405
00406 try
00407 {
00408
00409 targetFile.write( newFooter ) ;
00410
00411 }
00412 catch( const OutputStream::WriteFailedException & e )
00413 {
00414 throw LogException( "LogAggregatorHTML::WriteChannelFooter failed: "
00415 + e.toString() ) ;
00416 }
00417
00418
00419 }
00420