1. 场景
打印日志的时候,需要获取是在哪个地方被调用了,把调用点的信息一并打印出来。
2. 获取自身被调用点的方法
可以通过获取线程的调用栈,遍历后找到调用点。
3. 代码实现
import java.lang.management.ManagementFactory;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class Log {
private static final String INFO = "INFO";
private static final String WARN = "WARN";
private static final String ERROR = "ERROR";
private static final String DEBUG = "DEBUG";
private static final String EMPTY = "";
private static final String DEFAULT = "\033[0m%s\033[0m";
private static final String FONT_GREEN = "\033[32m%s\033[0m";
private static final String FONT_YELLOW = "\033[33m%s\033[0m";
private static final String FONT_RED = "\033[31m%s\033[0m";
private static final String FONT_MAGENTA = "\033[35m%s\033[0m";
private static final String FONT_CYAN = "\033[36m%s\033[0m";
private static final String SELF_CLASS_NAME = Log.class.getName();
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
private static final ZoneId ZONE_ID = ZoneId.systemDefault();
private static String pid;
static {
String name = ManagementFactory.getRuntimeMXBean().getName();
pid = createColorfulStr(name.split("@")[0], FONT_MAGENTA);
}
private static StackTraceElement findCallPoint() {
Thread currentThread = Thread.currentThread();
StackTraceElement[] stackTraces = currentThread.getStackTrace();
boolean isFrontOfLogClass = true;
for (StackTraceElement stackTrace : stackTraces) {
if (SELF_CLASS_NAME.equals(stackTrace.getClassName())) {
isFrontOfLogClass = false;
continue;
}
if (isFrontOfLogClass) {
continue;
}
return stackTrace;
}
return null;
}
private static String getMsgPrefix(String msgType) {
StackTraceElement callPoint = findCallPoint();
if (callPoint == null) {
return "-";
}
String timeStamp = LocalDateTime.now().atZone(ZONE_ID).format(DATE_TIME_FORMATTER);
String threadName = Thread.currentThread().getName();
String className = callPoint.getClassName();
String fileName = callPoint.getFileName();
int lineNumber = callPoint.getLineNumber();
String methodName = callPoint.getMethodName();
StringBuffer sb = new StringBuffer();
sb.append(timeStamp)
.append(" ")
.append(createColorfulStr(msgType))
.append(" ")
.append(pid)
.append(" --- [")
.append(threadName)
.append("] at ")
.append(createColorfulStr(String.format("%s.%s(%s:%d) ", className, methodName, fileName, lineNumber), FONT_CYAN));
return sb.toString();
}
private static String createColorfulStr(String str) {
return createColorfulStr(str, null);
}
private static String createColorfulStr(String str, String color) {
if (color == null) {
color = DEFAULT;
}
if (str == null) {
str = EMPTY;
}
switch (str) {
case DEBUG:
return String.format(FONT_GREEN, DEBUG);
case INFO:
return String.format(FONT_GREEN, " " + INFO);
case WARN:
return String.format(FONT_YELLOW, " " + WARN);
case ERROR:
return String.format(FONT_RED, ERROR);
}
return String.format(color, str);
}
public static void info(String msg) {
System.out.println(getMsgPrefix(INFO) + msg);
}
public static void warn(String msg) {
System.out.println(getMsgPrefix(WARN) + msg);
}
public static void error(String msg) {
System.out.println(getMsgPrefix(ERROR) + msg);
}
public static void debug(String msg) {
System.out.println(getMsgPrefix(DEBUG) + msg);
}
}
4. 测试
测试代码:
public class Test {
public static void main(String[] args) {
Log.info("=====testLog main=====");
testLog();
}
private static void testLog() {
Log.info("=====testLog info=====");
Log.warn("=====testLog warn=====");
Log.error("=====testLog error=====");
Log.debug("=====testLog debug=====");
}
}
控制台输出:
2025-04-22T00:49:28.443+08:00 INFO 26888 --- [main] at com.example.study.controller.Test.main(Test.java:5) =====testLog main=====
2025-04-22T00:49:28.449+08:00 INFO 26888 --- [main] at com.example.study.controller.Test.testLog(Test.java:10) =====testLog info=====
2025-04-22T00:49:28.449+08:00 WARN 26888 --- [main] at com.example.study.controller.Test.testLog(Test.java:11) =====testLog warn=====
2025-04-22T00:49:28.449+08:00 ERROR 26888 --- [main] at com.example.study.controller.Test.testLog(Test.java:12) =====testLog error=====
2025-04-22T00:49:28.449+08:00 DEBUG 26888 --- [main] at com.example.study.controller.Test.testLog(Test.java:13) =====testLog debug=====