Log4j 2
  1. Log4j 2
  2. LOG4J2-330

NoSQLAppender cannot insert log event to MongoDB

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0-beta8
    • Fix Version/s: 2.0-rc1
    • Component/s: Appenders
    • Labels:
      None
    • Environment:

      JDK 1.7, Mongo Driver 2.11.2

      Description

      Seems like NoSQLAppender can't insert any log events to Mongo due to lack of serializer for Level enum.

      2013-07-31 18:19:27,831 ERROR An exception occurred processing Appender databaseAppender java.lang.IllegalArgumentException: can't serialize class org.apache.logging.log4j.Level
      at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:270)
      at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:174)
      at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:120)
      at com.mongodb.DefaultDBEncoder.writeObject(DefaultDBEncoder.java:27)
      at com.mongodb.OutMessage.putObject(OutMessage.java:289)
      at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:239)
      at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:204)
      at com.mongodb.DBCollection.insert(DBCollection.java:148)
      at com.mongodb.DBCollection.insert(DBCollection.java:91)
      at org.apache.logging.log4j.core.appender.db.nosql.mongo.MongoDBConnection.insertObject(MongoDBConnection.java:61)

      Here is my config

      <configuration status="WARN">
      <appenders>
      <NoSql name="databaseAppender" suppressExceptions="true">
      <MongoDb collectionName="applicationLog" factoryClassName="com.borsch.DBManager" factoryMethodName="getNewMongoClient" writeConcernConstant="NONE" username="root" password="qwe"/>
      </NoSql>
      </appenders>
      <loggers>
      <root level="error">
      <appender-ref ref="databaseAppender"/>
      </root>
      </loggers>
      </configuration>

      For now I used following workaround (code is in Scala)

       
      class LevelBSONEncoder extends org.bson.Transformer {
        def transform(o: Any): AnyRef =
          o match { case level: org.apache.logging.log4j.Level => new java.lang.Integer(level.intLevel()) }
      }
      
      // which is used like this
      
      org.bson.BSON.addEncodingHook(org.apache.logging.log4j.Level.ERROR.getClass, new LevelBSONEncoder())
      

      I think it should be done in appender.

        Activity

        Hide
        Nick Williams added a comment -

        Thanks. I'll get this in soon.

        Show
        Nick Williams added a comment - Thanks. I'll get this in soon.
        Hide
        Nick Williams added a comment -

        Fixed in trunk. Please verify (either by compiling from trunk or waiting for beta9) and close.

        Show
        Nick Williams added a comment - Fixed in trunk. Please verify (either by compiling from trunk or waiting for beta9) and close.
        Hide
        Nick Williams added a comment -

        By the way: Unfortunately MongoDB does not provide a way to configure transformers on a per-connection basis. It's a static configuration, which is global and affects everything. There's no way really around this. If per-connection transformers had been allowed, I would have made this configurable. Since it has to be static (potentially affecting multiple applications in certain environments), I made the transformer use the String Level name, which is more verbose and less fragile than using the ordinal, level number, etc. Note that this is different than the one you are using, and so will result in log events being persisted differently.

        Show
        Nick Williams added a comment - By the way: Unfortunately MongoDB does not provide a way to configure transformers on a per-connection basis. It's a static configuration, which is global and affects everything. There's no way really around this. If per-connection transformers had been allowed, I would have made this configurable. Since it has to be static (potentially affecting multiple applications in certain environments), I made the transformer use the String Level name, which is more verbose and less fragile than using the ordinal, level number, etc. Note that this is different than the one you are using, and so will result in log events being persisted differently.
        Hide
        Poorna Subhash P added a comment - - edited

        I checked it in 2.0-beta9, it is still not working.Below is the stacktrace.

        java.lang.IllegalArgumentException: can't serialize class org.apache.logging.log4j.Level
        at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:270)
        at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:174)
        at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:120)
        at com.mongodb.DefaultDBEncoder.writeObject(DefaultDBEncoder.java:27)
        at com.mongodb.OutMessage.putObject(OutMessage.java:289)
        at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:239)
        at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:204)
        at com.mongodb.DBCollection.insert(DBCollection.java:148)
        at com.mongodb.DBCollection.insert(DBCollection.java:91)

        I have looked at the class MongoDBConnection.java. Updated code only has decodeHook registered, not the encodeHook. Hence encoding is still failing.

        Show
        Poorna Subhash P added a comment - - edited I checked it in 2.0-beta9, it is still not working.Below is the stacktrace. java.lang.IllegalArgumentException: can't serialize class org.apache.logging.log4j.Level at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:270) at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:174) at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:120) at com.mongodb.DefaultDBEncoder.writeObject(DefaultDBEncoder.java:27) at com.mongodb.OutMessage.putObject(OutMessage.java:289) at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:239) at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:204) at com.mongodb.DBCollection.insert(DBCollection.java:148) at com.mongodb.DBCollection.insert(DBCollection.java:91) I have looked at the class MongoDBConnection.java. Updated code only has decodeHook registered, not the encodeHook. Hence encoding is still failing.
        Hide
        Nick Williams added a comment - - edited

        *head desk*

        That was a stupid mistake on my part. It's unfortunate that you weren't able to verify this bug before beta9 was released. I could have gotten it fixed. But it is what it is. The fix will be in 2.0.0.next.

        Show
        Nick Williams added a comment - - edited * head desk * That was a stupid mistake on my part. It's unfortunate that you weren't able to verify this bug before beta9 was released. I could have gotten it fixed. But it is what it is. The fix will be in 2.0.0.next.
        Hide
        Poorna Subhash P added a comment -

        Hi Nick,
        I am not the reporter of the bug. I just happened to upgrade to 2.0 today and encountered the issue.

        Show
        Poorna Subhash P added a comment - Hi Nick, I am not the reporter of the bug. I just happened to upgrade to 2.0 today and encountered the issue.
        Hide
        Nick Williams added a comment -

        Oh. Haha. My bad. I guess that's my queue to go to bed.

        Show
        Nick Williams added a comment - Oh. Haha. My bad. I guess that's my queue to go to bed.
        Hide
        Remko Popma added a comment -

        Looks like Nick fixed this issue in RC1, as part of the fix for LOG4J2-475.

        Please verify and close.

        Show
        Remko Popma added a comment - Looks like Nick fixed this issue in RC1, as part of the fix for LOG4J2-475 . Please verify and close.

          People

          • Assignee:
            Nick Williams
            Reporter:
            Ruslan
          • Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development