Skip to content

Commit

Permalink
Merge pull request #70 from Connehito/4.x
Browse files Browse the repository at this point in the history
fix #61
  • Loading branch information
o0h authored May 30, 2021
2 parents 9b2972b + a8dcac2 commit 964d786
Show file tree
Hide file tree
Showing 30 changed files with 453 additions and 126 deletions.
7 changes: 5 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ php:
- 7.2
- 7.3
- 7.4
- 8.0

cache:
directories:
Expand All @@ -15,13 +16,15 @@ env:

matrix:
include:
- php: 7.4
- php: 8.0
env: PREFER_LOWEST="" TEST=1 CODECOV=1 STAN=0
- php: 7.4
- php: 8.0
env: PREFER_LOWEST="" TEST=0 CODECOV=0 STAN=1

before_script:
- phpenv config-rm xdebug.ini
- echo "assert.exception = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- if [[ $TRAVIS_PHP_VERSION = 7.2 ]]; then composer remove --dev phpspec/prophecy-phpunit; fi
- composer update --prefer-dist --no-interaction $PREFER_LOWEST
- composer show -i
# @see https://github.com/cakephp/cakephp/pull/13567#issuecomment-525844184
Expand Down
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ CakePHP integration for Sentry.
[![License](https://poser.pugx.org/connehito/cake-sentry/license)](https://packagist.org/packages/connehito/cake-sentry)

## Requirements
- PHP 7.2+
- PHP 7.2+ / PHP 8.0+
- CakePHP 4.0+
- and [Sentry](https://sentry.io) account

Expand All @@ -21,6 +21,23 @@ CakePHP integration for Sentry.
composer require connehito/cake-sentry:^3.0
```

If you do not have the ` php-http/async-client-implementation` package, you will need to install it together.
In that case, you will get a message like the following

```
Problem 1
- sentry/sentry[3.2.0, ... , 3.3.0] require php-http/async-client-implementation ^1.0 -> could not be found in any version, but the following packages provide it:
```

Then, you can use the following command to provide a package such as `symfony/http-client`.

```
composer require connehito/cake-sentry symfony/http-client
```

You can find the available packages on [Packagist](https://packagist.org/providers/php-http/async-client-implementation).


## Usage

### Set config files.
Expand Down
13 changes: 7 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
"description": "Sentry plugin for CakePHP",
"type": "cakephp-plugin",
"require": {
"php": "^7.2",
"php": "^7.2 || ^8.0",
"cakephp/cakephp": "^4.0",
"php-http/guzzle6-adapter": "^v1.1.1|^v2.0",
"sentry/sentry": "^2.2"
"sentry/sentry": "^3.2"
},
"require-dev": {
"cakephp/cakephp-codesniffer": "^3.0",
"jangregor/phpstan-prophecy": "^0.4.2",
"cakephp/cakephp-codesniffer": "@stable",
"jangregor/phpstan-prophecy": "@stable",
"phpspec/prophecy-phpunit": "^2.0",
"phpstan/phpstan": "@stable",
"phpunit/phpunit": "^8.5.0"
"phpunit/phpunit": "^8.5 || ^9.3",
"symfony/http-client": "^5.2"
},
"license": "MIT",
"autoload": {
Expand Down
4 changes: 2 additions & 2 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
includes:
- vendor/jangregor/phpstan-prophecy/src/extension.neon
- vendor/jangregor/phpstan-prophecy/extension.neon
parameters:
paths:
- src
- tests/TestCase
level: 5
autoload_files:
bootstrapFiles:
- tests/bootstrap.php
1 change: 1 addition & 0 deletions src/Error/ConsoleErrorHandler.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);

namespace Connehito\CakeSentry\Error;

Expand Down
2 changes: 2 additions & 0 deletions src/Error/ErrorHandler.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php
declare(strict_types=1);

namespace Connehito\CakeSentry\Error;

use Cake\Error\ErrorHandler as CakeErrorHandler;
Expand Down
3 changes: 1 addition & 2 deletions src/Error/ErrorHandlerTrait.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
<?php
declare(strict_types=1);

namespace Connehito\CakeSentry\Error;

use Cake\Core\InstanceConfigTrait;
use Connehito\CakeSentry\Http\Client;
use ErrorException;

trait ErrorHandlerTrait
Expand Down
1 change: 0 additions & 1 deletion src/Error/ErrorLogger.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

class ErrorLogger extends CakeErrorLogger
{

/**
* {@inheritDoc}
*
Expand Down
85 changes: 58 additions & 27 deletions src/Http/Client.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);

namespace Connehito\CakeSentry\Http;

Expand All @@ -7,11 +8,12 @@
use Cake\Event\Event;
use Cake\Event\EventDispatcherTrait;
use Cake\Utility\Hash;
use Psr\Http\Message\ServerRequestInterface;
use RuntimeException;
use Sentry\Breadcrumb;
use Sentry\EventHint;
use Sentry\SentrySdk;
use Sentry\Serializer\RepresentationSerializer;
use Sentry\Severity;
use Sentry\StacktraceBuilder;
use Sentry\State\Hub;
use function Sentry\init;

Expand All @@ -21,13 +23,22 @@ class Client
use InstanceConfigTrait;

/* @var array default instance config */
protected $_defaultConfig = [];
protected $_defaultConfig = [
'sentry' => [
'prefixes' => [
APP,
],
'in_app_exclude' => [
ROOT . DS . 'vendor' . DS,
],
],
];

/* @var Hub */
protected $hub;

/* @var ServerRequestInterface */
protected $request;
/* @var StacktraceBuilder */
protected $stackTraceBuilder;

/**
* Client constructor.
Expand All @@ -36,14 +47,22 @@ class Client
*/
public function __construct(array $config)
{
$userConfig = Configure::read('Sentry');
if ($userConfig) {
$this->_defaultConfig['sentry'] = array_merge($this->_defaultConfig['sentry'], $userConfig);
}
$this->setConfig($config);
$this->setupClient();
$this->stackTraceBuilder = new StacktraceBuilder(
$this->getHub()->getClient()->getOptions(),
new RepresentationSerializer($this->getHub()->getClient()->getOptions())
);
}

/**
* Accessor for current hub
*
* @return Hub
* @return \Sentry\State\Hub
*/
public function getHub(): Hub
{
Expand All @@ -53,10 +72,9 @@ public function getHub(): Hub
/**
* Capture exception for sentry.
*
* @param mixed $level error level
* @param string|int $level error level
* @param string $message error message
* @param array $context subject
*
* @return void
*/
public function capture($level, string $message, array $context): void
Expand All @@ -68,25 +86,23 @@ public function capture($level, string $message, array $context): void
if ($exception) {
$lastEventId = $this->hub->captureException($exception);
} else {
$stacks = array_slice(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT), 3);
if (method_exists(Severity::class, $level)) {
$severity = (Severity::class . '::' . $level)();
} else {
$severity = Severity::fromError($level);
}
foreach ($stacks as $stack) {
$method = isset($stack['class']) ? "{$stack['class']}::{$stack['function']}" : $stack['function'];
unset($stack['class']);
unset($stack['function']);
$this->hub->addBreadcrumb(new Breadcrumb(
$severity,
Breadcrumb::TYPE_ERROR,
'method',
$method,
$stack
));
$hint = new EventHint();

$stackTrace = $context['stackTrace'] ?? false;
if ($stackTrace) {
$hint->stacktrace = $this->stackTraceBuilder->buildFromBacktrace(
$stackTrace,
$stackTrace[0]['file'],
$stackTrace[0]['line']
);
unset($context['stackTrace']);
}
$lastEventId = $this->hub->captureMessage($message, $severity);
$this->hub->configureScope(function (\Sentry\State\Scope $scope) use ($context) {
$scope->setExtras($context);
});

$severity = $this->convertLevelToSeverity($level);
$lastEventId = $this->hub->captureMessage($message, $severity, $hint);
}

$context['lastEventId'] = $lastEventId;
Expand All @@ -101,7 +117,7 @@ public function capture($level, string $message, array $context): void
*/
protected function setupClient(): void
{
$config = (array)Configure::read('Sentry');
$config = $this->getConfig('sentry');
if (!Hash::check($config, 'dsn')) {
throw new RuntimeException('Sentry DSN not provided.');
}
Expand All @@ -112,4 +128,19 @@ protected function setupClient(): void
$event = new Event('CakeSentry.Client.afterSetup', $this);
$this->getEventManager()->dispatch($event);
}

/**
* Convert error info to severity
*
* @param string|int $level Error name or level(int)
* @return \Sentry\Severity
*/
private function convertLevelToSeverity($level): Severity
{
if (is_string($level) && method_exists(Severity::class, $level)) {
return (Severity::class . '::' . $level)();
}

return Severity::fromError($level);
}
}
6 changes: 4 additions & 2 deletions src/Log/Engine/SentryLog.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);

namespace Connehito\CakeSentry\Log\Engine;

Expand All @@ -11,7 +12,7 @@ class SentryLog extends BaseLog
protected $client;

/**
* {@inheritdoc}
* @inheritDoc
*/
public function __construct(array $config = [])
{
Expand All @@ -23,10 +24,11 @@ public function __construct(array $config = [])
}

/**
* {@inheritdoc}
* @inheritDoc
*/
public function log($level, $message, array $context = [])
{
$context['stackTrace'] = debug_backtrace();
$this->client->capture($level, $message, $context);
}
}
1 change: 1 addition & 0 deletions src/Plugin.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);

namespace Connehito\CakeSentry;

Expand Down
2 changes: 1 addition & 1 deletion tests/TestCase/Error/ErrorHandlerTraitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ private function getSubject()
public $wrappedException;

/**
* Implement a non-functional method to avoid echoing in running test.
* {@inheritDoc}
* Implement a non-functional method to avoid echoing in running test.
*/
protected function _displayError(array $error, bool $debug): void
{
Expand Down
6 changes: 4 additions & 2 deletions tests/TestCase/Error/ErrorLoggerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
use Cake\Log\Log;
use Cake\TestSuite\TestCase;
use Connehito\CakeSentry\Error\ErrorLogger;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\MockObject\MockObject; // phpcs:ignore SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse
use Psr\Log\LoggerInterface;
use RuntimeException;

final class ErrorLoggerTest extends TestCase
{
/** @var MockObject LoggerInterface */
/**
* @var MockObject|LoggerInterface LoggerInterface
*/
private $subject;

/**
Expand Down
Loading

0 comments on commit 964d786

Please sign in to comment.