diff --git a/cmd/server/main.go b/cmd/server/main.go index 6f99ff3..f252adf 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -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) } } } diff --git a/config.go b/config.go index 1490233..10072a3 100644 --- a/config.go +++ b/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 } diff --git a/connection.go b/connection.go index 9e4bcc4..9f23211 100644 --- a/connection.go +++ b/connection.go @@ -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 diff --git a/listener.go b/listener.go index bed6902..609181b 100644 --- a/listener.go +++ b/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 } diff --git a/plugins/actions/file/file.go b/plugins/actions/file/file.go index 7f8fae8..741bced 100644 --- a/plugins/actions/file/file.go +++ b/plugins/actions/file/file.go @@ -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) } diff --git a/rule.go b/rule.go index e3fc99b..5c43afd 100644 --- a/rule.go +++ b/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 } diff --git a/server.go b/server.go index f6ed071..88de0f6 100644 --- a/server.go +++ b/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) diff --git a/template/template.go b/template/template.go index c0142d2..faf8d6b 100644 --- a/template/template.go +++ b/template/template.go @@ -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)) }