如何在 Android 上启用 apache commons HttpClient 的日志记录

发布于 2024-09-09 23:28:29 字数 517 浏览 11 评论 0原文

为了在普通 Java 应用程序中启用 apache commons HttpClient 的日志记录,我使用了:

System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
System.setProperty("org.apache.commons.logging.simplelog.log.httpclient.wire", "debug");
System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient", "debug");

但在 android 上,我在 LogCat 中看不到日志。

我错过了什么吗?

To enable logging for apache commons HttpClient in normal Java application I used:

System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
System.setProperty("org.apache.commons.logging.simplelog.log.httpclient.wire", "debug");
System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient", "debug");

But on android I don't see logs in LogCat.

Am I missing some thing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

但可醉心 2024-09-16 23:28:29

忽略我之前的评论。我在 org.apache.http 日志记录页面上找到了解决方案。您原来的答案是指 httpclient-3.x 日志记录,最近版本的工作代码来自 http 组件日志记录

java.util.logging.Logger.getLogger("org.apache.http.wire").setLevel(java.util.logging.Level.FINEST);
java.util.logging.Logger.getLogger("org.apache.http.headers").setLevel(java.util.logging.Level.FINEST);

System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
System.setProperty("org.apache.commons.logging.simplelog.log.httpclient.wire", "debug");
System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.http", "debug");
System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.http.headers", "debug");

和属性:

adb shell setprop log.tag.org.apache.http VERBOSE
adb shell setprop log.tag.org.apache.http.wire VERBOSE
adb shell setprop log.tag.org.apache.http.headers VERBOSE

区别在于日志记录标记名称。

Ignore my earlier comment. I found the solution on the org.apache.http logging page. Your original answer was referring to httpclient-3.x logging, and the working code for recent versions comes from http-components logging

java.util.logging.Logger.getLogger("org.apache.http.wire").setLevel(java.util.logging.Level.FINEST);
java.util.logging.Logger.getLogger("org.apache.http.headers").setLevel(java.util.logging.Level.FINEST);

System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
System.setProperty("org.apache.commons.logging.simplelog.log.httpclient.wire", "debug");
System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.http", "debug");
System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.http.headers", "debug");

and properties:

adb shell setprop log.tag.org.apache.http VERBOSE
adb shell setprop log.tag.org.apache.http.wire VERBOSE
adb shell setprop log.tag.org.apache.http.headers VERBOSE

The difference is in the logging tag names.

你怎么敢 2024-09-16 23:28:29

这是一个解决方案(无需深入研究细节)

控制台:

adb shell setprop log.tag.httpclient.wire.header VERBOSE
adb shell setprop log.tag.httpclient.wire.content VERBOSE

代码:

java.util.logging.Logger.getLogger("httpclient.wire.header").setLevel(java.util.logging.Level.FINEST);
java.util.logging.Logger.getLogger("httpclient.wire.content").setLevel(java.util.logging.Level.FINEST);

测试:

java.util.logging.Logger.getLogger("httpclient.wire.content").log(java.util.logging.Level.CONFIG, "hola");

Here is a solution (without digging into details)

Console:

adb shell setprop log.tag.httpclient.wire.header VERBOSE
adb shell setprop log.tag.httpclient.wire.content VERBOSE

Code:

java.util.logging.Logger.getLogger("httpclient.wire.header").setLevel(java.util.logging.Level.FINEST);
java.util.logging.Logger.getLogger("httpclient.wire.content").setLevel(java.util.logging.Level.FINEST);

Test:

java.util.logging.Logger.getLogger("httpclient.wire.content").log(java.util.logging.Level.CONFIG, "hola");
等数载,海棠开 2024-09-16 23:28:29

魔鬼在于细节。我正在运行 2.3.3 模拟器并让它与:

java.util.logging.Logger.getLogger("org.apache.http.wire").setLevel(java.util.logging.Level.FINEST);
java.util.logging.Logger.getLogger("org.apache.http.headers").setLevel(java.util.logging.Level.FINEST);

和 adb shell

# setprop log.tag.org.apache.http.wire VERBOSE
# setprop log.tag.org.apache.http.headers VERBOSE

一起工作因此,日志说明符似乎是不同的。

The devil is in the details. I'm running the 2.3.3 emulator and got it working with:

java.util.logging.Logger.getLogger("org.apache.http.wire").setLevel(java.util.logging.Level.FINEST);
java.util.logging.Logger.getLogger("org.apache.http.headers").setLevel(java.util.logging.Level.FINEST);

and in the adb shell

# setprop log.tag.org.apache.http.wire VERBOSE
# setprop log.tag.org.apache.http.headers VERBOSE

Thus it seems the log specifiers are different.

夜司空 2024-09-16 23:28:29

你只需要使用

java.util.logging.Logger.getLogger(yourFullClassName).setLevel(java.util.logging.Level.All);

Android

adb shell setprop log.tag.correspondingTag VERBOSE

使用这个函数从类全名中获取相应的Tag:

public static String loggerNameToTag(String loggerName)
  {
    if (loggerName == null) {
      return "null";
    }

    int length = loggerName.length();
    if (length <= 23) {
      return loggerName;
    }

    int lastPeriod = loggerName.lastIndexOf(".");
    return length - (lastPeriod + 1) <= 23 ? loggerName.substring(lastPeriod + 1) : loggerName.substring(loggerName.length() - 23);
  }

例如,我想为“org.apache.http.impl.client.DefaultRequestDirector”类启用日志记录,请执行以下操作

String clzName = "org.apache.http.impl.client.DefaultRequestDirector";
String newClzName = loggerNameToTag(clzName);
System.out.println("className:" + clzName + " tagName is " + newClzName);    //get tagName from class full name,and then it will be used in setprop
Logger jdkLogger = Logger.getLogger(clzName);
jdkLogger.setLevel(Level.ALL);
if (jdkLogger.isLoggable(Level.FINE))
{
        jdkLogger.log(Level.FINE, "jdk log msg");    
        jdkLogger.log(Level.Fine,"tagName is")
}

:在亚行外壳中

setprop log.tag.DefaultRequestDirector VERBOSE

You just need to use

java.util.logging.Logger.getLogger(yourFullClassName).setLevel(java.util.logging.Level.All);

and

adb shell setprop log.tag.correspondingTag VERBOSE

Android use this function to get correspondingTag from class full name:

public static String loggerNameToTag(String loggerName)
  {
    if (loggerName == null) {
      return "null";
    }

    int length = loggerName.length();
    if (length <= 23) {
      return loggerName;
    }

    int lastPeriod = loggerName.lastIndexOf(".");
    return length - (lastPeriod + 1) <= 23 ? loggerName.substring(lastPeriod + 1) : loggerName.substring(loggerName.length() - 23);
  }

so for example,I want to enable logging for “org.apache.http.impl.client.DefaultRequestDirector” class,do such things below:

String clzName = "org.apache.http.impl.client.DefaultRequestDirector";
String newClzName = loggerNameToTag(clzName);
System.out.println("className:" + clzName + " tagName is " + newClzName);    //get tagName from class full name,and then it will be used in setprop
Logger jdkLogger = Logger.getLogger(clzName);
jdkLogger.setLevel(Level.ALL);
if (jdkLogger.isLoggable(Level.FINE))
{
        jdkLogger.log(Level.FINE, "jdk log msg");    
        jdkLogger.log(Level.Fine,"tagName is")
}

And then in adb shell

setprop log.tag.DefaultRequestDirector VERBOSE
你丑哭了我 2024-09-16 23:28:29

对于 Apache Http Components 版本 5.x,您需要使用 slf4jlogging Facade,例如 JUL (Jakarta Common Logging) 在编译时绑定日志记录后端。

implementation 'org.slf4j:slf4j-jdk14:2.0.0-alpha7'

通过检索root记录器

final Logger rootLogger = java.util.logging.Logger.getLogger("");

final Logger rootLogger = java.util.logging.LogManager.getLogManager().getLogger("")

将日志记录级别设置为适当的级别,否则消息将被丢弃

rootLogger.setLevel(Level.ALL);

实现您自己的java.util.logging.Handler以接收消息

public static class LogHandler extends Handler {

    @Override
    public void close() {
        // do nothing
    }

    @Override
    public void flush() {
        // do nothing
    }

    @Override
    public void publish(LogRecord record) {
        final Level level = record.getLevel();
        if (level == Level.INFO) {
            Log.i(record.getLoggerName(), record.getMessage());
        } else if (level == Level.WARNING) {
            Log.w(record.getLoggerName(), record.getMessage());
        } else if (level == Level.SEVERE) {
            Log.e(record.getLoggerName(), record.getMessage());
        } else if (level == Level.FINE) {
            Log.d(record.getLoggerName(), record.getMessage());
        } else {
            Log.v(record.getLoggerName(), record.getMessage());
        }
    }
}

设置处理程序

final LogHandler logHandler = new LogHandler();
rootLogger.addHandler(logHandler);

并为为模块提供了一个 setLevel 函数。容器需要对未初始化的外部记录器保持强引用,否则垃圾收集器将取消分配,并且 level 参数将设置为默认值。

private static HashMap<String, Logger> sLoggerMap = new HashMap<>();

保存 modules

public static class Module {
    final String mModule;

    public static final Module APACHE_HTTP = new Module("org.apache.hc.client5.http");
    public static final Module APACHE_HTTP_WIRE = new Module("org.apache.hc.client5.http.wire");
    public static final Module APACHE_HTTP_HEADERS = new Module("org.apache.hc.client5.http.headers");

    Module(final String module) {
        mModule = module;
    }
}

和函数的

public static void setLogging(final Module module, final Level level) {
    Logger logger = sLoggerMap.get(module.mModule);
    if (logger == null) {
        logger = Logger.getLogger(module.mModule);
        sLoggerMap.put(module.mModule, logger);
    }
    logger.setLevel(level);
}

类并像这样使用它(我将所有内容封装在 Logging 类中)

Logging.setLogging(Logging.Module.APACHE_HTTP_WIRE, Level.FINE);

当请求异步时,它有其自身的缺点。切换日志级别将影响所有正在进行的请求。

对于发布版本,请将以下内容添加到 proguard-rules.pro

-keep class org.apache.hc.client5.http.** {
    <fields>;
    <methods>;
}

For Apache Http Components version 5.x, you need to use slf4j logging Facade e.g. JUL (Jakarta Common Logging) to bind a logging backend at compile time.

implementation 'org.slf4j:slf4j-jdk14:2.0.0-alpha7'

Retrieve the root logger via

final Logger rootLogger = java.util.logging.Logger.getLogger("");

or

final Logger rootLogger = java.util.logging.LogManager.getLogManager().getLogger("")

Set the logging level to proper level, otherwise messages are discarded

rootLogger.setLevel(Level.ALL);

Implement your own java.util.logging.Handler for receiving messages

public static class LogHandler extends Handler {

    @Override
    public void close() {
        // do nothing
    }

    @Override
    public void flush() {
        // do nothing
    }

    @Override
    public void publish(LogRecord record) {
        final Level level = record.getLevel();
        if (level == Level.INFO) {
            Log.i(record.getLoggerName(), record.getMessage());
        } else if (level == Level.WARNING) {
            Log.w(record.getLoggerName(), record.getMessage());
        } else if (level == Level.SEVERE) {
            Log.e(record.getLoggerName(), record.getMessage());
        } else if (level == Level.FINE) {
            Log.d(record.getLoggerName(), record.getMessage());
        } else {
            Log.v(record.getLoggerName(), record.getMessage());
        }
    }
}

Set the handler

final LogHandler logHandler = new LogHandler();
rootLogger.addHandler(logHandler);

And for goodies a setLevel function for modules. A container is required to keep strong reference to uninitialized external loggers, otherwise garbage collector will deallocate and level parameter will be set to default.

private static HashMap<String, Logger> sLoggerMap = new HashMap<>();

Class to hold modules

public static class Module {
    final String mModule;

    public static final Module APACHE_HTTP = new Module("org.apache.hc.client5.http");
    public static final Module APACHE_HTTP_WIRE = new Module("org.apache.hc.client5.http.wire");
    public static final Module APACHE_HTTP_HEADERS = new Module("org.apache.hc.client5.http.headers");

    Module(final String module) {
        mModule = module;
    }
}

With function

public static void setLogging(final Module module, final Level level) {
    Logger logger = sLoggerMap.get(module.mModule);
    if (logger == null) {
        logger = Logger.getLogger(module.mModule);
        sLoggerMap.put(module.mModule, logger);
    }
    logger.setLevel(level);
}

And use it like so (I'm encapsulating everything inside Logging class)

Logging.setLogging(Logging.Module.APACHE_HTTP_WIRE, Level.FINE);

It has its own drawbacks when requests are async. Switching log level will affect all the in progress request.

For release build, add following to proguard-rules.pro

-keep class org.apache.hc.client5.http.** {
    <fields>;
    <methods>;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文