Skip to content
Closed
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
42 changes: 42 additions & 0 deletions .examples/docker-compose-mysql-storage/config/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
storage:
type: mysql
path: "${MYSQL_USER}:${MYSQL_PASSWORD}@tcp(mysql:3306)/${MYSQL_DATABASE}?charset=utf8mb4&parseTime=True&loc=Local&multiStatements=true&interpolateParams=true"

endpoints:
- name: back-end
group: core
url: "https://example.org/"
interval: 5m
conditions:
- "[STATUS] == 200"
- "[CERTIFICATE_EXPIRATION] > 48h"

- name: monitoring
group: internal
url: "https://example.org/"
interval: 5m
conditions:
- "[STATUS] == 200"

- name: nas
group: internal
url: "https://example.org/"
interval: 5m
conditions:
- "[STATUS] == 200"

- name: example-dns-query
url: "8.8.8.8" # Address of the DNS server to use
interval: 5m
dns:
query-name: "example.com"
query-type: "A"
conditions:
- "[BODY] == 93.184.215.14"
- "[DNS_RCODE] == NOERROR"

- name: icmp-ping
url: "icmp://example.org"
interval: 1m
conditions:
- "[CONNECTED] == true"
34 changes: 34 additions & 0 deletions .examples/docker-compose-mysql-storage/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
version: "3.9"
services:
mysql:
image: mysql:lts
volumes:
- ./data/db:/var/lib/mysql
ports:
- "3306:3306"
environment:
- MYSQL_DATABASE=gatus
- MYSQL_USER=username
- MYSQL_PASSWORD=password
- MYSQL_ROOT_PASSWORD=root_password
networks:
- web

gatus:
image: twinproduction/gatus:latest
restart: always
ports:
- "8080:8080"
environment:
- MYSQL_USER=username
- MYSQL_PASSWORD=password
- MYSQL_DATABASE=gatus
volumes:
- ./config:/config
networks:
- web
depends_on:
- mysql

networks:
web:
24 changes: 16 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -382,14 +382,14 @@ Here are some examples of conditions you can use:


### Storage
| Parameter | Description | Default |
|:------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------|:-----------|
| `storage` | Storage configuration | `{}` |
| `storage.path` | Path to persist the data in. Only supported for types `sqlite` and `postgres`. | `""` |
| `storage.type` | Type of storage. Valid types: `memory`, `sqlite`, `postgres`. | `"memory"` |
| `storage.caching` | Whether to use write-through caching. Improves loading time for large dashboards. <br />Only supported if `storage.type` is `sqlite` or `postgres` | `false` |
| `storage.maximum-number-of-results` | The maximum number of results that an endpoint can have | `100` |
| `storage.maximum-number-of-events` | The maximum number of events that an endpoint can have | `50` |
| Parameter | Description | Default |
|:------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------|
| `storage` | Storage configuration | `{}` |
| `storage.path` | Path to persist the data in. Only supported for types `sqlite`, `postgres` and `mysql`. | `""` |
| `storage.type` | Type of storage. Valid types: `memory`, `sqlite`, `postgres` and `mysql`. | `"memory"` |
| `storage.caching` | Whether to use write-through caching. Improves loading time for large dashboards. <br />Only supported if `storage.type` is `sqlite` or `postgres` or `mysql` | `false` |
| `storage.maximum-number-of-results` | The maximum number of results that an endpoint can have | `100` |
| `storage.maximum-number-of-events` | The maximum number of events that an endpoint can have | `50` |

The results for each endpoint health check as well as the data for uptime and the past events must be persisted
so that they can be displayed on the dashboard. These parameters allow you to configure the storage in question.
Expand Down Expand Up @@ -419,6 +419,14 @@ storage:
```
See [examples/docker-compose-postgres-storage](.examples/docker-compose-postgres-storage) for an example.

- If `storage.type` is `mysql`, `storage.path` must be the connection URL:
```yaml
storage:
type: mysql
path: "user:password@tcp(127.0.0.1:3306)/gatus?charset=utf8mb4&parseTime=True&loc=Local&multiStatements=true&interpolateParams=true"
```
See [examples/docker-compose-mysql-storage](.examples/docker-compose-mysql-storage) for an example.


### Client configuration
In order to support a wide range of environments, each monitored endpoint has a unique configuration for
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (
github.com/TwiN/whois v1.1.10
github.com/aws/aws-sdk-go v1.55.6
github.com/coreos/go-oidc/v3 v3.14.1
github.com/go-sql-driver/mysql v1.9.2
github.com/gofiber/fiber/v2 v2.52.6
github.com/google/go-github/v48 v48.2.0
github.com/google/uuid v1.6.0
Expand All @@ -35,6 +36,7 @@ require (
cloud.google.com/go/auth v0.15.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/andybalholm/brotli v1.1.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
code.gitea.io/sdk/gitea v0.19.0 h1:8I6s1s4RHgzxiPHhOQdgim1RWIRcr0LVMbHBjBFXq4Y=
code.gitea.io/sdk/gitea v0.19.0/go.mod h1:IG9xZJoltDNeDSW0qiF2Vqx5orMWa7OhVWrjvrd5NpI=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/TwiN/deepmerge v0.2.2 h1:FUG9QMIYg/j2aQyPPhA3XTFJwXSNHI/swaR4Lbyxwg4=
github.com/TwiN/deepmerge v0.2.2/go.mod h1:4OHvjV3pPNJCJZBHswYAwk6rxiD8h8YZ+9cPo7nu4oI=
github.com/TwiN/g8/v2 v2.0.0 h1:+hwIbRLMhDd2iwHzkZUPp2FkX7yTx8ddYOnS91HkDqQ=
Expand Down Expand Up @@ -46,6 +48,8 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRjiHuU=
github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI=
github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
Expand Down
2 changes: 1 addition & 1 deletion storage/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (c *Config) ValidateAndSetDefaults() error {
if c.Type == "" {
c.Type = TypeMemory
}
if (c.Type == TypePostgres || c.Type == TypeSQLite) && len(c.Path) == 0 {
if (c.Type == TypeMySQL || c.Type == TypePostgres || c.Type == TypeSQLite) && len(c.Path) == 0 {
return ErrSQLStorageRequiresPath
}
if c.Type == TypeMemory && len(c.Path) > 0 {
Expand Down
91 changes: 91 additions & 0 deletions storage/store/sql/specific_mysql.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package sql

func (s *Store) createMySQLSchema() error {
_, err := s.db.Exec(`
CREATE TABLE IF NOT EXISTS endpoints (
endpoint_id BIGINT AUTO_INCREMENT PRIMARY KEY,
endpoint_key VARCHAR(255) UNIQUE,
endpoint_name VARCHAR(255) NOT NULL,
endpoint_group VARCHAR(255) NOT NULL,
UNIQUE(endpoint_name, endpoint_group)
)
`)
if err != nil {
return err
}
_, err = s.db.Exec(`
CREATE TABLE IF NOT EXISTS endpoint_events (
endpoint_event_id BIGINT AUTO_INCREMENT PRIMARY KEY,
endpoint_id BIGINT NOT NULL,
event_type VARCHAR(255) NOT NULL,
event_timestamp DATETIME NOT NULL,
FOREIGN KEY (endpoint_id) REFERENCES endpoints(endpoint_id) ON DELETE CASCADE
)
`)
if err != nil {
return err
}
_, err = s.db.Exec(`
CREATE TABLE IF NOT EXISTS endpoint_results (
endpoint_result_id BIGINT AUTO_INCREMENT PRIMARY KEY,
endpoint_id BIGINT NOT NULL,
success BOOLEAN NOT NULL,
errors TEXT NOT NULL,
connected BOOLEAN NOT NULL,
status INT NOT NULL,
dns_rcode VARCHAR(255) NOT NULL,
certificate_expiration BIGINT NOT NULL,
domain_expiration BIGINT NOT NULL,
hostname VARCHAR(255) NOT NULL,
ip VARCHAR(255) NOT NULL,
duration BIGINT NOT NULL,
timestamp DATETIME NOT NULL,
FOREIGN KEY (endpoint_id) REFERENCES endpoints(endpoint_id) ON DELETE CASCADE
)
`)
if err != nil {
return err
}
_, err = s.db.Exec(`
CREATE TABLE IF NOT EXISTS endpoint_result_conditions (
endpoint_result_condition_id BIGINT AUTO_INCREMENT PRIMARY KEY,
endpoint_result_id BIGINT NOT NULL,
` + "`condition`" + ` TEXT NOT NULL,
success BOOLEAN NOT NULL,
FOREIGN KEY (endpoint_result_id) REFERENCES endpoint_results(endpoint_result_id) ON DELETE CASCADE
)
`)
if err != nil {
return err
}
_, err = s.db.Exec(`
CREATE TABLE IF NOT EXISTS endpoint_uptimes (
endpoint_uptime_id BIGINT AUTO_INCREMENT PRIMARY KEY,
endpoint_id BIGINT NOT NULL,
hour_unix_timestamp BIGINT NOT NULL,
total_executions BIGINT NOT NULL,
successful_executions BIGINT NOT NULL,
total_response_time BIGINT NOT NULL,
UNIQUE(endpoint_id, hour_unix_timestamp),
FOREIGN KEY (endpoint_id) REFERENCES endpoints(endpoint_id) ON DELETE CASCADE
)
`)
if err != nil {
return err
}
_, err = s.db.Exec(`
CREATE TABLE IF NOT EXISTS endpoint_alerts_triggered (
endpoint_alert_trigger_id BIGINT AUTO_INCREMENT PRIMARY KEY,
endpoint_id BIGINT NOT NULL,
configuration_checksum VARCHAR(255) NOT NULL,
resolve_key VARCHAR(255) NOT NULL,
number_of_successes_in_a_row INT NOT NULL,
UNIQUE(endpoint_id, configuration_checksum),
FOREIGN KEY (endpoint_id) REFERENCES endpoints(endpoint_id) ON DELETE CASCADE
)
`)
if err != nil {
return err
}
return nil
}
Loading