mirror of
https://github.com/wneessen/logranger.git
synced 2024-12-22 10:00:38 +01:00
Refactor variable names for improved code readability
The changes involved refactor and clean-up of variable names. This encompasses making the names more descriptive and meaningful to enhance the readability of the code. Accuracy of variable names in conveying their usage and purpose has been greatly improved. The changes span across multiple files, touching crucial components like the server, rulesets, connection, and configuration handling.
This commit is contained in:
parent
c86532d5d9
commit
80e30c6bda
8 changed files with 204 additions and 203 deletions
|
@ -20,49 +20,49 @@ const (
|
|||
)
|
||||
|
||||
func main() {
|
||||
l := slog.New(slog.NewJSONHandler(os.Stdout, nil)).With(slog.String("context", "logranger"))
|
||||
cp := "logranger.toml"
|
||||
cpe := os.Getenv("LOGRANGER_CONFIG")
|
||||
if cpe != "" {
|
||||
cp = cpe
|
||||
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)).With(slog.String("context", "logranger"))
|
||||
confPath := "logranger.toml"
|
||||
confPathEnv := os.Getenv("LOGRANGER_CONFIG")
|
||||
if confPathEnv != "" {
|
||||
confPath = confPathEnv
|
||||
}
|
||||
|
||||
p := filepath.Dir(cp)
|
||||
f := filepath.Base(cp)
|
||||
c, err := logranger.NewConfig(p, f)
|
||||
path := filepath.Dir(confPath)
|
||||
file := filepath.Base(confPath)
|
||||
config, err := logranger.NewConfig(path, file)
|
||||
if err != nil {
|
||||
l.Error("failed to read/parse config", LogErrKey, err)
|
||||
logger.Error("failed to read/parse config", LogErrKey, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
s, err := logranger.New(c)
|
||||
server, err := logranger.New(config)
|
||||
if err != nil {
|
||||
l.Error("failed to create new server", LogErrKey, err)
|
||||
logger.Error("failed to create new server", LogErrKey, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err = s.Run(); err != nil {
|
||||
l.Error("failed to start logranger", LogErrKey, err)
|
||||
if err = server.Run(); err != nil {
|
||||
logger.Error("failed to start logranger", LogErrKey, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
|
||||
sc := make(chan os.Signal, 1)
|
||||
signal.Notify(sc)
|
||||
for rc := range sc {
|
||||
if rc == syscall.SIGKILL || rc == syscall.SIGABRT || rc == syscall.SIGINT || rc == syscall.SIGTERM {
|
||||
l.Warn("received signal. shutting down server", slog.String("signal", rc.String()))
|
||||
// s.Stop()
|
||||
l.Info("server gracefully shut down")
|
||||
signalChan := make(chan os.Signal, 1)
|
||||
signal.Notify(signalChan)
|
||||
for recvSig := range signalChan {
|
||||
if recvSig == syscall.SIGKILL || recvSig == syscall.SIGABRT || recvSig == syscall.SIGINT || recvSig == syscall.SIGTERM {
|
||||
logger.Warn("received signal. shutting down server", slog.String("signal", recvSig.String()))
|
||||
// server.Stop()
|
||||
logger.Info("server gracefully shut down")
|
||||
os.Exit(0)
|
||||
}
|
||||
if rc == syscall.SIGHUP {
|
||||
l.Info(`received signal`,
|
||||
if recvSig == syscall.SIGHUP {
|
||||
logger.Info(`received signal`,
|
||||
slog.String("signal", "SIGHUP"),
|
||||
slog.String("action", "reloading config/ruleset"))
|
||||
if err = s.ReloadConfig(p, f); err != nil {
|
||||
l.Error("failed to reload config", LogErrKey, err)
|
||||
if err = server.ReloadConfig(path, file); err != nil {
|
||||
logger.Error("failed to reload config", LogErrKey, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
24
config.go
24
config.go
|
@ -56,25 +56,25 @@ type Config struct {
|
|||
// configuration values. It takes in the file path and file name of the configuration
|
||||
// file as parameters. It returns a pointer to the Config object and an error if
|
||||
// there was a problem reading or loading the configuration.
|
||||
func NewConfig(p, f string) (*Config, error) {
|
||||
co := Config{}
|
||||
_, err := os.Stat(fmt.Sprintf("%s/%s", p, f))
|
||||
func NewConfig(path, file string) (*Config, error) {
|
||||
config := Config{}
|
||||
_, err := os.Stat(fmt.Sprintf("%s/%s", path, file))
|
||||
if err != nil {
|
||||
return &co, fmt.Errorf("failed to read config: %w", err)
|
||||
return &config, fmt.Errorf("failed to read config: %w", err)
|
||||
}
|
||||
|
||||
if err := fig.Load(&co, fig.Dirs(p), fig.File(f), fig.UseEnv("logranger")); err != nil {
|
||||
return &co, fmt.Errorf("failed to load config: %w", err)
|
||||
if err := fig.Load(&config, fig.Dirs(path), fig.File(file), fig.UseEnv("logranger")); err != nil {
|
||||
return &config, fmt.Errorf("failed to load config: %w", err)
|
||||
}
|
||||
|
||||
switch {
|
||||
case strings.EqualFold(co.Parser.Type, "rfc3164"):
|
||||
co.internal.ParserType = rfc3164.Type
|
||||
case strings.EqualFold(co.Parser.Type, "rfc5424"):
|
||||
co.internal.ParserType = rfc5424.Type
|
||||
case strings.EqualFold(config.Parser.Type, "rfc3164"):
|
||||
config.internal.ParserType = rfc3164.Type
|
||||
case strings.EqualFold(config.Parser.Type, "rfc5424"):
|
||||
config.internal.ParserType = rfc5424.Type
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown parser type: %s", co.Parser.Type)
|
||||
return nil, fmt.Errorf("unknown parser type: %s", config.Parser.Type)
|
||||
}
|
||||
|
||||
return &co, nil
|
||||
return &config, nil
|
||||
}
|
||||
|
|
|
@ -22,14 +22,14 @@ type Connection struct {
|
|||
// NewConnection creates a new Connection object with the provided net.Conn.
|
||||
// The Connection object holds a reference to the provided net.Conn, along with an ID string,
|
||||
// bufio.Reader, and bufio.Writer. It returns a pointer to the created Connection object.
|
||||
func NewConnection(nc net.Conn) *Connection {
|
||||
c := &Connection{
|
||||
conn: nc,
|
||||
func NewConnection(netConn net.Conn) *Connection {
|
||||
connection := &Connection{
|
||||
conn: netConn,
|
||||
id: NewConnectionID(),
|
||||
rb: bufio.NewReader(nc),
|
||||
wb: bufio.NewWriter(nc),
|
||||
rb: bufio.NewReader(netConn),
|
||||
wb: bufio.NewWriter(netConn),
|
||||
}
|
||||
return c
|
||||
return connection
|
||||
}
|
||||
|
||||
// NewConnectionID generates a new unique message ID using a random number generator
|
||||
|
|
39
listener.go
39
listener.go
|
@ -26,42 +26,43 @@ const (
|
|||
// NewListener initializes and returns a net.Listener based on the provided
|
||||
// configuration. It takes a pointer to a Config struct as a parameter.
|
||||
// Returns the net.Listener and an error if any occurred during initialization.
|
||||
func NewListener(c *Config) (net.Listener, error) {
|
||||
var l net.Listener
|
||||
var lerr error
|
||||
switch c.Listener.Type {
|
||||
func NewListener(config *Config) (net.Listener, error) {
|
||||
var listener net.Listener
|
||||
var listenerErr error
|
||||
switch config.Listener.Type {
|
||||
case ListenerUnix:
|
||||
rua, err := net.ResolveUnixAddr("unix", c.Listener.ListenerUnix.Path)
|
||||
resolveUnixAddr, err := net.ResolveUnixAddr("unix", config.Listener.ListenerUnix.Path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to resolve UNIX listener socket: %w", err)
|
||||
}
|
||||
l, lerr = net.Listen("unix", rua.String())
|
||||
listener, listenerErr = net.Listen("unix", resolveUnixAddr.String())
|
||||
case ListenerTCP:
|
||||
la := net.JoinHostPort(c.Listener.ListenerTCP.Addr, fmt.Sprintf("%d", c.Listener.ListenerTCP.Port))
|
||||
l, lerr = net.Listen("tcp", la)
|
||||
listenAddr := net.JoinHostPort(config.Listener.ListenerTCP.Addr,
|
||||
fmt.Sprintf("%d", config.Listener.ListenerTCP.Port))
|
||||
listener, listenerErr = net.Listen("tcp", listenAddr)
|
||||
case ListenerTLS:
|
||||
if c.Listener.ListenerTLS.CertPath == "" || c.Listener.ListenerTLS.KeyPath == "" {
|
||||
if config.Listener.ListenerTLS.CertPath == "" || config.Listener.ListenerTLS.KeyPath == "" {
|
||||
return nil, ErrCertConfigEmpty
|
||||
}
|
||||
ce, err := tls.LoadX509KeyPair(c.Listener.ListenerTLS.CertPath, c.Listener.ListenerTLS.KeyPath)
|
||||
cert, err := tls.LoadX509KeyPair(config.Listener.ListenerTLS.CertPath, config.Listener.ListenerTLS.KeyPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load X509 certificate: %w", err)
|
||||
}
|
||||
la := net.JoinHostPort(c.Listener.ListenerTLS.Addr, fmt.Sprintf("%d", c.Listener.ListenerTLS.Port))
|
||||
lc := &tls.Config{Certificates: []tls.Certificate{ce}}
|
||||
l, lerr = tls.Listen("tcp", la, lc)
|
||||
listenAddr := net.JoinHostPort(config.Listener.ListenerTLS.Addr, fmt.Sprintf("%d", config.Listener.ListenerTLS.Port))
|
||||
listenConf := &tls.Config{Certificates: []tls.Certificate{cert}}
|
||||
listener, listenerErr = tls.Listen("tcp", listenAddr, listenConf)
|
||||
default:
|
||||
return nil, fmt.Errorf("failed to initialize listener: unknown listener type in config")
|
||||
}
|
||||
if lerr != nil {
|
||||
return nil, fmt.Errorf("failed to initialize listener: %w", lerr)
|
||||
if listenerErr != nil {
|
||||
return nil, fmt.Errorf("failed to initialize listener: %w", listenerErr)
|
||||
}
|
||||
return l, nil
|
||||
return listener, nil
|
||||
}
|
||||
|
||||
// UnmarshalString satisfies the fig.StringUnmarshaler interface for the ListenerType type
|
||||
func (l *ListenerType) UnmarshalString(v string) error {
|
||||
switch strings.ToLower(v) {
|
||||
func (l *ListenerType) UnmarshalString(value string) error {
|
||||
switch strings.ToLower(value) {
|
||||
case "unix":
|
||||
*l = ListenerUnix
|
||||
case "tcp":
|
||||
|
@ -69,7 +70,7 @@ func (l *ListenerType) UnmarshalString(v string) error {
|
|||
case "tls":
|
||||
*l = ListenerTLS
|
||||
default:
|
||||
return fmt.Errorf("unknown listener type: %s", v)
|
||||
return fmt.Errorf("unknown listener type: %s", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -34,29 +34,29 @@ type File struct {
|
|||
//
|
||||
// If any of the required configuration parameters are missing or invalid, an error
|
||||
// is returned.
|
||||
func (f *File) Config(cm map[string]any) error {
|
||||
if cm["file"] == nil {
|
||||
func (f *File) Config(configMap map[string]any) error {
|
||||
if configMap["file"] == nil {
|
||||
return nil
|
||||
}
|
||||
c, ok := cm["file"].(map[string]any)
|
||||
config, ok := configMap["file"].(map[string]any)
|
||||
if !ok {
|
||||
return fmt.Errorf("missing configuration for file action")
|
||||
}
|
||||
f.Enabled = true
|
||||
|
||||
fp, ok := c["output_filepath"].(string)
|
||||
if !ok || fp == "" {
|
||||
filePath, ok := config["output_filepath"].(string)
|
||||
if !ok || filePath == "" {
|
||||
return fmt.Errorf("no output_filename configured for file action")
|
||||
}
|
||||
f.FilePath = fp
|
||||
f.FilePath = filePath
|
||||
|
||||
ot, ok := c["output_template"].(string)
|
||||
if !ok || ot == "" {
|
||||
outputTpl, ok := config["output_template"].(string)
|
||||
if !ok || outputTpl == "" {
|
||||
return fmt.Errorf("not output_template configured for file action")
|
||||
}
|
||||
f.OutputTemplate = ot
|
||||
f.OutputTemplate = outputTpl
|
||||
|
||||
if ow, ok := c["overwrite"].(bool); ok && ow {
|
||||
if hasOverwrite, ok := config["overwrite"].(bool); ok && hasOverwrite {
|
||||
f.Overwrite = true
|
||||
}
|
||||
|
||||
|
@ -65,34 +65,34 @@ func (f *File) Config(cm map[string]any) error {
|
|||
|
||||
// Process satisfies the plugins.Action interface for the File type
|
||||
// It takes in the log message (lm), match groups (mg), and configuration map (cm).
|
||||
func (f *File) Process(lm parsesyslog.LogMsg, mg []string) error {
|
||||
func (f *File) Process(logMessage parsesyslog.LogMsg, matchGroup []string) error {
|
||||
if !f.Enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
of := os.O_APPEND | os.O_CREATE | os.O_WRONLY
|
||||
openFlags := os.O_APPEND | os.O_CREATE | os.O_WRONLY
|
||||
if f.Overwrite {
|
||||
of = os.O_TRUNC | os.O_CREATE | os.O_WRONLY
|
||||
openFlags = os.O_TRUNC | os.O_CREATE | os.O_WRONLY
|
||||
}
|
||||
|
||||
fh, err := os.OpenFile(f.FilePath, of, 0o600)
|
||||
fileHandle, err := os.OpenFile(f.FilePath, openFlags, 0o600)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open file for writing in file action: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = fh.Close()
|
||||
_ = fileHandle.Close()
|
||||
}()
|
||||
|
||||
t, err := template.Compile(lm, mg, f.OutputTemplate)
|
||||
tpl, err := template.Compile(logMessage, matchGroup, f.OutputTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = fh.WriteString(t)
|
||||
_, err = fileHandle.WriteString(tpl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write log message to file %q: %w",
|
||||
f.FilePath, err)
|
||||
}
|
||||
if err = fh.Sync(); err != nil {
|
||||
if err = fileHandle.Sync(); err != nil {
|
||||
return fmt.Errorf("failed to sync memory to file %q: %w",
|
||||
f.FilePath, err)
|
||||
}
|
||||
|
|
30
rule.go
30
rule.go
|
@ -32,28 +32,28 @@ type Rule struct {
|
|||
// existence, and loads the Ruleset using the fig library.
|
||||
// It checks for duplicate rules and returns an error if any duplicates are found.
|
||||
// If all operations are successful, it returns the created Ruleset and no error.
|
||||
func NewRuleset(c *Config) (*Ruleset, error) {
|
||||
rs := &Ruleset{}
|
||||
p := filepath.Dir(c.Server.RuleFile)
|
||||
f := filepath.Base(c.Server.RuleFile)
|
||||
_, err := os.Stat(fmt.Sprintf("%s/%s", p, f))
|
||||
func NewRuleset(config *Config) (*Ruleset, error) {
|
||||
ruleset := &Ruleset{}
|
||||
path := filepath.Dir(config.Server.RuleFile)
|
||||
file := filepath.Base(config.Server.RuleFile)
|
||||
_, err := os.Stat(fmt.Sprintf("%s/%s", path, file))
|
||||
if err != nil {
|
||||
return rs, fmt.Errorf("failed to read config: %w", err)
|
||||
return ruleset, fmt.Errorf("failed to read config: %w", err)
|
||||
}
|
||||
|
||||
if err = fig.Load(rs, fig.Dirs(p), fig.File(f), fig.UseStrict()); err != nil {
|
||||
return rs, fmt.Errorf("failed to load ruleset: %w", err)
|
||||
if err = fig.Load(ruleset, fig.Dirs(path), fig.File(file), fig.UseStrict()); err != nil {
|
||||
return ruleset, fmt.Errorf("failed to load ruleset: %w", err)
|
||||
}
|
||||
|
||||
rna := make([]string, 0)
|
||||
for _, r := range rs.Rule {
|
||||
for _, rn := range rna {
|
||||
if strings.EqualFold(r.ID, rn) {
|
||||
return nil, fmt.Errorf("duplicate rule found: %s", r.ID)
|
||||
rules := make([]string, 0)
|
||||
for _, rule := range ruleset.Rule {
|
||||
for _, rulename := range rules {
|
||||
if strings.EqualFold(rule.ID, rulename) {
|
||||
return nil, fmt.Errorf("duplicate rule found: %s", rule.ID)
|
||||
}
|
||||
}
|
||||
rna = append(rna, r.ID)
|
||||
rules = append(rules, rule.ID)
|
||||
}
|
||||
|
||||
return rs, nil
|
||||
return ruleset, nil
|
||||
}
|
||||
|
|
122
server.go
122
server.go
|
@ -45,62 +45,62 @@ type Server struct {
|
|||
}
|
||||
|
||||
// New creates a new instance of Server based on the provided Config
|
||||
func New(c *Config) (*Server, error) {
|
||||
s := &Server{
|
||||
conf: c,
|
||||
func New(config *Config) (*Server, error) {
|
||||
server := &Server{
|
||||
conf: config,
|
||||
}
|
||||
|
||||
s.setLogLevel()
|
||||
server.setLogLevel()
|
||||
|
||||
if err := s.setRules(); err != nil {
|
||||
return s, err
|
||||
if err := server.setRules(); err != nil {
|
||||
return server, err
|
||||
}
|
||||
|
||||
p, err := parsesyslog.New(s.conf.internal.ParserType)
|
||||
parser, err := parsesyslog.New(server.conf.internal.ParserType)
|
||||
if err != nil {
|
||||
return s, fmt.Errorf("failed to initialize syslog parser: %w", err)
|
||||
return server, fmt.Errorf("failed to initialize syslog parser: %w", err)
|
||||
}
|
||||
s.parser = p
|
||||
server.parser = parser
|
||||
|
||||
if len(actions.Actions) <= 0 {
|
||||
return s, fmt.Errorf("no action plugins found/configured")
|
||||
return server, fmt.Errorf("no action plugins found/configured")
|
||||
}
|
||||
|
||||
return s, nil
|
||||
return server, nil
|
||||
}
|
||||
|
||||
// Run starts the logranger Server by creating a new listener using the NewListener
|
||||
// method and calling RunWithListener with the obtained listener.
|
||||
func (s *Server) Run() error {
|
||||
l, err := NewListener(s.conf)
|
||||
listener, err := NewListener(s.conf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.RunWithListener(l)
|
||||
return s.RunWithListener(listener)
|
||||
}
|
||||
|
||||
// RunWithListener sets the listener for the server and performs some additional
|
||||
// tasks for initializing the server. It creates a PID file, writes the process ID
|
||||
// to the file, and listens for connections. It returns an error if any of the
|
||||
// initialization steps fail.
|
||||
func (s *Server) RunWithListener(l net.Listener) error {
|
||||
s.listener = l
|
||||
func (s *Server) RunWithListener(listener net.Listener) error {
|
||||
s.listener = listener
|
||||
|
||||
// Create PID file
|
||||
pf, err := os.Create(s.conf.Server.PIDFile)
|
||||
pidFile, err := os.Create(s.conf.Server.PIDFile)
|
||||
if err != nil {
|
||||
s.log.Error("failed to create PID file", LogErrKey, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
pid := os.Getpid()
|
||||
s.log.Debug("creating PID file", slog.String("pid_file", pf.Name()),
|
||||
s.log.Debug("creating PID file", slog.String("pid_file", pidFile.Name()),
|
||||
slog.Int("pid", pid))
|
||||
_, err = pf.WriteString(fmt.Sprintf("%d", pid))
|
||||
_, err = pidFile.WriteString(fmt.Sprintf("%d", pid))
|
||||
if err != nil {
|
||||
s.log.Error("failed to write PID to PID file", LogErrKey, err)
|
||||
_ = pf.Close()
|
||||
_ = pidFile.Close()
|
||||
}
|
||||
if err = pf.Close(); err != nil {
|
||||
if err = pidFile.Close(); err != nil {
|
||||
s.log.Error("failed to close PID file", LogErrKey, err)
|
||||
}
|
||||
|
||||
|
@ -116,47 +116,47 @@ func (s *Server) Listen() {
|
|||
defer s.wg.Done()
|
||||
s.log.Info("listening for new connections", slog.String("listen_addr", s.listener.Addr().String()))
|
||||
for {
|
||||
c, err := s.listener.Accept()
|
||||
acceptConn, err := s.listener.Accept()
|
||||
if err != nil {
|
||||
s.log.Error("failed to accept new connection", LogErrKey, err)
|
||||
continue
|
||||
}
|
||||
s.log.Debug("accepted new connection",
|
||||
slog.String("remote_addr", c.RemoteAddr().String()))
|
||||
conn := NewConnection(c)
|
||||
slog.String("remote_addr", acceptConn.RemoteAddr().String()))
|
||||
connection := NewConnection(acceptConn)
|
||||
s.wg.Add(1)
|
||||
go func(co *Connection) {
|
||||
s.HandleConnection(co)
|
||||
s.wg.Done()
|
||||
}(conn)
|
||||
}(connection)
|
||||
}
|
||||
}
|
||||
|
||||
// HandleConnection handles a single connection by parsing and processing log messages.
|
||||
// It logs debug information about the connection and measures the processing time.
|
||||
// It closes the connection when done, and logs any error encountered during the process.
|
||||
func (s *Server) HandleConnection(c *Connection) {
|
||||
func (s *Server) HandleConnection(connection *Connection) {
|
||||
defer func() {
|
||||
if err := c.conn.Close(); err != nil {
|
||||
if err := connection.conn.Close(); err != nil {
|
||||
s.log.Error("failed to close connection", LogErrKey, err)
|
||||
}
|
||||
}()
|
||||
|
||||
ReadLoop:
|
||||
for {
|
||||
if err := c.conn.SetDeadline(time.Now().Add(s.conf.Parser.Timeout)); err != nil {
|
||||
if err := connection.conn.SetDeadline(time.Now().Add(s.conf.Parser.Timeout)); err != nil {
|
||||
s.log.Error("failed to set processing deadline", LogErrKey, err,
|
||||
slog.Duration("timeout", s.conf.Parser.Timeout))
|
||||
return
|
||||
}
|
||||
lm, err := s.parser.ParseReader(c.rb)
|
||||
logMessage, err := s.parser.ParseReader(connection.rb)
|
||||
if err != nil {
|
||||
var ne *net.OpError
|
||||
var netErr *net.OpError
|
||||
switch {
|
||||
case errors.As(err, &ne):
|
||||
case errors.As(err, &netErr):
|
||||
if s.conf.Log.Extended {
|
||||
s.log.Error("network error while processing message", LogErrKey,
|
||||
ne.Error())
|
||||
netErr.Error())
|
||||
}
|
||||
return
|
||||
case errors.Is(err, io.EOF):
|
||||
|
@ -172,7 +172,7 @@ ReadLoop:
|
|||
}
|
||||
}
|
||||
s.wg.Add(1)
|
||||
go s.processMessage(lm)
|
||||
go s.processMessage(logMessage)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,36 +182,36 @@ ReadLoop:
|
|||
// The method first checks if the ruleset is not nil. If it is nil, no actions will be
|
||||
// executed. For each rule in the ruleset, it checks if the log message matches the
|
||||
// rule's regular expression.
|
||||
func (s *Server) processMessage(lm parsesyslog.LogMsg) {
|
||||
func (s *Server) processMessage(logMessage parsesyslog.LogMsg) {
|
||||
defer s.wg.Done()
|
||||
if s.ruleset != nil {
|
||||
for _, r := range s.ruleset.Rule {
|
||||
if !r.Regexp.MatchString(lm.Message.String()) {
|
||||
for _, rule := range s.ruleset.Rule {
|
||||
if !rule.Regexp.MatchString(logMessage.Message.String()) {
|
||||
continue
|
||||
}
|
||||
if r.HostMatch != nil && !r.HostMatch.MatchString(lm.Hostname) {
|
||||
if rule.HostMatch != nil && !rule.HostMatch.MatchString(logMessage.Hostname) {
|
||||
continue
|
||||
}
|
||||
mg := r.Regexp.FindStringSubmatch(lm.Message.String())
|
||||
for n, a := range actions.Actions {
|
||||
bt := time.Now()
|
||||
if err := a.Config(r.Actions); err != nil {
|
||||
matchGroup := rule.Regexp.FindStringSubmatch(logMessage.Message.String())
|
||||
for name, action := range actions.Actions {
|
||||
startTime := time.Now()
|
||||
if err := action.Config(rule.Actions); err != nil {
|
||||
s.log.Error("failed to config action", LogErrKey, err,
|
||||
slog.String("action", n), slog.String("rule_id", r.ID))
|
||||
slog.String("action", name), slog.String("rule_id", rule.ID))
|
||||
continue
|
||||
}
|
||||
s.log.Debug("log message matches rule, executing action",
|
||||
slog.String("action", n), slog.String("rule_id", r.ID))
|
||||
if err := a.Process(lm, mg); err != nil {
|
||||
slog.String("action", name), slog.String("rule_id", rule.ID))
|
||||
if err := action.Process(logMessage, matchGroup); err != nil {
|
||||
s.log.Error("failed to process action", LogErrKey, err,
|
||||
slog.String("action", n), slog.String("rule_id", r.ID))
|
||||
slog.String("action", name), slog.String("rule_id", rule.ID))
|
||||
}
|
||||
if s.conf.Log.Extended {
|
||||
pt := time.Since(bt)
|
||||
procTime := time.Since(startTime)
|
||||
s.log.Debug("action processing benchmark",
|
||||
slog.Duration("processing_time", pt),
|
||||
slog.String("processing_time_human", pt.String()),
|
||||
slog.String("action", n), slog.String("rule_id", r.ID))
|
||||
slog.Duration("processing_time", procTime),
|
||||
slog.String("processing_time_human", procTime.String()),
|
||||
slog.String("action", name), slog.String("rule_id", rule.ID))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -226,21 +226,21 @@ func (s *Server) processMessage(lm parsesyslog.LogMsg) {
|
|||
// Finally, it creates a new `slog.Logger` with the JSON handler and sets the `s.log` field
|
||||
// of the `Server` struct to the logger, with a context value of "logranger".
|
||||
func (s *Server) setLogLevel() {
|
||||
lo := slog.HandlerOptions{}
|
||||
logOpts := slog.HandlerOptions{}
|
||||
switch strings.ToLower(s.conf.Log.Level) {
|
||||
case "debug":
|
||||
lo.Level = slog.LevelDebug
|
||||
logOpts.Level = slog.LevelDebug
|
||||
case "info":
|
||||
lo.Level = slog.LevelInfo
|
||||
logOpts.Level = slog.LevelInfo
|
||||
case "warn":
|
||||
lo.Level = slog.LevelWarn
|
||||
logOpts.Level = slog.LevelWarn
|
||||
case "error":
|
||||
lo.Level = slog.LevelError
|
||||
logOpts.Level = slog.LevelError
|
||||
default:
|
||||
lo.Level = slog.LevelInfo
|
||||
logOpts.Level = slog.LevelInfo
|
||||
}
|
||||
lh := slog.NewJSONHandler(os.Stdout, &lo)
|
||||
s.log = slog.New(lh).With(slog.String("context", "logranger"))
|
||||
logHandler := slog.NewJSONHandler(os.Stdout, &logOpts)
|
||||
s.log = slog.New(logHandler).With(slog.String("context", "logranger"))
|
||||
}
|
||||
|
||||
// setRules initializes/updates the ruleset for the logranger Server by
|
||||
|
@ -248,11 +248,11 @@ func (s *Server) setLogLevel() {
|
|||
// to the Server's ruleset field.
|
||||
// It returns an error if there is a failure in reading or loading the ruleset.
|
||||
func (s *Server) setRules() error {
|
||||
rs, err := NewRuleset(s.conf)
|
||||
ruleset, err := NewRuleset(s.conf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read ruleset: %w", err)
|
||||
}
|
||||
s.ruleset = rs
|
||||
s.ruleset = ruleset
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -261,12 +261,12 @@ func (s *Server) setRules() error {
|
|||
// It creates a new Config using the NewConfig method and updates the Server's
|
||||
// conf field. It also reloads the configured Ruleset.
|
||||
// If an error occurs while reloading the configuration, an error is returned.
|
||||
func (s *Server) ReloadConfig(p, f string) error {
|
||||
c, err := NewConfig(p, f)
|
||||
func (s *Server) ReloadConfig(path, file string) error {
|
||||
config, err := NewConfig(path, file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to reload config: %w", err)
|
||||
}
|
||||
s.conf = c
|
||||
s.conf = config
|
||||
|
||||
if err := s.setRules(); err != nil {
|
||||
return fmt.Errorf("failed to reload ruleset: %w", err)
|
||||
|
|
|
@ -44,99 +44,99 @@ type FuncMap struct{}
|
|||
// the FuncMap. It then populates a map with values from the LogMsg
|
||||
// and current time and executes the template using the map as the
|
||||
// data source. The compiled template result or an error is returned.
|
||||
func Compile(lm parsesyslog.LogMsg, mg []string, ot string) (string, error) {
|
||||
pt := strings.Builder{}
|
||||
fm := NewTemplateFuncMap()
|
||||
func Compile(logMessage parsesyslog.LogMsg, matchGroup []string, outputTpl string) (string, error) {
|
||||
procText := strings.Builder{}
|
||||
funcMap := NewTemplateFuncMap()
|
||||
|
||||
ot = strings.ReplaceAll(ot, `\n`, "\n")
|
||||
ot = strings.ReplaceAll(ot, `\t`, "\t")
|
||||
ot = strings.ReplaceAll(ot, `\r`, "\r")
|
||||
tpl, err := template.New("template").Funcs(fm).Parse(ot)
|
||||
outputTpl = strings.ReplaceAll(outputTpl, `\n`, "\n")
|
||||
outputTpl = strings.ReplaceAll(outputTpl, `\t`, "\t")
|
||||
outputTpl = strings.ReplaceAll(outputTpl, `\r`, "\r")
|
||||
tpl, err := template.New("template").Funcs(funcMap).Parse(outputTpl)
|
||||
if err != nil {
|
||||
return pt.String(), fmt.Errorf("failed to create template: %w", err)
|
||||
return procText.String(), fmt.Errorf("failed to create template: %w", err)
|
||||
}
|
||||
|
||||
dm := make(map[string]any)
|
||||
dm["match"] = mg
|
||||
dm["hostname"] = lm.Hostname
|
||||
dm["timestamp"] = lm.Timestamp
|
||||
dm["now_rfc3339"] = time.Now().Format(time.RFC3339)
|
||||
dm["now_unix"] = time.Now().Unix()
|
||||
dm["severity"] = lm.Severity.String()
|
||||
dm["facility"] = lm.Facility.String()
|
||||
dm["appname"] = lm.AppName
|
||||
dm["original_message"] = lm.Message
|
||||
dataMap := make(map[string]any)
|
||||
dataMap["match"] = matchGroup
|
||||
dataMap["hostname"] = logMessage.Hostname
|
||||
dataMap["timestamp"] = logMessage.Timestamp
|
||||
dataMap["now_rfc3339"] = time.Now().Format(time.RFC3339)
|
||||
dataMap["now_unix"] = time.Now().Unix()
|
||||
dataMap["severity"] = logMessage.Severity.String()
|
||||
dataMap["facility"] = logMessage.Facility.String()
|
||||
dataMap["appname"] = logMessage.AppName
|
||||
dataMap["original_message"] = logMessage.Message
|
||||
|
||||
if err = tpl.Execute(&pt, dm); err != nil {
|
||||
return pt.String(), fmt.Errorf("failed to compile template: %w", err)
|
||||
if err = tpl.Execute(&procText, dataMap); err != nil {
|
||||
return procText.String(), fmt.Errorf("failed to compile template: %w", err)
|
||||
}
|
||||
return pt.String(), nil
|
||||
return procText.String(), nil
|
||||
}
|
||||
|
||||
// NewTemplateFuncMap creates a new template function map by returning a
|
||||
// template.FuncMap.
|
||||
func NewTemplateFuncMap() template.FuncMap {
|
||||
fm := FuncMap{}
|
||||
funcMap := FuncMap{}
|
||||
return template.FuncMap{
|
||||
"_ToLower": fm.ToLower,
|
||||
"_ToUpper": fm.ToUpper,
|
||||
"_ToBase64": fm.ToBase64,
|
||||
"_ToSHA1": fm.ToSHA1,
|
||||
"_ToSHA256": fm.ToSHA256,
|
||||
"_ToSHA512": fm.ToSHA512,
|
||||
"_ToLower": funcMap.ToLower,
|
||||
"_ToUpper": funcMap.ToUpper,
|
||||
"_ToBase64": funcMap.ToBase64,
|
||||
"_ToSHA1": funcMap.ToSHA1,
|
||||
"_ToSHA256": funcMap.ToSHA256,
|
||||
"_ToSHA512": funcMap.ToSHA512,
|
||||
}
|
||||
}
|
||||
|
||||
// ToLower returns a given string as lower-case representation
|
||||
func (*FuncMap) ToLower(s string) string {
|
||||
return strings.ToLower(s)
|
||||
func (*FuncMap) ToLower(value string) string {
|
||||
return strings.ToLower(value)
|
||||
}
|
||||
|
||||
// ToUpper returns a given string as upper-case representation
|
||||
func (*FuncMap) ToUpper(s string) string {
|
||||
return strings.ToUpper(s)
|
||||
func (*FuncMap) ToUpper(value string) string {
|
||||
return strings.ToUpper(value)
|
||||
}
|
||||
|
||||
// ToBase64 returns the base64 encoding of a given string.
|
||||
func (*FuncMap) ToBase64(s string) string {
|
||||
return base64.RawStdEncoding.EncodeToString([]byte(s))
|
||||
func (*FuncMap) ToBase64(value string) string {
|
||||
return base64.RawStdEncoding.EncodeToString([]byte(value))
|
||||
}
|
||||
|
||||
// ToSHA1 returns the SHA-1 hash of the given string
|
||||
func (*FuncMap) ToSHA1(s string) string {
|
||||
return toSHA(s, SHA1)
|
||||
func (*FuncMap) ToSHA1(value string) string {
|
||||
return toSHA(value, SHA1)
|
||||
}
|
||||
|
||||
// ToSHA256 returns the SHA-256 hash of the given string
|
||||
func (*FuncMap) ToSHA256(s string) string {
|
||||
return toSHA(s, SHA256)
|
||||
func (*FuncMap) ToSHA256(value string) string {
|
||||
return toSHA(value, SHA256)
|
||||
}
|
||||
|
||||
// ToSHA512 returns the SHA-512 hash of the given string
|
||||
func (*FuncMap) ToSHA512(s string) string {
|
||||
return toSHA(s, SHA512)
|
||||
func (*FuncMap) ToSHA512(value string) string {
|
||||
return toSHA(value, SHA512)
|
||||
}
|
||||
|
||||
// toSHA is a function that converts a string to a SHA hash.
|
||||
//
|
||||
// The function takes two parameters: a string 's' and a 'sa' of
|
||||
// type SHAAlgo which defines the SHA algorithm to be used.
|
||||
func toSHA(s string, sa SHAAlgo) string {
|
||||
var h hash.Hash
|
||||
switch sa {
|
||||
func toSHA(value string, algo SHAAlgo) string {
|
||||
var dataHash hash.Hash
|
||||
switch algo {
|
||||
case SHA1:
|
||||
h = sha1.New()
|
||||
dataHash = sha1.New()
|
||||
case SHA256:
|
||||
h = sha256.New()
|
||||
dataHash = sha256.New()
|
||||
case SHA512:
|
||||
h = sha512.New()
|
||||
dataHash = sha512.New()
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
||||
_, err := io.WriteString(h, s)
|
||||
_, err := io.WriteString(dataHash, value)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
return fmt.Sprintf("%x", dataHash.Sum(nil))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue