package config import ( "fmt" "net" "net/url" "strconv" "strings" "git.apinb.com/bsm-sdk/core/conf" ) var Spec SrvConfig type AlertForwardConf struct { BaseURL string `yaml:"base_url"` InternalKey string `yaml:"internal_key"` Enabled bool `yaml:"enabled"` DefaultPolicyID uint `yaml:"default_policy_id"` } type IngestConf struct { SyslogListenAddr string `yaml:"syslog_listen_addr"` TrapListenAddr string `yaml:"trap_listen_addr"` RuleRefreshSecs int `yaml:"rule_refresh_secs"` } type ResourceEventConf struct { // HMACSecret 用于校验 dc-control 推送签名(X-Event-Signature)。 HMACSecret string `yaml:"hmac_secret"` // MaxSkewSecs 允许事件时间与服务端时间的最大偏差(秒)。 MaxSkewSecs int `yaml:"max_skew_secs"` } type OTLPConf struct { InternalKey string `yaml:"internal_key"` } type SystemSettingsConf struct { BaseURL string `yaml:"base_url"` RefreshSeconds int `yaml:"refresh_seconds"` TimeoutSeconds int `yaml:"timeout_seconds"` } type SrvConfig struct { conf.Base `yaml:",inline"` Databases *conf.DBConf `yaml:"Databases"` MicroService *conf.MicroServiceConf `yaml:"MicroService"` Rpc map[string]conf.RpcConf `yaml:"Rpc"` Gateway *conf.GatewayConf `yaml:"Gateway"` Apm *conf.ApmConf `yaml:"APM"` AlertForward *AlertForwardConf `yaml:"AlertForward"` Ingest IngestConf `yaml:"Ingest"` ResourceEvent ResourceEventConf `yaml:"ResourceEvent"` OTLP OTLPConf `yaml:"OTLP"` SystemSettings SystemSettingsConf `yaml:"SystemSettings"` } func New(srvKey string) { conf.New(srvKey, &Spec) if err := Validate(); err != nil { panic(fmt.Errorf("logs 配置校验失败: %w", err)) } Spec.Addr = net.JoinHostPort(Spec.BindIP, Spec.Port) conf.PrintInfo(Spec.Addr) } // Validate 校验日志服务配置,不生成随机端口、监听地址或刷新间隔。 func Validate() error { Spec.Service = strings.TrimSpace(Spec.Service) Spec.Port = strings.TrimSpace(Spec.Port) Spec.BindIP = strings.TrimSpace(Spec.BindIP) Spec.ResourceEvent.HMACSecret = strings.TrimSpace(Spec.ResourceEvent.HMACSecret) Spec.OTLP.InternalKey = strings.TrimSpace(Spec.OTLP.InternalKey) Spec.SystemSettings.BaseURL = strings.TrimRight(strings.TrimSpace(Spec.SystemSettings.BaseURL), "/") if Spec.Service == "" { return fmt.Errorf("Service 不能为空") } port, err := strconv.Atoi(Spec.Port) if err != nil || port < 1 || port > 65535 { return fmt.Errorf("Port 必须是 1 到 65535 的整数") } if net.ParseIP(Spec.BindIP) == nil { return fmt.Errorf("BindIP 必须是明确的 IPv4 或 IPv6 地址") } if Spec.Databases == nil || strings.TrimSpace(Spec.Databases.Driver) == "" || len(Spec.Databases.Source) == 0 { return fmt.Errorf("Databases.Driver 和 Databases.Source 不能为空") } if strings.TrimSpace(Spec.Cache) == "" { return fmt.Errorf("Cache 不能为空") } if Spec.ResourceEvent.HMACSecret == "" || Spec.ResourceEvent.MaxSkewSecs <= 0 { return fmt.Errorf("ResourceEvent.hmac_secret 和 max_skew_secs 必须有效") } if Spec.OTLP.InternalKey == "" { return fmt.Errorf("OTLP.internal_key 不能为空") } parsedSystemSettingsURL, err := url.Parse(Spec.SystemSettings.BaseURL) if err != nil || parsedSystemSettingsURL.Host == "" || (parsedSystemSettingsURL.Scheme != "http" && parsedSystemSettingsURL.Scheme != "https") { return fmt.Errorf("SystemSettings.base_url 必须是完整的 HTTP 或 HTTPS 地址") } if Spec.SystemSettings.RefreshSeconds <= 0 || Spec.SystemSettings.TimeoutSeconds <= 0 { return fmt.Errorf("SystemSettings.refresh_seconds 和 timeout_seconds 必须大于 0") } if Spec.Ingest.RuleRefreshSecs <= 0 { return fmt.Errorf("Ingest.rule_refresh_secs 必须大于 0") } for name, addr := range map[string]string{ "syslog_listen_addr": Spec.Ingest.SyslogListenAddr, "trap_listen_addr": Spec.Ingest.TrapListenAddr, } { addr = strings.TrimSpace(addr) if addr == "" { continue } if _, err := net.ResolveUDPAddr("udp", addr); err != nil { return fmt.Errorf("Ingest.%s 无效: %w", name, err) } } if Spec.AlertForward != nil && Spec.AlertForward.Enabled { Spec.AlertForward.BaseURL = strings.TrimSpace(Spec.AlertForward.BaseURL) Spec.AlertForward.InternalKey = strings.TrimSpace(Spec.AlertForward.InternalKey) parsed, err := url.Parse(Spec.AlertForward.BaseURL) if err != nil || parsed.Host == "" || (parsed.Scheme != "http" && parsed.Scheme != "https") { return fmt.Errorf("AlertForward.base_url 必须是完整的 HTTP 或 HTTPS 地址") } if Spec.AlertForward.InternalKey == "" { return fmt.Errorf("AlertForward.internal_key 不能为空") } } return nil }