1
18 package net.bull.javamelody.internal.common;
19
20 import java.lang.reflect.Method;
21 import java.util.ArrayList;
22 import java.util.Date;
23 import java.util.LinkedList;
24 import java.util.List;
25
26 import javax.servlet.http.HttpServletRequest;
27
28 import net.bull.javamelody.JavaMelodyLogger;
29 import net.bull.javamelody.Parameter;
30
31
35 public final class LOG {
36 public static final boolean LOG4J_ENABLED = isLog4jEnabled();
37 public static final boolean LOG4J2_ENABLED = isLog4j2Enabled();
38 public static final boolean LOGBACK_ENABLED = isLogbackEnabled();
39
40 public static final int MAX_DEBUGGING_LOGS_COUNT = 50;
41
42 private static final JavaMelodyLogger JAVA_MELODY_LOGGER = getJavaMelodyLogger();
43
44 private static final LinkedList<String> DEBUGGING_LOGS = new LinkedList<>();
45
46 private LOG() {
47 super();
48 }
49
50 public static void logHttpRequest(HttpServletRequest httpRequest, String requestName,
51 long duration, boolean systemError, int responseStatus, long responseSize,
52 String filterName) {
53
54
55 JAVA_MELODY_LOGGER.logHttpRequest(httpRequest, requestName, duration, systemError,
56 responseStatus, responseSize, filterName);
57 }
58
59 public static String buildLogMessage(HttpServletRequest httpRequest, long duration,
60 boolean systemError, int responseStatus, long responseSize) {
61 final StringBuilder msg = new StringBuilder();
62 msg.append("remoteAddr = ").append(httpRequest.getRemoteAddr());
63 final String forwardedFor = httpRequest.getHeader("X-Forwarded-For");
64 if (forwardedFor != null) {
65 msg.append(", forwardedFor = ").append(forwardedFor);
66 }
67 msg.append(", request = ").append(
68 httpRequest.getRequestURI().substring(httpRequest.getContextPath().length()));
69 if (httpRequest.getQueryString() != null) {
70 msg.append('?').append(httpRequest.getQueryString());
71 }
72 msg.append(' ').append(httpRequest.getMethod());
73 msg.append(": ").append(duration).append(" ms");
74 if (systemError) {
75 msg.append(", error ").append(responseStatus);
76 }
77 msg.append(", ").append(responseSize / 1024L).append(" Kb");
78 return msg.toString();
79 }
80
81 public static void debug(String msg) {
82 JAVA_MELODY_LOGGER.debug(msg);
83 addDebuggingLog("DEBUG", msg);
84 }
85
86 public static void debug(String msg, Throwable throwable) {
87 JAVA_MELODY_LOGGER.debug(msg, throwable);
88 addDebuggingLog("DEBUG", msg);
89 }
90
91 public static void info(String msg, Throwable throwable) {
92 JAVA_MELODY_LOGGER.info(msg, throwable);
93 addDebuggingLog("INFO", msg);
94 }
95
96 public static void info(String msg) {
97 JAVA_MELODY_LOGGER.info(msg);
98 addDebuggingLog("INFO", msg);
99 }
100
101 public static void warn(String msg, Throwable throwable) {
102 try {
103 JAVA_MELODY_LOGGER.warn(msg, throwable);
104 addDebuggingLog("WARN", msg);
105 } catch (final Throwable t) {
106
107 t.printStackTrace(System.err);
108 }
109 }
110
111 public static List<String> getDebuggingLogs() {
112 synchronized (DEBUGGING_LOGS) {
113 return new ArrayList<>(DEBUGGING_LOGS);
114 }
115 }
116
117 private static void addDebuggingLog(String level, String msg) {
118 synchronized (DEBUGGING_LOGS) {
119 DEBUGGING_LOGS.addLast(new Date().toString() + '\t' + level + '\t' + msg);
120 while (DEBUGGING_LOGS.size() > MAX_DEBUGGING_LOGS_COUNT) {
121 DEBUGGING_LOGS.removeFirst();
122 }
123 }
124 }
125
126 private static boolean isLog4jEnabled() {
127 try {
128 Class.forName("org.apache.log4j.Logger");
129
130
131 Class.forName("org.apache.log4j.AppenderSkeleton");
132
133 Class.forName("org.apache.log4j.spi.LocationInfo");
134 return true;
135 } catch (final Throwable e) {
136
137
138 return false;
139 }
140 }
141
142 private static boolean isLog4j2Enabled() {
143 try {
144 Class.forName("org.apache.logging.log4j.Logger");
145
146 Class.forName("org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder");
147 return true;
148 } catch (final Throwable e) {
149 return false;
150 }
151 }
152
153 private static boolean isLogbackEnabled() {
154 try {
155 Class.forName("ch.qos.logback.classic.Logger");
156 final Class<?> loggerFactoryClass = Class.forName("org.slf4j.LoggerFactory");
157 final Method method = loggerFactoryClass.getMethod("getILoggerFactory");
158 final Object obj = method.invoke(null);
159
160
161 return Class.forName("ch.qos.logback.classic.LoggerContext")
162 .isAssignableFrom(obj.getClass());
163 } catch (final Throwable e) {
164 return false;
165 }
166 }
167
168 private static JavaMelodyLogger getJavaMelodyLogger() {
169
170 final String loggerClass = Parameter.LOGGER_CLASS.getValue();
171 if (loggerClass != null) {
172 final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
173 try {
174 return JavaMelodyLogger.class.cast(tccl.loadClass(loggerClass).newInstance());
175 } catch (final Exception e) {
176 throw new IllegalStateException(e);
177 }
178 }
179
180
181 if (LOGBACK_ENABLED) {
182 return new LogbackLogger();
183 } else if (LOG4J2_ENABLED) {
184 return new Log4J2Logger();
185 } else if (LOG4J_ENABLED) {
186 return new Log4JLogger();
187 } else {
188 return new JavaLogger();
189 }
190 }
191 }
192