關於PostgreSQL錯誤日誌與慢查詢日誌收集
PostgreSQL錯誤日誌與慢查詢日誌對於線上系統分析、問題預警、問題排查起到非常重要的作用,在此不做贅述。
此文件記錄錯誤日誌與慢查詢日誌的收集、分析與儲存展示的方法。
一、總體思路
PostgreSQL日誌輸出可以配置多種多樣的格式,其中以csvlog格式輸出的日誌資訊最全面。但是CSV日誌只能以本地檔案的方式收集,不能直接寫入網路,實時上傳日誌伺服器。
日誌收集:
PostgreSQL伺服器分佈在不同的機器,我們使用rsyslog客戶端-伺服器的方式來收集日誌到日誌伺服器。具體方法:在PostgreSQL伺服器部署客戶端,在日誌伺服器部署伺服器,客戶端監控日誌檔案的變化,實時將新增日誌上傳到伺服器,伺服器根據不同客戶端上傳的日誌,分別記錄在不同的檔案中。
此方法的好處是在PostgreSQL伺服器本地可以儲存一份原始的完整的csv日誌,供全量資訊檢視與分析。
日誌分析:
使用Logstash進行日誌分析,Logstash是一個開源資料收集引擎,具有實時管道功能。Logstash可以動態地將來自不同檔案的資料統一起來,進行資料篩選清洗,並將資料標準化到你所選擇的目的地。
日誌儲存展示:
使用傳統的Elasticsearch進行資料儲存,Kibana進行資料展示。
二、rsyslog伺服器端配置
新增以下內容到rsyslog配置檔案/etc/rsyslog.conf,並重啟rsyslog服務。
$PreserveFQDN on #用於正確的獲取主機名 $FileOwner root #儲存的檔案屬主 $FileGroup root #檔案屬主 $FileCreateMode 0644 #生成的檔案許可權 $DirCreateMode 0755 #生成的目錄許可權 $Umask 0022 $PrivDropToUser root #可以刪除日誌的使用者 $PrivDropToGroup root #可以刪除日誌的使用者組 module(load="imuxsock") module(load="imklog") module(load="imudp") #input(type="imudp" port="514") module(load="imtcp" MaxSessions="500") input(type="imtcp" port="514") $template linefmt,"%msg:2:$%\n" #接收日誌的格式(去掉開頭的空格) $template pgloglocation,"/data/pglogs/%hostname%/%$YEAR%-%$MONTH%-%$DAY%.csv" :rawmsg,contains,"pg_5432" ?pgloglocation;linefmt ##變數:%fromhost-ip%
三、rsyslog客戶端配置
新建配置檔案/etc/rsyslog.d/10-pg.conf,並重啟rsyslog服務。
cat /etc/rsyslog.d/10-pg.conf module(load="imuxsock") module(load="imklog") module(load="imfile") #module(load="imudp") #input(type="imudp" port="514") module(load="imtcp" MaxSessions="500") input(type="imtcp" port="514") ruleset(name="remote"){ action(type="omfwd" target="x.x.x.x" #日誌伺服器IP地址 port="514" #埠 protocol="tcp" #使用協議 queue.type="linkedList" #使用非同步處理 queue.spoolDirectory="/var/log/rsyslog" #佇列目錄 queue.fileName="pglog" #佇列名稱 queue.maxDiskSpace="1g" #佇列佔最大磁碟空間 queue.saveOnShutdown="on" #儲存記憶體資料如果rsyslog關閉 action.resumeRetryCount="-1" #無限重試插入失敗 ) stop } input( type="imfile" File="/pg/data/log/*.csv" #PG伺服器日誌路徑 Facility="local1" Severity="info" Tag="pg_5432" #定義日誌標籤,重要,服務端根據這個標籤可以識別日誌 PersistStateInterval="1" #回寫偏移量資料到檔案間隔時間(秒),根據實際情況而定 deleteStateOnFileDelete="on" reopenOnTruncate="on" Ruleset="remote" #rsyslog.conf中定義的rule名稱 )
四、logstash配置
在日誌伺服器上編輯好配置檔案後,啟動logstash即可。配置檔案如下:
input { file { path => ["/data/pglogs/*/*.csv"] start_position => "end" codec => multiline { pattern => "^20[0-9]{2}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}" negate => true what => "previous" } } } filter { csv { separator => "," columns => ["log_time","user_name","database_name","process_id","connection_from","session_id","session_line_num","command_tag","session_start_time","virtual_transaction_id","transaction_id","error_severity","sql_state_code","message","detail","hint","internal_query","internal_query_pos","context","query","query_pos","location","application_name"] convert => { "process_id" => "integer" "session_line_num" => "integer" "transaction_id" => "integer" "internal_query_pos" => "integer" "query_pos" => "integer" } skip_empty_columns => true } mutate{ split => { "log_time" => " CST" } add_field => { "log_time_tmp" => "%{[log_time][0]}" } remove_field => ["log_time"] } date { match => ["log_time_tmp","yyyy-MM-dd HH:mm:ss.SSS"] target => "@timestamp" locale => "cn" remove_field => ["log_time_tmp"] } if "duration:" in [message] and "ms" in [message] and "statement:" in [message] { grok{ match => { "message" => "duration: %{NUMBER:duration} ms" } } mutate{ split => { "message" => "statement: " } add_field => { "statement" => "%{[message][1]}" } remove_field => ["message"] } } mutate{ split => { "path" => "/" } add_field => { "db_host" => "%{[path][3]}" } remove_field => ["path","host"] convert => { "duration" => "float" } } } output { if [error_severity] == "ERROR" or [error_severity] == "FATAL" or [error_severity] == "PANIC" { elasticsearch { hosts => ["x.x.x.x:x","x.x.x.x:x"] index => "pg_error" id => "elasticsearch_pg_error" } }else if [duration] and [statement] { elasticsearch { hosts => ["x.x.x.x:x","x.x.x.x:x"] index => "pg_slow" id => "elasticsearch_pg_slow" } } }
五、此處省略了Elasticsearch儲存與Kibana展示,這裡不多介紹
補充:PostgreSQL開發者模式錯誤反饋與日誌設定
####when何時記錄
#client_min_messages = notice log_min_messages = debug5 #debug級別是提供給開發人員使用的,這個可以看到程式呼叫的資訊以及SQL轉化為資料結構的資訊,每分鐘的級別
####where記錄到哪裡
#log_destination = 'stderr' logging_collector = on #開啟日誌收集 log_directory = 'pg_log' #日誌目錄 log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
####what寫什麼日誌
debug_print_parse = on #解析樹 debug_print_rewritten = on #查詢重寫後的SQL debug_print_plan = on #執行計劃詳細 debug_pretty_print = on #對debug_print_parse,debug_print_rewritten,debug_print_plan可讀性格式化 #log_checkpoints = off #如果是研究pg的磁碟IO,這個需要設定為on log_connections = on #連線日誌 log_disconnection = on #斷開連線日誌 #log_duration=on #語句執行時間,對於分析
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援我們。如有錯誤或未考慮完全的地方,望不吝賜教。