14#include <mx/mxError.hpp>
15#include <mx/ioutils/fileUtils.hpp>
17#include "../../libMagAOX/libMagAOX.hpp"
41class logdump :
public mx::app::application
77 virtual int gettimes( std::vector<std::string> &logs );
82 config.add(
"pauseTime",
90 "When following, time in milliseconds to pause before checking for new entries." );
91 config.add(
"fileCheckInterval",
99 "When following, number of pause intervals between checks for new files." );
109 "Directory to search for logs. MagAO-X default is normally used." );
118 "The file extension of log files. MagAO-X default is normally used." );
119 config.add(
"nfiles",
127 "Number of log files to dump. If 0, then all matching files dumped. Default: 0, 1 if following." );
128 config.add(
"follow",
136 "Follow the log, printing new entries as they appear." );
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." );
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." );
166 "A single file to process. If no / are found in name it will look in the specified directory (or "
167 "MagAO-X default)." );
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" );
186 "JSON mode: emits one JSON document per line for each record in the log" );
204 config(
m_dir,
"dir" );
208 config(
m_ext,
"ext" );
213 if(
m_file ==
"" && config.nonOptions.size() < 1 )
215 std::cerr <<
"logdump: need application name. Try logdump -h for help.\n";
218 if(
m_file ==
"" && config.nonOptions.size() > 1 )
220 std::cerr <<
"logdump: only one application at a time supported. Try logdump -h for help.\n";
223 m_prefixes.resize( config.nonOptions.size() );
224 for(
size_t i = 0; i < config.nonOptions.size(); ++i )
229 if( config.isSet(
"time" ) )
231 if( config.isSet(
"json" ) )
241 config( tmpstr,
"level" );
249 std::cerr <<
m_codes.size() <<
"\n";
258 std::vector<std::string> subdirs, logs;
262 if(
m_file.find(
'/' ) == std::string::npos )
265 std::string devName, YYYY, MM, DD, hh, mm, ss, nn;
268 m_file =
m_dir +
'/' + devName +
'/' + YYYY +
'_' + MM +
'_' + DD +
'/' +
m_file;
275 mx_error_check_rv(mx::ioutils::getFileNames(subdirs,
m_dir +
"/" +
m_prefixes[0],
"",
"",
"" ),-1);
279 mx_error_check_rv(mx::ioutils::getFileNames(logs, subdirs.back(),
m_prefixes[0],
"",
m_ext ), -1);
283 for(
size_t d = 0; d < subdirs.size(); ++d )
286 std::vector<std::string> tlogs;
287 mx_error_check_rv(mx::ioutils::getFileNames(tlogs, subdirs[d],
m_prefixes[0],
"",
m_ext ),-1);
288 logs.insert( logs.end(), tlogs.begin(), tlogs.end() );
307 bool firstRun =
true;
309 for(
size_t i = logs.size() -
m_nfiles; i < logs.size(); ++i )
311 std::string fname = logs[i];
318 fin = fopen( fname.c_str(),
"rb" );
321 off_t finSize = mx::ioutils::fileSize( fileno( fin ) );
323 std::cerr << fname <<
"\n";
328 while( !feof( fin ) )
339 if(
m_follow ==
true && i == logs.size() - 1 )
345 std::this_thread::sleep_for( std::chrono::duration<unsigned long, std::milli>(
m_pauseTime ) );
355 size_t old_subdirs_sz = subdirs.size();
356 mx_error_check_rv(mx::ioutils::getFileNames( subdirs,
m_dir +
"/" +
m_prefixes[0],
"",
"",
"" ),-1);
357 if( subdirs.size() > old_subdirs_sz )
364 size_t old_logs_sz = logs.size();
366 mx_error_check_rv(mx::ioutils::getFileNames( logs, subdirs.back(),
m_prefixes[0],
"",
m_ext ),-1);
368 if( logs.size() > old_logs_sz )
408 fseek( fin, len, SEEK_CUR );
415 for(
size_t c = 0; c <
m_codes.size(); ++c )
426 fseek( fin, len, SEEK_CUR );
433 if( (
size_t)hSz + (
size_t)len > buffSz )
435 logBuff =
bufferPtrT( (
char *) ::operator
new(hSz + len));
437 memcpy( logBuff.get(), head.get(), hSz );
440 nrd = fread( logBuff.get() + hSz,
sizeof(
char ), len, fin );
446 if(
m_follow && firstRun && finSize > 512 && totNrd < finSize - 512 )
454 std::cerr <<
"Log " << fname <<
" failed verification on code=" << ec
455 <<
" at byte=" << totNrd - len - hSz <<
". File possibly corrupt. Exiting." << std::endl;
477 static_cast<void>( len );
483 for(
int i = 0; i < 80; ++i )
485 std::cout <<
"\n\t\t\t\t SOFTWARE RESTART\n";
486 for(
int i = 0; i < 80; ++i )
496 std::cout <<
"\033[104m\033[91m\033[5m\033[1m";
501 std::cout <<
"\033[101m\033[5m";
506 std::cout <<
"\033[41m\033[1m";
511 std::cout <<
"\033[91m\033[1m";
516 std::cout <<
"\033[93m\033[1m";
521 std::cout <<
"\033[1m";
527 std::cout <<
"\033[0m";
528 std::cout << std::endl;
533 static_cast<void>( len );
535 std::cout << std::endl;
540 for(
size_t i = logs.size() -
m_nfiles; i < logs.size(); ++i )
542 std::string fname = logs[i];
547 fin = fopen( fname.c_str(),
"rb" );
566 std::cerr <<
"got no header\n";
587 uint32_t nRecords = 1;
588 fseek( fin, len, SEEK_CUR );
592 while( !feof( fin ) )
627 fseek( fin, len, SEEK_CUR );
636 <<
" " << nRecords << std::endl;
An application to dump MagAo-X binary logs to the terminal.
bool m_follow
Number of files to dump. Default is 0, unless following then the default is 1.
virtual int gettimes(std::vector< std::string > &logs)
std::vector< eventCodeT > m_codes
void printLogJson(const msgLenT &len, bufferPtrT &logBuff)
int m_fileCheckInterval
When following, pause time to check for new data. msec. Default is 250 msec.
virtual void setupConfig()
virtual void loadConfig()
unsigned long m_pauseTime
void printLogBuff(const logPrioT &lvl, const eventCodeT &ec, const msgLenT &len, bufferPtrT &logBuff)
std::vector< std::string > m_prefixes
When following, number of loops to wait before checking for a new file. Default is 4.
mx::verbose::vvv verboseT
#define MAGAOX_default_logExt
The extension for MagAO-X binary log files.
#define MAGAOX_logRelPath
The relative path to the log directory.
#define MAGAOX_path
The path to the MagAO-X system files.
#define MAGAOX_env_path
Environment variable setting the MagAO-X path.
uint16_t msgLen1T
The type used for intermediate message length.
uint16_t eventCodeT
The type of an event code (16-bit unsigned int).
uint64_t msgLen2T
The type used for long message length.
msgLen2T msgLenT
The type used to refer to the message length, regardless of length.
int8_t logPrioT
The type of the log priority code.
static int eventCode(bufferPtrT &logBuffer, const eventCodeT &ec)
Set the event code of a log entry.
static msgLen0T msgLen0(bufferPtrT &logBuffer)
Extract the short message length of a log entry message.
static void * messageBuffer(bufferPtrT &logBuffer)
Get the message buffer address.
std::shared_ptr< char > bufferPtrT
The log entry buffer smart pointer.
static size_t headerSize(bufferPtrT &logBuffer)
Get the size of the header, including the variable size length field, for an existing logBuffer.
static int msgLen(bufferPtrT &logBuffer, const msgLenT &msgLen)
Set the message length of a log entry message.
static int logLevel(bufferPtrT &logBuffer, const logPrioT &lvl)
Set the level of a log entry in a logBuffer header.
static int timespec(bufferPtrT &logBuffer, const timespecX &ts)
Set the timespec of a log entry.
mx::error_t parseFilePath(std::string &devName, std::string &YYYY, std::string &MM, std::string &DD, std::string &hh, std::string &mm, std::string &ss, std::string &nn, const std::string &fname)
Parse a standard XWCTk timestamp filepath.
static constexpr flatlogs::eventCodeT GIT_STATE
iosT & logJsonFormat(iosT &ios, flatlogs::bufferPtrT &buffer)
bool logVerify(flatlogs::eventCodeT ec, flatlogs::bufferPtrT &buffer, flatlogs::msgLenT len)
iosT & logStdFormat(iosT &ios, flatlogs::bufferPtrT &buffer)
static constexpr logPrioT LOG_NOTICE
A normal but significant condition.
static constexpr logPrioT LOG_INFO
Informational. The info log level is the lowest level recorded during normal operations.
static constexpr logPrioT LOG_CRITICAL
The process can not continue and will shut down (fatal)
static constexpr logPrioT LOG_WARNING
A condition has occurred which may become an error, but the process continues.
static constexpr logPrioT LOG_ERROR
An error has occured which the software will attempt to correct.
static constexpr logPrioT LOG_DEFAULT
Used to denote "use the default level for this log type".
static constexpr logPrioT LOG_EMERGENCY
Normal operations of the entire system should be shut down immediately.
static constexpr logPrioT LOG_ALERT
This should only be used if some action is required by operators to keep the system safe.
logPrioT logLevelFromString(const std::string &str)
Get the log priority from a string, which might have the number or the name.
static std::string repoName(void *msgBuffer)
Access the repo name field.
A fixed-width timespec structure.
nanosecT time_ns
Nanoseconds.
secT time_s
Time since the Unix epoch.
std::string ISO8601DateTimeStrX()
Get a date-time string in ISO 8601 format for timespecX.