2020use Cake \Console \Arguments ;
2121use Cake \Console \ConsoleIo ;
2222use Cake \Core \ContainerInterface ;
23+ use Cake \Log \Engine \ConsoleLog ;
24+ use Cake \Log \Log ;
2325use Cake \Queue \Job \Message ;
2426use Cake \Queue \Queue \Processor ;
2527use Enqueue \Null \NullConnectionFactory ;
2628use Enqueue \Null \NullMessage ;
2729use Interop \Queue \Message as QueueMessage ;
2830use Interop \Queue \Processor as InteropProcessor ;
31+ use Psr \Log \LoggerInterface ;
2932use Psr \Log \NullLogger ;
3033use RuntimeException ;
3134use Throwable ;
@@ -160,8 +163,10 @@ protected function executeJob(array $data): string
160163 }
161164 }
162165
166+ $ logger = $ this ->configureLogging ($ data );
167+
163168 $ message = new Message ($ queueMessage , $ context , $ this ->container );
164- $ processor = new Processor (new NullLogger () , $ this ->container );
169+ $ processor = new Processor ($ logger , $ this ->container );
165170
166171 $ result = $ processor ->processMessage ($ message );
167172
@@ -170,6 +175,52 @@ protected function executeJob(array $data): string
170175 return is_string ($ result ) ? $ result : (string )$ result ;
171176 }
172177
178+ /**
179+ * Configure logging to use STDERR to prevent job logs from contaminating STDOUT.
180+ * Reconfigures all CakePHP loggers to write to STDERR.
181+ *
182+ * @param array<string, mixed> $data Job data
183+ * @return \Psr\Log\LoggerInterface
184+ */
185+ protected function configureLogging (array $ data ): LoggerInterface
186+ {
187+ if (Log::drop ('stderr ' )) {
188+ // Logger was already configured, remove it first
189+ }
190+
191+ Log::setConfig ('stderr ' , [
192+ 'className ' => ConsoleLog::class,
193+ 'stream ' => 'php://stderr ' ,
194+ ]);
195+
196+ $ loggerName = $ data ['logger ' ] ?? 'stderr ' ;
197+ if ($ loggerName === 'stdout ' ) {
198+ $ loggerName = 'stderr ' ;
199+ }
200+
201+ $ logger = Log::engine ($ loggerName );
202+ if (!$ logger instanceof LoggerInterface) {
203+ $ logger = new NullLogger ();
204+ }
205+
206+ // Reconfigure all CakePHP logs to use stderr to prevent job logs from appearing in STDOUT
207+ $ loggers = Log::configured ();
208+ foreach ($ loggers as $ configLoggerName ) {
209+ if ($ configLoggerName === 'stderr ' ) {
210+ continue ;
211+ }
212+
213+ Log::drop ($ configLoggerName );
214+ }
215+
216+ Log::setConfig ('default ' , [
217+ 'className ' => ConsoleLog::class,
218+ 'stream ' => 'php://stderr ' ,
219+ ]);
220+
221+ return $ logger ;
222+ }
223+
173224 /**
174225 * Output result as JSON to STDOUT.
175226 *
0 commit comments