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
15 changes: 9 additions & 6 deletions src/Logs/LogsAggregator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Sentry\Attributes\Attribute;
use Sentry\Client;
use Sentry\ClientInterface;
use Sentry\Event;
use Sentry\EventId;
use Sentry\SentrySdk;
Expand Down Expand Up @@ -159,20 +160,22 @@ public function add(
$logs->push($log);

if ($logFlushThreshold !== null && \count($logs) >= $logFlushThreshold) {
$this->flush($hub);
$this->flush($client);
}
}

public function flush(?HubInterface $hub = null): ?EventId
public function flush(?ClientInterface $client = null): ?EventId
{
if ($this->logs === null || $this->logs->isEmpty()) {
$logs = $this->logs;

if ($logs === null || $logs->isEmpty()) {
return null;
}

$hub = $hub ?? SentrySdk::getCurrentHub();
$event = Event::createLogs()->setLogs($this->logs->drain());
$client = $client ?? SentrySdk::getCurrentHub()->getClient();
$event = Event::createLogs()->setLogs($logs->drain());

return $hub->captureEvent($event);
return $client->captureEvent($event);
}

/**
Expand Down
15 changes: 9 additions & 6 deletions src/Metrics/MetricsAggregator.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Sentry\Metrics;

use Sentry\Client;
use Sentry\ClientInterface;
use Sentry\Event;
use Sentry\EventId;
use Sentry\Metrics\Types\CounterMetric;
Expand Down Expand Up @@ -124,20 +125,22 @@ public function add(
$metrics->push($metric);

if ($metricFlushThreshold !== null && \count($metrics) >= $metricFlushThreshold) {
$this->flush($hub);
$this->flush($client);
}
}

public function flush(?HubInterface $hub = null): ?EventId
public function flush(?ClientInterface $client = null): ?EventId
{
if ($this->metrics === null || $this->metrics->isEmpty()) {
$metrics = $this->metrics;

if ($metrics === null || $metrics->isEmpty()) {
return null;
}

$hub = $hub ?? SentrySdk::getCurrentHub();
$event = Event::createMetrics()->setMetrics($this->metrics->drain());
$client = $client ?? SentrySdk::getCurrentHub()->getClient();
$event = Event::createMetrics()->setMetrics($metrics->drain());

return $hub->captureEvent($event);
return $client->captureEvent($event);
}

/**
Expand Down
8 changes: 3 additions & 5 deletions src/State/RuntimeContextManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,12 @@ private function removeContextById(string $runtimeContextId, ?int $timeout = nul

private function flushRuntimeContextResources(RuntimeContext $runtimeContext, ?int $timeout, LoggerInterface $logger): void
{
$hub = $runtimeContext->getHub();
$client = $runtimeContext->getHub()->getClient();

// captureEvent can throw before transport send (for example from scope event processors
// or before_send callbacks), so we isolate failures and continue flushing other resources.
try {
$runtimeContext->getLogsAggregator()->flush($hub);
$runtimeContext->getLogsAggregator()->flush($client);
} catch (\Throwable $exception) {
$logger->error('Failed to flush logs while ending a runtime context.', [
'exception' => $exception,
Expand All @@ -176,16 +176,14 @@ private function flushRuntimeContextResources(RuntimeContext $runtimeContext, ?i

// Keep metrics flush independent from logs flush so one bad callback does not block the rest.
try {
$runtimeContext->getMetricsAggregator()->flush($hub);
$runtimeContext->getMetricsAggregator()->flush($client);
} catch (\Throwable $exception) {
$logger->error('Failed to flush trace metrics while ending a runtime context.', [
'exception' => $exception,
'runtime_context_id' => $runtimeContext->getId(),
]);
}

$client = $hub->getClient();

// Custom transports may throw from close(); endContext must stay best-effort and non-fatal.
try {
$client->flush($timeout);
Expand Down
36 changes: 36 additions & 0 deletions tests/Logs/LogsAggregatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
use PHPUnit\Framework\TestCase;
use Sentry\Client;
use Sentry\ClientBuilder;
use Sentry\ClientInterface;
use Sentry\Event;
use Sentry\Logs\LogLevel;
use Sentry\Logs\LogsAggregator;
use Sentry\Options;
use Sentry\SentrySdk;
use Sentry\State\Hub;
use Sentry\State\Scope;
Expand Down Expand Up @@ -271,6 +274,39 @@ public function testFlushesImmediatelyWhenThresholdIsReached(): void
$this->assertSame('Second message', StubTransport::$events[0]->getLogs()[1]->getBody());
}

public function testFlushCapturesLogsWithProvidedClient(): void
{
$client = $this->createMock(ClientInterface::class);
$client->method('getOptions')
->willReturn(new Options([
'enable_logs' => true,
]));

$fallbackClient = $this->createMock(ClientInterface::class);
$fallbackClient->method('getOptions')
->willReturn(new Options([
'enable_logs' => true,
]));
$fallbackClient->expects($this->never())
->method('captureEvent');
SentrySdk::setCurrentHub(new Hub($fallbackClient));

$aggregator = new LogsAggregator();
$aggregator->add(LogLevel::info(), 'Test message');

$client->expects($this->once())
->method('captureEvent')
->with(
$this->callback(function (Event $event): bool {
$this->assertCount(1, $event->getLogs());

return true;
})
);

$aggregator->flush($client);
}

public function testDoesNotFlushImmediatelyWhenThresholdIsNull(): void
{
StubTransport::$events = [];
Expand Down
37 changes: 37 additions & 0 deletions tests/Metrics/TraceMetricsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@

use PHPUnit\Framework\TestCase;
use Sentry\Client;
use Sentry\ClientInterface;
use Sentry\Event;
use Sentry\Metrics\MetricsAggregator;
use Sentry\Metrics\Types\CounterMetric;
use Sentry\Metrics\Types\DistributionMetric;
use Sentry\Metrics\Types\GaugeMetric;
use Sentry\Metrics\Types\Metric;
use Sentry\Options;
use Sentry\SentrySdk;
use Sentry\State\Hub;
use Sentry\State\HubAdapter;
use Sentry\State\Scope;

Expand Down Expand Up @@ -110,6 +114,39 @@ public function testDoesNotFlushImmediatelyWhenMetricFlushThresholdIsNull(): voi
$this->assertCount(2, StubTransport::$events[0]->getMetrics());
}

public function testFlushCapturesMetricsWithProvidedClient(): void
{
$client = $this->createMock(ClientInterface::class);
$client->method('getOptions')
->willReturn(new Options([
'enable_metrics' => true,
]));

$fallbackClient = $this->createMock(ClientInterface::class);
$fallbackClient->method('getOptions')
->willReturn(new Options([
'enable_metrics' => true,
]));
$fallbackClient->expects($this->never())
->method('captureEvent');
SentrySdk::setCurrentHub(new Hub($fallbackClient));

$aggregator = new MetricsAggregator();
$aggregator->add(CounterMetric::TYPE, 'test-count', 2, ['foo' => 'bar'], null);

$client->expects($this->once())
->method('captureEvent')
->with(
$this->callback(function (Event $event): bool {
$this->assertCount(1, $event->getMetrics());

return true;
})
);

$aggregator->flush($client);
}

public function testMetricsBufferFullWhenMetricFlushThresholdIsNull(): void
{
HubAdapter::getInstance()->bindClient(new Client(new Options([
Expand Down