3030 */
3131public class CapturingLogger {
3232
33+ private static final String IMPLICIT_APPENDER_NAME = "__implicit" ;
34+
3335 /**
3436 * Constructs a new {@link CapturingLogger} named as the fully qualified name of
3537 * the invoking method. One name can be assigned to a single logger globally, so
@@ -52,42 +54,88 @@ public static Logger newCapturingLogger(final Level level, @Nullable StringLayou
5254 final String name = caller .getClassName () + "." + caller .getMethodName () + "." + level .toString ();
5355 final Logger logger = ESLoggerFactory .getLogger (name );
5456 Loggers .setLevel (logger , level );
55- final MockAppender appender = new MockAppender (name , layout );
57+ attachNewMockAppender (logger , IMPLICIT_APPENDER_NAME , layout );
58+ return logger ;
59+ }
60+
61+ public static void attachNewMockAppender (final Logger logger , final String appenderName , @ Nullable StringLayout layout )
62+ throws IllegalAccessException {
63+ final MockAppender appender = new MockAppender (buildAppenderName (logger .getName (), appenderName ), layout );
5664 appender .start ();
5765 Loggers .addAppender (logger , appender );
58- return logger ;
5966 }
6067
61- private static MockAppender getMockAppender (final String name ) {
68+ private static String buildAppenderName (final String loggerName , final String appenderName ) {
69+ // appender name also has to be unique globally (logging context globally)
70+ return loggerName + "." + appenderName ;
71+ }
72+
73+ private static MockAppender getMockAppender (final String loggerName , final String appenderName ) {
6274 final LoggerContext ctx = (LoggerContext ) LogManager .getContext (false );
6375 final Configuration config = ctx .getConfiguration ();
64- final LoggerConfig loggerConfig = config .getLoggerConfig (name );
65- return (MockAppender ) loggerConfig .getAppenders ().get (name );
76+ final LoggerConfig loggerConfig = config .getLoggerConfig (loggerName );
77+ final String mockAppenderName = buildAppenderName (loggerName , appenderName );
78+ return (MockAppender ) loggerConfig .getAppenders ().get (mockAppenderName );
6679 }
6780
6881 /**
69- * Checks if the logger's appender has captured any events.
82+ * Checks if the logger's appender(s) has captured any events.
7083 *
71- * @param name
84+ * @param loggerName
7285 * The unique global name of the logger.
86+ * @param appenderNames
87+ * Names of other appenders nested under this same logger.
7388 * @return {@code true} if no event has been captured, {@code false} otherwise.
7489 */
75- public static boolean isEmpty (final String name ) {
76- final MockAppender appender = getMockAppender (name );
77- return appender .isEmpty ();
90+ public static boolean isEmpty (final String loggerName , final String ... appenderNames ) {
91+ // check if implicit appender is empty
92+ final MockAppender implicitAppender = getMockAppender (loggerName , IMPLICIT_APPENDER_NAME );
93+ assert implicitAppender != null ;
94+ if (false == implicitAppender .isEmpty ()) {
95+ return false ;
96+ }
97+ if (null == appenderNames ) {
98+ return true ;
99+ }
100+ // check if any named appenders are empty
101+ for (String appenderName : appenderNames ) {
102+ final MockAppender namedAppender = getMockAppender (loggerName , appenderName );
103+ if (namedAppender != null && false == namedAppender .isEmpty ()) {
104+ return false ;
105+ }
106+ }
107+ return true ;
108+ }
109+
110+ /**
111+ * Gets the captured events for a logger by its name. Events are those of the
112+ * implicit appender of the logger.
113+ *
114+ * @param loggerName
115+ * The unique global name of the logger.
116+ * @param level
117+ * The priority level of the captured events to be returned.
118+ * @return A list of captured events formated to {@code String}.
119+ */
120+ public static List <String > output (final String loggerName , final Level level ) {
121+ return output (loggerName , IMPLICIT_APPENDER_NAME , level );
78122 }
79123
80124 /**
81- * Gets the captured events for a logger by its name.
125+ * Gets the captured events for a logger and an appender by their respective
126+ * names. There is a one to many relationship between loggers and appenders.
82127 *
83- * @param name
128+ * @param loggerName
84129 * The unique global name of the logger.
130+ * @param appenderName
131+ * The name of an appender associated with the {@code loggerName}
132+ * logger.
85133 * @param level
86134 * The priority level of the captured events to be returned.
87135 * @return A list of captured events formated to {@code String}.
88136 */
89- public static List <String > output (final String name , final Level level ) {
90- final MockAppender appender = getMockAppender (name );
137+ public static List <String > output (final String loggerName , final String appenderName , final Level level ) {
138+ final MockAppender appender = getMockAppender (loggerName , appenderName );
91139 return appender .output (level );
92140 }
93141
0 commit comments