实际开发过程中,很多项目使用的日志输出是logrus,为了保持统一,同时又能把日志输出到Android Logcat,同时还带上Android的日志级别。

默认的log.Println,也能输出,但默认的Tag是GoLog,日志级别是info,显然不能满足要求。

定义文件: log_android.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package g

/*
#cgo LDFLAGS: -landroid -llog

#include <android/log.h>
#include <string.h>
#include <stdlib.h>
*/
import "C"
import (
	"unsafe"

	"github.com/Sirupsen/logrus"
)

var levels = []logrus.Level{
	logrus.PanicLevel,
	logrus.FatalLevel,
	logrus.ErrorLevel,
	logrus.WarnLevel,
	logrus.InfoLevel,
	logrus.DebugLevel,
}

type androidHook struct {
	tag *C.char
	fmt logrus.Formatter
}

type androidFormatter struct{}

func (f *androidFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	return []byte(entry.Message), nil
}

func (hook *androidHook) Levels() []logrus.Level {
	return levels
}

func (hook *androidHook) Fire(e *logrus.Entry) error {
	var priority C.int

	formatted, err := hook.fmt.Format(e)
	if err != nil {
		return err
	}
	str := C.CString(string(formatted))

	switch e.Level {
	case logrus.PanicLevel:
		priority = C.ANDROID_LOG_FATAL
	case logrus.FatalLevel:
		priority = C.ANDROID_LOG_FATAL
	case logrus.ErrorLevel:
		priority = C.ANDROID_LOG_ERROR
	case logrus.WarnLevel:
		priority = C.ANDROID_LOG_WARN
	case logrus.InfoLevel:
		priority = C.ANDROID_LOG_INFO
	case logrus.DebugLevel:
		priority = C.ANDROID_LOG_DEBUG
	}
	C.__android_log_write(priority, hook.tag, str)
	C.free(unsafe.Pointer(str))
	return nil
}

// create a logrus Hook that forward entries to logcat
func AndroidLogHook(tag string) logrus.Hook {
	return &androidHook{
		tag: C.CString(tag),
		fmt: &androidFormatter{},
	}
}

使用方法:

1
logrus.AddHook(g.AndroidLogHook())

然后就可以开心地使用logrus.Debugf等接口了,很方便,不是吗。

参考链接:

  1. logrus-android