gomobile: Hook logrus日志输出至android logcat

实际开发过程中,很多项目使用的日志输出是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