Skip to content

Commit acdb325

Browse files
committed
[StopWatch] Provide a cleaner API
1 parent acd1287 commit acdb325

File tree

5 files changed

+195
-146
lines changed

5 files changed

+195
-146
lines changed

src/Symfony/Bundle/FrameworkBundle/Debug/TraceableEventDispatcher.php

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public function dispatch($eventName, Event $event = null)
5151
{
5252
switch ($eventName) {
5353
case 'kernel.request':
54-
$this->stopwatch->startSection();
54+
$this->stopwatch->openSection();
5555
break;
5656
case 'kernel.view':
5757
case 'kernel.response':
@@ -62,7 +62,8 @@ public function dispatch($eventName, Event $event = null)
6262
}
6363
break;
6464
case 'kernel.terminate':
65-
$this->stopwatch->startSection();
65+
$token = $event->getResponse()->headers->get('X-Debug-Token');
66+
$this->stopwatch->openSection($token);
6667
break;
6768
}
6869

@@ -82,8 +83,7 @@ public function dispatch($eventName, Event $event = null)
8283
$this->updateProfile($token);
8384
break;
8485
case 'kernel.terminate':
85-
$token = $event->getResponse()->headers->get('X-Debug-Token');
86-
$this->stopwatch->stopSection($token.'.terminate');
86+
$this->stopwatch->stopSection($token);
8787
$this->updateProfile($token);
8888
break;
8989
}
@@ -265,18 +265,7 @@ private function updateProfile($token)
265265
return;
266266
}
267267

268-
$events = $this->stopwatch->getSectionEvents($token);
269-
$origin = $events['__section__']->getOrigin();
270-
271-
foreach ($this->stopwatch->getSectionEvents($token.'.terminate') as $name => $event) {
272-
if (isset($events[$name])) {
273-
$events[$name]->merge($event);
274-
} else {
275-
$events[$name] = $event->setOrigin($origin);
276-
}
277-
}
278-
279-
$profile->getCollector('time')->setEvents($events);
268+
$profile->getCollector('time')->setEvents($this->stopwatch->getSectionEvents($token));
280269
$profiler->saveProfile($profile);
281270

282271
// children

src/Symfony/Component/HttpKernel/Debug/Stopwatch.php

Lines changed: 160 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,33 @@
1818
*/
1919
class Stopwatch
2020
{
21-
private $waiting;
2221
private $sections;
23-
private $events;
24-
private $origin;
22+
private $activeSections;
23+
24+
public function __construct()
25+
{
26+
$this->sections = $this->activeSections = array('__root__' => new Section('__root__'));
27+
}
2528

2629
/**
27-
* Starts a new section.
30+
* Creates a new section or re-opens an existing section.
31+
*
32+
* @param string|null $id The id of the session to re-open, null to create a new one
33+
*
34+
* @throws \LogicException When the section to re-open is not reachable
2835
*/
29-
public function startSection()
36+
public function openSection($id = null)
3037
{
31-
if ($this->events) {
32-
$this->start('__section__.child', 'section');
33-
$this->waiting[] = array($this->events, $this->origin);
34-
$this->events = array();
35-
}
38+
$current = end($this->activeSections);
3639

37-
$this->origin = microtime(true) * 1000;
40+
if (null !== $id) {
41+
if (false === $current->get($id)) {
42+
throw new \LogicException(sprintf('The section "%s" has been started at an other level and can not be opened.', $id));
43+
}
44+
}
3845

46+
$this->start('__section__.child', 'section');
47+
$this->activeSections[] = $current->open($id);
3948
$this->start('__section__');
4049
}
4150

@@ -52,17 +61,12 @@ public function stopSection($id)
5261
{
5362
$this->stop('__section__');
5463

55-
if (null !== $id) {
56-
$this->sections[$id] = $this->events;
64+
if (1 == count($this->activeSections)) {
65+
throw new \LogicException('There is no started section to stop.');
5766
}
5867

59-
if ($this->waiting) {
60-
list($this->events, $this->origin) = array_pop($this->waiting);
61-
$this->stop('__section__.child');
62-
} else {
63-
$this->origin = null;
64-
$this->events = array();
65-
}
68+
$this->sections[$id] = array_pop($this->activeSections)->setId($id);
69+
$this->stop('__section__.child');
6670
}
6771

6872
/**
@@ -74,6 +78,129 @@ public function stopSection($id)
7478
* @return StopwatchEvent A StopwatchEvent instance
7579
*/
7680
public function start($name, $category = null)
81+
{
82+
return end($this->activeSections)->startEvent($name, $category);
83+
}
84+
85+
/**
86+
* Stops an event.
87+
*
88+
* @param string $name The event name
89+
*
90+
* @return StopwatchEvent A StopwatchEvent instance
91+
*/
92+
public function stop($name)
93+
{
94+
return end($this->activeSections)->stopEvent($name);
95+
}
96+
97+
/**
98+
* Stops then restarts an event.
99+
*
100+
* @param string $name The event name
101+
*
102+
* @return Symfony\Component\HttpKernel\Debug\StopwatchEvent A StopwatchEvent instance
103+
*/
104+
public function lap($name)
105+
{
106+
return end($this->activeSections)->stopEvent($name)->start();
107+
}
108+
109+
/**
110+
* Gets all events for a given section.
111+
*
112+
* @param string $id A section identifier
113+
*
114+
* @return Symfony\Component\HttpKernel\Debug\StopwatchEvent[] An array of StopwatchEvent instances
115+
*/
116+
public function getSectionEvents($id)
117+
{
118+
return isset($this->sections[$id]) ? $this->sections[$id]->getEvents() : array();
119+
}
120+
}
121+
122+
class Section
123+
{
124+
private $events = array();
125+
private $origin;
126+
private $id;
127+
private $children = array();
128+
129+
/**
130+
* Constructor.
131+
*
132+
* @param float|null $origin Set the origin of the events in this section, use null to set their origin to their start time
133+
*/
134+
public function __construct($origin = null)
135+
{
136+
$this->origin = is_numeric($origin) ? $origin : null;
137+
}
138+
139+
/**
140+
* Returns the child section.
141+
*
142+
* @param string $id The child section identifier
143+
*
144+
* @return Section|false The child section or false when none found
145+
*/
146+
public function get($id)
147+
{
148+
foreach ($this->children as $child) {
149+
if ($id === $child->getId()) {
150+
return $child;
151+
}
152+
}
153+
154+
return false;
155+
}
156+
157+
/**
158+
* Creates or re-opens a child section.
159+
*
160+
* @param string|null $id null to create a new section, the identifier to re-open an existing one.
161+
*
162+
* @return Section A child section
163+
*/
164+
public function open($id)
165+
{
166+
if (false === $session = $this->get($id)) {
167+
$session = $this->children[] = new self(microtime(true) * 1000);
168+
}
169+
170+
return $session;
171+
}
172+
173+
/**
174+
* @return string The identifier of the section
175+
*/
176+
public function getId()
177+
{
178+
return $this->id;
179+
}
180+
181+
/**
182+
* Sets the session identifier.
183+
*
184+
* @param string $id The session identifier
185+
*
186+
* @return Section The current section
187+
*/
188+
public function setId($id)
189+
{
190+
$this->id = $id;
191+
192+
return $this;
193+
}
194+
195+
/**
196+
* Starts an event.
197+
*
198+
* @param string $name The event name
199+
* @param string $category The event category
200+
*
201+
* @return Symfony\Component\HttpKernel\Debug\StopwatchEvent The event
202+
*/
203+
public function startEvent($name, $category)
77204
{
78205
if (!isset($this->events[$name])) {
79206
$this->events[$name] = new StopwatchEvent($this->origin ?: microtime(true) * 1000, $category);
@@ -87,9 +214,11 @@ public function start($name, $category = null)
87214
*
88215
* @param string $name The event name
89216
*
90-
* @return StopwatchEvent A StopwatchEvent instance
217+
* @return Symfony\Component\HttpKernel\Debug\StopwatchEvent The event
218+
*
219+
* @throws \LogicException When the event has not been started
91220
*/
92-
public function stop($name)
221+
public function stopEvent($name)
93222
{
94223
if (!isset($this->events[$name])) {
95224
throw new \LogicException(sprintf('Event "%s" is not started.', $name));
@@ -99,26 +228,26 @@ public function stop($name)
99228
}
100229

101230
/**
102-
* Stops then restart an event.
231+
* Stops then restarts an event.
103232
*
104233
* @param string $name The event name
105234
*
106-
* @return StopwatchEvent A StopwatchEvent instance
235+
* @return Symfony\Component\HttpKernel\Debug\StopwatchEvent The event
236+
*
237+
* @throws \LogicException When the event has not been started
107238
*/
108239
public function lap($name)
109240
{
110241
return $this->stop($name)->start();
111242
}
112243

113244
/**
114-
* Gets all events for a given section.
115-
*
116-
* @param string $id A section identifier
245+
* Returns the events from this section.
117246
*
118-
* @return StopwatchEvent[] An array of StopwatchEvent instances
247+
* @return Symfony\Component\HttpKernel\Debug\StopwatchEvent[] An array of StopwatchEvent instances
119248
*/
120-
public function getSectionEvents($id)
249+
public function getEvents()
121250
{
122-
return isset($this->sections[$id]) ? $this->sections[$id] : array();
251+
return $this->events;
123252
}
124-
}
253+
}

src/Symfony/Component/HttpKernel/Debug/StopwatchEvent.php

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -59,47 +59,6 @@ public function getOrigin()
5959
return $this->origin;
6060
}
6161

62-
/**
63-
* Updates the origin.
64-
*
65-
* @param float $origin The origin time in milliseconds
66-
*
67-
* @return StopwatchEvent The event
68-
*
69-
* @throws \InvalidArgumentException When the raw time is not valid
70-
*/
71-
public function setOrigin($origin)
72-
{
73-
$origin = $this->formatTime($origin);
74-
$delta = $this->origin - $origin;
75-
$this->origin = $origin;
76-
foreach ($this->started as $i => $time) {
77-
$this->started[$i] = $this->formatTime($time + $delta);
78-
}
79-
foreach ($this->periods as $i => $period) {
80-
$this->periods[$i] = array(
81-
$this->formatTime($period[0] + $delta),
82-
$this->formatTime($period[1] + $delta)
83-
);
84-
}
85-
86-
return $this;
87-
}
88-
89-
/**
90-
* Merges two events.
91-
*
92-
* @param StopWatchEvent $event The event to merge
93-
*
94-
* @return StopwatchEvent The event
95-
*/
96-
public function merge(StopWatchEvent $event)
97-
{
98-
$this->periods = array_merge($this->periods, $event->setOrigin($this->origin)->getPeriods());
99-
100-
return $this;
101-
}
102-
10362
/**
10463
* Starts a new event period.
10564
*

0 commit comments

Comments
 (0)