[ Index ]

PHP Cross Reference of phpBB-3.1.12-deutsch

title

Body

[close]

/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/Profiler/ -> RedisProfilerStorage.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the Symfony package.
   5   *
   6   * (c) Fabien Potencier <fabien@symfony.com>
   7   *
   8   * For the full copyright and license information, please view the LICENSE
   9   * file that was distributed with this source code.
  10   */
  11  
  12  namespace Symfony\Component\HttpKernel\Profiler;
  13  
  14  /**
  15   * RedisProfilerStorage stores profiling information in Redis.
  16   *
  17   * @author Andrej Hudec <pulzarraider@gmail.com>
  18   * @author Stephane PY <py.stephane1@gmail.com>
  19   */
  20  class RedisProfilerStorage implements ProfilerStorageInterface
  21  {
  22      const TOKEN_PREFIX = 'sf_profiler_';
  23  
  24      const REDIS_OPT_SERIALIZER = 1;
  25      const REDIS_OPT_PREFIX = 2;
  26      const REDIS_SERIALIZER_NONE = 0;
  27      const REDIS_SERIALIZER_PHP = 1;
  28  
  29      protected $dsn;
  30      protected $lifetime;
  31  
  32      /**
  33       * @var \Redis
  34       */
  35      private $redis;
  36  
  37      /**
  38       * Constructor.
  39       *
  40       * @param string $dsn      A data source name
  41       * @param string $username Not used
  42       * @param string $password Not used
  43       * @param int    $lifetime The lifetime to use for the purge
  44       */
  45      public function __construct($dsn, $username = '', $password = '', $lifetime = 86400)
  46      {
  47          $this->dsn = $dsn;
  48          $this->lifetime = (int) $lifetime;
  49      }
  50  
  51      /**
  52       * {@inheritdoc}
  53       */
  54      public function find($ip, $url, $limit, $method, $start = null, $end = null)
  55      {
  56          $indexName = $this->getIndexName();
  57  
  58          if (!$indexContent = $this->getValue($indexName, self::REDIS_SERIALIZER_NONE)) {
  59              return array();
  60          }
  61  
  62          $profileList = array_reverse(explode("\n", $indexContent));
  63          $result = array();
  64  
  65          foreach ($profileList as $item) {
  66              if ($limit === 0) {
  67                  break;
  68              }
  69  
  70              if ($item == '') {
  71                  continue;
  72              }
  73  
  74              list($itemToken, $itemIp, $itemMethod, $itemUrl, $itemTime, $itemParent) = explode("\t", $item, 6);
  75  
  76              $itemTime = (int) $itemTime;
  77  
  78              if ($ip && false === strpos($itemIp, $ip) || $url && false === strpos($itemUrl, $url) || $method && false === strpos($itemMethod, $method)) {
  79                  continue;
  80              }
  81  
  82              if (!empty($start) && $itemTime < $start) {
  83                  continue;
  84              }
  85  
  86              if (!empty($end) && $itemTime > $end) {
  87                  continue;
  88              }
  89  
  90              $result[] = array(
  91                  'token' => $itemToken,
  92                  'ip' => $itemIp,
  93                  'method' => $itemMethod,
  94                  'url' => $itemUrl,
  95                  'time' => $itemTime,
  96                  'parent' => $itemParent,
  97              );
  98              --$limit;
  99          }
 100  
 101          return $result;
 102      }
 103  
 104      /**
 105       * {@inheritdoc}
 106       */
 107      public function purge()
 108      {
 109          // delete only items from index
 110          $indexName = $this->getIndexName();
 111  
 112          $indexContent = $this->getValue($indexName, self::REDIS_SERIALIZER_NONE);
 113  
 114          if (!$indexContent) {
 115              return false;
 116          }
 117  
 118          $profileList = explode("\n", $indexContent);
 119  
 120          $result = array();
 121  
 122          foreach ($profileList as $item) {
 123              if ($item == '') {
 124                  continue;
 125              }
 126  
 127              if (false !== $pos = strpos($item, "\t")) {
 128                  $result[] = $this->getItemName(substr($item, 0, $pos));
 129              }
 130          }
 131  
 132          $result[] = $indexName;
 133  
 134          return $this->delete($result);
 135      }
 136  
 137      /**
 138       * {@inheritdoc}
 139       */
 140      public function read($token)
 141      {
 142          if (empty($token)) {
 143              return false;
 144          }
 145  
 146          $profile = $this->getValue($this->getItemName($token), self::REDIS_SERIALIZER_PHP);
 147  
 148          if (false !== $profile) {
 149              $profile = $this->createProfileFromData($token, $profile);
 150          }
 151  
 152          return $profile;
 153      }
 154  
 155      /**
 156       * {@inheritdoc}
 157       */
 158      public function write(Profile $profile)
 159      {
 160          $data = array(
 161              'token' => $profile->getToken(),
 162              'parent' => $profile->getParentToken(),
 163              'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()),
 164              'data' => $profile->getCollectors(),
 165              'ip' => $profile->getIp(),
 166              'method' => $profile->getMethod(),
 167              'url' => $profile->getUrl(),
 168              'time' => $profile->getTime(),
 169          );
 170  
 171          $profileIndexed = false !== $this->getValue($this->getItemName($profile->getToken()));
 172  
 173          if ($this->setValue($this->getItemName($profile->getToken()), $data, $this->lifetime, self::REDIS_SERIALIZER_PHP)) {
 174              if (!$profileIndexed) {
 175                  // Add to index
 176                  $indexName = $this->getIndexName();
 177  
 178                  $indexRow = implode("\t", array(
 179                      $profile->getToken(),
 180                      $profile->getIp(),
 181                      $profile->getMethod(),
 182                      $profile->getUrl(),
 183                      $profile->getTime(),
 184                      $profile->getParentToken(),
 185                  ))."\n";
 186  
 187                  return $this->appendValue($indexName, $indexRow, $this->lifetime);
 188              }
 189  
 190              return true;
 191          }
 192  
 193          return false;
 194      }
 195  
 196      /**
 197       * Internal convenience method that returns the instance of Redis.
 198       *
 199       * @return \Redis
 200       *
 201       * @throws \RuntimeException
 202       */
 203      protected function getRedis()
 204      {
 205          if (null === $this->redis) {
 206              $data = parse_url($this->dsn);
 207  
 208              if (false === $data || !isset($data['scheme']) || $data['scheme'] !== 'redis' || !isset($data['host']) || !isset($data['port'])) {
 209                  throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Redis with an invalid dsn "%s". The minimal expected format is "redis://[host]:port".', $this->dsn));
 210              }
 211  
 212              if (!extension_loaded('redis')) {
 213                  throw new \RuntimeException('RedisProfilerStorage requires that the redis extension is loaded.');
 214              }
 215  
 216              $redis = new \Redis();
 217              $redis->connect($data['host'], $data['port']);
 218  
 219              if (isset($data['path'])) {
 220                  $redis->select(substr($data['path'], 1));
 221              }
 222  
 223              if (isset($data['pass'])) {
 224                  $redis->auth($data['pass']);
 225              }
 226  
 227              $redis->setOption(self::REDIS_OPT_PREFIX, self::TOKEN_PREFIX);
 228  
 229              $this->redis = $redis;
 230          }
 231  
 232          return $this->redis;
 233      }
 234  
 235      /**
 236       * Set instance of the Redis.
 237       *
 238       * @param \Redis $redis
 239       */
 240      public function setRedis($redis)
 241      {
 242          $this->redis = $redis;
 243      }
 244  
 245      private function createProfileFromData($token, $data, $parent = null)
 246      {
 247          $profile = new Profile($token);
 248          $profile->setIp($data['ip']);
 249          $profile->setMethod($data['method']);
 250          $profile->setUrl($data['url']);
 251          $profile->setTime($data['time']);
 252          $profile->setCollectors($data['data']);
 253  
 254          if (!$parent && $data['parent']) {
 255              $parent = $this->read($data['parent']);
 256          }
 257  
 258          if ($parent) {
 259              $profile->setParent($parent);
 260          }
 261  
 262          foreach ($data['children'] as $token) {
 263              if (!$token) {
 264                  continue;
 265              }
 266  
 267              if (!$childProfileData = $this->getValue($this->getItemName($token), self::REDIS_SERIALIZER_PHP)) {
 268                  continue;
 269              }
 270  
 271              $profile->addChild($this->createProfileFromData($token, $childProfileData, $profile));
 272          }
 273  
 274          return $profile;
 275      }
 276  
 277      /**
 278       * Gets the item name.
 279       *
 280       * @param string $token
 281       *
 282       * @return string
 283       */
 284      private function getItemName($token)
 285      {
 286          $name = $token;
 287  
 288          if ($this->isItemNameValid($name)) {
 289              return $name;
 290          }
 291  
 292          return false;
 293      }
 294  
 295      /**
 296       * Gets the name of the index.
 297       *
 298       * @return string
 299       */
 300      private function getIndexName()
 301      {
 302          $name = 'index';
 303  
 304          if ($this->isItemNameValid($name)) {
 305              return $name;
 306          }
 307  
 308          return false;
 309      }
 310  
 311      private function isItemNameValid($name)
 312      {
 313          $length = strlen($name);
 314  
 315          if ($length > 2147483648) {
 316              throw new \RuntimeException(sprintf('The Redis item key "%s" is too long (%s bytes). Allowed maximum size is 2^31 bytes.', $name, $length));
 317          }
 318  
 319          return true;
 320      }
 321  
 322      /**
 323       * Retrieves an item from the Redis server.
 324       *
 325       * @param string $key
 326       * @param int    $serializer
 327       *
 328       * @return mixed
 329       */
 330      private function getValue($key, $serializer = self::REDIS_SERIALIZER_NONE)
 331      {
 332          $redis = $this->getRedis();
 333          $redis->setOption(self::REDIS_OPT_SERIALIZER, $serializer);
 334  
 335          return $redis->get($key);
 336      }
 337  
 338      /**
 339       * Stores an item on the Redis server under the specified key.
 340       *
 341       * @param string $key
 342       * @param mixed  $value
 343       * @param int    $expiration
 344       * @param int    $serializer
 345       *
 346       * @return bool
 347       */
 348      private function setValue($key, $value, $expiration = 0, $serializer = self::REDIS_SERIALIZER_NONE)
 349      {
 350          $redis = $this->getRedis();
 351          $redis->setOption(self::REDIS_OPT_SERIALIZER, $serializer);
 352  
 353          return $redis->setex($key, $expiration, $value);
 354      }
 355  
 356      /**
 357       * Appends data to an existing item on the Redis server.
 358       *
 359       * @param string $key
 360       * @param string $value
 361       * @param int    $expiration
 362       *
 363       * @return bool
 364       */
 365      private function appendValue($key, $value, $expiration = 0)
 366      {
 367          $redis = $this->getRedis();
 368          $redis->setOption(self::REDIS_OPT_SERIALIZER, self::REDIS_SERIALIZER_NONE);
 369  
 370          if ($redis->exists($key)) {
 371              $redis->append($key, $value);
 372  
 373              return $redis->setTimeout($key, $expiration);
 374          }
 375  
 376          return $redis->setex($key, $expiration, $value);
 377      }
 378  
 379      /**
 380       * Removes the specified keys.
 381       *
 382       * @param array $keys
 383       *
 384       * @return bool
 385       */
 386      private function delete(array $keys)
 387      {
 388          return (bool) $this->getRedis()->delete($keys);
 389      }
 390  }


Generated: Thu Jan 11 00:25:41 2018 Cross-referenced by PHPXref 0.7.1