1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.classic.db;
15
16 import java.lang.reflect.Method;
17 import java.sql.Connection;
18 import java.sql.PreparedStatement;
19 import java.sql.SQLException;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.Map;
23 import java.util.Set;
24
25 import ch.qos.logback.classic.spi.ILoggingEvent;
26 import ch.qos.logback.classic.spi.StackTraceElementProxy;
27 import ch.qos.logback.core.db.DBAppenderBase;
28
29
30
31
32
33
34
35
36
37
38
39
40 public class DBAppender extends DBAppenderBase<ILoggingEvent> {
41 protected final String insertPropertiesSQL = "INSERT INTO logging_event_property (event_id, mapped_key, mapped_value) VALUES (?, ?, ?)";
42 protected final String insertExceptionSQL = "INSERT INTO logging_event_exception (event_id, i, trace_line) VALUES (?, ?, ?)";
43 protected static final String insertSQL;
44 protected static final Method GET_GENERATED_KEYS_METHOD;
45
46 static {
47 StringBuffer sql = new StringBuffer();
48 sql.append("INSERT INTO logging_event (");
49 sql.append("timestmp, ");
50 sql.append("formatted_message, ");
51 sql.append("logger_name, ");
52 sql.append("level_string, ");
53 sql.append("thread_name, ");
54 sql.append("reference_flag, ");
55 sql.append("caller_filename, ");
56 sql.append("caller_class, ");
57 sql.append("caller_method, ");
58 sql.append("caller_line) ");
59 sql.append(" VALUES (?, ?, ? ,?, ?, ?, ?, ?, ?,?)");
60 insertSQL = sql.toString();
61
62
63 Method getGeneratedKeysMethod;
64 try {
65
66 getGeneratedKeysMethod = PreparedStatement.class.getMethod(
67 "getGeneratedKeys", (Class[]) null);
68 } catch (Exception ex) {
69 getGeneratedKeysMethod = null;
70 }
71 GET_GENERATED_KEYS_METHOD = getGeneratedKeysMethod;
72 }
73
74 public DBAppender() {
75 }
76
77 @Override
78 protected void subAppend(Object eventObject, Connection connection,
79 PreparedStatement insertStatement) throws Throwable {
80 ILoggingEvent event = (ILoggingEvent) eventObject;
81
82 bindLoggingEventWithInsertStatement(insertStatement, event);
83
84 bindCallerDataWithPreparedStatement(insertStatement, event.getCallerData());
85
86 int updateCount = insertStatement.executeUpdate();
87 if (updateCount != 1) {
88 addWarn("Failed to insert loggingEvent");
89 }
90
91 int eventId = selectEventId(insertStatement, connection);
92
93 Map<String, String> mergedMap = mergePropertyMaps(event);
94 insertProperties(mergedMap, connection, eventId);
95
96 if (event.getThrowableProxy() != null) {
97 insertThrowable(event.getThrowableProxy().getStackTraceElementProxyArray(), connection, eventId);
98 }
99 }
100
101 void bindLoggingEventWithInsertStatement(PreparedStatement stmt, ILoggingEvent event)
102 throws SQLException {
103 stmt.setLong(1, event.getTimeStamp());
104 stmt.setString(2, event.getFormattedMessage());
105 stmt.setString(3, event.getLoggerName());
106 stmt.setString(4, event.getLevel().toString());
107 stmt.setString(5, event.getThreadName());
108 stmt.setShort(6, DBHelper.computeReferenceMask(event));
109 }
110
111 void bindCallerDataWithPreparedStatement(PreparedStatement stmt, StackTraceElement[] callerDataArray)
112 throws SQLException {
113 StackTraceElement callerData = callerDataArray[0];
114 if (callerData != null) {
115 stmt.setString(7, callerData.getFileName());
116 stmt.setString(8, callerData.getClassName());
117 stmt.setString(9, callerData.getMethodName());
118 stmt.setString(10, Integer.toString(callerData.getLineNumber()));
119 }
120 }
121
122 Map<String, String> mergePropertyMaps(ILoggingEvent event) {
123 Map<String, String> mergedMap = new HashMap<String, String>();
124
125
126
127
128 Map<String, String> loggerContextMap = event.getLoggerContextVO().getPropertyMap();
129 Map<String, String> mdcMap = event.getMDCPropertyMap();
130 if (loggerContextMap != null) {
131 mergedMap.putAll(loggerContextMap);
132 }
133 if (mdcMap != null) {
134 mergedMap.putAll(mdcMap);
135 }
136
137 return mergedMap;
138 }
139
140 @Override
141 protected Method getGeneratedKeysMethod() {
142 return GET_GENERATED_KEYS_METHOD;
143 }
144
145 @Override
146 protected String getInsertSQL() {
147 return insertSQL;
148 }
149
150 protected void insertProperties(Map<String, String> mergedMap,
151 Connection connection, int eventId) throws SQLException {
152 Set propertiesKeys = mergedMap.keySet();
153 if (propertiesKeys.size() > 0) {
154 PreparedStatement insertPropertiesStatement = connection
155 .prepareStatement(insertPropertiesSQL);
156
157 for (Iterator i = propertiesKeys.iterator(); i.hasNext();) {
158 String key = (String) i.next();
159 String value = (String) mergedMap.get(key);
160
161 insertPropertiesStatement.setInt(1, eventId);
162 insertPropertiesStatement.setString(2, key);
163 insertPropertiesStatement.setString(3, value);
164
165 if (cnxSupportsBatchUpdates) {
166 insertPropertiesStatement.addBatch();
167 } else {
168 insertPropertiesStatement.execute();
169 }
170 }
171
172 if (cnxSupportsBatchUpdates) {
173 insertPropertiesStatement.executeBatch();
174 }
175
176 insertPropertiesStatement.close();
177 insertPropertiesStatement = null;
178 }
179 }
180
181 protected void insertThrowable(StackTraceElementProxy[] stepArray, Connection connection,
182 int eventId) throws SQLException {
183
184 PreparedStatement insertExceptionStatement = connection
185 .prepareStatement(insertExceptionSQL);
186
187 for (short i = 0; i < stepArray.length; i++) {
188 insertExceptionStatement.setInt(1, eventId);
189 insertExceptionStatement.setShort(2, i);
190 insertExceptionStatement.setString(3, stepArray[i].toString());
191 if (cnxSupportsBatchUpdates) {
192 insertExceptionStatement.addBatch();
193 } else {
194 insertExceptionStatement.execute();
195 }
196 }
197 if (cnxSupportsBatchUpdates) {
198 insertExceptionStatement.executeBatch();
199 }
200 insertExceptionStatement.close();
201 insertExceptionStatement = null;
202
203 }
204 }