Skip to content
Draft
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
4 changes: 3 additions & 1 deletion src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,9 @@ public function captureException(\Throwable $exception, ?Scope $scope = null, ?E
*/
public function captureEvent(Event $event, ?EventHint $hint = null, ?Scope $scope = null): ?EventId
{
$event = $this->prepareEvent($event, $hint, $scope);
if ($event->getType() !== EventType::clientReport()) {
$event = $this->prepareEvent($event, $hint, $scope);
}

if ($event === null) {
return null;
Expand Down
54 changes: 54 additions & 0 deletions src/ClientReport/ClientReport.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace Sentry\ClientReport;

class ClientReport
{

/**
* @var string
*/
private $reason;

/**
* @var string
*/
private $category;

/**
* @var int
*/
private $quantity;

public function __construct(string $category, string $reason, int $quantity)
{
$this->category = $category;
$this->reason = $reason;
$this->quantity = $quantity;
}

/**
* @return string
*/
public function getCategory(): string
{
return $this->category;
}

/**
* @return int
*/
public function getQuantity(): int
{
return $this->quantity;
}

/**
* @return string
*/
public function getReason(): string
{
return $this->reason;
}

}
51 changes: 51 additions & 0 deletions src/ClientReport/ClientReportAggregator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace Sentry\ClientReport;

use Sentry\Event;
use Sentry\State\Hub;
use Sentry\State\HubAdapter;
use Sentry\Transport\DataCategory;

class ClientReportAggregator
{
private static $instance;

/**
* Nested array for local aggregation.
*
* @var array
*/
private $reports = [];

public function add(DataCategory $category, Reason $reason, int $quantity): void
{
$this->reports[(string) $category][(string) $reason] = ($this->reports[(string) $category][(string) $reason] ?? 0) + $quantity;
}

public function flush(): void
{
$reports = [];
foreach ($this->reports as $category => $reasons) {
foreach ($reasons as $reason => $quantity) {
$reports[] = new ClientReport($category, $reason, $quantity);
}
}
$event = Event::createClientReport();
$event->setClientReports($reports);

HubAdapter::getInstance()->captureEvent($event);
$this->reports = [];
}

public static function getInstance(): self
{
if (self::$instance === null) {
self::$instance = new self();
}

return self::$instance;
}
}
102 changes: 102 additions & 0 deletions src/ClientReport/Reason.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

namespace Sentry\ClientReport;

class Reason
{

/**
* @var string
*/
private $value;

private static $instances = [];

public function __construct(string $value)
{
$this->value = $value;
}

public static function queueOverflow(): self
{
return self::getInstance('queue_overflow');
}

public static function cacheOverflow(): self
{
return self::getInstance('cache_overflow');
}

public static function bufferOverflow(): self
{
return self::getInstance('buffer_overflow');
}

public static function ratelimitBackoff(): self
{
return self::getInstance('ratelimit_backoff');
}

public static function networkError(): self
{
return self::getInstance('network_error');
}

public static function sampleRate(): self
{
return self::getInstance('sample_rate');
}

public static function beforeSend(): self
{
return self::getInstance('before_send');
}

public static function eventProcessor(): self
{
return self::getInstance('event_processor');
}

public static function sendError(): self
{
return self::getInstance('send_error');
}

public static function internalSdkError(): self
{
return self::getInstance('internal_sdk_error');
}

public static function insufficientData(): self
{
return self::getInstance('insufficient_data');
}

public static function backpressure(): self
{
return self::getInstance('backpressure');
}

/**
* @return string
*/
public function getValue(): string
{
return $this->value;
}

public function __toString()
{
return $this->value;
}

private static function getInstance(string $value): self
{
if (!isset(self::$instances[$value])) {
self::$instances[$value] = new self($value);
}

return self::$instances[$value];
}

}
29 changes: 29 additions & 0 deletions src/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Sentry;

use Sentry\ClientReport\ClientReport;
use Sentry\Context\OsContext;
use Sentry\Context\RuntimeContext;
use Sentry\Logs\Log;
Expand Down Expand Up @@ -204,6 +205,11 @@ final class Event
*/
private $profile;

/**
* @var ClientReport[]
*/
private $clientReports;

private function __construct(?EventId $eventId, EventType $eventType)
{
$this->id = $eventId ?? EventId::generate();
Expand Down Expand Up @@ -249,6 +255,11 @@ public static function createMetrics(?EventId $eventId = null): self
return new self($eventId, EventType::metrics());
}

public static function createClientReport(?EventId $eventId = null): self
{
return new self($eventId, EventType::clientReport());
}

/**
* Gets the ID of this event.
*/
Expand Down Expand Up @@ -973,4 +984,22 @@ public function getTraceId(): ?string

return null;
}

/**
* @param ClientReport[] $clientReports
*/
public function setClientReports(array $clientReports): self
{
$this->clientReports = $clientReports;

return $this;
}

/**
* @return ClientReport[]
*/
public function getClientReports(): array
{
return $this->clientReports;
}
}
6 changes: 6 additions & 0 deletions src/EventType.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ public static function metrics(): self
return self::getInstance('metrics');
}

public static function clientReport(): self
{
return self::getInstance('client_report');
}

/**
* List of all cases on the enum.
*
Expand All @@ -68,6 +73,7 @@ public static function cases(): array
self::checkIn(),
self::logs(),
self::metrics(),
self::clientReport(),
];
}

Expand Down
8 changes: 8 additions & 0 deletions src/Logs/LogsAggregator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@

use Sentry\Attributes\Attribute;
use Sentry\Client;
use Sentry\ClientReport\ClientReportAggregator;
use Sentry\ClientReport\Reason;
use Sentry\Event;
use Sentry\EventId;
use Sentry\SentrySdk;
use Sentry\State\HubInterface;
use Sentry\State\Scope;
use Sentry\Transport\DataCategory;
use Sentry\Util\Arr;
use Sentry\Util\Str;

Expand All @@ -35,6 +38,11 @@ public function add(
array $values = [],
array $attributes = []
): void {
if (\count($this->logs) > 5) {
ClientReportAggregator::getInstance()->add(DataCategory::logBytes(), Reason::bufferOverflow(), 1);

return;
}
$timestamp = microtime(true);

$hub = SentrySdk::getCurrentHub();
Expand Down
30 changes: 30 additions & 0 deletions src/Serializer/EnvelopItems/ClientReportItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Sentry\Serializer\EnvelopItems;

use Sentry\ClientReport\ClientReport;
use Sentry\Event;

class ClientReportItem implements EnvelopeItemInterface
{
public static function toEnvelopeItem(Event $event): ?string
{
$reports = $event->getClientReports();

$headers = ['type' => 'client_report'];
$body = [
'timestamp' => time(),
'discarded_events' => array_map(function (ClientReport $report) {
return [
'category' => $report->getCategory(),
'reason' => $report->getReason(),
'quantity' => $report->getQuantity(),
];
}, $reports),
];

return \sprintf("%s\n%s", json_encode($headers), json_encode($body));
}
}
Loading