chore: version 1.0.6 - simplify YAML configuration
- Remove service.name and service.language (unused) - Remove enabled flags on outputs (presence = enabled) - Simplify correlation config: time_window_s (integer) instead of nested object - Simplify orphan_policy to emit_orphans boolean - Rename apache socket to http.socket - Add socket_permissions option for unix sockets (default: 0660) - Update tests for new configuration format Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@ -3,6 +3,7 @@ package config
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -11,7 +12,6 @@ import (
|
||||
|
||||
// Config holds the complete application configuration.
|
||||
type Config struct {
|
||||
Service ServiceConfig `yaml:"service"`
|
||||
Inputs InputsConfig `yaml:"inputs"`
|
||||
Outputs OutputsConfig `yaml:"outputs"`
|
||||
Correlation CorrelationConfig `yaml:"correlation"`
|
||||
@ -30,23 +30,23 @@ type InputsConfig struct {
|
||||
|
||||
// UnixSocketConfig holds a Unix socket source configuration.
|
||||
type UnixSocketConfig struct {
|
||||
Name string `yaml:"name"`
|
||||
Path string `yaml:"path"`
|
||||
Format string `yaml:"format"`
|
||||
SourceType string `yaml:"source_type"` // "A" for Apache/HTTP, "B" for Network
|
||||
Name string `yaml:"name"`
|
||||
Path string `yaml:"path"`
|
||||
Format string `yaml:"format"`
|
||||
SourceType string `yaml:"source_type"` // "A" for Apache/HTTP, "B" for Network
|
||||
SocketPermissions string `yaml:"socket_permissions"` // octal string, e.g., "0660", "0666"
|
||||
}
|
||||
|
||||
// OutputsConfig holds output sinks configuration.
|
||||
type OutputsConfig struct {
|
||||
File FileOutputConfig `yaml:"file"`
|
||||
ClickHouse ClickHouseOutputConfig `yaml:"clickhouse"`
|
||||
Stdout StdoutOutputConfig `yaml:"stdout"`
|
||||
Stdout bool `yaml:"stdout"`
|
||||
}
|
||||
|
||||
// FileOutputConfig holds file sink configuration.
|
||||
type FileOutputConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Path string `yaml:"path"`
|
||||
Path string `yaml:"path"`
|
||||
}
|
||||
|
||||
// ClickHouseOutputConfig holds ClickHouse sink configuration.
|
||||
@ -63,27 +63,15 @@ type ClickHouseOutputConfig struct {
|
||||
}
|
||||
|
||||
// StdoutOutputConfig holds stdout sink configuration.
|
||||
// Deprecated: stdout is now a boolean flag in OutputsConfig.
|
||||
type StdoutOutputConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
// CorrelationConfig holds correlation configuration.
|
||||
type CorrelationConfig struct {
|
||||
Key []string `yaml:"key"`
|
||||
TimeWindow TimeWindowConfig `yaml:"time_window"`
|
||||
OrphanPolicy OrphanPolicyConfig `yaml:"orphan_policy"`
|
||||
}
|
||||
|
||||
// TimeWindowConfig holds time window configuration.
|
||||
type TimeWindowConfig struct {
|
||||
Value int `yaml:"value"`
|
||||
Unit string `yaml:"unit"`
|
||||
}
|
||||
|
||||
// OrphanPolicyConfig holds orphan event policy configuration.
|
||||
type OrphanPolicyConfig struct {
|
||||
ApacheAlwaysEmit bool `yaml:"apache_always_emit"`
|
||||
NetworkEmit bool `yaml:"network_emit"`
|
||||
TimeWindowS int `yaml:"time_window_s"`
|
||||
EmitOrphans bool `yaml:"emit_orphans"`
|
||||
}
|
||||
|
||||
// Load loads configuration from a YAML file.
|
||||
@ -109,17 +97,12 @@ func Load(path string) (*Config, error) {
|
||||
// defaultConfig returns a Config with default values.
|
||||
func defaultConfig() *Config {
|
||||
return &Config{
|
||||
Service: ServiceConfig{
|
||||
Name: "logcorrelator",
|
||||
Language: "go",
|
||||
},
|
||||
Inputs: InputsConfig{
|
||||
UnixSockets: make([]UnixSocketConfig, 0),
|
||||
},
|
||||
Outputs: OutputsConfig{
|
||||
File: FileOutputConfig{
|
||||
Enabled: true,
|
||||
Path: "/var/log/logcorrelator/correlated.log",
|
||||
Path: "/var/log/logcorrelator/correlated.log",
|
||||
},
|
||||
ClickHouse: ClickHouseOutputConfig{
|
||||
Enabled: false,
|
||||
@ -130,20 +113,11 @@ func defaultConfig() *Config {
|
||||
AsyncInsert: true,
|
||||
TimeoutMs: 1000,
|
||||
},
|
||||
Stdout: StdoutOutputConfig{
|
||||
Enabled: false,
|
||||
},
|
||||
Stdout: false,
|
||||
},
|
||||
Correlation: CorrelationConfig{
|
||||
Key: []string{"src_ip", "src_port"},
|
||||
TimeWindow: TimeWindowConfig{
|
||||
Value: 1,
|
||||
Unit: "s",
|
||||
},
|
||||
OrphanPolicy: OrphanPolicyConfig{
|
||||
ApacheAlwaysEmit: true,
|
||||
NetworkEmit: false,
|
||||
},
|
||||
TimeWindowS: 1,
|
||||
EmitOrphans: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -176,12 +150,20 @@ func (c *Config) Validate() error {
|
||||
seenPaths[input.Path] = struct{}{}
|
||||
}
|
||||
|
||||
if !c.Outputs.File.Enabled && !c.Outputs.ClickHouse.Enabled && !c.Outputs.Stdout.Enabled {
|
||||
return fmt.Errorf("at least one output must be enabled")
|
||||
// At least one output must be enabled
|
||||
hasOutput := false
|
||||
if c.Outputs.File.Path != "" {
|
||||
hasOutput = true
|
||||
}
|
||||
if c.Outputs.ClickHouse.Enabled {
|
||||
hasOutput = true
|
||||
}
|
||||
if c.Outputs.Stdout {
|
||||
hasOutput = true
|
||||
}
|
||||
|
||||
if c.Outputs.File.Enabled && strings.TrimSpace(c.Outputs.File.Path) == "" {
|
||||
return fmt.Errorf("file output path is required when file output is enabled")
|
||||
if !hasOutput {
|
||||
return fmt.Errorf("at least one output must be enabled (file, clickhouse, or stdout)")
|
||||
}
|
||||
|
||||
if c.Outputs.ClickHouse.Enabled {
|
||||
@ -202,11 +184,8 @@ func (c *Config) Validate() error {
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.Correlation.Key) == 0 {
|
||||
return fmt.Errorf("correlation.key cannot be empty")
|
||||
}
|
||||
if c.Correlation.TimeWindow.Value <= 0 {
|
||||
return fmt.Errorf("correlation.time_window.value must be > 0")
|
||||
if c.Correlation.TimeWindowS <= 0 {
|
||||
return fmt.Errorf("correlation.time_window_s must be > 0")
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -214,24 +193,25 @@ func (c *Config) Validate() error {
|
||||
|
||||
// GetTimeWindow returns the time window as a duration.
|
||||
func (c *CorrelationConfig) GetTimeWindow() time.Duration {
|
||||
value := c.TimeWindow.Value
|
||||
value := c.TimeWindowS
|
||||
if value <= 0 {
|
||||
value = 1
|
||||
}
|
||||
|
||||
unit := c.TimeWindow.Unit
|
||||
if unit == "" {
|
||||
unit = "s"
|
||||
}
|
||||
|
||||
switch unit {
|
||||
case "ms", "millisecond", "milliseconds":
|
||||
return time.Duration(value) * time.Millisecond
|
||||
case "s", "second", "seconds":
|
||||
return time.Duration(value) * time.Second
|
||||
case "m", "minute", "minutes":
|
||||
return time.Duration(value) * time.Minute
|
||||
default:
|
||||
return time.Duration(value) * time.Second
|
||||
}
|
||||
return time.Duration(value) * time.Second
|
||||
}
|
||||
|
||||
// GetSocketPermissions returns the socket permissions as os.FileMode.
|
||||
// Default is 0660 (owner + group read/write).
|
||||
func (c *UnixSocketConfig) GetSocketPermissions() os.FileMode {
|
||||
if c.SocketPermissions == "" {
|
||||
return 0660
|
||||
}
|
||||
|
||||
// Parse octal string (e.g., "0660", "660", "0666")
|
||||
perms, err := strconv.ParseUint(strings.TrimPrefix(c.SocketPermissions, "0"), 8, 32)
|
||||
if err != nil {
|
||||
return 0660
|
||||
}
|
||||
|
||||
return os.FileMode(perms)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user