Skip to content

Commit 8932cd1

Browse files
Write event feed import log to separate file per contest
Fixes #2169
1 parent ef70ae8 commit 8932cd1

File tree

4 files changed

+37
-40
lines changed

4 files changed

+37
-40
lines changed

webapp/config/packages/monolog.yaml

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,3 @@
1-
monolog:
2-
# Set up logger for the event feed importer.
3-
# key, to make sure the logs don't also appear there.
4-
channels:
5-
- event-feed-importer
6-
handlers:
7-
event-feed-importer:
8-
level: info
9-
type: stream
10-
path: "%kernel.logs_dir%/event-feed-importer.log"
11-
channels: ["event-feed-importer"]
12-
131
when@dev:
142
monolog:
153
handlers:
@@ -31,10 +19,6 @@ when@dev:
3119
process_psr_3_messages: false
3220
channels: ["!event", "!doctrine", "!console"]
3321

34-
# In dev mode, also log debug messages
35-
event-feed-importer:
36-
level: debug
37-
3822
when@test:
3923
monolog:
4024
handlers:

webapp/src/DependencyInjection/Compiler/RemoveEventFeedImporterChannelFromLogs.php

Lines changed: 0 additions & 19 deletions
This file was deleted.

webapp/src/Kernel.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace App;
44

5-
use App\DependencyInjection\Compiler\RemoveEventFeedImporterChannelFromLogs;
65
use App\DependencyInjection\Compiler\SetDocLinksPass;
76
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
87
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -20,6 +19,5 @@ public function getProjectDir(): string
2019
protected function build(ContainerBuilder $container): void
2120
{
2221
$container->addCompilerPass(new SetDocLinksPass());
23-
$container->addCompilerPass(new RemoveEventFeedImporterChannelFromLogs());
2422
}
2523
}

webapp/src/Service/ExternalContestSourceService.php

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,13 @@
4444
use Exception;
4545
use InvalidArgumentException;
4646
use LogicException;
47+
use Monolog\Handler\StreamHandler;
48+
use Monolog\Level;
49+
use Monolog\Logger;
50+
use Monolog\Processor\ProcessorInterface;
4751
use Psr\Log\LoggerInterface;
4852
use Symfony\Component\DependencyInjection\Attribute\Autowire;
53+
use Symfony\Component\DependencyInjection\Attribute\AutowireIterator;
4954
use Symfony\Component\HttpClient\Exception\TransportException;
5055
use Symfony\Component\HttpFoundation\File\UploadedFile;
5156
use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException;
@@ -58,6 +63,7 @@
5863
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
5964
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
6065
use Symfony\Contracts\HttpClient\HttpClientInterface;
66+
use Traversable;
6167
use ZipArchive;
6268

6369
class ExternalContestSourceService
@@ -66,6 +72,8 @@ class ExternalContestSourceService
6672

6773
protected ?ExternalContestSource $source = null;
6874

75+
protected LoggerInterface $logger;
76+
6977
protected bool $contestLoaded = false;
7078
protected ?ContestData $cachedContestData = null;
7179
protected ?ApiInfo $cachedApiInfoData = null;
@@ -100,19 +108,28 @@ class ExternalContestSourceService
100108
'submission' => [],
101109
];
102110

111+
/**
112+
* @param Traversable<ProcessorInterface> $logProcessors
113+
*/
103114
public function __construct(
104115
HttpClientInterface $httpClient,
105116
protected readonly DOMJudgeService $dj,
106117
protected readonly EntityManagerInterface $em,
107-
#[Autowire(service: 'monolog.logger.event-feed-importer')]
108-
protected readonly LoggerInterface $logger,
109118
protected readonly ConfigurationService $config,
110119
protected readonly EventLogService $eventLog,
111120
protected readonly SubmissionService $submissionService,
112121
protected readonly ScoreboardService $scoreboardService,
113122
protected readonly SerializerInterface&DenormalizerInterface&NormalizerInterface $serializer,
123+
#[AutowireIterator(tag: 'monolog.processor')]
124+
protected readonly Traversable $logProcessors,
125+
#[Autowire(service: 'monolog.processor.psr_log_message')]
126+
protected readonly ProcessorInterface $psrLogMessageProcessor,
127+
#[Autowire(param: 'kernel.logs_dir')]
128+
protected readonly string $logDir,
129+
#[Autowire(param: 'kernel.environment')]
130+
protected readonly string $env,
114131
#[Autowire('%domjudge.version%')]
115-
string $domjudgeVersion
132+
string $domjudgeVersion,
116133
) {
117134
$clientOptions = [
118135
'headers' => [
@@ -269,6 +286,8 @@ public function getLastReadEventId(): ?string
269286
*/
270287
public function import(bool $fromStart, array $eventsToSkip, ?callable $progressReporter = null): bool
271288
{
289+
$this->configureLogger();
290+
272291
// We need the verdicts to validate judgement-types.
273292
$this->verdicts = $this->config->getVerdicts(['final', 'external']);
274293

@@ -2087,4 +2106,19 @@ protected function removeWarning(EventType $eventType, ?string $entityId, string
20872106
$this->em->flush();
20882107
}
20892108
}
2109+
2110+
protected function configureLogger(): void
2111+
{
2112+
// Configure a logger to use a file per contest.
2113+
// For this we need to create our own logger.
2114+
// This code is based on what Symfony does with their default loggers.
2115+
$name = sprintf('event-feed-importer-%s', $this->getSourceContestId());
2116+
$logFile = sprintf('%s/%s.log', $this->logDir, $name);
2117+
$handler = new StreamHandler(
2118+
$logFile,
2119+
$this->env === 'dev' ? Level::Debug : Level::Info,
2120+
);
2121+
$handler->pushProcessor($this->psrLogMessageProcessor);
2122+
$this->logger = new Logger($name, [$handler], iterator_to_array($this->logProcessors));
2123+
}
20902124
}

0 commit comments

Comments
 (0)