@@ -50,6 +50,8 @@ object PPLMonitorRunner : MonitorV2Runner {
5050
5151 private const val PPL_SQL_QUERY_FIELD = " query" // name of PPL query field when passing into PPL/SQL Execute API call
5252
53+ private const val TIMESTAMP_FIELD = " timestamp" // TODO: this should be deleted once PPL plugin side time keywords are introduced
54+
5355 override suspend fun runMonitorV2 (
5456 monitorV2 : MonitorV2 ,
5557 monitorCtx : MonitorRunnerExecutionContext , // MonitorV2 reads from same context as Monitor
@@ -141,7 +143,6 @@ object PPLMonitorRunner : MonitorV2Runner {
141143 appendCustomCondition(timeFilteredQuery, pplTrigger.customCondition!! )
142144 }
143145
144- // TODO: does this handle pagination? does it need to?
145146 // execute the PPL query
146147 val queryResponseJson = executePplQuery(queryToExecute, nodeClient)
147148 logger.info(" query execution results for trigger ${pplTrigger.name} : $queryResponseJson " )
@@ -229,7 +230,7 @@ object PPLMonitorRunner : MonitorV2Runner {
229230 }
230231 }
231232 } catch (e: Exception ) {
232- logger.error(" failed to run PPL Trigger ${pplTrigger.name} for PPL Monitor ${pplMonitor.name} " , e)
233+ logger.error(" failed to run PPL Trigger ${pplTrigger.name} from PPL Monitor ${pplMonitor.name} " , e)
233234
234235 // generate an alert with an error message
235236 monitorCtx.retryPolicy?.let {
@@ -283,11 +284,11 @@ object PPLMonitorRunner : MonitorV2Runner {
283284 // inject time filter into PPL query to only query for data within the (periodStart, periodEnd) interval
284285 // TODO: if query contains "_time", "span", "earliest", "latest", skip adding filter
285286 // pending https://github.com/opensearch-project/sql/issues/3969
286- // for now assume "_time" field is always present in customer data
287+ // for now assume TIMESTAMP_FIELD field is always present in customer data
287288
288289 // if the raw query contained any time check whatsoever, skip adding a time filter internally
289290 // and return query as is, customer's in-query time checks instantly and automatically overrides
290- if (query.contains(" _time " )) { // TODO: replace with PPL time keyword checks after that's GA
291+ if (query.contains(TIMESTAMP_FIELD )) { // TODO: replace with PPL time keyword checks after that's GA
291292 return query
292293 }
293294
@@ -302,8 +303,9 @@ object PPLMonitorRunner : MonitorV2Runner {
302303 val periodStartPplTimestamp = formatter.format(updatedPeriodStart)
303304 val periodEndPplTimeStamp = formatter.format(periodEnd)
304305
305- val timeFilterReplace = " | where _time > TIMESTAMP('$periodStartPplTimestamp ') and _time < TIMESTAMP('$periodEndPplTimeStamp ') |"
306- val timeFilterAppend = " | where _time > TIMESTAMP('$periodStartPplTimestamp ') and _time < TIMESTAMP('$periodEndPplTimeStamp ')"
306+ val timeFilterAppend = " | where $TIMESTAMP_FIELD > TIMESTAMP('$periodStartPplTimestamp ') and " +
307+ " $TIMESTAMP_FIELD < TIMESTAMP('$periodEndPplTimeStamp ')"
308+ val timeFilterReplace = " $timeFilterAppend |"
307309
308310 val timeFilteredQuery: String = if (query.contains(" |" )) {
309311 // if Monitor query contains piped statements, inject the time filter
@@ -319,33 +321,6 @@ object PPLMonitorRunner : MonitorV2Runner {
319321 return timeFilteredQuery
320322 }
321323
322- // appends user-defined custom trigger condition to PPL query, only for custom condition Triggers
323- private fun appendCustomCondition (query : String , customCondition : String ): String {
324- return " $query | $customCondition "
325- }
326-
327- // returns PPL query response as parsable JSONObject
328- private suspend fun executePplQuery (query : String , client : NodeClient ): JSONObject {
329- // call PPL plugin to execute time filtered query
330- val transportPplQueryRequest = TransportPPLQueryRequest (
331- query,
332- JSONObject (mapOf (PPL_SQL_QUERY_FIELD to query)),
333- null // null path falls back to a default path internal to SQL/PPL Plugin
334- )
335-
336- val transportPplQueryResponse = PPLPluginInterface .suspendUntil {
337- this .executeQuery(
338- client,
339- transportPplQueryRequest,
340- it
341- )
342- }
343-
344- val queryResponseJson = JSONObject (transportPplQueryResponse.result)
345-
346- return queryResponseJson
347- }
348-
349324 private fun evaluateNumResultsTrigger (numResults : Long , numResultsCondition : NumResultsCondition , numResultsValue : Long ): Boolean {
350325 return when (numResultsCondition) {
351326 NumResultsCondition .GREATER_THAN -> numResults > numResultsValue
@@ -402,33 +377,8 @@ object PPLMonitorRunner : MonitorV2Runner {
402377 // find the name of the eval result variable defined in custom condition
403378 val evalResultVarName = findEvalResultVar(pplTrigger.customCondition!! )
404379
405- // find the eval statement result variable in the PPL query response schema
406- val schemaList = customConditionQueryResponse.getJSONArray(" schema" )
407- var evalResultVarIdx = - 1
408- for (i in 0 until schemaList.length()) {
409- val schemaObj = schemaList.getJSONObject(i)
410- val columnName = schemaObj.getString(" name" )
411-
412- if (columnName == evalResultVarName) {
413- if (schemaObj.getString(" type" ) != " boolean" ) {
414- throw IllegalStateException (
415- " parsing results of PPL query with custom condition failed," +
416- " eval statement variable was not type boolean, but instead type: ${schemaObj.getString(" type" )} "
417- )
418- }
419-
420- evalResultVarIdx = i
421- break
422- }
423- }
424-
425- // eval statement result variable should always be found
426- if (evalResultVarIdx == - 1 ) {
427- throw IllegalStateException (
428- " expected to find eval statement results variable \" $evalResultVarName \" in results " +
429- " of PPL query with custom condition, but did not."
430- )
431- }
380+ // find the index eval statement result variable in the PPL query response schema
381+ val evalResultVarIdx = findEvalResultVarIdxInSchema(customConditionQueryResponse, evalResultVarName)
432382
433383 val dataRowList = customConditionQueryResponse.getJSONArray(" datarows" )
434384 for (i in 0 until dataRowList.length()) {
@@ -448,20 +398,6 @@ object PPLMonitorRunner : MonitorV2Runner {
448398 return relevantQueryResultRows
449399 }
450400
451- // TODO: is there maybe some PPL plugin util function we can use to replace this?
452- // searches a given custom condition eval statement for the name of the result
453- // variable and returns it
454- private fun findEvalResultVar (customCondition : String ): String {
455- // the PPL keyword "eval", followed by a whitespace must be present, otherwise a syntax error from PPL plugin would've
456- // been thrown when executing the query (without the whitespace, the query would've had something like "evalresult",
457- // which is invalid PPL
458- val startOfEvalStatement = " eval "
459-
460- val startIdx = customCondition.indexOf(startOfEvalStatement) + startOfEvalStatement.length
461- val endIdx = startIdx + customCondition.substring(startIdx).indexOfFirst { it == ' ' || it == ' =' }
462- return customCondition.substring(startIdx, endIdx)
463- }
464-
465401 // prepares the query results to be passed into alerts and notifications based on trigger mode
466402 // if result set, alert and notification simply stores all query results
467403 // if per result, each alert and notification stores a single row of the query results
@@ -480,7 +416,6 @@ object PPLMonitorRunner : MonitorV2Runner {
480416 individualRow.put(" datarows" , JSONArray (relevantQueryResultRows.getJSONArray(" datarows" ).getJSONArray(i).toList()))
481417 individualRows.add(individualRow)
482418 }
483-
484419 return individualRows
485420 }
486421
@@ -637,4 +572,72 @@ object PPLMonitorRunner : MonitorV2Runner {
637572// }
638573 }
639574 }
575+
576+ /* public util functions */
577+
578+ // appends user-defined custom trigger condition to PPL query, only for custom condition Triggers
579+ fun appendCustomCondition (query : String , customCondition : String ): String {
580+ return " $query | $customCondition "
581+ }
582+
583+ // returns PPL query response as parsable JSONObject
584+ suspend fun executePplQuery (query : String , client : NodeClient ): JSONObject {
585+ // call PPL plugin to execute time filtered query
586+ val transportPplQueryRequest = TransportPPLQueryRequest (
587+ query,
588+ JSONObject (mapOf (PPL_SQL_QUERY_FIELD to query)),
589+ null // null path falls back to a default path internal to SQL/PPL Plugin
590+ )
591+
592+ val transportPplQueryResponse = PPLPluginInterface .suspendUntil {
593+ this .executeQuery(
594+ client,
595+ transportPplQueryRequest,
596+ it
597+ )
598+ }
599+
600+ val queryResponseJson = JSONObject (transportPplQueryResponse.result)
601+
602+ return queryResponseJson
603+ }
604+
605+ // TODO: is there maybe some PPL plugin util function we can use to replace this?
606+ // searches a given custom condition eval statement for the name of
607+ // the eval result variable and returns it
608+ fun findEvalResultVar (customCondition : String ): String {
609+ // the PPL keyword "eval", followed by a whitespace must be present, otherwise a syntax error from PPL plugin would've
610+ // been thrown when executing the query (without the whitespace, the query would've had something like "evalresult",
611+ // which is invalid PPL
612+ val startOfEvalStatement = " eval "
613+
614+ val startIdx = customCondition.indexOf(startOfEvalStatement) + startOfEvalStatement.length
615+ val endIdx = startIdx + customCondition.substring(startIdx).indexOfFirst { it == ' ' || it == ' =' }
616+ return customCondition.substring(startIdx, endIdx)
617+ }
618+
619+ fun findEvalResultVarIdxInSchema (customConditionQueryResponse : JSONObject , evalResultVarName : String ): Int {
620+ // find the index eval statement result variable in the PPL query response schema
621+ val schemaList = customConditionQueryResponse.getJSONArray(" schema" )
622+ var evalResultVarIdx = - 1
623+ for (i in 0 until schemaList.length()) {
624+ val schemaObj = schemaList.getJSONObject(i)
625+ val columnName = schemaObj.getString(" name" )
626+
627+ if (columnName == evalResultVarName) {
628+ evalResultVarIdx = i
629+ break
630+ }
631+ }
632+
633+ // eval statement result variable should always be found
634+ if (evalResultVarIdx == - 1 ) {
635+ throw IllegalStateException (
636+ " expected to find eval statement results variable \" $evalResultVarName \" in results " +
637+ " of PPL query with custom condition, but did not."
638+ )
639+ }
640+
641+ return evalResultVarIdx
642+ }
640643}
0 commit comments