风险系数判断修复
This commit is contained in:
@@ -26,7 +26,8 @@ class VisitorLogAnalytics
|
||||
$byDevice = self::fetchDeviceTop($conn, $where, 8);
|
||||
$timing = self::fetchTimingStats($conn, $where);
|
||||
$compare = self::fetchCompare($conn, $filters, $summary);
|
||||
$conclusions = self::buildConclusions($summary, $byReason, $byCountry, $byHour, $byDevice, $timing, $compare, $byResult);
|
||||
$fpRisk = self::fetchFpRiskStats($conn, $where);
|
||||
$conclusions = self::buildConclusions($summary, $byReason, $byCountry, $byHour, $byDevice, $timing, $compare, $byResult, $fpRisk);
|
||||
|
||||
return [
|
||||
'summary' => $summary,
|
||||
@@ -37,6 +38,7 @@ class VisitorLogAnalytics
|
||||
'by_device' => $byDevice,
|
||||
'timing' => $timing,
|
||||
'compare' => $compare,
|
||||
'fp_risk' => $fpRisk,
|
||||
'conclusions' => $conclusions,
|
||||
];
|
||||
}
|
||||
@@ -338,6 +340,33 @@ class VisitorLogAnalytics
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 二次风控(byApiRisk)相关聚合:数字 reason、fp_hdata 覆盖率等。
|
||||
*
|
||||
* @param mysqli $conn
|
||||
* @param string $where
|
||||
*/
|
||||
private static function fetchFpRiskStats($conn, $where)
|
||||
{
|
||||
$sql = "SELECT
|
||||
SUM(CASE WHEN `reason` REGEXP '^[0-9]+$' OR `reason` REGEXP '^[0-9]+[[:space:]*::|/]' THEN 1 ELSE 0 END) AS score_reason_cnt,
|
||||
SUM(CASE WHEN `fp_hdata` IS NOT NULL AND TRIM(`fp_hdata`) <> '' THEN 1 ELSE 0 END) AS hdata_cnt,
|
||||
SUM(CASE WHEN `result` = 'false' AND (`reason` REGEXP '^[0-9]+$' OR `reason` REGEXP '风险|WebDriver|Canvas|自动化|指纹' OR `reason` REGEXP '^[0-9]+[[:space:]*::|/]') THEN 1 ELSE 0 END) AS fp_block_cnt,
|
||||
SUM(CASE WHEN `result` = 'true' AND (`reason` REGEXP '^[0-9]+$' OR `reason` REGEXP '^[0-9]+[[:space:]*::|/]') THEN 1 ELSE 0 END) AS fp_pass_cnt,
|
||||
AVG(CASE WHEN `reason` REGEXP '^[0-9]+$' THEN CAST(`reason` AS UNSIGNED) ELSE NULL END) AS avg_score_reason
|
||||
FROM `visitor_logs` WHERE {$where}";
|
||||
$res = $conn->query($sql);
|
||||
$row = $res ? $res->fetch_assoc() : [];
|
||||
|
||||
return [
|
||||
'score_reason_cnt' => (int) ($row['score_reason_cnt'] ?? 0),
|
||||
'hdata_cnt' => (int) ($row['hdata_cnt'] ?? 0),
|
||||
'fp_block_cnt' => (int) ($row['fp_block_cnt'] ?? 0),
|
||||
'fp_pass_cnt' => (int) ($row['fp_pass_cnt'] ?? 0),
|
||||
'avg_score_reason' => $row['avg_score_reason'] !== null ? round((float) $row['avg_score_reason'], 1) : null,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $summary
|
||||
* @param array $byReason
|
||||
@@ -347,9 +376,10 @@ class VisitorLogAnalytics
|
||||
* @param array $timing
|
||||
* @param array $compare
|
||||
* @param array $byResult
|
||||
* @param array $fpRisk
|
||||
* @return string[]
|
||||
*/
|
||||
private static function buildConclusions(array $summary, array $byReason, array $byCountry, array $byHour, array $byDevice, array $timing, array $compare, array $byResult)
|
||||
private static function buildConclusions(array $summary, array $byReason, array $byCountry, array $byHour, array $byDevice, array $timing, array $compare, array $byResult, array $fpRisk = [])
|
||||
{
|
||||
$lines = [];
|
||||
$total = (int) $summary['total'];
|
||||
@@ -429,6 +459,37 @@ class VisitorLogAnalytics
|
||||
$lines[] = '告警:检测中(wait)状态占比偏高,可能存在二次风控未完成或 f_check 回调异常。';
|
||||
}
|
||||
|
||||
$total = (int) $summary['total'];
|
||||
$hdataCnt = (int) ($fpRisk['hdata_cnt'] ?? 0);
|
||||
$scoreReasonCnt = (int) ($fpRisk['score_reason_cnt'] ?? 0);
|
||||
if ($total > 0 && $hdataCnt > 0) {
|
||||
$hdataPct = round($hdataCnt / $total * 100, 1);
|
||||
$lines[] = sprintf(
|
||||
'二次风控:%d 条含指纹 hdata(占 %.1f%%),%d 条 reason 为风险分格式。',
|
||||
$hdataCnt,
|
||||
$hdataPct,
|
||||
$scoreReasonCnt
|
||||
);
|
||||
if ($hdataPct < 30 && $total >= 20) {
|
||||
$lines[] = '关注:指纹 hdata 覆盖率偏低,请检查 CLOAK_RISK_NUMBER 是否为 0、cloakjs 是否加载,或加强判断是否导致采集失败。';
|
||||
}
|
||||
}
|
||||
if ($scoreReasonCnt >= 10 && ($fpRisk['avg_score_reason'] ?? null) !== null) {
|
||||
$avg = $fpRisk['avg_score_reason'];
|
||||
$lines[] = sprintf('指纹风险分 reason 平均约 %.1f 分(纯数字 reason 样本)。', $avg);
|
||||
if ($avg >= 60) {
|
||||
$lines[] = '关注:平均风险分偏高,若同时误拦真实用户,基础模式建议将风险系数调至 68 左右(加强模式 52)。';
|
||||
} elseif ($avg <= 25 && ($fpRisk['fp_block_cnt'] ?? 0) === 0 && $scoreReasonCnt >= 20) {
|
||||
$lines[] = '提示:风险分普遍较低且少见拦截,若需更严防护可适当降低风险系数或开启加强判断。';
|
||||
}
|
||||
}
|
||||
if (($fpRisk['fp_block_cnt'] ?? 0) >= 5 && $total >= 20) {
|
||||
$fpBlockRate = round($fpRisk['fp_block_cnt'] / max(1, $scoreReasonCnt) * 100, 1);
|
||||
if ($fpBlockRate >= 50 && $scoreReasonCnt >= 10) {
|
||||
$lines[] = sprintf('告警:指纹 reason 类拦截占指纹记录约 %.1f%%,建议抽样「判定详情」检查是否阈值过低(旧值 51 或加强模式阈值过高)。', $fpBlockRate);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array_slice($byReason, 0, 3) as $r) {
|
||||
if ($r['pct'] >= 40 && $total >= 20) {
|
||||
$lines[] = sprintf('关注:理由「%s」占比达 %.1f%%,建议针对性排查该规则。', $r['reason'], $r['pct']);
|
||||
|
||||
Reference in New Issue
Block a user