forked from go-gorm/opentracing
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathopentracing_helper.go
122 lines (102 loc) · 3.21 KB
/
opentracing_helper.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
package gormopentracing
import (
"context"
"unsafe"
jsoniter "github.com/json-iterator/go"
"github.com/opentracing/opentracing-go"
opentracinglog "github.com/opentracing/opentracing-go/log"
"gorm.io/gorm"
)
const (
_prefix = "gorm.opentracing"
_errorTagKey = "error"
)
var (
// span.Tag keys
_tableTagKey = keyWithPrefix("table")
// span.Log keys
//_errorLogKey = keyWithPrefix("error")
_resultLogKey = keyWithPrefix("result")
_sqlLogKey = keyWithPrefix("sql")
_rowsAffectedLogKey = keyWithPrefix("rowsAffected")
)
func keyWithPrefix(key string) string {
return _prefix + "." + key
}
var (
opentracingSpanKey = "opentracing:span"
json = jsoniter.ConfigCompatibleWithStandardLibrary
)
func (p opentracingPlugin) injectBefore(db *gorm.DB, op operationName) {
// make sure context could be used
if db == nil {
return
}
if db.Statement == nil || db.Statement.Context == nil {
db.Logger.Error(context.TODO(), "could not inject sp from nil Statement.Context or nil Statement")
return
}
sp, _ := opentracing.StartSpanFromContextWithTracer(db.Statement.Context, p.opt.tracer, op.String())
db.InstanceSet(opentracingSpanKey, sp)
}
func (p opentracingPlugin) extractAfter(db *gorm.DB) {
// make sure context could be used
if db == nil {
return
}
if db.Statement == nil || db.Statement.Context == nil {
db.Logger.Error(context.TODO(), "could not extract sp from nil Statement.Context or nil Statement")
return
}
// extract sp from db context
//sp := opentracing.SpanFromContext(db.Statement.Context)
v, ok := db.InstanceGet(opentracingSpanKey)
if !ok || v == nil {
return
}
sp, ok := v.(opentracing.Span)
if !ok || sp == nil {
return
}
defer sp.Finish()
// tag and log fields we want.
tag(sp, db)
log(sp, db, p.opt.logResult, p.opt.logSqlParameters)
}
// tag called after operation
func tag(sp opentracing.Span, db *gorm.DB) {
if err := db.Error; err != nil {
sp.SetTag(_errorTagKey, true)
}
sp.SetTag(_tableTagKey, db.Statement.Table)
}
// log called after operation
func log(sp opentracing.Span, db *gorm.DB, verbose bool, logSqlVariables bool) {
fields := make([]opentracinglog.Field, 0, 4)
fields = appendSql(fields, db, logSqlVariables)
fields = append(fields, opentracinglog.Object(_rowsAffectedLogKey, db.Statement.RowsAffected))
// log error
if err := db.Error; err != nil {
fields = append(fields, opentracinglog.Error(err))
}
if verbose && db.Statement.Dest != nil {
// DONE(@yeqown) fill result fields into span log
// FIXED(@yeqown) db.Statement.Dest still be metatable now ?
v, err := json.Marshal(db.Statement.Dest)
if err == nil {
fields = append(fields, opentracinglog.String(_resultLogKey, *(*string)(unsafe.Pointer(&v))))
} else {
db.Logger.Error(context.Background(), "could not marshal db.Statement.Dest: %v", err)
}
}
sp.LogFields(fields...)
}
func appendSql(fields []opentracinglog.Field, db *gorm.DB, logSqlVariables bool) []opentracinglog.Field {
if logSqlVariables {
fields = append(fields, opentracinglog.String(_sqlLogKey,
db.Dialector.Explain(db.Statement.SQL.String(), db.Statement.Vars...)))
} else {
fields = append(fields, opentracinglog.String(_sqlLogKey, db.Statement.SQL.String()))
}
return fields
}