1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.classic.pattern;
15
16 import java.util.ArrayList;
17 import java.util.List;
18 import java.util.Map;
19
20 import ch.qos.logback.classic.spi.CallerData;
21 import ch.qos.logback.classic.spi.ILoggingEvent;
22 import ch.qos.logback.core.Context;
23 import ch.qos.logback.core.CoreConstants;
24 import ch.qos.logback.core.boolex.EvaluationException;
25 import ch.qos.logback.core.boolex.EventEvaluator;
26 import ch.qos.logback.core.status.ErrorStatus;
27
28
29
30
31
32
33 public class CallerDataConverter extends ClassicConverter {
34
35 int depth = 5;
36 List<EventEvaluator<ILoggingEvent>> evaluatorList = null;
37
38 final int MAX_ERROR_COUNT = 4;
39 int errorCount = 0;
40
41 @SuppressWarnings("unchecked")
42 public void start() {
43 String depthStr = getFirstOption();
44 if (depthStr == null) {
45 return;
46 }
47
48 try {
49 depth = Integer.parseInt(depthStr);
50 } catch (NumberFormatException nfe) {
51 addError("Failed to parse depth option [" + depthStr + "]", nfe);
52 }
53
54 final List optionList = getOptionList();
55
56 if (optionList != null && optionList.size() > 1) {
57 final int optionListSize = optionList.size();
58 for (int i = 1; i < optionListSize; i++) {
59 String evaluatorStr = (String) optionList.get(i);
60 Context context = getContext();
61 if (context != null) {
62 Map evaluatorMap = (Map) context
63 .getObject(CoreConstants.EVALUATOR_MAP);
64 EventEvaluator<ILoggingEvent> ee = (EventEvaluator<ILoggingEvent>) evaluatorMap
65 .get(evaluatorStr);
66 if (ee != null) {
67 addEvaluator(ee);
68 }
69 }
70 }
71 }
72 }
73
74 private void addEvaluator(EventEvaluator<ILoggingEvent> ee) {
75 if (evaluatorList == null) {
76 evaluatorList = new ArrayList<EventEvaluator<ILoggingEvent>>();
77 }
78 evaluatorList.add(ee);
79 }
80
81 public String convert(ILoggingEvent le) {
82 StringBuilder buf = new StringBuilder();
83
84 if (evaluatorList != null) {
85 boolean printCallerData = false;
86 for (int i = 0; i < evaluatorList.size(); i++) {
87 EventEvaluator<ILoggingEvent> ee = evaluatorList.get(i);
88 try {
89 if (ee.evaluate(le)) {
90 printCallerData = true;
91 break;
92 }
93 } catch (EvaluationException eex) {
94 errorCount++;
95 if (errorCount < MAX_ERROR_COUNT) {
96 addError("Exception thrown for evaluator named [" + ee.getName()
97 + "]", eex);
98 } else if (errorCount == MAX_ERROR_COUNT) {
99 ErrorStatus errorStatus = new ErrorStatus(
100 "Exception thrown for evaluator named [" + ee.getName() + "].",
101 this, eex);
102 errorStatus.add(new ErrorStatus(
103 "This was the last warning about this evaluator's errors."
104 + "We don't want the StatusManager to get flooded.", this));
105 addStatus(errorStatus);
106 }
107
108 }
109 }
110
111 if (!printCallerData) {
112 return CoreConstants.EMPTY_STRING;
113 }
114 }
115
116 StackTraceElement[] cda = le.getCallerData();
117 if (cda != null && cda.length > 0) {
118 int limit = depth < cda.length ? depth : cda.length;
119
120 for (int i = 0; i < limit; i++) {
121 buf.append("Caller+");
122 buf.append(i);
123 buf.append("\t at ");
124 buf.append(cda[i]);
125 buf.append(CoreConstants.LINE_SEPARATOR);
126 }
127 return buf.toString();
128 } else {
129 return CallerData.CALLER_DATA_NA;
130 }
131 }
132 }