大多数网站托管(Web hosting)公司都支持客户对Web站点统计数据的访问,但是你往往会觉得服务器所产生的状态信息不够全面。例如,配置不正确的Web服务器不能识别某些文件类型,这些类型的文件就不会出现在状态信息之中。幸好,你可以用PHP来定制状态信息收集程序,这样你就可以获取你所需要的信息了。
公共日志文件格式(Common Logfile Format,CLF)的结构
CLF最初是NCSA为HTTPd(全球网服务器软件)而设计的。CERN HTTPd是一个由万维网联盟(World Wide Web Consortium,W3C)维护的公共域Web服务器。W3C网站列出了该日志文件规范。基于微软和UNIX的Web服务器都可以生成CLF格式的日志文件。CLF格式如下:
Host IdentAuthuserTime_Stamp "request" Status_codeFile_size
例如:
21.53.48.83 - - [22/Apr/2002:22:19:12 -0500] "GET /cnet.gif HTTP/1.0" 200 8237
下面是日志条目的细目分类:
Host是网站访问者的IP地址或者DNS名;在上面的例子中,它是21.53.48.83。
Ident是该访客的远端身份(RFC 931)。破折号表明“未指定”。
Authuser是用户ID(如果Web服务器已经验证了验证网站访问者的身份的话)。
Time_Stam是服务器以“日/月/年”这种格式返回的时间。
Request是网站访问者的HTTP请求,例如GET或者POST。
Status_Code是服务器所返回的状态代码,例如:200代表“正确——浏览器请求成功”。
File_Size是用户所请求文件的大小。在本例中,它为 8237字节。
服务器状态代码
你可以在HTTP标准中找到W3C所开发的服务器状态代码规范。这些由服务器所产生的状态代码表示了浏览器和服务器之间的数据传输成功与否。这些代码一般传递给浏览器(例如非常有名的404错误“页面没有找到“)或者添加到服务器日志中去。
收集数据
创建我们的自定义应用程序的第一步就是获取用户数据。每当用户选择网站的某个资源时,我们就希望创建一个对应的日志条目。幸好,服务器变量的存在使得我们能够查询用户浏览器并获取数据。
报头中的服务器变量携带了从浏览器传递到服务器的信息。REMOTE_ADDR就是一个服务器变量的例子。这个变量返回了用户的IP地址:
例子输出:27.234.125.222
下面的PHP代码将显示出当前用户的IP地址:
让我们看看我们的PHP应用程序的代码。首先,我们需要定义我们想跟踪的网站资源并指定文件大小:
//获取我们想记录的文件名称
$fileName="cnet-banner.gif";
$fileSize="92292";
你无需把这些值保存到静态变量中去。如果你要跟踪许多条目,那么你可以把它们保存到数组或者数据库中去。在这种情况下,你可能会希望通过一个外部链接来找到每个条目,如下所示:
其中“123”表示“cnet-banner.gif”所对应的记录。然后,我们通过服务器变量来查询用户浏览器。这样我们就得到在我们的日志文件中添加新条目所需的数据:
//得到网站浏览者的CLF信息
$host=$_SERVER['REMOTE_ADDR'];
$ident=$_SERVER['REMOTE_IDENT'];
$auth=$_SERVER['REMOTE_USER'];
$timeStamp=date("d/M/Y:H:i:s O");
$reqType=$_SERVER['REQUEST_METHOD'];
$servProtocol=$_SERVER['SERVER_PROTOCOL'];
$statusCode="200";
然后,我们检查服务器是否返回了空值(null)。根据CLF规范,空值应该用破折号来代替。这样,下一个代码块的任务就是寻找空值并用破折号来取代它:
//给空值添加破折号(根据规范)
if ($host==""){ $host="-"; }
if ($ident==""){ $ident="-"; }
if ($auth==""){ $auth="-"; }
if ($reqType==""){ $reqType="-"; }
if ($servProtocol==""){ $servProtocol="-"; }
一旦我们获取了必要的信息,这些值将被组织成一种符合CLF规范的格式:
//创建CLF格式的字符串
$clfString=$host." ".$ident." ".$auth." [".$timeStamp."] \"".$reqType." /".$fileName." ".$servProtocol."\" ".$statusCode." ".$fileSize."\r\n";
カスタム ログ ファイルを作成する
これで、フォーマットされたデータをカスタム ログ ファイルに保存できます。まず、ファイルの命名規則を作成し、毎日新しいログ ファイルを生成するメソッド (関数) を作成します。この記事の例では、各ファイルは「weblog-」で始まり、その後に月/日/年の日付が続き、ファイル拡張子は .log です。 .log 拡張子は通常、サーバー ログ ファイルを示します。 (実際、ほとんどのログ アナライザーは .log ファイルを検索します。)
// 現在の日付を使用してログ ファイルに名前を付けます
$logPath="./log/";
$logFile=$logPath."weblog-". mdy").".log";
次に、現在のログ ファイルが存在するかどうかを確認する必要があります。存在する場合は、エントリを追加します。存在しない場合は、アプリケーションが新しいログ ファイルを作成します。 (この時点でファイル名が変更されるため、通常、新しいログ ファイルの作成は日付が変わるときに行われます。)
//ログ ファイルが既に存在するかどうかを確認します
if (file_exists($logFile)){
// 存在する場合、それを開きます 既存のログファイル
$fileWrite = fopen($logFile,"a");}
else {
//それ以外の場合は、新しいログファイルを作成します
$fileWrite = fopen($logFile,"w"); }
ファイルへの書き込みまたは追加時に「アクセス許可が拒否されました」エラー メッセージが表示された場合は、対象のログ フォルダーのアクセス許可を書き込みを許可するように変更します。ほとんどの Web サーバーのデフォルトの権限は「読み取り可能および実行可能」です。フォルダーのアクセス許可は、CHMOD コマンドまたは FTP クライアントを使用して変更できます。
次に、2 人以上のユーザーが同時にログ ファイルにアクセスしたときに、そのうちの 1 人だけがファイルに書き込めるようにファイル ロック メカニズムを作成します。
//ファイル書き込み操作用のロック メカニズムを作成する
flock( $fileWrite, LOCK_SH);
最後に、エントリの内容を書き込みます:
//CLF エントリを書き込みます
fwrite($fileWrite,$clfString);
//ファイルのロック状態を解除します
flock($fileWrite, LOCK_UN) );
//ログ ファイルを閉じる
fclose($fileWrite);
ログ データを処理する
システムが商用化された後、顧客は収集された訪問者データの詳細な統計分析を希望します。すべてのカスタム ログ ファイルは標準形式で編成されているため、どのログ アナライザーでも処理できます。 Log Analyzer は、大規模なログ ファイルを分析し、円グラフ、ヒストグラム、その他の統計グラフィックを作成するツールです。ログ アナライザーは、データを収集し、どのユーザーが Web サイトにアクセスしたか、クリック数などに関する情報を統合するためにも使用されます。
いくつかの人気のあるログ アナライザーを以下に示します:
WebTrends は非常に優れたログ アナライザーであり、大規模な Web サイトやエンタープライズ レベルのネットワークに適しています。
Analog は、人気のある無料のログ アナライザーです。
Webalizer は無料の分析プログラムです。ほとんどの Web ブラウザでレポートを表示できるように、HTML レポートを生成できます。
標準準拠
他のタイプのロギングをサポートするようにアプリケーションを簡単に拡張できます。この方法により、ブラウザの種類や参照元 (参照元とは、現在の Web ページにリンクされていた前の Web ページを指します) など、より多くのデータを取得できます。ここでの教訓は、プログラミングするときに標準や慣例に従うことで、最終的に仕事が楽になるということです。