条件付きロギング最小限の循環的複雑度
-
01-07-2019 - |
質問
後で読む"どうしても制限は循環的複雑?"を実現し、多くの友人がなかなかの辺のこの新しい QA 方針当社のプロジェクト:以上10 循環的複雑度 ります。
意味:以上10'が','else','み','catch'およびその他のコードワークフローの分岐ます。ます。させていただきましたが"い民間試験方法は?'、このような政策は、多くの良いいたしました。
もの:当初の(200人の年数7年に長くプロジェクト、また楽しくログイン(いいえ、できませんので簡単に委譲するものアスペクト指向プログラミン'プログ).
myLogger.info("A String");
myLogger.fine("A more complicated String");
...
が最初のバージョンにはシステムとして活躍した経験した大容量のメモリーの問題ではなく、ログインした時off)などの ログパラメータ (文字列)は、常に計算し、その後継の情報()又は()機能は、新しいレベルのログインした'OFF'このため、ログインした。
でQAに帰すべてのプログラマな条件付きロギングります。
if(myLogger.isLoggable(Level.INFO) { myLogger.info("A String");
if(myLogger.isLoggable(Level.FINE) { myLogger.fine("A more complicated String");
...
しかし、今ることができません-するときに移'10循環的複雑さのレベルの機能に制限いる各種ログに入力された機能が実感として負担するので、"if(publish())"としてカウン+1の循環的複雑!
その機能は8'が','elseされたのではないでしょうか、強く結合しない-簡単-共有可能なアルゴリズムは、3つの重要なログを行...その違反に限るものの条件付きログがありません 本当に 一部の複雑さと機能---
いこいのか。
かの興味深い符号化の進化による紛争')は私のプロジェクトから取得したい考えています。
ありがとうございました。応答となります。
私は主張しなければならないのも問題にならない'のフォーマットの関連が議論評価の関連評価できるが、直前のメソッドを呼び出されるまでは何もしない)
だから、書上の"文字列"とは、実際にはaFunction()、aFunction()文字列で返し、呼び出し複雑な方法で収集と計算のログデータに表示されるロガー...は、この問題の 義務 利用条件付きロギング、そのため、実際の発行の人工増加の循環的複雑さに'...)
今はまったくの"variadic 機能として進していまJohn).
注意:迅速に試験java6ると私 変数引数関数 な評価し、その引数の前が呼ばれることで適用できないための関数呼び出しで、"グリーオブジェクト(または機能のラッパー')をtoString()にだけ呼び出されます。たします。
よって掲載して私の経験である.
休業させていただきまで、次は火曜日に投票しますを選択しのお答えなのです。
再度、ありがとうございました。提案:)
解決
Pythonをお渡ししますのでフォントの値としてパラメータのロギング機能です。文字列のフォーマットのみが適用された場合ログインが有効になります。あるもののオーバーヘッドの呼び出し、その微比を設定します。
log.info ("a = %s, b = %s", a, b)
いつものようにこの言語とvariadic引数(C/C++、C#/Javaなど)。
この最初がやりたかっただけで目の引数が難しい取得するものためのフォーマットする場合を文字列です。例えば、コードはすでにリストの番号でするためのログリストのためのデバッグしやすくなります。実行 mylist.toString()
ま取引所への新規上場申請を実施しない、結果としてスローされます。いま mylist
パラメータとしてのロギング機能を及ぼす場合がありますので扱う文字列フォーマットそのフォーマットでのみ行われます。
以降、OPの問題を具体的に述のJava、どのように上記使用することができます:
私は主張しなければならないのも問題にならない'のフォーマットの関連が議論評価の関連評価できるが、直前のメソッドを呼び出されるまでは何もしない)
フレキシビリティはオブジェクトを行いません高価な計算まで絶対に必要です。これは簡単に言語のようにSmalltalkにはPythonを支援するlambdas、閉鎖が可Javaのエリアを表示一部のエリアです。
言い機能 get_everything()
.で取得する各オブジェクトからデータベースをリストアップしました。だいたい話この場合、結果は破棄されることは明らかであり.その代わりに呼び出する機能を直接定義する内部クラスと呼ばれ LazyGetEverything
:
public class MainClass {
private class LazyGetEverything {
@Override
public String toString() {
return getEverything().toString();
}
}
private Object getEverything() {
/* returns what you want to .toString() in the inner class */
}
public void logEverything() {
log.info(new LazyGetEverything());
}
}
このコードでは、呼び出 getEverything()
に包まれたように実際に実行されます。ロギング機能を実行し toString()
そのパラメータのみの場合のデバッグが有効になります。そのように、コードがのみのオーバーヘッドの呼び出しの代わりにフル getEverything()
ます。
他のヒント
現在のロギングの枠組みの問題は議論の余地がある問題
現在のロギングの枠組みのようにslf4jはlog4j2を必要としないガード諸表のほとんどです。使用するパラメータ化されたログを書いイベントでログインを無条件にもメッセージフォーマットのみが発生した場合、イベントが有効になります。メッセージ構築を行い必要に応じて、ロガーによる事前emptively、アプリケーションによ
ご利用アンティークなログイン図書館、読み取得の背景となけの場合は旧館とパラメータ化されたメッセージ
はガード諸表も加え複雑?
検討を除いたロギングガード諸表からの循環的複雑さを計算します。
することにより、その予測可能で、条件付きロギングチェックねに貢献する複雑なコードです。
硬直的な指標できないプログラマに転す。ご注意!
このニューヨーク-タイム計算の複雑さんに合わせられる程度を示す中称の指示代名詞that degree、以下のアプローチを提供する場合があり仕事にしているのです。
の必要条件付きロギング
ていると思っていガード諸表に導入されたのですがコードのようになります:
private static final Logger log = Logger.getLogger(MyClass.class);
Connection connect(Widget w, Dongle d, Dongle alt)
throws ConnectionException
{
log.debug("Attempting connection of dongle " + d + " to widget " + w);
Connection c;
try {
c = w.connect(d);
} catch(ConnectionException ex) {
log.warn("Connection failed; attempting alternate dongle " + d, ex);
c = w.connect(alt);
}
log.debug("Connection succeeded: " + c);
return c;
}
Javaでは、それぞれのログ諸表を作成し新たな StringBuilder
, は、ソッドを呼び出しの toString()
方法は各オブジェクトに連結される文字列です。これらの toString()
方法は、マイナスとなることが見込まれる作 StringBuilder
インスタンスが、自分たちの呼び出し toString()
方法メンバーですが、可能性をオブジェクトグラフで表示します。前のJava5でもなく、 StringBuffer
利用されていたが、そのすべての業務は、同期化されます。)
この比較的費用がかかるため、場合には、あらゆるログの声は重-実行コードます。と書かれてい上、高価なメッセージフォーマットが発生した場合でも、ロガーは、廃棄のためのログレベルが高すぎる。
この導入ガード諸表の形式:
if (log.isDebugEnabled())
log.debug("Attempting connection of dongle " + d + " to widget " + w);
このガードは、引数の評価 d
や w
の文字列の連結が行われる場合のみ必要です。
解決のための簡単に、効率的なログイン
ただし、ロガーまたはラッパーを書いてますがお選ばれたログインパッケージ)からフォーマッタは、引数のフォーマッタには、メッセージ建設の入荷が大幅に遅れる可能性がござまですることは間違いありますので使用を減のガード諸表とその循環的複雑になります。
public final class FormatLogger
{
private final Logger log;
public FormatLogger(Logger log)
{
this.log = log;
}
public void debug(String formatter, Object... args)
{
log(Level.DEBUG, formatter, args);
}
… &c. for info, warn; also add overloads to log an exception …
public void log(Level level, String formatter, Object... args)
{
if (log.isEnabled(level)) {
/*
* Only now is the message constructed, and each "arg"
* evaluated by having its toString() method invoked.
*/
log.log(level, String.format(formatter, args));
}
}
}
class MyClass
{
private static final FormatLogger log =
new FormatLogger(Logger.getLogger(MyClass.class));
Connection connect(Widget w, Dongle d, Dongle alt)
throws ConnectionException
{
log.debug("Attempting connection of dongle %s to widget %s.", d, w);
Connection c;
try {
c = w.connect(d);
} catch(ConnectionException ex) {
log.warn("Connection failed; attempting alternate dongle %s.", d);
c = w.connect(alt);
}
log.debug("Connection succeeded: %s", c);
return c;
}
}
現在、 のカスケード toString()
通話とそのバッファ配分が発生します な要!この生的な環境を人と建物の為に創りのパフォーマンスをガード。小さなペナルティJava、オートボクシングのプリミティブ型の引数を渡すには、logger.
このコードにログインは言ってもクリーナーによって損なわれ文字列の連結になっていることがある。でもクリーナーの場合形式の文字列外部化のものを使用し ResourceBundle
るも役立つ可能性があるメンテナンスやラインソフトウェアです。
さらなる充実を図
また、Java、 MessageFormat
オブジェクトでも使用できる場所の"フォーマット" String
, いとの考えから追加機能などの選択肢形式を扱う基数番あり。他の代替えを自分のフォーマット機能を呼び出し一部のインタフェースを定義するための"評価"ではなく、基本 toString()
方法。
言語支援のラムダ仕様の表現又はコードブロックのパラメータとして、解決のためにこれとなっていることをロギングの方法。そう評価は、設定ファイルのみ必要な場合には実際に電話が実行してラムダ/コードブロックです。ようとしなかっただけると期待してなかった。
理論的に ことが可能です。たいという人の利用で生産によるパフォーマンス問題を期待していることに使lamdas/コードブロックです。
ものとして常にもし不確かな場合は、試験での測定への影響はcpuの負荷をしています。
ありがとうございましたご回答!皆さんはロック:)
今の私のフィードバックがないとして直進した:
あり、 プロジェクト として"一つのプログラムや走行を独自に単一の生産プラットフォーム')ると思うからできる全ての技術ってい:
- 専用のログリー'オブジェは、パロガーラッパーを呼び出すだけでtoString()が必要
- 併せて使用すればログイン variadic機能 (平Object[]array!)
がまちまちで、とによって説明@ジョンMillikinや@エリクソン.
しかし、この問題を余儀なくされる考えについて"なぜそうしたロギングのでしょうか。'
弊社のプロジェクトが実際に30件のプロジェクト(5~10人)配備各種生産プラットフォーム、非同期通信のニーズや中央バスです。
のログに記載のキングスカレッジロンドンとセン各プロジェクト 初 (5年前からそこはステップです。入 KPI.
うるロガーのログインもお願いいたします、自動的に作成されたオブジェクト(KPI)を登録します。シンプルなコール(myKPI.I_am_signaling_myself_to_you()という仕組みではありません必要な条件を解決の人工増加の循環的複雑さに'ます。
ることKPIのオブジェクトを知って人と同じものを見ることができないとか見ることができる場合もありますの申請うことができ、あわの取得に多くのデータを計算するのでその場でしたのです。
プラスするKPIのオブジェクトが監視される独立して計算/出版の需要その情報単一の個別発行バスです。
そのように、各顧客の求めることができるものとの情報を言いよう、私の処理開始、そしていつからですか?'), の代わりに、正しいログファイルgreppingのための隠の文字列...
実際、"なぜそうしたロギングのでしょうか。たワークショップを実施していなかったロギングのプログラマやユニットまたは統合テストがいを持つ、より広範な地域社会を含む最終顧客ます。当社の報告"機構が中央集権的であり、非同期であるため、24/7.
特定のKPI機構はこの範囲この質問です。言適切なキャリブレーションは、これまでの手で、最も複雑な非機能発行していかなければなりません。では、システムに膝から。正しく校正されたしかしながら、生命-セイバー.
再度、ありがとうございました。ご提案します。いと考えるわけにはいかない一部のシステムが簡単います。
その他のポイントはこの問いを示す特定の問題が考えているよりずっと大きく、複雑なコンテキスト
いま気に入ってくれている。いをお願いすることが問題にKPI(えいするものではありません質問にSOFもう、ここまで来ているのです!) 以降のまま次週へ続きます。
休業させていただきこの解答のための投票は翌火曜日、そして私を選定するとともに、答えはここにあ;))
ることも簡単に、その利用について"を抽出方法"リファクタリングのガード条項?おとえばコード:
public void Example()
{
if(myLogger.isLoggable(Level.INFO))
myLogger.info("A String");
if(myLogger.isLoggable(Level.FINE))
myLogger.fine("A more complicated String");
// +1 for each test and log message
}
になります:
public void Example()
{
_LogInfo();
_LogFine();
// +0 for each test and log message
}
private void _LogInfo()
{
if(!myLogger.isLoggable(Level.INFO))
return;
// Do your complex argument calculations/evaluations only when needed.
}
private void _LogFine(){ /* Ditto ... */ }
CやC++ん用のプリプロセッサの代わりにif文の条件付きロギング
パスのログレベルのロガーを及ぼす場合がありますのでるか否かについてのログ計算書:
//if(myLogger.isLoggable(Level.INFO) {myLogger.info("A String");
myLogger.info(Level.INFO,"A String");
更新:ああ、については、下記をご覧くださいた条件付きでのログなしで文字列を条件とします。ここから実行時よりもコンパイルす。
と思っているとは言い方をしていることではライブラリリファレンスを参照コードのロガーのクラスのフォーマットだけがレベルます。同様に内蔵sprintf.例えば:
myLogger.info(Level.INFO,"A String %d",some_number);
うお客様の基準とします。
altテキストhttp://www.scala-lang.org/sites/default/files/newsflash_logo.png
Scala はannontation @elidable() ることを可能にする除去方法のコンパイラフラグ。
のスカラREPL:
C:>scala
ウラノ-スカラ座版2.8.0.最終(Javaのホットスポット(TM)64ビットのサーバVMのJava1.6.0_16).型式表現について評価されます。タイプ:ります。
scala>輸入scala.アノテーションを期待でelidable 輸入scala.アノテーションを期待でelidable
scala>輸入scala.アノテーションを期待でelidable._ 輸入scala.アノテーションを期待でelidable._
scala>@elidableコンパウンド(極細)デフlogDebug(arg:String)=println(arg)
logDebug:(arg:文字列)のユニット
scala>logDebug("実験")
scala>
とelide-beloset
C:>scala-Xelide下0
ウラノ-スカラ座版2.8.0.最終(Javaのホットスポット(TM)64ビットのサーバVMのJava1.6.0_16).型式表現について評価されます。タイプ:ります。
scala>輸入scala.アノテーションを期待でelidable 輸入scala.アノテーションを期待でelidable
scala>輸入scala.アノテーションを期待でelidable._ 輸入scala.アノテーションを期待でelidable._
scala>@elidableコンパウンド(極細)デフlogDebug(arg:String)=println(arg)
logDebug:(arg:文字列)のユニット
scala>logDebug("実験")
試験
scala>
参照 Scalaを主張する定義
条件付きロギングが悪.で不要なタをコードです。
しなければなりませんの送信対象にして、ロガー:
Logger logger = ...
logger.log(Level.DEBUG,"The foo is {0} and the bar is {1}",new Object[]{foo, bar});
で、java.util.ロギングフォーマッタを使用するMessageFormatヤfooとbar入する文字列を出力します。するわけではなく、場合に呼び出されますのロガー、ハンドラグする。
のための追加の喜びがあるような表現言語で得ることができめ細かな制御方式には記録されたオブジェクト(toStringないため、常に有効であると).
聞で調べると、マクロのC/C++で作業して#定義の場合は、falseの場合無視しな評価以下の表現がtrueを返すストリームにするものではパイプを使用'<<'ります。このように:
LOGGER(LEVEL_INFO) << "A String";
そしてこれを解消に追加の"複雑さ"とツールは、もが不要の算定の文字列、又はその他表現するログインした場合のレベルには至らなかった。
こちらではの優雅なソリューション元素の発現
logger.info(logger.isInfoEnabled()?"ログを書くこちら---":null);
検討伐採util機能---
void debugUtil(String s, Object… args) {
if (LOG.isDebugEnabled())
LOG.debug(s, args);
}
);
その電話は、"閉鎖"を高く評価したいを避けなければなりません。
debugUtil(“We got a %s”, new Object() {
@Override String toString() {
// only evaluated if the debug statement is executed
return expensiveCallToGetSomeValue().toString;
}
}
);