Log4cxx
  1. Log4cxx
  2. LOGCXX-7

SocketAppender binary format not compatible with Chainsaw

    Details

    • Type: Improvement Improvement
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: 0.9.7
    • Fix Version/s: 0.10.0
    • Component/s: Appender
    • Labels:
      None

      Description

      Chainsaw can process debug events sent by the socket appender from log4j (using Java serialization), however log4net and log4cxx implementations of SocketAppender do not create compatible byte streams. It would be an improvement if both log4net and log4cxx produced streams compatible with log4j. It is possible, but not likely, that there are listeners for the existing formats that would be broken with such a change.

      Chainsaw is compatible with XMLSocketAppender.

      Thread starting at: http://nagoya.apache.org/eyebrowse/ReadMsg?listName=log4cxx-user@logging.apache.org&msgNo=155

        Activity

        Hide
        Curt Arnold added a comment -

        http://nagoya.apache.org/eyebrowse/ReadMsg?listName=log4cxx-user@logging.apache.org&msgNo=612

        Hi,

        After a little bit of struggling we succeeded in building
        0.9.7 on the tru64 using the compaq cxx compiler. However,
        we now run into a runtime problem.

        Using the DelayedLoop example and the simple socket server
        on the same platform works fine. However, if we run the
        DelayedLoop example on windows and the simple socket server
        on tru64 it does not work. DeleyedLoop does succeed in
        establishing a connection with the socket server, however
        no messages arrive (also no error reports on either
        side). We suspect something like an 32 bits integer is written
        and a 64 bits integer is read. Could this be the case? If
        so, will this still be the case in the next release?

        After some poking around (in CVS head) I discovered that
        the SocketOutputStream class uses plain int, long and
        unsigned int types for writing data to the socket.
        Shouldn't this be some kind of platform safe types?

        How is this best fixed?

        Show
        Curt Arnold added a comment - http://nagoya.apache.org/eyebrowse/ReadMsg?listName=log4cxx-user@logging.apache.org&msgNo=612 Hi, After a little bit of struggling we succeeded in building 0.9.7 on the tru64 using the compaq cxx compiler. However, we now run into a runtime problem. Using the DelayedLoop example and the simple socket server on the same platform works fine. However, if we run the DelayedLoop example on windows and the simple socket server on tru64 it does not work. DeleyedLoop does succeed in establishing a connection with the socket server, however no messages arrive (also no error reports on either side). We suspect something like an 32 bits integer is written and a 64 bits integer is read. Could this be the case? If so, will this still be the case in the next release? After some poking around (in CVS head) I discovered that the SocketOutputStream class uses plain int, long and unsigned int types for writing data to the socket. Shouldn't this be some kind of platform safe types? How is this best fixed?
        Hide
        Curt Arnold added a comment -

        The following is an analysis for the tests/witness/serialization files in log4j 1.2 based from http://java.sun.com/javase/6/docs/platform/serialization/spec/protocol.html. The newHandle production in the spec doesn't seem to appear in the serialized form, either I'm misinterpreting it or it is a bug in the spec.

        Analysis of simple.bin

        AC ED == Stream magic
        00 05 == Stream version

        73 == TC_OBJECT, start of newObject
        72 == TC_CLASSDESC, start of newClassDesc
        00 21 == "org.apache.log4j.spi.LoggingEvent".length()
        6F 72 ... 6E 74 == "org.apache.log4j.spi.LoggingEvent"
        F3 F2 B9 23 74 0B B5 3F == LoggingEvent.serialVersionUID
        newHandle should appear here
        03 == classDescFlags of SC_WRITE_METHOD | SC_SERIALIZABLE
        00 0A == fields.length()
        5A == prim_typecode for boolean 'Z'
        00 15 == "mdcCopyLookupRequired".length()
        6D 64 ... 65 64 == "mdcCopyLookupRequired"
        5A == boolean field 'Z'
        00 01 == "ndcLookupRequired".length()
        6E 64 ... 65 64 == "ndcLookupRequired"
        4A == prim_typecode for long 'J'
        00 09 == "timeStamp".length
        74 69 ... 70 == "timeStamp"
        4C == obj_typecode 'L'
        00 0C == "categoryName".length
        63 61 ... 6D 65 == "categoryName"
        74 == TC_STRING?
        00 12 == "Ljava/lang/String;".length
        4C 6A ... 63 67 3B == "Ljava/lang/String;"
        4C == obj_typecode 'L'
        00 0C == "locationInfo".length
        6C 6F ... 66 6F == "locationInfo"
        74 == TC_STRING?
        00 23 == "Lorg/apache/log4j/spi/LocationInfo;"
        4C 6F ... 3B == "Lorg/.../LocationInfo;"
        4C == obj_typecode 'L'
        00 07 == "mdcCopy".length
        6D 64 ... 79 74 == "mdcCopy"
        74 == TC_STRING
        00 15 == "Ljava/util/Hashtable;"
        4C 6A ... 3B == "Ljava/util/Hashtable;"
        4C == obj_typecode 'L'
        00 03 == "ndc".length
        6E 64 63 == "ndc"
        71 == TC_REFERENCE
        00 7E 00 01 == handle to second serialized field (looks like shortcut to String)
        4C == obj_typecode 'L'
        00 0F == "renderedMessage".length()
        72 65 ... 67 65 == "renderedMessage"
        71 == TC_REFERENCE
        00 7E 00 01 == shortcut to String
        4C == obj_typecode 'L'
        00 0A == "threadName".length()
        74 68 ... 6D 65 == "threadName"
        71 == TC_REFERENCE
        00 7E 00 01 - string shortcut
        4C == obj_typecode 'L'
        00 0D == "throwableInfo".length
        74 68 ... 66 6F == "throwableInfo"
        74 == TC_STRING
        00 2B == "Lorg/apache/log4j/ThrowableInformation;".length()
        4C 6F ... 6E 3B == "Lorg/apache/log4j/ThrowableInformation;"
        78 == TC_ENDBLOCKDATA (no class annotation)
        70 == TC_NULL (no superClassDesc, LoggingEvent extends Object)

        Content from 0000-015A appears to be fixed

        Fields in order of class descriptor
        00 == mdcCopyLookupRequired
        00 == ndcLookupRequired
        00 00 01 05 26 1C EB 0C == timeStamp
        74 00 04 72 6F 6F 74 == categoryName: TC_STRING "root".length() "root"
        70 == locationInfo : TC_NULL
        70 == mdcCopy : TC_NULL
        70 == ndc : TC_NULL
        74 00 0D 48 65 ... 64 2E == renderedMessage: TC_STRING "Hello, world.".length() "Hello, World"
        74 00 04 6D 61 69 6E == threadName: TC_STRING "main".length() "main"
        70 == throwableInfo: TC_NULL

        Level is written by LoggingEvent.writeObject after default serialization

        77 == TC_BLOCKDATA
        04 size
        00 00 4E 20 - Level.INFO
        70 == TC_NULL - indicates using standard log4j Level class
        78 == TC_ENDBLOCKDATA

        -----------
        Analysis of location.bin

        Content from 0000-015A appears to be fixed per analysis in simple.bin.analysis

        Fields in order of class descriptor
        00 == mdcCopyLookupRequired
        00 == ndcLookupRequired
        00 00 01 05 26 1F FD D5 == timeStamp
        74 00 04 72 6F 6F 74 == categoryName: TC_STRING "root".length() "root"

        locationInfo follows (simple was TC_NULL == 0x70)

        73 == TC_OBJECT
        72 == TC_CLASSDESC
        00 21 == "org.apache.log4j.spi.LocationInfo".length()
        6F 72 ... 6F == "org.apache.log4j.spi.LocationInfo"
        ED 99 BB E1 4A 91 A5 72 == serialVersionID
        02 == classDescFlags: SC_SERIALIZABLE
        00 01 == fields.length()
        4C == obj_typecode 'L'
        00 08 == "fullInfo".length()
        66 75 ... 66 6F == "fullInfo"
        71 == TC_REFERENCE
        00 7E 00 01 == shortcut to String
        78 == TC_ENDBLOCKDATA (no class annotation)
        70 == TC_NULL (no superclass)
        70 == TC_NULL (location determination failed due to flaw in test, would expect to be TC_STRING length data)
        70 == mdcCopy : TC_NULL

        rest follows simple.bin

        --------------

        Analysis of ndc.bin

        Content from 0000-015A appears to be fixed per analysis in simple.bin.analysis

        Fields in order of class descriptor
        00 == mdcCopyLookupRequired
        00 == ndcLookupRequired
        00 00 01 05 26 21 85 35 == timeStamp
        74 00 04 72 6F 6F 74 == categoryName: TC_STRING "root".length() "root"
        70 == locationInfo : TC_NULL
        70 == mdcCopy : TC_NULL
        74 == TC_STRING
        00 08 == "ndc test".length()
        6E 64 ... 73 74 == "ndc test"
        74 00 0D 48 65 ... 64 2E == renderedMessage: TC_STRING "Hello, world.".length() "Hello, World"

        rest follows simple.bin

        ------

        Analysis of mdc.bin

        Content from 0000-015A appears to be fixed per analysis in simple.bin.analysis

        Fields in order of class descriptor
        00 == mdcCopyLookupRequired
        00 == ndcLookupRequired
        00 00 01 05 26 21 E9 E1 == timeStamp
        74 00 04 72 6F 6F 74 == categoryName: TC_STRING "root".length() "root"
        70 == locationInfo : TC_NULL
        73 == TC_OBJECT
        72 == TC_CLASSDESC
        00 13 == "java.util.Hashtable".length()
        6A 61 ... 6C 65 == "java.util.Hashtable"
        13 BB 0F 25 21 4A E4 B8 == serialVersionID
        03 == classDescFlags: SC_SERIALIZABLE | SC_WRITE_OBJECT
        00 02== fields.length()
        46 == prim_typecode 'F' float
        00 0A == "loadFactor".length()
        6C 6F ... 6F 72 == "loadFactor"
        49 == prim_typecode 'I' integer
        00 09 == "threshold".length()
        74 68 ... 6F 6C== "threshold"
        78 == TC_ENDBLOCKDATA (no class annotation)
        70 == TC_NULL (no superclass)
        3F 40 00 00 == 0.75
        00 00 00 05 == 5
        77 == TC_BLOCKDATA
        08 == size
        00 00 00 07 == buckets.length()
        00 00 00 01 == length
        74 == TC_STRING
        00 06 == "mdckey".length()
        6D 64 63 6B 65 79 == "mdckey"
        74 == TC_STRING
        00 08 == "mdcvalue".length()
        6D 64 63 .. 65 == "mdcvalue"
        78 == TC_ENDBLOCKDATA
        74 == TC_STRING
        00 08 == "ndc test".length()
        6E 64 ... 73 74 == "ndc test"
        74 00 0D 48 65 ... 64 2E == renderedMessage: TC_STRING "Hello, world.".length() "Hello, World"

        rest follows simple.bin

        Show
        Curt Arnold added a comment - The following is an analysis for the tests/witness/serialization files in log4j 1.2 based from http://java.sun.com/javase/6/docs/platform/serialization/spec/protocol.html . The newHandle production in the spec doesn't seem to appear in the serialized form, either I'm misinterpreting it or it is a bug in the spec. Analysis of simple.bin AC ED == Stream magic 00 05 == Stream version 73 == TC_OBJECT, start of newObject 72 == TC_CLASSDESC, start of newClassDesc 00 21 == "org.apache.log4j.spi.LoggingEvent".length() 6F 72 ... 6E 74 == "org.apache.log4j.spi.LoggingEvent" F3 F2 B9 23 74 0B B5 3F == LoggingEvent.serialVersionUID newHandle should appear here 03 == classDescFlags of SC_WRITE_METHOD | SC_SERIALIZABLE 00 0A == fields.length() 5A == prim_typecode for boolean 'Z' 00 15 == "mdcCopyLookupRequired".length() 6D 64 ... 65 64 == "mdcCopyLookupRequired" 5A == boolean field 'Z' 00 01 == "ndcLookupRequired".length() 6E 64 ... 65 64 == "ndcLookupRequired" 4A == prim_typecode for long 'J' 00 09 == "timeStamp".length 74 69 ... 70 == "timeStamp" 4C == obj_typecode 'L' 00 0C == "categoryName".length 63 61 ... 6D 65 == "categoryName" 74 == TC_STRING? 00 12 == "Ljava/lang/String;".length 4C 6A ... 63 67 3B == "Ljava/lang/String;" 4C == obj_typecode 'L' 00 0C == "locationInfo".length 6C 6F ... 66 6F == "locationInfo" 74 == TC_STRING? 00 23 == "Lorg/apache/log4j/spi/LocationInfo;" 4C 6F ... 3B == "Lorg/.../LocationInfo;" 4C == obj_typecode 'L' 00 07 == "mdcCopy".length 6D 64 ... 79 74 == "mdcCopy" 74 == TC_STRING 00 15 == "Ljava/util/Hashtable;" 4C 6A ... 3B == "Ljava/util/Hashtable;" 4C == obj_typecode 'L' 00 03 == "ndc".length 6E 64 63 == "ndc" 71 == TC_REFERENCE 00 7E 00 01 == handle to second serialized field (looks like shortcut to String) 4C == obj_typecode 'L' 00 0F == "renderedMessage".length() 72 65 ... 67 65 == "renderedMessage" 71 == TC_REFERENCE 00 7E 00 01 == shortcut to String 4C == obj_typecode 'L' 00 0A == "threadName".length() 74 68 ... 6D 65 == "threadName" 71 == TC_REFERENCE 00 7E 00 01 - string shortcut 4C == obj_typecode 'L' 00 0D == "throwableInfo".length 74 68 ... 66 6F == "throwableInfo" 74 == TC_STRING 00 2B == "Lorg/apache/log4j/ThrowableInformation;".length() 4C 6F ... 6E 3B == "Lorg/apache/log4j/ThrowableInformation;" 78 == TC_ENDBLOCKDATA (no class annotation) 70 == TC_NULL (no superClassDesc, LoggingEvent extends Object) Content from 0000-015A appears to be fixed Fields in order of class descriptor 00 == mdcCopyLookupRequired 00 == ndcLookupRequired 00 00 01 05 26 1C EB 0C == timeStamp 74 00 04 72 6F 6F 74 == categoryName: TC_STRING "root".length() "root" 70 == locationInfo : TC_NULL 70 == mdcCopy : TC_NULL 70 == ndc : TC_NULL 74 00 0D 48 65 ... 64 2E == renderedMessage: TC_STRING "Hello, world.".length() "Hello, World" 74 00 04 6D 61 69 6E == threadName: TC_STRING "main".length() "main" 70 == throwableInfo: TC_NULL Level is written by LoggingEvent.writeObject after default serialization 77 == TC_BLOCKDATA 04 size 00 00 4E 20 - Level.INFO 70 == TC_NULL - indicates using standard log4j Level class 78 == TC_ENDBLOCKDATA ----------- Analysis of location.bin Content from 0000-015A appears to be fixed per analysis in simple.bin.analysis Fields in order of class descriptor 00 == mdcCopyLookupRequired 00 == ndcLookupRequired 00 00 01 05 26 1F FD D5 == timeStamp 74 00 04 72 6F 6F 74 == categoryName: TC_STRING "root".length() "root" locationInfo follows (simple was TC_NULL == 0x70) 73 == TC_OBJECT 72 == TC_CLASSDESC 00 21 == "org.apache.log4j.spi.LocationInfo".length() 6F 72 ... 6F == "org.apache.log4j.spi.LocationInfo" ED 99 BB E1 4A 91 A5 72 == serialVersionID 02 == classDescFlags: SC_SERIALIZABLE 00 01 == fields.length() 4C == obj_typecode 'L' 00 08 == "fullInfo".length() 66 75 ... 66 6F == "fullInfo" 71 == TC_REFERENCE 00 7E 00 01 == shortcut to String 78 == TC_ENDBLOCKDATA (no class annotation) 70 == TC_NULL (no superclass) 70 == TC_NULL (location determination failed due to flaw in test, would expect to be TC_STRING length data) 70 == mdcCopy : TC_NULL rest follows simple.bin -------------- Analysis of ndc.bin Content from 0000-015A appears to be fixed per analysis in simple.bin.analysis Fields in order of class descriptor 00 == mdcCopyLookupRequired 00 == ndcLookupRequired 00 00 01 05 26 21 85 35 == timeStamp 74 00 04 72 6F 6F 74 == categoryName: TC_STRING "root".length() "root" 70 == locationInfo : TC_NULL 70 == mdcCopy : TC_NULL 74 == TC_STRING 00 08 == "ndc test".length() 6E 64 ... 73 74 == "ndc test" 74 00 0D 48 65 ... 64 2E == renderedMessage: TC_STRING "Hello, world.".length() "Hello, World" rest follows simple.bin ------ Analysis of mdc.bin Content from 0000-015A appears to be fixed per analysis in simple.bin.analysis Fields in order of class descriptor 00 == mdcCopyLookupRequired 00 == ndcLookupRequired 00 00 01 05 26 21 E9 E1 == timeStamp 74 00 04 72 6F 6F 74 == categoryName: TC_STRING "root".length() "root" 70 == locationInfo : TC_NULL 73 == TC_OBJECT 72 == TC_CLASSDESC 00 13 == "java.util.Hashtable".length() 6A 61 ... 6C 65 == "java.util.Hashtable" 13 BB 0F 25 21 4A E4 B8 == serialVersionID 03 == classDescFlags: SC_SERIALIZABLE | SC_WRITE_OBJECT 00 02== fields.length() 46 == prim_typecode 'F' float 00 0A == "loadFactor".length() 6C 6F ... 6F 72 == "loadFactor" 49 == prim_typecode 'I' integer 00 09 == "threshold".length() 74 68 ... 6F 6C== "threshold" 78 == TC_ENDBLOCKDATA (no class annotation) 70 == TC_NULL (no superclass) 3F 40 00 00 == 0.75 00 00 00 05 == 5 77 == TC_BLOCKDATA 08 == size 00 00 00 07 == buckets.length() 00 00 00 01 == length 74 == TC_STRING 00 06 == "mdckey".length() 6D 64 63 6B 65 79 == "mdckey" 74 == TC_STRING 00 08 == "mdcvalue".length() 6D 64 63 .. 65 == "mdcvalue" 78 == TC_ENDBLOCKDATA 74 == TC_STRING 00 08 == "ndc test".length() 6E 64 ... 73 74 == "ndc test" 74 00 0D 48 65 ... 64 2E == renderedMessage: TC_STRING "Hello, world.".length() "Hello, World" rest follows simple.bin

          People

          • Assignee:
            Michaël CATANZARITI
            Reporter:
            Curt Arnold
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development