View source
<?php
namespace Drupal\memcache_admin\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Link;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\memcache_admin\Event\MemcacheStatsEvent;
class MemcacheStatisticsController extends ControllerBase {
use MessengerTrait;
use StringTranslationTrait;
public function statsTable($bin = 'default') {
$bin = $this
->getBinMapping($bin);
$memcache = \Drupal::service('memcache.factory')
->get($bin, TRUE);
$event = new MemcacheStatsEvent($memcache, $bin);
$event_dispatcher = \Drupal::service('event_dispatcher');
$event_dispatcher
->dispatch(MemcacheStatsEvent::BUILD_MEMCACHE_STATS, $event);
if ($memcache
->getMemcache() instanceof \Memcached) {
$raw_stats['driver_version'] = $this
->t('PECL Driver in Use: Memcached v@version', [
'@version' => phpversion('Memcached'),
]);
}
elseif ($memcache
->getMemcache() instanceof \Memcache) {
$raw_stats['driver_version'] = $this
->t('PECL Driver in Use: Memcache v@version', [
'@version' => phpversion('Memcache'),
]);
}
$event_dispatcher = \Drupal::service('event_dispatcher');
$event_dispatcher
->dispatch(MemcacheStatsEvent::REPORT_MEMCACHE_STATS, $event);
$output = [
'#markup' => '<p>' . $raw_stats['driver_version'],
];
$output[] = $this
->statsTablesOutput($bin, $event
->getServers(), $event
->getReport());
return $output;
}
public function statsTableRaw($cluster, $server, $type = 'default') {
$cluster = $this
->binMapping($cluster);
$server = str_replace('!', '/', $server);
$slab = \Drupal::routeMatch()
->getParameter('slab');
$memcache = \Drupal::service('memcache.factory')
->get($cluster, TRUE);
if ($type == 'slabs' && !empty($slab)) {
$stats = $memcache
->stats($cluster, $slab, FALSE);
}
else {
$stats = $memcache
->stats($cluster, $type, FALSE);
}
if (isset($stats[$cluster][$server]) && is_array($stats[$cluster][$server]) && count($stats[$cluster][$server])) {
$output = $this
->statsTablesRawOutput($cluster, $server, $stats[$cluster][$server], $type);
}
elseif ($type == 'slabs' && is_array($stats[$cluster]) && count($stats[$cluster])) {
$output = $this
->statsTablesRawOutput($cluster, $server, $stats[$cluster], $type);
}
else {
$output = $this
->statsTablesRawOutput($cluster, $server, [], $type);
$this
->messenger()
->addMessage($this
->t('No @type statistics for this bin.', [
'@type' => $type,
]));
}
return $output;
}
private function binMapping($bin = 'cache') {
$memcache = \Drupal::service('memcache.factory')
->get(NULL, TRUE);
$memcache_bins = $memcache
->getBins();
$bins = array_flip($memcache_bins);
if (isset($bins[$bin])) {
return $bins[$bin];
}
else {
return $this
->defaultBin($bin);
}
}
private function statsConnections($stats) {
return $this
->t('@current open of @total total', [
'@current' => number_format($stats['curr_connections']),
'@total' => number_format($stats['total_connections']),
]);
}
private function statsCounters($stats) {
if (!is_array($stats)) {
$stats = [];
}
$stats += [
'incr_hits' => 0,
'incr_misses' => 0,
'decr_hits' => 0,
'decr_misses' => 0,
];
return $this
->t('@incr increments, @decr decrements', [
'@incr' => number_format($stats['incr_hits'] + $stats['incr_misses']),
'@decr' => number_format($stats['decr_hits'] + $stats['decr_misses']),
]);
}
private function statsTablesOutput($bin, $servers, $stats) {
$memcache = \Drupal::service('memcache.factory')
->get(NULL, TRUE);
$memcache_bins = $memcache
->getBins();
$links = [];
if (!is_array($servers)) {
return;
}
foreach ($servers as $server) {
$links[] = Link::fromTextandUrl($server, Url::fromUri('base:/admin/reports/memcache/' . $memcache_bins[$bin] . '/' . str_replace('/', '!', $server)))
->toString();
}
if (count($servers) > 1) {
$headers = array_merge([
'',
$this
->t('Totals'),
], $links);
}
else {
$headers = array_merge([
'',
], $links);
}
$output = [];
foreach ($stats as $table => $data) {
$rows = [];
foreach ($data as $data_row) {
$row = [];
$row[] = $data_row['label'];
if (isset($data_row['total'])) {
$row[] = $data_row['total'];
}
foreach ($data_row['servers'] as $server) {
$row[] = $server;
}
$rows[] = $row;
}
$output[$table] = [
'#theme' => 'table',
'#header' => $headers,
'#rows' => $rows,
];
}
return $output;
}
private function statsTablesRawOutput($cluster, $server, $stats, $type) {
$user = \Drupal::currentUser();
$current_type = isset($type) ? $type : 'default';
$memcache = \Drupal::service('memcache.factory')
->get(NULL, TRUE);
$memcache_bins = $memcache
->getBins();
$bin = isset($memcache_bins[$cluster]) ? $memcache_bins[$cluster] : 'default';
$slab = \Drupal::routeMatch()
->getParameter('slab');
$links = [];
if (count($memcache
->statsTypes())) {
foreach ($memcache
->statsTypes() as $type) {
$link = Link::fromTextandUrl($type, Url::fromUri('base:/admin/reports/memcache/' . $bin . '/' . str_replace('/', '!', $server) . '/' . ($type == 'default' ? '' : $type)))
->toString();
if ($current_type == $type) {
$links[] = '<strong>' . $link . '</strong>';
}
else {
$links[] = $link;
}
}
}
$build = [
'links' => [
'#markup' => !empty($links) ? implode(' | ', $links) : '',
],
];
$build['table'] = [
'#type' => 'table',
'#header' => [
$this
->t('Property'),
$this
->t('Value'),
],
];
$row = 0;
if ($current_type == 'items' && isset($stats['items'])) {
$stats = $stats['items'];
}
foreach ($stats as $key => $value) {
if (($current_type == 'slabs' || $current_type == 'items') && is_int($key) && $user
->hasPermission('access slab cachedump')) {
$build['table'][$row]['key'] = [
'#type' => 'link',
'#title' => $this
->t('Slab @slab', [
'@slab' => $key,
]),
'#url' => Url::fromUri('base:/admin/reports/memcache/' . $bin . '/' . str_replace('/', '!', $server) . '/slabs/cachedump/' . $key),
];
}
else {
$build['table'][$row]['key'] = [
'#plain_text' => $key,
];
}
if (is_array($value)) {
$subrow = 0;
$build['table'][$row]['value'] = [
'#type' => 'table',
];
foreach ($value as $k => $v) {
if ($current_type == 'slabs' && $user
->hasPermission('access slab cachedump') && !empty($slab) && $k == 0) {
$k = $this
->t('Size');
$v = format_size($v);
}
elseif ($current_type == 'slabs' && $user
->hasPermission('access slab cachedump') && !empty($slab) && $k == 1) {
$k = $this
->t('Expire');
$full_stats = $memcache
->stats($cluster);
$infinite = $full_stats[$cluster][$server]['time'] - $full_stats[$cluster][$server]['uptime'];
if ($v == $infinite) {
$v = $this
->t('infinite');
}
else {
$v = $this
->t('in @time', [
'@time' => \Drupal::service('date.formatter')
->formatInterval($v - \Drupal::time()
->getRequestTime()),
]);
}
}
$build['table'][$row]['value'][$subrow] = [
'key' => [
'#plain_text' => $k,
],
'value' => [
'#plain_text' => $v,
],
];
$subrow++;
}
}
else {
$build['table'][$row]['value'] = [
'#plain_text' => $value,
];
}
$row++;
}
return $build;
}
protected function getBinMapping($bin = 'cache') {
$memcache = \Drupal::service('memcache.factory')
->get(NULL, TRUE);
$memcache_bins = $memcache
->getBins();
$bins = array_flip($memcache_bins);
if (isset($bins[$bin])) {
return $bins[$bin];
}
else {
return $this
->defaultBin($bin);
}
}
protected function defaultBin($bin) {
if ($bin == 'default') {
return 'cache';
}
return $bin;
}
}