Skip to content

Commit

Permalink
Option to set a frame processor on the profile
Browse files Browse the repository at this point in the history
  • Loading branch information
stayallive committed Jul 27, 2023
1 parent 15a028d commit 0a29499
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 8 deletions.
38 changes: 31 additions & 7 deletions src/Profiling/Profile.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@
* Type definition of the Sentry profile format.
* All fields are none otpional.
*
* @see https://develop.sentry.dev/sdk/sample-format/
* @see https://develop.sentry.dev/sdk/profiles/
*
* @phpstan-type SentryProfileFrame array{
* filename: string,
* abs_path: string,
* module: string|null,
* function: string,
* lineno: int,
* }
*
* @phpstan-type SentryProfile array{
* device: array{
Expand Down Expand Up @@ -44,11 +52,7 @@
* },
* version: string,
* profile: array{
* frames: array<int, array{
* function: string,
* filename: string,
* lineno: int|null,
* }>,
* frames: array<int, SentryProfileFrame>,
* samples: array<int, array{
* elapsed_since_start_ns: int,
* stack_id: int,
Expand Down Expand Up @@ -97,6 +101,11 @@ final class Profile
*/
private const MAX_PROFILE_DURATION = 30;

/**
* @var callable(SentryProfileFrame): SentryProfileFrame|null
*/
private static $frameProcessor;

/**
* @var float The start time of the profile as a Unix timestamp with microseconds
*/
Expand Down Expand Up @@ -189,14 +198,17 @@ public function getFormattedData(Event $event): ?array
$function = $file;
}

$frames[] = [
/** @var SentryProfileFrame $frame */
$frame = [
'filename' => $file,
'abs_path' => $absolutePath,
'module' => $module,
'function' => $function,
'lineno' => !empty($frame['line']) ? (int) $frame['line'] : null,
];

$frames[] = null !== self::$frameProcessor ? (self::$frameProcessor)($frame) : $frame;

$stacks[$stackId][] = $frameIndex;
++$frameIndex;
}
Expand Down Expand Up @@ -351,4 +363,16 @@ private function validateEvent(Event $event): bool

return true;
}

/**
* Set a callable to process each frame of the profile.
*
* @param callable(SentryProfileFrame $frame): SentryProfileFrame|null $frameProcessor
*
* @internal this method is used internally by framework SDKs to process each frame of the profile
*/
public static function setFrameProcessor(?callable $frameProcessor): void
{
self::$frameProcessor = $frameProcessor;
}
}
126 changes: 125 additions & 1 deletion tests/Profiling/ProfileTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ final class ProfileTest extends TestCase
/**
* @dataProvider formattedDataDataProvider
*/
public function testGetFormattedData(Event $event, array $excimerLog, $expectedData, ?Options $options = null): void
public function testGetFormattedData(Event $event, array $excimerLog, $expectedData, ?Options $options = null, ?callable $frameProcessor = null): void
{
Profile::setFrameProcessor($frameProcessor);

$profile = new Profile($options);
// 2022-02-28T09:41:00Z
$profile->setStartTimeStamp(1677573660.0000);
Expand Down Expand Up @@ -339,6 +341,128 @@ public static function formattedDataDataProvider(): \Generator
]),
];

yield 'With frame processor' => [
$event,
$excimerLog,
[
'device' => [
'architecture' => 'aarch64',
],
'event_id' => '815e57b4bb134056ab1840919834689d',
'os' => [
'name' => 'macOS',
'version' => '13.2.1',
'build_number' => '22D68',
],
'platform' => 'php',
'release' => '1.0.0',
'environment' => 'dev',
'runtime' => [
'name' => 'php',
'version' => '8.2.3',
],
'timestamp' => '2023-02-28T08:41:00.000+00:00',
'transaction' => [
'id' => 'fc9442f5aef34234bb22b9a615e30ccd',
'name' => 'GET /',
'trace_id' => '566e3688a61d4bc888951642d6f14a19',
'active_thread_id' => '0',
],
'version' => '1',
'profile' => [
'frames' => [
[
'filename' => '/var/www/html/index.php',
'abs_path' => '/var/www/html/index.php',
'module' => 'foo',
'function' => '/var/www/html/index.php',
'lineno' => 42,
],
[
'filename' => '/var/www/html/index.php',
'abs_path' => '/var/www/html/index.php',
'module' => 'foo',
'function' => '/var/www/html/index.php',
'lineno' => 42,
],
[
'filename' => '/var/www/html/function.php',
'abs_path' => '/var/www/html/function.php',
'module' => 'foo',
'function' => 'Function::doStuff',
'lineno' => 84,
],
[
'filename' => '/var/www/html/index.php',
'abs_path' => '/var/www/html/index.php',
'module' => 'foo',
'function' => '/var/www/html/index.php',
'lineno' => 42,
],
[
'filename' => '/var/www/html/function.php',
'abs_path' => '/var/www/html/function.php',
'module' => 'foo',
'function' => 'Function::doStuff',
'lineno' => 84,
],
[
'filename' => '/var/www/html/class.php',
'abs_path' => '/var/www/html/class.php',
'module' => 'foo',
'function' => 'Class\Something::run',
'lineno' => 42,
],
[
'filename' => '/var/www/html/index.php',
'abs_path' => '/var/www/html/index.php',
'module' => 'foo',
'function' => '{closure}',
'lineno' => 126,
],
],
'samples' => [
[
'elapsed_since_start_ns' => 1000000,
'stack_id' => 0,
'thread_id' => '0',
],
[
'elapsed_since_start_ns' => 2000000,
'stack_id' => 1,
'thread_id' => '0',
],
[
'elapsed_since_start_ns' => 3000000,
'stack_id' => 2,
'thread_id' => '0',
],
],
'stacks' => [
[
0,
],
[
1,
2,
],
[
3,
4,
5,
6,
],
],
],
],
null,
static function (array $data): array {
$data['module'] = 'foo';

return $data;
},
];

yield 'Too little samples' => [
$event,
[
Expand Down

0 comments on commit 0a29499

Please sign in to comment.