mirror of
https://github.com/k8sgpt-ai/k8sgpt.git
synced 2025-06-27 07:49:10 +00:00
* feat: add stats option to analyze command for performance insights Introduced a new feature to the analyze command that enables users to print detailed performance statistics of each analyzer. This enhancement aids in debugging and understanding the time taken by various components during analysis, providing valuable insights for performance optimization. Signed-off-by: Matthis Holleville <matthish29@gmail.com> * feat: enhance analysis command with statistics option Refactored the analysis command to support an enhanced statistics option, enabling users to opt-in for detailed performance metrics of the analysis process. This change introduces a more flexible approach to handling statistics, allowing for a clearer separation between the analysis output and performance metrics, thereby improving the usability and insights provided to the user. Signed-off-by: Matthis Holleville <matthish29@gmail.com> --------- Signed-off-by: Matthis Holleville <matthish29@gmail.com> Co-authored-by: Alex Jones <alexsimonjones@gmail.com> Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
160 lines
5.5 KiB
Go
160 lines
5.5 KiB
Go
/*
|
|
Copyright 2023 The K8sGPT Authors.
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package analyze
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
|
|
"github.com/fatih/color"
|
|
"github.com/k8sgpt-ai/k8sgpt/pkg/ai/interactive"
|
|
"github.com/k8sgpt-ai/k8sgpt/pkg/analysis"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var (
|
|
explain bool
|
|
backend string
|
|
output string
|
|
filters []string
|
|
language string
|
|
nocache bool
|
|
namespace string
|
|
labelSelector string
|
|
anonymize bool
|
|
maxConcurrency int
|
|
withDoc bool
|
|
interactiveMode bool
|
|
customAnalysis bool
|
|
customHeaders []string
|
|
withStats bool
|
|
)
|
|
|
|
// AnalyzeCmd represents the problems command
|
|
var AnalyzeCmd = &cobra.Command{
|
|
Use: "analyze",
|
|
Aliases: []string{"analyse"},
|
|
Short: "This command will find problems within your Kubernetes cluster",
|
|
Long: `This command will find problems within your Kubernetes cluster and
|
|
provide you with a list of issues that need to be resolved`,
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
// Create analysis configuration first.
|
|
config, err := analysis.NewAnalysis(
|
|
backend,
|
|
language,
|
|
filters,
|
|
namespace,
|
|
labelSelector,
|
|
nocache,
|
|
explain,
|
|
maxConcurrency,
|
|
withDoc,
|
|
interactiveMode,
|
|
customHeaders,
|
|
withStats,
|
|
)
|
|
|
|
if err != nil {
|
|
color.Red("Error: %v", err)
|
|
os.Exit(1)
|
|
}
|
|
defer config.Close()
|
|
|
|
if customAnalysis {
|
|
config.RunCustomAnalysis()
|
|
}
|
|
config.RunAnalysis()
|
|
|
|
if explain {
|
|
if err := config.GetAIResults(output, anonymize); err != nil {
|
|
color.Red("Error: %v", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
// print results
|
|
output_data, err := config.PrintOutput(output)
|
|
if err != nil {
|
|
color.Red("Error: %v", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
if withStats {
|
|
statsData := config.PrintStats()
|
|
fmt.Println(string(statsData))
|
|
}
|
|
|
|
fmt.Println(string(output_data))
|
|
|
|
if interactiveMode && explain {
|
|
if output == "json" {
|
|
color.Yellow("Caution: interactive mode using --json enabled may use additional tokens.")
|
|
}
|
|
sigs := make(chan os.Signal, 1)
|
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
|
interactiveClient := interactive.NewInteractionRunner(config, output_data)
|
|
|
|
go interactiveClient.StartInteraction()
|
|
for {
|
|
select {
|
|
case res := <-sigs:
|
|
switch res {
|
|
default:
|
|
os.Exit(0)
|
|
}
|
|
case res := <-interactiveClient.State:
|
|
switch res {
|
|
case interactive.E_EXITED:
|
|
os.Exit(0)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
// namespace flag
|
|
AnalyzeCmd.Flags().StringVarP(&namespace, "namespace", "n", "", "Namespace to analyze")
|
|
// no cache flag
|
|
AnalyzeCmd.Flags().BoolVarP(&nocache, "no-cache", "c", false, "Do not use cached data")
|
|
// anonymize flag
|
|
AnalyzeCmd.Flags().BoolVarP(&anonymize, "anonymize", "a", false, "Anonymize data before sending it to the AI backend. This flag masks sensitive data, such as Kubernetes object names and labels, by replacing it with a key. However, please note that this flag does not currently apply to events.")
|
|
// array of strings flag
|
|
AnalyzeCmd.Flags().StringSliceVarP(&filters, "filter", "f", []string{}, "Filter for these analyzers (e.g. Pod, PersistentVolumeClaim, Service, ReplicaSet)")
|
|
// explain flag
|
|
AnalyzeCmd.Flags().BoolVarP(&explain, "explain", "e", false, "Explain the problem to me")
|
|
// add flag for backend
|
|
AnalyzeCmd.Flags().StringVarP(&backend, "backend", "b", "", "Backend AI provider")
|
|
// output as json
|
|
AnalyzeCmd.Flags().StringVarP(&output, "output", "o", "text", "Output format (text, json)")
|
|
// add language options for output
|
|
AnalyzeCmd.Flags().StringVarP(&language, "language", "l", "english", "Languages to use for AI (e.g. 'English', 'Spanish', 'French', 'German', 'Italian', 'Portuguese', 'Dutch', 'Russian', 'Chinese', 'Japanese', 'Korean')")
|
|
// add max concurrency
|
|
AnalyzeCmd.Flags().IntVarP(&maxConcurrency, "max-concurrency", "m", 10, "Maximum number of concurrent requests to the Kubernetes API server")
|
|
// kubernetes doc flag
|
|
AnalyzeCmd.Flags().BoolVarP(&withDoc, "with-doc", "d", false, "Give me the official documentation of the involved field")
|
|
// interactive mode flag
|
|
AnalyzeCmd.Flags().BoolVarP(&interactiveMode, "interactive", "i", false, "Enable interactive mode that allows further conversation with LLM about the problem. Works only with --explain flag")
|
|
// custom analysis flag
|
|
AnalyzeCmd.Flags().BoolVarP(&customAnalysis, "custom-analysis", "z", false, "Enable custom analyzers")
|
|
// add custom headers flag
|
|
AnalyzeCmd.Flags().StringSliceVarP(&customHeaders, "custom-headers", "r", []string{}, "Custom Headers, <key>:<value> (e.g CustomHeaderKey:CustomHeaderValue AnotherHeader:AnotherValue)")
|
|
// label selector flag
|
|
AnalyzeCmd.Flags().StringVarP(&labelSelector, "selector", "L", "", "Label selector (label query) to filter on, supports '=', '==', and '!='. (e.g. -L key1=value1,key2=value2). Matching objects must satisfy all of the specified label constraints.")
|
|
// print stats
|
|
AnalyzeCmd.Flags().BoolVarP(&withStats, "with-stat", "s", false, "Print analysis stats. This option disables errors display.")
|
|
}
|