2013-01-10 55 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