OpenX报表模块分析笔记
Table of contents
OpenX报表模块分析笔记 ¶
报表相关数据库 ¶
即时表 ¶
bkt - bucket的略写
- ox_data_bkt_a
- ox_data_bkt_a_var
- ox_data_bkt_c - click 点击 (使用中)
字段名称 备注
interval_start 时间点,每5分钟为一个记录点,该时间点不可配置
creative_id banner_id - 广告编号
zone_id
count 点击次数
keyword
ahid 网站主ID,注意:若为广告交换类型的,网站主自己的广告,该ID才记录;若为CPC类别的,该ID也记录
- ox_data_bkt_country_c (使用中)
- ox_data_bkt_country_m (使用中)
- ox_data_bkt_e - expansions
- ox_data_bkt_m - impression (使用中)
字段名称 备注
interval_start 时间点,每5分钟为一个记录点,该时间点不可配置
creative_id banner_id - 广告编号
zone_id
count 显示次数
keyword
ahid 网站主ID,注意:若为广告交换类型的,网站主自己的广告,该ID才记录;若为CPC类别的,该ID也记录
- ox_data_bkt_r - request
- ox_data_bkt_t - times 展示时间,右侧富媒体用
中间表 ¶
- ox_data_intermediate_ad - the zone impression history table (使用中)
字段名称 备注
data_intermediate_ad_id
date_time 格式如 2010-04-20 19:40
operation_interval 操作时间间隔,可配置
operation_interval_id
interval_start
interval_end
ad_id
creative_id
zone_id
requests
impressions
expansions
times
clicks
conversions
total_basket_value
total_num_items
updated
keyword
ahid
- ox_data_intermediate_ad_connection - the migration of conversions
- ox_data_intermediate_ad_variable_value
汇总表 ¶
- ox_data_summary_ad_hourly (使用中)
- ox_data_summary_ad_zone_assoc
- ox_data_summary_channel_daily
- ox_data_summary_zone_impression_history (使用中)
原始表(暂时没使用) ¶
注意:此表的数据将周期性的被清空
- ox_data_raw_ad_click
- ox_data_raw_ad_impression
- ox_data_raw_ad_request
- ox_data_raw_tracker_impression
- ox_data_raw_tracker_variable_value
统计报表的生成 ¶
统计入口 ¶
- 广告记录 - 入口 www/delivery/lt.php or www/delivery/lg.php
// Run automaintenance, if needed
//注意:只有非LB配置下,而且启用了维护任务,才会触发报表统计功能;分布式方式部署后,将导致auto maintenance配置被禁用
if (!empty($GLOBALS['_MAX']['CONF']['maintenance']['autoMaintenance']) && empty($GLOBALS['_MAX']['CONF']['lb']['enabled'])) {
if (MAX_cacheCheckIfMaintenanceShouldRun()) {
include MAX_PATH . '/lib/OA/Maintenance/Auto.php';
OA_Maintenance_Auto::run();
}
}
- maintenance配置
//#参见/var目录的*.conf.php文件
[maintenance]
autoMaintenance=1 //是否启用自动维护计划: 0 - 不启用 1 - 启用
timeLimitScripts=300 //注意:单位为秒
operationInterval=20 //注意:单位为分钟
blockAdImpressions=0
blockAdClicks=0
channelForecasting=
pruneCompletedCampaignsSummaryData=
- 负载均衡配置 Load balance
[lb]
enabled=
type=mysql
host=localhost
port=3306
username=
password=
name=
persistent=
Maintenance入口 ¶
- 维护入口文件 lib/OA/Maintenance/Auto.php
Auto.php - A library class for providing automatic maintenance process methods.
Maintenance主体文件 ¶
- 维护统计引擎
- 文件 lib/OX/Maintenance.php
- Maintenance的执行 Link: http://www.openx.org/docs/2.4/adminguide/maintenance
Run the Maintenance Statistics Engine (MSE) process
//统计报表调用方法
/**
* A private method to run MSE.
*
* @access private
*/
function _runMSE()
{
$oMaintenanceStatistics = new OX_Maintenance_Statistics();
$oMaintenanceStatistics->run();
}
- MSE实现类 lib/OX/Maintenance/Statistics.php
- 核心成员$oTaskRunner - OA_Task_Runner
/**
* An OA_Task_Runner instance to store the MSE tasks.
*
* @var OA_Task_Runner
*/
var $oTaskRunner;
若有新任务需要扩展,可以通过一下方式扩展
$extendTask = new OX_Maintenance_Statistics_Task_ExtendTask();
$this->addTask($extenTask);
扩展的类置于:lib/OX/Maintenance/Statistics/Task目录
再如现有bucket数据(即使表)的更新,可以通过以下方式完成:
// Register this object as the controlling class for the process,
// so that tasks run by the task runner can locate this class to
// update the report, etc.
$oServiceLocator =& OA_ServiceLocator::instance();
$oServiceLocator->register('Maintenance_Statistics_Controller', $this);
// Create and register an instance of the OA_Dal_Maintenance_Statistics DAL
// class for the following tasks to use
if (!$oServiceLocator->get('OX_Dal_Maintenance_Statistics')) {
$oFactory = new OX_Dal_Maintenance_Statistics_Factory();
$oDal = $oFactory->factory();
$oServiceLocator->register('OX_Dal_Maintenance_Statistics', $oDal);
}
// Add the task to set the update requirements
$oSetUpdateRequirements = new OX_Maintenance_Statistics_Task_SetUpdateRequirements();
$this->oTaskRunner->addTask($oSetUpdateRequirements);
// Add the task to migrate the bucket data into the statistics tables //file statistics.php line 174
$oSummariseIntermediate = new OX_Maintenance_Statistics_Task_MigrateBucketData();
$this->oTaskRunner->addTask($oSummariseIntermediate);
// Add the task to handle the de-duplication and rejection of empty conversions
$oDeDuplicateConversions = new OX_Maintenance_Statistics_Task_DeDuplicateConversions();
$this->oTaskRunner->addTask($oDeDuplicateConversions);
// Add the task to handle the updating of "intermediate" statistics with
// conversion information, as a legacy issue until all code obtains
// conversion data from the standard conversion statistics tables
$oManageConversions = new OX_Maintenance_Statistics_Task_ManageConversions();
$this->oTaskRunner->addTask($oManageConversions);
// Add the task to summarise the intermediate statistics into final form
$oSummariseFinal = new OX_Maintenance_Statistics_Task_SummariseFinal();
$this->oTaskRunner->addTask($oSummariseFinal);
// Add the task to log the completion of the task
$oLogCompletion = new OX_Maintenance_Statistics_Task_LogCompletion();
$this->oTaskRunner->addTask($oLogCompletion);
// Add the task to manage (enable/disable) campaigns
$oManageCampaigns = new OX_Maintenance_Statistics_Task_ManageCampaigns();
$this->oTaskRunner->addTask($oManageCampaigns);
- Task的执行
只需调用 TaskRunner?的runTasks方法
// Run the MSE process tasks
$this->oTaskRunner->runTasks(); //file statistics.php line 209
调用该方法后,将逐个执行所有的Task,详见该方法的实现
/**
* A method to run the run() method of each task in the collection,
* in the registered order.
*
* @todo We should really make OA_Task::run return a boolean we can check.
*/
function runTasks()
{
// Remove tasks from the queue and unset them when done to prevent
// useless memory consumption
while ($oTask = array_shift($this->aTasks)) {
$oTask->run();
unset($oTask);
}
}
- 重要插件 deliveryLog
//参见 plugins/deliveryLog 目录
plugins/deliveryLog/oxLogRequest - 记录请求次数
plugins/deliveryLog/oxLogImpression - 记录显示次数
plugins/deliveryLog/oxLogClick - 记录点击
plugins/deliveryLog/oxCountry - 记录国家和区域
plugins/deliveryLog/oxLogTimes - 记录停留时间
- 重要DAL类(抽象MSE类OX_Dal_Maintenance_Statistics)
lib/OX/Dal/Maintenance/Statistics.php
注意:该类为抽象类,并不直接使用,对于mysql数据库,实际操作通过Statistics/Mysql.php来完成
- 统计报表查询页 www/admin/stats.php
- 报表模板文件目录
1. lib/OA/Admin/Statistics/Targeting
2. lib/OA/Admin/Statistics/Delivery/
- Controller类目录
//Delivery
lib/OA/Admin/Statistics/Delivery/Controller
- DAL
lib/OA/Dal/Statistics
广告项目的计费实现 ¶
经过检查,项目计费目前是已有功能
//现有计费类型参考 - 定义于 /constants.php
// Financial constants
define('MAX_FINANCE_CPM', 1);
define('MAX_FINANCE_CPC', 2);
define('MAX_FINANCE_CPA', 3);
define('MAX_FINANCE_MT', 4); // Monthly Tennancy
define('MAX_FINANCE_RS', 5); // % Revenue split (zone-only)
define('MAX_FINANCE_BV', 6); // % Basket value (zone-only)
define('MAX_FINANCE_AI', 7); // Amount per item (zone-only)
define('MAX_FINANCE_ANYVAR', 8); // % of any variable (zone-only)
define('MAX_FINANCE_VARSUM', 9); // % of a variable sum (zone-only)
define('MAX_FINANCE_DT', 10); // Day Tennancy
统计报表的展现 ¶
统计数据的获取 ¶
- Cheatsheet - 获的统计数据所有执行方法路径
- lib\OA\Admin\Statistics\Delivery\Controller\GlobalAdvertiser?.php 第134行
switch ($this->startLevel)
{
case 2:
//$this->aEntitiesData = $this->getBanners($aParams, $this->startLevel, $expand);
$this->aEntitiesData = $this->getBannersForKeyword($aParams, $this->startLevel, $expand);
break;
case 1:
//$this->aEntitiesData = $this->getCampaigns($aParams, $this->startLevel, $expand);
$this->aEntitiesData = $this->getCampaignsForkeyword($aParams, $this->startLevel, $expand);
break;
default:
$this->startLevel = 0;
//$this->aEntitiesData = $this->getAdvertisers($aParams, $this->startLevel, $expand);
$this->aEntitiesData = $this->getAdvertisersForKeyword($aParams, $this->startLevel, $expand); //以此作为入口
break;
}
- lib\OA\Admin\Statistics\Delivery\CommonEntity?.php - line 902, function getAdvertisersForKeyword
function getAdvertisersForKeyword($aParams, $level, $expand = ''){
//$aParams['include'] = array('advertiser_id', 'placement_id', 'keyword', 'ahid');
$aParams['include'] = array('advertiser_id', 'placement_id', 'keyword');
//$aParams['include'] = array('advertiser_id', 'placement_id');
$aParams['exclude'] = array('zone_id');
$this->prepareKeywordData($aParams); // line 909,执行此方法将导致查询数据库
$period_preset = MAX_getStoredValue('period_preset', 'today');
$aAdvertisers = $this->mergeData($aParams, 'advertiser_id');
- lib\OA\Admin\Statistics\Delivery\CommonEntity?.php - line 365, function prepareKeywordData
function prepareKeywordData($aParams)
{
if (is_null($this->data)){
$oNow = new Date();
$aParams['tz'] = $oNow->tz->getID();
// Get plugin aParams
$pluginParams = array();
foreach ($this->aPlugins as $oPlugin) {
$oPlugin->addQueryParams($pluginParams);
}
$pluginParams['add_columns']['s.keyword'] = 'keyword';
$pluginParams['add_columns']['s.ahid'] = 'ahid';
$aRows = Admin_DA::fromCache('getEntitiesStatsForAll', $aParams + $this->aDates + $pluginParams);
- lib\max\Admin_DA.php - function fromCache
$ret = $cache->call("Admin_DA::".$method, $aParams, $allFields); //line 540 in function from Cache
- lib\pear\Cache\Lite\Function.php 第89行,方法 call
...
89. if (strstr($target, '::')) { // classname::staticMethod
90. list($class, $method) = explode('::', $target);
91. $result = call_user_func_array(array($class, $method), $arguments); //调用AdminDA类中方法_getEntities
92. }
...
- lib\max\Admin_DA.php 方法第200行,方法 _getEntities
function _getEntities($entity, $aParams, $allFields = false, $key = null, $isAll=false)
{
if (empty($key)) {
$key = "{$entity}_id";
}
$aColumns = SqlBuilder::_getColumns($entity, $aParams, $allFields);
$aTables = SqlBuilder::_getTables($entity, $aParams);
$aLimitations = array_merge(
SqlBuilder::_getLimitations($entity, $aParams),
SqlBuilder::_getTableLimitations($aTables, $aParams)
);
$aGroupColumns = SqlBuilder::_getGroupColumns($entity, $aParams);
$aLeftJoinedTables = SqlBuilder::_getLeftJoinedTables($entity, $aParams);
$rows = SqlBuilder::_select($aColumns, $aTables, $aLimitations, $aGroupColumns, $key, $aLeftJoinedTables, $isAll); //将调用SqlBuilder.php中的_select方法
return $rows;
}
- lib\max\SqlBuilder?.php 第1139行,方法 _select执行查询,返回最终结果
function _select($aColumns, $aTables, $aLimitations, $aGroupColumns, $primaryKey, $aLeftJoinedTables = null, $isAll=false)
{
$conf = $GLOBALS['_MAX']['CONF'];
$oDbh = OA_DB::singleton();
$columns = '';
...
Important Tips:通过在_select方法返回值之前,添加 print('--debug begin--'.$query.'--debug end--'.);就可以看到完整的SQL语句,可以用此来检查报表数据的正确性啦
高级报表Advanced Reports ¶
- 源码目录 plugins/reports/oxReportsStandard
- 访问地址 www/admin/report-index.php
