Skip to content

Commit 600596f

Browse files
alamiraultnicolas-grekas
authored andcommitted
[HttpKernel] FileProfilerStorage remove expired profiles mechanism
1 parent 68725da commit 600596f

File tree

3 files changed

+82
-1
lines changed

3 files changed

+82
-1
lines changed

src/Symfony/Component/HttpKernel/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
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 one day
89

910
6.2
1011
---

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

Lines changed: 30 additions & 1 deletion
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

Lines changed: 51 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy