View Javadoc

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