Skip to content

Commit

Permalink
fix(betterUptime): make better uptime on success (#1075)
Browse files Browse the repository at this point in the history
* fix(betterUptime): make better uptime on success

* fix(betteruptime): only create alarm iff success

* fix(formsgsl): rm redundant call
  • Loading branch information
kishore03109 authored Jan 3, 2024
1 parent 7569526 commit 4f3133e
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 80 deletions.
79 changes: 0 additions & 79 deletions src/routes/formsg/formsgSiteLaunch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,6 @@ export class FormsgSiteLaunchRouter {
await mailer.sendMail(requesterEmail, subject, html)
}

sendMonitorCreationFailure = async (baseDomain: string): Promise<void> => {
const email = ISOMER_SUPPORT_EMAIL
const subject = `[Isomer] Monitor creation FAILURE`
const html = `The Uptime Robot monitor for the following site was not created successfully: ${baseDomain}`
await mailer.sendMail(email, subject, html)
}

digDomainRecords = async (
domain: string,
digType: DigType
Expand All @@ -250,77 +243,6 @@ export class FormsgSiteLaunchRouter {
return null
})

private async createMonitor(baseDomain: string) {
const uptimeRobotBaseUrl = "https://api.uptimerobot.com/v2"
try {
const UPTIME_ROBOT_API_KEY = config.get("uptimeRobot.apiKey")
const getResp = await axios.post<{ monitors: { id: string }[] }>(
`${uptimeRobotBaseUrl}/getMonitors?format=json`,
{
api_key: UPTIME_ROBOT_API_KEY,
search: baseDomain,
}
)
const affectedMonitorIds = getResp.data.monitors.map(
(monitor) => monitor.id
)
const getAlertContactsResp = await axios.post<{
alert_contacts: { id: string }[]
}>(`${uptimeRobotBaseUrl}/getAlertContacts?format=json`, {
api_key: UPTIME_ROBOT_API_KEY,
})
const alertContacts = getAlertContactsResp.data.alert_contacts
.map(
(contact) => `${contact.id}_0_0` // numbers at the end represent threshold + recurrence, always 0 for free plan
)
.join("-")
if (affectedMonitorIds.length === 0) {
// Create new monitor
await axios.post<{ monitors: { id: string }[] }>(
`${uptimeRobotBaseUrl}/newMonitor?format=json`,
{
api_key: UPTIME_ROBOT_API_KEY,
friendly_name: baseDomain,
url: `https://${baseDomain}`,
type: 1, // HTTP(S)
interval: 30,
timeout: 30,
alert_contacts: alertContacts,
http_method: 2, // GET
}
)
} else {
// Edit existing monitor
// We only edit the first matching monitor, in the case where multiple monitors exist
await axios.post<{ monitors: { id: string }[] }>(
`${uptimeRobotBaseUrl}/editMonitor?format=json`,
{
api_key: UPTIME_ROBOT_API_KEY,
id: affectedMonitorIds[0],
friendly_name: baseDomain,
url: `https://${baseDomain}`,
type: 1, // HTTP(S)
interval: 30,
timeout: 30,
alert_contacts: alertContacts,
http_method: 2, // GET
}
)
}
} catch (uptimerobotErr) {
// Non-blocking error, since site launch is still successful
const errMessage = `Unable to create better uptime monitor for ${baseDomain}. Error: ${uptimerobotErr}`
logger.error(errMessage)
try {
await this.sendMonitorCreationFailure(baseDomain)
} catch (monitorFailureEmailErr) {
logger.error(
`Failed to send error email for ${baseDomain}: ${monitorFailureEmailErr}`
)
}
}
}

private async handleSiteLaunchResults(
formResponses: FormResponsesProps[],
submissionId: string
Expand Down Expand Up @@ -386,7 +308,6 @@ export class FormsgSiteLaunchRouter {
)
}
// Create better uptime monitor
await this.createMonitor(launchResult.value.primaryDomainSource)
successResults.push(successResult)
}
}
Expand Down
83 changes: 82 additions & 1 deletion src/services/infra/InfraService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { SubDomainSettings } from "aws-sdk/clients/amplify"
import axios from "axios"
import Joi from "joi"
import {
Err,
Expand Down Expand Up @@ -605,6 +606,9 @@ export default class InfraService {
siteStatus: SiteStatus.Launched,
jobStatus: JobStatus.Ready,
}

// Create better uptime monitor iff site launch is a success
await this.createMonitor(message.primaryDomainSource)
} else {
updateSiteLaunchParams = {
id: site.value.id,
Expand All @@ -614,7 +618,6 @@ export default class InfraService {
}

await this.sitesService.update(updateSiteLaunchParams)

await this.sendEmailUpdate(message, isSuccess)
})
)
Expand All @@ -623,6 +626,84 @@ export default class InfraService {
}
}

private async createMonitor(baseDomain: string) {
const uptimeRobotBaseUrl = "https://api.uptimerobot.com/v2"
try {
const UPTIME_ROBOT_API_KEY = config.get("uptimeRobot.apiKey")
const getResp = await axios.post<{ monitors: { id: string }[] }>(
`${uptimeRobotBaseUrl}/getMonitors?format=json`,
{
api_key: UPTIME_ROBOT_API_KEY,
search: baseDomain,
}
)
const affectedMonitorIds = getResp.data.monitors.map(
(monitor) => monitor.id
)
const getAlertContactsResp = await axios.post<{
alert_contacts: { id: string }[]
}>(`${uptimeRobotBaseUrl}/getAlertContacts?format=json`, {
api_key: UPTIME_ROBOT_API_KEY,
})
const alertContacts = getAlertContactsResp.data.alert_contacts
.map(
(contact) => `${contact.id}_0_0` // numbers at the end represent threshold + recurrence, always 0 for free plan
)
.join("-")
if (affectedMonitorIds.length === 0) {
// Create new monitor
await axios.post<{ monitors: { id: string }[] }>(
`${uptimeRobotBaseUrl}/newMonitor?format=json`,
{
api_key: UPTIME_ROBOT_API_KEY,
friendly_name: baseDomain,
url: `https://${baseDomain}`,
type: 1, // HTTP(S)
interval: 30,
timeout: 30,
alert_contacts: alertContacts,
http_method: 2, // GET
}
)
} else {
// Edit existing monitor
// We only edit the first matching monitor, in the case where multiple monitors exist
await axios.post<{ monitors: { id: string }[] }>(
`${uptimeRobotBaseUrl}/editMonitor?format=json`,
{
api_key: UPTIME_ROBOT_API_KEY,
id: affectedMonitorIds[0],
friendly_name: baseDomain,
url: `https://${baseDomain}`,
type: 1, // HTTP(S)
interval: 30,
timeout: 30,
alert_contacts: alertContacts,
http_method: 2, // GET
}
)
}
} catch (uptimerobotErr) {
// Non-blocking error, since site launch is still successful
const errMessage = `Unable to create better uptime monitor for ${baseDomain}. Error: ${uptimerobotErr}`
logger.error(errMessage)
try {
await this.sendMonitorCreationFailure(baseDomain)
} catch (monitorFailureEmailErr) {
logger.error(
`Failed to send error email for ${baseDomain}: ${monitorFailureEmailErr}`
)
}
}
}

sendMonitorCreationFailure = async (baseDomain: string): Promise<void> => {
const email = ISOMER_SUPPORT_EMAIL
const subject = `[Isomer] Monitor creation FAILURE`
const html = `The Uptime Robot monitor for the following site was not created successfully: ${baseDomain}`
await mailer.sendMail(email, subject, html)
}

pollMessages = async () => {
setInterval(this.siteUpdate, SITE_LAUNCH_UPDATE_INTERVAL)
}
Expand Down

0 comments on commit 4f3133e

Please sign in to comment.