Profiler.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\HttpKernel\Profiler;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpFoundation\Response;
  13. use Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface;
  14. use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
  15. use Symfony\Component\HttpKernel\Log\LoggerInterface;
  16. /**
  17. * Profiler.
  18. *
  19. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  20. */
  21. class Profiler
  22. {
  23. protected $storage;
  24. protected $collectors;
  25. protected $logger;
  26. protected $enabled;
  27. protected $token;
  28. protected $data;
  29. protected $ip;
  30. protected $url;
  31. protected $time;
  32. protected $empty;
  33. /**
  34. * Constructor.
  35. *
  36. * @param ProfilerStorageInterface $storage A ProfilerStorageInterface instance
  37. * @param LoggerInterface $logger A LoggerInterface instance
  38. */
  39. public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null)
  40. {
  41. $this->storage = $storage;
  42. $this->logger = $logger;
  43. $this->collectors = array();
  44. $this->enabled = true;
  45. $this->empty = true;
  46. }
  47. /**
  48. * Disables the profiler.
  49. */
  50. public function disable()
  51. {
  52. $this->enabled = false;
  53. }
  54. /**
  55. * Loads a Profiler for the given Response.
  56. *
  57. * @param Response $response A Response instance
  58. *
  59. * @return Profiler A new Profiler instance
  60. */
  61. public function loadFromResponse(Response $response)
  62. {
  63. if (!$token = $response->headers->get('X-Debug-Token')) {
  64. return null;
  65. }
  66. return $this->loadFromToken($token);
  67. }
  68. /**
  69. * Loads a Profiler for the given token.
  70. *
  71. * @param string $token A token
  72. *
  73. * @return Profiler A new Profiler instance
  74. */
  75. public function loadFromToken($token)
  76. {
  77. $profiler = new self($this->storage, $this->logger);
  78. $profiler->setToken($token);
  79. return $profiler;
  80. }
  81. /**
  82. * Purges all data from the storage.
  83. */
  84. public function purge()
  85. {
  86. $this->storage->purge();
  87. }
  88. /**
  89. * Exports the current profiler data.
  90. *
  91. * @return string The exported data
  92. */
  93. public function export()
  94. {
  95. $data = base64_encode(serialize(array($this->token, $this->collectors, $this->ip, $this->url, $this->time)));
  96. return $data;
  97. }
  98. /**
  99. * Imports data into the profiler storage.
  100. *
  101. * @param string $data A data string as exported by the export() method
  102. *
  103. * @return string The token associated with the imported data
  104. */
  105. public function import($data)
  106. {
  107. list($token, $collectors, $ip, $url, $time) = unserialize(base64_decode($data));
  108. if (false !== $this->storage->read($token)) {
  109. return false;
  110. }
  111. $data = base64_encode(serialize($collectors));
  112. $this->storage->write($token, $data, $ip, $url, $time);
  113. return $token;
  114. }
  115. /**
  116. * Sets the token.
  117. *
  118. * @param string $token The token
  119. */
  120. public function setToken($token)
  121. {
  122. $this->token = $token;
  123. if (false !== $items = $this->storage->read($token)) {
  124. list($data, $this->ip, $this->url, $this->time) = $items;
  125. $this->set(unserialize(base64_decode($data)));
  126. $this->empty = false;
  127. } else {
  128. $this->empty = true;
  129. }
  130. }
  131. /**
  132. * Gets the token.
  133. *
  134. * @return string The token
  135. */
  136. public function getToken()
  137. {
  138. if (null === $this->token) {
  139. $this->token = uniqid();
  140. }
  141. return $this->token;
  142. }
  143. /**
  144. * Checks if the profiler is empty.
  145. *
  146. * @return Boolean Whether the profiler is empty or not
  147. */
  148. public function isEmpty()
  149. {
  150. return $this->empty;
  151. }
  152. /**
  153. * Returns the IP.
  154. *
  155. * @return string The IP
  156. */
  157. public function getIp()
  158. {
  159. return $this->ip;
  160. }
  161. /**
  162. * Returns the URL.
  163. *
  164. * @return string The URL
  165. */
  166. public function getUrl()
  167. {
  168. return $this->url;
  169. }
  170. /**
  171. * Returns the time.
  172. *
  173. * @return string The time
  174. */
  175. public function getTime()
  176. {
  177. return $this->time;
  178. }
  179. /**
  180. * Finds profiler tokens for the given criteria.
  181. *
  182. * @param string $ip The IP
  183. * @param string $url The URL
  184. * @param string $limit The maximum number of tokens to return
  185. *
  186. * @return array An array of tokens
  187. */
  188. public function find($ip, $url, $limit)
  189. {
  190. return $this->storage->find($ip, $url, $limit);
  191. }
  192. /**
  193. * Collects data for the given Response.
  194. *
  195. * @param Request $request A Request instance
  196. * @param Response $response A Response instance
  197. * @param \Exception $exception An exception instance if the request threw one
  198. */
  199. public function collect(Request $request, Response $response, \Exception $exception = null)
  200. {
  201. if (false === $this->enabled) {
  202. return;
  203. }
  204. $response->headers->set('X-Debug-Token', $this->getToken());
  205. foreach ($this->collectors as $collector) {
  206. $collector->collect($request, $response, $exception);
  207. }
  208. $this->ip = $request->server->get('REMOTE_ADDR');
  209. $this->url = $request->getUri();
  210. $this->time = time();
  211. $data = base64_encode(serialize($this->collectors));
  212. if (true === $this->storage->write($this->token, $data, $this->ip, $this->url, $this->time)) {
  213. $this->empty = false;
  214. } elseif (null !== $this->logger) {
  215. if (null !== $exception) {
  216. $this->logger->err(sprintf('Unable to store the profiler information (%s).', $exception->getMessage()));
  217. } else {
  218. $this->logger->err('Unable to store the profiler information (%s).');
  219. }
  220. }
  221. }
  222. /**
  223. * Gets the Collectors associated with this profiler.
  224. *
  225. * @return array An array of collectors
  226. */
  227. public function all()
  228. {
  229. return $this->collectors;
  230. }
  231. /**
  232. * Sets the Collectors associated with this profiler.
  233. *
  234. * @param array $collectors An array of collectors
  235. */
  236. public function set(array $collectors = array())
  237. {
  238. $this->collectors = array();
  239. foreach ($collectors as $collector) {
  240. $this->add($collector);
  241. }
  242. }
  243. /**
  244. * Adds a Collector.
  245. *
  246. * @param DataCollectorInterface $collector A DataCollectorInterface instance
  247. */
  248. public function add(DataCollectorInterface $collector)
  249. {
  250. $this->collectors[$collector->getName()] = $collector;
  251. }
  252. /**
  253. * Returns true if a Collector for the given name exists.
  254. *
  255. * @param string $name A collector name
  256. */
  257. public function has($name)
  258. {
  259. return isset($this->collectors[$name]);
  260. }
  261. /**
  262. * Gets a Collector by name.
  263. *
  264. * @param string $name A collector name
  265. *
  266. * @return DataCollectorInterface A DataCollectorInterface instance
  267. *
  268. * @throws \InvalidArgumentException if the collector does not exist
  269. */
  270. public function get($name)
  271. {
  272. if (!isset($this->collectors[$name])) {
  273. throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name));
  274. }
  275. return $this->collectors[$name];
  276. }
  277. }