269 lines
8.1 KiB
TypeScript
269 lines
8.1 KiB
TypeScript
|
|
/**
|
|||
|
|
* 巡检模块 - 前端 API 层
|
|||
|
|
*
|
|||
|
|
* 通过 window.electronAPI.inspection 调用主进程的巡检 IPC handlers。
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
// ---------- 类型定义 ----------
|
|||
|
|
|
|||
|
|
export type AlertLevel = "critical" | "warning" | "info";
|
|||
|
|
export type DeviceTier = "core" | "aggregation" | "access";
|
|||
|
|
export type InspectionStatus = "success" | "failed" | "timeout";
|
|||
|
|
export type AlertRecordStatus = "active" | "acknowledged" | "resolved" | "closed";
|
|||
|
|
export type Operator = ">" | "<" | "==" | "!=" | ">=" | "<=";
|
|||
|
|
|
|||
|
|
export interface InspectionLabels {
|
|||
|
|
alert_levels: Record<AlertLevel, string>;
|
|||
|
|
device_tiers: Record<DeviceTier, string>;
|
|||
|
|
inspection_status: Record<InspectionStatus, string>;
|
|||
|
|
alert_record_status: Record<AlertRecordStatus, string>;
|
|||
|
|
operators: Record<Operator, string>;
|
|||
|
|
device_catalog: Record<string, string>;
|
|||
|
|
metrics: Record<string, string>;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface DeviceCatalog {
|
|||
|
|
id: string;
|
|||
|
|
type_key: string;
|
|||
|
|
name: string;
|
|||
|
|
vendor: string;
|
|||
|
|
adapter_class: string;
|
|||
|
|
supported_metrics: string[];
|
|||
|
|
default_thresholds: AlertRule[];
|
|||
|
|
default_interval: number;
|
|||
|
|
description: string;
|
|||
|
|
preset: boolean;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface DeviceTierInfo {
|
|||
|
|
key: DeviceTier;
|
|||
|
|
label: string;
|
|||
|
|
default_interval: number;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface DeviceExtension {
|
|||
|
|
host_id: string;
|
|||
|
|
/** 主机名(IP 或域名),用于调度器匹配 vault SSH 配置 */
|
|||
|
|
hostname?: string | null;
|
|||
|
|
catalog_id: string;
|
|||
|
|
tier: DeviceTier | null;
|
|||
|
|
inspection_interval: number | null;
|
|||
|
|
inspection_enabled: boolean;
|
|||
|
|
custom_thresholds: AlertRule[];
|
|||
|
|
inspection_tags: string[];
|
|||
|
|
last_scan_at: number | null;
|
|||
|
|
last_scan_status: InspectionStatus | null;
|
|||
|
|
last_scan_error: string | null;
|
|||
|
|
created_at: number;
|
|||
|
|
updated_at: number;
|
|||
|
|
effective_interval?: number;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface AlertRule {
|
|||
|
|
id: string;
|
|||
|
|
name: string;
|
|||
|
|
metric: string;
|
|||
|
|
operator: Operator;
|
|||
|
|
threshold: string;
|
|||
|
|
level: AlertLevel;
|
|||
|
|
duration: number;
|
|||
|
|
scope_type: "all" | "tier" | "device" | "catalog";
|
|||
|
|
scope_value: string | string[] | null;
|
|||
|
|
enabled: boolean;
|
|||
|
|
preset?: boolean;
|
|||
|
|
created_at: number;
|
|||
|
|
updated_at: number;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface InspectionResult {
|
|||
|
|
id: string;
|
|||
|
|
job_id: string | null;
|
|||
|
|
device_id: string;
|
|||
|
|
timestamp: number;
|
|||
|
|
online: boolean;
|
|||
|
|
status: InspectionStatus;
|
|||
|
|
duration_ms: number;
|
|||
|
|
metrics: Record<string, any>;
|
|||
|
|
alerts: any[];
|
|||
|
|
error_message: string | null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface AlertRecord {
|
|||
|
|
id: string;
|
|||
|
|
rule_id: string;
|
|||
|
|
rule_name: string;
|
|||
|
|
device_id: string;
|
|||
|
|
device_name: string;
|
|||
|
|
metric: string;
|
|||
|
|
metric_value: string;
|
|||
|
|
threshold: string;
|
|||
|
|
level: AlertLevel;
|
|||
|
|
message: string;
|
|||
|
|
triggered_at: number;
|
|||
|
|
status: AlertRecordStatus;
|
|||
|
|
acknowledged_by: string | null;
|
|||
|
|
acknowledged_at: number | null;
|
|||
|
|
resolved_at: number | null;
|
|||
|
|
resolved_reason: string | null;
|
|||
|
|
note: string | null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface AlertStats {
|
|||
|
|
total: number;
|
|||
|
|
active: number;
|
|||
|
|
active_critical: number;
|
|||
|
|
active_warning: number;
|
|||
|
|
active_info: number;
|
|||
|
|
acknowledged: number;
|
|||
|
|
resolved: number;
|
|||
|
|
closed: number;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface SchedulerStatus {
|
|||
|
|
running: boolean;
|
|||
|
|
queue_size: number;
|
|||
|
|
active_scans: number;
|
|||
|
|
concurrency: number;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ---------- API 调用 ----------
|
|||
|
|
|
|||
|
|
const api = (window as any).netcatty?.inspection;
|
|||
|
|
|
|||
|
|
function isAvailable(): boolean {
|
|||
|
|
return !!api;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function invoke(name: string, ...args: any[]): Promise<any> {
|
|||
|
|
if (!api || typeof api[name] !== "function") {
|
|||
|
|
console.warn(`[Inspection] api.${name} 不可用`);
|
|||
|
|
return Promise.resolve(null);
|
|||
|
|
}
|
|||
|
|
return api[name](...args);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ---------- 标签 ----------
|
|||
|
|
export const inspectionLabelsApi = {
|
|||
|
|
isAvailable,
|
|||
|
|
getLabels: (): Promise<InspectionLabels> => invoke("getLabels"),
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// ---------- 系统配置 ----------
|
|||
|
|
export const inspectionSysConfigApi = {
|
|||
|
|
get: (): Promise<Record<string, any>> => invoke("getSysConfig"),
|
|||
|
|
update: (updates: Record<string, any>) => invoke("updateSysConfig", updates),
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// ---------- 设备类型 ----------
|
|||
|
|
export const inspectionCatalogApi = {
|
|||
|
|
list: (): Promise<DeviceCatalog[]> => invoke("getCatalog"),
|
|||
|
|
getTiers: (): Promise<DeviceTierInfo[]> => invoke("getTiers"),
|
|||
|
|
getAdapters: (): Promise<string[]> => invoke("getAdapters"),
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// ---------- 设备扩展 ----------
|
|||
|
|
export const inspectionDeviceApi = {
|
|||
|
|
getAll: (): Promise<Record<string, DeviceExtension>> => invoke("getAllExtensions"),
|
|||
|
|
get: (hostId: string): Promise<DeviceExtension | null> => invoke("getExtension", hostId),
|
|||
|
|
upsert: (hostId: string, data: Partial<DeviceExtension>): Promise<DeviceExtension> =>
|
|||
|
|
invoke("upsertExtension", hostId, data),
|
|||
|
|
remove: (hostId: string): Promise<boolean> => invoke("deleteExtension", hostId),
|
|||
|
|
getEffectiveInterval: (hostId: string): Promise<number> =>
|
|||
|
|
invoke("getEffectiveInterval", hostId),
|
|||
|
|
getEnabled: (): Promise<DeviceExtension[]> => invoke("getEnabledDevices"),
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// ---------- 告警规则 ----------
|
|||
|
|
export const inspectionAlertRuleApi = {
|
|||
|
|
list: (): Promise<AlertRule[]> => invoke("listRules"),
|
|||
|
|
get: (ruleId: string): Promise<AlertRule | null> => invoke("getRule", ruleId),
|
|||
|
|
create: (data: Partial<AlertRule>): Promise<AlertRule> => invoke("createRule", data),
|
|||
|
|
update: (ruleId: string, updates: Partial<AlertRule>): Promise<AlertRule | null> =>
|
|||
|
|
invoke("updateRule", ruleId, updates),
|
|||
|
|
remove: (ruleId: string): Promise<boolean> => invoke("deleteRule", ruleId),
|
|||
|
|
toggle: (ruleId: string, enabled: boolean): Promise<AlertRule | null> =>
|
|||
|
|
invoke("toggleRule", ruleId, enabled),
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// ---------- 巡检结果 ----------
|
|||
|
|
export const inspectionResultApi = {
|
|||
|
|
getLatestAll: (): Promise<InspectionResult[]> => invoke("getLatestAll"),
|
|||
|
|
getLatestByDevice: (hostId: string, limit = 20): Promise<InspectionResult[]> =>
|
|||
|
|
invoke("getLatestByDevice", hostId, limit),
|
|||
|
|
getRecent: (limit = 50): Promise<InspectionResult[]> =>
|
|||
|
|
invoke("getRecentResults", limit),
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// ---------- 告警记录 ----------
|
|||
|
|
export const inspectionAlertApi = {
|
|||
|
|
list: (options?: {
|
|||
|
|
status?: AlertRecordStatus;
|
|||
|
|
level?: AlertLevel;
|
|||
|
|
device_id?: string;
|
|||
|
|
limit?: number;
|
|||
|
|
}): Promise<AlertRecord[]> => invoke("listAlerts", options),
|
|||
|
|
getActive: (): Promise<AlertRecord[]> => invoke("getActiveAlerts"),
|
|||
|
|
getStats: (): Promise<AlertStats> => invoke("getAlertStats"),
|
|||
|
|
acknowledge: (alertId: string, operator = "system"): Promise<AlertRecord | null> =>
|
|||
|
|
invoke("acknowledgeAlert", alertId, operator),
|
|||
|
|
resolve: (
|
|||
|
|
alertId: string,
|
|||
|
|
reason = "manual",
|
|||
|
|
operator = "system",
|
|||
|
|
): Promise<AlertRecord | null> =>
|
|||
|
|
invoke("resolveAlert", alertId, reason, operator),
|
|||
|
|
close: (alertId: string, note = ""): Promise<AlertRecord | null> =>
|
|||
|
|
invoke("closeAlert", alertId, note),
|
|||
|
|
updateNote: (alertId: string, note: string): Promise<AlertRecord | null> =>
|
|||
|
|
invoke("updateAlertNote", alertId, note),
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// ---------- 调度器 ----------
|
|||
|
|
// SSHConfig 是用于 SSH 连接的主机配置(hostname/port/username/password/privateKey 等)
|
|||
|
|
export type SshHostConfig = Record<string, unknown>;
|
|||
|
|
|
|||
|
|
export const inspectionSchedulerApi = {
|
|||
|
|
start: (hostConfigs?: Record<string, SshHostConfig>): Promise<SchedulerStatus> =>
|
|||
|
|
invoke("schedulerStart", hostConfigs ? { hostConfigs } : {}),
|
|||
|
|
stop: (): Promise<SchedulerStatus> => invoke("schedulerStop"),
|
|||
|
|
status: (): Promise<SchedulerStatus> => invoke("schedulerStatus"),
|
|||
|
|
scanNow: (hostId: string): Promise<any> => invoke("scanNow", hostId),
|
|||
|
|
scanAllNow: (): Promise<any> => invoke("scanAllNow"),
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// ---------- 单次巡检执行 ----------
|
|||
|
|
export interface RunInspectionResult {
|
|||
|
|
success: boolean;
|
|||
|
|
status: string;
|
|||
|
|
metrics: Record<string, any>;
|
|||
|
|
error: string | null;
|
|||
|
|
duration: number;
|
|||
|
|
alerts: any[];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface HostConfigForInspection {
|
|||
|
|
id: string;
|
|||
|
|
label?: string;
|
|||
|
|
hostname: string;
|
|||
|
|
port?: number;
|
|||
|
|
username: string;
|
|||
|
|
password?: string;
|
|||
|
|
privateKeyContent?: string;
|
|||
|
|
passphrase?: string;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export const inspectionExecApi = {
|
|||
|
|
/**
|
|||
|
|
* 执行一次完整巡检(前端传入完整主机配置)
|
|||
|
|
* @param hostId 主机 ID
|
|||
|
|
* @param hostConfig 主机连接配置
|
|||
|
|
* @param catalogId 设备类型 ID(采集器 ID)
|
|||
|
|
*/
|
|||
|
|
runInspection: (
|
|||
|
|
hostId: string,
|
|||
|
|
hostConfig: HostConfigForInspection,
|
|||
|
|
catalogId: string
|
|||
|
|
): Promise<RunInspectionResult> =>
|
|||
|
|
invoke("runInspection", { hostId, hostConfig, catalogId }),
|
|||
|
|
};
|