Sentry is a service that helps you monitor and fix crashes in real time. The Trace Sample Rate determines the percentage chance that a given transaction will send trace data to Sentry.
Middleware in Laravel is a mechanism for filtering HTTP requests entering your application. Middleware can be created and registered to run during every HTTP request to your application, or you can assign them to specific routes.
Here is an example of a middleware for Laravel that sets the Sentry traces sample rate:
php<?php
namespace App\Http\Middleware;
use Closure;
use Sentry\State\HubInterface;
class SentryTracesSampleRate
{
protected $sentry;
public function __construct(HubInterface $sentry)
{
$this->sentry = $sentry;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string $percentage
* @return mixed
*/
public function handle($request, Closure $next, $percentage)
{
$transactionContext = new \Sentry\Tracing\TransactionContext();
$transactionContext->setName($request->route()->getName());
$transactionContext->setOp('http');
$transactionContext->setTraceSampleRate($percentage / 100.0);
$transaction = $this->sentry->startTransaction($transactionContext);
$request->session()->put('sentryTracer', $transaction);
$response = $next($request);
$transaction->finish();
return $response;
}
}
You need to register this middleware in the Kernel.php
file to make it work:
php<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
// ...
protected $routeMiddleware = [
// ...
'sentry.sample_rate' => \App\Http\Middleware\SentryTracesSampleRate::class,
];
}
After doing this, you can use the middleware in your routes by passing the sample rate as a parameter:
phpRoute::middleware(['sentry.sample_rate:50'])->group(function () {
Route::get('/example', function () {
//
});
});
In this example, the sentry.sample_rate
middleware is assigned to the route with a 50% sample rate.
Please note that you have to adjust this middleware according to your specific needs. For example, you might need to adapt it if you use a different Sentry SDK version or if your transaction handling is different.
Remember to ensure your Sentry SDK is correctly initialized and you have configured it to start a transaction for every HTTP request.
Certainly, below is an example of a unit test for the middleware using PHPUnit. We'll test that a transaction is started, set the correct name, and the correct trace sample rate is set.
php<?php
namespace Tests\Unit;
use App\Http\Middleware\SentryTracesSampleRate;
use Illuminate\Http\Request;
use Mockery;
use Sentry\State\HubInterface;
use Sentry\Tracing\Transaction;
use Sentry\Tracing\TransactionContext;
use Tests\TestCase;
class SentryTracesSampleRateTest extends TestCase
{
public function testSentryTracesSampleRateMiddleware()
{
$sampleRate = 50;
$transaction = Mockery::mock(Transaction::class);
$transaction->shouldReceive('finish')->once();
$sentry = Mockery::mock(HubInterface::class);
$sentry->shouldReceive('startTransaction')
->once()
->with(Mockery::on(function ($context) use ($sampleRate) {
$this->assertInstanceOf(TransactionContext::class, $context);
$this->assertEquals('GET /test', $context->getName());
$this->assertEquals($sampleRate / 100.0, $context->getTraceSampleRate());
return true;
}))
->andReturn($transaction);
$middleware = new SentryTracesSampleRate($sentry);
$request = Request::create('/test', 'GET');
$request->setRouteResolver(function () use ($request) {
return (new \Illuminate\Routing\Route('GET', '/test', []))->bind($request);
});
$response = $middleware->handle($request, function () {
return 'response';
}, $sampleRate);
$this->assertEquals('response', $response);
}
}
In this unit test:
- We create a mock Sentry object, and set up expectations that
startTransaction
should be called with certain parameters. - We create a new instance of the
SentryTracesSampleRate
middleware, passing in the mock Sentry object. - We create a mock request and response, and call the middleware's
handle
method, which should run the middleware's logic. - We then assert that the response returned by the middleware is as expected.
Before running the test, ensure that you have the necessary dependencies installed and set up for testing with PHPUnit in Laravel. Also, you will need to install Mockery to be able to mock objects in your tests.
Remember that unit tests should be part of a broader testing strategy, including integration and end-to-end tests, to ensure that your application is working correctly.