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