Build a comprehensive website monitoring application with ReasonML, OCaml, and server-reason-react.
Features:
- Real-time website monitoring with HTTP status checks
- Email and webhook alerting system
- Beautiful admin dashboard with Tailwind CSS
- Complete REST API for CRUD operations
- Background monitoring scheduler
- Multi-container Docker setup with 1-core CPU constraint
- PostgreSQL database with Caqti
- Full documentation and setup guides
Tech Stack:
- OCaml 5.0+ with ReasonML
- Dream web framework
- server-reason-react for UI
- PostgreSQL 16 database
- Docker & Docker Compose
Files:
- 9 OCaml source files (1961 LOC)
- 6 documentation files (1603 LOC)
- Complete Docker configuration
- Comprehensive API documentation
💘 Generated with Crush
326 lines
6.3 KiB
Markdown
326 lines
6.3 KiB
Markdown
# Website Monitor
|
|
|
|
A comprehensive website monitoring application built with ReasonML, OCaml, and server-reason-react. Monitor multiple websites for HTTP status deviations and receive alerts via email or webhooks.
|
|
|
|
## Features
|
|
|
|
- **Real-time Monitoring**: Continuously monitor websites for HTTP 200 status deviations
|
|
- **Alert System**: Send alerts via email or webhooks when websites go down or recover
|
|
- **Admin Dashboard**: Beautiful, responsive web interface for managing websites and alerts
|
|
- **REST API**: Full CRUD API for programmatic access
|
|
- **History Tracking**: Keep detailed history of all website checks
|
|
- **Docker Support**: Fully containerized with Docker and Docker Compose
|
|
- **Resource-Constrained Builds**: Docker builds limited to 1 CPU core
|
|
|
|
## Technology Stack
|
|
|
|
- **Language**: OCaml 5.0+ with ReasonML
|
|
- **Web Framework**: Dream (OCaml web framework)
|
|
- **Frontend**: server-reason-react (server-side React with ReasonML)
|
|
- **Database**: PostgreSQL with Caqti (OCaml database interface)
|
|
- **Async**: Lwt (OCaml's cooperative threading library)
|
|
- **Container**: Docker & Docker Compose
|
|
|
|
## Quick Start
|
|
|
|
### Prerequisites
|
|
|
|
- Docker 20.10+
|
|
- Docker Compose 2.0+
|
|
|
|
### Installation
|
|
|
|
1. Clone the repository:
|
|
```bash
|
|
git clone <repository-url>
|
|
cd test3
|
|
```
|
|
|
|
2. Create environment file:
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
3. Edit `.env` with your configuration (especially SMTP settings for alerts)
|
|
|
|
4. Start the application:
|
|
```bash
|
|
docker-compose up -d
|
|
```
|
|
|
|
5. Access the dashboard at http://localhost:8080
|
|
|
|
## Configuration
|
|
|
|
### Environment Variables
|
|
|
|
| Variable | Description | Default |
|
|
|----------|-------------|---------|
|
|
| `DB_PASSWORD` | PostgreSQL database password | `changeme` |
|
|
| `SMTP_HOST` | SMTP server hostname | `smtp.gmail.com` |
|
|
| `SMTP_PORT` | SMTP server port | `587` |
|
|
| `SMTP_USER` | SMTP username | - |
|
|
| `SMTP_PASSWORD` | SMTP password | - |
|
|
| `ADMIN_EMAIL` | Email to receive all alerts | `admin@example.com` |
|
|
| `SECRET_KEY` | Secret key for sessions | - |
|
|
| `ENVIRONMENT` | Environment (`development`/`production`) | `production` |
|
|
|
|
## API Documentation
|
|
|
|
### Websites
|
|
|
|
#### List all websites
|
|
```
|
|
GET /api/websites
|
|
```
|
|
|
|
#### Get website by ID
|
|
```
|
|
GET /api/websites/:id
|
|
```
|
|
|
|
#### Create website
|
|
```
|
|
POST /api/websites
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"name": "Example Site",
|
|
"url": "https://example.com",
|
|
"expected_status": 200,
|
|
"timeout": 30,
|
|
"check_interval": 300
|
|
}
|
|
```
|
|
|
|
#### Update website
|
|
```
|
|
PUT /api/websites/:id
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"name": "Updated Name",
|
|
"active": true
|
|
}
|
|
```
|
|
|
|
#### Delete website
|
|
```
|
|
DELETE /api/websites/:id
|
|
```
|
|
|
|
#### Check website now
|
|
```
|
|
POST /api/websites/:id/check
|
|
```
|
|
|
|
#### Get website history
|
|
```
|
|
GET /api/websites/:id/history?limit=100
|
|
```
|
|
|
|
#### Get website status
|
|
```
|
|
GET /api/websites/:id/status
|
|
```
|
|
|
|
### Alerts
|
|
|
|
#### List all alerts
|
|
```
|
|
GET /api/alerts
|
|
```
|
|
|
|
#### Get alert by ID
|
|
```
|
|
GET /api/alerts/:id
|
|
```
|
|
|
|
#### Create alert
|
|
```
|
|
POST /api/alerts
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"website_id": 1,
|
|
"alert_type": "email",
|
|
"config": {
|
|
"to_email": "admin@example.com",
|
|
"cc_email": "client@example.com",
|
|
"subject_prefix": "[Monitor]"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Update alert
|
|
```
|
|
PUT /api/alerts/:id
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"enabled": true
|
|
}
|
|
```
|
|
|
|
#### Delete alert
|
|
```
|
|
DELETE /api/alerts/:id
|
|
```
|
|
|
|
### Stats
|
|
|
|
#### Get summary statistics
|
|
```
|
|
GET /api/stats/summary
|
|
```
|
|
|
|
## Alert Types
|
|
|
|
### Email Alerts
|
|
|
|
Configuration:
|
|
```json
|
|
{
|
|
"to_email": "recipient@example.com",
|
|
"cc_email": "cc@example.com", // optional
|
|
"subject_prefix": "[Monitor]" // optional
|
|
}
|
|
```
|
|
|
|
### Webhook Alerts
|
|
|
|
Configuration:
|
|
```json
|
|
{
|
|
"url": "https://hooks.slack.com/services/...",
|
|
"method": "POST",
|
|
"headers": {
|
|
"Content-Type": "application/json"
|
|
},
|
|
"body_template": ""
|
|
}
|
|
```
|
|
|
|
## Development
|
|
|
|
### Local Development
|
|
|
|
1. Install dependencies:
|
|
```bash
|
|
opam install . --deps-only
|
|
```
|
|
|
|
2. Build the project:
|
|
```bash
|
|
dune build
|
|
```
|
|
|
|
3. Run tests:
|
|
```bash
|
|
dune test
|
|
```
|
|
|
|
4. Run the application:
|
|
```bash
|
|
dune exec bin/main.exe
|
|
```
|
|
|
|
### Docker Development
|
|
|
|
Build with CPU constraint (1 core):
|
|
```bash
|
|
docker build --build-arg BUILDKIT_INLINE_CACHE=1 -t website_monitor .
|
|
```
|
|
|
|
Run with Docker Compose:
|
|
```bash
|
|
docker-compose up
|
|
```
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
test3/
|
|
├── bin/
|
|
│ ├── dune # Binary build configuration
|
|
│ └── main.ml # Application entry point
|
|
├── lib/
|
|
│ ├── dune # Library build configuration
|
|
│ ├── database.ml # Database models and queries
|
|
│ ├── monitor.ml # Website monitoring logic
|
|
│ ├── alert.ml # Alerting system
|
|
│ ├── api.ml # REST API handlers
|
|
│ ├── ui.ml # Server-side React UI
|
|
│ └── scheduler.ml # Background monitoring scheduler
|
|
├── docker/
|
|
│ └── Dockerfile
|
|
├── docker-compose.yml
|
|
├── dune-project
|
|
├── website_monitor.opam
|
|
├── .env.example
|
|
└── README.md
|
|
```
|
|
|
|
## Monitoring Behavior
|
|
|
|
- Websites are checked at their configured `check_interval` (default: 5 minutes)
|
|
- Failed checks trigger alerts to configured endpoints
|
|
- Recovery alerts are sent when a website returns to normal
|
|
- Check history is retained for 30 days (configurable)
|
|
- The scheduler runs every minute to check due websites
|
|
|
|
## CPU Constraints
|
|
|
|
The Docker build is configured to use only 1 CPU core:
|
|
|
|
```dockerfile
|
|
ENV OPAMJOBS=1
|
|
```
|
|
|
|
In docker-compose.yml:
|
|
```yaml
|
|
cpus: '1.0'
|
|
cpuset: '0'
|
|
```
|
|
|
|
## Security Considerations
|
|
|
|
1. **Environment Variables**: Never commit `.env` files to version control
|
|
2. **Secrets**: Use strong random strings for `SECRET_KEY`
|
|
3. **SMTP**: Use app-specific passwords, not your main password
|
|
4. **Database**: Change default passwords in production
|
|
5. **HTTPS**: Use a reverse proxy (nginx, Traefik) for HTTPS
|
|
|
|
## Troubleshooting
|
|
|
|
### Database Connection Issues
|
|
```bash
|
|
docker-compose logs postgres
|
|
```
|
|
|
|
### SMTP Issues
|
|
- Check SMTP credentials in `.env`
|
|
- Verify SMTP host and port
|
|
- Use app-specific passwords for Gmail
|
|
|
|
### High CPU Usage
|
|
- Increase `check_interval` for less frequent checks
|
|
- Reduce number of active websites
|
|
- The build is already limited to 1 CPU core
|
|
|
|
## License
|
|
|
|
MIT License - see LICENSE file for details
|
|
|
|
## Contributing
|
|
|
|
1. Fork the repository
|
|
2. Create a feature branch
|
|
3. Make your changes
|
|
4. Write tests
|
|
5. Submit a pull request
|
|
|
|
## Support
|
|
|
|
For issues and questions, please open an issue on the GitHub repository.
|