2017-02-22 7 views
3

SonarLint私は次の行に問題があることを示しています。組み込みの文字列フォーマットとログパラメータとしての文字列連結

LOGGER.debug("Comparing objects: " + object1 + " and " + object2); 

サイドノート:この行を含むメソッドが頻繁に呼び出されることがあります。

この問題の説明は、「前提条件」とロギング引数は評価 (イカ:S2629)を必要としないはず

ある

グアバ com.googleにさらなる評価が必要なメッセージの引数を渡します。 common.base.Preconditionsチェックの結果、パフォーマンスは になります。それは、メソッドが実際に呼び出される前に、それぞれの引数 を解決する必要があるかどうかが理由です。同様に

、連結は、ログ レベルがメッセージを表示するために十分に低いかどうか、メソッドが呼び出されるたびに 実行されますので、ロギング方式に連結された文字列を渡すとも 不要なパフォーマンスヒットが発生することができます。

代わりに、静的またはあらかじめ計算された の値を前提条件のチェックとロギングの呼び出しに渡すようにコードを構造化する必要があります。

具体的には、内蔵の文字列フォーマットではなく 文字列の連結を使用する必要があり、メッセージがメソッド 呼び出しの結果である場合、前提条件はaltoghetherをスキップしなければならない、と 関連例外が条件付きでスローされるべきです代わりに。

違反コード

logger.log(Level.DEBUG, "Something went wrong: " + message); // Noncompliant; string concatenation performed even when log level too high to show DEBUG messages 

LOG.error("Unable to open file " + csvPath, e); // Noncompliant 

Preconditions.checkState(a > 0, "Arg must be positive, but got " + a); // Noncompliant. String concatenation performed even when a > 0 

Preconditions.checkState(condition, formatMessage()); //Noncompliant. formatMessage() invoked regardless of condition 

Preconditions.checkState(condition, "message: %s", formatMessage()); // Noncompliant 

適合

logger.log(Level.SEVERE, "Something went wrong: %s", message); // String formatting only applied if needed 

logger.log(Level.SEVERE,() -> "Something went wrong: " + message); //since Java 8, we can use Supplier , which will be evaluated lazily 

LOG.error("Unable to open file {}", csvPath, e); 

if (LOG.isDebugEnabled() { LOG.debug("Unable to open file " + csvPath, e); // this is compliant, because it will not evaluate if log level is above debug. } 

Preconditions.checkState(arg > 0, "Arg must be positive, but got %d", a); // String formatting only applied if needed 

if (!condition) { throw new IllegalStateException(formatMessage()); // formatMessage() only invoked conditionally } 

if (!condition) { throw new IllegalStateException("message: " + formatMessage()); } 

私は私がこの権利を理解しているかどうか100%わかりません。では、なぜこれが本当に問題なのですか?特に、文字列連結を使用するときのパフォーマンスヒットに関する部分。私はしばしばその文字列を読むので、連結はそれをフォーマットするより速いです。

EDIT:たぶん誰かが

LOGGER.debug("Comparing objects: " + object1 + " and " + object2); 

LOGGEr.debug("Comparing objects: {} and {}",object1, object2); 

の違いはバックグラウンドで動作している私を説明することができます。私はStringがメソッドに渡される前に作成されると思うからです。右?だから私にとっては違いはありません。しかし、明らかに私は間違っていますSonarLintはそれについて不平を言っているので

答えて

3

私はそこにあなたの答えを持っていると信じています。

連結チェックは事前に計算されます。したがって、条件付きでログフレームワークを10K回呼び出すと、すべてがfalseに評価される場合、理由なしで10K回連結されます。

this topicもチェックしてください。そしてIcaroの答えのコメントをチェックしてください。

StringBuilderもご覧ください。

+0

Icaroの答えは、文字列連結がはるかに高速であるという事実を述べています。だから私はなぜこれが問題なのだろうと思っています。 StringBuilderについて - > Icaroの答えでAmirRaminarのコメントが表示された場合、コンパイラによって "+"がStringBuilderコールに変換されていることがわかりました。 – Naxos84

+0

次のコメントは私にとってもっと面白いです;) – luso

1

文字列連結手段 LOGGER.info( "プログラムは" +新しい日付()で開始されました。

ロガー手段のフォーマットに組み込まれています。
LOGGER.info(「プログラムは{}で開始しました」、新しいDate());

違いに http://dba-presents.com/index.php/jvm/java/120-use-the-built-in-formatting-to-construct-this-argument

+0

ありがとうございます。しかし、あなた自身の言葉でまとめてください。リンクがある日、少なくとも要約が消えてしまった場合に起こります。 – Naxos84

+0

ところで、面倒な 'Date'クラスは[' Instant'](https://docs.oracle.com/javase/9​​/docs/api/java/time/Instant.html)に置き換えられました。 [Oracle Tutorial](https://docs.oracle.com/javase/tutorial/datetime/)を参照してください。 –

1

を理解するために非常に良い記事は、loggingステートメントの下に考えてみましょう:

LOGGER.debug("Comparing objects: " + object1 + " and " + object2); 

この 'デバッグ' とは何ですか?

これはLOGGERのレベルではなく、ロギングステートメントのレベルです。 を参照してください、2つのレベルがあります。ここでは、デバッグでloggingステートメント()の

a)は1:

"Comparing objects: " + object1 + " and " + object2 

b)は一つはLOGGERのレベルです。したがって、LOGGERオブジェクトのレベルは何ですか: これはコードまたは一部のXMLでも定義する必要があります。そうでなければ、それは祖先からレベルを取る必要があります。

なぜ私はこれをすべて伝えていますか?

今のロギング文が印刷された(またはそれ以上の技術的な用語ではその「アペンダ」に送信する)場合に限ります。

Level of logging statement >= Level of LOGGER defined/obtained from somewhere in the code 

レベルの可能な値が

DEBUG < INFO < WARN < ERROR 

することができ(ログフレームワークによってはさらにいくつかあります)

質問に戻るようにしましょう:

"Comparing objects: " + object1 + " and " + object2 

は、上記で説明した「レベルルール」が失敗しても常に文字列の作成につながります。満足「レベルルールが上述」場合

しかし、

LOGGER.debug("Comparing objects: {} and {}",object1, object2); 

のみストリング形成をもたらすであろう。

だから、より賢いですか?

このurlと相談してください。

+0

リンクのThx。あなたはリンクの内容の短い要約を提供できますか? (リンクが将来のある時にブレーキをかける場合にのみ) – Naxos84

関連する問題