Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ phpstan:
vendor/bin/phpstan analyse

test: cs-fix phpstan
vendor/bin/phpunit
vendor/bin/phpunit --verbose

setup-git:
git config branch.autosetuprebase always
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"bin/sentry"
],
"autoload": {
"files": ["src/Sdk.php"],
"psr-4" : {
"Sentry\\" : "src/"
}
Expand Down
4 changes: 2 additions & 2 deletions src/ClientBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public function __construct(array $options = [])
/**
* {@inheritdoc}
*/
public static function create(array $options = [])
public static function create(array $options = []): self
{
return new static($options);
}
Expand Down Expand Up @@ -239,7 +239,7 @@ public function getMiddlewares()
/**
* {@inheritdoc}
*/
public function getClient()
public function getClient(): ClientInterface
{
$this->messageFactory = $this->messageFactory ?? MessageFactoryDiscovery::find();
$this->uriFactory = $this->uriFactory ?? UriFactoryDiscovery::find();
Expand Down
2 changes: 1 addition & 1 deletion src/ClientBuilderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,5 @@ public function getMiddlewares();
*
* @return ClientInterface
*/
public function getClient();
public function getClient(): ClientInterface;
}
87 changes: 87 additions & 0 deletions src/Sdk.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

namespace Sentry;

use Sentry\Breadcrumbs\Breadcrumb;
use Sentry\State\Hub;

/**
* Creates a new Client and Hub which will be set as current.
*
* @param array $options
*/
function init(array $options = []): void
{
Hub::setCurrent(new Hub(ClientBuilder::create($options)->getClient()));
}

/**
* Captures a message event and sends it to Sentry.
*
* @param string $message The message
* @param Severity $level The severity level of the message
*
* @return null|string
*/
function captureMessage(string $message, ?Severity $level = null): ?string
{
return Hub::getCurrent()->captureMessage($message, $level);
}

/**
* Captures an exception event and sends it to Sentry.
*
* @param \Throwable $exception The exception
*
* @return null|string
*/
function captureException(\Throwable $exception): ?string
{
return Hub::getCurrent()->captureException($exception);
}

/**
* Captures a new event using the provided data.
*
* @param array $payload The data of the event being captured
*
* @return null|string
*/
function captureEvent(array $payload): ?string
{
return Hub::getCurrent()->captureEvent($payload);
}

/**
* Records a new breadcrumb which will be attached to future events. They
* will be added to subsequent events to provide more context on user's
* actions prior to an error or crash.
*
* @param Breadcrumb $breadcrumb The breadcrumb to record
*/
function addBreadcrumb(Breadcrumb $breadcrumb): void
{
Hub::getCurrent()->addBreadcrumb($breadcrumb);
}

/**
* Calls the given callback passing to it the current scope so that any
* operation can be run within its context.
*
* @param callable $callback The callback to be executed
*/
function configureScope(callable $callback): void
{
Hub::getCurrent()->configureScope($callback);
}

/**
* Creates a new scope with and executes the given operation within. The scope
* is automatically removed once the operation finishes or throws.
*
* @param callable $callback The callback to be executed
*/
function withScope(callable $callback): void
{
Hub::getCurrent()->withScope($callback);
}
53 changes: 53 additions & 0 deletions src/State/Hub.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ final class Hub
/**
* Constructor.
*
* @var Hub
*/
private static $currentHub;

/**
* Hub constructor.
*
* @param ClientInterface|null $client The client bound to the hub
* @param Scope|null $scope The scope bound to the hub
*/
Expand Down Expand Up @@ -206,6 +213,24 @@ public function captureException(\Throwable $exception): ?string
return null;
}

/**
* Captures a new event using the provided data.
*
* @param array $payload The data of the event being captured
*
* @return null|string
*/
public function captureEvent(array $payload): ?string
{
$client = $this->getClient();

if (null !== $client) {
return $this->lastEventId = $client->capture($payload);
}

return null;
}

/**
* Records a new breadcrumb which will be attached to future events. They
* will be added to subsequent events to provide more context on user's
Expand All @@ -221,4 +246,32 @@ public function addBreadcrumb(Breadcrumb $breadcrumb): void
$client->addBreadcrumb($breadcrumb, $this->getScope());
}
}

/**
* Returns the current global Hub.
*
* @return Hub
*/
public static function getCurrent(): self
{
if (null === self::$currentHub) {
self::$currentHub = new self();
}

return self::$currentHub;
}

/**
* Sets the Hub as the current.
*
* @param self $hub
*
* @return Hub
*/
public static function setCurrent(self $hub): self
{
self::$currentHub = $hub;

return $hub;
}
}
111 changes: 111 additions & 0 deletions tests/SdkTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php

declare(strict_types=1);

namespace Sentry\Tests;

use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Sentry\Breadcrumbs\Breadcrumb;
use Sentry\ClientInterface;
use Sentry\State\Hub;
use function Sentry\addBreadcrumb;
use function Sentry\captureEvent;
use function Sentry\captureException;
use function Sentry\captureMessage;
use function Sentry\configureScope;
use function Sentry\init;
use function Sentry\withScope;

class SdkTest extends TestCase
{
protected function setUp(): void
{
init();
}

public function testInit(): void
{
$this->assertNotNull(Hub::getCurrent()->getClient());
}

public function testCaptureMessage(): void
{
/** @var ClientInterface|MockObject $client */
$client = $this->createMock(ClientInterface::class);
$client->expects($this->once())
->method('captureMessage')
->with('foo', [], ['level' => null])
->willReturn('92db40a886c0458288c7c83935a350ef');

Hub::getCurrent()->bindClient($client);
$this->assertEquals($client, Hub::getCurrent()->getClient());
$this->assertEquals('92db40a886c0458288c7c83935a350ef', captureMessage('foo'));
}

public function testCaptureException(): void
{
$exception = new \RuntimeException('foo');

/** @var ClientInterface|MockObject $client */
$client = $this->createMock(ClientInterface::class);
$client->expects($this->once())
->method('captureException')
->with($exception)
->willReturn('2b867534eead412cbdb882fd5d441690');

Hub::getCurrent()->bindClient($client);

$this->assertEquals('2b867534eead412cbdb882fd5d441690', captureException($exception));
}

public function testCaptureEvent(): void
{
/** @var ClientInterface|MockObject $client */
$client = $this->createMock(ClientInterface::class);
$client->expects($this->once())
->method('capture')
->with(['message' => 'test'])
->willReturn('2b867534eead412cbdb882fd5d441690');

Hub::getCurrent()->bindClient($client);

$this->assertEquals('2b867534eead412cbdb882fd5d441690', captureEvent(['message' => 'test']));
}

public function testAddBreadcrumb(): void
{
$breadcrumb = new Breadcrumb(Breadcrumb::LEVEL_ERROR, Breadcrumb::TYPE_ERROR, 'error_reporting');

/** @var ClientInterface|MockObject $client */
$client = $this->createMock(ClientInterface::class);
$client->expects($this->once())
->method('addBreadcrumb')
->with($breadcrumb, Hub::getCurrent()->getScope());

Hub::getCurrent()->bindClient($client);
addBreadcrumb($breadcrumb);
}

public function testWithScope(): void
{
$callbackInvoked = false;

withScope(function () use (&$callbackInvoked): void {
$callbackInvoked = true;
});

$this->assertTrue($callbackInvoked);
}

public function configureScope(): void
{
$callbackInvoked = false;

configureScope(function () use (&$callbackInvoked): void {
$callbackInvoked = true;
});

$this->assertTrue($callbackInvoked);
}
}
14 changes: 14 additions & 0 deletions tests/State/HubTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -262,4 +262,18 @@ public function testAddBreadcrumb(): void
$hub = new Hub($client, $scope);
$hub->addBreadcrumb($breadcrumb);
}

public function testCaptureEvent(): void
{
/** @var ClientInterface|MockObject $client */
$client = $this->createMock(ClientInterface::class);
$client->expects($this->once())
->method('capture')
->with(['message' => 'test'])
->willReturn('2b867534eead412cbdb882fd5d441690');

$hub = new Hub($client);

$this->assertEquals('2b867534eead412cbdb882fd5d441690', $hub->captureEvent(['message' => 'test']));
}
}