77
88package io.xh.hoist.monitor.provided
99
10+ import grails.gorm.transactions.ReadOnly
1011import grails.gorm.transactions.Transactional
1112import groovy.sql.Sql
1213import io.xh.hoist.BaseService
13- import io.xh.hoist.data.filter.Filter
1414import io.xh.hoist.monitor.Monitor
1515import io.xh.hoist.monitor.MonitorResult
1616import io.xh.hoist.util.Utils
17+ import io.xh.hoist.clienterror.ClientError
18+ import io.xh.hoist.track.TrackLog
1719
1820import static io.xh.hoist.monitor.MonitorStatus.FAIL
1921import static io.xh.hoist.monitor.MonitorStatus.INACTIVE
@@ -51,18 +53,14 @@ class DefaultMonitorDefinitionService extends BaseService {
5153 return
5254 }
5355
54- def aggregate = result. params . aggregate ?: ' avg'
55- if (! [' avg' , ' max' ]. contains(aggregate )) {
56- throw new RuntimeException (" Invalid aggregate parameter: ${ result.params. aggregate} " )
56+ def aggregate = result. getParam( ' aggregate' , ' avg' )
57+ if (! (aggregate in [' avg' , ' max' ])) {
58+ throw new RuntimeException (" Invalid aggregate parameter: $aggregate " )
5759 }
5860
59- def lookbackMinutes = result. params. lookbackMinutes
60- if (! lookbackMinutes) {
61- throw new RuntimeException (' No \" lookbackMinutes\" parameter provided' )
62- }
63-
64- def cutOffTime = currentTimeMillis() - lookbackMinutes * MINUTES
65- def snapshots = memoryMonitoringService. snapshots. findAll {it. key > cutOffTime}. values()
61+ def lookback = result. getRequiredParam(' lookbackMinutes' ) * MINUTES ,
62+ cutoffTime = currentTimeMillis() - lookback,
63+ snapshots = memoryMonitoringService. snapshots. findAll {it. key > cutoffTime}. values()
6664
6765 if (! snapshots) {
6866 result. metric = 0
@@ -74,50 +72,34 @@ class DefaultMonitorDefinitionService extends BaseService {
7472 : snapshots. max{it. usedPctMax}. usedPctMax
7573 }
7674
75+ @ReadOnly
76+ def xhClientErrorsMonitor (MonitorResult result ) {
77+ def lookback = result. getRequiredParam(' lookbackMinutes' ) * MINUTES ,
78+ cutoffDate = new Date (currentTimeMillis() - lookback)
79+
80+ result. metric = ClientError . countByDateCreatedGreaterThan(cutoffDate)
81+ }
82+
83+ @ReadOnly
7784 def xhLoadTimeMonitor (MonitorResult result ) {
7885 if (! trackLogAdminService. enabled) {
7986 result. status = INACTIVE
8087 return
8188 }
8289
83- def lookbackMinutes = result. params. lookbackMinutes
84- if (! lookbackMinutes) {
85- throw new RuntimeException (' No \" lookbackMinutes\" parameter provided.' )
86- }
87-
88- def cutOffTime = currentTimeMillis() - lookbackMinutes * MINUTES
89- def logs = trackLogAdminService. queryTrackLog(
90- Filter . parse([
91- filters : [
92- [
93- field : ' dateCreated' ,
94- op : ' >' ,
95- value : new Date (cutOffTime)
96- ],
97- [
98- field : ' elapsed' ,
99- op : ' !=' ,
100- value : null
101- ]
102- ],
103- op : " AND"
104- ])
105- )
106-
107- if (! logs) {
108- result. metric = 0
109- return
110- }
90+ def lookback = result. getRequiredParam(' lookbackMinutes' ) * MINUTES ,
91+ cutoffDate = new Date (currentTimeMillis() - lookback),
92+ logs = TrackLog . findAllByDateCreatedGreaterThanAndElapsedIsNotNull(cutoffDate)
11193
112- result. metric = logs. max{it. elapsed}. elapsed / SECONDS
94+ result. metric = logs ? logs . max{it. elapsed}. elapsed / SECONDS : 0
11395 }
11496
11597 def xhDbConnectionMonitor (MonitorResult result ) {
11698 def startTime = currentTimeMillis()
11799 Sql sql = new Sql (dataSource)
118100 try {
119101 // Support configurable table name for edge case where XH tables are in a custom schema.
120- def tableName = result. params . tableName ?: ' xh_monitor'
102+ def tableName = result. getParam( ' tableName' , ' xh_monitor' )
121103 sql. rows(" SELECT * FROM ${ Sql.expand(tableName)} WHERE code = 'xhDbConnectionMonitor'" )
122104 } finally {
123105 sql. close()
@@ -132,12 +114,9 @@ class DefaultMonitorDefinitionService extends BaseService {
132114 return
133115 }
134116
135- if (! result. params. queryUser) {
136- throw new RuntimeException (" No \" queryUser\" parameter provided." )
137- }
138-
139- def startTime = currentTimeMillis()
140- def user = ldapService. lookupUser(result. params. queryUser)
117+ def queryUser = result. getRequiredParam(' queryUser' ),
118+ user = ldapService. lookupUser(queryUser),
119+ startTime = currentTimeMillis()
141120
142121 if (! user) {
143122 result. message = " Failed to find expected user: ${ result.params.queryUser} "
@@ -177,6 +156,18 @@ class DefaultMonitorDefinitionService extends BaseService {
177156 + ' Set "aggregate" to "avg" to report average heap usage (default).\n '
178157 + ' Set "aggregate" to "max" to report the largest heap usage.'
179158 ],
159+ [
160+ code : ' xhClientErrorsMonitor' ,
161+ name : ' Client Errors (Last 30m)' ,
162+ metricType : ' Ceil' ,
163+ metricUnit : ' s' ,
164+ warnThreshold : 1 ,
165+ failThreshold : 10 ,
166+ active : true ,
167+ primaryOnly : true ,
168+ params : ' {\n\t "lookbackMinutes": 30\n }' ,
169+ notes : ' Reports the longest tracked event in the last {lookbackMinutes} minutes.'
170+ ],
180171 [
181172 code : ' xhLoadTimeMonitor' ,
182173 name : ' Max Load Time (Last 30m)' ,
0 commit comments