nginx lua を使用してウェブサイト統計のデータを収集する方法

WBOY
リリース: 2023-05-28 17:32:48
転載
851 人が閲覧しました

ウェブマスターや運営者はウェブサイトのデータ分析ツールをよく使用します。Google Analytics、Baidu Statistics、Tencent Analytics などが広く使用されています。統計データを収集したい場合は、まずデータを収集する必要があります。の原則を分析しましょう。以下のデータ収集を行い、データ収集システムを構築します。

データ収集原理分析

簡単に言うと、Web サイト統計分析ツールは、ターゲット Web サイトを閲覧するユーザーの行動 (特定の Web サイトを開くなど) を収集する必要があります。ウェブページ、特定のボタンのクリック、ショッピングカートへの商品の追加など)および追加の行動データ(注文行動によって生成された注文金額など)。初期の Web サイト統計では、ページを開くという 1 つのユーザー行動のみが収集されることがよくありました。そうなると、ページ上でのユーザーの行動は収集できなくなります。この収集戦略は、基本的なトラフィック分析、ソース分析、コンテンツ分析、訪問者属性などの一般的な分析視点に対応できますが、Ajax 技術や EC サイトの普及に伴い、EC ターゲットの統計分析の需要が高まっています。ますます強くなっているため、この伝統的な収集戦略はその能力を超えています。
その後、Google は自社製品である Google Analytics にカスタマイズ可能なデータ収集スクリプトを革新的に導入しました。Google Analytics によって定義された拡張可能なインターフェイスを通じて、ユーザーは少量の JavaScript コードを記述するだけでカスタム イベントとカスタマイズを実装できます。データの追跡と分析を定義します。メトリクス。現在、Baidu Statistics や Sogou Analytics などの製品が Google Analytics モデルをコピーしています。
実際には、2 つのデータ収集モードの基本原理とプロセスは同じですが、後者のモードでは JavaScript を通じてより多くの情報が収集されます。今日は、さまざまな Web サイト統計ツールのデータ収集の基本原則を見てみましょう。

プロセスの概要

まず、ユーザーの動作により、ブラウザからカウント対象のページへの http リクエストがトリガーされます。その動作が、ウェブページ。 Web ページが開かれると、ページに埋め込まれた JavaScript スニペットが実行されます。関連ツールを使用したことのある友人は、一般的な Web サイト統計ツールを使用するには、ユーザーが Web ページに小さな JavaScript コードを追加する必要があることを知っているはずです。このコード スニペットは、通常、script. タグが動的に作成され、src が別の js ファイルを指します。このとき、この別の js ファイル (図 1 の緑色のノード) がブラウザによって要求され、実行されます。この js は多くの場合、実際のデータ コレクションです脚本。データ収集が完了すると、js はバックエンド データ収集スクリプト (図 1 のバックエンド) を要求します。このスクリプトは通常、画像に見せかけた動的スクリプト プログラムであり、php、python、またはその他のサーバー側で記述される場合があります。収集されたデータは、http パラメータを介してバックエンド スクリプトに渡されます。バックエンド スクリプトはパラメータを解析し、固定形式でアクセス ログに記録します。同時に、追跡用の Cookie が一部保存される場合があります。クライアントへの http 応答に埋め込まれます。
上記はデータ収集の一般的なプロセスですが、以下では Google Analytics を例として、各段階の比較的詳細な分析を実行します。

埋め込みスクリプト実行フェーズ

Google Analytics (以下、GA) を利用するには、Google Analytics が提供する JavaScript フラグメントをページに挿入する必要があります。よく使われるのは埋め込みコードと呼ばれるものです。

_gaq は GA のグローバル配列であり、さまざまな構成を配置するために使用されます。各構成の形式は次のとおりです:

_gaq.push([‘Action’, ‘param1&rsquo ;, ‘param2’ , …]);

Action は構成アクションを指定し、その後に関連パラメーターのリストが続きます。 GA が提供するデフォルトの埋め込みコードには、2 つのプリセット設定が用意されています。_setAccount は、GA の登録時に割り当てられる Web サイトの識別 ID を設定するために使用されます。 _trackPageview は、ページ訪問を追跡するように GA に指示します。構成の詳細については、https://developers.google.com/analytics/devguides/collection/gajs/ を参照してください。実際、この _gaq は FIFO キューとして使用されており、埋め込みコードの前に設定コードを記述する必要はありません。詳細については、上記のリンクの手順を参照してください。
この記事に関する限り、_gaq のメカニズムには焦点が当てられていません。焦点はその背後にある匿名関数のコードにあります。これが埋め込まれたコードが実際に行う必要があることです。このコードの主な目的は、document.createElement メソッドを通じてスクリプトを作成し、プロトコル (http または https) に従って src を対応する ga.js にポイントすることにより、外部 js ファイル (ga.js) を導入することです。この要素を追加 ページの DOM ツリーに挿入します。
ga.async = true は、外部 js ファイルを非同期的に呼び出すこと、つまりブラウザの解析をブロックせず、外部 js ファイルのダウンロードが完了した後に非同期で実行することを意味することに注意してください。この属性は HTML5 で新たに導入されました。

データ収集スクリプトの実行フェーズ

データ収集スクリプト (ga.js) は、要求された後に実行されます。このスクリプトは通常、次のことを行います:
1. ブラウザーの組み込み JavaScript オブジェクトを通じて、ページ タイトルなどの情報を収集します (ドキュメントを通じて) .title )、リファラー (前の URL、document.referrer 経由)、ユーザー モニターの解像度 (windows.screen 経由)、Cookie 情報 (document.cookie 経由)、およびその他の情報。
2. _gaq を解析して構成情報を収集します。これには、ユーザー定義のイベント追跡、ビジネス データ (電子商取引 Web サイトの製品番号など) が含まれる場合があります。
3. 事前定義された形式に従って、上記の 2 つの手順で収集されたデータを解析して結合します。
4. バックエンド スクリプトをリクエストし、その情報を http リクエスト パラメータに入れてバックエンド スクリプトに渡します。
ここでの唯一の問題はステップ 4 です。JavaScript がバックエンド スクリプトをリクエストする一般的な方法は ajax ですが、ajax はクロスドメイン リクエストを行うことができません。ここで、ga.js はカウント対象の Web サイトのドメインで実行され、バックエンド スクリプトは別のドメインで実行されます (GA のバックエンド統計スクリプトは http://www.google-analytics.com/__utm.gif)。そしてajaxは機能しません。一般的な方法は、js スクリプトで Image オブジェクトを作成し、Image オブジェクトの src 属性をバックエンド スクリプトにポイントしてパラメータを渡すことであり、このとき、バックエンドへのクロスドメイン リクエストが実装されます。バックエンド スクリプトが gif ファイルに偽装されることが多いのはこのためです。 http パケット キャプチャを通じて、__utm.gif に対する ga.js のリクエストを確認できます。

ga.js が __utm.gif をリクエストするときに多くの情報を提供することがわかります。たとえば、utmsr=1280×1024 は画面解像度、utmac=UA-35712773-1 は _gaq から解析された値です。 GA の識別 ID など。
__utm.gif は、隠しコードが実行されたときにのみ要求されるわけではないことに注意してください。イベント追跡が _trackEvent で構成されている場合、このスクリプトはイベントの発生時にも要求されます。
ga.jsは圧縮・難読化されており可読性が非常に低いため解析は省略し、後の実装段階で同様の機能を持ったスクリプトを実装します。

バックエンド スクリプト実行フェーズ

GA の __utm.gif は、gif に見せかけたスクリプトです。この種のバックエンド スクリプトは通常、次のことを完了する必要があります:
1. http リクエスト パラメーターの情報を解析します。
2. 訪問者の IP など、クライアントが取得できない情報をサーバー (WebServer) から取得します。
3. フォーマットに従って情報をログに書き込みます。
4. 1×1 の空の gif 画像を応答コンテンツとして生成し、応答ヘッダーの Content-type を image/gif に設定します。
5. Set-cookie を使用して、応答ヘッダーに必要な Cookie 情報を設定します。
Cookie が設定される理由は、一意の訪問者を追跡する場合、通常のアプローチでは、リクエスト中にクライアントが指定された追跡 Cookie を持たない場合、ルールに従ってグローバルに一意の Cookie が生成され、埋め込まれるためです。ユーザーに送信するか、それ以外の場合は Set-cookie 取得した追跡 Cookie を配置して、同じユーザー Cookie を変更しないようにします (図 4 を参照)。

このアプローチは完璧ではありませんが (たとえば、Cookie をクリアしたりブラウザを変更したユーザーは 2 人のユーザーとみなされます)、現在広く使用されている方法です。サイト間で同じユーザーを追跡する必要がない場合は、js を使用して、カウントされる Web サイトのドメインの下に Cookie を植えることができます (GA はこれを行います)。ネットワーク全体を均一に配置したい場合は、Cookie を植えることができますバックエンド スクリプトを介してサーバー ドメインで次へ (実装は後でこれを行います)。

システムの設計と実装

上記の原則に基づいて、アクセスログ収集システムを自分で構築しました。
私はこのシステムを MyAnalytics と呼びます。

収集する情報を決定する

わかりやすくするために、GA の完全なデータ収集モデルを実装するつもりはありませんが、情報を収集します。

埋め込みコード

埋め込みコード GA モデルから学習しますが、現在、構成オブジェクトは FIFO キューとして使用されません。

現在、ma.js という名前の統計スクリプトを使用し、セカンダリ ドメイン名analytics.codinglabs.org を有効にしています。もちろん、ここには小さな問題があります。https サーバーがないため、コードが https サイトにデプロイされると問題が発生しますが、ここでは無視しましょう。

フロントエンド統計スクリプト

あまり完全ではありませんが、基本的な作業を完了できる統計スクリプト ma.js を作成しました:

    (function () {
    var params = {};
    //Document对象数据
    if(document) {
    params.domain = document.domain || '';
    params.url = document.URL || '';
    params.title = document.title || '';
    params.referrer = document.referrer || '';
    }
    //Window对象数据
    if(window && window.screen) {
    params.sh = window.screen.height || 0;
    params.sw = window.screen.width || 0;
    params.cd = window.screen.colorDepth || 0;
    }
    //navigator对象数据
    if(navigator) {
    params.lang = navigator.language || '';
    }
    //解析_maq配置
    if(_maq) {
    for(var i in _maq) {
    switch(_maq[i][0]) {
    case '_setAccount':
    params.account = _maq[i][1];
    break;
    default:
    break;
    }
    }
    }
    //拼接参数串
    var args = '';
    for(var i in params) {
    if(args != '') {
    args += '&';
    }
    args += i + '=' + encodeURIComponent(params[i]);
    }
    //通过Image对象请求后端脚本
    var img = new Image(1, 1);
    img.src = 'http://analytics.codinglabs.org/1.gif?' + args;
    })();
ログイン後にコピー

スクリプト全体を匿名関数に配置し、地球環境が汚染されていないことを確認します。この機能については原理セクションで説明したので、再度説明しません。このうち 1.gif はバックエンド スクリプトです。

ログ形式

ログは、非表示文字 ^A (ASCII コード 0x01、Linux では Ctrl v Ctrl を使用して入力できます) を使用して、1 行に 1 つのレコードを使用します。 a、以下では、「^A」は非表示文字 0x01 を表すために使用されます。具体的な形式は次のとおりです。
Time^AIP^Aドメイン名^AURL^Aページ タイトル^A参照者^A高解像度^A解像度ワイド^A色深度^ A言語^Aクライアント情報^AUユーザーID^AウェブサイトID

バックエンド スクリプト

为了简单和效率考虑,我打算直接使用nginx的access_log做日志收集,不过有个问题就是nginx配置本身的逻辑表达能力有限,所以我选用了OpenResty做这个事情。OpenResty是一个基于Nginx扩展出的高性能应用开发平台,内部集成了诸多有用的模块,其中的核心是通过ngx_lua模块集成了Lua,从而在nginx配置文件中可以通过Lua来表述业务。关于这个平台我这里不做过多介绍,感兴趣的同学可以参考其官方网站http://openresty.org/,或者这里有其作者章亦春(agentzh)做的一个非常有爱的介绍OpenResty的slide:http://agentzh.org/misc/slides/ngx-openresty-ecosystem/,关于ngx_lua可以参考:https://github.com/chaoslawful/lua-nginx-module。
首先,需要在nginx的配置文件中定义日志格式:
log_format tick “$msec^A$remote_addr^A$u_domain^A$u_url^A$u_title^A$u_referrer^A$u_sh^A$u_sw^A$u_cd^A$u_lang^A$http_user_agent^A$u_utrace^A$u_account”;
注意这里以u_开头的是我们待会会自己定义的变量,其它的是nginx内置变量。
然后是核心的两个location:

    location /1.gif {
    #伪装成gif文件
    default_type image/gif;
    #本身关闭access_log,通过subrequest记录log
    access_log off;
    access_by_lua "
    -- 用户跟踪cookie名为__utrace
    local uid = ngx.var.cookie___utrace
    if not uid then
    -- 如果没有则生成一个跟踪cookie,算法为md5(时间戳+IP+客户端信息)
    uid = ngx.md5(ngx.now() .. ngx.var.remote_addr .. ngx.var.http_user_agent)
    end
    ngx.header['Set-Cookie'] = {'__utrace=' .. uid .. '; path=/'}
    if ngx.var.arg_domain then
    -- 通过subrequest到/i-log记录日志,将参数和用户跟踪cookie带过去
    ngx.location.capture('/i-log?' .. ngx.var.args .. '&utrace=' .. uid)
    end
    ";
    #此请求不缓存
    add_header Expires "Fri, 01 Jan 1980 00:00:00 GMT";
    add_header Pragma "no-cache";
    add_header Cache-Control "no-cache, max-age=0, must-revalidate";
    #返回一个1×1的空gif图片
    empty_gif;
    }
    location /i-log {
    #内部location,不允许外部直接访问
    internal;
    #设置变量,注意需要unescape
    set_unescape_uri $u_domain $arg_domain;
    set_unescape_uri $u_url $arg_url;
    set_unescape_uri $u_title $arg_title;
    set_unescape_uri $u_referrer $arg_referrer;
    set_unescape_uri $u_sh $arg_sh;
    set_unescape_uri $u_sw $arg_sw;
    set_unescape_uri $u_cd $arg_cd;
    set_unescape_uri $u_lang $arg_lang;
    set_unescape_uri $u_utrace $arg_utrace;
    set_unescape_uri $u_account $arg_account;
    #打开日志
    log_subrequest on;
    #记录日志到ma.log,实际应用中最好加buffer,格式为tick
    access_log /path/to/logs/directory/ma.log tick;
    #输出空字符串
    echo '';
    }
ログイン後にコピー

要完全解释这段脚本的每一个细节有点超出本文的范围,而且用到了诸多第三方ngxin模块(全都包含在OpenResty中了),重点的地方我都用注释标出来了,可以不用完全理解每一行的意义,只要大约知道这个配置完成了我们在原理一节提到的后端逻辑就可以了。

日志轮转

日志收集系统需要处理大量的访问日志,在时间的累积下文件规模急剧膨胀,放在同一文件中管理不便。所以通常要按时间段将日志切分,例如每天或每小时切分一个日志。我这里为了效果明显,每一小时切分一个日志。通过 crontab 定时调用一个 shell 脚本,以下是该脚本的内容:

    _prefix="/path/to/nginx"
    time=`date +%Y%m%d%H`
    mv ${_prefix}/logs/ma.log ${_prefix}/logs/ma/ma-${time}.log
    kill -USR1 `cat ${_prefix}/logs/nginx.pid`
ログイン後にコピー

这个脚本将ma.log移动到指定文件夹并重命名为ma-{yyyymmddhh}.log,然后向nginx发送USR1信号令其重新打开日志文件。
然后再/etc/crontab里加入一行:

59 * * * * root /path/to/directory/rotatelog.sh
ログイン後にコピー

在每个小时的59分启动这个脚本进行日志轮转操作。

测试

下面可以测试这个系统是否能正常运行了。我昨天就在我的博客中埋了相关的点,通过http抓包可以看到ma.js和1.gif已经被正确请求。
同时可以看一下1.gif的请求参数。
相关信息确实也放在了请求参数中。
然后我tail打开日志文件,然后刷新一下页面,因为没有设access log buffer, 我立即得到了一条新日志:
1351060731.360^A0.0.0.0^Awww.codinglabs.org^Ahttp://www.codinglabs.org/^ACodingLabs^A^A1024^A1280^A24^Azh-CN^AMozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4^A4d612be64366768d32e623d594e82678^AU-1-1
注意实际上原日志中的^A是不可见的,这里我用可见的^A替换为方便阅读,另外IP由于涉及隐私我替换为了0.0.0.0。

关于分析

通过上面的分析和开发可以大致理解一个网站统计的日志收集系统是如何工作的。有了这些日志,就可以进行后续的分析了。本文只注重日志收集,所以不会写太多关于分析的东西。
注意,原始日志最好尽量多的保留信息而不要做过多过滤和处理。例如上面的MyAnalytics保留了毫秒级时间戳而不是格式化后的时间,时间的格式化是后面的系统做的事而不是日志收集系统的责任。后面的系统根据原始日志可以分析出很多东西,例如通过IP库可以定位访问者的地域、user agent中可以得到访问者的操作系统、浏览器等信息,再结合复杂的分析模型,就可以做流量、来源、访客、地域、路径等分析了。当然,一般不会直接对原始日志分析,而是会将其清洗格式化后转存到其它地方,如MySQL或HBase中再做分析。
分析部分的工作有很多开源的基础设施可以使用,例如实时分析可以使用Storm,而离线分析可以使用Hadoop。当然,在日志比较小的情况下,也可以通过shell命令做一些简单的分析,例如,下面三条命令可以分别得出我的博客在今天上午8点到9点的访问量(PV),访客数(UV)和独立IP数(IP):

    awk -F^A '{print $1}' ma-2012102409.log | wc -l
    awk -F^A '{print $12}' ma-2012102409.log | uniq | wc -l
    awk -F^A '{print $2}' ma-2012102409.log | uniq | wc -l
ログイン後にコピー

以上がnginx lua を使用してウェブサイト統計のデータを収集する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:yisu.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!