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 export digraph for profile #220

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
5 changes: 4 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ ENCRYPTER_KEY={encrypt-key}
SAFE_MIGRATIONS=true

# Queue
QUEUE_CONNECTION=sync
QUEUE_CONNECTION=roadrunner

# Broadcast
BROADCAST_CONNECTION=centrifugo

# Monolog
MONOLOG_DEFAULT_CHANNEL=default
Expand Down
1 change: 0 additions & 1 deletion app/modules/Profiler/Application/Handlers/StoreProfile.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
use Modules\Profiler\Interfaces\Jobs\StoreProfileHandler;
use Spiral\Queue\QueueInterface;

// TODO: refactor this, use repository
final readonly class StoreProfile implements EventHandlerInterface
{
public function __construct(
Expand Down
20 changes: 20 additions & 0 deletions app/modules/Profiler/Application/ProfilerBootloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,23 @@

use Modules\Profiler\Application\Mapper\EventTypeMapper;
use App\Application\Event\EventTypeRegistryInterface;
use Cycle\ORM\ORMInterface;
use Cycle\ORM\Select;
use Modules\Profiler\Application\Handlers\CalculateDiffsBetweenEdges;
use Modules\Profiler\Application\Handlers\CleanupEvent;
use Modules\Profiler\Application\Handlers\PrepareEdges;
use Modules\Profiler\Application\Handlers\PreparePeaks;
use Modules\Profiler\Application\Handlers\StoreProfile;
use Modules\Profiler\Domain\Edge;
use Modules\Profiler\Domain\EdgeFactoryInterface;
use Modules\Profiler\Domain\Profile;
use Modules\Profiler\Domain\ProfileEdgeRepositoryInterface;
use Modules\Profiler\Domain\ProfileFactoryInterface;
use Modules\Profiler\Domain\ProfileRepositoryInterface;
use Modules\Profiler\Integration\CycleOrm\EdgeFactory;
use Modules\Profiler\Integration\CycleOrm\ProfileEdgeRepository;
use Modules\Profiler\Integration\CycleOrm\ProfileFactory;
use Modules\Profiler\Integration\CycleOrm\ProfileRepository;
use Modules\Profiler\Interfaces\Queries\FindCallGraphByUuidHandler;
use Modules\Profiler\Interfaces\Queries\FindFlameChartByUuidHandler;
use Psr\Container\ContainerInterface;
Expand Down Expand Up @@ -56,6 +64,18 @@ public function defineSingletons(): array
): FindFlameChartByUuidHandler => $factory->make(FindFlameChartByUuidHandler::class, [
'bucket' => $storage->bucket('profiles'),
]),

ProfileRepositoryInterface::class => static fn(
ORMInterface $orm,
): ProfileRepositoryInterface => new ProfileRepository(
select: new Select(orm: $orm, role: Profile::class),
),

ProfileEdgeRepositoryInterface::class => static fn(
ORMInterface $orm,
): ProfileEdgeRepositoryInterface => new ProfileEdgeRepository(
select: new Select(orm: $orm, role: Edge::class),
),
];
}

Expand Down
17 changes: 17 additions & 0 deletions app/modules/Profiler/Application/Query/FindDigraphByUuid.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Modules\Profiler\Application\Query;

use App\Application\Domain\ValueObjects\Uuid;
use Spiral\Cqrs\QueryInterface;

final readonly class FindDigraphByUuid implements QueryInterface
{
public function __construct(
public Uuid $profileUuid,
public float $threshold = 0.01,
public bool $criticalPath = true,
) {}
}
2 changes: 1 addition & 1 deletion app/modules/Profiler/Domain/Edge.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
use Modules\Profiler\Domain\Edge\Diff;
use Modules\Profiler\Domain\Edge\Percents;

// TODO: add repository
#[Entity(
role: 'profile_edge',
repository: ProfileEdgeRepositoryInterface::class,
table: 'profile_edges',
)]
class Edge
Expand Down
3 changes: 2 additions & 1 deletion app/modules/Profiler/Domain/Profile.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
use Doctrine\Common\Collections\ArrayCollection;
use Modules\Profiler\Domain\Profile\Peaks;

// TODO: add repository
#[Entity(
role: 'profile',
repository: ProfileRepositoryInterface::class,
table: 'profiles',
)]
class Profile
Expand All @@ -25,6 +25,7 @@ class Profile
outerKey: 'profile_uuid',
orderBy: ['order' => 'ASC'],
fkOnDelete: 'CASCADE',
load: 'eager',
)]
public ArrayCollection $edges;

Expand Down
20 changes: 20 additions & 0 deletions app/modules/Profiler/Domain/ProfileEdgeRepositoryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Modules\Profiler\Domain;

use App\Application\Domain\ValueObjects\Uuid;
use Cycle\ORM\RepositoryInterface;

/**
* @template TEntity of Edge
* @extends RepositoryInterface<TEntity>
*/
interface ProfileEdgeRepositoryInterface extends RepositoryInterface
{
/**
* @return iterable<TEntity>
*/
public function getByProfileUuid(Uuid $profileUuid): iterable;
}
21 changes: 21 additions & 0 deletions app/modules/Profiler/Domain/ProfileRepositoryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Modules\Profiler\Domain;

use App\Application\Domain\ValueObjects\Uuid;
use App\Application\Exception\EntityNotFoundException;
use Cycle\ORM\RepositoryInterface;

/**
* @template TEntity of Profile
* @extends RepositoryInterface<TEntity>
*/
interface ProfileRepositoryInterface extends RepositoryInterface
{
/**
* @throws EntityNotFoundException
*/
public function getByUuid(Uuid $uuid): Profile;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Modules\Profiler\Integration\CycleOrm;

use App\Application\Domain\ValueObjects\Uuid;
use Cycle\ORM\Select\Repository;
use Modules\Profiler\Domain\ProfileEdgeRepositoryInterface;

final class ProfileEdgeRepository extends Repository implements ProfileEdgeRepositoryInterface
{
public function getByProfileUuid(Uuid $profileUuid): iterable
{
return $this->select()
->where('profile_uuid', $profileUuid)
->orderBy('order', 'ASC')
->fetchAll();
}
}
28 changes: 28 additions & 0 deletions app/modules/Profiler/Integration/CycleOrm/ProfileRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Modules\Profiler\Integration\CycleOrm;

use App\Application\Domain\ValueObjects\Uuid;
use App\Application\Exception\EntityNotFoundException;
use Cycle\ORM\Select\Repository;
use Modules\Profiler\Domain\Profile;
use Modules\Profiler\Domain\ProfileRepositoryInterface;

/**
* @extends ProfileRepositoryInterface<Profile>
*/
final class ProfileRepository extends Repository implements ProfileRepositoryInterface
{
public function getByUuid(Uuid $uuid): Profile
{
$profile = $this->findByPK($uuid);

if ($profile === null) {
throw new EntityNotFoundException('Profile not found');
}

return $profile;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Modules\Profiler\Interfaces\Http\Controllers;

use App\Application\Domain\ValueObjects\Uuid;
use App\Application\Exception\EntityNotFoundException;
use Modules\Profiler\Application\Query\FindDigraphByUuid;
use Spiral\Cqrs\QueryBusInterface;
use Spiral\Http\Exception\ClientException\NotFoundException;
use Spiral\Router\Annotation\Route;

final readonly class ShowDigraphAction
{
#[Route(route: 'profiler/<uuid>/digraph', name: 'profiler.show.digraph', methods: ['GET'], group: 'api')]
public function __invoke(
QueryBusInterface $bus,
Uuid $uuid,
): string {
try {
/** @var string $digraph */
$digraph = $bus->ask(
new FindDigraphByUuid(
profileUuid: $uuid,
),
);
} catch (EntityNotFoundException $e) {
throw new NotFoundException($e->getMessage());
}

return $digraph;
}
}
25 changes: 13 additions & 12 deletions app/modules/Profiler/Interfaces/Jobs/StoreProfileHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,16 @@

namespace Modules\Profiler\Interfaces\Jobs;

use Modules\Profiler\Domain\Edge\Cost;
use Modules\Profiler\Domain\Edge\Diff;
use Modules\Profiler\Domain\Edge\Percents;
use App\Application\Domain\ValueObjects\Uuid;
use Cycle\ORM\EntityManagerInterface;
use Cycle\ORM\ORMInterface;
use Modules\Profiler\Application\Query\FindTopFunctionsByUuid;
use Modules\Profiler\Domain\EdgeFactoryInterface;
use Modules\Profiler\Domain\Profile;
use Modules\Profiler\Domain\Edge;
use Modules\Profiler\Domain\ProfileRepositoryInterface;
use Spiral\Core\InvokerInterface;
use Spiral\Cqrs\QueryBusInterface;
use Spiral\Queue\JobHandler;

// TODO: refactor this, use repository
final class StoreProfileHandler extends JobHandler
{
private const BATCH_SIZE = 100;
Expand All @@ -26,7 +22,7 @@ public function __construct(
private readonly EdgeFactoryInterface $edgeFactory,
private readonly EntityManagerInterface $em,
private readonly QueryBusInterface $bus,
private readonly ORMInterface $orm,
private readonly ProfileRepositoryInterface $profiles,
InvokerInterface $invoker,
) {
parent::__construct($invoker);
Expand All @@ -41,25 +37,30 @@ public function invoke(array $payload): void
$batchSize = 0;
$i = 0;
foreach ($event['edges'] as $id => $edge) {
$parentUuid = null;
if ($edge['parent'] !== null && isset($parents[$edge['parent']])) {
$parentUuid = $parents[$edge['parent']];
}

$this->em->persist(
$edge = $this->edgeFactory->create(
profileUuid: $profileUuid,
order: $i++,
cost: new Cost(
cost: new Edge\Cost(
cpu: $edge['cost']['cpu'] ?? 0,
wt: $edge['cost']['wt'] ?? 0,
ct: $edge['cost']['ct'] ?? 0,
mu: $edge['cost']['mu'] ?? 0,
pmu: $edge['cost']['pmu'] ?? 0,
),
diff: new Diff(
diff: new Edge\Diff(
cpu: $edge['cost']['d_cpu'] ?? 0,
wt: $edge['cost']['d_wt'] ?? 0,
ct: $edge['cost']['d_ct'] ?? 0,
mu: $edge['cost']['d_mu'] ?? 0,
pmu: $edge['cost']['d_pmu'] ?? 0,
),
percents: new Percents(
percents: new Edge\Percents(
cpu: $edge['cost']['p_cpu'] ?? 0,
wt: $edge['cost']['p_wt'] ?? 0,
ct: $edge['cost']['p_ct'] ?? 0,
Expand All @@ -68,7 +69,7 @@ public function invoke(array $payload): void
),
callee: $edge['callee'],
caller: $edge['caller'],
parentUuid: $edge['parent'] ? $parents[$edge['parent']] ?? null : null,
parentUuid: $parentUuid,
),
);

Expand All @@ -82,7 +83,7 @@ public function invoke(array $payload): void
$batchSize++;
}

$profile = $this->orm->getRepository(Profile::class)->findByPK($profileUuid);
$profile = $this->profiles->getByUuid($profileUuid);
$functions = $this->bus->ask(new FindTopFunctionsByUuid(profileUuid: $profileUuid));

foreach ($functions['overall_totals'] as $metric => $value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,22 @@

namespace Modules\Profiler\Interfaces\Queries;

use App\Application\Domain\ValueObjects\Uuid;
use Cycle\ORM\ORMInterface;
use Modules\Profiler\Application\CallGraph\Node;
use Modules\Profiler\Application\Query\FindCallGraphByUuid;
use Modules\Profiler\Domain\Edge;
use Modules\Profiler\Domain\Profile;
use Modules\Profiler\Domain\ProfileRepositoryInterface;
use Spiral\Cqrs\Attribute\QueryHandler;

// TODO: refactor this, use repository
final readonly class FindCallGraphByUuidHandler
{
public function __construct(
private ORMInterface $orm,
private ProfileRepositoryInterface $profiles,
) {}

#[QueryHandler]
public function __invoke(FindCallGraphByUuid $query): array
{
$profile = $this->orm->getRepository(Profile::class)->findByPK($query->profileUuid);
$profile = $this->profiles->getByUuid($query->profileUuid);

$edges = $profile->edges;
$registered = [];
Expand All @@ -44,7 +41,7 @@ static function (array $carry, Edge $edge) use (&$registered, $query): array {

$registered[] = (string) $edge->getUuid();

if ($edge->getParentUuid() instanceof Uuid && \in_array((string) $edge->getParentUuid(), $registered, true)) {
if ($edge->getParentUuid() !== null && \in_array((string) $edge->getParentUuid(), $registered, true)) {
$carry['edges'][] = [
'data' => [
'source' => (string) $edge->getParentUuid(),
Expand Down
Loading
Loading