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

In async mode JsonLayout can't serialize an event with self referenced throwable

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 2.8.2, 2.9.0
    • None
    • Layouts
    • None

    Description

      When async logging is configured, JsonLayout cannot serialize a log event in which provided Throwable has a self-reference. For example, this may be the case for many Spring exceptions inherited from org.springframework.core.NestedRuntimeException or org.springframework.core.NestedCheckedException classes via getMostSpecificCause() method.

      The root cause of the bug is org.apache.logging.log4j.core.async.RingBufferLogEvent.getThrowable() method, it isn't marked as ignored by Jackson serializer, so when the Throwable in a log event contains a self-reference, Jackson blows up with an exception

      2017-09-07 13:28:08,799 Log4j2-TF-1-AsyncLogger[AsyncContext@6bc7c054]-1 ERROR com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: org.apache.logging.log4j.core.async.RingBufferLogEvent["throwable"]->org.log4j.App$SelfReferencedException["mostSpecificCause"]) com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: org.apache.logging.log4j.core.async.RingBufferLogEvent["throwable"]->org.log4j.App$SelfReferencedException["mostSpecificCause"])
      	at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
      	at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1191)
      	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter._handleSelfReference(BeanPropertyWriter.java:944)
      	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:721)
      	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
      	at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
      	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
      	at com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter.serializeAsField(SimpleBeanPropertyFilter.java:208)
      	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFieldsFiltered(BeanSerializerBase.java:771)
      	at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:153)
      	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
      	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
      	at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1396)
      	at com.fasterxml.jackson.databind.ObjectWriter._configAndWriteValue(ObjectWriter.java:1120)
      	at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:966)
      	at org.apache.logging.log4j.core.layout.AbstractJacksonLayout.toSerializable(AbstractJacksonLayout.java:213)
      	at org.apache.logging.log4j.core.layout.JsonLayout.toSerializable(JsonLayout.java:254)
      	at org.apache.logging.log4j.core.layout.AbstractJacksonLayout.toSerializable(AbstractJacksonLayout.java:193)
      	at org.apache.logging.log4j.core.layout.JsonLayout.toSerializable(JsonLayout.java:60)
      	at org.apache.logging.log4j.core.layout.AbstractJacksonLayout.toSerializable(AbstractJacksonLayout.java:34)
      	at org.apache.logging.log4j.core.layout.AbstractStringLayout.toByteArray(AbstractStringLayout.java:299)
      	at org.apache.logging.log4j.core.layout.AbstractLayout.encode(AbstractLayout.java:210)
      	at org.apache.logging.log4j.core.layout.AbstractLayout.encode(AbstractLayout.java:37)
      ...
      

      One possible workaround is to create a custom Layout which delegates necessary calls to the original JsonLayout catching possible JsonProcessingException - when the latter is actually caught, another attempt to serialize a LogEvent is made, but this time instead of the original log event object a Log4jLogEvent.createMemento(originalEvent) copy is serialized.

      The potential fix for the core JsonLayout class would be to configure Jackson to ignore RingBufferLogEvent.getThrowable()?

      Attachments

        1. log4j-issue.zip
          2 kB
          Leonid Bogdanov

        Activity

          People

            Unassigned Unassigned
            von_zeppelin Leonid Bogdanov
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated: