in src/push/monitor.ts [180:268]
export async function createLightweightMonitors(
workDir: string,
options: PushOptions
) {
const lwFiles = new Set<string>();
// Filter monitor files based on the provided pattern
const pattern = options.grepOpts?.pattern
? new RegExp(options.grepOpts?.pattern, 'i')
: /.(yml|yaml)$/;
const ignore = /(node_modules|.github)/;
await totalist(workDir, (rel, abs) => {
if (
!ignore.test(rel) &&
pattern.test(rel) &&
ALLOWED_LW_EXTENSIONS.includes(extname(abs))
) {
lwFiles.add(abs);
}
});
let warnOnce = false;
const monitors: Monitor[] = [];
for (const file of lwFiles.values()) {
// First check encoding and warn if any files are not the correct encoding.
const bufferContent = await readFile(file);
const isUtf8 = NodeBuffer.isUtf8(bufferContent);
if (!isUtf8) {
warn(`${file} is not UTF-8 encoded. Monitors might be skipped.`);
}
const content = bufferContent.toString('utf-8');
const lineCounter = new LineCounter();
const parsedDoc = parseDocument(content, {
lineCounter,
merge: true,
keepSourceTokens: true,
}) as Document.Parsed;
// Skip other yml files that are not relevant
const monitorSeq = parsedDoc.get('heartbeat.monitors') as YAMLSeq<YAMLMap>;
if (!monitorSeq) {
continue;
}
// Warn users about schedule that are less than 60 seconds
if (!warnOnce) {
warn(
'Lightweight monitor schedules will be adjusted to their nearest frequency supported by our synthetics infrastructure.'
);
warnOnce = true;
}
// Store the offsets of each monitor in the sequence to construct the source
// location later for capturing the error
const offsets = [];
for (const monNode of monitorSeq.items) {
offsets.push(monNode.srcToken.offset);
}
const mergedConfig = parsedDoc.toJS()[
'heartbeat.monitors'
] as Array<MonitorConfig>;
for (let i = 0; i < mergedConfig.length; i++) {
const monitor = mergedConfig[i];
// Skip browser monitors from the YML files
if (monitor['type'] === 'browser') {
warn(`Browser monitors from ${file} are skipped.`);
continue;
}
const { line, col } = lineCounter.linePos(offsets[i]);
try {
/**
* Build the monitor object from the yaml config along with global configuration
* and perform the match based on the provided filters
*/
const mon = buildMonitorFromYaml(monitor, options);
if (!mon.isMatch(options.grepOpts?.match, options.grepOpts?.tags)) {
continue;
}
mon.setSource({ file, line, column: col });
monitors.push(mon);
} catch (e) {
let outer = bold(`Aborted: ${e}\n`);
outer += indent(
`* ${monitor.id || monitor.name} - ${file}:${line}:${col}\n`
);
throw red(outer);
}
}
}
return monitors;
}