2013-01-10 54 views
0

我是根據下面的PHP代碼捕獲網頁瀏覽器日誌...PHP創建的日誌越來越損壞而寫

$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 
----------------------------------------------------------------------- 

這可能是值得指出的是,我使用的USI ng http://www.easyjquery.com從IP地址獲取位置信息。

因此,不同的人建議使用SQL數據庫進行日誌記錄,而不是平面文本日誌。有了這些建議,我就可以建立所述的SQL數據庫。我能夠在1秒內寫出7條記錄(儘可能快地達到F5),沒有問題。

在使用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(); 
} 

有一個問題,雖然。我的平面文本日誌似乎捕獲比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會產生相反的結果?)。

+1

我想你可能是對的,認爲這是一個併發問題。您可能會考慮使用簡單的日誌記錄框架,如已經整理了這些問題的kLogger。 – glomad

+1

有很多事情可能會中斷腳本,尤其是因爲您依賴客戶端代碼(通過ip腳本執行jQuery位置)來生成日誌內容。如果您正在使用這些日誌來生成分析,是否有一個原因,您不會使用數據庫或至少將它們保存爲鍵值序列(JSON)? – DeaconDesperado

+1

可能是一個併發問題。使用flock或者只是使用像mysql這樣的數據庫服務器來完成整個混亂,同時獲得穩健性和功能性,從而實現最小的開銷。 – goat

回答

1

據我所見,你可以使用文件鎖定或系統日誌。既然你似乎想讓你的應用程序寫不間斷的文本塊,我認爲鎖定是明智的。

$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定義的時間超出。

寫完所有這些後,我想你可能只是想考慮將所有這些插入到數據庫中,並且如果你需要一個日誌文件,那麼每天有一個cron作業運行一次,以便一次寫出文件,並可以選擇清空表格。

+0

我不特別需要一個日誌文件。它就在那裏,因爲這就是寫的東西。如果它在數據庫中,我可以從中查詢。 – doubleJ

+1

那麼,對於併發寫入數據集合,最好的解決方案當然是使用數據庫。 – Sammitch

+0

我只是想說明我已經創建了一個數據庫,並用一個新問題更新了我的問題。 – doubleJ