Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/console/plugin/DarkConsoleServicesPlugin.php b/src/applications/console/plugin/DarkConsoleServicesPlugin.php
index a14ed4b541..4a26665e0a 100644
--- a/src/applications/console/plugin/DarkConsoleServicesPlugin.php
+++ b/src/applications/console/plugin/DarkConsoleServicesPlugin.php
@@ -1,315 +1,315 @@
<?php
final class DarkConsoleServicesPlugin extends DarkConsolePlugin {
protected $observations;
public function getName() {
return pht('Services');
}
public function getDescription() {
return pht('Information about services.');
}
public static function getQueryAnalyzerHeader() {
return 'X-Phabricator-QueryAnalyzer';
}
public static function isQueryAnalyzerRequested() {
if (!empty($_REQUEST['__analyze__'])) {
return true;
}
$header = AphrontRequest::getHTTPHeader(self::getQueryAnalyzerHeader());
if ($header) {
return true;
}
return false;
}
public function didStartup() {
$should_analyze = self::isQueryAnalyzerRequested();
if ($should_analyze) {
PhutilServiceProfiler::getInstance()
->setCollectStackTraces(true);
}
return null;
}
/**
* @phutil-external-symbol class PhabricatorStartup
*/
public function generateData() {
$should_analyze = self::isQueryAnalyzerRequested();
$log = PhutilServiceProfiler::getInstance()->getServiceCallLog();
foreach ($log as $key => $entry) {
$config = idx($entry, 'config', array());
unset($log[$key]['config']);
if (!$should_analyze) {
$log[$key]['explain'] = array(
'sev' => 7,
'size' => null,
'reason' => pht('Disabled'),
);
// Query analysis is disabled for this request, so don't do any of it.
continue;
}
if ($entry['type'] != 'query') {
continue;
}
// For each SELECT query, go issue an EXPLAIN on it so we can flag stuff
// causing table scans, etc.
if (preg_match('/^\s*SELECT\b/i', $entry['query'])) {
$conn = PhabricatorDatabaseRef::newRawConnection($entry['config']);
try {
$explain = queryfx_all(
$conn,
'EXPLAIN %Q',
$entry['query']);
$badness = 0;
$size = 1;
$reason = null;
foreach ($explain as $table) {
$size *= (int)$table['rows'];
switch ($table['type']) {
case 'index':
$cur_badness = 1;
$cur_reason = 'Index';
break;
case 'const':
$cur_badness = 1;
$cur_reason = 'Const';
break;
case 'eq_ref';
$cur_badness = 2;
$cur_reason = 'EqRef';
break;
case 'range':
$cur_badness = 3;
$cur_reason = 'Range';
break;
case 'ref':
$cur_badness = 3;
$cur_reason = 'Ref';
break;
case 'fulltext':
$cur_badness = 3;
$cur_reason = 'Fulltext';
break;
case 'ALL':
if (preg_match('/Using where/', $table['Extra'])) {
if ($table['rows'] < 256 && !empty($table['possible_keys'])) {
$cur_badness = 2;
$cur_reason = pht('Small Table Scan');
} else {
$cur_badness = 6;
$cur_reason = pht('TABLE SCAN!');
}
} else {
$cur_badness = 3;
$cur_reason = pht('Whole Table');
}
break;
default:
if (preg_match('/No tables used/i', $table['Extra'])) {
$cur_badness = 1;
$cur_reason = pht('No Tables');
} else if (preg_match('/Impossible/i', $table['Extra'])) {
$cur_badness = 1;
$cur_reason = pht('Empty');
} else {
$cur_badness = 4;
$cur_reason = pht("Can't Analyze");
}
break;
}
if ($cur_badness > $badness) {
$badness = $cur_badness;
$reason = $cur_reason;
}
}
$log[$key]['explain'] = array(
'sev' => $badness,
'size' => $size,
'reason' => $reason,
);
} catch (Exception $ex) {
$log[$key]['explain'] = array(
'sev' => 5,
'size' => null,
'reason' => $ex->getMessage(),
);
}
}
}
return array(
'start' => PhabricatorStartup::getStartTime(),
'end' => microtime(true),
'log' => $log,
'analyzeURI' => (string)$this
->getRequestURI()
->alter('__analyze__', true),
'didAnalyze' => $should_analyze,
);
}
public function renderPanel() {
$data = $this->getData();
$log = $data['log'];
$results = array();
$results[] = phutil_tag(
'div',
array('class' => 'dark-console-panel-header'),
array(
phutil_tag(
'a',
array(
'href' => $data['analyzeURI'],
'class' => $data['didAnalyze'] ?
'disabled button' : 'button button-green',
),
pht('Analyze Query Plans')),
phutil_tag('h1', array(), pht('Calls to External Services')),
phutil_tag('div', array('style' => 'clear: both;')),
));
$page_total = $data['end'] - $data['start'];
$totals = array();
$counts = array();
foreach ($log as $row) {
$totals[$row['type']] = idx($totals, $row['type'], 0) + $row['duration'];
$counts[$row['type']] = idx($counts, $row['type'], 0) + 1;
}
$totals['All Services'] = array_sum($totals);
$counts['All Services'] = array_sum($counts);
$totals['Entire Page'] = $page_total;
$counts['Entire Page'] = 0;
$summary = array();
foreach ($totals as $type => $total) {
$summary[] = array(
$type,
number_format($counts[$type]),
pht('%s us', new PhutilNumber((int)(1000000 * $totals[$type]))),
sprintf('%.1f%%', 100 * $totals[$type] / $page_total),
);
}
$summary_table = new AphrontTableView($summary);
$summary_table->setColumnClasses(
array(
'',
'n',
'n',
'wide',
));
$summary_table->setHeaders(
array(
pht('Type'),
pht('Count'),
pht('Total Cost'),
pht('Page Weight'),
));
$results[] = $summary_table->render();
$rows = array();
foreach ($log as $row) {
$analysis = null;
switch ($row['type']) {
case 'query':
$info = $row['query'];
$info = wordwrap($info, 128, "\n", true);
if (!empty($row['explain'])) {
$analysis = phutil_tag(
'span',
array(
'class' => 'explain-sev-'.$row['explain']['sev'],
),
$row['explain']['reason']);
}
break;
case 'connect':
$info = $row['host'].':'.$row['database'];
break;
case 'exec':
$info = $row['command'];
break;
case 's3':
case 'conduit':
$info = $row['method'];
break;
case 'http':
$info = $row['uri'];
break;
default:
$info = '-';
break;
}
$offset = ($row['begin'] - $data['start']);
$rows[] = array(
$row['type'],
pht('+%s ms', new PhutilNumber(1000 * $offset)),
pht('%s us', new PhutilNumber(1000000 * $row['duration'])),
$info,
$analysis,
);
- if ($row['trace']) {
+ if (isset($row['trace'])) {
$rows[] = array(
null,
null,
null,
$row['trace'],
null,
);
}
}
$table = new AphrontTableView($rows);
$table->setColumnClasses(
array(
null,
'n',
'n',
'wide prewrap',
'',
));
$table->setHeaders(
array(
pht('Event'),
pht('Start'),
pht('Duration'),
pht('Details'),
pht('Analysis'),
));
$results[] = $table->render();
return phutil_implode_html("\n", $results);
}
}
diff --git a/src/applications/search/fulltextstorage/PhabricatorFerretFulltextStorageEngine.php b/src/applications/search/fulltextstorage/PhabricatorFerretFulltextStorageEngine.php
index a7d9570c57..fa03bcafdd 100644
--- a/src/applications/search/fulltextstorage/PhabricatorFerretFulltextStorageEngine.php
+++ b/src/applications/search/fulltextstorage/PhabricatorFerretFulltextStorageEngine.php
@@ -1,127 +1,127 @@
<?php
final class PhabricatorFerretFulltextStorageEngine
extends PhabricatorFulltextStorageEngine {
private $fulltextTokens = array();
private $engineLimits;
public function getEngineIdentifier() {
return 'mysql';
}
public function getHostType() {
return new PhabricatorMySQLSearchHost($this);
}
public function reindexAbstractDocument(
PhabricatorSearchAbstractDocument $doc) {
// NOTE: The Ferret engine indexes are rebuilt by an extension rather than
// by the main fulltext engine, and are always built regardless of
// configuration.
return;
}
public function executeSearch(PhabricatorSavedQuery $query) {
$all_objects = id(new PhutilClassMapQuery())
->setAncestorClass('PhabricatorFerretInterface')
->execute();
$type_map = array();
foreach ($all_objects as $object) {
$phid_type = phid_get_type($object->generatePHID());
$type_map[$phid_type] = array(
'object' => $object,
'engine' => $object->newFerretEngine(),
);
}
$types = $query->getParameter('types');
if ($types) {
$type_map = array_select_keys($type_map, $types);
}
$offset = (int)$query->getParameter('offset', 0);
$limit = (int)$query->getParameter('limit', 25);
// NOTE: For now, it's okay to query with the omnipotent viewer here
// because we're just returning PHIDs which we'll filter later.
$viewer = PhabricatorUser::getOmnipotentUser();
$type_results = array();
$metadata = array();
foreach ($type_map as $type => $spec) {
$engine = $spec['engine'];
$object = $spec['object'];
$local_query = new PhabricatorSavedQuery();
$local_query->setParameter('query', $query->getParameter('query'));
$project_phids = $query->getParameter('projectPHIDs');
if ($project_phids) {
$local_query->setParameter('projectPHIDs', $project_phids);
}
$subscriber_phids = $query->getParameter('subscriberPHIDs');
if ($subscriber_phids) {
$local_query->setParameter('subscriberPHIDs', $subscriber_phids);
}
$search_engine = $engine->newSearchEngine()
->setViewer($viewer);
$engine_query = $search_engine->buildQueryFromSavedQuery($local_query)
->setViewer($viewer);
$engine_query
->withFerretQuery($engine, $query)
->setOrder('relevance')
->setLimit($offset + $limit);
$results = $engine_query->execute();
$results = mpull($results, null, 'getPHID');
$type_results[$type] = $results;
$metadata += $engine_query->getFerretMetadata();
if (!$this->fulltextTokens) {
$this->fulltextTokens = $engine_query->getFerretTokens();
}
}
$list = array();
foreach ($type_results as $type => $results) {
$list += $results;
}
// Currently, the list is grouped by object type. For example, all the
// tasks might be first, then all the revisions, and so on. In each group,
// the results are ordered properly.
// Reorder the results so that the highest-ranking results come first,
// no matter which object types they belong to.
- $metadata = msort($metadata, 'getRelevanceSortVector');
+ $metadata = msortv($metadata, 'getRelevanceSortVector');
$list = array_select_keys($list, array_keys($metadata)) + $list;
$result_slice = array_slice($list, $offset, $limit, true);
return array_keys($result_slice);
}
public function indexExists() {
return true;
}
public function getIndexStats() {
return false;
}
public function getFulltextTokens() {
return $this->fulltextTokens;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Nov 6, 4:20 AM (21 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
321452
Default Alt Text
(12 KB)

Event Timeline