-
Notifications
You must be signed in to change notification settings - Fork 0
/
glib_logger.go
129 lines (114 loc) · 3.65 KB
/
glib_logger.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
* Copyright © 2023 omegarogue
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package gliblogger
import (
stdlog "log"
"os"
"strings"
"github.com/diamondburned/gotk4/pkg/glib/v2"
"github.com/rs/zerolog"
)
const (
CodeFileFieldName = "file"
CodeFuncFieldName = "func"
CodeLineFieldName = "line"
DomainFieldName = "domain"
GlibLevelFieldName = "glib_level"
)
func logLevelGlibZerolog(lvl glib.LogLevelFlags) zerolog.Level {
switch lvl & 0b11111100 {
case glib.LogLevelError:
return zerolog.ErrorLevel
case glib.LogLevelCritical:
return zerolog.FatalLevel
case glib.LogLevelWarning:
return zerolog.WarnLevel
case glib.LogLevelMessage:
return zerolog.InfoLevel
case glib.LogLevelDebug:
return zerolog.DebugLevel
}
return zerolog.NoLevel
}
// LoggerHandler creates a new LogWriterFunc that LogUseLogger uses. For
// more information, see LogUseLogger's documentation.
//
//goland:noinspection SpellCheckingInspection
//nolint:funlen,gocognit // I don't see a way to simplify this
func LoggerHandler(l *zerolog.Logger) glib.LogWriterFunc {
// Treat Lshortfile and Llongfile the same, because we don't have
// the full path in codeFile anyway.
Lfile := stdlog.Flags()&(stdlog.Lshortfile|stdlog.Llongfile) != 0
// Support $G_MESSAGES_DEBUG.
debugDomains := make(map[string]struct{})
for _, debugDomain := range strings.Fields(os.Getenv("G_MESSAGES_DEBUG")) {
debugDomains[debugDomain] = struct{}{}
}
// Special case: G_MESSAGES_DEBUG=all.
_, debugAll := debugDomains["all"]
return func(lvl glib.LogLevelFlags, fields []glib.LogField) glib.LogWriterOutput {
var codeFile, codeLine, codeFunc string
domain := "GLib (no domain)"
event := l.WithLevel(logLevelGlibZerolog(lvl))
for _, field := range fields {
if !Lfile {
switch field.Key() {
case "MESSAGE":
event.Str(zerolog.MessageFieldName, field.Value())
case "GLIB_DOMAIN":
event.Str(DomainFieldName, field.Value())
domain = field.Value()
}
// Skip setting code* if we don't have to.
continue
}
switch field.Key() {
case "MESSAGE":
event.Str(zerolog.MessageFieldName, field.Value())
case "CODE_FILE":
codeFile = field.Value()
case "CODE_LINE":
codeLine = field.Value()
case "CODE_FUNC":
codeFunc = field.Value()
case "GLIB_DOMAIN":
event.Str(DomainFieldName, field.Value())
domain = field.Value()
}
}
if !debugAll && (lvl&glib.LogLevelDebug != 0) && domain != "" {
if _, ok := debugDomains[domain]; !ok {
return glib.LogWriterHandled
}
}
// Minor issue: this works badly if consts are OR'd together.
// Probably never.
level := strings.TrimPrefix(lvl.String(), "Level")
event.Str(GlibLevelFieldName, level)
if !Lfile || (codeFile == "" && codeLine == "") {
event.Send()
return glib.LogWriterHandled
}
if codeFunc == "" {
event.Str(CodeLineFieldName, codeLine).Str(CodeFileFieldName, codeFile).Send()
return glib.LogWriterHandled
}
event.Str(CodeFuncFieldName, codeFunc).Send()
return glib.LogWriterHandled
}
}