web-dev-qa-db-ja.com

System.err.println()を使用してJava

System.err

「標準」エラー出力ストリーム。このストリームは既に開いており、出力データを受け入れる準備ができています。通常、このストリームは、ホスト環境またはユーザーによって指定されたディスプレイ出力または別の出力先に対応します。規則により、この出力ストリームは、主要な出力ストリームである変数outの値がファイルまたはその他の宛先にリダイレクトされている場合でも、ユーザーがすぐに注意を向けるべきエラーメッセージまたはその他の情報を表示するために使用されます。通常は継続的に監視されません。

そのため、私は通常、開発環境でのデバッグ(主にWebアプリ)の際にSystem.err.println()を使用します。 EclipseのようなほとんどのIDEで。 System.outおよびSystem.errは両方とも同じコンソールで印刷されます。System.errは異なる色(赤)で一意に強調表示されるため、System.errを使用すると値が視覚的に強調表示され、移動する必要がないので、出力しやすくなります。ログ全体を調べて、出力を検索します。これは常にデバッグモードでサーバーを起動する必要がなく、出力した特定の値を確認するだけで、実際に実行を中断して状態を検査することができない場合に役立ちます。

これは本当に悪い習慣ですか、私はそれをすべきではありませんか?私はこれを長い間行ってきましたが、時々これはとても役に立ちます。

3
Yellen

デバッグ時に出力を取得する必要があることは、特に悪い習慣ではありません(悪い習慣は、デバッグしないことです)。

私たちのプログラマーが怠け者であるというだけのことです。出力したいですか?あっち見て...

_System.err.println("Got an error: " + e);
_

とても簡単です。使用しているロギングフレームワークや、ログレベルのことを心配する必要はありません。そして、これが私たちがそれを行う理由です全体

しかし、これが問題です...妥当なサイズのプロジェクトがある場合は、ログインしています。そうしないと、それは悪い習慣です。このロギングがあり、それが賢明なものである場合(つまり、_Java.util.logging_ではない場合)、標準エラーに出力するアペンダーを設定するのは非常に簡単です。

そしてこれには、なぜそうしないのかという言い訳はありません

_package c.s.p.m.logging;

import org.Apache.log4j.Logger;

public class Main {
    private final static Logger LOG = Logger.getLogger(Main.class);

    public static void main(String[] args) {
        LOG.debug("Oops");
        LOG.info("This is awkward");
        LOG.error("This is bad");
    }
}
_

そして(そうです、私はxml形式を使用するそれらの奇妙なボールの1つです-これは最適なものではないかもしれないことに注意してください)

_<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.Apache.org/log4j/'>

    <appender name="console" class="org.Apache.log4j.ConsoleAppender">
        <param name="Target" value="System.err" />
        <layout class="org.Apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
        </layout>
    </appender>

    <appender name="file" class="org.Apache.log4j.RollingFileAppender">
        <param name="append" value="false" />
        <param name="maxFileSize" value="10MB" />
        <param name="maxBackupIndex" value="10" />
        <param name="file" value="logs/someFile.log" />
        <param name="threshold" value="ERROR" />
        <layout class="org.Apache.log4j.PatternLayout">
            <param name="ConversionPattern"
                   value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
        </layout>
    </appender>

    <logger name="c.s.p.m">
        <level value="DEBUG" />
        <appender-ref ref="console" />
    </logger>

    <root>
        <level value="ERROR" />
        <appender-ref ref="file" />
    </root>

</log4j:configuration>
_

そこに、私のコンソールに赤で、私は見る:

 2015-04-30 20:18:34 DEBUG Main:9-Oops 
 2015-04-30 20:18:34 INFO Main:10-これは厄介です
 2015 -04-30 20:18:34 ERROR Main:11-これは悪いです

一方、私のログファイルでは:

 2015-04-30 20:18:34エラーMain:11-これは悪いです

重要なのは、ロギングを使用するように設定した場合、実際には言い訳はありません。これは、コンソールアペンダーの設定ファイルの数行です。

それを設定する習慣としてそれを手に入れたら、ロガーは_System.err_よりもはるかに優れており、離れるのに何がそんなに長くかかったのか不思議に思いますprintlnから。タイムスタンプ、ログレベル、行番号...すべて無料です。少しの時間で、コンソールアペンダーから離れることもできます。ログファイルウォッチャーを使用すると、クラスごとに異なるログファイル(および集計ログファイル)が作成されます。 クレイジーアペンダー ...

そして何よりも、運用環境でコンソールをいっぱいにしてしまったSystem.err.println()を誤ってチェックインしてしまったため、同僚からのばかげた見栄えはなくなりました。

System.err.println()badではなく、あなたの習慣ではありません壊れる必要があります(自分の後を片付け、その後手を洗うことを確認する限り)、そこから離れると、より多くのより良いオプションがあることがわかります入力する文字がさらに少なくなります。

5
user40980

デフォルトのストリームを直接使用しないでください。実際にアプリケーションをデバッグしたくないときに、これを防ぐ簡単な方法はありますか?各行を調べて変更せずにログ出力ターゲットを変更する方法はありますか?その方法でログに記録しているすべてのメッセージは実際に非常に深刻であり、すべての環境で即時の対応が必要ですか?

実際のストリームを抽象化し、ロギングレベルの構成を提供するロギングフレームワークを使用する必要があります。

このようにして、必要な情報量を構成できます。 IDEを使用すると、このようなログを読みやすい方法で表示したり、フィルタリング機能を使用したりできます(特定のロギングレベルのメッセージのみ、テキスト検索など)。 IDEからどれだけのサポートが得られるかは、おそらく作業しているプラ​​ットフォームとその特定のツールに依存します。たとえば、LogCatは、Android開発のための本当に素晴らしいオプションをいくつか提供します。使用しているフレームワークやサーバーがこれほど多くのサポートを提供しない場合でも、私はむしろデフォルトのストリームを直接使用するのではなく、カラーリングとフィルタリング機能を備えたシンプルなログ表示プラグイン。または、BareTailなどのスタンドアロンツール(Windowsを使用している場合)、または tail -f log_file| grep --line-buffered some_regex_pattern の場合絶望的か、何か軽量なものが欲しくてUnix端末を持っている。

適切に管理されている場合、実際のロガーによってログに記録されたメッセージは、開発から本番までのあらゆる場所で役立ちます。

log4jSL4JLogbackまたはJava.util.loggingのクラス

どちらを選択したかはより広い主題ですが、抽象化の層を何も持たずに単にSystem.errを使用するよりも、どれも優れていると思います。

そして実際のデバッグでは、デバッガーが私にとってよりうまく機能します。分析中の行のスコープ内の変数の状態をチェックしたり、別の場所を調べたりするために、これらのprintlnステートメントで行うようにコードを変更して再コンパイルする必要はありません。これを使用すると、そのようなステートメントでコードを煩雑にする必要もなくなります。それらは不必要なスペースを取り、コードの背後にあるロジックを理解しようとするとき、それが必要かどうかにかかわらず、視覚的に解析する必要があります。

4
toniedzwiedz

ロギングは役に立たないと思います。実際に重要なこと、キャッチされていない例外はすでに印刷されているので、それは時間の無駄だと思います。

System.errに関する引用から:

慣例により、この出力ストリームは、errorメッセージまたはuser主要出力ストリーム、変数outの値が、通常は継続的に監視されていないファイルまたはその他の宛先にリダイレクトされている場合でも。

さて、私たちはデバッグ中にいくつかの変数をチェックしたい開発者です。それらはエラーではありません。それが、私が System.out を使用する理由です。これは、無用な出力を回避した場合でも読み取り可能です。

1
user175878