forked from r3-team/r3
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlog.go
184 lines (151 loc) · 3.78 KB
/
log.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
package log
import (
"fmt"
"r3/db"
"r3/tools"
"r3/types"
"sync"
"github.com/jackc/pgtype"
)
var (
access_mx = sync.Mutex{}
// log outputs
outputCli bool
// log levels
contextLevel = map[string]int{
"application": 1,
"backup": 1,
"cache": 1,
"csv": 1,
"mail": 1,
"ldap": 1,
"scheduler": 1,
"server": 1,
"transfer": 1,
}
)
func Get(dateFrom pgtype.Int8, dateTo pgtype.Int8, limit int, offset int,
context string, byString string) ([]types.Log, int, error) {
logs := make([]types.Log, 0)
total := 0
var qb tools.QueryBuilder
qb.UseDollarSigns()
qb.AddList("SELECT", []string{"l.level", "l.context", "l.message", "l.date_milli", "m.name"})
qb.Set("FROM", "instance.log AS l")
qb.Add("JOIN", "LEFT JOIN app.module AS m ON m.id = l.module_id")
if context != "" {
qb.Add("WHERE", `l.context::TEXT = {CONTEXT}`)
qb.AddPara("{CONTEXT}", context)
}
if byString != "" {
qb.Add("WHERE", `(
l.message ILIKE {NAME} OR
m.name ILIKE {NAME}
)`)
qb.AddPara("{NAME}", fmt.Sprintf("%%%s%%", byString))
}
if dateFrom.Status == pgtype.Present {
qb.Add("WHERE", "l.date_milli >= {DATEFROM}")
qb.AddPara("{DATEFROM}", dateFrom.Int*1000)
}
if dateTo.Status == pgtype.Present {
qb.Add("WHERE", "l.date_milli <= {DATETO}")
qb.AddPara("{DATETO}", dateTo.Int*1000)
}
qb.Add("ORDER", "l.date_milli DESC")
qb.Set("OFFSET", offset)
qb.Set("LIMIT", limit)
query, err := qb.GetQuery()
if err != nil {
return nil, 0, err
}
rows, err := db.Pool.Query(db.Ctx, query, qb.GetParaValues()...)
if err != nil {
return nil, 0, err
}
for rows.Next() {
var l types.Log
var dateMilli int64
if err := rows.Scan(&l.Level, &l.Context, &l.Message, &dateMilli, &l.ModuleName); err != nil {
return nil, 0, err
}
l.Date = int64(dateMilli / 1000)
logs = append(logs, l)
}
rows.Close()
// get total count
qb.UseDollarSigns()
qb.Reset("SELECT")
qb.Reset("ORDER")
qb.Reset("LIMIT")
qb.Reset("OFFSET")
qb.Add("SELECT", "COUNT(*)")
query, err = qb.GetQuery()
if err != nil {
return nil, 0, err
}
if err := db.Pool.QueryRow(db.Ctx, query, qb.GetParaValues()...).Scan(&total); err != nil {
return nil, 0, err
}
return logs, total, nil
}
func SetOutputCli(state bool) {
access_mx.Lock()
defer access_mx.Unlock()
outputCli = state
}
func SetLogLevel(context string, level int) {
access_mx.Lock()
defer access_mx.Unlock()
if _, exists := contextLevel[context]; !exists {
return
}
contextLevel[context] = level
}
func Info(context string, message string) {
write(3, context, message, nil)
}
func Warning(context string, message string, err error) {
write(2, context, message, err)
}
func Error(context string, message string, err error) {
write(1, context, message, err)
}
func write(level int, context string, message string, err error) {
levelActive, exists := contextLevel[context]
if !exists {
return
}
if level > levelActive {
return
}
// append error message, if available
if err != nil {
if message != "" {
message = fmt.Sprintf("%s, %s", message, err.Error())
} else {
message = err.Error()
}
}
// log to CLI if available
if outputCli {
fmt.Printf("%s %s %s\n", tools.GetTimeSql(), context, message)
}
// log to database if available
if db.Pool != nil {
// reduce message size stored in DB to at most 10k chars
// if access to larger messages is required, use CLI
if len(message) > 10000 {
message = message[:10000]
}
if _, err := db.Pool.Exec(db.Ctx, `
INSERT INTO instance.log (level, context, message, date_milli)
VALUES ($1,$2,$3,$4)
`, level, context, message, tools.GetTimeUnixMilli()); err != nil {
// if database logging fails, output error to CLI if available
if outputCli {
fmt.Printf("failed to write log to DB, error: %v\n", err)
}
}
}
}