Skip to content

Commit

Permalink
Make it configurable if the performance traces continues after the re…
Browse files Browse the repository at this point in the history
…sponse has been sent (#727)
  • Loading branch information
stayallive authored Jul 25, 2023
1 parent e950109 commit 9b26cad
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 18 deletions.
4 changes: 4 additions & 0 deletions config/sentry.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@

// Indicates that requests without a matching route should be traced
'missing_routes' => false,

// Indicates if the performance trace should continue after the response has been sent to the user until the application terminates
// This is required to capture any spans that are created after the response has been sent like queue jobs dispatched using `dispatch(...)->afterResponse()` for example
'continue_after_response' => true,
],

// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#send-default-pii
Expand Down
44 changes: 28 additions & 16 deletions src/Sentry/Laravel/Tracing/Middleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ class Middleware
*/
private $app;

/**
* Whether we should continue tracing after the response has been sent to the client.
*
* @var bool
*/
private $continueAfterResponse;

/**
* Whether the terminating callback has been registered.
*
Expand All @@ -57,9 +64,10 @@ class Middleware
*
* @param LaravelApplication|LumenApplication $app
*/
public function __construct($app)
public function __construct($app, bool $continueAfterResponse = true)
{
$this->app = $app;
$this->continueAfterResponse = $continueAfterResponse;
}

/**
Expand Down Expand Up @@ -108,22 +116,26 @@ public function terminate(Request $request, $response): void
$this->hydrateResponseData($response);
}

// Ensure we do not register the terminating callback multiple times since there is no point in doing so
if ($this->registeredTerminatingCallback) {
return;
}

// We need to finish the transaction after the response has been sent to the client
// so we register a terminating callback to do so, this allows us to also capture
// spans that are created during the termination of the application like queue
// dispatched using dispatch(...)->afterResponse(). This middleware is called
// before the terminating callbacks so we are 99.9% sure to be the last one
// to run except if another terminating callback is registered after ours.
$this->app->terminating(function () {
if ($this->continueAfterResponse) {
// Ensure we do not register the terminating callback multiple times since there is no point in doing so
if ($this->registeredTerminatingCallback) {
return;
}

// We need to finish the transaction after the response has been sent to the client
// so we register a terminating callback to do so, this allows us to also capture
// spans that are created during the termination of the application like queue
// dispatched using dispatch(...)->afterResponse(). This middleware is called
// before the terminating callbacks so we are 99.9% sure to be the last one
// to run except if another terminating callback is registered after ours.
$this->app->terminating(function () {
$this->finishTransaction();
});

$this->registeredTerminatingCallback = true;
} else {
$this->finishTransaction();
});

$this->registeredTerminatingCallback = true;
}
}

/**
Expand Down
11 changes: 9 additions & 2 deletions src/Sentry/Laravel/Tracing/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function boot(): void
});
}

$tracingConfig = $this->getUserConfig()['tracing'] ?? [];
$tracingConfig = $this->getTracingConfig();

$this->bindEvents($tracingConfig);

Expand All @@ -61,7 +61,9 @@ public function boot(): void
public function register(): void
{
$this->app->singleton(Middleware::class, function () {
return new Middleware($this->app);
$continueAfterResponse = ($this->getTracingConfig()['continue_after_response'] ?? true) === true;

return new Middleware($this->app, $continueAfterResponse);
});

$this->app->singleton(BacktraceHelper::class, function () {
Expand Down Expand Up @@ -132,6 +134,11 @@ private function wrapViewEngine(Engine $realEngine): Engine
return new ViewEngineDecorator($realEngine, $viewFactory);
}

private function getTracingConfig(): array
{
return $this->getUserConfig()['tracing'] ?? [];
}

private function decorateRoutingDispatchers(): void
{
$this->app->extend(CallableDispatcher::class, static function (CallableDispatcher $dispatcher) {
Expand Down

0 comments on commit 9b26cad

Please sign in to comment.