1 public class LogDBAppender extends DBAppenderBase{2
3 protectedString insertSQL;4 protected static finalMethod GET_GENERATED_KEYS_METHOD;5
6 privateDBNameResolver dbNameResolver;7
8 static final int TIMESTMP_INDEX = 1;9 static final int FORMATTED_MESSAGE_INDEX = 2;10 static final int LOGGER_NAME_INDEX = 3;11 static final int LEVEL_STRING_INDEX = 4;12 static final int THREAD_NAME_INDEX = 5;13 static final int REFERENCE_FLAG_INDEX = 6;14 static final int ARG0_INDEX = 7;15 static final int ARG1_INDEX = 8;16 static final int ARG2_INDEX = 9;17 static final int ARG3_INDEX = 10;18 static final int CALLER_FILENAME_INDEX = 11;19 static final int CALLER_CLASS_INDEX = 12;20 static final int CALLER_METHOD_INDEX = 13;21 static final int CALLER_LINE_INDEX = 14;22 static final int EVENT_ID_INDEX = 15;23
24 static final StackTraceElement EMPTY_CALLER_DATA =CallerData.naInstance();25
26 static{27 //PreparedStatement.getGeneratedKeys() method was added in JDK 1.4
28 Method getGeneratedKeysMethod;29 try{30 //the
31 getGeneratedKeysMethod = PreparedStatement.class.getMethod("getGeneratedKeys", (Class[]) null);32 } catch(Exception ex) {33 getGeneratedKeysMethod = null;34 }35 GET_GENERATED_KEYS_METHOD =getGeneratedKeysMethod;36 }37
38 public voidsetDbNameResolver(DBNameResolver dbNameResolver) {39 this.dbNameResolver =dbNameResolver;40 }41
42 @Override43 public voidstart() {44 if (dbNameResolver == null)45 dbNameResolver = newDefaultDBNameResolver();46 insertSQL =buildInsertSQL(dbNameResolver);47 super.start();48 }49
50 @Override51 protected void subAppend(ILoggingEvent event, Connection connection, PreparedStatement insertStatement) throwsThrowable {52
53 bindLoggingEventWithInsertStatement(insertStatement, event);54 bindLoggingEventArgumentsWithPreparedStatement(insertStatement, event.getArgumentArray());55
56 //This is expensive... should we do it every time?
57 bindCallerDataWithPreparedStatement(insertStatement, event.getCallerData());58
59 int updateCount =insertStatement.executeUpdate();60 if (updateCount != 1) {61 addWarn("Failed to insert loggingEvent");62 }63 }64
65 protected void secondarySubAppend(ILoggingEvent event, Connection connection, long eventId) throwsThrowable {66 Map mergedMap =mergePropertyMaps(event);67 //insertProperties(mergedMap, connection, eventId);68
69 //if (event.getThrowableProxy() != null) {70 //insertThrowable(event.getThrowableProxy(), connection, eventId);71 //}
72 }73
74 void bindLoggingEventWithInsertStatement(PreparedStatement stmt, ILoggingEvent event) throwsSQLException {75 stmt.setLong(TIMESTMP_INDEX, event.getTimeStamp());76 stmt.setString(FORMATTED_MESSAGE_INDEX, event.getFormattedMessage());77 stmt.setString(LOGGER_NAME_INDEX, event.getLoggerName());78 stmt.setString(LEVEL_STRING_INDEX, event.getLevel().toString());79 stmt.setString(THREAD_NAME_INDEX, event.getThreadName());80 stmt.setShort(REFERENCE_FLAG_INDEX, DBHelper.computeReferenceMask(event));81 }82
83 void bindLoggingEventArgumentsWithPreparedStatement(PreparedStatement stmt, Object[] argArray) throwsSQLException {84
85 int arrayLen = argArray != null ? argArray.length : 0;86
87 for (int i = 0; i < arrayLen && i < 4; i++) {88 stmt.setString(ARG0_INDEX +i, asStringTruncatedTo254(argArray[i]));89 }90 if (arrayLen < 4) {91 for (int i = arrayLen; i < 4; i++) {92 stmt.setString(ARG0_INDEX + i, null);93 }94 }95 }96
97 String asStringTruncatedTo254(Object o) {98 String s = null;99 if (o != null) {100 s =o.toString();101 }102
103 if (s == null) {104 return null;105 }106 if (s.length() <= 254) {107 returns;108 } else{109 return s.substring(0, 254);110 }111 }112
113 void bindCallerDataWithPreparedStatement(PreparedStatement stmt, StackTraceElement[] callerDataArray) throwsSQLException {114
115 StackTraceElement caller =extractFirstCaller(callerDataArray);116
117 stmt.setString(CALLER_FILENAME_INDEX, caller.getFileName());118 stmt.setString(CALLER_CLASS_INDEX, caller.getClassName());119 stmt.setString(CALLER_METHOD_INDEX, caller.getMethodName());120 stmt.setString(CALLER_LINE_INDEX, Integer.toString(caller.getLineNumber()));121 }122
123 privateStackTraceElement extractFirstCaller(StackTraceElement[] callerDataArray) {124 StackTraceElement caller =EMPTY_CALLER_DATA;125 if(hasAtLeastOneNonNullElement(callerDataArray))126 caller = callerDataArray[0];127 returncaller;128 }129
130 private booleanhasAtLeastOneNonNullElement(StackTraceElement[] callerDataArray) {131 return callerDataArray != null && callerDataArray.length > 0 && callerDataArray[0] != null;132 }133
134 MapmergePropertyMaps(ILoggingEvent event) {135 Map mergedMap = new HashMap();136 //we add the context properties first, then the event properties, since137 //we consider that event-specific properties should have priority over138 //context-wide properties.
139 Map loggerContextMap =event.getLoggerContextVO().getPropertyMap();140 Map mdcMap =event.getMDCPropertyMap();141 if (loggerContextMap != null) {142 mergedMap.putAll(loggerContextMap);143 }144 if (mdcMap != null) {145 mergedMap.putAll(mdcMap);146 }147
148 returnmergedMap;149 }150
151 @Override152 protectedMethod getGeneratedKeysMethod() {153 returnGET_GENERATED_KEYS_METHOD;154 }155
156 @Override157 protectedString getInsertSQL() {158 returninsertSQL;159 }160
161
162 staticString buildInsertSQL(DBNameResolver dbNameResolver) {163 StringBuilder sqlBuilder = new StringBuilder("INSERT INTO ");164 sqlBuilder.append(dbNameResolver.getTableName(TableName.LOGGING_EVENT)).append(" (");165 sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.TIMESTMP)).append(", ");166 sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.FORMATTED_MESSAGE)).append(", ");167 sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.LOGGER_NAME)).append(", ");168 sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.LEVEL_STRING)).append(", ");169 sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.THREAD_NAME)).append(", ");170 sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.REFERENCE_FLAG)).append(", ");171 sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG0)).append(", ");172 sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG1)).append(", ");173 sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG2)).append(", ");174 sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG3)).append(", ");175 sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_FILENAME)).append(", ");176 sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_CLASS)).append(", ");177 sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_METHOD)).append(", ");178 sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_LINE)).append(") ");179 sqlBuilder.append("VALUES (?, ?, ? ,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");180 returnsqlBuilder.toString();181 }182 }