-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtrace.go
144 lines (119 loc) · 4.7 KB
/
trace.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
package mongotrace
import (
"context"
"github.com/google/uuid"
"github.com/nsf/jsondiff"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"time"
)
const (
OperationADD = "ADD"
OperationUPDATE = "UPDATE"
OperationDELETE = "DELETE"
)
// Trace is a representation of a action perform in database.
type Trace struct {
// Default infos
ID string `json:"_id" bson:"_id"`
CreatedAt time.Time `json:"CreatedAt" bson:"CreatedAt"`
// Collection is the collection where action is perform
Collection string `json:"Collection" bson:"Collection"`
/*Operation is the operation who want to perform on db
OperationADD for InsertOne
OperationUPDATE for UpdateOne
OperationDELETE for DeleteOne*/
Operation string `json:"Operation" bson:"Operation"`
/*DocumentBefore is the json representation of document before the operation is performs on database
Need when Operation is UPDATE or DELETE*/
DocumentBefore string `json:"DocumentBefore" bson:"DocumentBefore"`
/*DocumentAfter is the json representation of document after the operation is performs on database
Need when Operation is ADD or UPDATE*/
DocumentAfter string `json:"DocumentAfter" bson:"DocumentAfter"`
/*Difference is the html representation of difference between DocumentBefore and DocumentAfter.
For a good readable render, you must put this html inside a <pre> tags*/
Difference string `json:"Difference" bson:"Difference"`
}
//save Save the trace in the given traceCollection
func (trace *Trace) save(database *mongo.Database, traceCollection string) error {
trace.ID = uuid.Must(uuid.NewRandom()).String()
trace.CreatedAt = time.Now().UTC()
_, err := database.Collection(traceCollection).InsertOne(context.TODO(), trace)
return err
}
// TraceOperationAdd set the DocumentAfter and save the trace in the given traceCollection
func TraceOperationAdd(database *mongo.Database, traceCollection string, collection string, documentAfter interface{}) (*Trace, error) {
trace := Trace{
Collection: collection,
Operation: OperationADD,
DocumentAfter: StructToJson(documentAfter),
}
err := trace.save(database, traceCollection)
if err != nil {
return nil, err
}
return &trace, nil
}
// TraceOperationDelete set the DocumentBefore and save the trace in the given traceCollection
func TraceOperationDelete(database *mongo.Database, traceCollection string, collection string, documentBefore interface{}) (*Trace, error) {
trace := Trace{
Collection: collection,
Operation: OperationDELETE,
DocumentBefore: StructToJson(documentBefore),
}
err := trace.save(database, traceCollection)
if err != nil {
return nil, err
}
return &trace, nil
}
// TraceOperationUpdateWithFilter set the DocumentBefore and DocumentAfter(searching by the filter params) get the difference between the two documents and save the trace in the given traceCollection
func TraceOperationUpdateWithFilter(database *mongo.Database, traceCollection string, collection string, documentBefore interface{}, filter interface{}) (*Trace, error) {
trace := Trace{
Collection: collection,
Operation: OperationUPDATE,
DocumentBefore: StructToJson(documentBefore),
}
err := trace.setDocumentAfterBySearch(database, filter)
if err != nil {
return nil, err
}
trace.getDifference()
err = trace.save(database, traceCollection)
if err != nil {
return nil, err
}
return &trace, nil
}
// TraceOperationUpdate set the DocumentBefore and DocumentAfter get the difference between the two documents and save the trace in the given traceCollection
func TraceOperationUpdate(database *mongo.Database, traceCollection string, collection string, documentBefore interface{}, documentAfter interface{}) (*Trace, error) {
trace := Trace{
Collection: collection,
Operation: OperationUPDATE,
DocumentBefore: StructToJson(documentBefore),
DocumentAfter: StructToJson(documentAfter),
}
trace.getDifference()
err := trace.save(database, traceCollection)
if err != nil {
return nil, err
}
return &trace, nil
}
// setDocumentAfterBySearch search a document in the Collection parsing it to json and set it as DocumentAfter
func (trace *Trace) setDocumentAfterBySearch(database *mongo.Database, filter interface{}) error {
var document bson.M
err := database.Collection(trace.Collection).FindOne(context.TODO(), filter).Decode(&document)
if err != nil {
return err
}
trace.DocumentAfter = StructToJson(document)
return nil
}
// getDifference sort the html representation of difference between DocumentBefore an DocumentAfter
func (trace *Trace) getDifference() {
opts := jsondiff.DefaultHTMLOptions()
opts.PrintTypes = false
_, desc := jsondiff.Compare([]byte(trace.DocumentBefore), []byte(trace.DocumentAfter), &opts)
trace.Difference = desc
}