@@ -562,6 +562,97 @@ void consumerVariantWithException() {
562562 assertSame (ex , r .throwable ());
563563 }
564564
565+ @ Test
566+ void eventCtxAttachesForeignContext () {
567+ Logger requestLog = TestLogger .create ("request" , enabledLevels , records ).with ()
568+ .attr ("requestId" , "req-42" )
569+ .attr ("traceId" , "abc-123" )
570+ .build ();
571+
572+ Logger log = TestLogger .create ("test" , enabledLevels , records );
573+ log .info ().ctx (requestLog ).attr ("msgId" , "1:2:3" ).log ("processed" );
574+
575+ assertEquals (1 , records .size ());
576+ LogRecord r = records .get (0 );
577+ // Logger name stays the static logger's name
578+ assertEquals ("test" , r .loggerName ());
579+ List <Attr > a = attrs (r );
580+ assertEquals (3 , a .size ());
581+ // ctx attrs come first
582+ assertEquals ("requestId" , a .get (0 ).key ());
583+ assertEquals ("traceId" , a .get (1 ).key ());
584+ // then per-event attrs
585+ assertEquals ("msgId" , a .get (2 ).key ());
586+ }
587+
588+ @ Test
589+ void eventCtxOrderedBeforeLoggerOwnContext () {
590+ Logger requestLog = TestLogger .create ("request" , enabledLevels , records ).with ()
591+ .attr ("requestId" , "req-42" )
592+ .build ();
593+
594+ Logger log = TestLogger .create ("test" , enabledLevels , records ).with ()
595+ .attr ("component" , "worker" )
596+ .build ();
597+
598+ log .info ().ctx (requestLog ).attr ("msgId" , "1:2:3" ).log ("processed" );
599+
600+ List <Attr > a = attrs (records .get (0 ));
601+ assertEquals (3 , a .size ());
602+ // ctx attrs first, then logger's own, then per-event
603+ assertEquals ("requestId" , a .get (0 ).key ());
604+ assertEquals ("component" , a .get (1 ).key ());
605+ assertEquals ("msgId" , a .get (2 ).key ());
606+ }
607+
608+ @ Test
609+ void eventCtxWithEmptyLoggerIsNoOp () {
610+ Logger empty = TestLogger .create ("empty" , enabledLevels , records );
611+ Logger log = TestLogger .create ("test" , enabledLevels , records );
612+
613+ log .info ().ctx (empty ).attr ("k" , "v" ).log ("msg" );
614+
615+ List <Attr > a = attrs (records .get (0 ));
616+ assertEquals (1 , a .size ());
617+ assertEquals ("k" , a .get (0 ).key ());
618+ }
619+
620+ @ Test
621+ void eventCtxMultipleCallsAppendInOrder () {
622+ Logger producerLog = TestLogger .create ("producer" , enabledLevels , records ).with ()
623+ .attr ("topic" , "orders" )
624+ .build ();
625+ Logger requestLog = TestLogger .create ("request" , enabledLevels , records ).with ()
626+ .attr ("requestId" , "req-42" )
627+ .build ();
628+
629+ Logger log = TestLogger .create ("test" , enabledLevels , records );
630+ log .info ()
631+ .ctx (producerLog )
632+ .ctx (requestLog )
633+ .attr ("extra" , "val" )
634+ .log ("combined" );
635+
636+ List <Attr > a = attrs (records .get (0 ));
637+ assertEquals (3 , a .size ());
638+ assertEquals ("topic" , a .get (0 ).key ());
639+ assertEquals ("requestId" , a .get (1 ).key ());
640+ assertEquals ("extra" , a .get (2 ).key ());
641+ }
642+
643+ @ Test
644+ void eventCtxOnDisabledLevelIsNoOp () {
645+ Logger requestLog = TestLogger .create ("request" , enabledLevels , records ).with ()
646+ .attr ("requestId" , "req-42" )
647+ .build ();
648+
649+ Logger log = TestLogger .create ("test" , enabledLevels , records );
650+ // DEBUG is disabled in this test setup
651+ log .debug ().ctx (requestLog ).attr ("k" , "v" ).log ("nope" );
652+
653+ assertEquals (0 , records .size ());
654+ }
655+
565656 @ Test
566657 void duplicateKeysInEventAttrs () {
567658 Logger log = TestLogger .create ("test" , enabledLevels , records ).with ()
0 commit comments