Hello all,

I finally have more time as a major deadline has passed at work. I was thinking about writing an improved JDBC appender. My intention is to create a new appender from scratch. As discussed previously, I figured I would have an abstract base class with an abstract getConnection() class and two concrete derivatives; one for getting the connection from a JNDI context and one for getting the connection from the DriverManager.

I just wanted to check in to see if anybody is working on this already. I also have a couple of questions:

1) The original JDBCAppender class has a buffer where it stored the events until a limit is hit. I'm not sure I understand the rationale behind this. Doesn't this cause most loggings to be fast but once in a while one client pays the bill for the rest? It also seems to have been a source of bugs in the past. Does anyone have a compelling reason for including it in the new appenders?

2) Is there a good place to look to get a feel for how the configuration works?

Thanks,
Ray


A couple of weeks ago we ran into the JDBCAppender bug that was fixed in 1.2.8.
While looking at the source code we found the bug and a few other improvement possibilities.
Below are two mail I sent to this list. Perhaps I need to explain better my thoughts here.


To: [EMAIL PROTECTED]
From: Roland Nygren <[EMAIL PROTECTED]>
Subject: JDBCAppender - faster buffer handling
Cc:
Bcc:
X-Eudora-Signature: <Standard>
Date: Thu, 06 Mar 2003 10:50:52 +0100


In JDBCAppender there are two ArrayLists: /** * ArrayList holding the buffer of Logging Events. */ protected ArrayList buffer;

  /**
   * Helper object for clearing out the buffer
   */
  protected ArrayList removes;

Why not just use one ArrayList instead of two to speed things up.
Using the ArrayList buffer as a FIFO-register could look like:
public synchronized void flushBuffer() {
//Do the actual logging
LoggingEvent logEvent = null;
while (buffer.size() >0) {
try {
logEvent = (LoggingEvent)buffer.remove(0);
} catch(Exception e) {
break;
}
try {
String sql = getLogStatement(logEvent);
execute(sql);
} catch (SQLException sqle) {
// Unable to store LogEvent i database, put it back in buffer.
if (logEvent != null) {
buffer.add(0, logEvent);
}
errorHandler.error("Failed to excute sql", sqle, ErrorCode.FLUSH_FAILURE);
}
}
}






To: [EMAIL PROTECTED]
From: Roland Nygren <[EMAIL PROTECTED]>
Subject: JDBCAppender - release user thread from writing to database
Cc:
Bcc:
X-Eudora-Signature: <Standard>
Date: Thu, 06 Mar 2003 11:05:55 +0100

It might be a good idea to release the user-thread from doing the actual database writing.
With a LogThread as in the example below the user-thread will return as soon as the LogEvent is stored in the buffer.


Depending on how Log4j is used it might not be permitted to create threads (like in an EJB container).
A configuration parameter that controlles if the JDBCAppender should use the thread or not might be useful.
Such configuration is not included below.



LogWorker logThread = new LogWorker(this);


  public JDBCAppender() {
    super();
    buffer = new ArrayList(bufferSize);
    logThread.start();
  }

  public void append(LoggingEvent event) {
    buffer.add(event);
    if (buffer.size() >= bufferSize)
      logThread.wakeup();
  }

  class LogWorker extends Thread {
    JDBCAppender parent;
    logWorker (JDBCAppender p) {
      parent = p;
    }
    public void run() {
        while (true) {
            try {
              synchronized(this) {
                wait();
              }
            } catch (InterruptedException e) { }
            parent.flushBuffer();
       }
    }

    public synchronized void wakeup() {
      notify();
    }
  }




---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to