/
EntryService.groovy
193 lines (172 loc) · 5.14 KB
/
EntryService.groovy
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
185
186
187
188
189
190
191
192
193
package errbuddy
import grails.converters.JSON
import grails.transaction.Transactional
import org.codehaus.groovy.grails.web.mapping.LinkGenerator
import org.joda.time.DateTime
@Transactional
class EntryService {
def sendgridService
def entryGroupService
def elasticSearchService
LinkGenerator grailsLinkGenerator
def applicationService
def jesqueService
def grailsApplication
def resolve(Entry entry) {
entry.entryGroup.resolved = true
}
def findSimilar(Entry entry) {
if (!entry.entryGroup) {
log.fatal("$entry.id had no entry group. this should not happen!")
return
}
def musts = [
{ term("entryGroup.application.id": entry.entryGroup.appId) },
{ term("entryGroup.collector": false) }
]
if (entry.exception)
musts << { term("exception": entry.exception.toLowerCase()) }
if (entry.controllerName) {
musts << { term("controllerName": entry.controllerName.toLowerCase()) }
musts << { term("actionName": entry.actionName.toLowerCase()) }
}
def possibleMatches = elasticSearchService.search([indices: Entry, types: Entry, from: 0, size: 100], {
bool {
must = musts
should = [
{
"more_like_this"(
"fields": ["message"],
"like_text": entry.message.toLowerCase(),
"min_term_freq": 1,
"max_query_terms": 12,
"percent_terms_to_match": 0.9,
"min_doc_freq": 1,
"min_word_length": 3
)
}
]
minimum_number_should_match = 1
}
})
if (!possibleMatches.searchResults) {
return []
}
Entry.createCriteria().list {
inList('id', possibleMatches.searchResults.id)
entryGroup {
eq('app', entry.entryGroup.app)
}
projections {
groupProperty('entryGroup')
countDistinct('id')
}
}
}
void findSimilarGroup(Entry entry) {
def similarId = entryGroupService.similarest(entry)
EntryGroup entryGroup
if (similarId) {
entryGroup = EntryGroup.findByEntryGroupId(similarId)
if (!entryGroup) {
log.error("$similarId was not found as an entryGroup. this means we have some weird stuff in elasticsaerch")
return
}
} else {
entryGroup = new EntryGroup(app: entry.entryGroup.app).save() // save a new EntryGroup
}
entry.refindSimilar = false
entry.save(flush: true)
jesqueService.enqueue(PutIntoEntryGroupJob.queueName, PutIntoEntryGroupJob, [entryGroup.id, entry.id])
}
void addToEntryGroup(long entryGroupId, long entryId) {
Entry entry = Entry.lock(entryId)
EntryGroup entryGroup = EntryGroup.lock(entryGroupId)
if (!entry || !entryGroup) {
log.error("Entry (${entry?.id}) or EntryGroup (${entryGroup?.id} was not found")
} else {
entry.entryGroup = entryGroup
entryGroup.lastUpdated = DateTime.now()
entryGroup.resolved = false
entryGroup.latest = entry
entryGroup.entryCount = entryGroup.entryCount + 1
entryGroup.save()
entry.save()
}
}
/**
* Adds an entry to the collector group of the given Application and sets the refindSimilar flag
* @param app
* @param entry
*/
void addToCollector(App app, Entry entry) {
def collectorGroup = applicationService.getCollectorGroup(app)
if (!collectorGroup) {
log.warn("Application $app.id has no Collector Group!")
return
}
entry.entryGroup = collectorGroup
entry.refindSimilar = true
entry.save();
}
/**
* Creates an entry and adds it to the collector group of the given application
* @param appId
* @param data
*/
void addEntryToApplication(Serializable appId, String data) {
App app = App.get(appId)
if (!app) {
log.warn("Application $appId is not existing")
return
}
def collectorGroup = EntryGroup.findByAppAndCollector(app, true)
if (!collectorGroup) {
log.warn("Application $appId has no Collector Group!")
return
}
def json = JSON.parse(data)
json.time = json.time ? new DateTime(json.time as long) : DateTime.now()
Entry entry = new Entry(json)
entry.stackTrace = json.stacktrace
entry.actionName = json.action
entry.controllerName = json.controller
entry.serviceName = json.service
if (json.level) {
entry.entryLevel = Entry.EntryLevel.valueOf(json.level)
}
entry.entryGroup = collectorGroup
// to be sure our json is parsed correctly
if (!entry.validate()) {
log.error("could not validate entry: $entry.errors.allErrors")
} else {
entry.save(flush: true)
jesqueService.enqueue("generic", FindSimilarEntriesJob, [entry.id])
}
}
void delete(Serializable id, boolean doCheckLatest) {
Entry entry = Entry.get(id)
if (!entry) {
return // looks like this was done already
}
if (doCheckLatest) {
EntryGroup.findAllByLatest(entry).each { // this should really never be more then one, but we saw it happen so lets go for each ...
it.latest = Entry.findByEntryGroupAndIdNotEqual(it, id, [sort: 'id', order: 'desc'])
it.save()
}
}
entry.delete()
}
/**
* Enqueues a new FindSimilarEntriesJob for all Entries that are in a collector group, and have the refindSimilar flag
*
*/
void doRefindFromCollector() {
Entry.createCriteria().list {
inList('entryGroup', EntryGroup.findAllByCollector(true))
eq('refindSimilar', true)
}?.each { Entry entry ->
jesqueService.enqueue("generic", FindSimilarEntriesJob, [entry.id])
}
}
}