Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add options for specifying run window for project monitors #798

Open
kazagz opened this issue Jul 5, 2023 · 2 comments
Open

Add options for specifying run window for project monitors #798

kazagz opened this issue Jul 5, 2023 · 2 comments

Comments

@kazagz
Copy link

kazagz commented Jul 5, 2023

Currently project monitors allow specifying schedule using predefined values. But there is no option to define run or exclusion window for monitors to run / don't run.

Use case

We're using private locations to monitor company's internal web applications. Most of these applications are only used during daytime and it's not important for them to be up during nighttime. There is no need to execute any checks outside of working hours as it creates unnecessary noise if during night application is down for maintenance or other reasons. It would be nice if you could do something like:

monitor.use({
  id: "monitor-id",
  schedule: 1,
  runWindow: {
    start: "08:00",
    end: "18:00",
    frequency: "daily",
  },
  enabled: true,
  privateLocations: ["your-private-location"],
});
@paulb-elastic
Copy link
Contributor

Thanks for raising @kazagz. Agreed, there is a need for maintenance windows within Synthetics, and something that's on our roadmap, although I can't say when we'll be able to get to this feature.

In the meantime, a workaround you could consider is to push your configuration through an external mechanism each night / morning, having changed enabled to false.

You'd end up with something like this (which would need to be run programmatically, maybe triggered via a cron schedule):

  • At 18:00
    • set enabled: false for all monitors that don't need to run overnight
    • push the configuration
  • At 08:00
    • set enabled: true for these monitors
    • push the configuration

@kazagz
Copy link
Author

kazagz commented Jul 5, 2023

@paulb-elastic I was thinking about doing something similar, but monitors might be having very different schedules. So it doesn't scale up very well. Besides that implementing external mechanism would add extra complexity to project and each commit has to be tested against both external mechanism and project monitors.

For now we're thinking about wrapping steps inside condition to check if they should run or not. It's not great solution, because journey still gets executed, but atleast it will always report success if executed outside of run window. So you don't get any unnecessary alerts, but at the same time monitor shows green on Synthetics app, which might not be correct.

Sample using rrule package to skip steps outside of schedule:

import { journey, step, monitor } from "@elastic/synthetics";
import { RRule } from "rrule";
import { MonitorConfig } from "@elastic/synthetics/src/dsl/monitor";

const monitorSchedule: MonitorConfig["schedule"] = 5;
const runSchedule = new RRule({
  freq: RRule.MINUTELY,
  interval: monitorSchedule,
  byweekday: [RRule.MO, RRule.TU, RRule.WE, RRule.TH, RRule.FR],
  byhour: [8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
});

const occurrences = runSchedule.between(
  new Date(),
  new Date(Date.now() + monitorSchedule * 60 * 1000)
);

journey("RRule sample", ({ page }) => {
  monitor.use({
    id: "monitor-id",
    schedule: monitorSchedule,
    enabled: true,
    privateLocations: ["your-private-location"],
  });

  // When in container, only execute within specified window.
  // Also execute when testing or running locally.
  if (
    (process.env.ELASTIC_CONTAINER === "true" && occurrences.length > 0) ||
    process.env.ELASTIC_CONTAINER !== "true"
  ) {
    step("Open https://www.elastic.co/", async () => {
      const login = await page.goto("https://www.elastic.co/");
    });
  }
});

This works on some level, but still generates 1ms empty runs when steps are skipped. If instead of skipping steps it would be to possible to skip entire journey, then it would be much better. It's not possible for now, conditionally skipping entire journey generates error journey did not finish executing, 0 steps ran: %!w(<nil>). Sample below would be acceptable as a workaround, if it wouldn't generate mentioned error:

import { journey, step, monitor, expect } from "@elastic/synthetics";
import { RRule } from "rrule";
import { MonitorConfig } from "@elastic/synthetics/src/dsl/monitor";

const monitorSchedule: MonitorConfig["schedule"] = 3;
const rule = new RRule({
  freq: RRule.MINUTELY,
  interval: monitorSchedule,
  byweekday: [RRule.MO, RRule.TU, RRule.WE, RRule.TH, RRule.FR],
  byhour: [8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
});

const occurrences = rule.between(
  new Date(),
  new Date(Date.now() + monitorSchedule * 60 * 1000)
);

// When in container, only execute within specified window.
// Also execute when testing or running locally.
if (
  (process.env.ELASTIC_CONTAINER === "true" && occurrences.length > 0) ||
  process.env.ELASTIC_CONTAINER !== "true"
) {
  journey("RRule sample", ({ page }) => {
    monitor.use({
      id: "monitor-id",
      schedule: monitorSchedule,
      enabled: true,
      privateLocations: ["your-private-location"],
    });

    step("Open https://www.elastic.co/", async () => {
      const login = await page.goto("https://www.elastic.co/");
    });
  });
}

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

No branches or pull requests

2 participants