程序运行日志记录

1 程序运行日志记录

我们的程序起来之后,在后台运行的时候,我们如何拿到他在运行中的一些信息呢,我们当然可以通过日志去记录。我们就得使用 log 包

[15:14:25 root@go testlog]#go doc log
package log // import "log"

Package log implements a simple logging package. It defines a type, Logger,
with methods for formatting output. It also has a predefined 'standard'
Logger accessible through helper functions Print[f|ln], Fatal[f|ln], and
Panic[f|ln], which are easier to use than creating a Logger manually. That
logger writes to standard error and prints the date and time of each logged
message. Every log message is output on a separate line: if the message
being printed does not end in a newline, the logger will add one. The Fatal
functions call os.Exit(1) after writing the log message. The Panic functions
call panic after writing the log message.

const Ldate = 1 << iota ...
func Fatal(v ...interface{})
func Fatalf(format string, v ...interface{})
func Fatalln(v ...interface{})
func Flags() int
func Output(calldepth int, s string) error
func Panic(v ...interface{})
func Panicf(format string, v ...interface{})
func Panicln(v ...interface{})
func Prefix() string
func Print(v ...interface{})
func Printf(format string, v ...interface{})
func Println(v ...interface{})
func SetFlags(flag int)
func SetOutput(w io.Writer)
func SetPrefix(prefix string)
func Writer() io.Writer
type Logger struct{ ... }
    func Default() *Logger
    func New(out io.Writer, prefix string, flag int) *Logger

1.1 日志的几种记录方式

1.1.1 log.Println 记录日志输出

log.Println 用法和

package main

import "log"

func main() {
    log.Println("println")
}

执行我们会发现他以一种日志加上我们打印内容输出到终端上

[15:20:55 root@go testlog]#go run main.go 
2021/08/04 15:21:36 println

1.1.2 log.Fatal 记录日志输出并退出程序输出状态码

Fatal 源码如下

func Fatal(v ...interface{}) {
    std.Output(2, fmt.Sprint(v...))
    os.Exit(1)
}

log.Fatal 用法

package main

import "log"

func main() {
    log.Fatal("fatal")
    fmt.Println("11111")
}

执行发现他会在终端输出我们打印的内容,并且返回一个退出状态码,直接退出程序,而没有打印 11111

[15:21:36 root@go testlog]#go run main.go 
2021/08/04 15:36:32 fatal
exit status 1

之所以有状态退出码 1,是因为在他的源码中调用了 os.Exit(1)

1.1.3 log.Panic 直接报 panic 并且退出程序

panic 源码如下

// Panic is equivalent to Print() followed by a call to panic().
func Panic(v ...interface{}) {
    s := fmt.Sprint(v...)
    std.Output(2, s)
    panic(s)
}

package main

import (
    "fmt"
    "log"
)

func main() {
    log.Panic("panic")
    fmt.Println("11111")
}

执行后发现直接报 panic 平且不会执行 fmt.Println("11111")

[15:38:04 root@go testlog]#go run main.go 
2021/08/04 16:08:41 panic
panic: panic

goroutine 1 [running]:
log.Panic(0xc000074f58, 0x1, 0x1)
        /usr/local/go/src/log/log.go:354 +0xae
main.main()
        /data/go/day11/testlog/main.go:9 +0x65
exit status 2

之所以有状态退出码 1,是因为在他的源码中调用了 os.Exit(2)

1.2 日志记录的几种格式

日志格式有以下几个属性:

  • 前缀:我们可以给日志加上前缀,通过 log.SetPrefix(),会在输出日志之前有我们指定的字符串前缀

  • 程序文件输出日志:log.SetFlags

  • 日志输入到文件中:log.SetOutput()

1.2.1 前缀

log.SetPrefix() 定义日志输出前缀

package main

import (
    "log"
)

func main() {
    log.SetPrefix("testlog ")
    log.Println("testlog")
}

执行发现输出的日志前面由我们的 testlog 的前缀

[17:32:57 root@go testlog]#go run main.go 
testlog 2021/08/04 17:33:08 testlog

1.2.2 程序文件输出日志

也就是说我们获取到是由那个程序提供的日志信息

package main

import (
    "log"
)

func main() {
    log.SetFlags(log.Flags() | log.Lshortfile)
    log.Print("print")
}

并且还能获取到程序报日志的代码行数

[17:47:55 root@go testlog]#go run main.go 
2021/08/04 17:48:00 print
2021/08/04 17:48:00 main.go:9: print        # 第 9 行输出日志

1.2.3 日志输入到文件中

log.SetOutput() 传递一个 write 对象,然后会把调用的日志写到 write 对象中

func log.SetOutput(w io.Writer)
package main

import (
    "log"
    "os"
)

func main() {
    // 创建 test.log 文件
    logfile, _ := os.Create("test.log")

    // 调用 log.SetOutput(logfile) 把日志写入到 logfile 中
    log.SetOutput(logfile)
    log.SetFlags(log.Flags() | log.Lshortfile)
    log.Print("print")
}

执行后在当前目录有了一个 test.log 文件并且记录的就是我们输出的日志信息

1.3 在 web 服务器中添加日志

在下面案例中我们通过闭包实现,闭包一般用在一堆函数有公共特征的函数,也就说这些函数有参数和返回值都是一样的时候,想在这些函数中加一些功能我们就可以使用闭包这种形式,其实也是其他语言装饰器的一种形式

我们现在每个请求来了以后都会请求到 http 包里面,http 包然后再通过我们在请求时候的 URL 会找定义的处理器方法,但是我们会发现他的请求数据都是从 Request 中来的,响应的状态码理论上我们也能通过 ResponseWriter 去获取

该功能会将用户访问的时间,还有客户端 ip 以及访问端口,请求方式,请求路径和 user-agent 信息都记录到weblog.log

我们这个是在 webUser 项目中 log 模块,该函数通过闭包实现

package log

import (
    "fmt"
    "log"
    "net/http"
    "os"
)

// 通过闭包的手段
// 编写日志包装函数,等会在路由中调用该函数,因为我们的 GetUser AddUser DeleteUser Edit 等多个函数满足 http.HandlerFunc 方法
func LoggerWrapper(action http.HandlerFunc) http.HandlerFunc {
    return func(rw http.ResponseWriter, r *http.Request) {
        action(rw, r)

        // 判断日志文件是否存在
        logFile := "weblog.log"
        file, err := os.OpenFile(logFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
        if err != nil {
            fmt.Println(err)
            return
        }

        // 写入日志文件
        log.SetOutput(file)
        log.SetFlags(log.Flags() | log.Lshortfile)
        log.Printf(`[%s] %s %s %s`, r.RemoteAddr, r.Method, r.URL.String(), r.Header.Get("User-Agent"))
    }
}

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇