/
transaction_logger.go
138 lines (114 loc) · 3.43 KB
/
transaction_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
130
131
132
133
134
135
136
137
138
// nolint: unused
package gocb
import (
"fmt"
"log"
"sync"
"time"
"github.com/couchbase/gocbcore/v10"
)
type loggableDocKey struct {
bucket string
scope string
collection string
id string
}
func newLoggableDocKey(bucket, scope, collection string, id string) loggableDocKey {
return loggableDocKey{
bucket: bucket,
scope: scope,
collection: collection,
id: id,
}
}
func (rdi loggableDocKey) String() string {
scope := rdi.scope
if scope == "" {
scope = "_default"
}
collection := rdi.collection
if collection == "" {
collection = "_default"
}
return redactUserDataString(rdi.bucket + "." + scope + "." + collection + "." + rdi.id)
}
// TransactionLogger is the logger used for logging in transactions.
type TransactionLogger interface {
Logs() []TransactionLogItem
}
// TransactionLogItem represents an entry in the transaction in memory logging.
type TransactionLogItem struct {
Level LogLevel
args []interface{}
txnID string
attemptID string
timestamp time.Time
fmt string
}
func (item TransactionLogItem) String() string {
return fmt.Sprintf("%s %s/%s %s", item.timestamp.AppendFormat([]byte{}, "15:04:05.000"), item.txnID, item.attemptID, fmt.Sprintf(item.fmt, item.args...))
}
// transactionLogger log to memory, also logging WARN and ERROR logs to the SDK logger.
type transactionLogger struct {
lock sync.Mutex
items []TransactionLogItem
logDirectlyBelowLevel gocbcore.LogLevel
txnID string
}
func newTransactionLogger() *transactionLogger {
return &transactionLogger{
logDirectlyBelowLevel: gocbcore.LogInfo,
items: make([]TransactionLogItem, 0, 256),
}
}
func (tl *transactionLogger) setTxnID(txnID string) {
tl.txnID = txnID[:5]
}
func (tl *transactionLogger) Logs() []TransactionLogItem {
tl.lock.Lock()
logs := make([]TransactionLogItem, len(tl.items))
copy(logs, tl.items)
tl.lock.Unlock()
return logs
}
func (tl *transactionLogger) Log(level gocbcore.LogLevel, offset int, txnID, attemptID, fmt string, args ...interface{}) error {
item := TransactionLogItem{
Level: LogLevel(level),
args: args,
txnID: txnID,
attemptID: attemptID,
timestamp: time.Now(),
fmt: fmt,
}
tl.lock.Lock()
tl.items = append(tl.items, item)
tl.lock.Unlock()
if level <= gocbcore.LogWarn {
logExf(LogLevel(level), offset, txnID+"/"+attemptID+" "+fmt, args...)
}
return nil
}
func (tl *transactionLogger) logExf(attemptID string, level gocbcore.LogLevel, fmt string, args ...interface{}) {
if attemptID != "" {
attemptID = attemptID[:5]
}
err := tl.Log(level, 1, tl.txnID, attemptID, fmt, args...)
if err != nil {
log.Printf("Transaction logger error occurred (%s)\n", err)
}
}
func (tl *transactionLogger) logDebugf(attemptID, format string, v ...interface{}) {
tl.logExf(attemptID, gocbcore.LogDebug, format, v...)
}
func (tl *transactionLogger) logSchedf(attemptID, format string, v ...interface{}) {
tl.logExf(attemptID, gocbcore.LogSched, format, v...)
}
func (tl *transactionLogger) logWarnf(attemptID, format string, v ...interface{}) {
tl.logExf(attemptID, gocbcore.LogWarn, format, v...)
}
func (tl *transactionLogger) logErrorf(attemptID, format string, v ...interface{}) {
tl.logExf(attemptID, gocbcore.LogError, format, v...)
}
func (tl *transactionLogger) logInfof(attemptID, format string, v ...interface{}) {
tl.logExf(attemptID, gocbcore.LogInfo, format, v...)
}