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);
  ~LogFileObject();

virtual void Write(bool force_flush, // Should we force a flush here?
                     time_t timestamp,  // Timestamp for this entry
                     const char* message,
                     int message_len);

// Configuration options
  void SetBasename(const char* basename);
  void SetExtension(const char* ext);
  void SetSymlinkBasename(const char* symlink_basename);

// Normal flushing routine
  virtual void Flush();

virtual uint32 LogSize() {
    MutexLock l(&lock_);
    return file_length_;
  }

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主要接口和类分析的更多相关文章

  1. JavaWeb学习——Servlet相关的接口和类

    JavaWeb学习——Servlet相关的接口和类 摘要:本文主要学习了Servlet相关的接口和类. Servlet的接口和类 三种方式 实现Servlet有三种方式: 实现javax.servle ...

  2. java容器二:List接口实现类源码分析

    一.ArrayList 1.存储结构 动态数组elementData transient Object[] elementData; 除此之外还有一些数据 //默认初始容量 private stati ...

  3. A11-java学习-二维数组-面向对象概念-类的编写-测试类的编写-创建对象-使用对象-递归

    二维数组的内存结构和使用 引用类型的内存结构 栈区.堆区.方法区.数据栈等内存分析和介绍 面向对象.面向过程区别和发展 类型的定义 引用类型.值类型 预定义类型和自定义类型 类型与对象(实例) 对象的 ...

  4. 集合框架二(Collection接口实现类常用遍历方法)

    四种常用遍历方式 Collection coll = new ArrayList(); coll.add("123"); coll.add("456"); co ...

  5. 探究UE4网络系列(二)、UE4网络核心类分析

    转载请标明出处:http://www.cnblogs.com/zblade/ 一.概要 前面分析了网络核心的基础类Socket/BSDSocket/SocketSubsystem/SocketSubs ...

  6. C++卷积神经网络实例:tiny_cnn代码具体解释(8)——partial_connected_layer层结构类分析(上)

    在之前的博文中我们已经将顶层的网络结构都介绍完毕,包括卷积层.下採样层.全连接层,在这篇博文中主要有两个任务.一是总体贯通一下卷积神经网络在对图像进行卷积处理的整个流程,二是继续我们的类分析.这次须要 ...

  7. C++的开源跨平台日志库glog学习研究(二)--宏的使用

    上一篇从整个工程上简单分析了glog,请看C++的开源跨平台日志库glog学习研究(一),这一篇对glog的实现代码入手,比如在其源码中以宏的使用最为广泛,接下来就先对各种宏的使用做一简单分析. 1. ...

  8. C++的开源跨平台日志库glog学习研究(三)--杂项

    在前面对glog分别做了两次学习,请看C++的开源跨平台日志库glog学习研究(一).C++的开源跨平台日志库glog学习研究(二)--宏的使用,这篇再做个扫尾工作,算是基本完成了. 编译期断言 动态 ...

  9. List接口实现类-ArrayList、Vector、LinkedList集合深入学习以及源代码解析

    学习List接口实现类 ArrayList  Vector  LinkedList List接口的实现类中最经常使用最重要的就是这三个:ArrayList.Vector.LinkedList. JDK ...

随机推荐

  1. OC的反射机制

    反射机制主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法.对于人一个对象,都能够调用这个对象的任意方法和属性.这种 ...

  2. 理解SSL、HTTPS原理中的对称加密与非对称加密

    1.对称性加密 双方使用的同一个密钥,既可以加密又可以解密,这种加密方法称为对称加密,也称为单密钥加密. 简单来说就是:加密与解密都是同一个秘钥.   优点:通常在消息发送方需要加密大量数据时使用,算 ...

  3. MySQL简单查询语句练习

    数据查询语法(DQL) DQL就是数据查询语言,数据库执行DQL语句不会对数据进行改变,而是让数据库发送结果集给客户端. 语法: SELECT selection_list /*要查询的列名称*/ F ...

  4. Codeforces 1064 D - Labyrinth

    D - Labyrinth 对于位置(i,j), j - c = R - L = const(常数), 其中R表示往右走了几步,L表示往左走了几步 所以R越大, L就越大, R越小, L就越小, 所以 ...

  5. 第 8 章 容器网络 - 071 - 如何定制 Calico 的 IP 池?

    定制IP池 首先定义一个 IP Pool,比如: calicoctl create -f ipPool.yml 用此 IP Pool 创建 calico 网络. docker network crea ...

  6. Ruby on Rails Tutorial 第一章笔记

    搭建开发环境 作者介绍了 Cloud9\ Coding.net 这样的云端开发环境 安装 Rails 1. 新建 rails 应用 首先,调用 rails new 命令创建一个新的 Rails 应用, ...

  7. js之Object属性封装

    在object.create出现之前,我们实现继承一般使用: function base(){} function children(){} //实现children继承base (function( ...

  8. 20175227张雪莹 2018-2019-2 《Java程序设计》第四周学习总结

    20175227张雪莹 2018-2019-2 <Java程序设计>第四周学习总结 教材学习内容总结 一.子类和父类. 1.子类只继承父类中的protected和public访问权限的成员 ...

  9. nio 序列化

    1.序列化 public class SerializeUtils<T extends Serializable> { public byte[] serialize(T t) { byt ...

  10. zabbix3.4.7使用过程中常见错误

    ================================================================================================ 1.Z ...