Skip to content

Commit c196466

Browse files
authored
[POA-1340] Add a mechanism to randomly _not_ start apidump. (#17)
Controlled by a flag and a new environment variable. The use case here is that we want to run the agent but some, but not all, of the pods in a critical deployment. This is not a great solution, but it's much easier than the alternatives considered. The deployment can include a probability as an environment variable that any given apidump command will run; those that don't run will just hang forever to avoid any problems caused by container exit. One downside is that changing the environment variable causes all the pods to be restarted.
1 parent 51ea8bb commit c196466

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

cmd/internal/apidump/apidump.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package apidump
22

33
import (
4+
"math/rand"
5+
"os"
6+
"strconv"
47
"time"
58

69
"github.com/akitasoftware/akita-libs/akid"
@@ -44,15 +47,56 @@ var (
4447
maxWitnessSize_bytes int
4548
dockerExtensionMode bool
4649
healthCheckPort int
50+
randomizedStart int
4751
)
4852

53+
// This function will either startup apidump normally, or never return, with probability
54+
// determined by randomizedStart/100. The value of the command-line flag may be
55+
// overridden by an environment variable to make it easier to apply.
56+
// This function should be called as early as possible in case termination of
57+
// the agent causes deployment problems.
58+
//
59+
// Negative values are effectively treated as 0 probability, instead of being validated.
60+
func applyRandomizedStart() {
61+
prob := randomizedStart
62+
63+
if env := os.Getenv("POSTMAN_AGENT_RANDOM_START"); env != "" {
64+
override, err := strconv.Atoi(env)
65+
if err == nil {
66+
prob = override
67+
}
68+
}
69+
70+
if prob < 100 {
71+
printer.Stdout.Infof("Starting trace with probability %d%%.\n", prob)
72+
73+
// Pre-1.20, Go does not seed the default Random object :(
74+
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
75+
r := rng.Intn(100) // in range [0,100),
76+
// so 1% probability means < 1, not <= 1:
77+
if r < prob {
78+
return
79+
}
80+
81+
printer.Stdout.Infof("This agent instance will not begin capturing data.\n")
82+
83+
// Wait forever
84+
select {}
85+
86+
// Unreachable
87+
os.Exit(0)
88+
}
89+
}
90+
4991
var Cmd = &cobra.Command{
5092
Use: "apidump",
5193
Short: "Capture requests/responses from network traffic.",
5294
Long: "Capture and store a sequence of requests/responses to a service by observing network traffic.",
5395
SilenceUsage: true,
5496
Args: cobra.ExactArgs(0),
5597
RunE: func(cmd *cobra.Command, _ []string) error {
98+
applyRandomizedStart()
99+
56100
traceTags, err := util.ParseTagsAndWarn(tagsFlag)
57101
if err != nil {
58102
return err
@@ -344,4 +388,12 @@ func init() {
344388
"Port to listen on for Docker extension health checks. This is an internal flag used by the Akita Docker extension.",
345389
)
346390
_ = Cmd.Flags().MarkHidden("health-check-port")
391+
392+
Cmd.Flags().IntVar(
393+
&randomizedStart,
394+
"randomized-start",
395+
100,
396+
"Probability that the apidump command will start intercepting traffic.",
397+
)
398+
_ = Cmd.Flags().MarkHidden("randomized-start")
347399
}

0 commit comments

Comments
 (0)