Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions 2022-03-health-checks-notifications/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# What is this repository about?

status-page is the code for a custom worker that can be used to create a Custom status-page using Cloudflare workers. It acceptes webhook notifications from Cloudflare Alert Notification service and creates a status-page which stores data in durable objects.

Change wrangler.toml to have your account that has access to Durable Objects.

# Steps to deploy to your account.

Install wrangler https://developers.cloudflare.com/workers/cli-wrangler/install-update if you don't have it installed already. Update wrangler to something greater than 1.19.3 as durable objects support does not work with previous versions.

```
$ wrangler publish --new-class Status
```

This will ensure the new class which ties to the durable object gets saved.
6 changes: 6 additions & 0 deletions 2022-03-health-checks-notifications/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "status-page",
"version": "1.0.0",
"description": "A template for kick-starting a Cloudflare Workers project using Durable Objects",
"module": "./src/index.mjs"
}
93 changes: 93 additions & 0 deletions 2022-03-health-checks-notifications/src/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Worker
export default {
async fetch(request, env) {
return await handleRequest(request, env);
}
}

async function handleRequest(request, env) {
let id = env.status.idFromName("A");
let obj = env.status.get(id);

return await obj.fetch(request);
}

// Durable Object
export class Status {
constructor(state, env) {
this.state = state;
}

async handleWebhook(request) {
const json = await request.json();

// Ignore webhook test notification upon creation
if ((json.text || "").includes("Hello World!")) return;

let healthCheckName = json.data?.name || "Unknown"
let details = {
status: json.data?.status || "Unknown",
failureReason: json.data?.reason || "Unknown"
}
await this.state.storage.put(healthCheckName, details)
}

async statusHTML() {
const statuses = await this.state.storage.list()
let statHTML = ""
for(let[hcName, details] of statuses) {
const status = details.status || ""
const failureReason = details.failureReason || ""
let hc = `<p>HealthCheckName: ${hcName} </p>
<p>Status: ${status} </p>
<p>FailureReason: ${failureReason}</p>
<br/>`
statHTML = statHTML + hc
}
return statHTML
}

async handleRoot() {
// Default of healthy for before any notifications have been triggered
const statuses = await this.statusHTML()

return new Response(`
<!DOCTYPE html>
<head>
<title>Status Page</title>
<style>
body {
font-family: Courier New;
padding-left: 10vw;
padding-right: 10vw;
padding-top: 5vh;
}
</style>
</head>
<body>
<h1>Status of Production Servers</h1>
<p>${statuses}</p>
</body>
`,
{
headers: {
'Content-Type': "text/html"
}
})
}

// Handle HTTP requests from clients.
async fetch(request) {
const url = new URL(request.url)
switch (url.pathname) {
case "/webhook":
await this.handleWebhook(request);
return new Response()
case "/":
return await this.handleRoot();
default:
return new Response('Path not found', { status: 404 })
}
}
}

18 changes: 18 additions & 0 deletions 2022-03-health-checks-notifications/wrangler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name = "status-page"
# type = "javascript" is required to use the `[build]` section
type = "javascript"
workers_dev = true
account_id = "<enter-your-account-id>"
route = ""
zone_id = ""
compatibility_date = "2022-02-11"

[build.upload]
# Upload the code directly from the src directory.
dir = "src"
# The "modules" upload format is required for all projects that export a Durable Objects class
format = "modules"
main = "./index.mjs"

[durable_objects]
bindings = [{name = "status", class_name = "Status"}]