Skip to content

Commit

Permalink
feat: catch possible error and log it (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
evan361425 authored Jul 20, 2021
1 parent 1c28a33 commit c730c12
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 15 deletions.
24 changes: 22 additions & 2 deletions config/xray.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,36 @@
return [
'name' => env('AWS_XRAY_SERVICE_NAME'),

'route_filters' => explode(',', env('AWS_XRAY_ROUTE_FILTERS', '')),

'enabled' => env('AWS_XRAY_ENABLED', true),

/*
|--------------------------------------------------------------------------
| Ignoring any possible error
|--------------------------------------------------------------------------
|
| In production, it will possibly need to ignore error from Xray.
|
*/
'ignore_error' => env('AWS_XRAY_IGNORE_ERROR', false),

/*
|--------------------------------------------------------------------------
| Ignored routes
|--------------------------------------------------------------------------
|
| Comma separated value to ignore record Xray.
| Default will allow all routes to trace.
|
*/
'route_filters' => explode(',', env('AWS_XRAY_ROUTE_FILTERS', '')),

/*
|--------------------------------------------------------------------------
| Submission method
|--------------------------------------------------------------------------
|
| This is where you can set the data submission method.
| If [AWS_XRAY_DAEMON_HOST] is set, it will automatically using [DaemonSegmentSubmitter]
| Supported classes: "APISegmentSubmitter", "DaemonSegmentSubmitter"
|
*/
Expand Down
9 changes: 7 additions & 2 deletions src/Collectors/DatabaseQueryCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Napp\Xray\Collectors;

use Exception;
use Illuminate\Database\Connection;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Database\Query\Expression;
Expand All @@ -16,8 +17,12 @@ class DatabaseQueryCollector extends EventsCollector
public function registerEventListeners(): void
{
$this->app->events->listen(QueryExecuted::class, function (QueryExecuted $query) {
$sql = $query->sql instanceof Expression ? $query->sql->getValue() : $query->sql;
$this->handleQueryReport($sql, $query->bindings, $query->time, $query->connection);
try {
$sql = $query->sql instanceof Expression ? $query->sql->getValue() : $query->sql;
$this->handleQueryReport($sql, $query->bindings, $query->time, $query->connection);
} catch (Exception $e) {
$this->handleException($e);
}
});

$this->bindingsEnabled = config('xray.db_bindings');
Expand Down
20 changes: 12 additions & 8 deletions src/Collectors/RouteCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,22 @@ public function registerEventListeners(): void

// Time between route resolution and request handled
$this->app['events']->listen(RouteMatched::class, function ($event) {
$this->addSegment('request handled')
->addAnnotation('controller', $this->getController());
$this->getSegment('route matching')->end();
});

$this->app['events']->listen(RequestHandled::class, function () {
$this->endSegment('route matching');
// Some middlewares might return a response
// before the RouteMatched has been dispatched
if ($this->hasAddedSegment('request handled')) {
$this->endSegment('request handled');
// end the segment first avoid missing end time
try {
$this->addSegment('request handled')
->addAnnotation('controller', $this->getController())
->end();
} catch (\Exception $e) {
$this->handleException($e);
}
});

$this->app['events']->listen(RequestHandled::class, function () {
$this->endSegment('request handled');
});
}

protected function getController(): string
Expand Down
22 changes: 22 additions & 0 deletions src/Collectors/SegmentCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Napp\Xray\Segments\TimeSegment;
use Napp\Xray\Segments\Trace;
use Pkerrigan\Xray\HttpSegment;
Expand Down Expand Up @@ -172,4 +173,25 @@ public function submitCliTracer(): void

$tracer::flush();
}

/**
* Record and log the exception
*
* If [ignore_error] is set to false, it will rethrow the exception
*
* @throws \Exception iif set [ignore_error] to false
*
* @param \Exception $e
* @return void
*/
public function handleException(\Exception $e)
{
Log::warning($e->getMessage(), ['exception' => $e]);
$this->current()
->addAnnotation('xrayError', $e->getMessage())
->addMetadata('xrayDatabaseQueryTrace', $e->getTraceAsString());
if (!config('xray.ignore_error')) {
throw $e;
}
}
}
4 changes: 1 addition & 3 deletions src/Collectors/ViewCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ public function registerEventListeners(): void

$this->app['events']->listen('composing:*', function ($view, $data = []) {
$viewName = substr($view, 11);
if ($this->hasAddedSegment('View ' . $viewName)) {
$this->endSegment('View ' . $viewName);
}
$this->endSegment('View ' . $viewName);
});
}
}
20 changes: 20 additions & 0 deletions tests/Collectors/SegmentCollectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,26 @@ public function test_end_empty_segments_wont_throw_exception()
$this->assertTrue(true);
}

public function test_handle_exception()
{
// should not rethrow exception
$this->app['config']->set('xray.ignore_error', true);
$exception = new \Exception('message', 0);
$collector = new SegmentCollector();

$collector->handleException($exception);

$serialized = $collector->current()->jsonSerialize();
$this->assertEquals('message', $serialized['annotations']['xrayError']);
$this->assertNotEmpty(($serialized['metadata']['xrayDatabaseQueryTrace']));

// should rethrow exception
$this->app['config']->set('xray.ignore_error', false);
$this->expectException(\Exception::class);

$collector->handleException($exception);
}

protected function createRequest()
{
$request = $this->createMock(Request::class);
Expand Down

0 comments on commit c730c12

Please sign in to comment.