0

私はこのウェブサイトを検索していて、時間デルタへの複数の参照を見てきましたが、私が探しているものを完全には見つけられませんでした。

基本的に、通信サーバーによって受信されるメッセージのリストがあり、各メッセージの送信と受信の間の待ち時間を計算したいと思います。次のようになります。

161336.934072 - TMsg out: [O] enter order. RefID [123] OrdID [4568]
161336.934159 - TMsg in: [A] accepted. ordID [456]  RefNumber [123] 

これらのメッセージと混ざり合っているのは他のメッセージでもありますが、私はOutメッセージと同じRefIDを持つメッセージの違いだけをキャプチャしたいと思います。

これまでのところ、メインログからどのメッセージがTmessagesであるかを整理するためにこれを行ってきましたが、実際には非効率的です。毎回新しいファイルを作成する必要はありません。:

big_file = open('C:/Users/kdalton/Documents/Minicomm.txt', 'r')
small_file1 = open('small_file1.txt', 'w')
for line in big_file:
    if 'T' in line: small_file1.write(line)
big_file.close()
small_file1.close()

2つのメッセージ間の時間デルタを計算し、メインログからこれらのメッセージを分類するにはどうすればよいですか?

4

2 に答える 2

1

まず、生のログ行を書き出さないでください。次に、dictを使用します。

tdeltas = {} # this is an empty dict
if "T" in line:
   get Refid number
   if Refid in tedeltas:
      tdeltas[Refid] = timestamp - tdeltas[Refid]
   else:
      tdeltas[Refid] = timestamp

そして最後に、リストに変換して印刷します

allRefids = sorted(tdeltas.keys())
for k in allRefids:
   print k+": "+tdeltas[k]+" secs"

timeモジュールから日付をオブジェクトに変換してから、 datetimetimedeltaオブジェクトを使用してdictに格納することをお勧めします。このタスクにはおそらく価値がありませんが、datetimeモジュールの使用方法を学ぶことは価値があります。

また、入力文字列からのRefidの解析と、時間を文字列から浮動小数点に変換したり戻したりする際に発生する可能性のある問題についても詳しく説明しました。

実際、受け入れられないRefidがある場合、デルタを保存するだけで混乱が生じます。これを実際に行っている場合は、開始日時、終了日時、およびデルタを含む値にタプルを格納します。新しいレコードの場合、次のようになります。(161336.934072,0,0)受け入れが検出された後は、次のようになります(161336.934072,161336.934159,.000087)。ロギングアクティビティが継続している場合、たとえば24時間年中無休で実行されているグローバルeコマースサイトの場合、デルタがゼロ以外のエントリがないか定期的にdictをスキャンし、レポートして削除します。次に、残りの値を取得し、開始日時で並べ替えてから、開始日時が古すぎる場合はレポートして削除します。これは、失敗したトランザクションが完了しないことを示しているためです。

また、実際のeコマースサイトでは、RedisやMemcacheなどを外部のdictとして使用して、別のサーバー/アプリケーションでレポートとメンテナンスを実行できるようにすることを検討するかもしれません。

于 2011-11-23T17:47:11.623 に答える
0

このジェネレーター関数は、IDと、outメッセージとinメッセージのタイムスタンプの違いを含むタプルを返します。(時差を使ってもっと複雑なことをしたい場合は、チェックしてくださいdatetime.timedelta)。これは、outメッセージが常にメッセージの前に表示されることを前提としていることに注意してください。

def get_time_deltas(infile):
    entries = (line.split() for line in open(INFILE, "r"))
    ts = {} 
    for e in entries:
        if len(e) == 11 and " ".join(e[2:5]) == "TMsg out: [O]":
            ts[e[8]] = e[0]   # store timestamp for id
        elif len(e) == 10 and " ".join(e[2:5]) == "TMsg in: [A]":   
            in_ts, ref_id = e[0], e[9]
            # Raises KeyError if out msg not seen yet. Handle if required.
            out_ts = ts.pop(ref_id)   # get ts for this id
            yield (ref_id[1:-1], float(in_ts) - float(out_ts))

これで、リストを取得できます。

>>> INFILE = 'C:/Users/kdalton/Documents/Minicomm.txt'
>>> list(get_time_deltas(INFILE))
[('123', 8.699999307282269e-05), ('1233', 0.00028700000257231295)]

または、ファイルに書き込みます。

>>> with open("out.txt", "w") as outfile:
...     for id, td in get_time_deltas(INFILE):
...          outfile.write("Msg %s took %f seconds\n", (id, td))

または、より複雑なワークフローにチェーンします。


アップデート:

(実際のデータを見て)

代わりにこれを試してください:

def get_time_deltas(infile):
    entries = (line.split() for line in open(INFILE, "r"))
    ts = {} 
    for e in entries:
        if " ".join(e[2:5]) == "OuchMsg out: [O]":
            ts[e[8]] = e[0]   # store timestamp for id
        elif " ".join(e[2:5]) == "OuchMsg in: [A]":   
            in_ts, ref_id = e[0], e[7]
            out_ts = ts.pop(ref_id, None)   # get ts for this id
            # TODO: handle case where out_ts = None (no id found)
            yield (ref_id[1:-1], float(in_ts) - float(out_ts))

INFILE = 'C:/Users/kdalton/Documents/Minicomm.txt'
print list(get_time_deltas(INFILE))

このバージョンでの変更点:

  • フィールドの数は、問題の投稿されたサンプル入力に記載されているものとは異なります。エントリ番号に基づいてチェックを削除しました
  • ordIDメッセージの場合は、メッセージinで一致するものrefIDですout
  • OuchMsg代わりに使用TMsg

アップデート2

デルタの平均を取得するには:

deltas = [d for _, d in get_time_deltas(INFILE)] 
average = sum(deltas) / len(deltas)

または、以前にすべてのデータを含むリストを生成したことがある場合は、ファイルを再解析する代わりにそれを再利用できます。

data = list(get_time_deltas(INFILE))
# .. use data for something some operation ...

# calculate average using the list
average = sum(d for _, d in data) / len(data)
于 2011-11-23T18:04:27.543 に答える