Skip to content

Add a configurable out field to AnsiLog, similar to the existing LEVEL field #3126

@junjiewwang

Description

@junjiewwang
  • 我已经在 issues 里搜索,没有重复的issue。

环境信息

When Arthas is embedded in other applications (e.g., OpenTelemetry Java Agent,
Spring Boot applications), AnsiLog outputs directly to System.out, which:

  1. Pollutes the host application's stdout
  2. Interferes with log collection systems
  3. Cannot be redirected to a separate file

The official AgentBootstrap already uses a configurable PrintStream pattern,
but AnsiLog still hardcodes System.out.

Solution

Add a configurable out field to AnsiLog, similar to the existing LEVEL field:

  • Default: System.out (backward compatible)
  • API: AnsiLog.out(PrintStream) / AnsiLog.out()
  • Thread-safe with volatile

期望的结果

diff --git a/common/src/main/java/com/taobao/arthas/common/AnsiLog.java b/common/src/main/java/com/taobao/arthas/common/AnsiLog.java
index xxx..yyy 100644
--- a/common/src/main/java/com/taobao/arthas/common/AnsiLog.java
+++ b/common/src/main/java/com/taobao/arthas/common/AnsiLog.java
@@ -1,5 +1,6 @@
 package com.taobao.arthas.common;
 
+import java.io.PrintStream;
 import java.util.logging.Level;
 import java.util.regex.Matcher;
 
@@ -20,6 +21,12 @@ public abstract class AnsiLog {
 
     static boolean enableColor;
 
+    /**
+     * Output stream for log messages, defaults to System.out.
+     * Can be configured via {@link #out(PrintStream)} for embedded scenarios.
+     */
+    private static volatile PrintStream out = System.out;
+
     public static java.util.logging.Level LEVEL = java.util.logging.Level.CONFIG;
 
     private static final String RESET = "\033[0m";
@@ -76,6 +83,28 @@ public abstract class AnsiLog {
         return enableColor;
     }
 
+    /**
+     * Set the output stream for log messages.
+     *
+     * @param printStream the output stream, null to use System.out
+     * @return the previous output stream
+     */
+    public static PrintStream out(PrintStream printStream) {
+        PrintStream old = out;
+        out = (printStream != null) ? printStream : System.out;
+        return old;
+    }
+
+    /**
+     * Get the current output stream.
+     *
+     * @return the current output stream
+     */
+    public static PrintStream out() {
+        return out;
+    }
+
     /**
      * set logger Level
      *
@@ -144,9 +173,9 @@ public abstract class AnsiLog {
     public static void trace(String msg) {
         if (canLog(Level.FINEST)) {
             if (enableColor) {
-                System.out.println(TRACE_COLOR_PREFIX + msg);
+                out.println(TRACE_COLOR_PREFIX + msg);
             } else {
-                System.out.println(TRACE_PREFIX + msg);
+                out.println(TRACE_PREFIX + msg);
             }
         }
     }
@@ -159,7 +188,7 @@ public abstract class AnsiLog {
 
     public static void trace(Throwable t) {
         if (canLog(Level.FINEST)) {
-            t.printStackTrace(System.out);
+            t.printStackTrace(out);
         }
     }
 
@@ -167,9 +196,9 @@ public abstract class AnsiLog {
     public static void debug(String msg) {
         if (canLog(Level.FINER)) {
             if (enableColor) {
-                System.out.println(DEBUG_COLOR_PREFIX + msg);
+                out.println(DEBUG_COLOR_PREFIX + msg);
             } else {
-                System.out.println(DEBUG_PREFIX + msg);
+                out.println(DEBUG_PREFIX + msg);
             }
         }
     }
@@ -182,7 +211,7 @@ public abstract class AnsiLog {
 
     public static void debug(Throwable t) {
         if (canLog(Level.FINER)) {
-            t.printStackTrace(System.out);
+            t.printStackTrace(out);
         }
     }
 
@@ -190,9 +219,9 @@ public abstract class AnsiLog {
     public static void info(String msg) {
         if (canLog(Level.CONFIG)) {
             if (enableColor) {
-                System.out.println(INFO_COLOR_PREFIX + msg);
+                out.println(INFO_COLOR_PREFIX + msg);
             } else {
-                System.out.println(INFO_PREFIX + msg);
+                out.println(INFO_PREFIX + msg);
             }
         }
     }
@@ -205,7 +234,7 @@ public abstract class AnsiLog {
 
     public static void info(Throwable t) {
         if (canLog(Level.CONFIG)) {
-            t.printStackTrace(System.out);
+            t.printStackTrace(out);
         }
     }
 
@@ -213,9 +242,9 @@ public abstract class AnsiLog {
     public static void warn(String msg) {
         if (canLog(Level.WARNING)) {
             if (enableColor) {
-                System.out.println(WARN_COLOR_PREFIX + msg);
+                out.println(WARN_COLOR_PREFIX + msg);
             } else {
-                System.out.println(WARN_PREFIX + msg);
+                out.println(WARN_PREFIX + msg);
             }
         }
     }
@@ -228,7 +257,7 @@ public abstract class AnsiLog {
 
     public static void warn(Throwable t) {
         if (canLog(Level.WARNING)) {
-            t.printStackTrace(System.out);
+            t.printStackTrace(out);
         }
     }
 
@@ -236,9 +265,9 @@ public abstract class AnsiLog {
     public static void error(String msg) {
         if (canLog(Level.SEVERE)) {
             if (enableColor) {
-                System.out.println(ERROR_COLOR_PREFIX + msg);
+                out.println(ERROR_COLOR_PREFIX + msg);
             } else {
-                System.out.println(ERROR_PREFIX + msg);
+                out.println(ERROR_PREFIX + msg);
             }
         }
     }
@@ -251,7 +280,7 @@ public abstract class AnsiLog {
 
     public static void error(Throwable t) {
         if (canLog(Level.SEVERE)) {
-            t.printStackTrace(System.out);
+            t.printStackTrace(out);
         }
     }

实际运行的结果

实际运行结果,最好有详细的日志,异常栈。尽量贴文本。

把异常信息贴到这里

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions