4

イベントのログ ファイルがいくつかあります (1 行に 1 つのイベント)。ログが重複する可能性があります。ログは、おそらく複数のタイム ゾーンから別のクライアント マシンで生成されます (ただし、タイム ゾーンはわかっていると思います)。各イベントには、共通の時刻に正規化されたタイムスタンプがあります (ログ ファイルに適したタイムゾーンで各ログ パーサーのカレンダー インスタンスをインスタンス化し、getTimeInMillis を使用して UTC 時刻を取得することにより)。ログはすでにタイムスタンプでソートされています。複数のイベントが同時に発生する可能性がありますが、それらは決して同等のイベントではありません。

これらのファイルは、1 つのログに 500000 以上のイベントが含まれるなど、比較的大きくなる可能性があるため、ログの内容全体を単純な Event[] に読み込むことはできません。

私がやろうとしているのは、各ログのイベントを単一のログにマージすることです。これはマージソート タスクのようなものですが、各ログは既にソートされているので、それらをまとめる必要があります。2 番目のコンポーネントは、同じイベントが個別のログ ファイルのそれぞれで目撃される可能性があり、ファイル出力ログで「重複したイベントを削除」したいということです。

これは、各ログ ファイルのいくつかの小さなバッファーを順次処理するように、「その場で」実行できますか? すべてのファイルを Event[] に読み込み、リストを並べ替え、重複を削除することはできませんが、これまでのところ、プログラミング能力が限られているため、これを解決策と見なすことしかできません。各ログから同時にイベントを読み取るときに、これを行うために使用できるより洗練されたアプローチはありますか?

4

6 に答える 6

11
  1. 各ログ ファイルから最初の行を読み取る

  2. ループ

    を。「最も早い」行を見つけます。

    b. マスター ログ ファイルに「最も早い」行を挿入する

    c. 最初の行を含むファイルから次の行を読み取る

b と c の間の重複をチェックして、それらの各ファイルのポインターを進めることができます。

于 2008-09-24T16:09:10.177 に答える
5

はい - すべてのログ ファイルを開きます。それぞれの最初の行を「現在の」行の配列に読み込みます。次に、現在の配列からタイムスタンプが最も低い行を繰り返し選択します。それを出力に書き込み、適切なソースファイルから新しい行を読み取って置き換えます。

これは Python の例ですが、これも適切な疑似コードになります。

def merge_files(files, key_func):
    # Populate the current array with the first line from each file
    current = [file.readline() for file in files]
    while len(current) > 0:
        # Find and return the row with the lowest key according to key_func
        min_idx = min(range(len(files)), key=lambda x: return key_func(current[x]))
        yield current[min_idx]
        new_line = files[min_idx].readline()
        if not new_line:
            # EOF, remove this file from consideration
            del current[min_idx]
            del files[min_idx]
        else:
            current[min_idx] = new_line
于 2008-09-24T16:09:14.140 に答える
1

このリンクをチェックしてください: http://www.codeodor.com/index.cfm/2007/5/10/Sorting-really-BIG-files/1194

  • (配列に基づく) ヒープを使用します。このヒープ/配列の要素数は、ログ ファイルの数と同じになります。

  • すべてのファイルから最初のレコードを読み取り、ヒープに挿入します。

  • ループするまで (どのファイルにもレコードがなくなるまで)

      > ヒープから最大要素を削除
      > 出力に書き出す
      > (前の) max 要素が属していたファイルから次のレコードを読み取る
          そのファイルにそれ以上レコードがない場合
              ファイルリストから削除
              継続する
      > (前の) max 要素と同じでない場合は、ヒープに追加します

これで、すべてのイベントが 1 つのログ ファイルにまとめられ、並べ替えられ、重複がなくなりました。アルゴリズムの時間計算量は (n log k) です。ここで、n はレコードの総数、k はログ ファイルの数です。

時間を最適化するために、ファイルとの間で読み取りを行う場合は、バッファー付きリーダー オブジェクトとバッファー付きライター オブジェクトを使用して、ディスクの読み取りと書き込みの回数を最小限に抑える必要があります。

于 2009-06-29T00:51:36.300 に答える
1

1 つのログ エントリに複数の行があるいくつかのログ ファイルを時系列にマージする必要がありました (Java アプリケーションはこれを頻繁に行います - それらのスタック トレースは同じです)。シンプルな shell+perl スクリプトを実装することにしました。それは私たちの仕事をカバーしています。興味がある場合は、http://code.google.com/p/logmerge/のリンクをたどってください。

于 2012-06-25T06:26:30.753 に答える
0

または、オープンソースのウェブサイト統計ツールであるAwstatsからログマージユーティリティを借りることもできます。

logresolvemerge.plは、複数のログファイルをマージできるperlスクリプトです。複数のスレッドを使用してログファイルをマージすることもできます(マルチスレッドで使用するには、perl 5.8が必要です)。ツールを作成する代わりに、すぐに利用できるツールを使用してみませんか?

于 2008-09-24T19:00:02.403 に答える
0

両方のソース ファイルから一度に 1 行だけ読み取ります。行を比較し、古い行を出力ファイルに書き込みます (そして次の行に進みます)。両方のファイルの最後に到達し、ファイルをマージするまで、これを行います。

そして、重複を必ず削除してください:)

C# のこのコードは、アプローチを示していると思います。

        StringReader fileStream1;
        StringReader fileStream2;
        Event eventCursorFile1 = Event.Parse(fileStream1.ReadLine());
        Event eventCursorFile2 = Event.Parse(fileStream2.ReadLine());

        while !(fileStream1.EOF && fileStream2.EOF)
        {
            if (eventCursorFile1.TimeStamp < eventCursorFile2.TimeStamp)
            {
                WriteToMasterFile(eventCursorFile1);
                eventCursorFile1 = Event.Parse(fileStream1.ReadLine());
            }
            else if (eventCursorFile1.TimeStamp == eventCursorFile2.TimeStamp)
            {
                WriteToMasterFile(eventCursorFile1);
                eventCursorFile1 = Event.Parse(fileStream1.ReadLine());
                eventCursorFile2 = Event.Parse(fileStream2.ReadLine());
            }
            else
            {
                WriteToMasterFile(eventCursorFile1);
                eventCursorFile2 = Event.Parse(fileStream2.ReadLine());
            }  
        }

これは単に Quick'n'dirty であるため、ブレーク条件は正確ではありませんが、似ているはずです..

于 2008-09-24T16:15:25.950 に答える