4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\HttpKernel\Profiler;
14 @trigger_error('The '.__NAMESPACE__.'\BaseMemcacheProfilerStorage class is deprecated since Symfony 2.8 and will be removed in 3.0. Use FileProfilerStorage instead.', E_USER_DEPRECATED);
17 * Base Memcache storage for profiling information in a Memcache.
19 * @author Andrej Hudec <pulzarraider@gmail.com>
21 * @deprecated Deprecated since Symfony 2.8, to be removed in Symfony 3.0.
22 * Use {@link FileProfilerStorage} instead.
24 abstract class BaseMemcacheProfilerStorage implements ProfilerStorageInterface
26 const TOKEN_PREFIX = 'sf_profiler_';
34 * @param string $dsn A data source name
35 * @param string $username
36 * @param string $password
37 * @param int $lifetime The lifetime to use for the purge
39 public function __construct($dsn, $username = '', $password = '', $lifetime = 86400)
42 $this->lifetime = (int) $lifetime;
48 public function find($ip, $url, $limit, $method, $start = null, $end = null)
50 $indexName = $this->getIndexName();
52 $indexContent = $this->getValue($indexName);
57 $profileList = explode("\n", $indexContent);
60 foreach ($profileList as $item) {
69 $values = explode("\t", $item, 7);
70 list($itemToken, $itemIp, $itemMethod, $itemUrl, $itemTime, $itemParent) = $values;
71 $statusCode = isset($values[6]) ? $values[6] : null;
73 $itemTime = (int) $itemTime;
75 if ($ip && false === strpos($itemIp, $ip) || $url && false === strpos($itemUrl, $url) || $method && false === strpos($itemMethod, $method)) {
79 if (!empty($start) && $itemTime < $start) {
83 if (!empty($end) && $itemTime > $end) {
87 $result[$itemToken] = array(
88 'token' => $itemToken,
90 'method' => $itemMethod,
93 'parent' => $itemParent,
94 'status_code' => $statusCode,
99 usort($result, function ($a, $b) {
100 if ($a['time'] === $b['time']) {
104 return $a['time'] > $b['time'] ? -1 : 1;
113 public function purge()
115 // delete only items from index
116 $indexName = $this->getIndexName();
118 $indexContent = $this->getValue($indexName);
120 if (!$indexContent) {
124 $profileList = explode("\n", $indexContent);
126 foreach ($profileList as $item) {
131 if (false !== $pos = strpos($item, "\t")) {
132 $this->delete($this->getItemName(substr($item, 0, $pos)));
136 return $this->delete($indexName);
142 public function read($token)
148 $profile = $this->getValue($this->getItemName($token));
150 if (false !== $profile) {
151 $profile = $this->createProfileFromData($token, $profile);
160 public function write(Profile $profile)
163 'token' => $profile->getToken(),
164 'parent' => $profile->getParentToken(),
165 'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()),
166 'data' => $profile->getCollectors(),
167 'ip' => $profile->getIp(),
168 'method' => $profile->getMethod(),
169 'url' => $profile->getUrl(),
170 'time' => $profile->getTime(),
173 $profileIndexed = false !== $this->getValue($this->getItemName($profile->getToken()));
175 if ($this->setValue($this->getItemName($profile->getToken()), $data, $this->lifetime)) {
176 if (!$profileIndexed) {
178 $indexName = $this->getIndexName();
180 $indexRow = implode("\t", array(
181 $profile->getToken(),
183 $profile->getMethod(),
186 $profile->getParentToken(),
187 $profile->getStatusCode(),
190 return $this->appendValue($indexName, $indexRow, $this->lifetime);
200 * Retrieve item from the memcache server.
206 abstract protected function getValue($key);
209 * Store an item on the memcache server under the specified key.
212 * @param mixed $value
213 * @param int $expiration
217 abstract protected function setValue($key, $value, $expiration = 0);
220 * Delete item from the memcache server.
226 abstract protected function delete($key);
229 * Append data to an existing item on the memcache server.
232 * @param string $value
233 * @param int $expiration
237 abstract protected function appendValue($key, $value, $expiration = 0);
239 private function createProfileFromData($token, $data, $parent = null)
241 $profile = new Profile($token);
242 $profile->setIp($data['ip']);
243 $profile->setMethod($data['method']);
244 $profile->setUrl($data['url']);
245 $profile->setTime($data['time']);
246 $profile->setCollectors($data['data']);
248 if (!$parent && $data['parent']) {
249 $parent = $this->read($data['parent']);
253 $profile->setParent($parent);
256 foreach ($data['children'] as $token) {
261 if (!$childProfileData = $this->getValue($this->getItemName($token))) {
265 $profile->addChild($this->createProfileFromData($token, $childProfileData, $profile));
274 * @param string $token
278 private function getItemName($token)
280 $name = self::TOKEN_PREFIX.$token;
282 if ($this->isItemNameValid($name)) {
294 private function getIndexName()
296 $name = self::TOKEN_PREFIX.'index';
298 if ($this->isItemNameValid($name)) {
305 private function isItemNameValid($name)
307 $length = strlen($name);
310 throw new \RuntimeException(sprintf('The memcache item key "%s" is too long (%s bytes). Allowed maximum size is 250 bytes.', $name, $length));