diff --git a/.gitignore b/.gitignore
index 0ba21f1..21dabd5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
.php_cs
.php_cs.cache
.phpunit.result.cache
+.phpunit.cache
build
composer.lock
coverage
diff --git a/README.md b/README.md
index 5e2ca41..c3d6d12 100644
--- a/README.md
+++ b/README.md
@@ -147,6 +147,7 @@ This package works as follows:
- `team_id`: The team id associated with the request (if available)
- `method`: The HTTP method (`GET/POST/...`)
- `route`: The route name (if available) or the route URI (eg `/posts/{post}`)
+ - `parameters`: The route parameters passed (if enabled else `null`)
- `status`: The HTTP status (eg `202`)
- `ip`: The request ip
- `date`: The date of the request as datetime (can be aggregated)
diff --git a/config/route-statistics.php b/config/route-statistics.php
index 6c7d5d3..dc80025 100644
--- a/config/route-statistics.php
+++ b/config/route-statistics.php
@@ -12,6 +12,16 @@
*/
'enabled' => env('ROUTE_STATISTICS_ENABLED', true),
+ /*
+ |--------------------------------------------------------------------------
+ | Store parameters
+ |--------------------------------------------------------------------------
+ |
+ | If this setting is set to true the route parameters will also be logged.
+ |
+ */
+ 'store_route_parameters' => env('ROUTE_STATISTICS_STORE_ROUTE_PARAMETERS', false),
+
/*
|--------------------------------------------------------------------------
| Aggregation
diff --git a/database/factories/RouteStatisticFactory.php b/database/factories/RouteStatisticFactory.php
index e64e413..68c54f0 100644
--- a/database/factories/RouteStatisticFactory.php
+++ b/database/factories/RouteStatisticFactory.php
@@ -15,6 +15,7 @@ public function definition()
'method' => $this->faker->randomElement(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']),
'route' => $this->faker->domainWord().'.'.$this->faker->randomElement(['index', 'create', 'store', 'show', 'edit', 'update', 'destroy']),
'status' => $this->faker->randomElement([200, 201, 202, 204, 300, 301, 302, 303, 304, 400, 401, 402, 403, 404, 405, 406, 422, 429, 500, 501, 502, 503, 504]),
+ 'parameters' => $this->faker->json(),
'ip' => $this->faker->ipv4(),
'date' => $this->faker->dateTime(),
'counter' => $this->faker->randomNumber(4),
diff --git a/database/migrations/add_parameters_to_route_statistics_table.php.stub b/database/migrations/add_parameters_to_route_statistics_table.php.stub
new file mode 100644
index 0000000..5879ad9
--- /dev/null
+++ b/database/migrations/add_parameters_to_route_statistics_table.php.stub
@@ -0,0 +1,22 @@
+json('parameters')->after('route')->nullable();
+ });
+ }
+
+ public function down()
+ {
+ Schema::table('route_statistics', function (Blueprint $table) {
+ $table->dropColumn('parameters');
+ });
+ }
+};
diff --git a/src/Commands/LaravelRouteStatisticsCommand.php b/src/Commands/LaravelRouteStatisticsCommand.php
index c3738ff..43f13e4 100644
--- a/src/Commands/LaravelRouteStatisticsCommand.php
+++ b/src/Commands/LaravelRouteStatisticsCommand.php
@@ -2,6 +2,7 @@
namespace Bilfeldt\LaravelRouteStatistics\Commands;
+use Bilfeldt\LaravelRouteStatistics\Models\RouteStatistic;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
@@ -40,11 +41,16 @@ public function handle()
$this->applyGrouping($query);
$this->applySorting($query);
- $results = $query->limit($this->option('limit'))->get();
+ $fields = $this->getFields();
+
+ $results = $query
+ ->limit($this->option('limit'))
+ ->get()
+ ->map(fn (RouteStatistic $model): array => $this->toTableRow($model, $fields));
$this->table(
- $this->getFields(),
- $results->toArray()
+ $fields,
+ $results
);
return Command::SUCCESS;
@@ -111,16 +117,30 @@ protected function getFields(): array
return array_merge($this->option('group'), ['last_used', 'counter']);
}
- return [
+ return array_filter([
'id',
'user_id',
'team_id',
'method',
'route',
'status',
+ config('route-statistics.store_route_parameters') === true ? 'parameters' : null,
'ip',
'date',
'counter',
- ];
+ ]);
+ }
+
+ /**
+ * @param RouteStatistic $model
+ * @param $fields array
+ * @return array
+ */
+ protected function toTableRow(RouteStatistic $model, array $fields): array
+ {
+ return array_map(
+ fn (mixed $item): mixed => is_array($item) ? json_encode($item) : $item,
+ $model->only($fields)
+ );
}
}
diff --git a/src/LaravelRouteStatisticsServiceProvider.php b/src/LaravelRouteStatisticsServiceProvider.php
index e74dc1f..5730063 100644
--- a/src/LaravelRouteStatisticsServiceProvider.php
+++ b/src/LaravelRouteStatisticsServiceProvider.php
@@ -60,6 +60,7 @@ private function publishMigrations()
{
$this->publishes([
__DIR__.'/../database/migrations/create_route_statistics_table.php.stub' => database_path('migrations/'.date('Y_m_d_His', time()).'_create_route_statistics_table.php'),
+ __DIR__.'/../database/migrations/add_parameters_to_route_statistics_table.php.stub' => database_path('migrations/'.date('Y_m_d_His', time()).'_add_parameters_to_route_statistics_table.php'),
// you can add any number of migrations here
], 'migrations');
}
diff --git a/src/Models/RouteStatistic.php b/src/Models/RouteStatistic.php
index 632bc05..a2f7642 100644
--- a/src/Models/RouteStatistic.php
+++ b/src/Models/RouteStatistic.php
@@ -23,6 +23,7 @@ class RouteStatistic extends Model implements RequestLoggerInterface
protected $casts = [
'date' => 'datetime',
+ 'parameters' => 'array',
];
//======================================================================
@@ -85,6 +86,7 @@ public function getLogAttributes(Request $request, $response, ?int $time = null,
'team_id' => $this->getRequestTeam($request)?->getKey(),
'method' => $request->getMethod(),
'route' => $request->route()?->getName() ?? $request->route()?->uri(),
+ 'parameters' => config('route-statistics.store_route_parameters') ? $request->route()->originalParameters() : null,
'status' => $response->getStatusCode(),
'ip' => $request->ip(),
'date' => $this->getDate(),
diff --git a/tests/TestCase.php b/tests/TestCase.php
index cd04265..593fb1f 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -35,7 +35,17 @@ public function getEnvironmentSetUp($app)
'prefix' => '',
]);
- $migration = include __DIR__.'/../database/migrations/create_route_statistics_table.php.stub';
- $migration->up();
+ $this->runMigrations([
+ 'create_route_statistics_table',
+ 'add_parameters_to_route_statistics_table',
+ ]);
+ }
+
+ private function runMigrations(array $fileNames): void
+ {
+ foreach ($fileNames as $fileName) {
+ $class = require __DIR__.'/../database/migrations/'.$fileName.'.php.stub';
+ $class->up();
+ }
}
}
diff --git a/tests/Unit/RouteStatisticModelTest.php b/tests/Unit/RouteStatisticModelTest.php
index 2af737b..83bcd2a 100644
--- a/tests/Unit/RouteStatisticModelTest.php
+++ b/tests/Unit/RouteStatisticModelTest.php
@@ -46,4 +46,52 @@ public function test_get_log_attributes(): void
{
$this->markTestIncomplete('Mock the request and response to ensture the correct attributes are returned');
}
+
+ public function test_logs_parameters_if_config_enabled(): void
+ {
+ Config::set('route-statistics.store_route_parameters', true);
+
+ $route = 'home';
+ $params = [
+ 'param1' => 'one',
+ 'param2' => 'two',
+ ];
+ $request = \Illuminate\Http\Request::create($route.'/'.implode('/', $this->get_route_parameters($params)), 'GET');
+ $this->app['router']->get($route.'/'.implode('/', $this->get_route_keys($params)), fn () => 'Test route response');
+ $response = $this->app['router']->dispatch($request);
+
+ (new RouteStatistic)->log($request, $response, 1, 2);
+
+ $log = RouteStatistic::first();
+ $this->assertEquals($params, $log->parameters);
+ }
+
+ public function test_logs_parameters_if_config_disabled(): void
+ {
+ Config::set('route-statistics.store_route_parameters', false);
+
+ $route = 'home';
+ $params = [
+ 'param1' => 'one',
+ 'param2' => 'two',
+ ];
+ $request = \Illuminate\Http\Request::create($route.'/'.implode('/', $this->get_route_parameters($params)), 'GET');
+ $this->app['router']->get($route.'/'.implode('/', $this->get_route_keys($params)), fn () => 'Test route response');
+ $response = $this->app['router']->dispatch($request);
+
+ (new RouteStatistic)->log($request, $response, 1, 2);
+
+ $log = RouteStatistic::first();
+ $this->assertNull($log->parameters);
+ }
+
+ private function get_route_parameters(array $parameters): array
+ {
+ return array_values($parameters);
+ }
+
+ private function get_route_keys(array $parameters): array
+ {
+ return array_map(fn ($parameter) => '{'.$parameter.'}', array_keys($parameters));
+ }
}