0

以下のPHPコードに基づいてWebページビューアのログをキャプチャしていました...

$viewerlog = "../SiteLogFiles/live-smoothstreaming-" . date('Ymd') . ".txt";
$fp = fopen($viewerlog,"a");
if ($fp) {
    fputs($fp,"-----------------------------------------------------------------------\r\n");
    fputs($fp,"Server Date:           $now\r\n");
    fputs($fp,"IP Address:            $ip\r\n");
    fputs($fp,"City:                  $city\r\n");
    fputs($fp,"State:                 $state\r\n");
    fputs($fp,"Country Name:          $countryname\r\n");
    fputs($fp,"Continent:             $continent\r\n");
    fputs($fp,"-----------------------------------------------------------------------\r\n");
    fclose($fp);
}

そして、それはこのようなログを生成します...

-----------------------------------------------------------------------
Server Date:           2013-01-06T05:32:06-06:00
IP Address:            157.55.32.61
City:                  Unknown
State:                 Unknown
Country Name:          United States
Continent:             North America
-----------------------------------------------------------------------
-----------------------------------------------------------------------
Server Date:           2013-01-06T06:02:40-06:00
IP Address:            157.55.32.187
City:                  Unknown
State:                 Unknown
Country Name:          United States
Continent:             North America
-----------------------------------------------------------------------

しかし、時折、ログが破損して次のようになります...

-----------------------------------------------------------------------
Server Date:           2012-12-21T18:27:27-06:00
IP Address:            99.54.103.128
City:                  Columbus
State:                 Ohio
Country Name:          United States
Continent:             North America
-----------------------------------------------------------------------
-----------------------------------------------------------------------
Server Date:           2012-12-21T18:27:53-06:00
IP Address:            75.97.98.115
City:                  Palmerton
State:                 Pennsylvania
--------------------------------------Continent:             North America
Server Date:           2012-12-21T18:27:54-06:00
---------------------
IP Address:            70.76.36.232
City:                  Saskatoon
State:                 Saskatchewan
Country Name:          Canada
Continent:             North America
-----------------------------------------------------------------------
-----------------------------------------------------------------------
Server Date:           2012-12-21T18:28:04-06:00
IP Address:            173.17.240.190
City:                  Springfield
State:                 Missouri
Country Name:          United States
Continent:             North America
-----------------------------------------------------------------------

IP アドレスから位置情報を取得するためにhttp://www.easyjquery.comを使用していることに注意してください。

そのため、さまざまな人が、フラット テキスト ログの代わりに SQL データベースをログに使用することを推奨しました。これらの推奨事項により、前述の SQL データベースをセットアップすることができました。問題なく、1 秒で (F5 を押すのと同じ速さで) 7 つのレコードを書き込むことができました。

使用中のPHPコードは次のとおりです...

try {
    $dbh = new PDO("sqlsrv:Server=localhost;Database=ViewerLogs", "", "");
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $stmt = $dbh->query("INSERT INTO dbo.LiveSmoothStreaming (DateTime, Ip, City, State, Country, Continent) VALUES('$now', '$ip', '$city', '$state', '$countryname', '$continent')");
    $stmt->setFetchMode(PDO::FETCH_ASSOC);
    $dbh = null;
}
catch(PDOException $e) {
    echo $e->getMessage();
}

ただし、1 つ問題があります。私のフラット テキスト ログは、SQL ログよりも多くのレコードをキャプチャしているようです。

フラット テキスト ログが生成されています...

Tue 5:58pm  68.55.34.32 Laurel      Maryland    United States   North America
Tue 5:58pm  70.88.57.62 Port Charlotte  Florida United States   North America
Tue 5:59pm  98.19.198.54    Eastview        Kentucky    United States   North America
Tue 5:59pm  71.3.202.110    Cape Coral      Florida United States   North America
Tue 5:59pm  173.218.32.154  Branson     Missouri    United States   North America
Tue 5:59pm  184.38.238.64   Unknown     Unknown United States   North America
Tue 5:59pm  67.239.18.161   Naples      Florida United States   North America

そして、SQLログが生成されています...

2013-02-05T17:58:45-06:00   68.55.34.32 Laurel      Maryland    United States   North America
2013-02-05T17:58:52-06:00   70.88.57.62 Port Charlotte  Florida     United States   North America
2013-02-05T17:59:06-06:00   71.3.202.110    Cape Coral  Florida     United States   North America
2013-02-05T17:59:23-06:00   67.239.18.161   Naples      Florida     United States   North America

ほんの数分で、違いがあることがわかります。数時間の間に、違いは数百になる可能性があります。

この特定のフラット テキスト ログには破損がなかったので、どうして間違っているのかわかりません。これは、SQL ログの問題を示しています。問題の可能性がないか PHP エラー ログを調べましたが、明らかな問題は見つかりませんでした (問題のページを検索して、それらのエラーを調べただけです)。

SQL がフラット テキスト ログのレコードをキャプチャしない理由について何か考えはありますか? 私のコードでは、SQL ロギングはフラット テキスト ロギングの直後に行われます (フラット テキストの前に SQL を配置すると、逆の結果が生じるのではないでしょうか?)。

4

1 に答える 1

1

私が見る限り、ファイル ロックまたは syslog のいずれかを使用できます。アプリに途切れのないテキストブロックを書き込みたいと思われるので、ロックすることをお勧めします。

$lockwait = 2;       // seconds to wait for lock
$waittime = 250000;  // microseconds to wait between lock attempts
// 2s / 250000us = 8 attempts.
$myfile = '/path/to/file.log';

if( $fh = fopen($myfile, 'a') ) {
  $waitsum = 0;
  // attempt to get exclusive, non-blocking lock
  $locked = flock($fh, LOCK_EX | LOCK_NB); 
  while( !$locked && ($waitsum <= $lockwait) ) {
    $waitsum += $waittime/1000000; // microseconds to seconds
    usleep($waittime);
    $locked = flock($fh, LOCK_EX | LOCK_NB);
  }
  if( !$locked ) {
    echo "Could not lock $myfile for write within $lockwait seconds.";
  } else {
    // write out your data here
    flock($fh, LOCK_UN);  // ALWAYS unlock
  }
  fclose($fh);            // ALWAYS close your file handle
} else {
  echo "Could not open $myfile";
  exit 1;
}

この少し複雑なアルゴリズムを使用して、TCP および CSMA/CD が輻輳を回避するために使用するものと同様のランダムな「バックオフ」待機を行うこともできます。

$max_wait   = 1000000; //  1 s

$min_interval = 10000; // 10 ms
$max_interval = 50000; // 50 ms

$cur_wait = $min_interval;
$tot_wait = 0;
$locked = flock($fh, LOCK_EX | LOCK_NB); 

while( !$locked && ($tot_wait <= $max_wait) ) {
  tot_wait += $cur_wait;
  usleep($cur_wait);
  cur_wait += rand($min_interval, $max_interval);
  $locked = flock($fh, LOCK_EX | LOCK_NB);
}
if( !$locked ) {
  echo "Could not lock $myfile for write within $lockwait seconds.";
} else {
  // write out your data here
  flock($fh, LOCK_UN);
}
fclose($fh);

$max_waitロックを取得できない場合、スクリプトは、で定義された時間を超えるまで、ロック試行間の待機時間を徐々に長くします。

これをすべて書いた後、これらすべてをデータベースに挿入することを検討したいと思うかもしれません。ログファイルが必要な場合は、1日に1回cronジョブを実行して、ファイルを一度に書き出し、オプションで空にしますテーブル。

于 2013-01-10T20:50:59.213 に答える