Uploaded image for project: 'Log4j 2'
  1. Log4j 2
  2. LOG4J2-2378

Are stateful Layouts officially supported?

    XMLWordPrintableJSON

Details

    • Question
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 2.8, 2.8.1, 2.8.2
    • None
    • Configurators, Layouts, Plugins
    • None

    Description

      **I'm using Log4J 2.8.2 in a corporate environment. I don't have permission to share any code at the moment, but if needed I can go through the steps necessary to do that.

      I'm working on a Layout that encodes events in a compact, binary format. Over the course of each hour, the Layout detects large, frequently repeating values and stores them in a List. When the log rolls over at the top of the next hour, the Layout's getHeader() call writes the list of repeating values at the beginning of the new file. From then on, the Layout can opt to write a reference to a position in that list instead of writing out the complete value in order to save space.

      This Layout relies on Log4J calling the `encode()` method on the Layout until rollover occurs and then calling `getHeader()`. Unfortunately, via debugging I can tell that Log4J is creating two different instances of my Layout. It uses one for calling `encode()` and then uses the other instance (which hasn't done any encoding) to call `getHeader()`. This results in the getHeader() instance writing out an empty list during rollover and the encode() instance emitting invalid references to a list that doesn't exist.

      I've traced this back to a library in my project calling `LoggerContext.getContext()`. This appears to create a second, default LoggerContext that initializes another copy of my Layout. If I modify that code to be `LoggerContext.getContext(false)`, no second context is created and my Layout works as expected.

      Based on this, I dug around in the code a bit. From what I've seen, the other Layout implementations provided by Log4J do not attempt to maintain any state over time. This is why, for instance, users  of PatternLayout and JsonLayout don't seem to run into this problem. Calling getHeader() on one instance of JsonLayout and encode() on another instance results in the same behavior because it is stateless.

      With this in mind:

      1. Are stateful Layouts meant to be supported?
      2. I've already changed the code that was creating another default LoggerContext. However, but I'm worried that other folks who'd like to use my code won't have that option. Is there something I can do to make sure that Log4J resolves to the same instance of my Layout each time?

       

       

      Attachments

        Activity

          People

            Unassigned Unassigned
            zslayton Zack Slayton
            Votes:
            1 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated: