Skip to content

Commit 24f79f9

Browse files
[Magento Community Engineering] Community Contributions - 2.4-develop-fast-lane-prs
- merged with '2.4-develop-expedited-prs' branch
2 parents 590d936 + 995e4a7 commit 24f79f9

File tree

7 files changed

+400
-22
lines changed

7 files changed

+400
-22
lines changed

app/code/Magento/Cron/Observer/ProcessCronQueueObserver.php

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
67
/**
78
* Handling cron jobs
89
*/
10+
911
namespace Magento\Cron\Observer;
1012

1113
use Magento\Cron\Model\Schedule;
@@ -69,6 +71,11 @@ class ProcessCronQueueObserver implements ObserverInterface
6971
*/
7072
const LOCK_PREFIX = 'CRON_GROUP_';
7173

74+
/**
75+
* Cron Job name pattern for Profiling
76+
*/
77+
const CRON_TIMERID = 'job %s';
78+
7279
/**
7380
* @var \Magento\Cron\Model\ResourceModel\Schedule\Collection
7481
*/
@@ -311,7 +318,7 @@ protected function _runJob($scheduledTime, $currentTime, $jobConfig, $schedule,
311318

312319
$schedule->setExecutedAt(strftime('%Y-%m-%d %H:%M:%S', $this->dateTime->gmtTimestamp()))->save();
313320

314-
$this->startProfiling();
321+
$this->startProfiling($jobCode);
315322
try {
316323
$this->logger->info(sprintf('Cron Job %s is run', $jobCode));
317324
//phpcs:ignore Magento2.Functions.DiscouragedFunction
@@ -323,7 +330,7 @@ protected function _runJob($scheduledTime, $currentTime, $jobConfig, $schedule,
323330
'Cron Job %s has an error: %s. Statistics: %s',
324331
$jobCode,
325332
$e->getMessage(),
326-
$this->getProfilingStat()
333+
$this->getProfilingStat($jobCode)
327334
)
328335
);
329336
if (!$e instanceof \Exception) {
@@ -335,7 +342,7 @@ protected function _runJob($scheduledTime, $currentTime, $jobConfig, $schedule,
335342
}
336343
throw $e;
337344
} finally {
338-
$this->stopProfiling();
345+
$this->stopProfiling($jobCode);
339346
}
340347

341348
$schedule->setStatus(
@@ -351,40 +358,55 @@ protected function _runJob($scheduledTime, $currentTime, $jobConfig, $schedule,
351358
sprintf(
352359
'Cron Job %s is successfully finished. Statistics: %s',
353360
$jobCode,
354-
$this->getProfilingStat()
361+
$this->getProfilingStat($jobCode)
355362
)
356363
);
357364
}
358365

359366
/**
360367
* Starts profiling
361368
*
369+
* @param string $jobName
362370
* @return void
363371
*/
364-
private function startProfiling()
372+
private function startProfiling(string $jobName = '')
365373
{
366374
$this->statProfiler->clear();
367-
$this->statProfiler->start('job', microtime(true), memory_get_usage(true), memory_get_usage());
375+
$this->statProfiler->start(
376+
sprintf(self::CRON_TIMERID, $jobName),
377+
microtime(true),
378+
memory_get_usage(true),
379+
memory_get_usage()
380+
);
368381
}
369382

370383
/**
371384
* Stops profiling
372385
*
386+
* @param string $jobName
373387
* @return void
374388
*/
375-
private function stopProfiling()
389+
private function stopProfiling(string $jobName = '')
376390
{
377-
$this->statProfiler->stop('job', microtime(true), memory_get_usage(true), memory_get_usage());
391+
$this->statProfiler->stop(
392+
sprintf(self::CRON_TIMERID, $jobName),
393+
microtime(true),
394+
memory_get_usage(true),
395+
memory_get_usage()
396+
);
378397
}
379398

380399
/**
381400
* Retrieves statistics in the JSON format
382401
*
402+
* @param string $jobName
383403
* @return string
384404
*/
385-
private function getProfilingStat()
405+
private function getProfilingStat(string $jobName): string
386406
{
387-
$stat = $this->statProfiler->get('job');
407+
$stat = $this->statProfiler->get(
408+
sprintf(self::CRON_TIMERID, $jobName)
409+
);
388410
unset($stat[Stat::START]);
389411
return json_encode($stat);
390412
}
@@ -418,7 +440,9 @@ private function getNonExitedSchedules($groupId)
418440
'status',
419441
[
420442
'in' => [
421-
Schedule::STATUS_PENDING, Schedule::STATUS_RUNNING, Schedule::STATUS_SUCCESS
443+
Schedule::STATUS_PENDING,
444+
Schedule::STATUS_RUNNING,
445+
Schedule::STATUS_SUCCESS
422446
]
423447
]
424448
);
@@ -478,10 +502,10 @@ private function generateSchedules($groupId)
478502
/**
479503
* Generate jobs for config information
480504
*
481-
* @param array $jobs
482-
* @param array $exists
483-
* @param string $groupId
484-
* @return void
505+
* @param array $jobs
506+
* @param array $exists
507+
* @param string $groupId
508+
* @return void
485509
*/
486510
protected function _generateJobs($jobs, $exists, $groupId)
487511
{

app/code/Magento/NewRelicReporting/Model/NewRelicWrapper.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
*/
66
namespace Magento\NewRelicReporting\Model;
77

8+
use Exception;
9+
810
/**
911
* Wrapper for New Relic functions
1012
*
@@ -31,10 +33,10 @@ public function addCustomParameter($param, $value)
3133
/**
3234
* Wrapper for 'newrelic_notice_error' function
3335
*
34-
* @param \Exception $exception
36+
* @param Exception $exception
3537
* @return void
3638
*/
37-
public function reportError($exception)
39+
public function reportError(Exception $exception)
3840
{
3941
if ($this->isExtensionInstalled()) {
4042
newrelic_notice_error($exception->getMessage(), $exception);
@@ -67,6 +69,19 @@ public function setTransactionName(string $transactionName): void
6769
}
6870
}
6971

72+
/**
73+
* Wrapper for 'newrelic_end_transaction'
74+
*
75+
* @param bool $ignore
76+
* @return void
77+
*/
78+
public function endTransaction($ignore = false)
79+
{
80+
if ($this->isExtensionInstalled()) {
81+
newrelic_end_transaction($ignore);
82+
}
83+
}
84+
7085
/**
7186
* Checks whether newrelic-php5 agent is installed
7287
*

app/code/Magento/NewRelicReporting/Plugin/CommandPlugin.php

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,24 @@ class CommandPlugin
2525
*/
2626
private $newRelicWrapper;
2727

28+
/**
29+
* @var string[]
30+
*/
31+
private $skipCommands;
32+
2833
/**
2934
* @param Config $config
3035
* @param NewRelicWrapper $newRelicWrapper
36+
* @param array $skipCommands
3137
*/
3238
public function __construct(
3339
Config $config,
34-
NewRelicWrapper $newRelicWrapper
40+
NewRelicWrapper $newRelicWrapper,
41+
array $skipCommands = []
3542
) {
3643
$this->config = $config;
3744
$this->newRelicWrapper = $newRelicWrapper;
45+
$this->skipCommands = $skipCommands;
3846
}
3947

4048
/**
@@ -46,10 +54,24 @@ public function __construct(
4654
*/
4755
public function beforeRun(Command $command, ...$args)
4856
{
49-
$this->newRelicWrapper->setTransactionName(
50-
sprintf('CLI %s', $command->getName())
51-
);
57+
if (!$this->isCommandSkipped($command)) {
58+
$this->newRelicWrapper->setTransactionName(
59+
sprintf('CLI %s', $command->getName())
60+
);
61+
}
5262

5363
return $args;
5464
}
65+
66+
/**
67+
* Determines whether the Command is declared to be skipped
68+
*
69+
* @param Command $command
70+
* @return bool
71+
*/
72+
private function isCommandSkipped(Command $command): bool
73+
{
74+
$commandName = $command->getName();
75+
return isset($this->skipCommands[$commandName]) && $this->skipCommands[$commandName] === true;
76+
}
5577
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\NewRelicReporting\Plugin;
9+
10+
use Magento\Framework\Profiler\Driver\Standard\Stat;
11+
use Magento\NewRelicReporting\Model\Config;
12+
use Magento\NewRelicReporting\Model\NewRelicWrapper;
13+
use Psr\Log\LoggerInterface;
14+
15+
/**
16+
* Class StatPlugin handles single Cron Jobs transaction names
17+
*/
18+
class StatPlugin
19+
{
20+
public const TIMER_NAME_CRON_PREFIX = 'job';
21+
22+
/**
23+
* @var Config
24+
*/
25+
private $config;
26+
27+
/**
28+
* @var NewRelicWrapper
29+
*/
30+
private $newRelicWrapper;
31+
32+
/**
33+
* @var LoggerInterface
34+
*/
35+
private $logger;
36+
37+
/**
38+
* @param Config $config
39+
* @param NewRelicWrapper $newRelicWrapper
40+
* @param LoggerInterface $logger
41+
*/
42+
public function __construct(
43+
Config $config,
44+
NewRelicWrapper $newRelicWrapper,
45+
LoggerInterface $logger
46+
) {
47+
$this->config = $config;
48+
$this->newRelicWrapper = $newRelicWrapper;
49+
$this->logger = $logger;
50+
}
51+
52+
/**
53+
* Before running original profiler, register NewRelic transaction
54+
*
55+
* @param Stat $schedule
56+
* @param array $args
57+
* @return array
58+
* @see \Magento\Cron\Observer\ProcessCronQueueObserver::startProfiling
59+
*
60+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
61+
*/
62+
public function beforeStart(Stat $schedule, ...$args): array
63+
{
64+
$timerName = current($args);
65+
66+
if ($this->isCronJob($timerName)) {
67+
$this->newRelicWrapper->setTransactionName(
68+
sprintf('Cron %s', $timerName)
69+
);
70+
}
71+
72+
return $args;
73+
}
74+
75+
/**
76+
* Before stopping original profiler, close NewRelic transaction
77+
*
78+
* @param Stat $schedule
79+
* @param array $args
80+
* @return array
81+
*
82+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
83+
*/
84+
public function beforeStop(Stat $schedule, ...$args): array
85+
{
86+
$timerName = current($args);
87+
88+
if ($this->isCronJob($timerName)) {
89+
$this->newRelicWrapper->endTransaction();
90+
}
91+
92+
return $args;
93+
}
94+
95+
/**
96+
* Determines whether provided name is Cron Job
97+
*
98+
* @param string $timerName
99+
* @return bool
100+
*/
101+
private function isCronJob(string $timerName): bool
102+
{
103+
return 0 === strpos($timerName, static::TIMER_NAME_CRON_PREFIX);
104+
}
105+
}

0 commit comments

Comments
 (0)