You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/2-features/14-exception-handling.md
+87-4Lines changed: 87 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,11 +5,9 @@ description: "Learn how exception handling works, how to manually report excepti
5
5
6
6
## Overview
7
7
8
-
Tempest comes with its own exception handler, which provides a simple way to catch and process exceptions. During local development, Tempest uses [Whoops](https://github.com/filp/whoops) to display detailed error pages. In production, it displays a generic error page.
8
+
Tempest comes with an exception handler that provides a simple way to report exceptions and render error responses.
9
9
10
-
When an exception is thrown, it is caught and piped through the registered exception reporters. By default, the only registered exception reporter, {b`Tempest\Core\LoggingExceptionReporter`}, logs the exception.
11
-
12
-
Custom exception reporters can be created by implementing the {b`Tempest\Core\Exceptions\ExceptionReporter`} interface. Classes implementing this interface are automatically [discovered](../4-internals/02-discovery.md) and do not require manual registration.
10
+
Custom [exception reporters](#writing-exception-reporters) can be created by implementing the {b`Tempest\Core\Exceptions\ExceptionReporter`} interface, and custom [exception renderers](#customizing-exception-rendering) can be created by implementing {b`Tempest\Router\Exceptions\ExceptionRenderer`}. These classes are automatically [discovered](../4-internals/02-discovery.md) and do not require manual registration.
13
11
14
12
## Processing exceptions
15
13
@@ -70,6 +68,91 @@ final readonly class UserWasNotFound extends Exception implements ProvidesContex
70
68
}
71
69
```
72
70
71
+
## Writing exception reporters
72
+
73
+
Exception reporters allow defining custom reporting logic for exceptions, such as sending them to external error tracking services like Sentry or logging them to specific destinations.
74
+
75
+
To create a custom reporter, implement the {b`Tempest\Core\Exceptions\ExceptionReporter`} interface and define a `report()` method:
76
+
77
+
```php app/SentryExceptionReporter.php
78
+
use Tempest\Core\Exceptions\ExceptionReporter;
79
+
use Throwable;
80
+
81
+
final class SentryExceptionReporter implements ExceptionReporter
82
+
{
83
+
public function __construct(
84
+
private SentryClient $sentry,
85
+
) {}
86
+
87
+
public function report(Throwable $throwable): void
88
+
{
89
+
$this->sentry->captureException($throwable);
90
+
}
91
+
}
92
+
```
93
+
94
+
Exception reporters are automatically [discovered](../4-internals/02-discovery.md) and registered. All registered reporters are invoked whenever an exception is processed, allowing multiple reporters to handle the same exception.
95
+
96
+
For example, the default logging reporter logs to a file, while the reporter above sends the error to Sentry.
97
+
98
+
If an exception reporter throws an exception during execution, it is silently caught to prevent infinite loops. This ensures that a failing reporter doesn't prevent other reporters from running.
99
+
100
+
### Accessing exception context
101
+
102
+
Exceptions can implement the {b`Tempest\Core\ProvidesContext`} interface, which reporters can leverage to provide additional context data during reporting:
103
+
104
+
```php app/SentryExceptionReporter.php
105
+
use Tempest\Core\Exceptions\ExceptionReporter;
106
+
use Tempest\Core\ProvidesContext;
107
+
use Sentry\State\HubInterface as Sentry;
108
+
use Sentry\State\Scope;
109
+
110
+
final class SentryExceptionReporter implements ExceptionReporter
111
+
{
112
+
public function __construct(
113
+
private readonly Sentry $sentry,
114
+
) {}
115
+
116
+
public function report(Throwable $throwable): void
117
+
{
118
+
$this->sentry->withScope(function (Scope $scope) use ($throwable) {
119
+
if ($throwable instanceof ProvidesContext) {
120
+
$scope->withContext($throwable->context());
121
+
}
122
+
123
+
$scope->captureException($throwable);
124
+
});
125
+
}
126
+
}
127
+
```
128
+
129
+
### Conditional reporting
130
+
131
+
Reporters can implement conditional logic to only report specific exception types or under certain conditions. There is no built-in filtering mechanism; reporters are responsible for determining when to report an exception.
132
+
133
+
```php app/CriticalErrorReporter.php
134
+
use Tempest\Core\Exceptions\ExceptionReporter;
135
+
use Throwable;
136
+
137
+
final class CriticalErrorReporter implements ExceptionReporter
138
+
{
139
+
public function __construct(
140
+
private AlertService $alerts,
141
+
) {}
142
+
143
+
public function report(Throwable $throwable): void
144
+
{
145
+
if (! $throwable instanceof CriticalException) {
146
+
return;
147
+
}
148
+
149
+
$this->alerts->sendCriticalAlert(
150
+
message: $throwable->getMessage(),
151
+
);
152
+
}
153
+
}
154
+
```
155
+
73
156
## Customizing exception rendering
74
157
75
158
Exception renderers provide control over how exceptions are rendered in HTTP responses. Custom renderers can be used to display specialized error pages for specific exception types, format errors differently based on content type (JSON, HTML, XML), or provide user-friendly error messages for common scenarios like 404 or validation failures.
0 commit comments