1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache license, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the license for the specific language governing permissions and
15 * limitations under the license.
16 */
17 package org.apache.logging.log4j.core.appender.db.jpa;
18
19 import java.util.Map;
20 import javax.persistence.Basic;
21 import javax.persistence.Convert;
22 import javax.persistence.MappedSuperclass;
23 import javax.persistence.Transient;
24
25 import org.apache.logging.log4j.Level;
26 import org.apache.logging.log4j.Marker;
27 import org.apache.logging.log4j.ThreadContext;
28 import org.apache.logging.log4j.core.LogEvent;
29 import org.apache.logging.log4j.core.appender.db.jpa.converter.*;
30 import org.apache.logging.log4j.core.impl.ThrowableProxy;
31 import org.apache.logging.log4j.core.time.Instant;
32 import org.apache.logging.log4j.message.Message;
33
34 /**
35 * Users of the JPA appender may want to extend this class instead of {@link AbstractLogEventWrapperEntity}. This class
36 * implements all of the required mutator methods but does not implement a mutable entity ID property. In order to
37 * create an entity based on this class, you need only create two constructors matching this class's constructors,
38 * annotate the class {@link javax.persistence.Entity @Entity} and {@link javax.persistence.Table @Table}, and implement
39 * the fully mutable entity ID property annotated with {@link javax.persistence.Id @Id} and
40 * {@link javax.persistence.GeneratedValue @GeneratedValue} to tell the JPA provider how to calculate an ID for new
41 * events.<br>
42 * <br>
43 * The attributes in this entity use the default column names (which, according to the JPA spec, are the property names
44 * minus the "get" and "set" from the accessors/mutators). If you want to use different column names for one or more
45 * columns, override the necessary accessor methods defined in this class with the same annotations plus the
46 * {@link javax.persistence.Column @Column} annotation to specify the column name.<br>
47 * <br>
48 * The {@link #getContextMap()} and {@link #getContextStack()} attributes in this entity use the
49 * {@link ContextMapAttributeConverter} and {@link ContextStackAttributeConverter}, respectively. These convert the
50 * properties to simple strings that cannot be converted back to the properties. If you wish to instead convert these to
51 * a reversible JSON string, override these attributes with the same annotations but use the
52 * {@link org.apache.logging.log4j.core.appender.db.jpa.converter.ContextMapJsonAttributeConverter} and
53 * {@link org.apache.logging.log4j.core.appender.db.jpa.converter.ContextStackJsonAttributeConverter} instead.<br>
54 * <br>
55 * All other attributes in this entity use reversible converters that can be used for both persistence and retrieval. If
56 * there are any attributes you do not want persistent, you should override their accessor methods and annotate with
57 * {@link javax.persistence.Transient @Transient}.
58 *
59 * @see AbstractLogEventWrapperEntity
60 */
61 @MappedSuperclass
62 public abstract class BasicLogEventEntity extends AbstractLogEventWrapperEntity {
63 private static final long serialVersionUID = 1L;
64
65 /**
66 * Instantiates this base class. All concrete implementations must have a constructor matching this constructor's
67 * signature. The no-argument constructor is required for a standards-compliant JPA provider to accept this as an
68 * entity.
69 */
70 public BasicLogEventEntity() {
71 super();
72 }
73
74 /**
75 * Instantiates this base class. All concrete implementations must have a constructor matching this constructor's
76 * signature. This constructor is used for wrapping this entity around a logged event.
77 *
78 * @param wrappedEvent The underlying event from which information is obtained.
79 */
80 public BasicLogEventEntity(final LogEvent wrappedEvent) {
81 super(wrappedEvent);
82 }
83
84 /**
85 * Gets the level. Annotated with {@code @Basic} and {@code @Enumerated(EnumType.STRING)}.
86 *
87 * @return the level.
88 */
89 @Override
90 @Convert(converter = LevelAttributeConverter.class)
91 public Level getLevel() {
92 return this.getWrappedEvent().getLevel();
93 }
94
95 /**
96 * Gets the logger name. Annotated with {@code @Basic}.
97 *
98 * @return the logger name.
99 */
100 @Override
101 @Basic
102 public String getLoggerName() {
103 return this.getWrappedEvent().getLoggerName();
104 }
105
106 /**
107 * Gets the source location information. Annotated with
108 * {@code @Convert(converter = StackTraceElementAttributeConverter.class)}.
109 *
110 * @return the source location information.
111 * @see StackTraceElementAttributeConverter
112 */
113 @Override
114 @Convert(converter = StackTraceElementAttributeConverter.class)
115 public StackTraceElement getSource() {
116 return this.getWrappedEvent().getSource();
117 }
118
119 /**
120 * Gets the message. Annotated with {@code @Convert(converter = MessageAttributeConverter.class)}.
121 *
122 * @return the message.
123 * @see MessageAttributeConverter
124 */
125 @Override
126 @Convert(converter = MessageAttributeConverter.class)
127 public Message getMessage() {
128 return this.getWrappedEvent().getMessage();
129 }
130
131 /**
132 * Gets the marker. Annotated with {@code @Convert(converter = MarkerAttributeConverter.class)}.
133 *
134 * @return the marker.
135 * @see MarkerAttributeConverter
136 */
137 @Override
138 @Convert(converter = MarkerAttributeConverter.class)
139 public Marker getMarker() {
140 return this.getWrappedEvent().getMarker();
141 }
142
143 /**
144 * Gets the thread ID. Annotated with {@code @Basic}.
145 *
146 * @return the thread ID.
147 */
148 @Override
149 @Basic
150 public long getThreadId() {
151 return this.getWrappedEvent().getThreadId();
152 }
153
154 /**
155 * Gets the thread name. Annotated with {@code @Basic}.
156 *
157 * @return the thread name.
158 */
159 @Override
160 @Basic
161 public int getThreadPriority() {
162 return this.getWrappedEvent().getThreadPriority();
163 }
164
165 /**
166 * Gets the thread name. Annotated with {@code @Basic}.
167 *
168 * @return the thread name.
169 */
170 @Override
171 @Basic
172 public String getThreadName() {
173 return this.getWrappedEvent().getThreadName();
174 }
175
176 /**
177 * Gets the number of milliseconds since JVM launch. Annotated with {@code @Basic}.
178 *
179 * @return the number of milliseconds since JVM launch.
180 */
181 @Override
182 @Basic
183 public long getTimeMillis() {
184 return this.getWrappedEvent().getTimeMillis();
185 }
186
187 @Override
188 @Convert(converter = InstantAttributeConverter.class)
189 public Instant getInstant() {
190 return this.getWrappedEvent().getInstant();
191 }
192
193 /**
194 * Returns the value of the running Java Virtual Machine's high-resolution time source when this event was created,
195 * or a dummy value if it is known that this value will not be used downstream.
196 *
197 * @return the JVM nano time
198 */
199 @Override
200 @Basic
201 public long getNanoTime() {
202 return this.getWrappedEvent().getNanoTime();
203 }
204
205 /**
206 * Gets the exception logged. Annotated with {@code @Convert(converter = ThrowableAttributeConverter.class)}.
207 *
208 * @return the exception logged.
209 * @see ThrowableAttributeConverter
210 */
211 @Override
212 @Convert(converter = ThrowableAttributeConverter.class)
213 public Throwable getThrown() {
214 return this.getWrappedEvent().getThrown();
215 }
216
217 /**
218 * Gets the exception logged. Annotated with {@code @Convert(converter = ThrowableAttributeConverter.class)}.
219 *
220 * @return the exception logged.
221 * @see ThrowableAttributeConverter
222 */
223 @Override
224 @Transient
225 public ThrowableProxy getThrownProxy() {
226 return this.getWrappedEvent().getThrownProxy();
227 }
228
229 /**
230 * Gets the context map. Annotated with {@code @Convert(converter = ContextMapAttributeConverter.class)}.
231 *
232 * @return the context map.
233 * @see ContextMapAttributeConverter
234 * @see org.apache.logging.log4j.core.appender.db.jpa.converter.ContextMapJsonAttributeConverter
235 */
236 @SuppressWarnings("deprecation")
237 @Override
238 @Convert(converter = ContextMapAttributeConverter.class)
239 public Map<String, String> getContextMap() {
240 return this.getWrappedEvent().getContextMap();
241 }
242
243 /**
244 * Gets the context stack. Annotated with {@code @Convert(converter = ContextStackAttributeConverter.class)}.
245 *
246 * @return the context stack.
247 * @see ContextStackAttributeConverter
248 * @see org.apache.logging.log4j.core.appender.db.jpa.converter.ContextStackJsonAttributeConverter
249 */
250 @Override
251 @Convert(converter = ContextStackAttributeConverter.class)
252 public ThreadContext.ContextStack getContextStack() {
253 return this.getWrappedEvent().getContextStack();
254 }
255
256 /**
257 * Gets the fully qualified class name of the caller of the logger API. Annotated with {@code @Basic}.
258 *
259 * @return the fully qualified class name of the caller of the logger API.
260 */
261 @Override
262 @Basic
263 public String getLoggerFqcn() {
264 return this.getWrappedEvent().getLoggerFqcn();
265 }
266 }