日誌源文件在:kaldi/src/base 中,kaldi-error.h ,kaldi-error.cc
使用時調用:
KALDI_ASSERT(num_chan > 0);
KALDI_WARN << "..." ;
KALDI_ERR <<"...";
KALDI_LOG <<"..."
KALDI_VLOG(2) <<"..." 有個全局變量:extern int32 g_kaldi_verbose_level; 在腳本中是用--verbose=2設置的
我看的過程就是順着調用理清源碼
在頭文件kaldi-error.h中定義了宏:
// The definition of the logging macros,
#define KALDI_ERR \
::kaldi::MessageLogger(::kaldi::LogMessageEnvelope::kError, \
__func__, __FILE__, __LINE__).stream()
#define KALDI_WARN \
::kaldi::MessageLogger(::kaldi::LogMessageEnvelope::kWarning, \
__func__, __FILE__, __LINE__).stream()
#define KALDI_LOG \
::kaldi::MessageLogger(::kaldi::LogMessageEnvelope::kInfo, \
__func__, __FILE__, __LINE__).stream()
#define KALDI_VLOG(v) if ((v) <= ::kaldi::g_kaldi_verbose_level) \
::kaldi::MessageLogger((::kaldi::LogMessageEnvelope::Severity)(v), \
__func__, __FILE__, __LINE__).stream()
其中:__func__, __FILE__, __LINE__ 分別是函數,文件,行。e.g. CalMfcc():recognition.cc:148
宏實際上創建了對象,並返回了ostringstream類型的ss_,所以在源碼中找不到重載"<<"的地方
inline std::ostream &stream() { return ss_; }
std::ostringstream ss_;
類對象:
struct LogMessageEnvelope {
enum Severity {
kAssertFailed = -3,
kError = -2,
kWarning = -1,
kInfo = 0,
};
// An 'enum Severity' value, or a positive number indicating verbosity level.
int severity;
const char *func;
const char *file;
int32 line;
};
class MessageLogger {
public:
/// Constructor stores the info,
MessageLogger(LogMessageEnvelope::Severity severity,
const char *func,
const char *file,
int32 line);
/// Destructor, calls 'HandleMessage' which prints the message,
/// (since C++11 a 'throwing' destructor must be declared 'noexcept(false)')
~MessageLogger() KALDI_NOEXCEPT(false);
/// The hook for the 'insertion operator', e.g.
/// 'KALDI_LOG << "Message,"',
inline std::ostream &stream() { return ss_; }
private:
/// The logging function,
static void HandleMessage(const LogMessageEnvelope &env, const char *msg);
private:
LogMessageEnvelope envelope_;
std::ostringstream ss_;
};
對象析構時,會調用HandleMessage()函數,輸出打印的內容:
MessageLogger::~MessageLogger() KALDI_NOEXCEPT(false) {
// remove trailing '\n',
std::string str = ss_.str();
while (!str.empty() && str[str.length() - 1] == '\n')
str.resize(str.length() - 1);
// print the mesage (or send to logging handler),
MessageLogger::HandleMessage(envelope_, str.c_str());
}
void MessageLogger::HandleMessage(const LogMessageEnvelope &envelope,
const char *message) {
// Send to a logging handler if provided.
if (g_log_handler != NULL) {
g_log_handler(envelope, message);
} else {
// Otherwise, we use the default Kaldi logging.
// Build the log-message 'header',
std::stringstream header;
if (envelope.severity > LogMessageEnvelope::kInfo) {
header << "VLOG[" << envelope.severity << "] (";
} else {
switch (envelope.severity) {
case LogMessageEnvelope::kInfo :
header << "LOG (";
break;
case LogMessageEnvelope::kWarning :
header << "WARNING (";
break;
case LogMessageEnvelope::kError :
header << "ERROR (";
break;
case LogMessageEnvelope::kAssertFailed :
header << "ASSERTION_FAILED (";
break;
default:
abort(); // coding error (unknown 'severity'),
}
}
// fill the other info from the envelope,
header << GetProgramName() << "[" KALDI_VERSION "]" << ':'
<< envelope.func << "():" << envelope.file << ':' << envelope.line
<< ")";
// Printing the message,
if (envelope.severity >= LogMessageEnvelope::kWarning) {
// VLOG, LOG, WARNING:
fprintf(stderr, "%s %s\n", header.str().c_str(), message);
} else {
// ERROR, ASSERT_FAILED (print with stack-trace):
fprintf(stderr, "%s %s\n\n%s\n", header.str().c_str(), message,
KaldiGetStackTrace().c_str());
}
}
在整個源碼中我們也沒有找到log文件路徑的配置,實際上是在腳本中設置的,會看到類型下面的腳本:
$cmd JOB=1:$nj $logdir/make_mfcc_${name}.JOB.log ...
cmd 沒用到集羣時是run.pl,在其中有這樣的代碼段:
system("mkdir -p `dirname $logfile` 2>/dev/null");
open(F, ">$logfile") || die "run.pl: Error opening log file $logfile";
print F "# " . $cmd . "\n";
print F "# Started at " . `date`;
$starttime = `date +'%s'`;
print F "#\n";
close(F);
...
open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)";
$enddate = `date`;
chop $enddate;
print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n";
print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n";
close(F);
...
是在peal中重定向到指定文件中的。
我們自己調用的時候直接 ">> xxx.log"時,會發現沒輸出。需要改成”2>>xxx.log“
爲什麼是2----Linux中有三種標準輸入輸出,分別是 STDIN,STDOUT,STDERR,對應的數字是
0,1,2
到這裏,基本整個邏輯沒太大的問題了,就是一些細節弄明白就行了