Skip to content

Commit

Permalink
feat(backend): Move tracing to only spans (#179)
Browse files Browse the repository at this point in the history
  • Loading branch information
cleptric committed May 2, 2024
1 parent 2b6c142 commit beccc8f
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 191 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"cakephp/plugin-installer": "^2.0.1",
"lcobucci/jwt": "^5.3",
"paragonie/csp-builder": "^3.0",
"sentry/sentry": "^4.7.0"
"sentry/sentry": "dev-only-spans"
},
"require-dev": {
"cakephp/bake": "^3.1.1",
Expand Down
222 changes: 146 additions & 76 deletions composer.lock

Large diffs are not rendered by default.

91 changes: 42 additions & 49 deletions src/Database/Log/SentryQueryLogger.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@

use Psr\Log\AbstractLogger;
use Sentry\SentrySdk;
use Sentry\Tracing\Span;
use Sentry\Tracing\SpanContext;
use Sentry\Tracing\SpanStatus;
use Sentry\Tracing\Spans\Span;
use Stringable;

class SentryQueryLogger extends AbstractLogger
{
private array $parentSpanStack = [];
private array $currentSpanStack = [];
// private array $parentSpanStack = [];
// private array $currentSpanStack = [];

/**
* @inheritDoc
Expand All @@ -26,69 +24,64 @@ public function log($level, string|Stringable $message, array $context = []): vo
return;
}

$dbTransactionSpan = null;
$loggedQueryContext = $context['query']->getContext();
if ($loggedQueryContext['query'] === 'BEGIN') {
$spanContext = new SpanContext();
$spanContext->setOp('db.transaction');
$spanContext->setData([
'db.system' => 'postgresql',
]);

$this->pushSpan($parentSpan->startChild($spanContext));
$dbTransactionSpan = Span::make()
->setAttribiute('sentry.op', 'db.transaction')
->setAttribiute('db.system', 'postgresql');

return;
}

if ($loggedQueryContext['query'] === 'COMMIT') {
$span = $this->popSpan();

if ($span !== null) {
$span->finish();
$span->setStatus(SpanStatus::ok());
if ($dbTransactionSpan !== null) {
$dbTransactionSpan->finish();
}

return;
}

$spanContext = new SpanContext();
$spanContext->setOp('db.sql.query');
$spanContext->setData([
'db.system' => 'postgresql',
]);
$spanContext->setDescription($loggedQueryContext['query']);
$spanContext->setStartTimestamp(microtime(true) - $loggedQueryContext['took'] / 1000);
$spanContext->setEndTimestamp($spanContext->getStartTimestamp() + $loggedQueryContext['took'] / 1000);
$parentSpan->startChild($spanContext);
$startTime = microtime(true) - $loggedQueryContext['took'] / 1_000;
$endTime = $startTime + $loggedQueryContext['took'] / 1_000;

Span::make()
->setName($loggedQueryContext['query'])
->setAttribiute('sentry.op', 'db.sql.query')
->setAttribiute('db.system', 'postgresql')
->setStartTimeUnixNanosetStartTime($startTime)
->setEndTimeUnixNanosetStartTime($endTime)
->finish();
}

/**
* @param \Sentry\Tracing\Span $span The span.
* @return void
*/
private function pushSpan(Span $span): void
{
$hub = SentrySdk::getCurrentHub();
// /**
// * @param \Sentry\Tracing\Span $span The span.
// * @return void
// */
// private function pushSpan(Span $span): void
// {
// $hub = SentrySdk::getCurrentHub();

$this->parentSpanStack[] = $hub->getSpan();
// $this->parentSpanStack[] = $hub->getSpan();

$hub->setSpan($span);
// $hub->setSpan($span);

$this->currentSpanStack[] = $span;
}
// $this->currentSpanStack[] = $span;
// }

/**
* @return \Sentry\Tracing\Span|null
*/
private function popSpan(): ?Span
{
if (count($this->currentSpanStack) === 0) {
return null;
}
// /**
// * @return \Sentry\Tracing\Span|null
// */
// private function popSpan(): ?Span
// {
// if (count($this->currentSpanStack) === 0) {
// return null;
// }

$parent = array_pop($this->parentSpanStack);
// $parent = array_pop($this->parentSpanStack);

SentrySdk::getCurrentHub()->setSpan($parent);
// SentrySdk::getCurrentHub()->setSpan($parent);

return array_pop($this->currentSpanStack);
}
// return array_pop($this->currentSpanStack);
// }
}
4 changes: 2 additions & 2 deletions src/Event/EventFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public static function createEvent(array $data): AbstractEvent
SentrySdk::getCurrentHub()->configureScope(function ($scope) use ($eventType): void {
$scope->setTag('event_type', $eventType);
});
SentrySdk::getCurrentHub()->getTransaction()->setName(
SentrySdk::getCurrentHub()->getTransaction()->getName() . ' - ' . $eventType
SentrySdk::getCurrentHub()->getSpan()->segmentSpan->setName(
SentrySdk::getCurrentHub()->getSpan()->segmentSpan->name . ' - ' . $eventType
);

switch ($eventType) {
Expand Down
45 changes: 26 additions & 19 deletions src/Http/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
use Cake\Http\Client\Response;
use Psr\Http\Message\RequestInterface;
use Sentry\SentrySdk;
use Sentry\Tracing\SpanContext;
use Sentry\Tracing\Spans\Span;
use Throwable;

class Client extends CakeClient
{
Expand All @@ -20,29 +21,35 @@ protected function _sendRequest(RequestInterface $request, array $options): Resp
$span = null;

if ($parentSpan !== null) {
$context = new SpanContext();
$context->setOp('http.client');
$context->setDescription(
sprintf(
'%s %s://%s%s',
strtoupper($request->getMethod()),
$request->getUri()->getScheme(),
$request->getUri()->getHost(),
$request->getUri()->getPath()
$span = Span::make()
->setName(
sprintf(
'%s %s://%s%s',
strtoupper($request->getMethod()),
$request->getUri()->getScheme(),
$request->getUri()->getHost(),
$request->getUri()->getPath()
)
)
);
$context->setData([
'http.query' => $request->getUri()->getQuery(),
'http.fragment' => $request->getUri()->getFragment(),
]);
$span = $parentSpan->startChild($context);
->setAttribiute('sentry.op', 'http.client')
->setAttribiute('http.query', $request->getUri()->getQuery())
->setAttribiute('http.fragment', $request->getUri()->getFragment())
->start();
}

$response = parent::_sendRequest($request, $options);
try {
$response = parent::_sendRequest($request, $options);
} catch (Throwable $e) {
if ($span !== null) {
$span->finish();
}
throw $e;
}

if ($span !== null) {
$span->setHttpStatus($response->getStatusCode());
$span->finish();
$span
->setAttribiute('http.response.status_code', (string)$response->getStatusCode())
->finish();
}

return $response;
Expand Down
43 changes: 15 additions & 28 deletions src/Middleware/SentryMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,9 @@
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Sentry\Metrics\MetricsUnit;
use Sentry\SentrySdk;
use Sentry\Tracing\SpanContext;
use Sentry\Tracing\TransactionContext;
use Sentry\Tracing\TransactionSource;
use Sentry\Tracing\Spans\Span;
use function microtime;
use function Sentry\metrics;
use function Sentry\startTransaction;

/**
* Sentry middleware
Expand All @@ -44,37 +40,29 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
$sentryTraceHeader = $request->getHeaderLine('sentry-trace');
$baggageHeader = $request->getHeaderLine('baggage');

$transactionContext = TransactionContext::fromHeaders($sentryTraceHeader, $baggageHeader)
->setOp('http.server')
$segmentSpan = Span::makeFromTrace($sentryTraceHeader, $baggageHeader)
->setAttribiute('sentry.op', 'http.server')
->setName($request->getMethod() . ' ' . $request->getUri()->getPath())
->setSource(TransactionSource::route())
->setStartTimestamp($requestStartTime);
->setStartTimeUnixNanosetStartTime($requestStartTime)
->start();

$transaction = startTransaction($transactionContext);

SentrySdk::getCurrentHub()->setSpan($transaction);

$spanContext = SpanContext::make()
->setOp('middleware.handle');
$span = $transaction->startChild($spanContext);

SentrySdk::getCurrentHub()->setSpan($span);
$span = Span::make()
->setAttribiute('sentry.op', 'middleware.handle')
->start();

$this->setupQueryLogging();

$response = $handler->handle($request);
// We don't want to trace 404 responses as they are not relevant for performance monitoring.
if ($response->getStatusCode() === 404) {
$transaction->setSampled(false);
}
// if ($response->getStatusCode() === 404) {
// $transaction->setSampled(false);
// }

$span->setHttpStatus($response->getStatusCode())
$span->finish();
$segmentSpan
->setAttribiute('http.response.status_code', (string)$response->getStatusCode())
->finish();

SentrySdk::getCurrentHub()->setSpan($transaction);

$transaction->setHttpStatus($response->getStatusCode());

metrics()->distribution(
key: 'gibpotato.gcp.mem_peak_usage',
value: memory_get_peak_usage(false),
Expand All @@ -83,8 +71,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface

EventManager::instance()->on(
'Server.terminate',
function (Event $event) use ($transaction): void {
$transaction->finish();
function (Event $event): void {
metrics()->flush();
},
);
Expand Down
30 changes: 15 additions & 15 deletions src/View/Helper/SentryHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

use Cake\View\Helper;
use Sentry\SentrySdk;
use Sentry\Tracing\Span;
use Sentry\Tracing\Spans\Span;

/**
* @property \Cake\View\Helper\HtmlHelper $Html
Expand All @@ -25,7 +25,7 @@ class SentryHelper extends Helper
protected array $_defaultConfig = [];

/**
* @var \Sentry\Tracing\Span|null
* @var \Sentry\Tracing\Spans\Span|null
*/
protected ?Span $span;

Expand All @@ -52,18 +52,18 @@ public function sentryTracingMeta(): ?string
);
}

/**
* @return string|null
*/
public function sentryBaggageMeta(): ?string
{
if (empty($this->span)) {
return null;
}
// /**
// * @return string|null
// */
// public function sentryBaggageMeta(): ?string
// {
// if (empty($this->span)) {
// return null;
// }

return $this->Html->meta(
'baggage',
$this->span->toBaggage()
);
}
// return $this->Html->meta(
// 'baggage',
// $this->span->toBaggage()
// );
// }
}
2 changes: 1 addition & 1 deletion templates/layout/default.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<?= $this->Html->charset() ?>
<meta name="viewport" content="width=device-width, initial-scale=1">
<?= $this->Sentry->sentryTracingMeta() ?>
<?= $this->Sentry->sentryBaggageMeta() ?>
<?php // $this->Sentry->sentryBaggageMeta() ?>
<?= $this->fetch('meta') ?>
<?= $this->Html->meta('icon') ?>
<title>
Expand Down

0 comments on commit beccc8f

Please sign in to comment.