View Javadoc
1   /*
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2024, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  
15  package ch.qos.logback.core.util;
16  
17  import ch.qos.logback.core.Context;
18  import ch.qos.logback.core.CoreConstants;
19  import ch.qos.logback.core.helpers.ThrowableToStringArray;
20  import ch.qos.logback.core.status.ErrorStatus;
21  import ch.qos.logback.core.status.Status;
22  import ch.qos.logback.core.status.StatusManager;
23  import ch.qos.logback.core.status.StatusUtil;
24  
25  import java.io.PrintStream;
26  import java.util.Iterator;
27  import java.util.List;
28  
29  import static ch.qos.logback.core.status.StatusUtil.filterStatusListByTimeThreshold;
30  
31  /**
32   *
33   * Same as StatusPrinter but with instance methods instead of static.
34   *
35   * @since 1.5.4
36   */
37  public class StatusPrinter2 {
38  
39  
40      private PrintStream ps = System.out;
41  
42      static CachingDateFormatter cachingDateFormat = new CachingDateFormatter("HH:mm:ss,SSS");
43  
44      public void setPrintStream(PrintStream printStream) {
45          ps = printStream;
46      }
47  
48      /**
49       * Print the contents of the context statuses, but only if they contain warnings
50       * or errors.
51       *
52       * @param context a context to print
53       */
54      public void printInCaseOfErrorsOrWarnings(Context context) {
55          printInCaseOfErrorsOrWarnings(context, 0);
56      }
57  
58      /**
59       * Print the contents of the context status, but only if they contain warnings
60       * or errors occurring later than the threshold.
61       *
62       * @param context a context to print
63       * @param threshold filter events later than the threshold
64       */
65      public void printInCaseOfErrorsOrWarnings(Context context, long threshold) {
66          if (context == null) {
67              throw new IllegalArgumentException("Context argument cannot be null");
68          }
69  
70          StatusManager sm = context.getStatusManager();
71          if (sm == null) {
72              ps.println("WARN: Context named \"" + context.getName() + "\" has no status manager");
73          } else {
74              StatusUtil statusUtil = new StatusUtil(context);
75              if (statusUtil.getHighestLevel(threshold) >= ErrorStatus.WARN) {
76                  print(sm, threshold);
77              }
78          }
79      }
80  
81      /**
82       * Print the contents of the context statuses, but only if they contain errors.
83       *
84       * @param context  a context to print
85       */
86      public void printIfErrorsOccured(Context context) {
87          if (context == null) {
88              throw new IllegalArgumentException("Context argument cannot be null");
89          }
90  
91          StatusManager sm = context.getStatusManager();
92          if (sm == null) {
93              ps.println("WARN: Context named \"" + context.getName() + "\" has no status manager");
94          } else {
95              StatusUtil statusUtil = new StatusUtil(context);
96              if (statusUtil.getHighestLevel(0) == ErrorStatus.ERROR) {
97                  print(sm);
98              }
99          }
100     }
101 
102     /**
103      * Print the contents of the context's status data.
104      *
105      * @param context a context to print
106      */
107     public void print(Context context) {
108         print(context, 0);
109     }
110 
111     /**
112      * Print context's status data with a timestamp higher than the threshold.
113      *
114      * @param context a context to print
115      */
116     public  void print(Context context, long threshold) {
117         if (context == null) {
118             throw new IllegalArgumentException("Context argument cannot be null");
119         }
120 
121         StatusManager sm = context.getStatusManager();
122         if (sm == null) {
123             ps.println("WARN: Context named \"" + context.getName() + "\" has no status manager");
124         } else {
125             print(sm, threshold);
126         }
127     }
128 
129     public void print(StatusManager sm) {
130         print(sm, 0);
131     }
132 
133     public  void print(StatusManager sm, long threshold) {
134         StringBuilder sb = new StringBuilder();
135         List<Status> filteredList = filterStatusListByTimeThreshold(sm.getCopyOfStatusList(), threshold);
136         buildStrFromStatusList(sb, filteredList);
137         ps.println(sb.toString());
138     }
139 
140     public void print(List<Status> statusList) {
141         StringBuilder sb = new StringBuilder();
142         buildStrFromStatusList(sb, statusList);
143         ps.println(sb.toString());
144     }
145 
146     private void buildStrFromStatusList(StringBuilder sb, List<Status> statusList) {
147         if (statusList == null)
148             return;
149         for (Status s : statusList) {
150             buildStr(sb, "", s);
151         }
152     }
153 
154     private void appendThrowable(StringBuilder sb, Throwable t) {
155         String[] stringRep = ThrowableToStringArray.convert(t);
156 
157         for (String s : stringRep) {
158             if (s.startsWith(CoreConstants.CAUSED_BY)) {
159                 // nothing
160             } else if (Character.isDigit(s.charAt(0))) {
161                 // if line resembles "48 common frames omitted"
162                 sb.append("\t... ");
163             } else {
164                 // most of the time. just add a tab+"at"
165                 sb.append("\tat ");
166             }
167             sb.append(s).append(CoreConstants.LINE_SEPARATOR);
168         }
169     }
170 
171     public void buildStr(StringBuilder sb, String indentation, Status s) {
172         String prefix;
173         if (s.hasChildren()) {
174             prefix = indentation + "+ ";
175         } else {
176             prefix = indentation + "|-";
177         }
178 
179         if (cachingDateFormat != null) {
180             String dateStr = cachingDateFormat.format(s.getTimestamp());
181             sb.append(dateStr).append(" ");
182         }
183         sb.append(prefix).append(s).append(CoreConstants.LINE_SEPARATOR);
184 
185         if (s.getThrowable() != null) {
186             appendThrowable(sb, s.getThrowable());
187         }
188         if (s.hasChildren()) {
189             Iterator<Status> ite = s.iterator();
190             while (ite.hasNext()) {
191                 Status child = ite.next();
192                 buildStr(sb, indentation + "  ", child);
193             }
194         }
195     }
196 }