import { WebClient } from "@slack/web-api";
import dayjs from "dayjs";
type Slack = {
token: string;
};
function formatError(error: any) {
if (error.stack && error.name && error.message) {
const formatted = `*${error.name}: ${error.message}*\`\`\`\n${error.stack}\n\`\`\``;
if (formatted.length > 2900) {
return `\`\`\`\n${JSON.stringify(error, null, 2).substring(0, 2900)}...\n(truncated)\n\`\`\``;
} else {
return formatted;
}
} else {
const stringified = JSON.stringify(error, null, 2);
if (stringified.length > 2900) {
return `\`\`\`\n${stringified.substring(0, 2900)}...\n(truncated)\n\`\`\``;
} else {
return `\`\`\`\n${stringified}\n\`\`\``;
}
}
}
function getTriggerInfo(baseUrl: string, workspace_id: string, trigger_path?: string) {
if (trigger_path) {
const triggerType = trigger_path.split("/")[0];
const prettyTriggerType = triggerType.charAt(0).toUpperCase() + triggerType.replace("_", " ").slice(1);
const triggerTypePath = triggerType === "http_trigger" ? "routes" : triggerType + "s";
const triggerPath = trigger_path.replace(`${triggerType}/`, "");
const url = `${baseUrl}/${triggerTypePath}?workspace=${encodeURIComponent(workspace_id)}\#${encodeURIComponent(
triggerPath
)}`;
return {
prettyTriggerType,
triggerPath,
url,
};
}
}
export async function main(
workspace_id: string,
job_id: string, // The UUID of the job that errored
path: string, // The path of the script or flow that errored
is_flow: boolean, // Whether the runnable is a flow
error: object, // The error details
started_at: string, // The start datetime of the latest job that failed
slack: Slack,
channel: string,
schedule_path?: string, // The path of the schedule
trigger_path?: string, // The path of the trigger that errored in the format <trigger_type>/<trigger_path>
failed_times?: number // Minimum number of times the schedule failed before calling the error handler
) {
const baseUrl = process.env["WM_BASE_URL"];
const scheduleUrl =
baseUrl +
"/runs?schedule_path=" +
encodeURIComponent(schedule_path) +
"&workspace=" +
encodeURIComponent(workspace_id);
const scriptOrFlowRunUrl =
baseUrl + (is_flow ? "/flows/get/" : "/scripts/get/") + path + "?workspace=" + encodeURIComponent(workspace_id);
const web = new WebClient(slack.token);
const jobRunUrl = baseUrl + "/run/" + job_id + "?workspace=" + encodeURIComponent(workspace_id);
const triggerInfo = getTriggerInfo(baseUrl, workspace_id, trigger_path);
let mdText = "";
if (schedule_path) {
mdText = `*Schedule <${scheduleUrl}|${schedule_path}> failed*${
failed_times > 1 ? " " + failed_times + " times in a row" : ""
}:\n- Run <${jobRunUrl}|${job_id}> of ${is_flow ? "flow" : "script"}: <${scriptOrFlowRunUrl}|${path}>`;
} else if (triggerInfo) {
mdText = `*${triggerInfo.prettyTriggerType} <${triggerInfo.url}|${
triggerInfo.triggerPath
}> failed*\n- Run <${jobRunUrl}|${job_id}> of ${is_flow ? "flow" : "script"}: <${scriptOrFlowRunUrl}|${path}>`;
} else {
mdText = `*Run <${jobRunUrl}|${job_id}> of ${is_flow ? "flow" : "script"} <${scriptOrFlowRunUrl}|${path}> failed*`;
}
const rawText = mdText.replaceAll(/[<>$*]/g, "");
const errorText = `${(failed_times ?? 1) > 1 ? "Last failed" : "Failed"} job started at: ${dayjs(started_at).format(
"DD.MM.YYYY HH:mm (Z)"
)}\n${formatError(error)}`;
await web.chat.postMessage({
channel,
text: rawText,
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: mdText,
},
},
],
attachments: [
{
color: "#ff0000",
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: errorText,
},
},
],
fallback: errorText,
},
],
});
}
Submitted by hugo697 1 day ago
import { WebClient } from "@slack/web-api";
import dayjs from "dayjs";
type Slack = {
token: string;
};
function formatError(error: any) {
if (error.stack && error.name && error.message) {
const formatted = `*${error.name}: ${error.message}*\`\`\`\n${error.stack}\n\`\`\``;
if (formatted.length > 2900) {
return `\`\`\`\n${JSON.stringify(error, null, 2).substring(0, 2900)}...\n(truncated)\n\`\`\``;
} else {
return formatted
}
} else {
const stringified = JSON.stringify(error, null, 2);
if (stringified.length > 2900) {
return `\`\`\`\n${stringified.substring(0, 2900)}...\n(truncated)\n\`\`\``;
} else {
return `\`\`\`\n${stringified}\n\`\`\``;
}
}
}
export async function main(
workspace_id: string,
job_id: string, // The UUID of the job that errored
path: string, // The path of the script or flow that errored
is_flow: boolean, // Whether the runnable is a flow
schedule_path: string, // The path of the schedule
error: object, // The error details
started_at: string, // The start datetime of the latest job that failed
failed_times: number, // Minimum number of times the schedule failed before calling the error handler
slack: Slack,
channel: string,
) {
const baseUrl = process.env["WM_BASE_URL"];
const scheduleUrl = baseUrl + "/runs?schedule_path=" +
encodeURIComponent(schedule_path) + "&workspace=" + encodeURIComponent(workspace_id);
const scriptOrFlowRunUrl = baseUrl + (is_flow ? "/flows/get/" : "/scripts/get/") +
path + "?workspace=" + encodeURIComponent(workspace_id);
const web = new WebClient(slack.token);
const jobRunUrl = baseUrl + "/run/" + job_id + "?workspace=" + encodeURIComponent(workspace_id);
let rawText = ""
if (schedule_path === undefined) {
rawText = `${schedule_path != undefined ? `Schedule ${schedule_path} failed ` : ""}${failed_times > 1 ? (failed_times + " times in a row") : ""}`
} else {
rawText = `Run <${jobRunUrl}|${job_id}> of ${is_flow ? "flow" : "script"}: <${scriptOrFlowRunUrl}|${path}> failed ${failed_times > 1 ? (failed_times + " times in a row") : ""}`
}
let mdText = ""
if (schedule_path === undefined) {
mdText = `*Run <${jobRunUrl}|${job_id}> of ${is_flow ? "flow" : "script"} <${scriptOrFlowRunUrl}|${path}> failed*${failed_times > 1 ? (" " + failed_times + " times in a row") : ""}:`
} else {
mdText = `*Schedule <${scheduleUrl}|${schedule_path}> failed*${failed_times > 1 ? (" " + failed_times + " times in a row") : ""}:\n- Run <${jobRunUrl}|${job_id}> of ${is_flow ? "flow" : "script"}: <${scriptOrFlowRunUrl}|${path}>`
}
const errorText = `Last failure at: ${dayjs(started_at).format("DD.MM.YYYY HH:mm (Z)")
}\n${formatError(error)}`
await web.chat.postMessage({
channel,
text: rawText,
blocks: [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": mdText,
},
},
],
attachments: [
{
color: "#ff0000",
"blocks": [{
"type": "section",
"text": {
"type": "mrkdwn",
"text": errorText,
},
}],
fallback: errorText
},
],
});
}
Submitted by hugo697 255 days ago
import { WebClient } from "@slack/web-api";
import dayjs from "dayjs";
type Slack = {
token: string;
};
function formatError(error: any) {
if (error.stack && error.name && error.message) {
return `*${error.name}: ${error.message}*\`\`\`\n${error.stack}\n\`\`\``;
} else {
const stringified = JSON.stringify(error, null, 2);
if (stringified.length > 2900) {
return `\`\`\`\n${stringified.substring(0, 2900)}...\n(truncated)\n\`\`\``;
} else {
return `\`\`\`\n${stringified}\n\`\`\``;
}
}
}
export async function main(
workspace_id: string,
job_id: string, // The UUID of the job that errored
path: string, // The path of the script or flow that errored
is_flow: boolean, // Whether the runnable is a flow
schedule_path: string, // The path of the schedule
error: object, // The error details
started_at: string, // The start datetime of the latest job that failed
failed_times: number, // Minimum number of times the schedule failed before calling the error handler
slack: Slack,
channel: string,
) {
const baseUrl = process.env["WM_BASE_URL"];
const scheduleUrl = baseUrl + "/runs?schedule_path=" +
encodeURIComponent(schedule_path) + "&workspace=" + encodeURIComponent(workspace_id);
const scriptOrFlowRunUrl = baseUrl + (is_flow ? "/flows/get/" : "/scripts/get/") +
path + "?workspace=" + encodeURIComponent(workspace_id);
const web = new WebClient(slack.token);
const jobRunUrl = baseUrl + "/run/" + job_id + "?workspace=" + encodeURIComponent(workspace_id);
let rawText = ""
if (schedule_path === undefined) {
rawText = `${schedule_path != undefined ? `Schedule ${schedule_path} failed ` : ""}${failed_times > 1 ? (failed_times + " times in a row") : ""}`
} else {
rawText = `Run <${jobRunUrl}|${job_id}> of ${is_flow ? "flow" : "script"}: <${scriptOrFlowRunUrl}|${path}> failed ${failed_times > 1 ? (failed_times + " times in a row") : ""}`
}
let mdText = ""
if (schedule_path === undefined) {
mdText = `*Run <${jobRunUrl}|${job_id}> of ${is_flow ? "flow" : "script"} <${scriptOrFlowRunUrl}|${path}> failed*${failed_times > 1 ? (" " + failed_times + " times in a row") : ""}:`
} else {
mdText = `*Schedule <${scheduleUrl}|${schedule_path}> failed*${failed_times > 1 ? (" " + failed_times + " times in a row") : ""}:\n- Run <${jobRunUrl}|${job_id}> of ${is_flow ? "flow" : "script"}: <${scriptOrFlowRunUrl}|${path}>`
}
await web.chat.postMessage({
channel,
text: rawText,
blocks: [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": mdText,
},
},
],
attachments: [
{
color: "#ff0000",
"blocks": [{
"type": "section",
"text": {
"type": "mrkdwn",
"text": `Last failure at: ${
dayjs(started_at).format("DD.MM.YYYY HH:mm (Z)")
}\n${formatError(error)}`,
},
}],
},
],
});
}
Submitted by hugo697 255 days ago
import { WebClient } from "@slack/web-api";
import dayjs from "dayjs";
type Slack = {
token: string;
};
function formatError(error: any) {
if (error.stack && error.name && error.message) {
return `*${error.name}: ${error.message}*\`\`\`\n${error.stack}\n\`\`\``;
} else {
return `\`\`\`\n${JSON.stringify(error, null, 2)}\n\`\`\``;
}
}
export async function main(
workspace_id: string,
job_id: string, // The UUID of the job that errored
path: string, // The path of the script or flow that errored
is_flow: boolean, // Whether the runnable is a flow
schedule_path: string, // The path of the schedule
error: object, // The error details
started_at: string, // The start datetime of the latest job that failed
failed_times: number, // Minimum number of times the schedule failed before calling the error handler
slack: Slack,
channel: string,
) {
const baseUrl = process.env["WM_BASE_URL"];
const scheduleUrl = baseUrl + "/runs?schedule_path=" +
encodeURIComponent(schedule_path) + "&workspace=" + encodeURIComponent(workspace_id);
const scriptOrFlowRunUrl = baseUrl + (is_flow ? "/flows/get/" : "/scripts/get/") +
path + "?workspace=" + encodeURIComponent(workspace_id);
const web = new WebClient(slack.token);
const jobRunUrl = baseUrl + "/run/" + job_id + "?workspace=" + encodeURIComponent(workspace_id);
let rawText = ""
if (schedule_path === undefined) {
rawText = `${schedule_path != undefined ? `Schedule ${schedule_path} failed ` : ""}${failed_times > 1 ? (failed_times + " times in a row") : ""}`
} else {
rawText = `Run <${jobRunUrl}|${job_id}> of ${is_flow ? "flow" : "script"}: <${scriptOrFlowRunUrl}|${path}> failed ${failed_times > 1 ? (failed_times + " times in a row") : ""}`
}
let mdText = ""
if (schedule_path === undefined) {
mdText = `*Run <${jobRunUrl}|${job_id}> of ${is_flow ? "flow" : "script"} <${scriptOrFlowRunUrl}|${path}> failed*${failed_times > 1 ? (" " + failed_times + " times in a row") : ""}:`
} else {
mdText = `*Schedule <${scheduleUrl}|${schedule_path}> failed*${failed_times > 1 ? (" " + failed_times + " times in a row") : ""}:\n- Run <${jobRunUrl}|${job_id}> of ${is_flow ? "flow" : "script"}: <${scriptOrFlowRunUrl}|${path}>`
}
await web.chat.postMessage({
channel,
text: rawText,
blocks: [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": mdText,
},
},
],
attachments: [
{
color: "#ff0000",
"blocks": [{
"type": "section",
"text": {
"type": "mrkdwn",
"text": `Last failure at: ${
dayjs(started_at).format("DD.MM.YYYY HH:mm (Z)")
}\n${formatError(error)}`,
},
}],
},
],
});
}
Submitted by hugo697 303 days ago
import { WebClient } from "@slack/web-api";
import dayjs from "dayjs";
type Slack = {
token: string;
};
function formatError(error: any) {
if (error.stack && error.name && error.message) {
return `*${error.name}: ${error.message}*\`\`\`\n${error.stack}\n\`\`\``;
} else {
return `\`\`\`\n${JSON.stringify(error, null, 2)}\n\`\`\``;
}
}
export async function main(
workspace_id: string,
job_id: string, // The UUID of the job that errored
path: string, // The path of the script or flow that errored
is_flow: boolean, // Whether the runnable is a flow
schedule_path: string, // The path of the schedule
error: object, // The error details
started_at: string, // The start datetime of the latest job that failed
failed_times: number, // Minimum number of times the schedule failed before calling the error handler
slack: Slack,
channel: string,
) {
const baseUrl = process.env["WM_BASE_URL"];
const scheduleUrl = baseUrl + "/runs?schedule_path=" +
encodeURIComponent(schedule_path) + "&workspace=" + encodeURIComponent(workspace_id);
const scriptOrFlowRunUrl = baseUrl + (is_flow ? "/flows/get/" : "/scripts/get/") +
path + "?workspace=" + encodeURIComponent(workspace_id);
const web = new WebClient(slack.token);
const jobRunUrl = baseUrl + "/run/" + job_id + "?workspace=" + encodeURIComponent(workspace_id);
let rawText = ""
if (schedule_path === undefined) {
rawText = `${schedule_path != undefined ? `Schedule ${schedule_path} failed ` : ""}${failed_times > 1 ? (failed_times + " times in a row") : ""}`
} else {
rawText = `Run <${jobRunUrl}|${job_id}> of ${is_flow ? "flow" : "script"}: <${scriptOrFlowRunUrl}|${path}> failed ${failed_times > 1 ? (failed_times + " times in a row") : ""}`
}
let mdText = ""
if (schedule_path === undefined) {
mdText = `*Run <${jobRunUrl}|${job_id}> of ${is_flow ? "flow" : "script"} <${scriptOrFlowRunUrl}|${path}> failed*${failed_times > 1 ? (" " + failed_times + " times in a row") : ""}:`
} else {
mdText = `*Schedule <${scheduleUrl}|${schedule_path}> failed*${failed_times > 1 ? (" " + failed_times + " times in a row") : ""}:\n- Run <${jobRunUrl}|${job_id}> of ${is_flow ? "flow" : "script"}: <${scriptOrFlowRunUrl}|${path}>`
}
await web.chat.postMessage({
channel,
text: rawText,
blocks: [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": mdText,
},
},
],
attachments: [
{
color: "#ff0000",
"blocks": [{
"type": "section",
"text": {
"type": "mrkdwn",
"text": `Last failure at: ${
dayjs(started_at).format("DD.MM.YYYY HH:mm (Z)")
}\n${formatError(error)}`,
},
}],
},
],
});
}
Submitted by hugo697 303 days ago