package model import ( "fmt" "strings" "time" ) type Entry struct { Timestamp string Hostname string WorkingDir string Command string } // ParseLine parses a log line in "TIMESTAMP HOSTNAME DIR COMMAND..." format. func ParseLine(line string) (Entry, error) { line = strings.TrimSpace(line) if line == "" { return Entry{}, fmt.Errorf("empty line") } // Split into at most 4 parts: timestamp, hostname, dir, command(rest) parts := strings.SplitN(line, " ", 4) if len(parts) < 4 { return Entry{}, fmt.Errorf("malformed line: %q", line) } ts := parts[0] if _, err := time.Parse(time.RFC3339, ts); err != nil { return Entry{}, fmt.Errorf("invalid timestamp %q: %w", ts, err) } if parts[1] == "" || parts[2] == "" || parts[3] == "" { return Entry{}, fmt.Errorf("empty field in line: %q", line) } return Entry{ Timestamp: ts, Hostname: parts[1], WorkingDir: parts[2], Command: parts[3], }, nil } // Format returns the entry in log format: "TIMESTAMP HOSTNAME DIR COMMAND" func (e Entry) Format() string { return fmt.Sprintf("%s %s %s %s", e.Timestamp, e.Hostname, e.WorkingDir, e.Command) }