001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.core.util; 015 016import java.io.PrintStream; 017import java.util.Iterator; 018import java.util.List; 019 020import ch.qos.logback.core.Context; 021import ch.qos.logback.core.CoreConstants; 022import ch.qos.logback.core.helpers.ThrowableToStringArray; 023import ch.qos.logback.core.status.*; 024 025import static ch.qos.logback.core.status.StatusUtil.filterStatusListByTimeThreshold; 026 027public class StatusPrinter { 028 029 private static PrintStream ps = System.out; 030 031 static CachingDateFormatter cachingDateFormat = new CachingDateFormatter("HH:mm:ss,SSS"); 032 033 public static void setPrintStream(PrintStream printStream) { 034 ps = printStream; 035 } 036 037 /** 038 * Print the contents of the context statuses, but only if they contain warnings 039 * or errors. 040 * 041 * @param context 042 */ 043 public static void printInCaseOfErrorsOrWarnings(Context context) { 044 printInCaseOfErrorsOrWarnings(context, 0); 045 } 046 047 /** 048 * Print the contents of the context status, but only if they contain warnings 049 * or errors occurring later than the threshold. 050 * 051 * @param context 052 */ 053 public static void printInCaseOfErrorsOrWarnings(Context context, long threshold) { 054 if (context == null) { 055 throw new IllegalArgumentException("Context argument cannot be null"); 056 } 057 058 StatusManager sm = context.getStatusManager(); 059 if (sm == null) { 060 ps.println("WARN: Context named \"" + context.getName() + "\" has no status manager"); 061 } else { 062 StatusUtil statusUtil = new StatusUtil(context); 063 if (statusUtil.getHighestLevel(threshold) >= ErrorStatus.WARN) { 064 print(sm, threshold); 065 } 066 } 067 } 068 069 /** 070 * Print the contents of the context statuses, but only if they contain errors. 071 * 072 * @param context 073 */ 074 public static void printIfErrorsOccured(Context context) { 075 if (context == null) { 076 throw new IllegalArgumentException("Context argument cannot be null"); 077 } 078 079 StatusManager sm = context.getStatusManager(); 080 if (sm == null) { 081 ps.println("WARN: Context named \"" + context.getName() + "\" has no status manager"); 082 } else { 083 StatusUtil statusUtil = new StatusUtil(context); 084 if (statusUtil.getHighestLevel(0) == ErrorStatus.ERROR) { 085 print(sm); 086 } 087 } 088 } 089 090 /** 091 * Print the contents of the context's status data. 092 * 093 * @param context 094 */ 095 public static void print(Context context) { 096 print(context, 0); 097 } 098 099 /** 100 * Print context's status data with a timestamp higher than the threshold. 101 * 102 * @param context 103 */ 104 public static void print(Context context, long threshold) { 105 if (context == null) { 106 throw new IllegalArgumentException("Context argument cannot be null"); 107 } 108 109 StatusManager sm = context.getStatusManager(); 110 if (sm == null) { 111 ps.println("WARN: Context named \"" + context.getName() + "\" has no status manager"); 112 } else { 113 print(sm, threshold); 114 } 115 } 116 117 public static void print(StatusManager sm) { 118 print(sm, 0); 119 } 120 121 public static void print(StatusManager sm, long threshold) { 122 StringBuilder sb = new StringBuilder(); 123 List<Status> filteredList = filterStatusListByTimeThreshold(sm.getCopyOfStatusList(), threshold); 124 buildStrFromStatusList(sb, filteredList); 125 ps.println(sb.toString()); 126 } 127 128 public static void print(List<Status> statusList) { 129 StringBuilder sb = new StringBuilder(); 130 buildStrFromStatusList(sb, statusList); 131 ps.println(sb.toString()); 132 } 133 134 private static void buildStrFromStatusList(StringBuilder sb, List<Status> statusList) { 135 if (statusList == null) 136 return; 137 for (Status s : statusList) { 138 buildStr(sb, "", s); 139 } 140 } 141 142 // private static void buildStrFromStatusManager(StringBuilder sb, StatusManager 143 // sm) { 144 // } 145 146 private static void appendThrowable(StringBuilder sb, Throwable t) { 147 String[] stringRep = ThrowableToStringArray.convert(t); 148 149 for (String s : stringRep) { 150 if (s.startsWith(CoreConstants.CAUSED_BY)) { 151 // nothing 152 } else if (Character.isDigit(s.charAt(0))) { 153 // if line resembles "48 common frames omitted" 154 sb.append("\t... "); 155 } else { 156 // most of the time. just add a tab+"at" 157 sb.append("\tat "); 158 } 159 sb.append(s).append(CoreConstants.LINE_SEPARATOR); 160 } 161 } 162 163 public static void buildStr(StringBuilder sb, String indentation, Status s) { 164 String prefix; 165 if (s.hasChildren()) { 166 prefix = indentation + "+ "; 167 } else { 168 prefix = indentation + "|-"; 169 } 170 171 if (cachingDateFormat != null) { 172 String dateStr = cachingDateFormat.format(s.getDate()); 173 sb.append(dateStr).append(" "); 174 } 175 sb.append(prefix).append(s).append(CoreConstants.LINE_SEPARATOR); 176 177 if (s.getThrowable() != null) { 178 appendThrowable(sb, s.getThrowable()); 179 } 180 if (s.hasChildren()) { 181 Iterator<Status> ite = s.iterator(); 182 while (ite.hasNext()) { 183 Status child = ite.next(); 184 buildStr(sb, indentation + " ", child); 185 } 186 } 187 } 188 189}