Skip to content

Commit

Permalink
Added CPU and Memory usage to logs #2379
Browse files Browse the repository at this point in the history
Signed-off-by: João Reigota <[email protected]>
  • Loading branch information
cx-joao-reigota committed Apr 22, 2021
1 parent 6391652 commit 79e08d1
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 8 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ require (
github.com/open-policy-agent/opa v0.27.1
github.com/pelletier/go-toml v1.8.1 // indirect
github.com/pkg/errors v0.9.1
github.com/pkg/profile v1.5.0
github.com/rs/zerolog v1.21.0
github.com/spf13/cobra v1.1.3
github.com/spf13/pflag v1.0.5
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pkg/profile v1.5.0 h1:042Buzk+NhDI+DeSAA62RwJL8VAuZUMQZUjCsRz1Mug=
github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
3 changes: 3 additions & 0 deletions internal/console/helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"sync"

"github.com/BurntSushi/toml"
"github.com/Checkmarx/kics/internal/global"
"github.com/Checkmarx/kics/pkg/model"
"github.com/Checkmarx/kics/pkg/report"
"github.com/gookit/color"
Expand Down Expand Up @@ -244,13 +245,15 @@ func FileAnalyzer(path string) (string, error) {
// GenerateReport execute each report function to generate report
func GenerateReport(path, filename string, body interface{}, formats []string) error {
log.Debug().Msgf("helpers.GenerateReport()")
global.Metric.Start("generate_report")
var err error = nil
for _, format := range formats {
if err = reportGenerators[format](path, filename, body); err != nil {
log.Error().Msgf("Failed to generate %s report", format)
break
}
}
global.Metric.Stop()
return err
}

Expand Down
15 changes: 12 additions & 3 deletions internal/console/kics.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ var (
noColor bool
silent bool
ci bool
metric string

warning []string
)
Expand Down Expand Up @@ -89,9 +90,17 @@ func initialize(rootCmd *cobra.Command) error {
"",
false,
"display only log messages to CLI output (mutually exclusive with silent)")
rootCmd.PersistentFlags().StringVarP(&metric,
"metrics",
"",
"",
"display metrics for the steps of kics exucution (CPU, MEM)")

err := rootCmd.PersistentFlags().MarkDeprecated(printer.LogFileFlag, "please use --log-path instead")
if err != nil {
if err := rootCmd.PersistentFlags().MarkHidden("metrics"); err != nil {
return err
}

if err := rootCmd.PersistentFlags().MarkDeprecated(printer.LogFileFlag, "please use --log-path instead"); err != nil {
return err
}

Expand Down Expand Up @@ -132,7 +141,7 @@ func Execute() error {
}
defer sentry.Flush(timeMult * time.Second)

if err := initialize(rootCmd); err != nil {
if err = initialize(rootCmd); err != nil {
sentry.CaptureException(err)
log.Err(err).Msg("Failed to initialize CLI")
return err
Expand Down
13 changes: 10 additions & 3 deletions internal/console/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
consoleHelpers "github.com/Checkmarx/kics/internal/console/helpers"
internalPrinter "github.com/Checkmarx/kics/internal/console/printer"
"github.com/Checkmarx/kics/internal/constants"
"github.com/Checkmarx/kics/internal/global"
"github.com/Checkmarx/kics/internal/metrics"
"github.com/Checkmarx/kics/internal/storage"
"github.com/Checkmarx/kics/internal/tracker"
"github.com/Checkmarx/kics/pkg/engine"
Expand Down Expand Up @@ -84,12 +86,17 @@ func NewScanCmd() *cobra.Command {
Use: scanCommandStr,
Short: "Executes a scan analysis",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
err := initializeConfig(cmd)
if err != nil {
if err := initializeConfig(cmd); err != nil {
return err
}
if err := internalPrinter.SetupPrinter(cmd.InheritedFlags()); err != nil {
return err
}
err = internalPrinter.SetupPrinter(cmd.InheritedFlags())
var err error
global.Metric, err = metrics.InitializeMetrics(cmd.InheritedFlags().Lookup("metrics"))
if err != nil {
sentry.CaptureException(err)
log.Err(err).Msg("Failed to initialize Metrics")
return err
}
return nil
Expand Down
9 changes: 9 additions & 0 deletions internal/global/global.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package global

import (
"github.com/Checkmarx/kics/internal/metrics"
)

var (
Metric *metrics.Metrics
)
18 changes: 18 additions & 0 deletions internal/metrics/cpu_metric.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package metrics

import (
"github.com/pkg/profile"
)

type cpuMetric struct{}

// Start - start gathering metrics for CPU usage
func (c cpuMetric) Start(location, path string) metricProfile {
profCPU := profile.Start(profile.CPUProfile, profile.Quiet, profile.NoShutdownHook, profile.ProfilePath(path))
return profCPU
}

// Stop - stop gathering metrics for CPU usage
func (c cpuMetric) Stop(profCPU metricProfile) {
profCPU.Stop()
}
18 changes: 18 additions & 0 deletions internal/metrics/mem_metric.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package metrics

import (
"github.com/pkg/profile"
)

type memMetric struct{}

// Start - start gathering metrics for Memory usage
func (c memMetric) Start(location, path string) metricProfile {
profMem := profile.Start(profile.MemProfile, profile.Quiet, profile.NoShutdownHook, profile.ProfilePath(path))
return profMem
}

// Stop - stop gathering metrics for Memory usage
func (c memMetric) Stop(profMem metricProfile) {
profMem.Stop()
}
108 changes: 108 additions & 0 deletions internal/metrics/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package metrics

import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"

"github.com/rs/zerolog/log"
"github.com/spf13/pflag"
)

// Start - starts gathering metrics based on the type of metrics and writes metrics to string
// Stop - stops gathering metrics for the type of metrics specified
type metricType interface {
Start(location, path string) metricProfile
Stop(metricProfile)
}

type metricProfile interface{ Stop() }

// Metrics - structure to keep information relevant to the metrics calculation
type Metrics struct {
metric metricType
metricsID string
location string
profile metricProfile
disable bool
tempDIR string
}

// InitializeMetrics - creates a new instance of a Metrics based on the type of metrics specified
func InitializeMetrics(metric *pflag.Flag) (*Metrics, error) {
metricStr := metric.Value.String()
var err error
metrics := &Metrics{}
switch strings.ToLower(metricStr) {
case "cpu":
metrics.metric = cpuMetric{}
case "mem":
metrics.metric = memMetric{}
case "":
metrics.disable = true
default:
metrics.disable = true
err = fmt.Errorf("unknonwn metric: %s (available metrics: cpu, mem)", metricStr)
}

// Create temporary dir to keep pprof file
if !metrics.disable {
temp, errCreate := os.MkdirTemp(".", "*")
if errCreate != nil {
err = errCreate
}

metrics.tempDIR = temp
metrics.metricsID = metricStr
}

return metrics, err
}

// Start - starts gathering metrics for the location specified
func (m *Metrics) Start(location string) {
if m.disable {
return
}
log.Debug().Msgf("Started %s profiling for %s", m.metricsID, location)
m.location = location
m.profile = m.metric.Start(location, m.tempDIR)
}

// Stop - stops gathering metrics and logs the result
func (m *Metrics) Stop() {
if m.disable {
return
}
profile := fmt.Sprintf("%s.pprof", strings.ToLower(m.metricsID))
log.Debug().Msgf("Stopped %s profiling for %s", m.metricsID, m.location)
m.metric.Stop(m.profile)

if err := m.readFile(filepath.Join(m.tempDIR, profile)); err != nil {
log.Error().Msgf("failed to get metrics from %s: %s", m.location, err)
}
}

func (m *Metrics) readFile(profile string) error {
// Remove temporary directory
defer func() {
if err := os.RemoveAll(m.tempDIR); err != nil {
log.Error().Msgf("failed to remove metric temporary dir %s: %s", m.tempDIR, err)
}
}()
// Since profiling in golang creates a binary pprof file we need to call pprof tool
// to the information we need
cmd := exec.Command("go", "tool", "pprof", "-list", "total", profile)
b, err := cmd.Output()
if err != nil {
return err
}

// Get information of total metric usage
lines := strings.Split(string(b), "\n")
log.Info().Msgf("Total %s usage for %s: %s", strings.ToUpper(m.metricsID), m.location, lines[0])

return nil
}
4 changes: 4 additions & 0 deletions pkg/engine/inspector.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"

consoleHelpers "github.com/Checkmarx/kics/internal/console/helpers"
"github.com/Checkmarx/kics/internal/global"
"github.com/Checkmarx/kics/pkg/detector"
"github.com/Checkmarx/kics/pkg/detector/docker"
"github.com/Checkmarx/kics/pkg/detector/helm"
Expand Down Expand Up @@ -106,6 +107,7 @@ func NewInspector(
excludeResults map[string]bool) (*Inspector, error) {
log.Debug().Msg("engine.NewInspector()")

global.Metric.Start("get_queries")
queries, err := queriesSource.GetQueries(excludeQueries)
if err != nil {
return nil, errors.Wrap(err, "failed to get queries")
Expand Down Expand Up @@ -159,6 +161,8 @@ func NewInspector(

queriesNumber := sumAllAggregatedQueries(opaQueries)

global.Metric.Stop()

log.Info().
Msgf("Inspector initialized, number of queries=%d", queriesNumber)

Expand Down
7 changes: 5 additions & 2 deletions pkg/kics/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"io"

"github.com/Checkmarx/kics/internal/global"
"github.com/Checkmarx/kics/pkg/engine"
"github.com/Checkmarx/kics/pkg/engine/provider"
"github.com/Checkmarx/kics/pkg/model"
Expand Down Expand Up @@ -49,6 +50,7 @@ type Service struct {
// StartScan executes scan over the context, using the scanID as reference
func (s *Service) StartScan(ctx context.Context, scanID string, hideProgress bool) error {
log.Debug().Msg("service.StartScan()")
global.Metric.Start("get_sources")
if err := s.SourceProvider.GetSources(
ctx,
s.Parser.SupportedExtensions(),
Expand All @@ -61,14 +63,15 @@ func (s *Service) StartScan(ctx context.Context, scanID string, hideProgress boo
); err != nil {
return errors.Wrap(err, "failed to read sources")
}

global.Metric.Stop()
global.Metric.Start("inspect")
vulnerabilities, err := s.Inspector.Inspect(ctx, scanID, s.files, hideProgress, s.SourceProvider.GetBasePath())
if err != nil {
return errors.Wrap(err, "failed to inspect files")
}

err = s.Storage.SaveVulnerabilities(ctx, vulnerabilities)

global.Metric.Stop()
return errors.Wrap(err, "failed to save vulnerabilities")
}

Expand Down

0 comments on commit 79e08d1

Please sign in to comment.