Files
build-web-application-with-…/12.1.md

7.6 KiB
Raw Blame History

12.1 应用日志

我们期望开发的Web应用程序能够把整个程序运行过程中出现的各种事件一一记录下来Go语言中提供了一个简易的log包我们使用该包可以方便的实现日志记录的功能这些日志都是基本的给予fmt包的打印再结合panic之类的一些函数来处理我们一般的打印抛出错误之类的。如果我们想把我们的应用日志保存到文件然后又能够结合日志实现很多复杂的功能编写过Java或者C++的读者应该都使用过log4j和log4cpp之类的日志工具Go目前标准包就如前面介绍的只是包含了一个简单的包但是目前第三方开发的一个日志系统实现了很强大的日志功能https://github.com/cihub/seelog,接下来我们介绍如何该日志系统来实现我们应用的日志功能。

seelog介绍

seelog是用Go语言实现的一个日志系统他提供了一些简单的函数来实现复杂的日志分配、过滤和格式化。他主要有如下特性

  • XML配置文件可以不用重新编译程序而动态的加载配置信息

  • 能够动态改变配置而不需要重启应用

  • 能够同时把日志输出到多种流中

  • 支持不同的日志输出

    • 命令行输出
    • 文件输出
    • 缓存输出
    • 支持log rotate
    • SMTP邮件

上面介绍的只是部分特性其他seelog是一个特别强大的日志处理系统详细的可以参考官方网站的wiki。接下来介绍一下如何在项目中使用

首先安装seelog

go get -u github.com/cihub/seelog

然后我们来看一个简单的例子:

package main

import log "github.com/cihub/seelog"

func main() {
    defer log.Flush()
    log.Info("Hello from Seelog!")
}

我们编译之后可以正常的输出日志了说明seelog日志系统已经成功安装并且可以正常运行了。

基于seelog的自定义日志处理

seelog支持让我们给予seelog自定义日志处理下面这个是我目前基于seelog日志系统做的自定义的日志处理包

package logs

import (
	"errors"
	"fmt"
	seelog "github.com/cihub/seelog"
	"io"
)

var Logger seelog.LoggerInterface

func loadAppConfig() {
	appConfig := `
<seelog minlevel="warn">
    <outputs formatid="common">
        <rollingfile type="size" filename="/data/logs/roll.log" maxsize="100000" maxrolls="5"/>
		<filter levels="critical">
            <file path="/data/logs/critical.log" formatid="critical"/>
            <smtp formatid="criticalemail" senderaddress="astaxie@gmail.com" sendername="ShortUrl API" hostname="smtp.gmail.com" hostport="587" username="mailusername" password="mailpassword">
                <recipient address="xiemengjun@gmail.com"/>
            </smtp>
        </filter>
    </outputs>
    <formats>
        <format id="common" format="%Date/%Time [%LEV] %Msg%n" />
	    <format id="critical" format="%File %FullPath %Func %Msg%n" />
	    <format id="criticalemail" format="Critical error on our server!\n    %Time %Date %RelFile %Func %Msg \nSent by Seelog"/>
    </formats>
</seelog>
`
	logger, err := seelog.LoggerFromConfigAsBytes([]byte(appConfig))
	if err != nil {
		fmt.Println(err)
		return
	}
	UseLogger(logger)
}

func init() {
	DisableLog()
	loadAppConfig()
}

// DisableLog disables all library log output
func DisableLog() {
	Logger = seelog.Disabled
}

// UseLogger uses a specified seelog.LoggerInterface to output library log.
// Use this func if you are using Seelog logging system in your app.
func UseLogger(newLogger seelog.LoggerInterface) {
	Logger = newLogger
}

上面主要实现了三个函数,

  • DisableLog

    初始化全局变量Logger为目前seelog的禁用状态主要防止Logger初始化多次

  • loadAppConfig

    根据配置文件初始化seelog的配置信息这里我们把配置文件通过字符串读取设置好了当然也可以通过读取XML文件。里面的配置说明如下

    • seelog

      minlevel可有可无有的话设置最小级别的日志级别需要记录还有maxlevel也是类似的原理

    • outputs

      输出信息到那些地方这里分成了两个数据一个记录到log rotate文件里面。第二设置了一个filter如果这个错误级别是critical那么发送邮件。

    • formats

      定义了各种日志的格式

  • UseLogger

    设置当前的日志器为相应的日志处理

上面我们定义了一个自定义的日志处理包,下面就是使用示例:

package main

import (
	"net/http"
	"project/logs"
	"project/configs"
	"project/routes"
)

func main() {
	addr, _ := configs.MainConfig.String("server", "addr")
	logs.Logger.Info("Start server at:%v", addr)
	err := http.ListenAndServe(addr, routes.NewMux())
	logs.Logger.Critical("Server err:%v", err)
}

发生错误发送邮件

上面的例子解释了如何设置发送邮件我们通过如下的smtp配置用来发送邮件

<smtp formatid="criticalemail" senderaddress="astaxie@gmail.com" sendername="ShortUrl API" hostname="smtp.gmail.com" hostport="587" username="mailusername" password="mailpassword">
	<recipient address="xiemengjun@gmail.com"/>
</smtp>

邮件的格式通过criticalemail配置然后通过其他的配置发送邮件服务器的配置通过recipient配置接收邮件的用户如果有多个用户可以再添加一行。

要测试这个代码是否正常工作,可以在代码中增加类似下面的一个假消息。不过记住过后要把它删除,否则上线之后就会收到很多垃圾邮件。

logs.Logger.Critical("test Critical message")

现在只要我们的应用在线上记录一个Critical的信息你的邮箱就会收到一个Email这样一旦线上的系统出现问题你就能立马通过邮件获知就能及时的进行处理。

使用应用日志

对于应用日志,每个人的应用场景可能会各不相同,有些人利用应用日志来做数据分析,有些人利用应用日志来做性能分析,有些人来做用户行为分析,还有些就是纯粹的记录方便应用出现问题的时候可以查找问题。

举一个例子,我们需要跟踪用户尝试登陆系统的操作。这里会把成功与不成功的尝试都记录下来。记录成功的使用"Info"日志级别,而不成功的使用"warn"级别。如果想查找所有不成功的登陆我们可以利用linux的grep之类的命令工具如下

# cat /data/logs/roll.log | grep "failed login"
2012-12-11 11:12:00 WARN : failed login attempt from 11.22.33.44 username password

通过这种方式我们就可以很方便的查找相应的信息这样有利于我们针对应用日志做一些统计和分析。另外我们还需要考虑日志的大小对于一个高流量的Web应用来说日志的增长是相当可怕的所以我们在seelog的配置文件里面设置了logrotate这样就能保证日志文件不会因为不断变大而导致我们的磁盘空间不够引起问题。

小结

通过上面对seelog系统的介绍以及如何开发基于seelog的日志处理包我们现在可以很轻松的就搭建起来一个功能强大的日志处理系统日志处理系统对于我们的数据分析提供可靠的数据源通过分析可以进一步优化我们的系统而且一旦应用出现问题也方便我们查找问题而同时seelog也提供了调试输出的功能这样对于开发阶段来说就可以很方便的来调试各种数据上线的时候通过设置minlevel可以很方便的屏蔽这些调试级别的信息。