Skip to content

Commit 58d0662

Browse files
alamiraultfabpot
authored andcommitted
[HttpKernel] FileProfilerStorage remove expired profiles mechanism
1 parent 68725da commit 58d0662

File tree

3 files changed

+82
-1
lines changed

3 files changed

+82
-1
lines changed

src/Symfony/Component/HttpKernel/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
---
66

77
* Deprecate parameters `container.dumper.inline_factories` and `container.dumper.inline_class_loader`, use `.container.dumper.inline_factories` and `.container.dumper.inline_class_loader` instead
8+
* `FileProfilerStorage` removes profiles automatically after two days
89

910
6.2
1011
---

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

+30-1
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,15 @@ public function write(Profile $profile): bool
165165
$profile->getIp(),
166166
$profile->getMethod(),
167167
$profile->getUrl(),
168-
$profile->getTime(),
168+
$profile->getTime() ?: time(),
169169
$profile->getParentToken(),
170170
$profile->getStatusCode(),
171171
]);
172172
fclose($file);
173+
174+
if (1 === mt_rand(1, 10)) {
175+
$this->removeExpiredProfiles();
176+
}
173177
}
174178

175179
return true;
@@ -289,4 +293,29 @@ private function doRead($token, Profile $profile = null): ?Profile
289293

290294
return $this->createProfileFromData($token, $data, $profile);
291295
}
296+
297+
private function removeExpiredProfiles()
298+
{
299+
$minimalProfileTimestamp = time() - 2 * 86400;
300+
$file = $this->getIndexFilename();
301+
$handle = fopen($file, 'r');
302+
303+
if ($offset = is_file($file.'.offset') ? (int) file_get_contents($file.'.offset') : 0) {
304+
fseek($handle, $offset);
305+
}
306+
307+
while ($line = fgets($handle)) {
308+
[$csvToken, , , , $csvTime] = str_getcsv($line);
309+
310+
if ($csvTime >= $minimalProfileTimestamp) {
311+
break;
312+
}
313+
314+
@unlink($this->getFilename($csvToken));
315+
$offset += \strlen($line);
316+
}
317+
fclose($handle);
318+
319+
file_put_contents($file.'.offset', $offset);
320+
}
292321
}

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

+51
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,57 @@ public function testMultiRowIndexFile()
344344
$this->assertFalse(fgetcsv($handle));
345345
}
346346

347+
/**
348+
* @dataProvider provideExpiredProfiles
349+
*/
350+
public function testRemoveExpiredProfiles(string $index, string $expectedOffset)
351+
{
352+
$file = $this->tmpDir.'/index.csv';
353+
file_put_contents($file, $index);
354+
355+
$r = new \ReflectionMethod($this->storage, 'removeExpiredProfiles');
356+
$r->invoke($this->storage);
357+
358+
$this->assertSame($expectedOffset, file_get_contents($this->tmpDir.'/index.csv.offset'));
359+
}
360+
361+
public static function provideExpiredProfiles()
362+
{
363+
$oneHourAgo = new \DateTimeImmutable('-1 hour');
364+
365+
yield 'One unexpired profile' => [
366+
<<<CSV
367+
token0,127.0.0.0,,http://foo.bar/0,{$oneHourAgo->getTimestamp()},,
368+
369+
CSV,
370+
'0',
371+
];
372+
373+
$threeDaysAgo = new \DateTimeImmutable('-3 days');
374+
375+
yield 'One expired profile' => [
376+
<<<CSV
377+
token0,127.0.0.0,,http://foo.bar/0,{$threeDaysAgo->getTimestamp()},,
378+
379+
CSV,
380+
'48',
381+
];
382+
383+
$fourDaysAgo = new \DateTimeImmutable('-4 days');
384+
$threeDaysAgo = new \DateTimeImmutable('-3 days');
385+
$oneHourAgo = new \DateTimeImmutable('-1 hour');
386+
387+
yield 'Multiple expired profiles' => [
388+
<<<CSV
389+
token0,127.0.0.0,,http://foo.bar/0,{$fourDaysAgo->getTimestamp()},,
390+
token1,127.0.0.1,,http://foo.bar/1,{$threeDaysAgo->getTimestamp()},,
391+
token2,127.0.0.2,,http://foo.bar/2,{$oneHourAgo->getTimestamp()},,
392+
393+
CSV,
394+
'96',
395+
];
396+
}
397+
347398
public function testReadLineFromFile()
348399
{
349400
$r = new \ReflectionMethod($this->storage, 'readLineFromFile');

0 commit comments

Comments
 (0)