1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.appender.db.nosql;
18
19 import java.util.Map;
20
21 import org.apache.logging.log4j.Marker;
22 import org.apache.logging.log4j.ThreadContext;
23 import org.apache.logging.log4j.core.LogEvent;
24 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
25 import org.apache.logging.log4j.core.appender.ManagerFactory;
26 import org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager;
27
28
29
30
31
32
33 public final class NoSQLDatabaseManager<W> extends AbstractDatabaseManager {
34 private static final NoSQLDatabaseManagerFactory FACTORY = new NoSQLDatabaseManagerFactory();
35
36 private final NoSQLProvider<NoSQLConnection<W, ? extends NoSQLObject<W>>> provider;
37
38 private NoSQLConnection<W, ? extends NoSQLObject<W>> connection;
39
40 private NoSQLDatabaseManager(final String name, final int bufferSize,
41 final NoSQLProvider<NoSQLConnection<W, ? extends NoSQLObject<W>>> provider) {
42 super(name, bufferSize);
43 this.provider = provider;
44 }
45
46 @Override
47 protected void startupInternal() {
48
49 }
50
51 @Override
52 protected void shutdownInternal() {
53 if (this.connection != null) {
54 this.commitAndClose();
55 }
56 }
57
58 @Override
59 protected void connectAndStart() {
60 try {
61 this.connection = this.provider.getConnection();
62 } catch (Exception e) {
63 throw new AppenderLoggingException("Failed to get connection from NoSQL connection provider.", e);
64 }
65 }
66
67 @Override
68 protected void writeInternal(final LogEvent event) {
69 if (!this.isRunning() || this.connection == null || this.connection.isClosed()) {
70 throw new AppenderLoggingException(
71 "Cannot write logging event; NoSQL manager not connected to the database.");
72 }
73
74 final NoSQLObject<W> entity = this.connection.createObject();
75 entity.set("level", event.getLevel());
76 entity.set("loggerName", event.getLoggerName());
77 entity.set("message", event.getMessage() == null ? null : event.getMessage().getFormattedMessage());
78
79 final StackTraceElement source = event.getSource();
80 if (source == null) {
81 entity.set("source", (Object) null);
82 } else {
83 entity.set("source", this.convertStackTraceElement(source));
84 }
85
86 Marker marker = event.getMarker();
87 if (marker == null) {
88 entity.set("marker", (Object) null);
89 } else {
90 final NoSQLObject<W> originalMarkerEntity = this.connection.createObject();
91 NoSQLObject<W> markerEntity = originalMarkerEntity;
92 markerEntity.set("name", marker.getName());
93 while (marker.getParent() != null) {
94 marker = marker.getParent();
95 final NoSQLObject<W> parentMarkerEntity = this.connection.createObject();
96 parentMarkerEntity.set("name", marker.getName());
97 markerEntity.set("parent", parentMarkerEntity);
98 markerEntity = parentMarkerEntity;
99 }
100 entity.set("marker", originalMarkerEntity);
101 }
102
103 entity.set("threadName", event.getThreadName());
104 entity.set("millis", event.getMillis());
105 entity.set("date", new java.util.Date(event.getMillis()));
106
107 @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
108 Throwable thrown = event.getThrown();
109 if (thrown == null) {
110 entity.set("thrown", (Object) null);
111 } else {
112 final NoSQLObject<W> originalExceptionEntity = this.connection.createObject();
113 NoSQLObject<W> exceptionEntity = originalExceptionEntity;
114 exceptionEntity.set("type", thrown.getClass().getName());
115 exceptionEntity.set("message", thrown.getMessage());
116 exceptionEntity.set("stackTrace", this.convertStackTrace(thrown.getStackTrace()));
117 while (thrown.getCause() != null) {
118 thrown = thrown.getCause();
119 final NoSQLObject<W> causingExceptionEntity = this.connection.createObject();
120 causingExceptionEntity.set("type", thrown.getClass().getName());
121 causingExceptionEntity.set("message", thrown.getMessage());
122 causingExceptionEntity.set("stackTrace", this.convertStackTrace(thrown.getStackTrace()));
123 exceptionEntity.set("cause", causingExceptionEntity);
124 exceptionEntity = causingExceptionEntity;
125 }
126
127 entity.set("thrown", originalExceptionEntity);
128 }
129
130 final Map<String, String> contextMap = event.getContextMap();
131 if (contextMap == null) {
132 entity.set("contextMap", (Object) null);
133 } else {
134 final NoSQLObject<W> contextMapEntity = this.connection.createObject();
135 for (final Map.Entry<String, String> entry : contextMap.entrySet()) {
136 contextMapEntity.set(entry.getKey(), entry.getValue());
137 }
138 entity.set("contextMap", contextMapEntity);
139 }
140
141 final ThreadContext.ContextStack contextStack = event.getContextStack();
142 if (contextStack == null) {
143 entity.set("contextStack", (Object) null);
144 } else {
145 entity.set("contextStack", contextStack.asList().toArray());
146 }
147
148 this.connection.insertObject(entity);
149 }
150
151 @Override
152 protected void commitAndClose() {
153 try {
154 if (this.connection != null && !this.connection.isClosed()) {
155 this.connection.close();
156 }
157 } catch (Exception e) {
158 throw new AppenderLoggingException("Failed to commit and close NoSQL connection in manager.", e);
159 }
160 }
161
162 private NoSQLObject<W>[] convertStackTrace(final StackTraceElement[] stackTrace) {
163 final NoSQLObject<W>[] stackTraceEntities = this.connection.createList(stackTrace.length);
164 for (int i = 0; i < stackTrace.length; i++) {
165 stackTraceEntities[i] = this.convertStackTraceElement(stackTrace[i]);
166 }
167 return stackTraceEntities;
168 }
169
170 private NoSQLObject<W> convertStackTraceElement(final StackTraceElement element) {
171 final NoSQLObject<W> elementEntity = this.connection.createObject();
172 elementEntity.set("className", element.getClassName());
173 elementEntity.set("methodName", element.getMethodName());
174 elementEntity.set("fileName", element.getFileName());
175 elementEntity.set("lineNumber", element.getLineNumber());
176 return elementEntity;
177 }
178
179
180
181
182
183
184
185
186
187 public static NoSQLDatabaseManager<?> getNoSQLDatabaseManager(final String name, final int bufferSize,
188 final NoSQLProvider<?> provider) {
189 return AbstractDatabaseManager.getManager(name, new FactoryData(bufferSize, provider), FACTORY);
190 }
191
192
193
194
195 private static final class FactoryData extends AbstractDatabaseManager.AbstractFactoryData {
196 private final NoSQLProvider<?> provider;
197
198 protected FactoryData(final int bufferSize, final NoSQLProvider<?> provider) {
199 super(bufferSize);
200 this.provider = provider;
201 }
202 }
203
204
205
206
207 private static final class NoSQLDatabaseManagerFactory implements
208 ManagerFactory<NoSQLDatabaseManager<?>, FactoryData> {
209 @Override
210 @SuppressWarnings("unchecked")
211 public NoSQLDatabaseManager<?> createManager(final String name, final FactoryData data) {
212 return new NoSQLDatabaseManager(name, data.getBufferSize(), data.provider);
213 }
214 }
215 }