diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index d8a5337b..434ee1ab 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -2,6 +2,7 @@ namespace App\Providers; +use App\Models\User; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Gate; use App\Models\EdarateOstani; @@ -50,5 +51,9 @@ class AuthServiceProvider extends ServiceProvider return $user->can('supervise-fast-react') || ($user->can('supervise-fast-react-province') && $road_observed->province_id == $user->province_id); }); + + Gate::define('viewPulse', function (User $user) { + return $user->username == 'witel'; + }); } } diff --git a/bootstrap/cache/packages.php b/bootstrap/cache/packages.php index 9ba8eb78..58a2a104 100755 --- a/bootstrap/cache/packages.php +++ b/bootstrap/cache/packages.php @@ -28,6 +28,17 @@ 0 => 'KitLoong\\MigrationsGenerator\\MigrationsGeneratorServiceProvider', ), ), + 'laravel/pulse' => + array ( + 'aliases' => + array ( + 'Pulse' => 'Laravel\\Pulse\\Facades\\Pulse', + ), + 'providers' => + array ( + 0 => 'Laravel\\Pulse\\PulseServiceProvider', + ), + ), 'laravel/sail' => array ( 'providers' => @@ -63,6 +74,17 @@ 0 => 'Laravel\\Ui\\UiServiceProvider', ), ), + 'livewire/livewire' => + array ( + 'aliases' => + array ( + 'Livewire' => 'Livewire\\Livewire', + ), + 'providers' => + array ( + 0 => 'Livewire\\LivewireServiceProvider', + ), + ), 'maatwebsite/excel' => array ( 'providers' => diff --git a/bootstrap/cache/services.php b/bootstrap/cache/services.php index 13560d20..da457a76 100755 --- a/bootstrap/cache/services.php +++ b/bootstrap/cache/services.php @@ -26,26 +26,28 @@ 22 => 'Barryvdh\\Debugbar\\ServiceProvider', 23 => 'Hekmatinasser\\Verta\\Laravel\\VertaServiceProvider', 24 => 'KitLoong\\MigrationsGenerator\\MigrationsGeneratorServiceProvider', - 25 => 'Laravel\\Sail\\SailServiceProvider', - 26 => 'Laravel\\Sanctum\\SanctumServiceProvider', - 27 => 'Laravel\\Telescope\\TelescopeServiceProvider', - 28 => 'Laravel\\Tinker\\TinkerServiceProvider', - 29 => 'Laravel\\Ui\\UiServiceProvider', - 30 => 'Maatwebsite\\Excel\\ExcelServiceProvider', - 31 => 'Carbon\\Laravel\\ServiceProvider', - 32 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider', - 33 => 'Termwind\\Laravel\\TermwindServiceProvider', - 34 => 'Spatie\\LaravelIgnition\\IgnitionServiceProvider', - 35 => 'Spatie\\Permission\\PermissionServiceProvider', - 36 => 'Spatie\\Permission\\PermissionServiceProvider', - 37 => 'App\\Providers\\AppServiceProvider', - 38 => 'App\\Providers\\AuthServiceProvider', - 39 => 'App\\Providers\\EventServiceProvider', - 40 => 'App\\Providers\\RouteServiceProvider', - 41 => 'App\\Providers\\TelescopeServiceProvider', - 42 => 'Barryvdh\\Debugbar\\ServiceProvider', - 43 => 'App\\Providers\\DataTableServiceProvider', - 44 => 'App\\Providers\\FileServiceProvider', + 25 => 'Laravel\\Pulse\\PulseServiceProvider', + 26 => 'Laravel\\Sail\\SailServiceProvider', + 27 => 'Laravel\\Sanctum\\SanctumServiceProvider', + 28 => 'Laravel\\Telescope\\TelescopeServiceProvider', + 29 => 'Laravel\\Tinker\\TinkerServiceProvider', + 30 => 'Laravel\\Ui\\UiServiceProvider', + 31 => 'Livewire\\LivewireServiceProvider', + 32 => 'Maatwebsite\\Excel\\ExcelServiceProvider', + 33 => 'Carbon\\Laravel\\ServiceProvider', + 34 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider', + 35 => 'Termwind\\Laravel\\TermwindServiceProvider', + 36 => 'Spatie\\LaravelIgnition\\IgnitionServiceProvider', + 37 => 'Spatie\\Permission\\PermissionServiceProvider', + 38 => 'Spatie\\Permission\\PermissionServiceProvider', + 39 => 'App\\Providers\\AppServiceProvider', + 40 => 'App\\Providers\\AuthServiceProvider', + 41 => 'App\\Providers\\EventServiceProvider', + 42 => 'App\\Providers\\RouteServiceProvider', + 43 => 'App\\Providers\\TelescopeServiceProvider', + 44 => 'Barryvdh\\Debugbar\\ServiceProvider', + 45 => 'App\\Providers\\DataTableServiceProvider', + 46 => 'App\\Providers\\FileServiceProvider', ), 'eager' => array ( @@ -62,24 +64,26 @@ 10 => 'Barryvdh\\Debugbar\\ServiceProvider', 11 => 'Hekmatinasser\\Verta\\Laravel\\VertaServiceProvider', 12 => 'KitLoong\\MigrationsGenerator\\MigrationsGeneratorServiceProvider', - 13 => 'Laravel\\Sanctum\\SanctumServiceProvider', - 14 => 'Laravel\\Telescope\\TelescopeServiceProvider', - 15 => 'Laravel\\Ui\\UiServiceProvider', - 16 => 'Maatwebsite\\Excel\\ExcelServiceProvider', - 17 => 'Carbon\\Laravel\\ServiceProvider', - 18 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider', - 19 => 'Termwind\\Laravel\\TermwindServiceProvider', - 20 => 'Spatie\\LaravelIgnition\\IgnitionServiceProvider', - 21 => 'Spatie\\Permission\\PermissionServiceProvider', - 22 => 'Spatie\\Permission\\PermissionServiceProvider', - 23 => 'App\\Providers\\AppServiceProvider', - 24 => 'App\\Providers\\AuthServiceProvider', - 25 => 'App\\Providers\\EventServiceProvider', - 26 => 'App\\Providers\\RouteServiceProvider', - 27 => 'App\\Providers\\TelescopeServiceProvider', - 28 => 'Barryvdh\\Debugbar\\ServiceProvider', - 29 => 'App\\Providers\\DataTableServiceProvider', - 30 => 'App\\Providers\\FileServiceProvider', + 13 => 'Laravel\\Pulse\\PulseServiceProvider', + 14 => 'Laravel\\Sanctum\\SanctumServiceProvider', + 15 => 'Laravel\\Telescope\\TelescopeServiceProvider', + 16 => 'Laravel\\Ui\\UiServiceProvider', + 17 => 'Livewire\\LivewireServiceProvider', + 18 => 'Maatwebsite\\Excel\\ExcelServiceProvider', + 19 => 'Carbon\\Laravel\\ServiceProvider', + 20 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider', + 21 => 'Termwind\\Laravel\\TermwindServiceProvider', + 22 => 'Spatie\\LaravelIgnition\\IgnitionServiceProvider', + 23 => 'Spatie\\Permission\\PermissionServiceProvider', + 24 => 'Spatie\\Permission\\PermissionServiceProvider', + 25 => 'App\\Providers\\AppServiceProvider', + 26 => 'App\\Providers\\AuthServiceProvider', + 27 => 'App\\Providers\\EventServiceProvider', + 28 => 'App\\Providers\\RouteServiceProvider', + 29 => 'App\\Providers\\TelescopeServiceProvider', + 30 => 'Barryvdh\\Debugbar\\ServiceProvider', + 31 => 'App\\Providers\\DataTableServiceProvider', + 32 => 'App\\Providers\\FileServiceProvider', ), 'deferred' => array ( diff --git a/composer.json b/composer.json index 05a8958e..825d349e 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,7 @@ "guzzlehttp/guzzle": "^7.2", "hekmatinasser/verta": "^8.3", "laravel/framework": "^10.10", + "laravel/pulse": "^1.0@beta", "laravel/sanctum": "^3.2", "laravel/telescope": "^4.17", "laravel/tinker": "^2.8", @@ -76,6 +77,6 @@ "php-http/discovery": true } }, - "minimum-stability": "stable", + "minimum-stability": "beta", "prefer-stable": true } diff --git a/composer.lock b/composer.lock index 7c8ba57f..406835fc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f354c54643bedde32669099052baa40c", + "content-hash": "fb6adbe1f5e02aaf3de31c514710f0b6", "packages": [ { "name": "beberlei/assert", @@ -865,6 +865,61 @@ ], "time": "2022-12-15T16:57:16+00:00" }, + { + "name": "doctrine/sql-formatter", + "version": "1.5.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/sql-formatter.git", + "reference": "d6d00aba6fd2957fe5216fe2b7673e9985db20c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/d6d00aba6fd2957fe5216fe2b7673e9985db20c8", + "reference": "d6d00aba6fd2957fe5216fe2b7673e9985db20c8", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "ergebnis/phpunit-slow-test-detector": "^2.14", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5" + }, + "bin": [ + "bin/sql-formatter" + ], + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\SqlFormatter\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeremy Dorn", + "email": "jeremy@jeremydorn.com", + "homepage": "https://jeremydorn.com/" + } + ], + "description": "a PHP SQL highlighting library", + "homepage": "https://github.com/doctrine/sql-formatter/", + "keywords": [ + "highlight", + "sql" + ], + "support": { + "issues": "https://github.com/doctrine/sql-formatter/issues", + "source": "https://github.com/doctrine/sql-formatter/tree/1.5.2" + }, + "time": "2025-01-24T11:45:48+00:00" + }, { "name": "dragonmantank/cron-expression", "version": "v3.3.3", @@ -2043,6 +2098,92 @@ }, "time": "2023-12-29T22:37:42+00:00" }, + { + "name": "laravel/pulse", + "version": "v1.0.0-beta15", + "source": { + "type": "git", + "url": "https://github.com/laravel/pulse.git", + "reference": "6fc88b3ead77fd1c67428f0c0fa6ac2ec5302e2b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pulse/zipball/6fc88b3ead77fd1c67428f0c0fa6ac2ec5302e2b", + "reference": "6fc88b3ead77fd1c67428f0c0fa6ac2ec5302e2b", + "shasum": "" + }, + "require": { + "doctrine/sql-formatter": "^1.1", + "guzzlehttp/promises": "^1.0|^2.0", + "illuminate/auth": "^10.34|^11.0", + "illuminate/cache": "^10.34|^11.0", + "illuminate/config": "^10.34|^11.0", + "illuminate/console": "^10.34|^11.0", + "illuminate/contracts": "^10.34|^11.0", + "illuminate/database": "^10.34|^11.0", + "illuminate/events": "^10.34|^11.0", + "illuminate/http": "^10.34|^11.0", + "illuminate/queue": "^10.34|^11.0", + "illuminate/redis": "^10.34|^11.0", + "illuminate/routing": "^10.34|^11.0", + "illuminate/support": "^10.34|^11.0", + "illuminate/view": "^10.34|^11.0", + "livewire/livewire": "^3.2", + "nesbot/carbon": "^2.67|^3.0", + "php": "^8.1" + }, + "conflict": { + "nunomaduro/collision": "<7.7.0" + }, + "require-dev": { + "guzzlehttp/guzzle": "^7.7", + "mockery/mockery": "^1.0", + "orchestra/testbench": "^8.16|^9.0", + "pestphp/pest": "^2.0", + "pestphp/pest-plugin-laravel": "^2.2", + "phpstan/phpstan": "^1.11", + "predis/predis": "^1.0|^2.0" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Pulse": "Laravel\\Pulse\\Facades\\Pulse" + }, + "providers": [ + "Laravel\\Pulse\\PulseServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Pulse\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.", + "homepage": "https://github.com/laravel/pulse", + "keywords": [ + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/pulse/issues", + "source": "https://github.com/laravel/pulse" + }, + "time": "2024-03-11T13:19:11+00:00" + }, { "name": "laravel/sanctum", "version": "v3.3.3", @@ -2762,6 +2903,82 @@ ], "time": "2024-01-28T23:22:08+00:00" }, + { + "name": "livewire/livewire", + "version": "v3.5.4", + "source": { + "type": "git", + "url": "https://github.com/livewire/livewire.git", + "reference": "b158c6386a892efc6c5e4682e682829baac1f933" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/livewire/livewire/zipball/b158c6386a892efc6c5e4682e682829baac1f933", + "reference": "b158c6386a892efc6c5e4682e682829baac1f933", + "shasum": "" + }, + "require": { + "illuminate/database": "^10.0|^11.0", + "illuminate/routing": "^10.0|^11.0", + "illuminate/support": "^10.0|^11.0", + "illuminate/validation": "^10.0|^11.0", + "league/mime-type-detection": "^1.9", + "php": "^8.1", + "symfony/console": "^6.0|^7.0", + "symfony/http-kernel": "^6.2|^7.0" + }, + "require-dev": { + "calebporzio/sushi": "^2.1", + "laravel/framework": "^10.15.0|^11.0", + "laravel/prompts": "^0.1.6", + "mockery/mockery": "^1.3.1", + "orchestra/testbench": "^8.21.0|^9.0", + "orchestra/testbench-dusk": "^8.24|^9.1", + "phpunit/phpunit": "^10.4", + "psy/psysh": "^0.11.22|^0.12" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Livewire": "Livewire\\Livewire" + }, + "providers": [ + "Livewire\\LivewireServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Livewire\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Caleb Porzio", + "email": "calebporzio@gmail.com" + } + ], + "description": "A front-end framework for Laravel.", + "support": { + "issues": "https://github.com/livewire/livewire/issues", + "source": "https://github.com/livewire/livewire/tree/v3.5.4" + }, + "funding": [ + { + "url": "https://github.com/livewire", + "type": "github" + } + ], + "time": "2024-07-15T18:27:32+00:00" + }, { "name": "maatwebsite/excel", "version": "3.1.52", @@ -9807,14 +10024,16 @@ } ], "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], + "minimum-stability": "beta", + "stability-flags": { + "laravel/pulse": 10 + }, "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.1", "ext-zip": "*" }, - "platform-dev": [], + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/config/pulse.php b/config/pulse.php new file mode 100644 index 00000000..2eb95ccc --- /dev/null +++ b/config/pulse.php @@ -0,0 +1,233 @@ + env('PULSE_DOMAIN'), + + /* + |-------------------------------------------------------------------------- + | Pulse Path + |-------------------------------------------------------------------------- + | + | This is the path which the Pulse dashboard will be accessible from. Feel + | free to change this path to anything you'd like. Note that this won't + | affect the path of the internal API that is never exposed to users. + | + */ + + 'path' => env('PULSE_PATH', 'pulse'), + + /* + |-------------------------------------------------------------------------- + | Pulse Master Switch + |-------------------------------------------------------------------------- + | + | This configuration option may be used to completely disable all Pulse + | data recorders regardless of their individual configurations. This + | provides a single option to quickly disable all Pulse recording. + | + */ + + 'enabled' => env('PULSE_ENABLED', true), + + /* + |-------------------------------------------------------------------------- + | Pulse Storage Driver + |-------------------------------------------------------------------------- + | + | This configuration option determines which storage driver will be used + | while storing entries from Pulse's recorders. In addition, you also + | may provide any options to configure the selected storage driver. + | + */ + + 'storage' => [ + 'driver' => env('PULSE_STORAGE_DRIVER', 'database'), + + 'database' => [ + 'connection' => env('PULSE_DB_CONNECTION', null), + 'chunk' => 1000, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Pulse Ingest Driver + |-------------------------------------------------------------------------- + | + | This configuration options determines the ingest driver that will be used + | to capture entries from Pulse's recorders. Ingest drivers are great to + | free up your request workers quickly by offloading the data storage. + | + */ + + 'ingest' => [ + 'driver' => env('PULSE_INGEST_DRIVER', 'storage'), + + 'buffer' => env('PULSE_INGEST_BUFFER', 5_000), + + 'trim' => [ + 'lottery' => [1, 1_000], + 'keep' => '7 days', + ], + + 'redis' => [ + 'connection' => env('PULSE_REDIS_CONNECTION'), + 'chunk' => 1000, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Pulse Cache Driver + |-------------------------------------------------------------------------- + | + | This configuration option determines the cache driver that will be used + | for various tasks, including caching dashboard results, establishing + | locks for events that should only occur on one server and signals. + | + */ + + 'cache' => env('PULSE_CACHE_DRIVER'), + + /* + |-------------------------------------------------------------------------- + | Pulse Route Middleware + |-------------------------------------------------------------------------- + | + | These middleware will be assigned to every Pulse route, giving you the + | chance to add your own middleware to this list or change any of the + | existing middleware. Of course, reasonable defaults are provided. + | + */ + + 'middleware' => [ + 'web', + Authorize::class, + ], + + /* + |-------------------------------------------------------------------------- + | Pulse Recorders + |-------------------------------------------------------------------------- + | + | The following array lists the "recorders" that will be registered with + | Pulse, along with their configuration. Recorders gather application + | event data from requests and tasks to pass to your ingest driver. + | + */ + + 'recorders' => [ + Recorders\CacheInteractions::class => [ + 'enabled' => env('PULSE_CACHE_INTERACTIONS_ENABLED', true), + 'sample_rate' => env('PULSE_CACHE_INTERACTIONS_SAMPLE_RATE', 1), + 'ignore' => [ + ...Pulse::defaultVendorCacheKeys(), + ], + 'groups' => [ + '/^job-exceptions:.*/' => 'job-exceptions:*', + // '/:\d+/' => ':*', + ], + ], + + Recorders\Exceptions::class => [ + 'enabled' => env('PULSE_EXCEPTIONS_ENABLED', true), + 'sample_rate' => env('PULSE_EXCEPTIONS_SAMPLE_RATE', 1), + 'location' => env('PULSE_EXCEPTIONS_LOCATION', true), + 'ignore' => [ + // '/^Package\\\\Exceptions\\\\/', + ], + ], + + Recorders\Queues::class => [ + 'enabled' => env('PULSE_QUEUES_ENABLED', true), + 'sample_rate' => env('PULSE_QUEUES_SAMPLE_RATE', 1), + 'ignore' => [ + // '/^Package\\\\Jobs\\\\/', + ], + ], + + Recorders\Servers::class => [ + 'server_name' => env('PULSE_SERVER_NAME', gethostname()), + 'directories' => explode(':', env('PULSE_SERVER_DIRECTORIES', '/')), + ], + + Recorders\SlowJobs::class => [ + 'enabled' => env('PULSE_SLOW_JOBS_ENABLED', true), + 'sample_rate' => env('PULSE_SLOW_JOBS_SAMPLE_RATE', 1), + 'threshold' => env('PULSE_SLOW_JOBS_THRESHOLD', 1000), + 'ignore' => [ + // '/^Package\\\\Jobs\\\\/', + ], + ], + + Recorders\SlowOutgoingRequests::class => [ + 'enabled' => env('PULSE_SLOW_OUTGOING_REQUESTS_ENABLED', true), + 'sample_rate' => env('PULSE_SLOW_OUTGOING_REQUESTS_SAMPLE_RATE', 1), + 'threshold' => env('PULSE_SLOW_OUTGOING_REQUESTS_THRESHOLD', 1000), + 'ignore' => [ + // '#^http://127\.0\.0\.1:13714#', // Inertia SSR... + ], + 'groups' => [ + // '#^https://api\.github\.com/repos/.*$#' => 'api.github.com/repos/*', + // '#^https?://([^/]*).*$#' => '\1', + // '#/\d+#' => '/*', + ], + ], + + Recorders\SlowQueries::class => [ + 'enabled' => env('PULSE_SLOW_QUERIES_ENABLED', true), + 'sample_rate' => env('PULSE_SLOW_QUERIES_SAMPLE_RATE', 1), + 'threshold' => env('PULSE_SLOW_QUERIES_THRESHOLD', 1000), + 'location' => env('PULSE_SLOW_QUERIES_LOCATION', true), + 'highlighting' => env('PULSE_SLOW_QUERIES_HIGHLIGHTING', true), + 'max_query_length' => env('PULSE_SLOW_QUERIES_MAX_QUERY_LENGTH', null), + 'ignore' => [ + '/(["`])pulse_[\w]+?\1/', // Pulse tables... + '/(["`])telescope_[\w]+?\1/', // Telescope tables... + ], + ], + + Recorders\SlowRequests::class => [ + 'enabled' => env('PULSE_SLOW_REQUESTS_ENABLED', true), + 'sample_rate' => env('PULSE_SLOW_REQUESTS_SAMPLE_RATE', 1), + 'threshold' => env('PULSE_SLOW_REQUESTS_THRESHOLD', 1000), + 'ignore' => [ + '#^/pulse$#', // Pulse dashboard... + '#^/telescope#', // Telescope dashboard... + ], + ], + + Recorders\UserJobs::class => [ + 'enabled' => env('PULSE_USER_JOBS_ENABLED', true), + 'sample_rate' => env('PULSE_USER_JOBS_SAMPLE_RATE', 1), + 'ignore' => [ + // '/^Package\\\\Jobs\\\\/', + ], + ], + + Recorders\UserRequests::class => [ + 'enabled' => env('PULSE_USER_REQUESTS_ENABLED', true), + 'sample_rate' => env('PULSE_USER_REQUESTS_SAMPLE_RATE', 1), + 'ignore' => [ + '#^/pulse$#', // Pulse dashboard... + '#^/telescope#', // Telescope dashboard... + ], + ], + ], +]; diff --git a/database/migrations/2023_06_07_000001_create_pulse_tables.php b/database/migrations/2023_06_07_000001_create_pulse_tables.php new file mode 100644 index 00000000..f75b51e4 --- /dev/null +++ b/database/migrations/2023_06_07_000001_create_pulse_tables.php @@ -0,0 +1,84 @@ +shouldRun()) { + return; + } + + Schema::create('pulse_values', function (Blueprint $table) { + $table->id(); + $table->unsignedInteger('timestamp'); + $table->string('type'); + $table->mediumText('key'); + match ($this->driver()) { + 'mysql' => $table->char('key_hash', 16)->charset('binary')->virtualAs('unhex(md5(`key`))'), + 'pgsql' => $table->uuid('key_hash')->storedAs('md5("key")::uuid'), + 'sqlite' => $table->string('key_hash'), + }; + $table->mediumText('value'); + + $table->index('timestamp'); // For trimming... + $table->index('type'); // For fast lookups and purging... + $table->unique(['type', 'key_hash']); // For data integrity and upserts... + }); + + Schema::create('pulse_entries', function (Blueprint $table) { + $table->id(); + $table->unsignedInteger('timestamp'); + $table->string('type'); + $table->mediumText('key'); + match ($this->driver()) { + 'mysql' => $table->char('key_hash', 16)->charset('binary')->virtualAs('unhex(md5(`key`))'), + 'pgsql' => $table->uuid('key_hash')->storedAs('md5("key")::uuid'), + 'sqlite' => $table->string('key_hash'), + }; + $table->bigInteger('value')->nullable(); + + $table->index('timestamp'); // For trimming... + $table->index('type'); // For purging... + $table->index('key_hash'); // For mapping... + $table->index(['timestamp', 'type', 'key_hash', 'value']); // For aggregate queries... + }); + + Schema::create('pulse_aggregates', function (Blueprint $table) { + $table->id(); + $table->unsignedInteger('bucket'); + $table->unsignedMediumInteger('period'); + $table->string('type'); + $table->mediumText('key'); + match ($this->driver()) { + 'mysql' => $table->char('key_hash', 16)->charset('binary')->virtualAs('unhex(md5(`key`))'), + 'pgsql' => $table->uuid('key_hash')->storedAs('md5("key")::uuid'), + 'sqlite' => $table->string('key_hash'), + }; + $table->string('aggregate'); + $table->decimal('value', 20, 2); + $table->unsignedInteger('count')->nullable(); + + $table->unique(['bucket', 'period', 'type', 'aggregate', 'key_hash']); // Force "on duplicate update"... + $table->index(['period', 'bucket']); // For trimming... + $table->index('type'); // For purging... + $table->index(['period', 'type', 'aggregate', 'bucket']); // For aggregate queries... + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('pulse_values'); + Schema::dropIfExists('pulse_entries'); + Schema::dropIfExists('pulse_aggregates'); + } +};