Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ability to filter incoming requests #45

Merged
merged 8 commits into from
Dec 27, 2023
Merged
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
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,35 @@ The above results in:

![XML-example](https://raw.githubusercontent.com/Napp/xray-laravel/master/docs/xray-xml-example.png)

## Request filtering
There might be some requests you wish not to track in Amazon X-Ray. In order to filter out those requests, you can call the `addRequestFilterCallback` function, on the `Xray` facade.
This function takes a callback as a parameter. The callback takes a `Symfony\Component\HttpFoundation\Request` as a parameter and is expected to return a boolean.

Please note that this function call needs to be done in the `register` function of your `AppServiceProvider`. You should, also, keep the checks relatively simple, since most of the application service providers won't be booted when calling the filtering callbacks.

When LaravelXray is booting, the request is checked against each registered callbacks. If none returns false, the request is captured. Otherwise, it is not.

```php
use Symfony\Component\HttpFoundation\Request;
use Napp\Xray\Facades\Xray;

class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
Xray::addRequestFilterCallback(function(Request $request) {
/* some conditions */
return true;
});
}
}
```

## Daemon support

The X-Ray daemon is automatically run in a Lambda environment. Use this over the default `Napp\Xray\Submission\APISegmentSubmitter` to relay requests to Amazon X-Ray.
Expand Down
1 change: 1 addition & 0 deletions src/Facades/Xray.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
* @method static void initCliTracer(string $name)
* @method static void submitHttpTracer($response)
* @method static void submitCliTracer()
* @method static void addRequestFilterCallback(callable $callback)
*
* @see \Napp\Xray\Xray
*/
Expand Down
19 changes: 19 additions & 0 deletions src/Xray.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ class Xray
{
private $collector;

private $requestFilterCallables;

public function __construct(SegmentCollector $collector)
{
$this->collector = $collector;
$this->requestFilterCallables = [];
}

public function tracer(): Trace
Expand Down Expand Up @@ -82,4 +85,20 @@ public function submitCliTracer(): void
{
$this->collector->submitCliTracer();
}

public function addRequestFilterCallback(callable $callback): void
{
$this->requestFilterCallables[] = $callback;
}

public function shouldCaptureRequest(Request $request): bool
{
foreach ($this->requestFilterCallables as $requestFilterCallable) {
if (! $requestFilterCallable($request)) {
return false;
}
}

return true;
}
}
6 changes: 6 additions & 0 deletions src/XrayServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ public function boot()
return;
}

$xraySingleton = $this->app->make('xray');

if (! $this->app->runningInConsole() && ! $xraySingleton->shouldCaptureRequest($this->app->make('request'))) {
return;
}

$this->registerCollectors();
}

Expand Down
95 changes: 95 additions & 0 deletions tests/Facades/XrayTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

namespace Napp\Xray\Tests\Facades;

use Napp\Xray\Collectors\SegmentCollector;
use Napp\Xray\Xray;
use Symfony\Component\HttpFoundation\Request;
use PHPUnit\Framework\TestCase;

class XrayTest extends TestCase
{
public function test_it_should_register_request_filtering_callback() {
// given an Xray object
/** @var Xray $xrayObject */
$xrayObject = new Xray(new SegmentCollector());

// and a mock of a callback to check if the current request should be captured.
$callbackCalled = false;
$requestCapturingCallbackMock = function(Request $request) use (&$callbackCalled) {
$callbackCalled = true;
};

// and the callback has been registered on the facade as a filter callback
$xrayObject->addRequestFilterCallback($requestCapturingCallbackMock);

// when checking, on the facade, if the request should be captured
$request = new Request();
$xrayObject->shouldCaptureRequest($request);

// then the callback should have been called
$this->assertTrue($callbackCalled);
}

public function test_it_should_return_true_when_no_request_filter_callable_returns_false() {
// given a xray object
/** @var Xray $xrayObject */
$xrayObject = new Xray(new SegmentCollector());

// and some request filter callback that return true
$givenRequestCallbackCount = 3;
for($i = 0; $i < $givenRequestCallbackCount; $i ++) {
$xrayObject->addRequestFilterCallback(function() {
return true;
});
}

// when checking, on the facade, if the request should be captured
$request = new Request();
$result = $xrayObject->shouldCaptureRequest($request);

// then it should return true
$this->assertTrue($result);
}

public function test_it_should_return_false_if_at_least_one_request_filter_callback_returns_false() {
// given a xray object
/** @var Xray $xrayObject */
$xrayObject = new Xray(new SegmentCollector());

// and some request filter callback that return true
$givenRequestCallbackCount = 3;
for($i = 0; $i < $givenRequestCallbackCount; $i ++) {
$xrayObject->addRequestFilterCallback(function() {
return true;
});
}

// and one request filter callback that returns false
$xrayObject->addRequestFilterCallback(function() {
return false;
});

// when checking, on the facade, if the request should be captured
$request = new Request();
$result = $xrayObject->shouldCaptureRequest($request);

// then it should return false
$this->assertFalse($result);
}

public function test_it_should_return_true_if_no_request_filtering_callback_are_defined() {
// given a xray object
/** @var Xray $xrayObject */
$xrayObject = new Xray(new SegmentCollector());

// and no request filtering callback defined

// when checking, on the facade, if the request should be captured
$request = new Request();
$result = $xrayObject->shouldCaptureRequest($request);

// then it should return true
$this->assertTrue($result);
}
}
Loading