Andrew Rose
Andrew Rose

Reputation: 838

Close a dynamically created Log4j 2 appender

I'm using the Routing functionality in Log4j 2 to dynamically create appenders at runtime. When I know that those appenders are finished with, I'd like to tell Log4j so that it can tidy up the related resources (flush & close files, free its internal objects related to those appenders, etc.). Without doing this, Log4j still has open file handles and I'm unable to manipulate the files that it has written (from an external process which post-processes and archives the logs).

How do I tell Log4j that an appender won't be used again?

I include my Log4j configuration for completeness.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>

    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} %level{ERROR=!, WARN=?, INFO=-, DEBUG=., TRACE=.} %msg%n"/>
    </Console>

    <Routing name="MatchLogs">
      <Routes pattern="$${ctx:matchID}">
        <Route>
          <RandomAccessFile name="MatchLog-${ctx:matchID}" fileName="logs/${ctx:matchID}.log">
            <PatternLayout pattern="%d{ISO8601} %-5level %-30.30logger{1} %msg%n"/>
          </RandomAccessFile>
        </Route>
      </Routes>
    </Routing>
    <Async name="AsyncWrapper">
      <AppenderRef ref="MatchLogs" level="debug"/>
      <AppenderRef ref="Console" level = "info"/>
    </Async>

    <Routing name="MatchStatsLogs">
      <Routes pattern="$${ctx:matchID}">
        <Route>
          <RandomAccessFile name="MatchStatsLog-${ctx:matchID}" fileName="logs/${ctx:matchID}_stats.log">
            <PatternLayout pattern="%msg"/>
          </RandomAccessFile>
        </Route>
      </Routes>
    </Routing>
    <Async name="AsyncStatsWrapper">
      <AppenderRef ref="MatchStatsLogs" level="debug"/>
    </Async>

  </Appenders>


  <Loggers>
    <Logger name="stats" level="trace" additivity="false">
      <AppenderRef ref="AsyncStatsWrapper"/>
    </Logger>
    <Root level="debug">
      <AppenderRef ref="AsyncWrapper"/>
    </Root>
  </Loggers>


</Configuration>

When a match starts, I call ThreadContext.put("matchID", theMatchID); from each thread that is involved in that match. When a match finishes, I clear the ThreadContext. Obviously that isn't sufficient for Log4j to know that I'm not going to re-use that match ID, so it keeps the Appender around. However, I know that I'm not going to re-use the match ID, so how do I tell Log4j to tidy up?

Upvotes: 4

Views: 3184

Answers (1)

Remko Popma
Remko Popma

Reputation: 36754

Log4J does not provide that function yet. You may want to raise a feature request in the Log4J2 issue tracker (https://issues.apache.org/jira/browse/LOG4J2 ).

Upvotes: 2

Related Questions