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