Skip to content

Commit 23f4d46

Browse files
miesMicha 'mies' Hernandez van Leuffenbrettimus
authored
uptime monitor sample (#37)
* init * Add gitignore, .dev.vars.example, and check in migration files * Update wrangler in all package.json * Update uptime-monitor package.json * Remove typescript language server from example deps * Update cloudflare workers types * Code cleanup * Remove honc-hatch comment * Add a few notes and a format command to the uptime-monitor * Update readme --------- Co-authored-by: Micha 'mies' Hernandez van Leuffen <[email protected]> Co-authored-by: Brett Beutell <[email protected]>
1 parent c7392d4 commit 23f4d46

File tree

28 files changed

+1094
-127
lines changed

28 files changed

+1094
-127
lines changed

examples/cf-retrieval-augmented-goose/package.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"db:migrate": "drizzle-kit migrate",
1010
"db:setup": "npm run db:generate && npm run db:migrate",
1111
"db:studio": "drizzle-kit studio",
12-
"fiberplane": "pnpx @fiberplane/studio@canary",
12+
"fiberplane": "npx @fiberplane/studio@latest",
1313
"vectors:create": "tsx --tsconfig tsconfig.scripts.json scripts/create-vectors.ts",
1414
"format": "biome check . --write"
1515
},
@@ -34,7 +34,6 @@
3434
"pgvector": "^0.2.0",
3535
"tsx": "^4.19.2",
3636
"typescript": "^5.5.4",
37-
"typescript-language-server": "^4.3.3",
38-
"wrangler": "3.92.0"
37+
"wrangler": "^3.95.0"
3938
}
4039
}

examples/goose-joke-generator/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,6 @@
2525
"drizzle-kit": "^0.28.1",
2626
"tsx": "^4.19.2",
2727
"typescript": "^5.5.4",
28-
"wrangler": "3.92.0"
28+
"wrangler": "^3.95.0"
2929
}
3030
}

examples/goose-review-bot/package.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"db:seed": "tsx seed.ts",
99
"db:setup": "npm run db:generate && npm run db:migrate && npm run db:seed",
1010
"db:studio": "drizzle-kit studio",
11-
"fiberplane": "npx @fiberplane/studio@canary",
11+
"fiberplane": "npx @fiberplane/studio@latest",
1212
"format": "biome format . --write"
1313
},
1414
"dependencies": {
@@ -27,8 +27,7 @@
2727
"drizzle-kit": "^0.28.1",
2828
"tsx": "^4.19.2",
2929
"typescript": "^5.5.4",
30-
"typescript-language-server": "^4.3.3",
31-
"wrangler": "3.92.0"
30+
"wrangler": "^3.95.0"
3231
},
3332
"description": "an api that listens for github pull requests and does code reviews"
3433
}

examples/honcanator/package.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"db:migrate": "drizzle-kit migrate",
88
"db:setup": "npm run db:generate && npm run db:migrate",
99
"db:studio": "drizzle-kit studio",
10-
"fiberplane": "npx @fiberplane/studio@canary",
10+
"fiberplane": "npx @fiberplane/studio@latest",
1111
"format": "biome check . --write"
1212
},
1313
"dependencies": {
@@ -22,8 +22,7 @@
2222
"drizzle-kit": "^0.28.1",
2323
"tsx": "^4.19.2",
2424
"typescript": "^5.5.4",
25-
"typescript-language-server": "^4.3.3",
26-
"wrangler": "3.92.0"
25+
"wrangler": "^3.95.0"
2726
},
2827
"packageManager": "[email protected]+sha512.f549b8a52c9d2b8536762f99c0722205efc5af913e77835dbccc3b0b0b2ca9e7dc8022b78062c17291c48e88749c70ce88eb5a74f1fa8c4bf5e18bb46c8bd83a"
2928
}

examples/placegoose/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@
3535
"@types/prismjs": "^1.26.5",
3636
"drizzle-kit": "^0.28.1",
3737
"tsx": "^4.19.2",
38-
"wrangler": "3.92.0"
38+
"wrangler": "^3.95.0"
3939
}
4040
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Connect to local fiberplane instance
2+
FPX_ENDPOINT=http://localhost:8788/v1/traces

examples/uptime-monitor/.gitignore

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Normally you don't ignore this file, but it's nice to ignore it for the examples
2+
.fpxconfig
3+
4+
# prod
5+
dist/
6+
7+
# deps
8+
node_modules/
9+
.wrangler
10+
11+
# env
12+
.env
13+
.env.production
14+
.dev.vars
15+
.prod.vars
16+
17+
# misc
18+
.DS_Store

examples/uptime-monitor/README.md

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
## 🪿 Website Uptime Monitor
2+
3+
A serverless website monitoring application built with the HONC stack (Hono, OpenTelemetry, and Cloudflare). This application allows you to monitor the uptime of websites by performing periodic health checks and storing the results in a D1 database.
4+
5+
### Features
6+
7+
- Monitor multiple websites simultaneously
8+
- Configurable check intervals per website
9+
- Track response times and HTTP status codes
10+
- Calculate uptime percentages
11+
- RESTful API for managing monitored websites
12+
- Simple web interface to view monitored sites
13+
14+
### Technology Stack
15+
16+
- **Hono**: Lightweight web framework for Cloudflare Workers
17+
- **D1**: Cloudflare's serverless SQL database
18+
- **Drizzle ORM**: Type-safe database toolkit
19+
- **Durable Objects**: For managing persistent monitoring schedules
20+
- **OpenTelemetry**: For observability and monitoring
21+
22+
### Getting Started
23+
24+
[D1](https://developers.cloudflare.com/d1/) is Cloudflare's serverless SQL database. Running this application involves two key steps: first, setting up the project locally, and second, deploying it in production.
25+
26+
### Project Structure
27+
28+
```#
29+
├── src
30+
│ ├── index.tsx # Hono app entry point
31+
│ └── db
32+
│ └── schema.ts # Database schema
33+
├── .dev.vars.example # Example .dev.vars file
34+
├── .prod.vars.example # Example .prod.vars file
35+
├── seed.ts # Optional script to seed the db
36+
├── drizzle.config.ts # Drizzle configuration
37+
├── package.json
38+
├── tsconfig.json # TypeScript configuration
39+
└── wrangler.toml # Cloudflare Workers configuration
40+
```
41+
42+
### Commands for local development
43+
44+
Create a `.dev.vars` file from the example file:
45+
46+
```sh
47+
cp .dev.vars.example .dev.vars
48+
```
49+
50+
Run the migrations and (optionally) seed the database:
51+
52+
```sh
53+
# this is a convenience script that runs db:touch, db:generate, db:migrate, and db:seed
54+
npm run db:setup
55+
```
56+
57+
Run the development server:
58+
59+
```sh
60+
npm run dev
61+
```
62+
63+
As you iterate on the database schema, you'll need to generate a new migration file and apply it like so:
64+
65+
```sh
66+
npm run db:generate
67+
npm run db:migrate
68+
```
69+
70+
### Commands for deployment
71+
72+
Before deploying your worker to Cloudflare, ensure that you have a running D1 instance on Cloudflare to connect your worker to.
73+
74+
You can create a D1 instance by navigating to the `Workers & Pages` section and selecting `D1 SQL Database.`
75+
76+
Alternatively, you can create a D1 instance using the CLI:
77+
78+
```sh
79+
npx wrangler d1 create <database-name>
80+
```
81+
82+
After creating the database, update the `wrangler.toml` file with the database id.
83+
84+
```toml
85+
[[d1_databases]]
86+
binding = "DB"
87+
database_name = "uptime-d1-database"
88+
database_id = "<database-id-you-just-created>"
89+
migrations_dir = "drizzle/migrations"
90+
```
91+
92+
Include the following information in a `.prod.vars` file:
93+
94+
```sh
95+
CLOUDFLARE_D1_TOKEN="" # An API token with D1 edit permissions. You can create API tokens from your Cloudflare profile
96+
CLOUDFLARE_ACCOUNT_ID="" # Find your Account id on the Workers & Pages overview (upper right)
97+
CLOUDFLARE_DATABASE_ID="" # Find the database ID under workers & pages under D1 SQL Database and by selecting the created database
98+
```
99+
100+
If you haven’t generated the latest migration files yet, run:
101+
```shell
102+
npm run db:generate
103+
```
104+
105+
Afterwards, run the migration script for production:
106+
```shell
107+
npm run db:migrate:prod
108+
```
109+
110+
Change the name of the project in `wrangler.toml` if you want to, but for now it is:
111+
112+
```toml
113+
name = "uptime-monitor"
114+
```
115+
116+
Finally, deploy your worker
117+
118+
```shell
119+
npm run deploy
120+
```
121+
122+

examples/uptime-monitor/biome.jsonc

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3+
"extends": ["../../biome.jsonc"]
4+
}
+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import fs from "node:fs";
2+
import path from "node:path";
3+
import { config } from "dotenv";
4+
import { defineConfig } from "drizzle-kit";
5+
6+
let dbConfig: ReturnType<typeof defineConfig>;
7+
if (process.env.ENVIROMENT === "production") {
8+
config({ path: "./.prod.vars" });
9+
dbConfig = defineConfig({
10+
schema: "./src/db/schema.ts",
11+
out: "./drizzle/migrations",
12+
dialect: "sqlite",
13+
driver: "d1-http",
14+
dbCredentials: {
15+
accountId: process.env.CLOUDFLARE_ACCOUNT_ID ?? "",
16+
databaseId: process.env.CLOUDFLARE_DATABASE_ID ?? "",
17+
token: process.env.CLOUDFLARE_D1_TOKEN ?? "",
18+
},
19+
});
20+
} else {
21+
config({ path: "./.dev.vars" });
22+
const localD1DB = getLocalD1DB();
23+
if (!localD1DB) {
24+
process.exit(1);
25+
}
26+
27+
dbConfig = defineConfig({
28+
schema: "./src/db/schema.ts",
29+
out: "./drizzle/migrations",
30+
dialect: "sqlite",
31+
dbCredentials: {
32+
url: localD1DB,
33+
},
34+
});
35+
}
36+
37+
export default dbConfig;
38+
39+
function getLocalD1DB() {
40+
try {
41+
const basePath = path.resolve(".wrangler");
42+
const files = fs
43+
.readdirSync(basePath, { encoding: "utf-8", recursive: true })
44+
.filter((f) => f.endsWith(".sqlite"));
45+
46+
// In case there are multiple .sqlite files, we want the most recent one.
47+
files.sort((a, b) => {
48+
const statA = fs.statSync(path.join(basePath, a));
49+
const statB = fs.statSync(path.join(basePath, b));
50+
return statB.mtime.getTime() - statA.mtime.getTime();
51+
});
52+
const dbFile = files[0];
53+
54+
if (!dbFile) {
55+
throw new Error(`.sqlite file not found in ${basePath}`);
56+
}
57+
58+
const url = path.resolve(basePath, dbFile);
59+
60+
return url;
61+
} catch (err) {
62+
if (err instanceof Error) {
63+
console.log(`Error resolving local D1 DB: ${err.message}`);
64+
} else {
65+
console.log(`Error resolving local D1 DB: ${err}`);
66+
}
67+
}
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CREATE TABLE `uptime_checks` (
2+
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
3+
`websiteId` integer NOT NULL,
4+
`timestamp` text NOT NULL,
5+
`status` integer,
6+
`responseTime` integer,
7+
`isUp` integer NOT NULL,
8+
FOREIGN KEY (`websiteId`) REFERENCES `websites`(`id`) ON UPDATE no action ON DELETE no action
9+
);
10+
--> statement-breakpoint
11+
CREATE TABLE `websites` (
12+
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
13+
`url` text NOT NULL,
14+
`name` text NOT NULL,
15+
`checkInterval` integer NOT NULL,
16+
`createdAt` text NOT NULL
17+
);

0 commit comments

Comments
 (0)