package models import "time" // Collector 日志采集器(部署客户端),关联一个已部署的 Loki 作为推送目标 type Collector struct { ID uint `json:"id"` Name string `json:"name"` Type string `json:"type"` // host-promtail | k8s-daemonset | k8s-fluentbit-sidecar LokiDeploymentID uint `json:"lokiDeploymentID"` LokiDeployment *LokiDeployment `json:"lokiDeployment,omitempty"` RefType string `json:"refType"` // host | cluster HostID *uint `json:"hostID,omitempty"` Host *Host `json:"host,omitempty"` ClusterID *uint `json:"clusterID,omitempty"` Cluster *Cluster `json:"cluster,omitempty"` TargetDeployment string `json:"targetDeployment"` // sidecar 专用:目标 deployment 名 Namespace string `json:"namespace"` // 采集器自身部署所在的 k8s 命名空间 // AppLabelSource 决定 app 标签从哪里取值(可填私有标签,便于按自己的规范匹配)。 // 留空 = 默认:app.kubernetes.io/name → app → Pod 的 controller_name(去 hash) → pod 名 // 可填:controller_name / app.kubernetes.io/name / app / k8s.kuboard.cn/name 等任意 Pod 标签 AppLabelSource string `json:"appLabelSource"` // AppInclude 只采集这些 app 的日志(白名单,按 AppLabelSource 解析出的 app 值匹配)。 // 留空 = 不限制。配合 TargetNamespaces 可显著收敛日志量。 AppInclude []string `json:"appInclude"` // TargetNamespaces 只采集这些命名空间的 Pod 日志;为空表示采集全集群。 // 对应 promtail 里 kubernetes_sd_configs.namespaces.names TargetNamespaces []string `json:"targetNamespaces"` LogPath string `json:"logPath"` // 采集日志路径 Labels string `json:"labels"` // 额外标签(JSON) // ScrapeJobs 主机模式的结构化采集项(多 job / 多路径 / 多行合并 / 丢弃 / 限流)。 // 为空时按 LogPath 生成默认的两个 job(app + system),保持旧行为。 ScrapeJobs []ScrapeJob `json:"scrapeJobs,omitempty"` // ResolvedHostname / SyslogFormat 是上一次安装到目标机时探测到的真实值。 // 用途:① host 标签写真实主机名(不再写 ${HOSTNAME});② 系统日志按目标机 // 实际格式(ISO8601 vs 传统 syslog)选正则 —— 这两条是安装期才能知道的信息, // 存下来才能让「配置预览」和线上真实配置一致。 // SystemLogPaths 安装时探测到的系统日志绝对路径(Ubuntu/Debian 与 RHEL 系不同), // 存下来让「预览配置」和实际下发保持一致。 SystemLogPaths []string `json:"systemLogPaths,omitempty"` ResolvedHostname string `json:"resolvedHostname,omitempty"` SyslogFormat string `json:"syslogFormat,omitempty"` // iso8601 | syslog Status string `json:"status"` // pending | active | error StatusMessage string `json:"statusMessage"` Config string `json:"config"` // 生成的配置快照 CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } func (c *Collector) Sanitized() map[string]interface{} { var loki map[string]interface{} if c.LokiDeployment != nil { loki = map[string]interface{}{ "id": c.LokiDeployment.ID, "name": c.LokiDeployment.Name, "endpoint": c.LokiDeployment.Endpoint, "status": c.LokiDeployment.Status, } } var host map[string]interface{} if c.Host != nil { host = c.Host.Sanitized() } var cluster map[string]interface{} if c.Cluster != nil { cluster = c.Cluster.Sanitized() } return map[string]interface{}{ "id": c.ID, "name": c.Name, "type": c.Type, "lokiDeploymentID": c.LokiDeploymentID, "lokiDeployment": loki, "refType": c.RefType, "hostID": c.HostID, "host": host, "clusterID": c.ClusterID, "cluster": cluster, "targetDeployment": c.TargetDeployment, "namespace": c.Namespace, // 采集范围配置:必须一起输出,否则前端编辑框读不到(显示为空), // 用户一保存就会把现有配置写空 —— 这是重构加 Sanitized() 时漏字段导致的回归。 "targetNamespaces": c.TargetNamespaces, "appLabelSource": c.AppLabelSource, "appInclude": c.AppInclude, "logPath": c.LogPath, "labels": c.Labels, "scrapeJobs": c.ScrapeJobs, "systemLogPaths": c.SystemLogPaths, "resolvedHostname": c.ResolvedHostname, "syslogFormat": c.SyslogFormat, "status": c.Status, "statusMessage": c.StatusMessage, "createdAt": c.CreatedAt, "updatedAt": c.UpdatedAt, } }