日志源文件在: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
到这里,基本整个逻辑没太大的问题了,就是一些细节弄明白就行了