Files
aler_dashboard_git/alert_dashboard/www/api/index.php
T

408 lines
16 KiB
PHP

<?php
session_start();
$act = $_GET['act'] ?? '';
// 未登录直接拒绝所有接口访问
if(empty($_SESSION['user_id'])){
header("Content-Type:application/json;charset=utf-8");
echo json_encode(["code"=>401,"msg"=>"未登录,请前往登录页面"], JSON_UNESCAPED_UNICODE);
exit;
}
// 统一数据库配置
$dbHost = "10.150.117.190";
$dbUser = "root";
$dbPass = "hp93000";
$dbName = "alert_mail_stat";
// 统一数据库连接函数
function getDbConn() {
global $dbHost, $dbUser, $dbPass, $dbName;
$conn = mysqli_connect($dbHost, $dbUser, $dbPass, $dbName);
mysqli_set_charset($conn, "utf8mb4");
return $conn;
}
// CSV导出接口(支持指定历史日期下载,不输出JSON头)
if ($act === "export_csv") {
$conn = getDbConn();
if (!$conn) {
header("Content-Type:text/html;charset=utf-8");
echo "数据库连接失败:" . mysqli_connect_error();
exit;
}
// 接收自定义日期参数,不传则取今日
$targetDate = $_GET['date'] ?? date("Y-m-d");
// 简单日期格式校验 Y-m-d
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $targetDate)) {
header("Content-Type:application/json;charset=utf-8");
echo json_encode(["code"=>400,"msg"=>"日期格式错误,请使用 Y-m-d,例如 2026-07-01"], JSON_UNESCAPED_UNICODE);
exit;
}
$sql = "SELECT alert_type,alert_name,instance,severity,starts_at,receive_time
FROM alert_log WHERE DATE(receive_time) = '$targetDate' ORDER BY receive_time DESC";
$res = mysqli_query($conn, $sql);
ob_clean();
header("Content-Type: text/csv; charset=utf-8");
header("Content-Disposition: attachment; filename=告警报表_" . $targetDate . ".csv");
echo "\xEF\xBB\xBF";
$header = ["告警状态", "告警名称", "实例", "级别", "故障开始时间", "接收时间"];
echo implode(",", $header) . "\r\n";
while ($row = mysqli_fetch_assoc($res)) {
$status = $row['alert_type'] == 1 ? "触发" : "恢复";
$line = [
$status,
$row['alert_name'],
$row['instance'],
$row['severity'],
$row['starts_at'],
$row['receive_time']
];
foreach ($line as &$v) {
$v = '"' . str_replace('"', '""', $v) . '"';
}
echo implode(",", $line) . "\r\n";
}
mysqli_close($conn);
exit;
}
// 所有JSON接口统一返回头
header("Content-Type:application/json;charset=utf-8");
$conn = getDbConn();
if (!$conn) {
echo json_encode(["code" => 500, "msg" => "数据库连接失败:" . mysqli_connect_error()], JSON_UNESCAPED_UNICODE);
exit;
}
$today = date("Y-m-d");
// 调试代码:打印GET入参,测试完成后删除此段
// $getAct = $_GET['act'] ?? '';
//echo json_encode([
// "debug_act" => $getAct,
// "debug_rule" => $_GET['rule_name'] ?? '',
// "debug_instance" => $_GET['instance'] ?? ''
//], JSON_UNESCAPED_UNICODE);
//exit;
// 接口1:下线整条监控规则(该规则下所有实例一并清理)
if($act === "clear_offline_rule"){
$rule = $_GET['rule_name'] ?? '';
if(empty($rule)){
echo json_encode(["code"=>400,"msg"=>"缺少rule_name参数"],JSON_UNESCAPED_UNICODE);
exit;
}
$ruleEsc = mysqli_real_escape_string($conn, $rule);
// 标记该规则下全部实例为下线
$updateSql = "UPDATE monitor_rule SET status=0, update_at=NOW() WHERE rule_name='$ruleEsc'";
mysqli_query($conn, $updateSql);
// 批量插入恢复记录,消除页面残留告警
$insertSql = "
INSERT INTO alert_log (alert_type,alert_name,instance,severity,starts_at,receive_time)
SELECT DISTINCT 2,alert_name,instance,severity,NOW(),NOW()
FROM alert_log
WHERE alert_name='$ruleEsc'
AND (alert_name,instance) NOT IN (
SELECT alert_name,instance FROM alert_log WHERE alert_type=2
)
";
mysqli_query($conn, $insertSql);
echo json_encode(["code"=>0,"msg"=>"整条规则下线完成,所有实例告警已清除"],JSON_UNESCAPED_UNICODE);
exit;
}
// 接口2:单独下线单台实例(仅隐藏指定机器,同规则其他主机不受影响)
if($act === "clear_single_instance"){
$rule = $_GET['rule_name'] ?? '';
$inst = $_GET['instance'] ?? '';
if(empty($rule) || empty($inst)){
echo json_encode(["code"=>400,"msg"=>"缺少rule_name或instance参数"],JSON_UNESCAPED_UNICODE);
exit;
}
$ruleEsc = mysqli_real_escape_string($conn, $rule);
$instEsc = mysqli_real_escape_string($conn, $inst);
// 第一步:删除当前实例旧的恢复记录,避免重复拦截
$delSql = "DELETE FROM alert_log WHERE alert_type=2 AND alert_name='$ruleEsc' AND instance='$instEsc'";
mysqli_query($conn, $delSql);
// 第二步:插入最新恢复记录,移除NOT IN限制,强制生成
$insertSql = "
INSERT INTO alert_log (alert_type,alert_name,instance,severity,starts_at,receive_time)
SELECT DISTINCT 2,alert_name,instance,severity,NOW(),NOW()
FROM alert_log
WHERE alert_name='$ruleEsc' AND instance='$instEsc'
";
mysqli_query($conn, $insertSql);
$affected = mysqli_affected_rows($conn);
echo json_encode([
"code"=>0,
"msg"=>"单实例告警清理完成",
"insert_rows" => $affected
],JSON_UNESCAPED_UNICODE);
exit;
}
// 接口3:恢复整条已下线规则(status改为1,重新展示所有实例告警)
if($act === "restore_rule"){
$rule = $_GET['rule_name'] ?? '';
if(empty($rule)){
echo json_encode(["code"=>400,"msg"=>"缺少rule_name参数"],JSON_UNESCAPED_UNICODE);
exit;
}
$ruleEsc = mysqli_real_escape_string($conn, $rule);
$updateSql = "UPDATE monitor_rule SET status=1, update_at=NOW() WHERE rule_name='$ruleEsc'";
mysqli_query($conn, $updateSql);
echo json_encode(["code"=>0,"msg"=>"监控规则已恢复,新故障会正常展示"],JSON_UNESCAPED_UNICODE);
exit;
}
// 接口4:恢复单台实例(仅把指定rule+instance置为启用)
if($act === "restore_single_instance"){
$rule = $_GET['rule_name'] ?? '';
$inst = $_GET['instance'] ?? '';
if(empty($rule) || empty($inst)){
echo json_encode(["code"=>400,"msg"=>"缺少rule_name或instance参数"],JSON_UNESCAPED_UNICODE);
exit;
}
$ruleEsc = mysqli_real_escape_string($conn, $rule);
$instEsc = mysqli_real_escape_string($conn, $inst);
$updateSql = "UPDATE monitor_rule SET status=1, update_at=NOW() WHERE rule_name='$ruleEsc' AND instance='$instEsc'";
mysqli_query($conn, $updateSql);
echo json_encode(["code"=>0,"msg"=>"单实例已恢复"],JSON_UNESCAPED_UNICODE);
exit;
}
// 接口5:删除单实例全部告警日志
if($act === "delete_single_instance_log"){
$rule = $_GET['rule_name'] ?? '';
$inst = $_GET['instance'] ?? '';
if(empty($rule) || empty($inst)){
echo json_encode(["code"=>400,"msg"=>"缺少rule_name或instance参数"],JSON_UNESCAPED_UNICODE);
exit;
}
$ruleEsc = mysqli_real_escape_string($conn, $rule);
$instEsc = mysqli_real_escape_string($conn, $inst);
$delSql = "DELETE FROM alert_log WHERE alert_name='$ruleEsc' AND instance='$instEsc'";
mysqli_query($conn, $delSql);
$aff = mysqli_affected_rows($conn);
echo json_encode(["code"=>0,"msg"=>"单实例告警日志已删除","affected_rows"=>$aff],JSON_UNESCAPED_UNICODE);
exit;
}
// 接口:永久屏蔽单台实例(monitor_rule 该条实例status=0,不手动恢复永远不告警)
if($act === "offline_single_instance"){
$rule = $_GET['rule_name'] ?? '';
$inst = $_GET['instance'] ?? '';
if(empty($rule) || empty($inst)){
echo json_encode(["code"=>400,"msg"=>"缺少rule_name或instance参数"],JSON_UNESCAPED_UNICODE);
exit;
}
$ruleEsc = mysqli_real_escape_string($conn, $rule);
$instEsc = mysqli_real_escape_string($conn, $inst);
// 把这条【规则+实例】状态改为0,永久屏蔽
$updateSql = "UPDATE monitor_rule SET status=0, update_at=NOW() WHERE rule_name='$ruleEsc' AND instance='$instEsc'";
mysqli_query($conn, $updateSql);
$aff = mysqli_affected_rows($conn);
// 同步生成恢复日志,界面立刻消失旧告警
$delOld = "DELETE FROM alert_log WHERE alert_type=2 AND alert_name='$ruleEsc' AND instance='$instEsc'";
mysqli_query($conn, $delOld);
$insertSql = "
INSERT INTO alert_log (alert_type,alert_name,instance,severity,starts_at,receive_time)
SELECT DISTINCT 2,alert_name,instance,severity,NOW(),NOW()
FROM alert_log
WHERE alert_name='$ruleEsc' AND instance='$instEsc'
";
mysqli_query($conn, $insertSql);
echo json_encode([
"code"=>0,
"msg"=>"单实例已永久屏蔽,需调用restore_single_instance恢复",
"update_rows"=>$aff
],JSON_UNESCAPED_UNICODE);
exit;
}
// 新增:同步Prometheus实时告警,自动清理残留恢复记录
if($act === "sync_prom_alerts"){
$promUrl = "http://10.150.117.190:9090/api/v1/alerts";
$resp = @file_get_contents($promUrl);
if($resp === false){
echo json_encode(["code"=>500,"msg"=>"无法连接Prometheus接口"],JSON_UNESCAPED_UNICODE);
exit;
}
$promData = json_decode($resp,true);
if(!isset($promData['data']['alerts'])){
echo json_encode(["code"=>500,"msg"=>"Prometheus返回数据异常"],JSON_UNESCAPED_UNICODE);
exit;
}
$firingMap = [];
foreach($promData['data']['alerts'] as $item){
$an = $item['labels']['alertname'];
$ins = $item['labels']['instance'];
$key = "$an||$ins";
$firingMap[$key] = 1;
}
$res = mysqli_query($conn,"SELECT alert_name,instance FROM alert_log WHERE alert_type=2");
$delCnt = 0;
while($row = mysqli_fetch_assoc($res)){
$k = $row['alert_name']."||".$row['instance'];
if(isset($firingMap[$k])){
$n = mysqli_real_escape_string($conn,$row['alert_name']);
$i = mysqli_real_escape_string($conn,$row['instance']);
mysqli_query($conn,"DELETE FROM alert_log WHERE alert_type=2 AND alert_name='$n' AND instance='$i'");
$delCnt++;
}
}
echo json_encode(["code"=>0,"msg"=>"同步完成","delete_clear_log"=>$delCnt],JSON_UNESCAPED_UNICODE);
exit;
}
// ============后台管理专用接口 start============
// 修改密码 BCrypt哈希加密,匹配历史密码算法
if($act === "change_pwd"){
$uid = $_SESSION['user_id'];
$oldPwdRaw = $_GET['old_pwd'] ?? '';
$newPwdRaw = $_GET['new_pwd'] ?? '';
if(empty($oldPwdRaw) || empty($newPwdRaw)){
echo json_encode(["code"=>400,"msg"=>"密码不能为空"],JSON_UNESCAPED_UNICODE);
exit;
}
// 查询原密码哈希
$userSql = "SELECT password FROM admin_user WHERE user_id='$uid' LIMIT 1";
$userRes = mysqli_query($conn,$userSql);
$userRow = mysqli_fetch_assoc($userRes);
if(!$userRow){
echo json_encode(["code"=>401,"msg"=>"账户不存在"],JSON_UNESCAPED_UNICODE);
exit;
}
$oldHash = $userRow['password'];
// 校验旧密码(和原有登录逻辑一致)
if(!password_verify($oldPwdRaw, $oldHash)){
echo json_encode(["code"=>400,"msg"=>"原密码输入错误"],JSON_UNESCAPED_UNICODE);
exit;
}
// 生成新bcrypt哈希
$newHash = password_hash($newPwdRaw, PASSWORD_DEFAULT);
$updateSql = "UPDATE admin_user SET password='$newHash', update_at=NOW() WHERE user_id='$uid'";
mysqli_query($conn,$updateSql);
echo json_encode(["code"=>0,"msg"=>"密码修改成功"],JSON_UNESCAPED_UNICODE);
exit;
}
// 保存界面外观配置
if($act === "save_theme"){
// 兼容POST/GET
$title = mysqli_real_escape_string($conn,$_POST['title'] ?? $_GET['title'] ?? '');
$color = mysqli_real_escape_string($conn,$_POST['color'] ?? $_GET['color'] ?? '');
$pagesize = mysqli_real_escape_string($conn,$_POST['pagesize'] ?? $_GET['pagesize'] ?? '20');
$footer = mysqli_real_escape_string($conn,$_POST['footer'] ?? $_GET['footer'] ?? '');
$lang = mysqli_real_escape_string($conn,$_POST['lang'] ?? $_GET['lang'] ?? 'zh');
$sql = "REPLACE INTO sys_config (k,v) VALUES
('page_title','$title'),
('theme_color','$color'),
('page_size','$pagesize'),
('footer_text','$footer'),
('lang','$lang')";
mysqli_query($conn,$sql);
echo json_encode(["code"=>0,"msg"=>"外观配置已保存"],JSON_UNESCAPED_UNICODE);
exit;
}
// 保存侧边栏外链
if($act === "save_sidebar_link"){
$linkText = mysqli_real_escape_string($conn,$_GET['link_text'] ?? '');
$sql = "REPLACE INTO sys_config (k,v) VALUES ('sidebar_links','$linkText')";
mysqli_query($conn,$sql);
echo json_encode(["code"=>0,"msg"=>"侧边外链保存成功"],JSON_UNESCAPED_UNICODE);
exit;
}
// 单独切换语言接口
if ($_POST['act'] === 'save_lang') {
$lang = mysqli_real_escape_string($conn, $_POST['lang']);
$sql = "REPLACE INTO sys_config(k, v) VALUES ('lang', '$lang')";
mysqli_query($conn, $sql);
echo json_encode(["code" => 0]);
exit;
}
// ============后台管理专用接口 end============
// 1. 今日统计卡片
if ($act === "day_total") {
$sql = "SELECT
SUM(IF(alert_type=1,1,0)) as fire_count,
SUM(IF(alert_type=2,1,0)) as resolve_count,
COUNT(DISTINCT instance) as instance_num
FROM alert_log WHERE DATE(receive_time) = '$today'";
$data = mysqli_fetch_assoc(mysqli_query($conn, $sql));
echo json_encode($data, JSON_UNESCAPED_UNICODE);
exit;
}
// 2. 今日告警TOP10图表
if ($act === "top_alert") {
$sql = "SELECT alert_name,COUNT(*) cnt FROM alert_log WHERE DATE(receive_time)='$today' GROUP BY alert_name ORDER BY cnt DESC LIMIT 10";
$list = [];
$q = mysqli_query($conn, $sql);
while ($r = mysqli_fetch_assoc($q)) $list[] = $r;
echo json_encode($list, JSON_UNESCAPED_UNICODE);
exit;
}
// 3. 今日全量告警明细表格
if ($act === "log_list") {
$sql = "SELECT alert_type,alert_name,instance,severity,starts_at,ends_at,receive_time
FROM alert_log WHERE DATE(receive_time)='$today' ORDER BY receive_time DESC";
$list = [];
$q = mysqli_query($conn, $sql);
while ($r = mysqli_fetch_assoc($q)) $list[] = $r;
echo json_encode($list, JSON_UNESCAPED_UNICODE);
exit;
}
// 4. 全局跨天未恢复告警(过滤整条下线规则,单实例仅靠恢复日志隐藏)
if ($act === "active_firing") {
$maxSql = "SELECT alert_name,instance,MAX(receive_time) max_rt FROM alert_log GROUP BY alert_name,instance";
$maxRes = mysqli_query($conn, $maxSql);
$activeList = [];
while ($maxRow = mysqli_fetch_assoc($maxRes)) {
$an = $conn->real_escape_string($maxRow['alert_name']);
$ins = $conn->real_escape_string($maxRow['instance']);
$mrt = $conn->real_escape_string($maxRow['max_rt']);
// 判断该规则是否整条下线,下线直接跳过
$ruleCheck = mysqli_query($conn, "SELECT status FROM monitor_rule WHERE rule_name='$an' LIMIT 1");
$ruleStatus = 1;
if($ruleCheck && $ruleRow = mysqli_fetch_assoc($ruleCheck)){
$ruleStatus = intval($ruleRow['status']);
}
if($ruleStatus === 0){
continue;
}
$rowSql = "SELECT alert_name,instance,severity,starts_at,receive_time,alert_type
FROM alert_log
WHERE alert_name='$an' AND instance='$ins' AND receive_time='$mrt'";
$rowRes = mysqli_query($conn, $rowSql);
$data = mysqli_fetch_assoc($rowRes);
if ($data && (int)$data['alert_type'] === 1) {
$activeList[] = $data;
}
}
echo json_encode($activeList, JSON_UNESCAPED_UNICODE);
exit;
}
// 非法请求兜底
echo json_encode(["code" => 400, "msg" => "无效请求参数act"], JSON_UNESCAPED_UNICODE);
mysqli_close($conn);
?>