禁用 HttpClient 日志记录

167

我正在使用commons-httpclient 3.1进行集成测试套件。 HttpClient的默认日志记录非常嘈杂,我似乎无法将其关闭。 我尝试按照此处的说明操作,但它们都没有任何作用。

主要是我需要让org.apache.http.wire记录器安静下来。问题的一部分在于我不知道HttpClient尝试使用哪种类型的记录器。我以前从未使用过这个库。我尝试创建一个log4j.properties文件并将其放入我的test/resources文件夹中,修改jre/lib中的主logging.properties文件,并按照记录页面上指定的各种日志记录选项发送到Maven中,但它们都没有任何作用。

更新: 更正:实际上,出现问题的输出似乎是通过jwebunit对HttpClient的使用而产生的,而不是我的使用。 无论哪种方式,这都是不可取的。

更新: 感谢到目前为止所做的尝试。我已经尝试了下面所有建议,但仍然没有运气。 我的src/test/resources文件夹中有一个commons-logging.properties文件,其内容如下:

org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.Log4jFactory
log4j.configuration=log4j.properties

在同一个文件夹中放置一个名为 log4j.properties 的文件,其内容如下:

log4j.rootLogger=ERROR, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%c] %m%n

#This is the line that should make httpclient shut up
log4j.logger.org.apache.http=ERROR

然而,当我运行我的测试时,我仍然会得到很多这样的输出:

21:57:41.413 [main] DEBUG org.apache.http.wire - << "                                   [\r][\n]"
21:57:41.413 [main] DEBUG org.apache.http.wire - << "[\r][\n]"
21:57:41.413 [main] DEBUG org.apache.http.wire - << "                                   [\r][\n]"
21:57:41.413 [main] DEBUG org.apache.http.wire - << "                               </ul>[\n]"
21:57:41.413 [main] DEBUG org.apache.http.wire - << "    [\n]"
21:57:41.424 [main] DEBUG org.apache.http.wire - << "[\n]"
21:57:41.425 [main] DEBUG org.apache.http.wire - << "[\r][\n]"
21:57:41.425 [main] DEBUG org.apache.http.wire - << "[\r][\n]"
21:57:41.425 [main] DEBUG org.apache.http.wire - << "                   </div>[\r][\n]"
21:57:41.425 [main] DEBUG org.apache.http.wire - << "                </li>[\r][\n]"
21:57:41.425 [main] DEBUG org.apache.http.wire - << "            [\r][\n]"
21:57:41.425 [main] DEBUG org.apache.http.wire - << "            [\r][\n]"
21:57:41.433 [main] DEBUG org.apache.http.wire - << "        </ul>[\n]"
21:57:41.433 [main] DEBUG org.apache.http.wire - << "</div>[\n]"
21:57:41.433 [main] DEBUG org.apache.http.wire - << "[\n]"
21:57:41.433 [main] DEBUG org.apache.http.wire - << "</div>[\n]"
21:57:41.433 [main] DEBUG org.apache.http.wire - << "[\n]"
21:57:41.433 [main] DEBUG org.apache.http.wire - << "[\n]"
21:57:41.433 [main] DEBUG org.apache.http.wire - << "[\n]"
21:57:41.433 [main] DEBUG org.apache.http.wire - << "[\n]"
21:57:41.433 [main] DEBUG org.apache.http.wire - << "<div class="details">[\n]"
21:57:41.442 [main] DEBUG org.apache.http.wire - << "[\n]"
21:57:41.443 [main] DEBUG org.apache.http.wire - << "[\n]"
21:57:41.443 [main] DEBUG org.apache.http.wire - << "<div class="details-body details-precis  ">[\n]
"
21:57:41.443 [main] DEBUG org.apache.http.wire - << "<div class="details-state">[\n]"
21:57:41.443 [main] DEBUG org.apache.http.wire - << "[\n]"
21:57:41.443 [main] DEBUG org.apache.http.wire - << "</div>[\n]"
21:57:41.443 [main] DEBUG org.apache.http.wire - << "</div>[\n]"
21:57:41.443 [main] DEBUG org.apache.http.wire - << "[\n]"
21:57:41.455 [main] DEBUG org.apache.http.wire - << "[\n]"
21:57:41.455 [main] DEBUG org.apache.http.wire - << "</div>[\n]"
21:57:41.455 [main] DEBUG org.apache.http.wire - << "[\n]"
21:57:41.455 [main] DEBUG org.apache.http.wire - << "</div>[\n]"
21:57:41.455 [main] DEBUG org.apache.http.wire - << "</div>[\n]"
21:57:41.455 [main] DEBUG org.apache.http.wire - << "[\n]"
21:57:41.455 [main] DEBUG org.apache.http.wire - << "[\n]"
21:57:41.455 [main] DEBUG org.apache.http.wire - << "[\n]"
21:57:41.455 [main] DEBUG org.apache.http.wire - << "[\r][\n]"
Destroying 1 processes21:57:41.465 [main] DEBUG org.apache.http.wire - << "[\r][\n]"

当从网络传输数据时,输出所有内容的日志让这个库对我来说不可用...直到我找出如何关闭它。请问是否需要特殊处理才能读取日志配置?


对于所有遇到这个问题的人:请确保在您的VM选项中添加“-Dlog4j.debug”,以确保正确的配置文件被加载。 - Tommy
3
请参阅 https://dev59.com/IXM_5IYBdhLWcg3wTRPL。以下为摘录:public class Main { static { System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.NoOpLog"); } // 其余代码与之前相同 } - PVS
1
官方文档:http://hc.apache.org/httpclient-3.x/logging.html - Christophe Roussy
5
这个问题OP解决了吗?我遇到了完全相同的问题,非常困扰。 - Collin Bell
2
这个问题解决了吗?尝试了很多答案,但没有成功。 - Markvds
天啊,这让我回到了HttpURLConnection。 - ropo
37个回答

104

更新 log4j.properties 文件,包括以下内容:

log4j.logger.httpclient.wire.header=WARN
log4j.logger.httpclient.wire.content=WARN
请注意,如果未安装Log4j库,则HttpClient(因此也包括JWebUnit)将使用logback。在这种情况下,创建或编辑logback.xml以包含:
<configuration>
    <logger name="org.apache" level="WARN" />
    <logger name="httpclient" level="WARN" /> 
</configuration>

log4j.properties文件中,将Log4j的日志级别设置为WARN,并指定包名为org.apache.commons.httpclient,这种方法不能按预期工作

log4j.logger.org.apache.commons.httpclient=WARN

这是因为 HttpClient(v3.1)的源代码使用了以下日志名称:

public static Wire HEADER_WIRE = new Wire(LogFactory.getLog("httpclient.wire.header"));
public static Wire CONTENT_WIRE = new Wire(LogFactory.getLog("httpclient.wire.content"));

27
在4.2.1版本的源代码中,日志名称为:"org.apache.http.headers"和"org.apache.http.wire",但即使使用它们,我似乎无法关闭繁琐的Apache日志记录。 - Tinclon
谢谢!!!另外:如果您在自己的代码中使用httpclient并且尚未使用Log4j,则还要记得在类路径中包含log4j jar... - FelixD
你好,关于log4j的xml配置文件应该怎么处理呢?谢谢。 - Xiaobo Gu

34

注意:本回答的一些内容可能会重复您已经了解(或认为自己了解)的东西,但是有关此问题存在一些错误信息,因此我将从头开始详细说明

  • Commons HttpClient使用Commons-Logging进行其所有日志记录需求。

  • Commons-Logging不是一个完整的日志框架,而是对几个现有日志框架的包装器。

  • 这意味着当您想要控制日志输出时,您(大多数情况下)最终会配置除Commons-Logging之外的库,但由于Commons-Logging包装了几个其他库,如果不知道您的确切设置,则很难猜测需要配置哪一个。

  • Commons-Logging可以记录到log4j,但也可以记录到java.util.logging(JDK1.4记录)

  • Commons-Logging试图聪明地猜测您正在使用哪个日志框架,并将其日志发送到该框架。

  • 如果您尚未拥有日志框架,并且在1.4或以上的JRE上运行(您确实应该这样做),那么它可能会将其日志消息发送到JDK日志记录(java.util.logging

  • 依赖Commons-Logging的自动发现机制容易出错。仅在类路径中添加log4j.jar将导致它切换使用哪个日志机制,这可能不是您想要的。

  • 最好明确告诉Commons-Logging要使用哪个日志库

  • 您可以按照这些说明创建一个commons-logging.properties文件来执行此操作。

  • 要配置commons-httpclient记录日志,您需要遵循以下步骤:

  • 决定使用哪个底层日志框架。历史上,常见的选择是 log4jjava.util.logging。到了2022年,常见选择是 LogBack(也是Spring框架的默认选择)。

  • 设置 commons-logging 属性文件指向正确的 Log 实现。例如:
    要使用 log4j,需要在属性文件中加入以下内容:
    org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
    要使用 JDK logging,设置如下:
    org.apache.commons.logging.Log=org.apache.commons.logging.impl.Jdk14Logger
    要使用 Slf4J:
    org.apache.commons.logging.Log=org.apache.logging.slf4j.SLF4JLogger

    这些也可以作为系统属性设置(例如在命令行上使用 -D)。

    1. 配置底层日志实现(例如 log4j)以忽略您不需要的消息,并输出您需要的消息。

    这是很多步骤,但这就是所需的。Apache-commons 的开发人员倾向于假设您已经配置好了日志框架,并且他们可以通过自动发现来确定是哪个框架。
    如果对您来说这不是真的,那么就需要更多的工作才能让事情正常运行。


    1
    这是非常有用的信息;我真的觉得它应该被添加到这个页面。你是为了这个写的吗? - natem345
    1
    哎呀,这个答案很棒,但是我没能让它起作用。我正在使用Dropwizard,我尝试了你提到的所有方法,但都没有成功 :'( - Vic Seedoubleyew

    23

    对于log4j,在应用程序的source目录下,添加以下内容到log4j.properties文件中:

    log4j.logger.org.apache=WARN
    log4j.logger.httpclient=WARN
    

    对于logback,以下的logback.xml将消除噪音:

    <configuration>
        <logger name="org.apache" level="WARN" />
        <logger name="httpclient" level="WARN" /> 
    </configuration>
    

    1
    我正在使用log4j。在日志中添加前两行完全解决了我的问题。所有其他的日志消息都按照我设置的级别显示,而Apache日志则不是。非常有帮助。谢谢。 - Arun Thundyill Saseendran
    这可能因您的情况而异,但是对于禁用AWS SDK默认启用的极其冗长的日志记录,这是唯一有效的方法。 - Matt Baker

    21

    这对我的测试有效;

    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", "ERROR");
    System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.http", "ERROR");
    System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.http.headers", "ERROR");
    

    你把这个放在测试里了吗? - manikanta nvsr

    20

    我将这个代码放入了我的log4j配置文件中

    log4j.logger.org.apache.http.wire=WARN
    

    这将限制输出为警告级别或更高级别。


    19

    在使用RestAssured和JUnit时,我遇到了这个问题。对我来说,这种编程方法有效:

    @BeforeClass
    public static void setUpClass() {
        ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) org.slf4j.LoggerFactory.getLogger("org.apache.http");
        root.setLevel(ch.qos.logback.classic.Level.INFO);
    
        //...
    }
    

    4
    太棒了,这是唯一对我有效的解决方案。非常感谢。 - lasote
    谢谢!一开始在测试方法中使用了完全相同的代码,但没有任何作用。将其放置在自己的@Before@BeforeClass函数中非常有效。 - ExactaBox
    唯一对我有效的解决方案。在WebApplicationInitializer中启动了此项工作。 - Anwar Reefat
    如果你只是从主方法运行本地测试,那么这就是你需要的 :) 谢谢! - Julian Cardenas

    12

    花了很长时间才发现,JWebUnit已经捆绑了 Logback 日志组件,所以它甚至不会使用 log4j.propertiescommons-logging.properties

    相反,创建一个名为 logback.xml 的文件并将其放置在您的源代码文件夹中(在我的情况下,是src):

    <configuration debug="false">
      <!-- definition of appender STDOUT -->
      <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
          <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
        </encoder>
      </appender>
    
      <root level="ERROR">
        <!-- appender referenced after it is defined -->
        <appender-ref ref="STDOUT"/>
      </root> 
    </configuration>
    

    看起来Logback仍在开发中,API似乎仍在变化,因此这个代码示例将来可能会失败。另请参阅这个StackOverflow问题


    1
    你太美了。因为这个东西,我差点杀了一只猫。它让我发疯了。 - Manish Patel
    这对我来说是解决方案。我认为这是因为我包含的其他库传递地包含了logback,所以它被锁定在这个记录器上。 - Nathan

    8
    我们使用XML而不是属性文件来配置日志输出。以下代码可以使其保持安静。
    <logger name="org.apache.commons.httpclient">
        <level value="fatal"/>
    </logger>
    
    <logger name="httpclient.wire.header">
        <level value="fatal"/>
    </logger>
    
    <logger name="httpclient.wire.content">
        <level value="fatal"/>
    </logger>
    

    6

    使用Log4j和HttpCLient的简单方法(本例中使用v3.1,应该适用于更高版本,但可能需要进行少量更改)

    确保所有依赖项都正确,并对下载内容进行MD5校验!

    import org.apache.commons.httpclient.HttpClient;  
    import org.apache.log4j.Level;  
    import org.apache.log4j.Logger;  
    
    ---
    
    Logger.getLogger("org.apache.commons.httpclient").setLevel(Level.WARN);
    Logger.getLogger("httpclient.wire.header").setLevel(Level.WARN);
    Logger.getLogger("httpclient.wire.content").setLevel(Level.WARN);
    
    HttpClient client = new HttpClient();
    

    我应该把它放在main方法中吗? - parsecer
    @parsecer 你可以。 - WiR3D

    6
    可能是某个依赖项引入了一个日志配置文件(除非它是一个应该这样做的框架,否则他们真的不应该这样做)导致此问题出现。

    我一直困扰着同样的问题,最后决定好好研究一下。

    结果发现,我的项目依赖于 http-builder-0.5.2.jar,其中包含了一个名为 log4j.xml 的文件。并且,org.apache.http.wire 的日志级别确实为 DEBUG!我找到它的方法只是检查所有依赖库中的 jar 文件,然后运行 "jar tvf" 命令并搜索 log4j。

    虽然这个发现让我最终解决了我的问题,将我的http-builder 依赖版本升级到 0.6,但是当开发者将 log4j.xml 文件捆绑到 jar 文件中去时,我仍然感到困惑。不管怎样,这可能暂时与本主题无关。但是考虑到之前在寻找解决方案时,我从未看到过我的解决方案,所以我认为提及这个有用的解决方案是很有意义的。希望对某个人有帮助。


    使用<!-- https://mvnrepository.com/artifact/com.fredericboisguerin.excel/excel-reader-writer --> <dependency> <groupId>com.fredericboisguerin.excel</groupId> <artifactId>excel-reader-writer</artifactId> <version>2.1</version> </dependency>时出现了类似的问题。移除该依赖后,日志消失了。谢谢! - adom

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接