Skip to content

Commit

Permalink
Attach Laravel's Context to events as metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
imjoehaines committed May 22, 2024
1 parent b1d31a4 commit 554ddb6
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 1 deletion.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Changelog
=========

## TBD

### Enhancements

* Attach Laravel 11's `Context` to events as metadata under the key 'Laravel Context'. Hidden context will only be added if the new configuration option `attach_hidden_context` is enabled, either in `config/bugsnag.php` or via the environment variable `BUGSNAG_ATTACH_HIDDEN_CONTEXT`
[#537](https://github.com/bugsnag/bugsnag-laravel/pull/537)

## v2.27.0 (2024-03-13)

### Enhancements
Expand Down
12 changes: 12 additions & 0 deletions config/bugsnag.php
Original file line number Diff line number Diff line change
Expand Up @@ -361,4 +361,16 @@
*/

'max_breadcrumbs' => null,

/*
|--------------------------------------------------------------------------
| Attach hidden context
|--------------------------------------------------------------------------
|
| The maximum number of breadcrumbs to send with a report.
|
| This should be an integer between 0-100 (inclusive).
*/

'attach_hidden_context' => env('BUGSNAG_ATTACH_HIDDEN_CONTEXT', false),
];
22 changes: 22 additions & 0 deletions src/BugsnagServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
use Illuminate\Queue\QueueManager;
use Illuminate\Routing\Events\RouteMatched;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Context;
use Laravel\Lumen\Application as LumenApplication;
use Monolog\Handler\PsrHandler;
use Monolog\Logger;
Expand Down Expand Up @@ -439,6 +440,27 @@ protected function setupCallbacks(Client $client, Container $app, array $config)
}
}));
}

// Laravel 11 has a 'Context' class for storing metadata
// https://laravel.com/docs/11.x/context
if (class_exists(Context::class)) {
$client->registerCallback(function (Report $report) {
$context = Context::all();

$report->setMetaData(['Laravel Context' => $context]);
});

// only attach hidden context if enabled, otherwise sensitive data
// could leak to bugsnag
if (isset($config['attach_hidden_context']) && $config['attach_hidden_context']) {
$client->registerCallback(function (Report $report) {
$hiddenContext = Context::allHidden();

$report->setMetaData(['Laravel Hidden Context' => $hiddenContext]);
});

}
}
}

/**
Expand Down
6 changes: 5 additions & 1 deletion tests/Middleware/UnhandledStateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@

function debug_backtrace()
{
return DebugBacktraceStub::get();
if (DebugBacktraceStub::hasValue()) {
return DebugBacktraceStub::get();
}

return \debug_backtrace();
}

namespace Bugsnag\BugsnagLaravel\Tests\Middleware;
Expand Down
76 changes: 76 additions & 0 deletions tests/ServiceProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
use Bugsnag\BugsnagLaravel\Tests\Stubs\InjecteeWithLogInterface;
use Bugsnag\Client;
use Bugsnag\FeatureFlag;
use Bugsnag\Report;
use Bugsnag\PsrLogger\BugsnagLogger;
use Bugsnag\PsrLogger\MultiLogger as BaseMultiLogger;
use Illuminate\Contracts\Logging\Log;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Context;

class ServiceProviderTest extends AbstractTestCase
{
Expand Down Expand Up @@ -531,4 +533,78 @@ public function testMaxBreadcrumbsCanBeSetFromConfig()
$this->assertInstanceOf(Client::class, $client);
$this->assertSame(73, $client->getMaxBreadcrumbs());
}

public function testItSetsContextAsMetadata()
{
if (!class_exists(Context::class)) {
$this->markTestSkipped("Requires Laravel 11's 'Context' class");
}

Context::add('a', 1234);
Context::add('b', true);

/** @var Client $client */
$client = $this->app->make(Client::class);

Context::add('c', 'hello');
Context::add('d', [1, 2, 3]);

$expected = ['a' => 1234, 'b' => true, 'c' => 'hello', 'd' => [1, 2, 3]];
$actual = [];
$hasHiddenContext = true;

$client->notifyException(
new \Exception('hello'),
function (Report $report) use (&$actual, &$hasHiddenContext) {
$metadata = $report->getMetadata();

$actual = $metadata['Laravel Context'];
$hasHiddenContext = isset($metadata['Laravel Hidden Context']);
}
);

$this->assertSame($expected, $actual);
$this->assertFalse($hasHiddenContext);
}

public function testItSetsHiddenContextAsMetadataIfConfiguredToDoSo()
{
if (!class_exists(Context::class)) {
$this->markTestSkipped("Requires Laravel 11's 'Context' class");
}

Context::addHidden('a', 1234);
Context::add('b', true);

/** @var \Illuminate\Config\Repository $laravelConfig */
$laravelConfig = $this->app->config;
$bugsnagConfig = $laravelConfig->get('bugsnag');
$bugsnagConfig['attach_hidden_context'] = true;

$laravelConfig->set('bugsnag', $bugsnagConfig);

/** @var Client $client */
$client = $this->app->make(Client::class);

Context::add('c', 'hello');
Context::addHidden('d', [1, 2, 3]);

$expectedContext = ['b' => true, 'c' => 'hello'];
$expectedHiddenContext = ['a' => 1234, 'd' => [1, 2, 3]];
$actualContext = [];
$actualHiddenContext = [];

$client->notifyException(
new \Exception('hello'),
function (Report $report) use (&$actualContext, &$actualHiddenContext) {
$metadata = $report->getMetadata();

$actualContext = $metadata['Laravel Context'];
$actualHiddenContext = $metadata['Laravel Hidden Context'];
}
);

$this->assertSame($expectedContext, $actualContext);
$this->assertSame($expectedHiddenContext, $actualHiddenContext);
}
}
5 changes: 5 additions & 0 deletions tests/Stubs/DebugBacktraceStub.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ public static function set(array $backtrace)
self::$backtrace = $backtrace;
}

public static function hasValue()
{
return self::$backtrace !== [];
}

public static function clear()
{
self::$backtrace = [];
Expand Down

0 comments on commit 554ddb6

Please sign in to comment.