Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Sentry Developer Metrics #1619

Merged
merged 38 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
316f9ba
New Seralizer Types
cleptric Oct 30, 2023
631a7b8
Add DDM support
cleptric Oct 31, 2023
48183e0
Refactor code & add gauges
cleptric Nov 8, 2023
0564a0c
Make it a tad more DRY
cleptric Nov 8, 2023
69b4053
Add MetricsUnit
cleptric Nov 8, 2023
013ee65
Add tests
cleptric Nov 8, 2023
cb05d64
Make it clear that this is experimental
cleptric Nov 8, 2023
600c6e2
Add Seralizer test
cleptric Nov 8, 2023
efc781a
Fix test name
cleptric Nov 8, 2023
b8a9b1b
More comments
cleptric Nov 8, 2023
e253088
Add default tags
cleptric Nov 9, 2023
f893fe9
Change merge order
cleptric Nov 9, 2023
ea39e2d
CS
cleptric Nov 9, 2023
6a185d3
Move to statsd format
cleptric Dec 18, 2023
df90dcc
Add code locations & source context
cleptric Dec 18, 2023
b42e7ec
Fix code locations
cleptric Dec 19, 2023
8e66b4d
Attach metrics aggregations to spans
cleptric Dec 19, 2023
ca54624
Add support for sets in the metrics summary
cleptric Dec 20, 2023
c98a2a7
CS
cleptric Dec 20, 2023
cf23291
Cast min/max to float
cleptric Dec 20, 2023
4a1f4e8
Add tests
cleptric Dec 20, 2023
a1f3aa7
CS
cleptric Dec 20, 2023
6f7b86b
Remove experimental functions file
cleptric Dec 20, 2023
06d7a31
Normalize tags
cleptric Dec 21, 2023
3d7c037
Improve readability
cleptric Dec 21, 2023
f3d960b
Cleanup
cleptric Dec 21, 2023
1006e01
Hash metric bucket keys with md5
cleptric Dec 21, 2023
e9e9120
Add `attach_metric_code_locations` option
cleptric Dec 21, 2023
6c4fa02
Static analyzer fixes
stayallive Dec 21, 2023
0b4de92
Fix indentation
stayallive Dec 21, 2023
5a8b852
Make metrics an non-null array
stayallive Dec 21, 2023
b421c07
CS
stayallive Dec 21, 2023
05f3de3
Remove invalid docblock
stayallive Dec 21, 2023
0456cc6
Fix PHP 7.x
stayallive Dec 21, 2023
e231896
psalm happy
stayallive Dec 21, 2023
28b8b63
Change dynamic construction
stayallive Dec 21, 2023
33bcf76
Fix gauge
stayallive Dec 21, 2023
c25e310
Update types
stayallive Dec 21, 2023
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
10 changes: 10 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ parameters:
count: 1
path: src/Logger/DebugStdOutLogger.php

-
message: "#^Method Sentry\\\\Metrics\\\\Types\\\\AbstractType\\:\\:add\\(\\) has parameter \\$value with no type specified\\.$#"
count: 1
path: src/Metrics/Types/AbstractType.php

-
message: "#^Parameter \\#1 \\$level of method Monolog\\\\Handler\\\\AbstractHandler\\:\\:__construct\\(\\) expects 100\\|200\\|250\\|300\\|400\\|500\\|550\\|600\\|'ALERT'\\|'alert'\\|'CRITICAL'\\|'critical'\\|'DEBUG'\\|'debug'\\|'EMERGENCY'\\|'emergency'\\|'ERROR'\\|'error'\\|'INFO'\\|'info'\\|'NOTICE'\\|'notice'\\|'WARNING'\\|'warning'\\|Monolog\\\\Level, int\\|Monolog\\\\Level\\|string given\\.$#"
count: 1
Expand Down Expand Up @@ -230,6 +235,11 @@ parameters:
count: 1
path: src/Options.php

-
message: "#^Method Sentry\\\\Options\\:\\:shouldAttachMetricCodeLocations\\(\\) should return bool but returns mixed\\.$#"
count: 1
path: src/Options.php

-
message: "#^Method Sentry\\\\Options\\:\\:shouldAttachStacktrace\\(\\) should return bool but returns mixed\\.$#"
count: 1
Expand Down
29 changes: 29 additions & 0 deletions src/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Sentry\Context\OsContext;
use Sentry\Context\RuntimeContext;
use Sentry\Metrics\Types\AbstractType;
use Sentry\Profiling\Profile;
use Sentry\Tracing\Span;

Expand Down Expand Up @@ -55,6 +56,11 @@ final class Event
*/
private $checkIn;

/**
* @var array<string, AbstractType> The metrics data
*/
private $metrics = [];

/**
* @var string|null The name of the server (e.g. the host name)
*/
Expand Down Expand Up @@ -210,6 +216,11 @@ public static function createCheckIn(?EventId $eventId = null): self
return new self($eventId, EventType::checkIn());
}

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

/**
* Gets the ID of this event.
*/
Expand Down Expand Up @@ -354,6 +365,24 @@ public function setCheckIn(?CheckIn $checkIn): self
return $this;
}

/**
* @return array<string, AbstractType>
*/
public function getMetrics(): array
{
return $this->metrics;
}

/**
* @param array<string, AbstractType> $metrics
*/
public function setMetrics(array $metrics): self
{
$this->metrics = $metrics;

return $this;
}

/**
* Gets the name of the server.
*/
Expand Down
5 changes: 5 additions & 0 deletions src/EventType.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ public static function checkIn(): self
return self::getInstance('check_in');
}

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

public function __toString(): string
{
return $this->value;
Expand Down
32 changes: 27 additions & 5 deletions src/Integration/FrameContextifierIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Sentry\Event;
use Sentry\Frame;
use Sentry\SentrySdk;
use Sentry\Stacktrace;
use Sentry\State\Scope;
Expand Down Expand Up @@ -65,6 +66,13 @@ public function setupOnce(): void
}
}

foreach ($event->getMetrics() as $metric) {
if ($metric->hasCodeLocation()) {
$frame = $metric->getCodeLocation();
$integration->addContextToStacktraceFrame($maxContextLines, $frame);
}
}

return $event;
});
}
Expand All @@ -78,16 +86,30 @@ public function setupOnce(): void
private function addContextToStacktraceFrames(int $maxContextLines, Stacktrace $stacktrace): void
{
foreach ($stacktrace->getFrames() as $frame) {
if ($frame->isInternal() || $frame->getAbsoluteFilePath() === null) {
if ($frame->isInternal()) {
continue;
}

$sourceCodeExcerpt = $this->getSourceCodeExcerpt($maxContextLines, $frame->getAbsoluteFilePath(), $frame->getLine());
$this->addContextToStacktraceFrame($maxContextLines, $frame);
}
}

$frame->setPreContext($sourceCodeExcerpt['pre_context']);
$frame->setContextLine($sourceCodeExcerpt['context_line']);
$frame->setPostContext($sourceCodeExcerpt['post_context']);
/**
* Contextifies the given frame.
*
* @param int $maxContextLines The maximum number of lines of code to read
*/
private function addContextToStacktraceFrame(int $maxContextLines, Frame $frame): void
{
if ($frame->getAbsoluteFilePath() === null) {
return;
}

$sourceCodeExcerpt = $this->getSourceCodeExcerpt($maxContextLines, $frame->getAbsoluteFilePath(), $frame->getLine());

$frame->setPreContext($sourceCodeExcerpt['pre_context']);
$frame->setContextLine($sourceCodeExcerpt['context_line']);
$frame->setPostContext($sourceCodeExcerpt['post_context']);
}

/**
Expand Down
135 changes: 135 additions & 0 deletions src/Metrics/Metrics.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?php

declare(strict_types=1);

namespace Sentry\Metrics;

use Sentry\EventId;
use Sentry\Metrics\Types\CounterType;
use Sentry\Metrics\Types\DistributionType;
use Sentry\Metrics\Types\GaugeType;
use Sentry\Metrics\Types\SetType;

final class Metrics
{
/**
* @var self|null
*/
private static $instance;

/**
* @var MetricsAggregator
*/
private $aggregator;

private function __construct()
{
$this->aggregator = new MetricsAggregator();
}

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

return self::$instance;
}

/**
* @param int|float $value
* @param string[] $tags
*/
public function increment(
string $key,
$value,
?MetricsUnit $unit = null,
array $tags = [],
?int $timestamp = null,
int $stackLevel = 0
): void {
$this->aggregator->add(
CounterType::TYPE,
$key,
$value,
$unit,
$tags,
$timestamp,
$stackLevel
);
}

/**
* @param int|float $value
* @param string[] $tags
*/
public function distribution(
string $key,
$value,
?MetricsUnit $unit = null,
array $tags = [],
?int $timestamp = null,
int $stackLevel = 0
): void {
$this->aggregator->add(
DistributionType::TYPE,
$key,
$value,
$unit,
$tags,
$timestamp,
$stackLevel
);
}

/**
* @param int|float $value
* @param string[] $tags
*/
public function gauge(
string $key,
$value,
?MetricsUnit $unit = null,
array $tags = [],
?int $timestamp = null,
int $stackLevel = 0
): void {
$this->aggregator->add(
GaugeType::TYPE,
$key,
$value,
$unit,
$tags,
$timestamp,
$stackLevel
);
}

/**
* @param int|string $value
* @param string[] $tags
*/
public function set(
string $key,
$value,
?MetricsUnit $unit = null,
array $tags = [],
?int $timestamp = null,
int $stackLevel = 0
): void {
$this->aggregator->add(
SetType::TYPE,
$key,
$value,
$unit,
$tags,
$timestamp,
$stackLevel
);
}

public function flush(): ?EventId
{
return $this->aggregator->flush();
}
}
Loading