golang加輸出日誌,golang更新日誌

本文目錄一覽:

golang常用的包—-寫日誌 log包

golang提供了一個簡單的日誌輸出包log,常用用法,已經基本滿足日常的日誌輸出需求

1、日誌級別有3個,info,fatal,panic

2、 日誌文件的輸出

輸出的結果 a.log

[Debug]main.go:45: debug info is ,check list ,hello

[Debug]main.go:46: debug info is ,check list ,hello000111

[Info]2020/09/09 Info check

標準輸出:

[Info]2020/09/09 Info check stdout

樣例二:

輸出結果為:

[Info]2020/09/09 Check init info

[Info]2020/09/09 go to function Check

Golang將日誌同時輸出到控制台和文件

日常開發當中需要將golang的log包打印的日誌同時輸出到控制台和文件,應該如何解決這個問題?

log包可以通過SetOutput()方法指定日誌輸出的方式(Writer),但是只能指定一個輸出的方式(Writer)。我們利用io.MultiWriter()將多個Writer拼成一個Writer使用的特性,把log.Println()輸出的內容分流到控制台和文件當中。

原文地址

golang logger輸出格式怎麼修改

1.Logger結構

首先來看下類型Logger的定義:

type Logger struct {

mu sync.Mutex // ensures atomic writes; protects the following fields

prefix string // prefix to write at beginning of each line

flag int // properties

out io.Writer // destination for output

buf []byte // for accumulating text to write

}

主要有5個成員,其中3個我們比較熟悉,分別是表示Log前綴的 “prefix”,表示Log頭標籤的 “flag” ,以及Log的輸出目的地out。 buf是一個位元組數組,主要用來存放即將刷入out的內容,相當於一個臨時緩存,在對輸出內容進行序列化時作為存儲目的地。 mu是一個mutex主要用來作線程安全的實習,當有多個goroutine同時往一個目的刷內容的時候,通過mutex保證每次寫入是一條完整的信息。

2.std及整體結構

在前一篇文章中我們提到了log模塊提供了一套包級別的簡單接口,使用該接口可以直接將日誌內容打印到標準錯誤。那麼該過程是怎麼實現的呢?其實就是通過一個內置的Logger類型的變量 “std” 來實現的。該變量使用:

var std = New(os.Stderr, “”, LstdFlags)

進行初始化,默認輸出到系統的標準輸出 “os.Stderr” ,前綴為空,使用日期加時間作為Log抬頭。

當我們調用 log.Print的時候是怎麼執行的呢?我們看其代碼:

func Print(v …interface{}) {

std.Output(2, fmt.Sprint(v…))

}

這裡實際就是調用了Logger對象的 Output方法,將日誌內容按照fmt包中約定的格式轉義後傳給Output。Output定義如下 :

func (l *Logger) Output(calldepth int, s string) error

其中s為日誌沒有加前綴和Log抬頭的具體內容,xxxxx 。該函數執行具體的將日誌刷入到對應的位置。

3.核心函數的實現

Logger.Output是執行具體的將日誌刷入到對應位置的方法。

該方法首先根據需要獲得當前時間和調用該方法的文件及行號信息。然後調用formatHeader方法將Log的前綴和Log抬頭先格式化好 放入Logger.buf中,然後再將Log的內容存入到Logger.buf中,最後調用Logger.out.Write方法將完整的日誌寫入到輸出目的地中。

由於寫入文件以及拼接buf的過程是線程非安全的,因此使用mutex保證每次寫入的原子性。

l.mu.Lock()

defer l.mu.Unlock()

將buf的拼接和文件的寫入放入這個後面,使得在多個goroutine使用同一個Logger對象是,不會弄亂buf,也不會雜糅的寫入。

該方法的第一個參數最終會傳遞給runtime.Caller的skip,指的是跳過的棧的深度。這裡我記住給2就可以了。這樣就會得到我們調用log 是所處的位置。

在golang的注釋中說鎖住 runtime.Caller的過程比較重,這點我還是不很了解,只是從代碼中看到其在這裡把鎖打開了。

if l.flag(Lshortfile|Llongfile) != 0 {

// release lock while getting caller info – it『s expensive.

l.mu.Unlock()

var ok bool

_, file, line, ok = runtime.Caller(calldepth)

if !ok {

file = “???”

line = 0

}

l.mu.Lock()

}

在formatHeader裏面首先將前綴直接複製到Logger.buf中,然後根據flag選擇Log抬頭的內容,這裡用到了一個log模塊實現的 itoa的方法,作用類似c的itoa,將一個整數轉換成一個字符串。只是其轉換後將結果直接追加到了buf的尾部。

縱觀整個實現,最值得學習的就是線程安全的部分。在什麼位置合適做怎樣的同步操作。

4.對外接口的實現

在了解了核心格式化和輸出結構後,在看其封裝就非常簡單了,幾乎都是首先用Output進行日誌的記錄,然後在必要的時候 做os.exit或者panic的操作,這裡看下Fatal的實現。

func (l *Logger) Fatal(v …interface{}) {

l.Output(2, fmt.Sprint(v…))

os.Exit(1)

}

// Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1).

func (l *Logger) Fatalf(format string, v …interface{}) {

l.Output(2, fmt.Sprintf(format, v…))

os.Exit(1)

}

// Fatalln is equivalent to l.Println() followed by a call to os.Exit(1).

func (l *Logger) Fatalln(v …interface{}) {

l.Output(2, fmt.Sprintln(v…))

os.Exit(1)

}

這裡也驗證了我們之前做的Panic的結果,先做輸出日誌操作。再進行panic。

Supervisor與Logrotate

        在golang的gin項目中使用supervisor守護進程,用子進程配置將標準輸出日誌轉移到指定目錄下,然後使用阿里雲的日誌服務將標準輸出日誌轉移到線上做一些分析和預警。

      項目上線之後一切正常,可是周日夜裡三點左右阿里雲的日誌服務採集不到日誌,一頓pv為0的告警過來,趕緊打開電腦,線上服務正常,鬆一口氣,supervisor狀態也正常,觀察了一會業務數據正常就安然入睡了,心想可能是因為配置項有缺陷吧,回頭好好整整supervisor的配置再觀察一波。

       早上起來打開服務器,cd /var/log/supervisor/,發現存在兩個日誌文件,分別是xxxx.log-20201223和xxxx.log,xxxx.log的大小為0,xxxx.log-20201223還在繼續寫入請求日誌,權限問題?chmod 777之後發現新的文件還是不寫入日誌,重啟 supervisor之後發現日誌能正常寫入了。。。一開始懷疑是supervisor日誌切割備份有問題,將配置stdout日誌文件大小的stdout_logfile_maxbytes配置項,默認 50MB改成0,代表無限大,stdout日誌文件備份數的stdout_logfile_backups配置項,默認10改為0,代表不備份,重啟supervisor,心想不切割總不會再出現切割之後不往新文件寫內容的問題了,真乃明智之選。:)

        一周過去,0pv的告警如期而至,雖然不影響線上業務,如鯁在喉讓我久久不能釋懷。全網翻,百度谷歌,中文英文,去github上翻issue等等,看到一個歷史issue1090,Better support for logrotate,感覺和日誌轉儲相關,於是查了下logrotate相關資料,logrotate程序是一個日誌文件管理工具。用於分割日誌文件,刪除舊的日誌文件,並創建新的日誌文件,起到「轉儲」作用。centos系統默認安裝,於是找到對應的配置文件,果不其然裏面就有supervisor,默認配置如下:

/var/log/supervisor/*.log {

      missingok

      weekly

      notifempty

      nocompress

},看到weekly感覺離這個問題的答案不遠了,於是去查找linux的logrotate往舊文件寫入的問題,在一篇logrotate writing to old app.log.1 instead of app.log的文章中找到需要配置參數copytruncate,是用於還在打開中的日誌文件,把當前日誌備份並截斷;是先拷貝再清空的方式,拷貝和清空之間有一個時間差,可能會丟失部分日誌數據。增加完配置之後,為了快速驗證結果,修改weekly為daily,第二天日誌正常切割了,新的文件也正常寫入了標準日誌。至此問題解決。

        linux的logrotate對於運維來說可能是常識,作為開發剛接觸運維,只能慢慢積累了,工作之餘看看相關的運維知識,盡量少採坑。

Golang的log包哪個好用

建議使用Log,這是android專門用來開發打印日誌使用的。輸出的日誌可以在Logcat中查看。 Android開發中,所的有輸出都在logcat中 包含System.out輸出和printStackTrace()輸出都在Logcat中,Android開發,建議使用android提供的Log

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/200769.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-05 20:03
下一篇 2024-12-06 11:28

相關推薦

  • 使用Golang調用Python

    在現代軟件開發中,多種編程語言的協作是相當普遍的。其中一種使用場景是Golang調用Python,這使得在使用Python庫的同時,可以利用Golang的高性能和強大並發能力。這篇…

    編程 2025-04-29
  • Cron執行日誌用法介紹

    本文將從多個方面對cron執行日誌進行詳細闡述,包括cron執行日誌的定義、cron執行日誌的產生原因、cron執行日誌的格式以及如何解讀cron執行日誌。 一、定義 Cron是一…

    編程 2025-04-29
  • Hibernate日誌打印sql參數

    本文將從多個方面介紹如何在Hibernate中打印SQL參數。Hibernate作為一種ORM框架,可以通過打印SQL參數方便開發者調試和優化Hibernate應用。 一、通過配置…

    編程 2025-04-29
  • 使用Snare服務收集日誌:完整教程

    本教程將介紹如何使用Snare服務收集Windows服務器上的日誌,並將其發送到遠程服務器進行集中管理。 一、安裝和配置Snare 1、下載Snare安裝程序並安裝。 https:…

    編程 2025-04-29
  • 使用Golang創建黑色背景圖片的方法

    本文將從多個方面介紹使用Golang創建黑色背景圖片的方法。 一、安裝必要的代碼庫和工具 在開始創建黑色背景圖片之前,我們需要先安裝必要的代碼庫和工具: go get -u git…

    編程 2025-04-29
  • Log4j日誌打印到Systemout.log

    Log4j是Apache的一個強大的日誌組件,可以幫助開發者更好地管理日誌。在Java應用程序中,很多開發者都會選擇使用Log4j來實現日誌輸出。本文將介紹如何使用Log4j將日誌…

    編程 2025-04-28
  • 如何將Linux系統日誌發送到日誌服務器

    本文將介紹如何將Linux系統日誌發送到日誌服務器,以方便管理和監控系統狀態。 一、安裝rsyslog軟件包 rsyslog是Linux系統上默認的系統日誌軟件,用於收集系統事件和…

    編程 2025-04-27
  • SpringBoot如何設置不輸出Info日誌

    本篇文章將帶您了解如何在SpringBoot項目中關閉Info級別日誌輸出。 一、為什麼要關閉Info日誌 在開發中,我們經常會使用Log4j、Logback等框架來輸出日誌信息,…

    編程 2025-04-27
  • Mybatis-plus 日誌詳解

    一、日誌框架概述 1、什麼是日誌框架 日誌框架是一個用於管理日誌的工具,使用日誌框架可以幫助開發人員記錄程序運行時產生的信息、警告和錯誤消息。常用的日誌框架有log4j和logba…

    編程 2025-04-24
  • Python日誌記錄詳解

    在軟件開發中,日誌記錄是非常重要的一項功能。它可以幫助開發者追蹤程序的狀態,發現問題並進行調試。Python提供了很多模塊來處理日誌記錄,例如logging模塊。在這篇文章中,我們…

    編程 2025-04-24

發表回復

登錄後才能評論