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);

// ShutdownGOOGLE_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的构造函数。

 1 #define LOG(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()
 2 #define SYSLOG(severity) SYSLOG_ ## severity(0).stream()
 3
 4 #if GOOGLE_STRIP_LOG == 0
 5 #define COMPACT_GOOGLE_LOG_INFO google::LogMessage( \
 6       __FILE__, __LINE__)
 7 #define LOG_TO_STRING_INFO(message) google::LogMessage( \
 8       __FILE__, __LINE__, google::GLOG_INFO, message)
 9 #else
10 #define COMPACT_GOOGLE_LOG_INFO google::NullStream()
11 #define LOG_TO_STRING_INFO(message) google::NullStream()
12 #endif

下面我们看看构造函数的内容,就是初始化了一些东西,文件名称,Log等级,行号等参数。

 1 LogMessage::LogMessage(const char* file, int line)
 2     : allocated_(NULL) {
 3   Init(file, line, GLOG_INFO, &LogMessage::SendToLog);
 4 }
 5
 6 void LogMessage::Init(const char* file,int line,LogSeverity severity,void (LogMessage::*send_method)()) {/*do something*/ }

析构函数:

1 LogMessage::~LogMessage() {
2   Flush();//写数据
3 }
4 // Flush buffered message, called by the destructor, or any other function
5 // that needs to synchronize the log.
6 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:文件后缀名设置
效果如图

具体代码:
1 inline void LogDestination::SetLogFilenameExtension(const char* ext) {
2   // Prevent any subtle race conditions by wrapping a mutex lock around
3   // all this stuff.
4   MutexLock l(&log_mutex);
5   for ( int severity = 0; severity < NUM_SEVERITIES; ++severity ) {
6     log_destination(severity)->fileobject_.SetExtension(ext);
7   }
8 }

而SetExtension来自类LogFileObject,此处先不展开。我们看setExtension
 1 /*
 2 string filename_extension_;     // option users can specify (eg to add port#)
 3 */
 4 void LogFileObject::SetExtension(const char* ext) {
 5   MutexLock l(&lock_);
 6   if (filename_extension_ != ext) {
 7     // Get rid of old log file since we are changing names
 8     if (file_ != NULL) {
 9       fclose(file_);
10       file_ = NULL;
11       rollover_attempt_ = kRolloverAttemptFrequency-1;
12     }
13     filename_extension_ = ext;
14   }
15 }

可以看出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_;
关于这个类,我们看一个函数:
 1 void LogFileObject::Write(bool force_flush,
 2                           time_t timestamp,
 3                           const char* message,
 4                           int message_len) {
 5   MutexLock l(&lock_);
 6
 7   //条件判断,不符合直接return
 8   if (base_filename_selected_ && base_filename_.empty()) {
 9     return;
10   }
11
12
13     if (base_filename_selected_)
14     {
15         /*如果没有创建日志文件,return*/
16       if (!CreateLogfile(time_pid_string)) {
17         perror("Could not create log file");
18         fprintf(stderr, "COULD NOT CREATE LOGFILE '%s'!\n",
19                 time_pid_string.c_str());
20         return;
21       }
22     }
23     else
24     {
25     ostringstream file_header_stream;
26     file_header_stream.fill('0');
27
28     file_header_stream << "Log file created at: "
29                        << 1900+tm_time.tm_year << '/'
30                        << setw(2) << 1+tm_time.tm_mon << '/'
31                        << setw(2) << tm_time.tm_mday
32                        << ' '
33                        << setw(2) << tm_time.tm_hour << ':'
34                        << setw(2) << tm_time.tm_min << ':'
35                        << setw(2) << tm_time.tm_sec << '\n'
36                        << "Running on machine: "
37                        << LogDestination::hostname() << '\n'
38                        << "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu "
39                        << "threadid file:line] msg" << '\n';
40     const string& file_header_string = file_header_stream.str();
41
42     const int header_len = file_header_string.size();
43     fwrite(file_header_string.data(), 1, header_len, file_);
44     file_length_ += header_len;
45     bytes_since_flush_ += header_len;
46   }
47     /*写满了怎么办?*/
48   // Write to LOG file
49   if ( !stop_writing ) {
50     // fwrite() doesn't return an error when the disk is full, for
51     // messages that are less than 4096 bytes. When the disk is full,
52     // it returns the message length for messages that are less than
53     // 4096 bytes. fwrite() returns 4096 for message lengths that are
54     // greater than 4096, thereby indicating an error.
55     errno = 0;
56     fwrite(message, 1, message_len, file_);
57     if ( FLAGS_stop_logging_if_full_disk &&
58          errno == ENOSPC ) {  // disk full, stop writing to disk
59       stop_writing = true;  // until the disk is
60       return;
61     } else {
62       file_length_ += message_len;
63       bytes_since_flush_ += message_len;
64     }
65   }
66   else {
67     if ( CycleClock_Now() >= next_flush_time_ )
68       stop_writing = false;  // check to see if disk has free space.
69     return;  // no need to flush
70   }
71 /*do otherthings*/
72 }

对应的就是以下内容
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的值,就可以直接修改文件的名字,因为原始的名字真的是太长了,而且不便查找。

 1 bool LogFileObject::CreateLogfile(const string& time_pid_string) {
 2   string string_filename = base_filename_+filename_extension_+
 3                            time_pid_string;
 4   const char* filename = string_filename.c_str();
 5   int fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, FLAGS_logfile_mode);
 6   if (fd == -1) return false;
 7 #ifdef HAVE_FCNTL
 8   // Mark the file close-on-exec. We don't really care if this fails
 9   fcntl(fd, F_SETFD, FD_CLOEXEC);
10 #endif
11
12   file_ = fdopen(fd, "a");  // Make a FILE*.
13   if (file_ == NULL) {  // Man, we're screwed!
14     close(fd);
15     unlink(filename);  // Erase the half-baked evidence: an unusable log file
16     return false;
17   }
18
19   // We try to create a symlink called <program_name>.<severity>,
20   // which is easier to use.  (Every time we create a new logfile,
21   // we destroy the old symlink and create a new one, so it always
22   // points to the latest logfile.)  If it fails, we're sad but it's
23   // no error.
24   /*do something*/
25
26    return true;  // Everything worked
27 }

3.太深了……写不动了

参考网站:http://www.cnblogs.com/tianyajuanke/archive/2013/02/22/2921850.html

转载于:https://www.cnblogs.com/whutao/p/10331103.html

glog学习(二):glog主要接口和类分析相关推荐

  1. html与java接口,JavaWeb学习——Servlet相关的接口和类

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

  2. Java基础学习(二十一)之接口

    1. 接口 1.1 接口概述 五孔插线面板,不同品牌都能使用,因为它们遵循同样的规范来生产的.所以说接口其实就是一种公共的规范,只要符合规范,大家都可以使用. 笔记本,USB口,鼠标,键盘,U盘 接口 ...

  3. libed2k源码导读:(二)Session接口以及实现分析

    第二章 Session接口以及实现分析 目录 第二章 Session接口以及实现分析 2.1 获取会话状态 2.2 管理会话中所有的传输任务 2.3 管理点对点连接 2.4 管理alert 2.4.1 ...

  4. 从零开始学USB(二十二、USB接口HID类设备(四)_报表描述符Local类)

    本地项目标签定义控件的特征. 这些项目不会转移到下一个主要项目. 如果Main项定义了多个控件,则可能会有几个类似的Local项标签. 例如,一个Input项可能有几个与之关联的Usage标签,每个控 ...

  5. Android消息驱动Handler类分析

    Android系统中的消息驱动工作原理: 1.有一个消息队列,可以往这个消息队列中投递消息; 2.有一个消息循环,不断的从消息队列中取得消息,然后处理. 工作流程: 1.事件源将待处理的消息加入到消息 ...

  6. Kotlin 学习笔记(八)—— Kotlin类与对象之接口

    Kotlin 学习笔记(八)-- Kotlin类与对象之接口 Kotlin学习笔记系列教程 Kotlin 学习笔记(一)-- 概述.学习曲线.开发工具.参考资料 Kotlin 学习笔记(二)-- 基础 ...

  7. Hibernate学习(二):heibernate核心接口

    Hibernate是一种对JDBC做了轻量级封装的对象---关系映射工具,所谓轻量级封装,是指Hibernate并没有完全封装JDBC,Java应用即可以通过Hibernate API访问数据库,还可 ...

  8. 【Java】(二十四)File类(文件操作,文件夹操作,FileFilter接口);Properties属性集合

    继续上一章,学习JavaIO框架 [Java](二十三)IO框架:流的概念与分类,字节流(对象流[序列化.反序列化]),编码方式,字符流(打印流,转换流) 上一节的学习(字节流,字符流)都是对文件内容 ...

  9. qml学习笔记(二):可视化元素基类Item详解(上半场anchors等等)

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7851 ...

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

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

最新文章

  1. javascript 实现模拟滚动条,但不支持鼠标滚轮
  2. vant组件搜索并选择_Vue.js自定义弹层组件|vue仿微信/ios弹窗
  3. java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams
  4. ggplot2箱式图两两比较_R绘图 第四篇:绘制箱图(ggplot2)
  5. linux系统如何用root用户登陆,Linux用root账号创建一个新的登录账号的方法
  6. springcloud gateway ribbon使用_Github点赞接近 70k 的Spring Cloud学习教程+实战项目推荐!牛批!...
  7. Vue中数组变动监听
  8. struct interface_GCTT | 接受 interface 参数,返回 struct 在 go 中意味着什么
  9. 为什么太重感情的人基本都是穷人?
  10. 线性表顺序表模板 纯本人手工创造
  11. 美团回应遭反垄断调查;腾讯因《地下城与勇士》被抄袭获赔3000万;iOS 14.5 正式版发布|极客头条...
  12. iOS开发之字典(NSDictionary)和JSON字符串(NSString)之间互转
  13. org.apache.hadoop.fs.ChecksumException: Checksum error
  14. 【前端词典】进阶必备的网络基础
  15. python 拆分pdf指定页_Python简单拆分PDF文件,将一个PDF文件拆分成指定份数
  16. 只有10分,5分,2分,1分的硬币;顾客付款x分,商品价格y分。如何找零所使用的硬币最少(递归实现)
  17. [转载]AlphaGo 的棋局,与人工智能有关,与人生无关
  18. SPSSPRO杯第十五届数学中国数学建模网络挑战赛赛题浅评
  19. QQ Scheme跳转接口
  20. 当Forms表单遇到Power BI

热门文章

  1. linux下dns视图配置
  2. 第二章 身份验证——跟我学习springmvc shiro mybatis
  3. java中实现多线程的两种基本方法
  4. linux和Dos下换行符转换
  5. 开源 免费 java CMS - FreeCMS1.5 标签 ajaxStore
  6. Eclipse 4.7(Oxygen)安装Tomcat Plugin 后没有小猫图标解决方法
  7. java 测试 jar_java – 从可执行jar运行spring测试
  8. qt socket 传递结构体 结构体中有list_GO语言入门-14、结构体
  9. vb导入数据到mysql_用VB程序导入与导出MySQL数据的有关问题(急)
  10. redis安装配置 mysql_学习环境安装 mysql 与 redis