一.背景
日志记录是获取系统运行状态的有效手段,Postgresql通过无名pipe机制和独立日志进程实现系统日志的统一管理。
二.日志进程启动
1.配置参数
在文件postgresql.conf的ERROR REPORTING AND LOGGING的注释下面找到logging_collector设置logging_collector=on打开日志进程,同时需要重新启动数据库使设置生效。
2.启动进程
2.1 syslogger进程是postmaster的子进程
1)postmaster为父进程。
2)syslogger_start,包括正常启动流程和syslogger异常启动流程。
3)pipe(syslogpipe)创建管道,用于接收stderr/stdout输入。
4)mkdir 创建日志目录文件。
5)logfile_getname得到日志文件名。
6)fork_process fork子进程(syslogger进程)。
7)dup2 重定向stdout/stderr到syslogpipe管道。
8)fclose 因为postmaster不会直接写syslogFile,所以关闭日志文件。
9)返回子进程id。
2.2 子进程流程
1)syslogger日志进程。
2)InitPostmasterChild子进程变量初始化。
3)closePostmasterPorts关闭fork父进程的端口。
4)断开和postmaster共享内存的连接。
5)业务主入口。
6)信号处理设置。
7)循环处理,包括:重载日志配置文件、日志目录、日志文件切换、日志启动时间处理、日志大小控制、读管道信息、写日志文件。
3.管道读写日志协议
1)PipeProtoHeader
typedef struct
{
char nuls[2]; /* always \0\0 */
uint16 len; /* size of this chunk (counts data only) */
int32 pid; /* writer's pid */
char is_last; /* last chunk of message? 't' or 'f' ('T' or
* 'F' for CSV case) */
char data[FLEXIBLE_ARRAY_MEMBER]; /* data payload starts here */
} PipeProtoHeader;
当一次写的日志过大,可以通过 is_last标识切割成多个包,syslogger接收后统一写入日志文件。
2)elog.h写日志函数
一般用ereport(elevel,rest)作为其他进程写日志的api。
三.源码位置
1.src/backend/postmaster/postmaster.c
2.src/backend/postmaster/syslogger.c
3.src/backend/utils/error/elog.c