Skip to content

Commit

Permalink
Merge branch 'main' into fix/add-max-tokens-to-serve
Browse files Browse the repository at this point in the history
  • Loading branch information
samirtahir91 authored Oct 30, 2024
2 parents bc4bdad + 3eec9bb commit 5a84185
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 42 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,22 @@ _Analysis with custom headers_
k8sgpt analyze --explain --custom-headers CustomHeaderKey:CustomHeaderValue
```

_Print analysis stats_

```
k8sgpt analyze -s
The stats mode allows for debugging and understanding the time taken by an analysis by displaying the statistics of each analyzer.
- Analyzer Ingress took 47.125583ms
- Analyzer PersistentVolumeClaim took 53.009167ms
- Analyzer CronJob took 57.517792ms
- Analyzer Deployment took 156.6205ms
- Analyzer Node took 160.109833ms
- Analyzer ReplicaSet took 245.938333ms
- Analyzer StatefulSet took 448.0455ms
- Analyzer Pod took 5.662594708s
- Analyzer Service took 38.583359166s
```

</details>

## LLM AI Backends
Expand Down
10 changes: 10 additions & 0 deletions cmd/analyze/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ var (
interactiveMode bool
customAnalysis bool
customHeaders []string
withStats bool
)

// AnalyzeCmd represents the problems command
Expand All @@ -63,6 +64,7 @@ var AnalyzeCmd = &cobra.Command{
withDoc,
interactiveMode,
customHeaders,
withStats,
)

if err != nil {
Expand All @@ -88,6 +90,12 @@ var AnalyzeCmd = &cobra.Command{
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 {
Expand Down Expand Up @@ -146,4 +154,6 @@ func init() {
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.")
}
90 changes: 49 additions & 41 deletions pkg/analysis/analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import (
"encoding/base64"
"errors"
"fmt"
"reflect"
"strings"
"sync"
"time"

"github.com/fatih/color"
openapi_v2 "github.com/google/gnostic/openapiv2"
Expand Down Expand Up @@ -50,6 +50,8 @@ type Analysis struct {
MaxConcurrency int
AnalysisAIProvider string // The name of the AI Provider used for this analysis
WithDoc bool
WithStats bool
Stats []common.AnalysisStats
}

type (
Expand Down Expand Up @@ -82,6 +84,7 @@ func NewAnalysis(
withDoc bool,
interactiveMode bool,
httpHeaders []string,
withStats bool,
) (*Analysis, error) {
// Get kubernetes client from viper.
kubecontext := viper.GetString("kubecontext")
Expand Down Expand Up @@ -112,6 +115,7 @@ func NewAnalysis(
Explain: explain,
MaxConcurrency: maxConcurrency,
WithDoc: withDoc,
WithStats: withStats,
}
if !explain {
// Return early if AI use was not requested.
Expand Down Expand Up @@ -243,22 +247,10 @@ func (a *Analysis) RunAnalysis() {
var mutex sync.Mutex
// if there are no filters selected and no active_filters then run coreAnalyzer
if len(a.Filters) == 0 && len(activeFilters) == 0 {
for _, analyzer := range coreAnalyzerMap {
for name, analyzer := range coreAnalyzerMap {
wg.Add(1)
semaphore <- struct{}{}
go func(analyzer common.IAnalyzer, wg *sync.WaitGroup, semaphore chan struct{}) {
defer wg.Done()
results, err := analyzer.Analyze(analyzerConfig)
if err != nil {
mutex.Lock()
a.Errors = append(a.Errors, fmt.Sprintf("[%s] %s", reflect.TypeOf(analyzer).Name(), err))
mutex.Unlock()
}
mutex.Lock()
a.Results = append(a.Results, results...)
mutex.Unlock()
<-semaphore
}(analyzer, &wg, semaphore)
go a.executeAnalyzer(analyzer, name, analyzerConfig, semaphore, &wg, &mutex)

}
wg.Wait()
Expand All @@ -270,19 +262,7 @@ func (a *Analysis) RunAnalysis() {
if analyzer, ok := analyzerMap[filter]; ok {
semaphore <- struct{}{}
wg.Add(1)
go func(analyzer common.IAnalyzer, filter string) {
defer wg.Done()
results, err := analyzer.Analyze(analyzerConfig)
if err != nil {
mutex.Lock()
a.Errors = append(a.Errors, fmt.Sprintf("[%s] %s", filter, err))
mutex.Unlock()
}
mutex.Lock()
a.Results = append(a.Results, results...)
mutex.Unlock()
<-semaphore
}(analyzer, filter)
go a.executeAnalyzer(analyzer, filter, analyzerConfig, semaphore, &wg, &mutex)
} else {
a.Errors = append(a.Errors, fmt.Sprintf("\"%s\" filter does not exist. Please run k8sgpt filters list.", filter))
}
Expand All @@ -296,24 +276,52 @@ func (a *Analysis) RunAnalysis() {
if analyzer, ok := analyzerMap[filter]; ok {
semaphore <- struct{}{}
wg.Add(1)
go func(analyzer common.IAnalyzer, filter string) {
defer wg.Done()
results, err := analyzer.Analyze(analyzerConfig)
if err != nil {
mutex.Lock()
a.Errors = append(a.Errors, fmt.Sprintf("[%s] %s", filter, err))
mutex.Unlock()
}
mutex.Lock()
a.Results = append(a.Results, results...)
mutex.Unlock()
<-semaphore
}(analyzer, filter)
go a.executeAnalyzer(analyzer, filter, analyzerConfig, semaphore, &wg, &mutex)
}
}
wg.Wait()
}

func (a *Analysis) executeAnalyzer(analyzer common.IAnalyzer, filter string, analyzerConfig common.Analyzer, semaphore chan struct{}, wg *sync.WaitGroup, mutex *sync.Mutex) {
defer wg.Done()

var startTime time.Time
var elapsedTime time.Duration

// Start the timer
if a.WithStats {
startTime = time.Now()
}

// Run the analyzer
results, err := analyzer.Analyze(analyzerConfig)

// Measure the time taken
if a.WithStats {
elapsedTime = time.Since(startTime)
}
stat := common.AnalysisStats{
Analyzer: filter,
DurationTime: elapsedTime,
}

mutex.Lock()
defer mutex.Unlock()

if err != nil {
if a.WithStats {
a.Stats = append(a.Stats, stat)
}
a.Errors = append(a.Errors, fmt.Sprintf("[%s] %s", filter, err))
} else {
if a.WithStats {
a.Stats = append(a.Stats, stat)
}
a.Results = append(a.Results, results...)
}
<-semaphore
}

func (a *Analysis) GetAIResults(output string, anonymize bool) error {
if len(a.Results) == 0 {
return nil
Expand Down
12 changes: 12 additions & 0 deletions pkg/analysis/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ func (a *Analysis) jsonOutput() ([]byte, error) {
return output, nil
}

func (a *Analysis) PrintStats() []byte {
var output strings.Builder

output.WriteString(color.YellowString("The stats mode allows for debugging and understanding the time taken by an analysis by displaying the statistics of each analyzer.\n"))

for _, stat := range a.Stats {
output.WriteString(fmt.Sprintf("- Analyzer %s took %s \n", color.YellowString(stat.Analyzer), stat.DurationTime))
}

return []byte(output.String())
}

func (a *Analysis) textOutput() ([]byte, error) {
var output strings.Builder

Expand Down
6 changes: 6 additions & 0 deletions pkg/common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package common

import (
"context"
"time"

trivy "github.com/aquasecurity/trivy-operator/pkg/apis/aquasecurity/v1alpha1"
openapi_v2 "github.com/google/gnostic/openapiv2"
Expand Down Expand Up @@ -80,6 +81,11 @@ type Result struct {
ParentObject string `json:"parentObject"`
}

type AnalysisStats struct {
Analyzer string `json:"analyzer"`
DurationTime time.Duration `json:"durationTime"`
}

type Failure struct {
Text string
KubernetesDoc string
Expand Down
4 changes: 3 additions & 1 deletion pkg/server/analyze/analyze.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package analyze

import (
schemav1 "buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go/schema/v1"
"context"
json "encoding/json"

schemav1 "buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go/schema/v1"
"github.com/k8sgpt-ai/k8sgpt/pkg/analysis"
)

Expand Down Expand Up @@ -31,6 +32,7 @@ func (h *Handler) Analyze(ctx context.Context, i *schemav1.AnalyzeRequest) (
false, // Kubernetes Doc disabled in server mode
false, // Interactive mode disabled in server mode
[]string{}, //TODO: add custom http headers in server mode
false, // with stats disable
)
config.Context = ctx // Replace context for correct timeouts.
if err != nil {
Expand Down

0 comments on commit 5a84185

Please sign in to comment.