@@ -12,6 +12,7 @@ import (
1212 "github.com/stackrox/sensor-metrics-analyzer/internal/parser"
1313 "github.com/stackrox/sensor-metrics-analyzer/internal/reporter"
1414 "github.com/stackrox/sensor-metrics-analyzer/internal/rules"
15+ "github.com/stackrox/sensor-metrics-analyzer/internal/tui"
1516)
1617
1718func main () {
@@ -41,35 +42,51 @@ func analyzeCommand() {
4142 rulesDir := fs .String ("rules" , "." , "Directory containing TOML rules (default: current directory)" )
4243 loadLevelDir := fs .String ("load-level-dir" , "./load-level" , "Directory containing load detection rules" )
4344 output := fs .String ("output" , "" , "Output file (default: stdout)" )
44- format := fs .String ("format" , "console" , "Output format: console, markdown" )
45+ format := fs .String ("format" , "console" , "Output format: console, markdown, tui (interactive) " )
4546 clusterName := fs .String ("cluster" , "" , "Cluster name (extracted from filename if not provided)" )
4647 loadLevelOverride := fs .String ("load-level" , "" , "Override detected load level (low/medium/high)" )
4748 acsVersionOverride := fs .String ("acs-version" , "" , "Override detected ACS version" )
4849 templatePath := fs .String ("template" , "./templates/markdown.tmpl" , "Path to markdown template" )
4950
5051 fs .Usage = func () {
51- fmt .Fprintf (os .Stderr , "Usage: metrics-analyzer analyze <metrics-file> [flags] \n \n " )
52+ fmt .Fprintf (os .Stderr , "Usage: metrics-analyzer analyze [flags] <metrics-file>\n \n " )
5253 fmt .Fprintf (os .Stderr , "Analyzes Prometheus metrics using declarative TOML rules.\n \n " )
5354 fmt .Fprintf (os .Stderr , "Arguments:\n " )
5455 fmt .Fprintf (os .Stderr , " metrics-file Path to Prometheus metrics file\n \n " )
5556 fmt .Fprintf (os .Stderr , "Flags:\n " )
5657 fs .PrintDefaults ()
58+ fmt .Fprintf (os .Stderr , "\n ⚠️ Note: Flags must come BEFORE the metrics file!\n " )
5759 fmt .Fprintf (os .Stderr , "\n Examples:\n " )
5860 fmt .Fprintf (os .Stderr , " metrics-analyzer analyze metrics.txt\n " )
59- fmt .Fprintf (os .Stderr , " metrics-analyzer analyze metrics.txt --rules ./automated-rules\n " )
60- fmt .Fprintf (os .Stderr , " metrics-analyzer analyze metrics.txt --format markdown --output report.md\n " )
61- fmt .Fprintf (os .Stderr , " metrics-analyzer analyze metrics.txt --load-level high --acs-version 4.8 \n " )
61+ fmt .Fprintf (os .Stderr , " metrics-analyzer analyze --rules ./automated-rules metrics.txt \n " )
62+ fmt .Fprintf (os .Stderr , " metrics-analyzer analyze --format markdown --output report.md metrics.txt \n " )
63+ fmt .Fprintf (os .Stderr , " metrics-analyzer analyze --format tui --rules ./automated-rules metrics.txt \n " )
6264 }
6365
6466 fs .Parse (os .Args [2 :])
6567
6668 if fs .NArg () < 1 {
67- fmt .Fprintf (os .Stderr , "Usage: metrics-analyzer analyze <metrics-file> [flags]\n " )
69+ fmt .Fprintf (os .Stderr , "Error: missing metrics file\n " )
70+ fmt .Fprintf (os .Stderr , "Usage: metrics-analyzer analyze [flags] <metrics-file>\n " )
6871 os .Exit (1 )
6972 }
7073
7174 metricsFile := fs .Arg (0 )
7275
76+ // Check for flags after positional argument (common mistake)
77+ for i := 1 ; i < fs .NArg (); i ++ {
78+ arg := fs .Arg (i )
79+ if strings .HasPrefix (arg , "-" ) {
80+ fmt .Fprintf (os .Stderr , "Error: flags must come before the metrics file, not after\n " )
81+ fmt .Fprintf (os .Stderr , " Found flag '%s' after '%s'\n \n " , arg , metricsFile )
82+ fmt .Fprintf (os .Stderr , "Correct usage:\n " )
83+ fmt .Fprintf (os .Stderr , " metrics-analyzer analyze [flags] <metrics-file>\n \n " )
84+ fmt .Fprintf (os .Stderr , "Example:\n " )
85+ fmt .Fprintf (os .Stderr , " metrics-analyzer analyze --format tui --rules ./automated-rules %s\n " , metricsFile )
86+ os .Exit (1 )
87+ }
88+ }
89+
7390 // Extract cluster name from filename if not provided
7491 if * clusterName == "" {
7592 * clusterName = extractClusterName (metricsFile )
@@ -129,6 +146,16 @@ func analyzeCommand() {
129146 // Generate report
130147 var outputContent string
131148 switch * format {
149+ case "tui" :
150+ // Interactive TUI mode
151+ if * output != "" {
152+ fmt .Fprintf (os .Stderr , "Warning: --output is ignored in TUI mode\n " )
153+ }
154+ if err := tui .Run (report ); err != nil {
155+ fmt .Fprintf (os .Stderr , "TUI error: %v\n " , err )
156+ os .Exit (1 )
157+ }
158+ return
132159 case "console" :
133160 // If output file specified, still use console format
134161 if * output != "" {
@@ -247,10 +274,13 @@ func printUsage() {
247274 fmt .Println ()
248275 fmt .Println ("Examples:" )
249276 fmt .Println (" metrics-analyzer analyze metrics.txt" )
250- fmt .Println (" metrics-analyzer analyze metrics.txt --rules ./automated-rules" )
251- fmt .Println (" metrics-analyzer analyze metrics.txt --format markdown --output report.md" )
252- fmt .Println (" metrics-analyzer analyze metrics.txt --load-level high --acs-version 4.8" )
277+ fmt .Println (" metrics-analyzer analyze --rules ./automated-rules metrics.txt" )
278+ fmt .Println (" metrics-analyzer analyze --format markdown --output report.md metrics.txt" )
279+ fmt .Println (" metrics-analyzer analyze --format tui --rules ./automated-rules metrics.txt" )
280+ fmt .Println (" metrics-analyzer analyze --load-level high --acs-version 4.8 metrics.txt" )
253281 fmt .Println (" metrics-analyzer validate" )
254282 fmt .Println (" metrics-analyzer validate ./automated-rules" )
255283 fmt .Println (" metrics-analyzer list-rules" )
284+ fmt .Println ()
285+ fmt .Println ("Note: Flags must come BEFORE positional arguments!" )
256286}
0 commit comments