Fix/ppl monitor test notification - #1500
Conversation
sendTestMessage had no MONITOR_TYPE.PPL case, so PPL monitors fell into the default branch which serializes a v1 query-level monitor (top-level trigger with a painless condition) and posts it to the v1 _execute API. The backend rejects this with: Incompatible trigger [...] for monitor type [ppl_monitor] Route PPL monitors through buildPPLMonitorFromFormik (the same serializer used to save them) and POST to /api/alerting/v2/monitors/_execute, keeping only the action under test and forcing an always-true number_of_results >= 0 condition so the notification fires. Signed-off-by: Riya Saxena <riysaxen@amazon.com>
Covers: v2 _execute dispatch for MONITOR_TYPE.PPL, ppl_monitor payload shape (no v1 top-level triggers / painless condition / match_all inputs), forced always-firing condition with only the tested action retained, v1 endpoint regression for query-level monitors, and error handling. Signed-off-by: Riya Saxena <riysaxen@amazon.com>
The v2 monitors _execute route's query schema only accepts dataSourceId; passing dryrun (copied from the v1 call) failed route validation with '[request query.dryrun]: definition for this key is missing'. Remove it. Also surface rejected fetches (e.g. route validation 400s) via backendErrorNotification instead of only console.error, so the user gets a toast instead of silence. Signed-off-by: Riya Saxena <riysaxen@amazon.com>
…rvice
executeMonitor forwarded the { ppl_monitor: {...} } body to the engine
untranslated. The engine only speaks the v1 monitor format, so
Monitor.parse rejected it with 'Monitor name is null'. Apply the same
toV1MonitorBody translation that createMonitor and updateMonitor use.
Signed-off-by: Riya Saxena <riysaxen@amazon.com>
toV1MonitorBody defaults a missing query to an empty string, so any update request whose body lacks the PPL query would silently persist an empty query -- silent data loss reported by customers as 'update monitor drops the PPL query'. Reject such updates with an explicit error instead of writing an empty query. Signed-off-by: Riya Saxena <riysaxen@amazon.com>
…anslation Covers: update rejected when query missing or whitespace-only (engine never called), valid update translated to v1 shape (top-level name, ppl_input inputs, ppl_trigger-wrapped triggers), and execute body translated to v1 (no ppl_monitor wrapper, name present). Signed-off-by: Riya Saxena <riysaxen@amazon.com>
The helpers/services mocks replaced the whole modules, but the component's import chain calls dataSourceEnabled() at module load, failing the suite with 'dataSourceEnabled is not a function'. Spread jest.requireActual so only the intended functions are stubbed. Signed-off-by: Riya Saxena <riysaxen@amazon.com>
|
mac/linux fail is a due to platform-dependent dependency hoisting, not related to this PR |
eirsep
left a comment
There was a problem hiding this comment.
Re: (monitor update erasing the PPL query)
The guard is a good defensive fix — it stops the silent data loss by rejecting query-less
update bodies. But it's shifting the failure mode, not fixing the root cause: we go from "update silently wipes the query" to "update returns a 4xx saying the query is empty." If something upstream is actually sending update bodies without the query, the user still can't save — they just get an error instead of silent corruption. And, we don't have an RCA for why empty query is being passed from ux
@eirsep Fair challenge on the missing RCA — tracked it down. There is a concrete producer of query-less/empty-query update bodies, and it's the edit-page hydration on the 3.x release lines: The producer (3.5/3.7 release lines): initialValues.pplQuery = initialValues.pplQuery || _.get(monitorToEdit, 'ppl_monitor.query') || '';but the v2 Why it doesn't reproduce on main: the hydration was since reworked — Why the guard still belongs on main: (1) a PPL monitor with an empty query is never a valid save — there's no legitimate caller intent the rejection could break; (2) the update route is also reachable from quick-action paths ( Happy to split the guard into its own PR if you'd prefer this one stay scoped to the test-notification fix. |
|
Nit (maintainability): the test-message result-handling block is duplicated.
Consider extracting a shared helper, e.g. Not blocking — just flagging to keep the two paths from diverging. |
Deduplicate the checkForError -> success-toast -> backendErrorNotification block that was repeated in sendTestMessage and sendTestMessageForPplMonitor into handleTestMessageResponse, per review feedback. Signed-off-by: Riya Saxena <riysaxen@amazon.com>
@lezzago Good call — extracted |
d294848
into
opensearch-project:main
…1505) * Accept v1-shape monitor body in PPL update guard and toV1MonitorBody The monitor details page enable/disable toggle round-trips the monitor in raw v1 shape (query nested in inputs[0].ppl_input.query, nothing at top level). toV1MonitorBody read only the top-level query and defaulted to '', so before the empty-query guard this path silently wiped the monitor's PPL query on every toggle; after the guard it was rejected outright. Fall back to inputs[0].ppl_input.query in both toV1MonitorBody and the updateMonitor guard so v1-shape bodies pass through with their query intact, while truly query-less bodies are still rejected. Signed-off-by: Riya Saxena <riysaxen@amazon.com> * Address review: drop v1/v2 language, add empty nested-query rejection tests - Rename toV1MonitorBody -> toEngineMonitorBody, flattenV1Monitor -> flattenEngineMonitor, and reword all v1/v2 comments to 'engine format' vs 'flattened format' (toepkerd) -- v2 APIs were never launched, so version language is a vestige of the removed v2 push. - Add tests asserting the guard still rejects engine-shape bodies whose nested query is empty or whose ppl_input is empty (eirsep). Signed-off-by: Riya Saxena <riysaxen@amazon.com> * Fix pre-existing main test failure: unwrap ppl_monitor in lookback-strip test buildPPLMonitorFromFormik returns the wrapped shape { ppl_monitor: {...} } (from #1500), but the lookback-strip test (from #1501) asserted query on the top-level return, which is undefined -- a semantic merge conflict between the two PRs that has kept the unit-test workflow red on main since Aug 20. Assert against ppl_monitor.query instead. Signed-off-by: Riya Saxena <riysaxen@amazon.com> * Address review: strip stale trigger metadata from engine-shape bodies, extract shared extractPplQuery helper - Unwrap ppl_trigger before stripping id/last_triggered_time/last_execution_time so the newly-accepted engine-shape bodies get the same trigger cleaning as the flattened path - Extract extractPplQuery() shared by the update guard and toEngineMonitorBody so the two can never drift apart - A whitespace-only top-level query no longer short-circuits the nested query fallback Signed-off-by: Riya Saxena <riysaxen@amazon.com> --------- Signed-off-by: Riya Saxena <riysaxen@amazon.com>
Description
Bug 1: "Send test message" always fails for PPL monitors.
ConfigureActionsPpl.sendTestMessagehad noMONITOR_TYPE.PPLcase in its monitor-type switch, so PPL monitors fell into thedefault:branch, which serializes a v1 query-level monitor — a top-level trigger with a painlesscondition.scriptand amatch_allsearch input — and POSTs it to the v1_executeAPI. The backend correctly rejects that combination with:Fix: PPL monitors now build the test payload with
buildPPLMonitorFromFormik— the same serializer used to save them, so the trigger shape (number_of_resultsetc.) is correct by construction — keep only the action under test, force an always-firingnum_results_condition: '>='/num_results_value: 0condition, and POST to/api/alerting/v2/monitors/_execute. The v1 path for query/bucket/doc-level monitors is unchanged.Bug 2: the v2
_executeOSD route forwarded the body untranslated.The engine only speaks the v1 monitor format;
PplAlertingMonitorService.createMonitor/updateMonitortranslate viatoV1MonitorBody, butexecuteMonitorforwarded{ ppl_monitor: {...} }raw, which the engine'sMonitor.parserejects withMonitor name is null.Fix: apply the same
toV1MonitorBodytranslation inexecuteMonitor.Bug 3: monitor updates could silently erase the PPL query.
toV1MonitorBodydefaults a missing query to'', so any update request whose body lacked the query silently persisted an empty query — surfacing to users as "updating a monitor drops the PPL query".Fix:
updateMonitornow rejects query-less bodies with an explicit error instead of writing an empty query.Also:
backendErrorNotificationinstead of onlyconsole.error._executecall no longer passesdryrun, which is not part of the v2 route's query schema and failed validation.Testing
public/pages/CreateTrigger/containers/ConfigureActions/ConfigureActionsPpl.test.js— v2 endpoint dispatch for PPL monitors,ppl_monitorpayload shape (no v1 top-level triggers / painless condition /match_allinputs), forced always-firing condition with only the tested action retained, v1 endpoint regression for query-level monitors, error handling.server/services/PplAlertingMonitorService.test.js— update rejected when query is missing or whitespace-only (engine never called), valid update translated to the v1 engine format, execute body translated to v1 (top-levelname,ppl_inputinputs,ppl_trigger-wrapped triggers).triggered: true) via a direct_executecall; the update guard returns the rejection message and leaves the stored query intact; error toasts render in the UI.Related Issues
n/a — found while investigating PPL monitor notification failures. Happy to file tracking issues if maintainers prefer.
Check List
--signoff.