8000 [HttpKernel] FileProfilerStorage has remove expired profiles mechanism · symfony/symfony@c670f8a · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit c670f8a

Browse files
committed
[HttpKernel] FileProfilerStorage has remove expired profiles mechanism
1 parent e1581a0 commit c670f8a

File tree

2 files changed

+114
-1
lines changed

2 files changed

+114
-1
lines changed

src/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
*/
1919
class FileProfilerStorage implements ProfilerStorageInterface
2020
{
21+
protected const MAX_RETENTION_DAYS = 1;
22+
2123
/**
2224
* Folder where profiler data are stored.
2325
*/
@@ -180,7 +182,7 @@ public function write(Profile $profile): bool
180182

181183
if (!$profileIndexed) {
182184
// Add to index
183-
if (false === $file = fopen($this->getIndexFilename(), 'a')) {
185+
if (false === $file = fopen($indexFilename = $this->getIndexFilename(), 'a')) {
184186
return false;
185187
}
186188

@@ -194,11 +196,55 @@ public function write(Profile $profile): bool
194196
$profile->getStatusCode(),
195197
]);
196198
fclose($file);
199+
200+
$this->removeExpiredProfiles($indexFilename);
197201
}
198202

199203
return true;
200204
}
201205

206+
protected function removeExpiredProfiles(string $indexFilename)
207+
{
208+
$minimalProfileTimestamp = (new \DateTime())
209+
->modify(sprintf('-%d days', self::MAX_RETENTION_DAYS))
210+
->getTimestamp();
211+
212+
$handle = fopen($indexFilename, 'r');
213+
214+
$tmpIndexFileName = $indexFilename.'.tmp';
215+
$atLeastOneExpiredProfile = false;
216+
while ($line = fgets($handle)) {
217+
$csv = str_getcsv($line);
218+
$token = $csv[0];
219+
$profileTimestamp = (int) $csv[4];
220+
221+
if (0 !== $profileTimestamp && $profileTimestamp < $minimalProfileTimestamp) {
222+
$atLeastOneExpiredProfile = true;
223+
$this->unlinkTokenFile($token);
224+
} else {
225+
if ($atLeastOneExpiredProfile) {
226+
file_put_contents($tmpIndexFileName, $line);
227+
}
228+
break;
229+
}
230+
}
231+
232+
if ($atLeastOneExpiredProfile) {
233+
file_put_contents($tmpIndexFileName, stream_get_contents($handle), \FILE_APPEND);
234+
unlink($indexFilename);
235+
rename($tmpIndexFileName, $indexFilename);
236+
} else {
237+
fclose($handle);
238+
}
239+
}
240+
241+
public function unlinkTokenFile(string $token)
242+
{
243+
if (file_exists($filename = $this->getFilename($token))) {
244+
unlink($filename);
245+
}
246+
}
247+
202248
/**
203249
* Gets filename to store data, associated to the token.
204250
*/

src/Symfony/Component/HttpKernel/Tests/Profiler/FileProfilerStorageTest.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,73 @@ public function testMultiRowIn 8000 dexFile()
344344
$this->assertFalse(fgetcsv($handle));
345345
}
346346

347+
/**
348+
* @dataProvider removeExpiredProfilesProvider
349+
*/
350+
public function testRemoveExpiredProfiles(string $originalExpectedIndexContent, string $newExpectedIndexContent)
351+
{
352+
$indexFilename = $this->tmpDir.'/index.csv';
353+
354+
file_put_contents($indexFilename, $originalExpectedIndexContent);
355+
356+
$this->assertSame($originalExpectedIndexContent, file_get_contents($indexFilename));
357+
358+
$r = new \ReflectionMethod($this->storage, 'removeExpiredProfiles');
359+
$r->invoke($this->storage, $indexFilename);
360+
361+
$this->assertSame($newExpectedIndexContent, file_get_contents($indexFilename));
362+
}
363+
364+
public function removeExpiredProfilesProvider()
365+
{
366+
$oneHourAgo = new \DateTime('now');
367+
$oneHourAgo->modify('-1 hour');
368+
369+
yield 'One unexpired profile' => [
370+
<<< CSV
371+
token0,127.0.0.0,,http://foo.bar/0,{$oneHourAgo->getTimestamp()},,
372+
373+
CSV,
374+
<<< CSV
375+
token0,127.0.0.0,,http://foo.bar/0,{$oneHourAgo->getTimestamp()},,
376+
377+
CSV,
378+
];
379+
380+
$twoDaysAgo = new \DateTime('now');
381+
$twoDaysAgo->modify('-2 days');
382+
383+
yield 'One expired profile' => [
384+
<<< CSV
385+
token0,127.0.0.0,,http://foo.bar/0,{$twoDaysAgo->getTimestamp()},,
386+
387+
CSV,
388+
'',
389+
];
390+
391+
$threeDaysAgo = new \DateTime('now');
392+
$threeDaysAgo->modify('-3 days');
393+
394+
$twoDaysAgo = new \DateTime('now');
395+
$twoDaysAgo->modify('-2 days');
396+
397+
$oneHourAgo = new \DateTime('now');
398+
$oneHourAgo->modify('-1 hour');
399+
400+
yield 'Multiple expired profiles' => [
401+
<<< CSV
402+
token0,127.0.0.0,,http://foo.bar/0,{$threeDaysAgo->getTimestamp()},,
403+
token1,127.0.0.1,,http://foo.bar/1,{$twoDaysAgo->getTimestamp()},,
404+
token2,127.0.0.2,,http://foo.bar/2,{$oneHourAgo->getTimestamp()},,
405+
406+
CSV,
407+
<<< CSV
408+
token2,127.0.0.2,,http://foo.bar/2,{$oneHourAgo->getTimestamp()},,
409+
410+
CSV,
411+
];
412+
}
413+
347414
public function testReadLineFromFile()
348415
{
349416
$r = new \ReflectionMethod($this->storage, 'readLineFromFile');

0 commit comments

Comments
 (0)
0