/
exception.go
115 lines (89 loc) · 2.69 KB
/
exception.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
package lurch
import (
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson"
"time"
"log"
"hash/fnv"
"path"
)
type Exception struct {
Id bson.ObjectId "_id,omitempty"
UniqueId uint32
Name string
Message string
Status string
Comments []string
Instances []time.Time
Traces []*Trace `bson:"Trace",omitempty`
}
// Create a new Exception
// This will generate a UniqueId for the error
func generateUniqueId(name, message string, backtrace []string) (uniqueId uint32) {
id := path.Join(name, message)
// Add first line of backtrace if available
if len(backtrace) > 0 {
id = path.Join(id, backtrace[0])
}
hash := fnv.New32a()
hash.Write([]byte(id))
return hash.Sum32()
}
func NewException(name, message string, backtrace []string) (exception *Exception, err error) {
exception = &Exception{UniqueId: generateUniqueId(name, message, backtrace), Name: name, Message: message}
return
}
// Find an Exception by UniqueId from Mongo
func FindException(uniqueId uint32, db *mgo.Database) (exception *Exception, err error) {
exception = &Exception{}
err = db.C("exceptions").Find(bson.M{"uniqueid": uniqueId}).One(&exception)
if err != nil {
return nil, err
}
return
}
// Find an Exception by UniqueId from Mongo
func GetExceptions(db *mgo.Database) (exceptions []*Exception, err error) {
iter := db.C("exceptions").Find(nil).Iter()
err = iter.All(&exceptions)
if err != nil {
return
}
return
}
func (exception *Exception) Insert(db *mgo.Database) (err error) {
err = db.C("exceptions").Insert(exception)
if err != nil {
return err // That's a failure
}
return
}
// Upsert will insert a new Exception if nothing matching uniqueid exists
// Then, it will add to instances/traces of the Exception
func (exception *Exception) Upsert(trace *Trace, db *mgo.Database) (err error) {
log.Printf("Upserting: %#v\n", exception)
if err = db.C("exceptions").EnsureIndex(mgo.Index{Key: []string{"uniqueid"}, Unique: true}); err != nil {
return
}
// First, we'll try to insert
// Due to the unique constraint on UniqueID, this will fail if the record exists already
err = db.C("exceptions").Insert(&exception)
if err != nil && !mgo.IsDup(err) { // Swallow duplicate error
return
}
// Now, we're going to push the instance to mark when this happened
err = db.C("exceptions").Update(bson.M{"uniqueid": exception.UniqueId}, bson.M{
"$push": bson.M{"instances": time.Now() },
})
if err != nil {
return err
}
// Finally, we'll add the trace (for now, unlimited)
err = db.C("exceptions").Update(bson.M{"uniqueid": exception.UniqueId}, bson.M{
"$push": bson.M{"traces": &trace },
})
if err != nil {
return err
}
return
}