Skip to content

Commit ada422c

Browse files
authored
Merge pull request #79 from cloudcreativity/feature/log-swallowed-exception
feat: allow swallowed exception to be logged
2 parents ba1055a + cce88ef commit ada422c

3 files changed

Lines changed: 81 additions & 1 deletion

File tree

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,19 @@ config:
257257
If an exception occurs when this setting is `true`, the `$request->ipinfo`
258258
object will be equal to `null`.
259259

260+
If you want the suppressed exception to be logged, you can set the
261+
`no_except_log_level` to a valid PSR log level. E.g. to log it as a `notice`:
262+
263+
```php
264+
'ipinfo' => [
265+
...
266+
'no_except' => true,
267+
'no_except_log_level' => \Psr\Log\LogLevel::NOTICE,
268+
],
269+
```
270+
271+
> The default value for `no_except_log_level` is `null`, which means that no logging will occur.
272+
260273
### Trying test application with Laravel Sail
261274

262275
Install Laravel Sail with:

src/ipinfolaravel.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ class ipinfolaravel
4545
*/
4646
public $no_except = false;
4747

48+
/**
49+
* The log level for swallowed exceptions.
50+
*
51+
* Set to a valid log level, e.g. debug, info, notice etc.
52+
* If null, the exception will not be logged.
53+
*
54+
* @var null
55+
*/
56+
public $no_except_log_level = null;
57+
4858
const CACHE_MAXSIZE = 4096;
4959
const CACHE_TTL = 60 * 24;
5060

@@ -73,6 +83,10 @@ public function handle($request, Closure $next)
7383
if (!$this->no_except) {
7484
throw $e;
7585
}
86+
87+
if (is_string($this->no_except_log_level)) {
88+
logger()->log($this->no_except_log_level, 'ipinfo: ' . $e->getMessage(), ['exception' => $e]);
89+
}
7690
}
7791
}
7892

@@ -89,6 +103,7 @@ public function configure()
89103
$this->access_token = config('services.ipinfo.access_token', null);
90104
$this->filter = config('services.ipinfo.filter', [$this, 'defaultFilter']);
91105
$this->no_except = config('services.ipinfo.no_except', false);
106+
$this->no_except_log_level = config('services.ipinfo.no_except_log_level');
92107
$this->ip_selector = config('services.ipinfo.ip_selector', new DefaultIPSelector());
93108

94109
if ($custom_countries = config('services.ipinfo.countries_file', null)) {

tests/IpinfolaravelTest.php

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
use ipinfo\ipinfolaravel\iphandler\IPHandlerInterface;
88
use Orchestra\Testbench\TestCase;
99
use ipinfo\ipinfolaravel\ipinfolaravel;
10+
use PHPUnit\Framework\MockObject\MockObject;
11+
use Psr\Log\LoggerInterface;
12+
use Psr\Log\LogLevel;
1013

1114
class IpinfolaravelTest extends TestCase
1215
{
@@ -21,6 +24,7 @@ protected function makeMiddlewareWithMocks(
2124
$selector,
2225
$filter = null,
2326
$noExcept = false,
27+
$noExceptLogLevel = null,
2428
) {
2529
// stub out configure() so it doesn't overwrite our mocks
2630
$mw = $this->getMockBuilder(ipinfolaravel::class)
@@ -31,6 +35,7 @@ protected function makeMiddlewareWithMocks(
3135
$mw->ip_selector = $selector;
3236
$mw->filter = $filter;
3337
$mw->no_except = $noExcept;
38+
$mw->no_except_log_level = $noExceptLogLevel;
3439
return $mw;
3540
}
3641

@@ -109,7 +114,7 @@ public function test_handle_throws_if_client_throws_and_no_except_false()
109114
$mw->handle(Request::create("/", "GET"), function () {});
110115
}
111116

112-
public function test_handle_swallows_if_client_throws_and_no_except_true()
117+
public function test_handle_swallows_if_client_throws_and_no_except_true_without_logging()
113118
{
114119
$client = $this->createMock(IPinfoClient::class);
115120
$client
@@ -119,6 +124,9 @@ public function test_handle_swallows_if_client_throws_and_no_except_true()
119124
$selector = $this->createMock(IPHandlerInterface::class);
120125
$selector->method("getIP")->willReturn("1.2.3.4");
121126

127+
$logger = $this->makeLog();
128+
$logger->expects($this->never())->method('log');
129+
122130
$mw = $this->makeMiddlewareWithMocks($client, $selector, null, true);
123131

124132
$captured = "unset";
@@ -131,6 +139,38 @@ public function test_handle_swallows_if_client_throws_and_no_except_true()
131139
$this->assertNull($captured);
132140
}
133141

142+
public function test_handle_swallows_if_client_throws_and_no_except_true_with_logging()
143+
{
144+
$client = $this->createMock(IPinfoClient::class);
145+
$client
146+
->method("getDetails")
147+
->willThrowException($expected = new \RuntimeException('Boom! That went wrong.'));
148+
149+
$selector = $this->createMock(IPHandlerInterface::class);
150+
$selector->method("getIP")->willReturn("1.2.3.4");
151+
152+
$logger = $this->makeLog();
153+
$logger
154+
->expects($this->once())
155+
->method('log')
156+
->with(
157+
LogLevel::ALERT,
158+
'ipinfo: ' . $expected->getMessage(),
159+
['exception' => $expected],
160+
);
161+
162+
$mw = $this->makeMiddlewareWithMocks($client, $selector, null, true, LogLevel::ALERT);
163+
164+
$captured = "unset";
165+
$next = function ($req) use (&$captured) {
166+
$captured = $req->get("ipinfo");
167+
return new Response();
168+
};
169+
170+
$mw->handle(Request::create("/", "GET"), $next);
171+
$this->assertNull($captured);
172+
}
173+
134174
public function test_defaultFilter_detects_bots_and_spiders()
135175
{
136176
$mw = new ipinfolaravel();
@@ -150,4 +190,16 @@ public function test_defaultFilter_detects_bots_and_spiders()
150190
$r4 = Request::create("/", "GET");
151191
$this->assertFalse($mw->defaultFilter($r4));
152192
}
193+
194+
/**
195+
* @return MockObject&LoggerInterface
196+
*/
197+
private function makeLog()
198+
{
199+
$logger = $this->createMock(LoggerInterface::class);
200+
$this->app->instance(LoggerInterface::class, $logger);
201+
$this->app->instance('log', $logger);
202+
203+
return $logger;
204+
}
153205
}

0 commit comments

Comments
 (0)