Skip to content

Commit

Permalink
Allow analyzing multiple files sequentially (#13)
Browse files Browse the repository at this point in the history
* Allow analyzing multiple files sequentially

* Cleanup file handling code

We no longer rely on runtime.GC() for closing file,
 at least when analyzing

* Analyze and Daemon are mutually exclusive

* Further cleanup code

* Restore old timing of systemd.NotifyReady()

* fileiter.NewWithScanner: Move bufSz to const value
  • Loading branch information
iBug authored Sep 5, 2024
1 parent b3db9fd commit 214f38b
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 41 deletions.
62 changes: 39 additions & 23 deletions cmd/run.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"errors"
"fmt"
"os"
"os/signal"
Expand All @@ -15,16 +16,26 @@ import (

const defaultFilename = "/var/log/nginx/mirrors/access_json.log"

func filenameFromArgs(args []string) string {
func filenamesFromArgs(args []string) []string {
if len(args) == 0 {
return defaultFilename
return []string{defaultFilename}
}
return args[0]
return args
}

func runWithConfig(cmd *cobra.Command, args []string, config analyze.AnalyzerConfig) error {
filename := filenameFromArgs(args)
fmt.Fprintln(cmd.ErrOrStderr(), "Using log file:", filename)
// Sanily check
if config.Analyze && config.Daemon {
return errors.New("analyze mode and daemonizing are mutually exclusive")
}

filenames := filenamesFromArgs(args)
// Allow multiple files only in analyze mode
if !config.Analyze && len(filenames) != 1 {
return errors.New("only one log file can be specified when following or daemonizing")
}
fmt.Fprintln(cmd.ErrOrStderr(), "Using log files:", filenames)

analyzer, err := analyze.NewAnalyzer(config)
if err != nil {
return fmt.Errorf("failed to create analyzer: %w", err)
Expand All @@ -43,26 +54,32 @@ func runWithConfig(cmd *cobra.Command, args []string, config analyze.AnalyzerCon
}
}()

iterator, err := analyzer.OpenFileIterator(filename)
if err != nil {
return fmt.Errorf("failed to open file: %w", err)
}

if !config.Analyze && !config.Daemon {
go tui.New(analyzer).Run()
}
if config.Daemon {
if err := systemd.NotifyReady(); err != nil {
return fmt.Errorf("failed to notify systemd: %w", err)
if config.Analyze {
for _, filename := range filenames {
err = analyzer.AnalyzeFile(filename)
if err != nil {
break
}
}
analyzer.PrintTopValues(nil, config.SortBy, "")
return err
} else {
// Tail mode
iter, err := analyzer.OpenTailIterator(filenames[0])
if err != nil {
return err
}
}

analyzer.RunLoop(iterator)
if config.Daemon {
if err := systemd.NotifyReady(); err != nil {
return fmt.Errorf("failed to notify systemd: %w", err)
}
} else {
go tui.New(analyzer).Run()
}

if config.Analyze {
analyzer.PrintTopValues(nil, config.SortBy, "")
return analyzer.RunLoop(iter)
}
return nil
}

func runCmd() *cobra.Command {
Expand All @@ -81,10 +98,9 @@ func runCmd() *cobra.Command {

func analyzeCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "analyze [filename]",
Use: "analyze [filename...]",
Aliases: []string{"analyse"},
Short: "Log analyse mode (no tail following, only show top N at the end, and implies --whole)",
Args: cobra.MaximumNArgs(1),
}
config := analyze.DefaultConfig()
config.InstallFlags(cmd.Flags())
Expand Down
17 changes: 17 additions & 0 deletions pkg/analyze/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,23 @@ func (a *Analyzer) RunLoop(iter fileiter.Iterator) error {
return nil
}

func (a *Analyzer) AnalyzeFile(filename string) error {
f, err := os.Open(filename)
if err != nil {
return err
}
defer f.Close()
return a.RunLoop(fileiter.NewWithScanner(f))
}

func (a *Analyzer) TailFile(filename string) error {
iter, err := a.OpenTailIterator(filename)
if err != nil {
return err
}
return a.RunLoop(iter)
}

func (a *Analyzer) handleLine(line []byte) error {
logItem, err := a.logParser.Parse(line)
if err != nil {
Expand Down
4 changes: 1 addition & 3 deletions pkg/analyze/analyze_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,10 @@ func benchmarkAnalyzeLoop(b *testing.B, parserStr string) {
b.Fatal(err)
}

t, err := a.OpenFileIterator(logPath)
err = a.AnalyzeFile(logPath)
if err != nil {
b.Fatal(err)
}

a.RunLoop(t)
a.PrintTopValues(nil, SortBySize, "")
}

Expand Down
13 changes: 0 additions & 13 deletions pkg/analyze/file.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package analyze

import (
"bufio"
"io"
"os"

Expand Down Expand Up @@ -56,15 +55,3 @@ func (a *Analyzer) OpenTailIterator(filename string) (fileiter.Iterator, error)
}
return fileiter.NewWithTail(t), nil
}

func (a *Analyzer) OpenFileIterator(filename string) (fileiter.Iterator, error) {
if !a.Config.Analyze {
return a.OpenTailIterator(filename)
} else {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
return fileiter.NewWithScanner(bufio.NewScanner(file)), nil
}
}
7 changes: 5 additions & 2 deletions pkg/fileiter/iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package fileiter

import (
"bufio"
"io"

"github.com/nxadm/tail"
)
Expand All @@ -14,9 +15,11 @@ type scannerIterator struct {
scanner *bufio.Scanner
}

func NewWithScanner(scanner *bufio.Scanner) Iterator {
func NewWithScanner(r io.Reader) Iterator {
// Prepare a large buffer
scanner.Buffer(make([]byte, 1024*1024), 1024*1024)
const bufSz = 1024 * 1024
scanner := bufio.NewScanner(r)
scanner.Buffer(make([]byte, bufSz), bufSz)
return &scannerIterator{scanner: scanner}
}

Expand Down

0 comments on commit 214f38b

Please sign in to comment.