[ Index ]

PHP Cross Reference of phpBB-3.2.8-deutsch

title

Body

[close]

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


Generated: Tue Apr 7 19:42:26 2020 Cross-referenced by PHPXref 0.7.1