glog学习(二):glog主要接口和类分析
1.glog的主要接口如下。
#define LOG(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()
#define SYSLOG(severity) SYSLOG_ ## severity(0).stream() // Initialize.
GOOGLE_GLOG_DLL_DECL void InitGoogleLogging(const char* argv0); // Shutdown
GOOGLE_GLOG_DLL_DECL void ShutdownGoogleLogging(); // 设置回调接口,如果失败调用接口.
GOOGLE_GLOG_DLL_DECL void InstallFailureFunction(void (*fail_func)()); // Add or remove a LogSink as a consumer of logging data. Thread-safe.
GOOGLE_GLOG_DLL_DECL void AddLogSink(LogSink *destination);
GOOGLE_GLOG_DLL_DECL void RemoveLogSink(LogSink *destination); //设置日志扩展名称,thread-safe。
GOOGLE_GLOG_DLL_DECL void SetLogFilenameExtension(
const char* filename_extension); //
// 设置某种等级的日志标准输出,thread-safe.
//
GOOGLE_GLOG_DLL_DECL void SetStderrLogging(LogSeverity min_severity); //
// 设置所有的日志标准输出. Thread-safe.
//
GOOGLE_GLOG_DLL_DECL void LogToStderr(); //
// Make it so that all log messages of at least a particular severity are
// logged via email to a list of addresses (in addition to logging to the
// usual log file(s)). The list of addresses is just a string containing
// the email addresses to send to (separated by spaces, say). Thread-safe.
//
GOOGLE_GLOG_DLL_DECL void SetEmailLogging(LogSeverity min_severity,
const char* addresses); // A simple function that sends email. dest is a commma-separated
// list of addressess. Thread-safe.
GOOGLE_GLOG_DLL_DECL bool SendEmail(const char *dest,
const char *subject, const char *body); GOOGLE_GLOG_DLL_DECL const std::vector<std::string>& GetLoggingDirectories(); // For tests only: Clear the internal [cached] list of logging directories to
// force a refresh the next time GetLoggingDirectories is called.
// Thread-hostile.
void TestOnly_ClearLoggingDirectoriesList(); // Returns a set of existing temporary directories, which will be a
// subset of the directories returned by GetLogginDirectories().
// Thread-safe.
GOOGLE_GLOG_DLL_DECL void GetExistingTempDirectories(
std::vector<std::string>* list); // Print any fatal message again -- useful to call from signal handler
// so that the last thing in the output is the fatal message.
// Thread-hostile, but a race is unlikely.
GOOGLE_GLOG_DLL_DECL void ReprintFatalMessage(); // Truncate a log file that may be the append-only output of multiple
// processes and hence can't simply be renamed/reopened (typically a
// stdout/stderr). If the file "path" is > "limit" bytes, copy the
// last "keep" bytes to offset 0 and truncate the rest. Since we could
// be racing with other writers, this approach has the potential to
// lose very small amounts of data. For security, only follow symlinks
// if the path is /proc/self/fd/*
GOOGLE_GLOG_DLL_DECL void TruncateLogFile(const char *path,
int64 limit, int64 keep); // Truncate stdout and stderr if they are over the value specified by
// --max_log_size; keep the final 1MB. This function has the same
// race condition as TruncateLogFile.
GOOGLE_GLOG_DLL_DECL void TruncateStdoutStderr(); // Return the string representation of the provided LogSeverity level.
// Thread-safe.
GOOGLE_GLOG_DLL_DECL const char* GetLogSeverityName(LogSeverity severity);
使用方法如下:
(1)初始化
(2)logdestination提供文件地址,文件前缀名,输出属性的设置接口。
(3)logmessage提供日志内容的具体输出接口,封装为LOG(…)。
(4)shutdown,析构
2.直接用到的类。
从上述接口分析,我们可以得到我们直接接触到的类和文件。
2.1
LogMessage:This class more or less represents a particular log message. You create an instance of LogMessage and then stream stuff to it. When you finish streaming to it, ~LogMessage is called and the full message gets streamed to the appropriate destination.从日志中我们可以看出,日志信息的输出主要看这个类,创建LogMessage的实例,获得数据流,结束后,调用析构函数~LogMessage(),然后stream流向目的文件。
LogMessage的主要成员说明,由于一些参数太长我就省略掉了,大家可以参考具体的文档。
LogMessage |
Public: class LogStream : public std::ostream //流 LogMessage(***);//构造函数 ~LogMessage();//析构函数 void Flush(); void SendToLog(); void SendToSyslogAndLog(); static void __declspec(noreturn) Fail(); std::ostream& stream(); |
Private: void SendToSinkAndLog(); void SendToSink(); void WriteToStringAndLog(); void SaveOrSendToLog(); void Init(……); LogMessageData* allocated_; LogMessageData* data_; friend class LogDestination; LogMessage(const LogMessage&); void operator=(const LogMessage&); |
日志内容的具体输出接口为LOG(***);其实是LogMessage封装后的接口,##起到连接的作用。 LOG(INFO) << str;其实替换过去就是COMPACT_GOOGLE_LOG_INFO.stream()<<str;最终调用的还是LogMessage的构造函数。
#define LOG(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()
#define SYSLOG(severity) SYSLOG_ ## severity(0).stream() #if GOOGLE_STRIP_LOG == 0
#define COMPACT_GOOGLE_LOG_INFO google::LogMessage( \
__FILE__, __LINE__)
#define LOG_TO_STRING_INFO(message) google::LogMessage( \
__FILE__, __LINE__, google::GLOG_INFO, message)
#else
#define COMPACT_GOOGLE_LOG_INFO google::NullStream()
#define LOG_TO_STRING_INFO(message) google::NullStream()
#endif
下面我们看看构造函数的内容,就是初始化了一些东西,文件名称,Log等级,行号等参数。
LogMessage::LogMessage(const char* file, int line)
: allocated_(NULL) {
Init(file, line, GLOG_INFO, &LogMessage::SendToLog);
} void LogMessage::Init(const char* file,int line,LogSeverity severity,void (LogMessage::*send_method)()) {/*do something*/ }
析构函数:
LogMessage::~LogMessage() {
Flush();//写数据
}
// Flush buffered message, called by the destructor, or any other function
// that needs to synchronize the log.
void LogMessage::Flush() {/*flush*/}
LogMessage中有一个友类,LogDestination,接下来我们看一下这个类。
2.2
LogDestination
LogDestination |
Public: friend class LogMessage; friend void ReprintFatalMessage(); friend base::Logger* base::GetLogger(LogSeverity); friend void base::SetLogger(LogSeverity, base::Logger*); static void SetLogDestination(LogSeverity severity, const char* base_filename); static void SetLogSymlink(LogSeverity severity, const char* symlink_basename); static void AddLogSink(LogSink *destination); static void RemoveLogSink(LogSink *destination); static void SetLogFilenameExtension(const char* filename_extension); static void SetStderrLogging(LogSeverity min_severity); static void SetEmailLogging(LogSeverity min_severity, const char* addresses); static void LogToStderr(); static void FlushLogFiles(int min_severity); static void FlushLogFilesUnsafe(int min_severity); static const int kNetworkBytes = 1400; static const string& hostname(); static const bool& terminal_supports_color(); static void DeleteLogDestinations(); |
Private: LogDestination(LogSeverity severity, const char* base_filename); ~LogDestination() { } static vector<LogSink*>* sinks_; static Mutex sink_mutex_; LogDestination(const LogDestination&); LogDestination& operator=(const LogDestination&); |
LogDestination主要提供了日志文件的名称设置接口和日志的书写方式。我们看个例子:
SetLogFilenameExtension:文件后缀名设置
效果如图
具体代码:
inline void LogDestination::SetLogFilenameExtension(const char* ext) {
// Prevent any subtle race conditions by wrapping a mutex lock around
// all this stuff.
MutexLock l(&log_mutex);
for ( int severity = ; severity < NUM_SEVERITIES; ++severity ) {
log_destination(severity)->fileobject_.SetExtension(ext);
}
}
而SetExtension来自类LogFileObject,此处先不展开。我们看setExtension
/*
string filename_extension_; // option users can specify (eg to add port#)
*/
void LogFileObject::SetExtension(const char* ext) {
MutexLock l(&lock_);
if (filename_extension_ != ext) {
// Get rid of old log file since we are changing names
if (file_ != NULL) {
fclose(file_);
file_ = NULL;
rollover_attempt_ = kRolloverAttemptFrequency-;
}
filename_extension_ = ext;
}
}
可以看出LogDestination其实只是一个壳,负责和LogMessage以及其他的一些类进行互动。真正实现还得看LogFileObject类。
2.3
LogFileObject
LogFileObject : public base::Logger |
LogFileObject(LogSeverity severity, const char* base_filename); virtual void Write(bool force_flush, // Should we force a flush here? // Configuration options // Normal flushing routine virtual uint32 LogSize() { void FlushUnlocked(); |
Mutex lock_; bool base_filename_selected_; string base_filename_; string symlink_basename_; string filename_extension_; // option users can specify (eg to add port#) FILE* file_; LogSeverity severity_; uint32 bytes_since_flush_; uint32 dropped_mem_length_; uint32 file_length_; unsigned int rollover_attempt_; int64 next_flush_time_; |
关于这个类,我们看一个函数:
void LogFileObject::Write(bool force_flush,
time_t timestamp,
const char* message,
int message_len) {
MutexLock l(&lock_); //条件判断,不符合直接return
if (base_filename_selected_ && base_filename_.empty()) {
return;
} if (base_filename_selected_)
{
/*如果没有创建日志文件,return*/
if (!CreateLogfile(time_pid_string)) {
perror("Could not create log file");
fprintf(stderr, "COULD NOT CREATE LOGFILE '%s'!\n",
time_pid_string.c_str());
return;
}
}
else
{
ostringstream file_header_stream;
file_header_stream.fill(''); file_header_stream << "Log file created at: "
<< +tm_time.tm_year << '/'
<< setw() << +tm_time.tm_mon << '/'
<< setw() << tm_time.tm_mday
<< ' '
<< setw() << tm_time.tm_hour << ':'
<< setw() << tm_time.tm_min << ':'
<< setw() << tm_time.tm_sec << '\n'
<< "Running on machine: "
<< LogDestination::hostname() << '\n'
<< "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu "
<< "threadid file:line] msg" << '\n';
const string& file_header_string = file_header_stream.str(); const int header_len = file_header_string.size();
fwrite(file_header_string.data(), , header_len, file_);
file_length_ += header_len;
bytes_since_flush_ += header_len;
}
/*写满了怎么办?*/
// Write to LOG file
if ( !stop_writing ) {
// fwrite() doesn't return an error when the disk is full, for
// messages that are less than 4096 bytes. When the disk is full,
// it returns the message length for messages that are less than
// 4096 bytes. fwrite() returns 4096 for message lengths that are
// greater than 4096, thereby indicating an error.
errno = ;
fwrite(message, , message_len, file_);
if ( FLAGS_stop_logging_if_full_disk &&
errno == ENOSPC ) { // disk full, stop writing to disk
stop_writing = true; // until the disk is
return;
} else {
file_length_ += message_len;
bytes_since_flush_ += message_len;
}
}
else {
if ( CycleClock_Now() >= next_flush_time_ )
stop_writing = false; // check to see if disk has free space.
return; // no need to flush
}
/*do otherthings*/
}
对应的就是以下内容
Log file created at: 2019/01/28 15:27:56
Running on machine: HostName
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
I0128 15:27:56.937649 16208 glogtest.cpp:20] hello log!
I0128 15:27:56.958592 16208 glogtest.cpp:21] info testhello log!
W0128 15:27:56.958592 16208 glogtest.cpp:22] warning test
E0128 15:27:56.958592 16208 glogtest.cpp:23] error test
我们再看一个函数:可以看出这个函数的功能就是创建文件名称。如果我们可以修改time_pid_string这个值,或者直接修改string_filename的值,就可以直接修改文件的名字,因为原始的名字真的是太长了,而且不便查找。
bool LogFileObject::CreateLogfile(const string& time_pid_string) {
string string_filename = base_filename_+filename_extension_+
time_pid_string;
const char* filename = string_filename.c_str();
int fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, FLAGS_logfile_mode);
if (fd == -) return false;
#ifdef HAVE_FCNTL
// Mark the file close-on-exec. We don't really care if this fails
fcntl(fd, F_SETFD, FD_CLOEXEC);
#endif file_ = fdopen(fd, "a"); // Make a FILE*.
if (file_ == NULL) { // Man, we're screwed!
close(fd);
unlink(filename); // Erase the half-baked evidence: an unusable log file
return false;
} // We try to create a symlink called <program_name>.<severity>,
// which is easier to use. (Every time we create a new logfile,
// we destroy the old symlink and create a new one, so it always
// points to the latest logfile.) If it fails, we're sad but it's
// no error.
/*do something*/ return true; // Everything worked
}
3.太深了……写不动了
参考网站:http://www.cnblogs.com/tianyajuanke/archive/2013/02/22/2921850.html
glog学习(二):glog主要接口和类分析的更多相关文章
- JavaWeb学习——Servlet相关的接口和类
JavaWeb学习——Servlet相关的接口和类 摘要:本文主要学习了Servlet相关的接口和类. Servlet的接口和类 三种方式 实现Servlet有三种方式: 实现javax.servle ...
- java容器二:List接口实现类源码分析
一.ArrayList 1.存储结构 动态数组elementData transient Object[] elementData; 除此之外还有一些数据 //默认初始容量 private stati ...
- A11-java学习-二维数组-面向对象概念-类的编写-测试类的编写-创建对象-使用对象-递归
二维数组的内存结构和使用 引用类型的内存结构 栈区.堆区.方法区.数据栈等内存分析和介绍 面向对象.面向过程区别和发展 类型的定义 引用类型.值类型 预定义类型和自定义类型 类型与对象(实例) 对象的 ...
- 集合框架二(Collection接口实现类常用遍历方法)
四种常用遍历方式 Collection coll = new ArrayList(); coll.add("123"); coll.add("456"); co ...
- 探究UE4网络系列(二)、UE4网络核心类分析
转载请标明出处:http://www.cnblogs.com/zblade/ 一.概要 前面分析了网络核心的基础类Socket/BSDSocket/SocketSubsystem/SocketSubs ...
- C++卷积神经网络实例:tiny_cnn代码具体解释(8)——partial_connected_layer层结构类分析(上)
在之前的博文中我们已经将顶层的网络结构都介绍完毕,包括卷积层.下採样层.全连接层,在这篇博文中主要有两个任务.一是总体贯通一下卷积神经网络在对图像进行卷积处理的整个流程,二是继续我们的类分析.这次须要 ...
- C++的开源跨平台日志库glog学习研究(二)--宏的使用
上一篇从整个工程上简单分析了glog,请看C++的开源跨平台日志库glog学习研究(一),这一篇对glog的实现代码入手,比如在其源码中以宏的使用最为广泛,接下来就先对各种宏的使用做一简单分析. 1. ...
- C++的开源跨平台日志库glog学习研究(三)--杂项
在前面对glog分别做了两次学习,请看C++的开源跨平台日志库glog学习研究(一).C++的开源跨平台日志库glog学习研究(二)--宏的使用,这篇再做个扫尾工作,算是基本完成了. 编译期断言 动态 ...
- List接口实现类-ArrayList、Vector、LinkedList集合深入学习以及源代码解析
学习List接口实现类 ArrayList Vector LinkedList List接口的实现类中最经常使用最重要的就是这三个:ArrayList.Vector.LinkedList. JDK ...
随机推荐
- OC的反射机制
反射机制主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法.对于人一个对象,都能够调用这个对象的任意方法和属性.这种 ...
- 理解SSL、HTTPS原理中的对称加密与非对称加密
1.对称性加密 双方使用的同一个密钥,既可以加密又可以解密,这种加密方法称为对称加密,也称为单密钥加密. 简单来说就是:加密与解密都是同一个秘钥. 优点:通常在消息发送方需要加密大量数据时使用,算 ...
- MySQL简单查询语句练习
数据查询语法(DQL) DQL就是数据查询语言,数据库执行DQL语句不会对数据进行改变,而是让数据库发送结果集给客户端. 语法: SELECT selection_list /*要查询的列名称*/ F ...
- Codeforces 1064 D - Labyrinth
D - Labyrinth 对于位置(i,j), j - c = R - L = const(常数), 其中R表示往右走了几步,L表示往左走了几步 所以R越大, L就越大, R越小, L就越小, 所以 ...
- 第 8 章 容器网络 - 071 - 如何定制 Calico 的 IP 池?
定制IP池 首先定义一个 IP Pool,比如: calicoctl create -f ipPool.yml 用此 IP Pool 创建 calico 网络. docker network crea ...
- Ruby on Rails Tutorial 第一章笔记
搭建开发环境 作者介绍了 Cloud9\ Coding.net 这样的云端开发环境 安装 Rails 1. 新建 rails 应用 首先,调用 rails new 命令创建一个新的 Rails 应用, ...
- js之Object属性封装
在object.create出现之前,我们实现继承一般使用: function base(){} function children(){} //实现children继承base (function( ...
- 20175227张雪莹 2018-2019-2 《Java程序设计》第四周学习总结
20175227张雪莹 2018-2019-2 <Java程序设计>第四周学习总结 教材学习内容总结 一.子类和父类. 1.子类只继承父类中的protected和public访问权限的成员 ...
- nio 序列化
1.序列化 public class SerializeUtils<T extends Serializable> { public byte[] serialize(T t) { byt ...
- zabbix3.4.7使用过程中常见错误
================================================================================================ 1.Z ...