Skip to content

Commit

Permalink
Merge pull request #151 from ralphjsmit/rjs/add-database-size-check
Browse files Browse the repository at this point in the history
Add DatabaseSizeCheck
  • Loading branch information
freekmurze authored Jan 25, 2023
2 parents 6411fab + 157c960 commit f6707fa
Show file tree
Hide file tree
Showing 16 changed files with 154 additions and 15 deletions.
39 changes: 39 additions & 0 deletions docs/available-checks/db-size-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
title: DB size
weight: 7
---

This check makes sure that your database is not too big. This check supports MySQL and Postgres.

If the database is larger than the specified maximum, this check will fail.

## Requirements

You'll need to install the `doctrine/dbal` package in your project.

```bash
composer require doctrine/dbal
```


## Usage

Here's how you can register the check.

```php
use Spatie\Health\Facades\Health;
use Spatie\Health\Checks\Checks\DatabaseSizeCheck;

Health::checks([
DatabaseSizeCheck::new()
->failWhenSizeAboveGb(errorThresholdGb: 5.0)
]);
```

### Specifying the database connection

To check another database connection, call `connectionName()`

```php
DatabaseSizeCheck::new()->connectionName('another-connection-name')->failWhenSizeAboveGb(5.0),
```
2 changes: 1 addition & 1 deletion docs/available-checks/db-table-size-check.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: DB table size
weight: 7
weight: 8
---

This check makes sure the tables of your database are not too big. This check supports MySQL and Postgres.
Expand Down
2 changes: 1 addition & 1 deletion docs/available-checks/debug-mode.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Debug mode
weight: 8
weight: 9
---

This check will make sure that debug mode is set to `false`. It will fail when debug mode is `true`.
Expand Down
2 changes: 1 addition & 1 deletion docs/available-checks/environment.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Environment
weight: 9
weight: 10
---

This check will make sure your application is running used the right environment. By default, this check will fail when the environment is not equal to `production`.
Expand Down
2 changes: 1 addition & 1 deletion docs/available-checks/flare-error-count.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Flare error count
weight: 10
weight: 11
---

This check will monitor the amount of errors and exceptions your application throws. For this check you'll need to have an account on [Flare](https://flareapp.io).
Expand Down
2 changes: 1 addition & 1 deletion docs/available-checks/horizon.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Horizon
weight: 11
weight: 12
---

This check will make sure Horizon is running. It will report a warning when Horizon is paused, and a failure when Horizon is not running.
Expand Down
2 changes: 1 addition & 1 deletion docs/available-checks/meilisearch.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: MeiliSearch
weight: 12
weight: 13
---

This check will verify if MeiliSearch is running. It will call MeiliSearch's [built-in health endpoint](https://docs.meilisearch.com/reference/api/health.html) and verify that its status returns `available`.
Expand Down
2 changes: 1 addition & 1 deletion docs/available-checks/ping.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Ping
weight: 13
weight: 14
---

This check will send a request to a given URL. It will report a failure when that URL doesn't respond with a successful response code within a second.
Expand Down
2 changes: 1 addition & 1 deletion docs/available-checks/queue.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Queue
weight: 14
weight: 15
---

This check will make sure that queued jobs are running. This check works by dispatching a test job (this will be done via a scheduled command), and verify if that test job is handled on time.
Expand Down
2 changes: 1 addition & 1 deletion docs/available-checks/redis.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Redis
weight: 15
weight: 16
---

This check will make sure Redis is running. By default, this check will make sure the `default` connection is working.
Expand Down
2 changes: 1 addition & 1 deletion docs/available-checks/schedule.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Schedule
weight: 16
weight: 17
---

This check will make sure the schedule is running. If the check detects that the schedule is not run every minute, it will fail.
Expand Down
2 changes: 1 addition & 1 deletion docs/available-checks/security-advisories.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Security advisories
weight: 17
weight: 18
---

This check will check if the PHP packages installed in your project have known security vulnerabilities. This check works using [Packagist's security vulnerability API](https://php.watch/articles/composer-audit#packagist-vuln-list-api).
Expand Down
2 changes: 1 addition & 1 deletion docs/available-checks/used-disk-space.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Used disk space
weight: 18
weight: 19
---

This check will monitor the percentage of available disk space.
Expand Down
54 changes: 54 additions & 0 deletions src/Checks/Checks/DatabaseSizeCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace Spatie\Health\Checks\Checks;

use Illuminate\Database\ConnectionResolverInterface;
use Spatie\Health\Checks\Check;
use Spatie\Health\Checks\Result;
use Spatie\Health\Support\DbConnectionInfo;

class DatabaseSizeCheck extends Check
{
protected ?string $connectionName = null;

protected float $failWhenSizeAboveGb = 1;

public function connectionName(string $connectionName): self
{
$this->connectionName = $connectionName;

return $this;
}

public function failWhenSizeAboveGb(float $errorThresholdGb): self
{
$this->failWhenSizeAboveGb = $errorThresholdGb;

return $this;
}

public function run(): Result
{
$result = Result::make();

$databaseSizeInGb = $this->getDatabaseSizeInGb();

return $databaseSizeInGb >= $this->failWhenSizeAboveGb
? $result->failed("Database size is {$databaseSizeInGb} GB, which is above the threshold of {$this->failWhenSizeAboveGb} GB")
: $result->ok("{$databaseSizeInGb} GB");
}

protected function getDefaultConnectionName(): string
{
return config('database.default');
}

protected function getDatabaseSizeInGb(): float
{
$connectionName = $this->connectionName ?? $this->getDefaultConnectionName();

$connection = app(ConnectionResolverInterface::class)->connection($connectionName);

return round((new DbConnectionInfo())->databaseSizeInMb($connection) / 1000, 2);
}
}
29 changes: 26 additions & 3 deletions src/Support/DbConnectionInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ class DbConnectionInfo
public function connectionCount(ConnectionInterface $connection): int
{
return match (true) {
$connection instanceof MySqlConnection => (int) $connection->selectOne($connection->raw('show status where variable_name = "threads_connected"'))->Value,
$connection instanceof PostgresConnection => (int) $connection->selectOne('select count(*) as connections from pg_stat_activity')->connections,
default => throw new DatabaseNotSupported()
$connection instanceof MySqlConnection => (int)$connection->selectOne($connection->raw('show status where variable_name = "threads_connected"'))->Value,
$connection instanceof PostgresConnection => (int)$connection->selectOne('select count(*) as connections from pg_stat_activity')->connections,
default => throw DatabaseNotSupported::make($connection),
};
}

Expand All @@ -29,6 +29,15 @@ public function tableSizeInMb(ConnectionInterface $connection, string $table): f
return $sizeInBytes / 1024 / 1024;
}

public function databaseSizeInMb(ConnectionInterface $connection): float
{
return match (true) {
$connection instanceof MySqlConnection => $this->getMySQlDatabaseSize($connection),
$connection instanceof PostgresConnection => $this->getPostgresDatabaseSize($connection),
default => throw DatabaseNotSupported::make($connection),
};
}

protected function getMySQLTableSize(ConnectionInterface $connection, string $table): int
{
return $connection->selectOne('SELECT (data_length + index_length) AS size FROM information_schema.TABLES WHERE table_schema = ? AND table_name = ?', [
Expand All @@ -43,4 +52,18 @@ protected function getPostgresTableSize(ConnectionInterface $connection, string
$table,
])->size;
}

protected function getMySQLDatabaseSize(ConnectionInterface $connection): int
{
return $connection->selectOne('SELECT size from (SELECT table_schema "name", ROUND(SUM(data_length + index_length) / 1024 / 1024, 1) as size FROM information_schema.tables GROUP BY table_schema) alias_one where name = ?', [
$connection->getDatabaseName(),
])->size;
}

protected function getPostgresDatabaseSize(ConnectionInterface $connection): int
{
return $connection->selectOne('SELECT pg_size_pretty(pg_database_size(?)) AS size;', [
$connection->getDatabaseName(),
])->size;
}
}
23 changes: 23 additions & 0 deletions tests/Checks/DatabaseSizeCheckTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

use Illuminate\Support\Facades\DB;
use Spatie\Health\Checks\Checks\DatabaseSizeCheck;
use Spatie\Health\Enums\Status;

it('will determine that database size is ok if it does not cross the maximum', function () {
$result = DatabaseSizeCheck::new()
->connectionName('mysql')
->failWhenSizeAboveGb(50)
->run();

expect($result->status)->toBe(Status::ok());
});

it('will determine that database size is not ok if it does cross the maximum', function () {
$result = DatabaseSizeCheck::new()
->connectionName('mysql')
->failWhenSizeAboveGb(0)
->run();

expect($result->status)->toBe(Status::failed());
});

0 comments on commit f6707fa

Please sign in to comment.