Skip to content

Commit 1cd7ede

Browse files
print warnings with --warnings flag (#1001)
* warnings flag supresses warning messages * formatting fixes * fix tests
1 parent 25f9e0f commit 1cd7ede

File tree

6 files changed

+99
-48
lines changed

6 files changed

+99
-48
lines changed

cmd/src/scout_advise.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ func init() {
3131
3232
Output advice to file
3333
$ src scout advise --o path/to/file
34+
35+
Output with warnings
36+
$ src scout advise --warnings
3437
`
3538

3639
flagSet := flag.NewFlagSet("advise", flag.ExitOnError)
@@ -45,6 +48,7 @@ func init() {
4548
namespace = flagSet.String("namespace", "", "(optional) specify the kubernetes namespace to use")
4649
pod = flagSet.String("pod", "", "(optional) specify a single pod")
4750
output = flagSet.String("o", "", "(optional) output advice to file")
51+
warnings = flagSet.Bool("warnings", false, "(optional) output advice with warnings")
4852
)
4953

5054
if home := homedir.HomeDir(); home != "" {
@@ -88,6 +92,9 @@ func init() {
8892
if *output != "" {
8993
options = append(options, advise.WithOutput(*output))
9094
}
95+
if *warnings {
96+
options = append(options, advise.WithWarnings(true))
97+
}
9198

9299
return advise.K8s(
93100
context.Background(),
@@ -103,5 +110,4 @@ func init() {
103110
handler: handler,
104111
usageFunc: usage,
105112
})
106-
107113
}

internal/scout/advise/advise.go

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@ import (
1212
type Option = func(config *scout.Config)
1313

1414
const (
15-
OVER_100 = "\t%s %s: Your %s usage is over 100%% (%.2f%%). Add more %s."
16-
OVER_80 = "\t%s %s: Your %s usage is over 80%% (%.2f%%). Consider raising limits."
17-
OVER_40 = "\t%s %s: Your %s usage is under 80%% (%.2f%%). Keep %s allocation the same."
18-
UNDER_40 = "\t%s %s: Your %s usage is under 40%% (%.2f%%). Consider lowering limits."
15+
UNDER_PROVISIONED = "%s %s: %s is under-provisioned (%.2f%% usage). Add resources."
16+
WELL_PROVISIONED = "%s %s: %s is well-provisioned (%.2f%% usage). No action needed."
17+
OVER_PROVISIONED = "%s %s: %s is over-provisioned (%.2f%% usage). Trim resources."
1918
)
2019

2120
func WithNamespace(namespace string) Option {
@@ -36,50 +35,49 @@ func WithOutput(pathToFile string) Option {
3635
}
3736
}
3837

39-
func CheckUsage(usage float64, resourceType string, container string) string {
40-
var message string
38+
func WithWarnings(includeWarnings bool) Option {
39+
return func(config *scout.Config) {
40+
config.Warnings = includeWarnings
41+
}
42+
}
43+
44+
func CheckUsage(usage float64, resourceType string, container string) scout.Advice {
45+
var advice scout.Advice
4146
switch {
42-
case usage >= 100:
43-
message = fmt.Sprintf(
44-
OVER_100,
47+
case usage >= 80:
48+
advice.Kind = scout.DANGER
49+
advice.Msg = fmt.Sprintf(
50+
UNDER_PROVISIONED,
4551
scout.FlashingLightEmoji,
4652
container,
4753
resourceType,
4854
usage,
49-
resourceType,
5055
)
51-
case usage >= 80 && usage < 100:
52-
message = fmt.Sprintf(
53-
OVER_80,
54-
scout.WarningSign,
55-
container,
56-
resourceType,
57-
usage,
58-
)
59-
case usage >= 40 && usage < 80:
60-
message = fmt.Sprintf(
61-
OVER_40,
56+
case usage >= 20 && usage < 80:
57+
advice.Kind = scout.HEALTHY
58+
advice.Msg = fmt.Sprintf(
59+
WELL_PROVISIONED,
6260
scout.SuccessEmoji,
6361
container,
6462
resourceType,
6563
usage,
66-
resourceType,
6764
)
6865
default:
69-
message = fmt.Sprintf(
70-
UNDER_40,
66+
advice.Kind = scout.WARNING
67+
advice.Msg = fmt.Sprintf(
68+
OVER_PROVISIONED,
7169
scout.WarningSign,
7270
container,
7371
resourceType,
7472
usage,
7573
)
7674
}
7775

78-
return message
76+
return advice
7977
}
8078

8179
// outputToFile writes resource allocation advice for a Kubernetes pod to a file.
82-
func OutputToFile(ctx context.Context, cfg *scout.Config, name string, advice []string) error {
80+
func OutputToFile(ctx context.Context, cfg *scout.Config, name string, advice []scout.Advice) error {
8381
file, err := os.OpenFile(cfg.Output, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
8482
if err != nil {
8583
return errors.Wrap(err, "failed to open file")
@@ -90,8 +88,8 @@ func OutputToFile(ctx context.Context, cfg *scout.Config, name string, advice []
9088
return errors.Wrap(err, "failed to write service name to file")
9189
}
9290

93-
for _, msg := range advice {
94-
if _, err := fmt.Fprintf(file, "%s\n", msg); err != nil {
91+
for _, adv := range advice {
92+
if _, err := fmt.Fprintf(file, "%s\n", adv.Msg); err != nil {
9593
return errors.Wrap(err, "failed to write container advice to file")
9694
}
9795
}

internal/scout/advise/advise_test.go

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,35 +16,47 @@ func TestCheckUsage(t *testing.T) {
1616
usage float64
1717
resourceType string
1818
container string
19-
want string
19+
want scout.Advice
2020
}{
2121
{
2222
name: "should return correct message for usage over 100",
2323
usage: 110,
2424
resourceType: "cpu",
2525
container: "gitserver-0",
26-
want: "\t🚨 gitserver-0: Your cpu usage is over 100% (110.00%). Add more cpu.",
26+
want: scout.Advice{
27+
Kind: scout.DANGER,
28+
Msg: "🚨 gitserver-0: cpu is under-provisioned (110.00% usage). Add resources.",
29+
},
2730
},
2831
{
2932
name: "should return correct message for usage over 80 and under 100",
3033
usage: 87,
3134
resourceType: "memory",
3235
container: "gitserver-0",
33-
want: "\t⚠️ gitserver-0: Your memory usage is over 80% (87.00%). Consider raising limits.",
36+
want: scout.Advice{
37+
Kind: scout.DANGER,
38+
Msg: "🚨 gitserver-0: memory is under-provisioned (87.00% usage). Add resources.",
39+
},
3440
},
3541
{
3642
name: "should return correct message for usage over 40 and under 80",
3743
usage: 63.4,
3844
resourceType: "memory",
3945
container: "gitserver-0",
40-
want: "\t✅ gitserver-0: Your memory usage is under 80% (63.40%). Keep memory allocation the same.",
46+
want: scout.Advice{
47+
Kind: scout.HEALTHY,
48+
Msg: "✅ gitserver-0: memory is well-provisioned (63.40% usage). No action needed.",
49+
},
4150
},
4251
{
4352
name: "should return correct message for usage under 40",
44-
usage: 22.33,
53+
usage: 12.33,
4554
resourceType: "memory",
4655
container: "gitserver-0",
47-
want: "\t⚠️ gitserver-0: Your memory usage is under 40% (22.33%). Consider lowering limits.",
56+
want: scout.Advice{
57+
Kind: scout.WARNING,
58+
Msg: "⚠️ gitserver-0: memory is over-provisioned (12.33% usage). Trim resources.",
59+
},
4860
},
4961
}
5062

@@ -65,9 +77,15 @@ func TestOutputToFile(t *testing.T) {
6577
Output: os.TempDir() + string(os.PathSeparator) + "test.txt",
6678
}
6779
name := "gitserver-0"
68-
advice := []string{
69-
"Add more CPU",
70-
"Add more memory",
80+
advice := []scout.Advice{
81+
{
82+
Kind: scout.WARNING,
83+
Msg: "Add more CPU",
84+
},
85+
{
86+
Kind: scout.WARNING,
87+
Msg: "Add more memory",
88+
},
7189
}
7290

7391
err := OutputToFile(context.Background(), cfg, name, advice)
@@ -82,13 +100,14 @@ func TestOutputToFile(t *testing.T) {
82100
want string
83101
}{
84102
{1, "- gitserver-0"},
85-
{2, "Add more CPU"},
86-
{3, "Add more memory"},
103+
{2, advice[0].Msg},
104+
{3, advice[1].Msg},
87105
}
88106

89107
for _, tc := range cases {
90108
tc := tc
91-
if lines[tc.lineNum-1] != tc.want {
109+
got := lines[tc.lineNum-1]
110+
if got != tc.want {
92111
t.Errorf("Expected %q, got %q", tc.want, lines[tc.lineNum-1])
93112
}
94113
}

internal/scout/advise/k8s.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package advise
33
import (
44
"context"
55
"fmt"
6+
"time"
67

78
"github.com/sourcegraph/sourcegraph/lib/errors"
89
"github.com/sourcegraph/src-cli/internal/scout"
@@ -24,6 +25,7 @@ func K8s(
2425
Namespace: "default",
2526
Pod: "",
2627
Output: "",
28+
Warnings: false,
2729
RestConfig: restConfig,
2830
K8sClient: k8sClient,
2931
MetricsClient: metricsClient,
@@ -51,6 +53,10 @@ func K8s(
5153
return nil
5254
}
5355

56+
if cfg.Output != "" {
57+
fmt.Printf("writing to %s. This can take a few minutes...", cfg.Output)
58+
}
59+
5460
for _, pod := range pods {
5561
err = Advise(ctx, cfg, pod)
5662
if err != nil {
@@ -67,29 +73,42 @@ func K8s(
6773
// of a resource is needed. Advice is generated and either printed to the console
6874
// or output to a file depending on the cfg.Output field.
6975
func Advise(ctx context.Context, cfg *scout.Config, pod v1.Pod) error {
70-
var advice []string
76+
var advice []scout.Advice
7177
usageMetrics, err := getUsageMetrics(ctx, cfg, pod)
7278
if err != nil {
7379
return errors.Wrap(err, "could not get usage metrics")
7480
}
75-
7681
for _, metrics := range usageMetrics {
7782
cpuAdvice := CheckUsage(metrics.CpuUsage, "CPU", metrics.ContainerName)
78-
advice = append(advice, cpuAdvice)
83+
if cfg.Warnings {
84+
advice = append(advice, cpuAdvice)
85+
} else if !cfg.Warnings && cpuAdvice.Kind != scout.WARNING {
86+
advice = append(advice, cpuAdvice)
87+
}
7988

8089
memoryAdvice := CheckUsage(metrics.MemoryUsage, "memory", metrics.ContainerName)
81-
advice = append(advice, memoryAdvice)
90+
if cfg.Warnings {
91+
advice = append(advice, memoryAdvice)
92+
} else if !cfg.Warnings && memoryAdvice.Kind != scout.WARNING {
93+
advice = append(advice, memoryAdvice)
94+
}
8295

8396
if metrics.Storage != nil {
8497
storageAdvice := CheckUsage(metrics.StorageUsage, "storage", metrics.ContainerName)
85-
advice = append(advice, storageAdvice)
98+
if cfg.Warnings {
99+
advice = append(advice, storageAdvice)
100+
} else if !cfg.Warnings && storageAdvice.Kind != scout.WARNING {
101+
advice = append(advice, storageAdvice)
102+
}
86103
}
87104

88105
if cfg.Output != "" {
89106
OutputToFile(ctx, cfg, pod.Name, advice)
90107
} else {
91-
for _, msg := range advice {
92-
fmt.Println(msg)
108+
fmt.Printf("%s %s: advising...\n", scout.EmojiFingerPointRight, pod.Name)
109+
time.Sleep(time.Millisecond * 300)
110+
for _, adv := range advice {
111+
fmt.Printf("\t%s\n", adv.Msg)
93112
}
94113
}
95114
}

internal/scout/constants.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,7 @@ const (
66
FlashingLightEmoji = "🚨"
77
SuccessEmoji = "✅"
88
WarningSign = "⚠️ " // why does this need an extra space to align?!?!
9+
HEALTHY = "HEALTHY"
10+
WARNING = "WARNING"
11+
DANGER = "DANGER"
912
)

internal/scout/types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ type Config struct {
1111
Namespace string
1212
Pod string
1313
Output string
14+
Warnings bool
1415
RestConfig *rest.Config
1516
K8sClient *kubernetes.Clientset
1617
MetricsClient *metricsv.Clientset
@@ -36,3 +37,8 @@ type UsageStats struct {
3637
MemoryUsage float64
3738
StorageUsage float64
3839
}
40+
41+
type Advice struct {
42+
Kind string
43+
Msg string
44+
}

0 commit comments

Comments
 (0)