Skip to content

feat: add timeout option to browser monitors#1113

Draft
miguelmartin-elastic wants to merge 12 commits intoelastic:mainfrom
miguelmartin-elastic:1101-add-monitor-timeout-config-field
Draft

feat: add timeout option to browser monitors#1113
miguelmartin-elastic wants to merge 12 commits intoelastic:mainfrom
miguelmartin-elastic:1101-add-monitor-timeout-config-field

Conversation

@miguelmartin-elastic
Copy link
Copy Markdown

@miguelmartin-elastic miguelmartin-elastic commented Feb 2, 2026

closes #1101

Summary

  • Enforce monitor timeout parsing (s/m/h) and apply it as a journey-level timeout in the local runner.
  • Respect timeout precedence (local monitor > global monitor > CLI/options).
  • Add unit tests for global, local override, and CLI timeout sources.

Manual Test Plan

Lightweight monitor

  • Ensure that timeout are correctly validated and enforced when passed using yaml config (same behaviour as of today)
  • Ensure that, with these changes, timeout can be passed and enforced for lightweight monitors using also cli options and config file

Local runner (run)

  • CLI timeout

    • Add a journey with a step that sleeps >1s.
    • Run: npx @elastic/synthetics . --timeout 1s
    • Verify: journey fails with “Journey timeout of 1s exceeded”.
  • Global config timeout

    • In synthetics.config.ts, set monitor: { timeout: '1s' }.
    • Run: npx @elastic/synthetics .
    • Verify: journey fails with “Journey timeout of 1s exceeded”.
  • Per‑monitor override

    • Keep global timeout: '1s' in config.
    • In the journey, set monitor.use({ timeout: '2s' }) and keep the slow step (~1.1s).
    • Run: npx @elastic/synthetics .
    • Verify: journey completes successfully.
  • Validation

    • Set timeout: '1x' in config or monitor.use.
    • Run: npx @elastic/synthetics .
    • Verify: error “Invalid timeout format… Expected format is a number followed by 's', 'm', or 'h'.”

Push (project monitors)

  • CLI timeout on push

    • Run: npx @elastic/synthetics push --timeout 30s
    • Verify: monitors in Kibana have timeout: "30s".
  • Global config timeout on push

    • In synthetics.config.ts, set monitor: { timeout: '30s' }.
    • Run: npx @elastic/synthetics push
    • Verify: monitors in Kibana have timeout: "30s".
  • Per‑monitor override on push

    • Keep global timeout: '30s'.
    • In a journey, set monitor.use({ timeout: '10s' }).
    • Run: npx @elastic/synthetics push
    • Verify: that specific monitor has timeout: "10s" and others keep "30s".
  • No Private locations warning

    • Configure locations (public) plus timeout on any monitor and DO NOT include any private location.
    • Run: npx @elastic/synthetics push
    • Verify: warning about timeout only enforced in private locations.

miguelmartin-elastic and others added 4 commits February 6, 2026 19:45
Parse monitor timeout strings, apply them as journey timeouts, and add unit
coverage for global, local, and CLI timeout sources.

Co-authored-by: Cursor <cursoragent@cursor.com>
Update push warning to trigger only without privateLocations and add a unit
coverage for the warning output.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use a dedicated test-bundler-zip folder to avoid parallel test collisions
between bundler and plugin suites.

Include updated Node types from linting hooks.

Co-authored-by: Cursor <cursoragent@cursor.com>
Validate CLI/config timeouts for lightweight monitors, pass the timeout into
YAML-backed monitor configs, and cover it with tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
import { Bundler } from '../../src/push/bundler';

const PROJECT_DIR = join(__dirname, 'test-bundler');
const PROJECT_DIR = join(__dirname, 'test-bundler-zip');
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this because this and the plugin.test.ts were failing when ran locally and in parallel

if (step.status === 'failed') {
journey.status = step.status;
journey.error = step.error;
await this.withJourneyTimeout(timeoutMs, timeoutValue, async () => {
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not very familiar with how the runner works behind the scenes, so I would really like to know what you think about this approach @emilioalvap (not sure if this is even needed at all, but I assume it is?)

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a configurable timeout option for monitors, validates its format, wires it into the local runner as a journey-level timeout, and surfaces a warning when timeout is configured without private locations.

Changes:

  • Introduces timeout parsing/validation (s/m/h) and adds it to MonitorConfig.
  • Applies timeout precedence (per-journey monitor > global monitor > CLI/options) and enforces it in the local runner.
  • Adds CLI flag support and warning behavior; expands unit test coverage for push + runner behavior.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/push/monitor.ts Passes timeout from YAML/CLI into monitor config and validates its format.
src/push/index.ts Adds a warning helper for “timeout configured without private locations”.
src/dsl/monitor.ts Adds validateTimeout/parseTimeout, extends MonitorConfig, and validates timeout in Monitor.validate().
src/core/runner.ts Adds journey-level timeout enforcement with precedence logic and passes CLI timeout into the created runner monitor.
src/common_types.ts Plumbs timeout through CLI/base args typing.
src/cli.ts Adds --timeout flag and invokes the new push warning.
package.json Updates @types/node patch version.
tests/push/monitor.test.ts Adds lightweight monitor tests for CLI timeout and invalid format rejection.
tests/push/index.test.ts Adds tests for --timeout push behavior and the “no privateLocations” warning.
tests/push/bundler.test.ts Renames test directory reference used for zip validation.
tests/core/runner.test.ts Adds journey timeout tests for global/local/CLI precedence and enforcement.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +443 to +456
const timeoutError = new Error(
`Journey timeout of ${timeoutValue} exceeded`
);
let timeoutId: ReturnType<typeof setTimeout> | undefined;
const timeoutPromise = new Promise<T>((_, reject) => {
timeoutId = setTimeout(() => reject(timeoutError), timeoutMs);
});
try {
return await Promise.race([fn(), timeoutPromise]);
} finally {
if (timeoutId) {
clearTimeout(timeoutId);
}
}
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Promise.racerejects on timeout but does not cancelfn()`, so the journey steps can continue running in the background after the timeout triggers (potentially impacting subsequent journeys and resource cleanup). Consider introducing cancellation (e.g., an AbortController passed down to step execution / Playwright operations) and stopping execution when the timeout fires, rather than only rejecting the wrapper promise.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a valid concern. Doing it the right way may require a little bit more of thinking and possibly is out of scope for this issue/PR? If we want to use a different approach I can send a separate PR Lmkwyt @emilioalvap

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Add timeout option to monitor DSL

2 participants