1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package net.sf.aspect4log.aspect;
18
19 import net.sf.aspect4log.Log;
20 import net.sf.aspect4log.Log.Level;
21 import net.sf.aspect4log.conf.LogFormatConfiguration;
22 import net.sf.aspect4log.conf.LogFormatConfigurationUtils;
23 import net.sf.aspect4log.text.MessageBuilder;
24 import net.sf.aspect4log.text.MessageBuilderFactory;
25
26 import org.aspectj.lang.ProceedingJoinPoint;
27 import org.aspectj.lang.annotation.Around;
28 import org.aspectj.lang.annotation.Aspect;
29 import org.aspectj.lang.reflect.MethodSignature;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32 import org.slf4j.MDC;
33
34
35
36
37
38
39
40
41 @Aspect
42 public class LogAspect {
43
44 private static final LogAspect INSTANCE = new LogAspect();
45
46
47
48
49 public static LogAspect aspectOf() {
50 return INSTANCE;
51 }
52
53
54
55
56 private final static LogFormatConfiguration logFormatConfiguration = LogFormatConfigurationUtils.readConfiguration();
57
58 public static LogFormatConfiguration getLogFormatConfiguration() {
59 return logFormatConfiguration;
60 }
61
62
63
64
65
66 private static final ThreadLocal<Integer> thraedLocalIndent = new ThreadLocal<Integer>();
67
68
69 @Around("(execution(!@net.sf.aspect4log.Log *(@net.sf.aspect4log.Log *).*(..))|| execution(!@net.sf.aspect4log.Log *.new(..))) && @within(log)")
70 public Object logNotAnnotatedMethondsInAnnotatedClasses(ProceedingJoinPoint pjp, Log log) throws Throwable {
71 return log(pjp, log);
72 }
73
74
75 @Around("(execution(@net.sf.aspect4log.Log *.new(..)) || execution(@net.sf.aspect4log.Log * *.*(..)) ) && @annotation(log)")
76 public Object logAnnotatedMethods(ProceedingJoinPoint pjp, Log log) throws Throwable {
77 return log(pjp, log);
78 }
79
80 public static final Integer getThreadLocalIdent() {
81 return thraedLocalIndent.get() == null ? Integer.valueOf(0) : thraedLocalIndent.get();
82 }
83
84 private Object log(ProceedingJoinPoint pjp, Log log) throws Throwable {
85
86 MessageBuilderFactory factory = logFormatConfiguration.getMessageBuilderFactory();
87
88 boolean isConstractorCall = "constructor-execution".equals(pjp.getStaticPart().getKind());
89
90 String declaringClass = pjp.getSignature().getDeclaringTypeName();
91 String methodName = isConstractorCall ? pjp.getSignature().getDeclaringType().getSimpleName() : pjp.getSignature().getName();
92 Logger logger = LoggerFactory.getLogger(declaringClass);
93 try {
94 increaseIndent(log);
95 setMDC(log, pjp.getArgs());
96
97 MessageBuilder enterMessageBuilder = factory.createEnterMessageBuilder(methodName, log, pjp.getArgs());
98 log(logger, log.enterLevel(), enterMessageBuilder, null);
99 Object result = pjp.proceed();
100 Class<?> returnClass = null;
101 boolean returnsNothing = true;
102 if (isConstractorCall) {
103 returnsNothing = false;
104 } else {
105 returnClass = ((MethodSignature) pjp.getSignature()).getReturnType();
106 returnsNothing = Void.TYPE.equals(returnClass);
107 }
108 MessageBuilder messageBuilder = factory.createSuccessfulReturnMessageBuilder(methodName, log, pjp.getArgs(), returnsNothing, result);
109 log(logger, log.exitLevel(), messageBuilder, null);
110 return result;
111 } catch (Throwable e) {
112 Level level = Level.ERROR;
113 Throwable throwable = e;
114 String template = Log.Exceptions.EXCEPTION_DEFAULT_TEMPLATE;
115 exceptionExitSearchLoop: for (Log.Exceptions exceptions : log.on()) {
116 for (Class<? extends Throwable> t : exceptions.exceptions()) {
117 if (t.isAssignableFrom(e.getClass())) {
118 level = exceptions.level();
119 throwable = exceptions.stackTrace() ? e : null;
120 template = exceptions.template();
121 break exceptionExitSearchLoop;
122 }
123 }
124 }
125 MessageBuilder messageBuilder = factory.createExceptionReturnMessageBuilder(methodName, log, pjp.getArgs(), e, template);
126 log(logger, level, messageBuilder, throwable);
127 throw e;
128 } finally {
129 decreaseIndent(log);
130 removeMDC(log);
131 }
132 }
133
134 private void setMDC(Log log, Object[] args) {
135 if (!log.mdcKey().isEmpty()) {
136 MessageBuilder mdcMessageBuilder = logFormatConfiguration.getMessageBuilderFactory().createMdcTemplate(log, args);
137 MDC.put(log.mdcKey(), mdcMessageBuilder.build());
138 }
139 }
140
141 private void removeMDC(Log log) {
142 if (!log.mdcKey().isEmpty()) {
143 MDC.remove(log.mdcKey());
144 }
145 }
146
147 private void increaseIndent(Log log) {
148 if (log.indent()) {
149 if (thraedLocalIndent.get() == null) {
150 thraedLocalIndent.set(Integer.valueOf(0));
151 } else if (thraedLocalIndent.get() != null) {
152 thraedLocalIndent.set(Integer.valueOf(thraedLocalIndent.get() + 1));
153 }
154 }
155 }
156
157 private void decreaseIndent(Log log) {
158 if (log.indent()) {
159 if (thraedLocalIndent.get().equals(Integer.valueOf(0))) {
160 thraedLocalIndent.remove();
161 } else {
162 thraedLocalIndent.set(Integer.valueOf(thraedLocalIndent.get() - 1));
163 }
164 }
165 }
166
167 private void log(Logger logger, Level level, MessageBuilder messageBuilder, Throwable throable) {
168 switch (level) {
169 case TRACE:
170 if (logger.isTraceEnabled()) {
171 logger.trace(messageBuilder.build(), throable);
172 }
173 break;
174 case DEBUG:
175 if (logger.isDebugEnabled()) {
176 logger.debug(messageBuilder.build(), throable);
177 }
178 break;
179 case INFO:
180 if (logger.isInfoEnabled()) {
181 logger.info(messageBuilder.build(), throable);
182 }
183 break;
184 case WARN:
185 if (logger.isWarnEnabled()) {
186 logger.warn(messageBuilder.build(), throable);
187 }
188 break;
189 case ERROR:
190 if (logger.isErrorEnabled()) {
191 logger.error(messageBuilder.build(), throable);
192 }
193 break;
194 default:
195
196 }
197 }
198
199 }