LCOV - code coverage report
Current view: top level - utils/logdump - logdump.hpp (source / functions) Coverage Total Hit
Test: MagAOX Lines: 0.0 % 218 0
Test Date: 2026-01-03 21:03:39 Functions: 0.0 % 6 0

            Line data    Source code
       1              : /** \file logdump.hpp
       2              :  * \brief A simple utility to dump MagAO-X binary logs to stdout.
       3              :  *
       4              :  * \ingroup logdump_files
       5              :  */
       6              : 
       7              : #ifndef logdump_hpp
       8              : #define logdump_hpp
       9              : 
      10              : #include <iostream>
      11              : #include <cstring>
      12              : #include <filesystem>
      13              : 
      14              : #include <mx/mxError.hpp>
      15              : #include <mx/ioutils/fileUtils.hpp>
      16              : 
      17              : #include "../../libMagAOX/libMagAOX.hpp"
      18              : using namespace MagAOX::logger;
      19              : 
      20              : using namespace flatlogs;
      21              : 
      22              : /** \defgroup logdump logdump: MagAO-X Log Reader
      23              :  * \brief Read a MagAO-X binary log file.
      24              :  *
      25              :  * <a href="../handbook/utils/logdump.html">Utility Documentation</a>
      26              :  *
      27              :  * \ingroup utils
      28              :  *
      29              :  */
      30              : 
      31              : /** \defgroup logdump_files logdump Files
      32              :  * \ingroup logdump
      33              :  */
      34              : 
      35              : /// An application to dump MagAo-X binary logs to the terminal.
      36              : /** \todo document this
      37              :  * \todo add config for colors, both on/off and options to change.
      38              :  *
      39              :  * \ingroup logdump
      40              :  */
      41              : class logdump : public mx::app::application
      42              : {
      43              :     typedef mx::verbose::vvv verboseT;
      44              : 
      45              :   protected:
      46              :     std::string m_dir;
      47              :     std::string m_ext;
      48              :     std::string m_file;
      49              : 
      50              :     bool m_time{ false };
      51              :     bool m_jsonMode{ false };
      52              : 
      53              :     unsigned long m_pauseTime{ 250 }; /// When following, pause time to check for new data. msec. Default is 250 msec.
      54              :     int           m_fileCheckInterval{
      55              :         20 }; /// When following, number of loops to wait before checking for a new file.  Default is 4.
      56              : 
      57              :     std::vector<std::string> m_prefixes;
      58              : 
      59              :     size_t m_nfiles{ 0 }; /// Number of files to dump.  Default is 0, unless following then the default is 1.
      60              : 
      61              :     bool m_follow{ false };
      62              : 
      63              :     logPrioT m_level{ logPrio::LOG_DEFAULT };
      64              : 
      65              :     std::vector<eventCodeT> m_codes;
      66              : 
      67              :     void printLogBuff( const logPrioT &lvl, const eventCodeT &ec, const msgLenT &len, bufferPtrT &logBuff );
      68              :     void printLogJson( const msgLenT &len, bufferPtrT &logBuff );
      69              : 
      70              :   public:
      71              :     virtual void setupConfig();
      72              : 
      73              :     virtual void loadConfig();
      74              : 
      75              :     virtual int execute();
      76              : 
      77              :     virtual int gettimes( std::vector<std::string> &logs );
      78              : };
      79              : 
      80            0 : void logdump::setupConfig()
      81              : {
      82            0 :     config.add( "pauseTime",
      83              :                 "p",
      84              :                 "pauseTime",
      85              :                 argType::Required,
      86              :                 "",
      87              :                 "pauseTime",
      88              :                 false,
      89              :                 "int",
      90              :                 "When following, time in milliseconds to pause before checking for new entries." );
      91            0 :     config.add( "fileCheckInterval",
      92              :                 "",
      93              :                 "fileCheckInterval",
      94              :                 argType::Required,
      95              :                 "",
      96              :                 "fileCheckInterval",
      97              :                 false,
      98              :                 "int",
      99              :                 "When following, number of pause intervals between checks for new files." );
     100              : 
     101            0 :     config.add( "dir",
     102              :                 "d",
     103              :                 "dir",
     104              :                 argType::Required,
     105              :                 "",
     106              :                 "dir",
     107              :                 false,
     108              :                 "string",
     109              :                 "Directory to search for logs. MagAO-X default is normally used." );
     110            0 :     config.add( "ext",
     111              :                 "e",
     112              :                 "ext",
     113              :                 argType::Required,
     114              :                 "",
     115              :                 "ext",
     116              :                 false,
     117              :                 "string",
     118              :                 "The file extension of log files.  MagAO-X default is normally used." );
     119            0 :     config.add( "nfiles",
     120              :                 "n",
     121              :                 "nfiles",
     122              :                 argType::Required,
     123              :                 "",
     124              :                 "nfiles",
     125              :                 false,
     126              :                 "int",
     127              :                 "Number of log files to dump.  If 0, then all matching files dumped.  Default: 0, 1 if following." );
     128            0 :     config.add( "follow",
     129              :                 "f",
     130              :                 "follow",
     131              :                 argType::True,
     132              :                 "",
     133              :                 "follow",
     134              :                 false,
     135              :                 "bool",
     136              :                 "Follow the log, printing new entries as they appear." );
     137            0 :     config.add( "level",
     138              :                 "L",
     139              :                 "level",
     140              :                 argType::Required,
     141              :                 "",
     142              :                 "level",
     143              :                 false,
     144              :                 "int/string",
     145              :                 "Minimum log level to dump, either an integer or a string. -1/TELEMETRY [the default], 0/DEFAULT, "
     146              :                 "1/D1/DBG1/DEBUG2, 2/D2/DBG2/DEBUG1,3/INFO,4/WARNING,5/ERROR,6/CRITICAL,7/FATAL.  Note that only the "
     147              :                 "mininum unique string is required." );
     148            0 :     config.add( "code",
     149              :                 "C",
     150              :                 "code",
     151              :                 argType::Required,
     152              :                 "",
     153              :                 "code",
     154              :                 false,
     155              :                 "int",
     156              :                 "The event code, or vector of codes, to dump.  If not specified, all codes are dumped.  See "
     157              :                 "logCodes.hpp for a complete list of codes." );
     158            0 :     config.add( "file",
     159              :                 "F",
     160              :                 "file",
     161              :                 argType::Required,
     162              :                 "",
     163              :                 "file",
     164              :                 false,
     165              :                 "string",
     166              :                 "A single file to process.  If no / are found in name it will look in the specified directory (or "
     167              :                 "MagAO-X default)." );
     168            0 :     config.add( "time",
     169              :                 "T",
     170              :                 "time",
     171              :                 argType::True,
     172              :                 "",
     173              :                 "time",
     174              :                 false,
     175              :                 "bool",
     176              :                 "time span mode: prints the ISO 8601 UTC timestamps of the first and last entry, the elapsed time in "
     177              :                 "seconds, and the number of records in the file as a space-delimited string" );
     178            0 :     config.add( "json",
     179              :                 "J",
     180              :                 "json",
     181              :                 argType::True,
     182              :                 "",
     183              :                 "json",
     184              :                 false,
     185              :                 "bool",
     186              :                 "JSON mode: emits one JSON document per line for each record in the log" );
     187            0 : }
     188              : 
     189            0 : void logdump::loadConfig()
     190              : {
     191            0 :     config( m_pauseTime, "pauseTime" );
     192            0 :     config( m_fileCheckInterval, "fileCheckInterval" );
     193              : 
     194              :     // Get default log dir
     195            0 :     std::string tmpstr = mx::sys::getEnv( MAGAOX_env_path );
     196            0 :     if( tmpstr == "" )
     197              :     {
     198            0 :         tmpstr = MAGAOX_path;
     199              :     }
     200            0 :     m_dir = tmpstr + "/" + MAGAOX_logRelPath;
     201              :     ;
     202              : 
     203              :     // Now check for config option for dir
     204            0 :     config( m_dir, "dir" );
     205              : 
     206            0 :     m_ext = ".";
     207            0 :     m_ext += MAGAOX_default_logExt;
     208            0 :     config( m_ext, "ext" );
     209              :     ///\todo need to check for lack of "." and error or fix
     210              : 
     211            0 :     config( m_file, "file" );
     212              : 
     213            0 :     if( m_file == "" && config.nonOptions.size() < 1 )
     214              :     {
     215            0 :         std::cerr << "logdump: need application name. Try logdump -h for help.\n";
     216              :     }
     217              : 
     218            0 :     if( m_file == "" && config.nonOptions.size() > 1 )
     219              :     {
     220            0 :         std::cerr << "logdump: only one application at a time supported. Try logdump -h for help.\n";
     221              :     }
     222              : 
     223            0 :     m_prefixes.resize( config.nonOptions.size() );
     224            0 :     for( size_t i = 0; i < config.nonOptions.size(); ++i )
     225              :     {
     226            0 :         m_prefixes[i] = config.nonOptions[i];
     227              :     }
     228              : 
     229            0 :     if( config.isSet( "time" ) )
     230            0 :         m_time = true;
     231            0 :     if( config.isSet( "json" ) )
     232            0 :         m_jsonMode = true;
     233              : 
     234            0 :     config( m_follow, "follow" );
     235              : 
     236            0 :     if( m_follow )
     237            0 :         m_nfiles = 1; // default to 1 if follow is set.
     238            0 :     config( m_nfiles, "nfiles" );
     239              : 
     240            0 :     tmpstr = "";
     241            0 :     config( tmpstr, "level" );
     242            0 :     if( tmpstr != "" )
     243              :     {
     244            0 :         m_level = logLevelFromString( tmpstr );
     245              :     }
     246              : 
     247            0 :     config( m_codes, "code" );
     248              : 
     249            0 :     std::cerr << m_codes.size() << "\n";
     250            0 : }
     251              : 
     252            0 : int logdump::execute()
     253              : {
     254              : 
     255            0 :     if( m_file == "" && m_prefixes.size() != 1 )
     256            0 :         return -1; // error message will have been printed in loadConfig.
     257              : 
     258            0 :     std::vector<std::string> subdirs, logs;
     259              : 
     260            0 :     if( m_file != "" )
     261              :     {
     262            0 :         if( m_file.find( '/' ) == std::string::npos )
     263              :         {
     264              : 
     265            0 :             std::string devName, YYYY, MM, DD, hh, mm, ss, nn;
     266            0 :             mx_error_check_rv(MagAOX::file::parseFilePath( devName, YYYY, MM, DD, hh, mm, ss, nn, m_file ),-1);
     267              : 
     268            0 :             m_file = m_dir + '/' + devName + '/' + YYYY + '_' + MM + '_' + DD + '/' + m_file;
     269            0 :         }
     270              : 
     271            0 :         logs.push_back( m_file );
     272              :     }
     273              :     else
     274              :     {
     275            0 :         mx_error_check_rv(mx::ioutils::getFileNames(subdirs, m_dir + "/" + m_prefixes[0], "", "", "" ),-1);
     276              : 
     277            0 :         if( m_follow )
     278              :         {
     279            0 :             mx_error_check_rv(mx::ioutils::getFileNames(logs, subdirs.back(), m_prefixes[0], "", m_ext ), -1);
     280              :         }
     281              :         else
     282              :         {
     283            0 :             for( size_t d = 0; d < subdirs.size(); ++d )
     284              :             {
     285              :                 // get subdir vectors one at a time and append to build the whole list
     286            0 :                 std::vector<std::string> tlogs;
     287            0 :                 mx_error_check_rv(mx::ioutils::getFileNames(tlogs, subdirs[d], m_prefixes[0], "", m_ext ),-1);
     288            0 :                 logs.insert( logs.end(), tlogs.begin(), tlogs.end() );
     289            0 :             }
     290              :         }
     291              :     }
     292              : 
     293              :     ///\todo if follow is set, then should nfiles default to 1 unless explicitly set?
     294            0 :     if( m_nfiles == 0 )
     295              :     {
     296            0 :         m_nfiles = logs.size();
     297              :     }
     298              : 
     299            0 :     if( m_nfiles > logs.size() )
     300            0 :         m_nfiles = logs.size();
     301              : 
     302            0 :     if( m_time )
     303              :     {
     304            0 :         return gettimes( logs );
     305              :     }
     306              : 
     307            0 :     bool firstRun = true; // for only showing latest entries on first run when following.
     308              : 
     309            0 :     for( size_t i = logs.size() - m_nfiles; i < logs.size(); ++i )
     310              :     {
     311            0 :         std::string fname = logs[i];
     312              :         FILE       *fin;
     313              : 
     314            0 :         bufferPtrT head( (char *) ::operator new(logHeader::maxHeadSize));
     315              : 
     316            0 :         bufferPtrT logBuff;
     317              : 
     318            0 :         fin = fopen( fname.c_str(), "rb" );
     319              : 
     320              :         //--> get size here!!
     321            0 :         off_t finSize = mx::ioutils::fileSize( fileno( fin ) );
     322              : 
     323            0 :         std::cerr << fname << "\n";
     324              : 
     325            0 :         off_t totNrd = 0;
     326              : 
     327            0 :         size_t buffSz = 0;
     328            0 :         while( !feof( fin ) ) //<--This should be an exit condition controlled by loop logic, not feof.
     329              :         {
     330              :             int nrd;
     331              : 
     332              :             ///\todo check for errors on all reads . . .
     333              : 
     334              :             // Read next header
     335            0 :             nrd = fread( head.get(), sizeof( char ), logHeader::minHeadSize, fin );
     336            0 :             if( nrd == 0 )
     337              :             {
     338              :                 // If we're following and on the last log file, wait for more to show up.
     339            0 :                 if( m_follow == true && i == logs.size() - 1 )
     340              :                 {
     341            0 :                     int check = 0;
     342            0 :                     firstRun  = false; // from now on we show all logs
     343            0 :                     while( nrd == 0 )
     344              :                     {
     345            0 :                         std::this_thread::sleep_for( std::chrono::duration<unsigned long, std::milli>( m_pauseTime ) );
     346            0 :                         clearerr( fin );
     347            0 :                         nrd = fread( head.get(), sizeof( char ), logHeader::minHeadSize, fin );
     348            0 :                         if( nrd > 0 )
     349            0 :                             break;
     350              : 
     351            0 :                         ++check;
     352            0 :                         if( check >= m_fileCheckInterval )
     353              :                         {
     354              :                             // Check if a new sub-directory exists now.
     355            0 :                             size_t old_subdirs_sz = subdirs.size();
     356            0 :                             mx_error_check_rv(mx::ioutils::getFileNames( subdirs, m_dir + "/" + m_prefixes[0], "", "", "" ),-1);
     357            0 :                             if( subdirs.size() > old_subdirs_sz )
     358              :                             {
     359              :                                 // new subdirs(s) detected;
     360            0 :                                 break;
     361              :                             }
     362              : 
     363              :                             // Check if a new file exists now.
     364            0 :                             size_t old_logs_sz = logs.size();
     365              : 
     366            0 :                             mx_error_check_rv(mx::ioutils::getFileNames( logs, subdirs.back(), m_prefixes[0], "", m_ext ),-1);
     367              : 
     368            0 :                             if( logs.size() > old_logs_sz )
     369              :                             {
     370              :                                 // new file(s) detected;
     371            0 :                                 break;
     372              :                             }
     373            0 :                             check = 0;
     374              :                         }
     375              :                     }
     376              :                 }
     377              :                 else
     378              :                 {
     379            0 :                     break;
     380              :                 }
     381              :             }
     382              : 
     383              :             // We got here without any data, probably means time to get a new file.
     384            0 :             if( nrd == 0 )
     385            0 :                 break;
     386              : 
     387            0 :             totNrd += nrd;
     388              : 
     389            0 :             if( logHeader::msgLen0( head ) == logHeader::MAX_LEN0 - 1 )
     390              :             {
     391              :                 // Intermediate size message, read two more bytes
     392            0 :                 nrd = fread( head.get() + logHeader::minHeadSize, sizeof( char ), sizeof( msgLen1T ), fin );
     393              :             }
     394            0 :             else if( logHeader::msgLen0( head ) == logHeader::MAX_LEN0 )
     395              :             {
     396              :                 // Large size message: read 8 more bytes
     397            0 :                 nrd = fread( head.get() + logHeader::minHeadSize, sizeof( char ), sizeof( msgLen2T ), fin );
     398              :             }
     399              : 
     400            0 :             logPrioT   lvl = logHeader::logLevel( head );
     401            0 :             eventCodeT ec  = logHeader::eventCode( head );
     402            0 :             msgLenT    len = logHeader::msgLen( head );
     403              : 
     404              :             // Here: check if lvl, eventCode, etc, match what we want.
     405              :             // If not, fseek and loop.
     406            0 :             if( lvl > m_level )
     407              :             {
     408            0 :                 fseek( fin, len, SEEK_CUR );
     409            0 :                 continue;
     410              :             }
     411              : 
     412            0 :             if( m_codes.size() > 0 )
     413              :             {
     414            0 :                 bool found = false;
     415            0 :                 for( size_t c = 0; c < m_codes.size(); ++c )
     416              :                 {
     417            0 :                     if( m_codes[c] == ec )
     418              :                     {
     419            0 :                         found = true;
     420            0 :                         break;
     421              :                     }
     422              :                 }
     423              : 
     424            0 :                 if( !found )
     425              :                 {
     426            0 :                     fseek( fin, len, SEEK_CUR );
     427            0 :                     continue;
     428              :                 }
     429              :             }
     430              : 
     431            0 :             size_t hSz = logHeader::headerSize( head );
     432              : 
     433            0 :             if( (size_t)hSz + (size_t)len > buffSz )
     434              :             {
     435            0 :                 logBuff = bufferPtrT( (char *) ::operator new(hSz + len));
     436              :             }
     437            0 :             memcpy( logBuff.get(), head.get(), hSz );
     438              : 
     439              :             ///\todo what do we do if nrd not equal to expected size?
     440            0 :             nrd = fread( logBuff.get() + hSz, sizeof( char ), len, fin );
     441              :             // If not following, exit loop without printing the incomplete log entry (go on to next file).cd
     442              :             // If following, wait for it, but also be checking for new log file in case of crash
     443              : 
     444            0 :             totNrd += nrd;
     445              : 
     446            0 :             if( m_follow && firstRun && finSize > 512 && totNrd < finSize - 512 )
     447              :             {
     448              :                 // firstRun = false;
     449            0 :                 continue;
     450              :             }
     451              : 
     452            0 :             if( !logVerify( ec, logBuff, len ) )
     453              :             {
     454            0 :                 std::cerr << "Log " << fname << " failed verification on code=" << ec
     455            0 :                           << " at byte=" << totNrd - len - hSz << ". File possibly corrupt.  Exiting." << std::endl;
     456            0 :                 return -1;
     457              :             }
     458              : 
     459            0 :             if( m_jsonMode )
     460              :             {
     461            0 :                 printLogJson( len, logBuff );
     462              :             }
     463              :             else
     464              :             {
     465            0 :                 printLogBuff( lvl, ec, len, logBuff );
     466              :             }
     467              :         }
     468              : 
     469            0 :         fclose( fin );
     470            0 :     }
     471              : 
     472            0 :     return 0;
     473            0 : }
     474              : 
     475            0 : inline void logdump::printLogBuff( const logPrioT &lvl, const eventCodeT &ec, const msgLenT &len, bufferPtrT &logBuff )
     476              : {
     477              :     static_cast<void>( len ); // be unused
     478              : 
     479            0 :     if( ec == eventCodes::GIT_STATE )
     480              :     {
     481            0 :         if( git_state::repoName( logHeader::messageBuffer( logBuff ) ) == "MagAOX" )
     482              :         {
     483            0 :             for( int i = 0; i < 80; ++i )
     484            0 :                 std::cout << '-';
     485            0 :             std::cout << "\n\t\t\t\t SOFTWARE RESTART\n";
     486            0 :             for( int i = 0; i < 80; ++i )
     487            0 :                 std::cout << '-';
     488            0 :             std::cout << '\n';
     489              :         }
     490              :     }
     491              : 
     492            0 :     if( lvl < logPrio::LOG_INFO )
     493              :     {
     494            0 :         if( lvl == logPrio::LOG_EMERGENCY )
     495              :         {
     496            0 :             std::cout << "\033[104m\033[91m\033[5m\033[1m";
     497              :         }
     498              : 
     499            0 :         if( lvl == logPrio::LOG_ALERT )
     500              :         {
     501            0 :             std::cout << "\033[101m\033[5m";
     502              :         }
     503              : 
     504            0 :         if( lvl == logPrio::LOG_CRITICAL )
     505              :         {
     506            0 :             std::cout << "\033[41m\033[1m";
     507              :         }
     508              : 
     509            0 :         if( lvl == logPrio::LOG_ERROR )
     510              :         {
     511            0 :             std::cout << "\033[91m\033[1m";
     512              :         }
     513              : 
     514            0 :         if( lvl == logPrio::LOG_WARNING )
     515              :         {
     516            0 :             std::cout << "\033[93m\033[1m";
     517              :         }
     518              : 
     519            0 :         if( lvl == logPrio::LOG_NOTICE )
     520              :         {
     521            0 :             std::cout << "\033[1m";
     522              :         }
     523              :     }
     524              : 
     525            0 :     logStdFormat( std::cout, logBuff );
     526              : 
     527            0 :     std::cout << "\033[0m";
     528            0 :     std::cout << std::endl;
     529            0 : }
     530              : 
     531            0 : inline void logdump::printLogJson( const msgLenT &len, bufferPtrT &logBuff )
     532              : {
     533              :     static_cast<void>( len ); // be unused
     534            0 :     logJsonFormat( std::cout, logBuff );
     535            0 :     std::cout << std::endl;
     536            0 : }
     537              : 
     538            0 : int logdump::gettimes( std::vector<std::string> &logs )
     539              : {
     540            0 :     for( size_t i = logs.size() - m_nfiles; i < logs.size(); ++i )
     541              :     {
     542            0 :         std::string fname = logs[i];
     543              :         FILE       *fin;
     544              : 
     545            0 :         bufferPtrT head( (char *) ::operator new(logHeader::maxHeadSize) );
     546              : 
     547            0 :         fin = fopen( fname.c_str(), "rb" );
     548              : 
     549              :         //--> get size here!!
     550              :         // off_t finSize = mx::ioutils::fileSize( fileno(fin) );
     551              : 
     552            0 :         off_t totNrd = 0;
     553              : 
     554              :         // size_t buffSz = 0;
     555              : 
     556              :         // Read firs header
     557              : 
     558              :         int nrd;
     559              : 
     560              :         ///\todo check for errors on all reads . . .
     561              : 
     562              :         // Read next header
     563            0 :         nrd = fread( head.get(), sizeof( char ), logHeader::minHeadSize, fin );
     564            0 :         if( nrd == 0 )
     565              :         {
     566            0 :             std::cerr << "got no header\n";
     567            0 :             return 0;
     568              :         }
     569              : 
     570            0 :         if( logHeader::msgLen0( head ) == logHeader::MAX_LEN0 - 1 )
     571              :         {
     572              :             // Intermediate size message, read two more bytes
     573            0 :             nrd = fread( head.get() + logHeader::minHeadSize, sizeof( char ), sizeof( msgLen1T ), fin );
     574              :         }
     575            0 :         else if( logHeader::msgLen0( head ) == logHeader::MAX_LEN0 )
     576              :         {
     577              :             // Large size message: read 8 more bytes
     578            0 :             nrd = fread( head.get() + logHeader::minHeadSize, sizeof( char ), sizeof( msgLen2T ), fin );
     579              :         }
     580              : 
     581              :         // logPrioT lvl = logHeader::logLevel(head);
     582              :         // eventCodeT ec = logHeader::eventCode(head);
     583            0 :         msgLenT   len = logHeader::msgLen( head );
     584            0 :         timespecX ts0 = logHeader::timespec( head );
     585              :         // size_t hSz = logHeader::headerSize(head);
     586              : 
     587            0 :         uint32_t nRecords = 1;
     588            0 :         fseek( fin, len, SEEK_CUR );
     589              : 
     590            0 :         timespecX ts;
     591              : 
     592            0 :         while( !feof( fin ) ) //<--This should be an exit condition controlled by loop logic, not feof.
     593              :         {
     594              :             int nrd;
     595              : 
     596              :             // Read next header
     597            0 :             nrd = fread( head.get(), sizeof( char ), logHeader::minHeadSize, fin );
     598            0 :             if( nrd == 0 )
     599              :             {
     600            0 :                 break;
     601              :             }
     602            0 :             nRecords += 1;
     603              : 
     604              :             // We got here without any data, probably means time to get a new file.
     605            0 :             if( nrd == 0 )
     606            0 :                 break;
     607              : 
     608            0 :             totNrd += nrd;
     609              : 
     610            0 :             if( logHeader::msgLen0( head ) == logHeader::MAX_LEN0 - 1 )
     611              :             {
     612              :                 // Intermediate size message, read two more bytes
     613            0 :                 nrd = fread( head.get() + logHeader::minHeadSize, sizeof( char ), sizeof( msgLen1T ), fin );
     614              :             }
     615            0 :             else if( logHeader::msgLen0( head ) == logHeader::MAX_LEN0 )
     616              :             {
     617              :                 // Large size message: read 8 more bytes
     618            0 :                 nrd = fread( head.get() + logHeader::minHeadSize, sizeof( char ), sizeof( msgLen2T ), fin );
     619              :             }
     620              : 
     621              :             // lvl = logHeader::logLevel(head);
     622              :             // ec = logHeader::eventCode(head);
     623            0 :             len = logHeader::msgLen( head );
     624            0 :             ts  = logHeader::timespec( head );
     625              :             // hSz = logHeader::headerSize(head);
     626              : 
     627            0 :             fseek( fin, len, SEEK_CUR );
     628              :         }
     629              : 
     630            0 :         fclose( fin );
     631              : 
     632            0 :         double t0 = ts0.time_s + ts0.time_ns / 1e9;
     633            0 :         double t  = ts.time_s + ts.time_ns / 1e9;
     634              : 
     635            0 :         std::cout << fname << " " << ts0.ISO8601DateTimeStrX() << "Z " << ts.ISO8601DateTimeStrX() << "Z " << t - t0
     636            0 :                   << " " << nRecords << std::endl;
     637            0 :     }
     638              : 
     639            0 :     return 0;
     640              : }
     641              : 
     642              : #endif // logdump_hpp
        

Generated by: LCOV version 2.0-1