3

現在、バックトレースとともにエラーをログに記録するロガーがあります。ロガーは を介し​​てバックトレースを JSON にシリアル化しますjson_encode()

いくつかの仮想コードを見てみましょう...

<?php
    error_reporting(-1);                          // show all errors
    function test($b){
        echo json_encode(debug_backtrace());      // take a backtrace snapshot
    }
    $c = imagecreate(50,50);                      // create a resource...
    test($c);                                     // ...and pass to function
?>

上記のコードを実行すると、次のように表示されます。

警告: json_encode() [function.json-encode]:タイプはサポートされていません。5 行目の /code/ch6gVw で null としてエンコードされています [{"file":"/code/ch6gVw","line":8,"function" :"テスト","引数":[null]}]

ここで、次の 2 つのことが起こっていることがわかります。

  1. ロガー自体が警告を発しています! 悪い悪い悪い!
  2. ログに記録されたデータから、関数に null を渡したことがわかります?!?!

したがって、私の提案する解決策は次のようなものです。

foreach($trace as $i=>$v)
    if(is_resource($v))
        $trace[$i] = (string)$v.' ('.get_resource_type($v).')';

結果は次のようになりますResource id #1 (gd)


ただし、これは重大な問題を引き起こす可能性があります。

  1. 配列が自分自身を参照する無限ループに陥らないように、どの配列をループしたかを何らかの方法で追跡する必要があります ($GLOBALSこの混乱を引き起こす傾向があります)。
  2. オブジェクト プロパティのリソースも変換する必要がありますが、オブジェクトは配列とは異なり、元のもののコピーではないため、プロパティを変更するとライブ オブジェクトが変更されます。一方、clone()対象物に対してどれくらい安全ですか?
  3. このようなループはサーバーの速度を著しく低下させませんか (バックトレースは大きくなる傾向があります)。
4

2 に答える 2

2

私は次の機能で終わった:

function clean_trace($branch){
    if(is_object($branch)){
        // object
        $props = array();
        $branch = clone($branch); // doesn't clone cause some issues?
        foreach($props as $k=>$v)
            $branch->$k = clean_trace($v);
    }elseif(is_array($branch)){
        // array
        foreach($branch as $k=>$v)
            $branch[$k] = clean_trace($v);
    }elseif(is_resource($branch)){
        // resource
        $branch = (string)$branch.' ('.get_resource_type($branch).')';
    }elseif(is_string($branch)){
        // string (ensure it is UTF-8, see: https://bugs.php.net/bug.php?id=47130)
        $branch = utf8_encode($branch);
    }
    // other (hopefully serializable) stuff
    return $branch;
}

ここで実際の動作を見ることができます。しかし、私は確信していません:

  • 非常に遅い(大量のデータを反復処理する)
  • 非常にメモリを集中的に使用します(元のデータを台無しにしないようにデータをコピーする必要があります)
  • 配列/オブジェクトが自分自身を参照する場合は安全ではありません
    • 例: $a = array(); $a['ref'] = &$a;(PHP はいくつかの内部変数に対してこれを行います)
  • オブジェクトのクローン作成には重大な副作用があるのではないかと心配しています (魔法の方法を考えてみて__clone()ください。大混乱への誘いです)。
于 2011-12-06T08:35:06.217 に答える
1

後で結果をきれいに印刷するために使用できるデータ構造としてバックトレースを保存しようとしていますか?

それが必要ない場合は、保管$result = print_r(debug_backtrace(), true)して完了します。

そうでない場合、最初のショットは次のようになります。

<?php
error_reporting(-1);
function test($b){
    echo json_encode(clean(debug_backtrace()));
}   
$c = fopen("/tmp/foo", "w");
test($c);


function clean($trace) {
    array_walk_recursive($trace, function(&$element) {
        if(is_object(&$element)) {
            // work around unrealizable elements and preserve typing
            $element = array(get_class($element), (object)$element); 
        } else if(is_resource($element)) {
            $element = get_resource_type($element) . '#'  .(int)$element;
        }   
    }); 
    return $trace;
}   

これは単なる大まかなスケッチですが、後で検査するためにバックトラックをテキスト以外の形式または既に処理された形式で保存し、成熟したフレームワークを見回しても何も起こらなかったプロジェクトを私は知りません

于 2011-12-14T09:31:15.220 に答える