Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions internal/agent/prompts/phase_cloud_configure_recording.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,45 @@ Configure the recording parameters for Tusk Drift Cloud.

### Configuration Options

1. **Sampling Rate** (0.0 to 1.0):
- Percentage of requests to record
1. **Sampling Mode**:
- `adaptive` (default): Automatically adjusts sampling rate under load to reduce overhead
- `fixed`: Uses a constant sampling rate

2. **Base Sampling Rate** (0.0 to 1.0):
- Base percentage of requests to record
- In adaptive mode, the SDK may temporarily reduce below this rate under pressure
- Recommended: 0.1 (10%) for dev/staging, 0.01 (1%) for production
- Default: 0.1

2. **Export Spans** (boolean):
3. **Export Spans** (boolean):
- Whether to upload trace data to Tusk Cloud
- Required for cloud features
- Default: true

3. **Record Environment Variables** (boolean):
4. **Record Environment Variables** (boolean):
- Whether to record and replay environment variables
- Recommended if app behavior depends on env vars
- Default: false

### Steps

1. **Present defaults**: Tell the user the default configuration:
- Sampling rate: 0.1 (10%)
- Sampling mode: adaptive
- Base sampling rate: 0.1 (10%)
- Export spans: true
- Record env vars: false

2. **Ask for customization**: Use `ask_user` to ask if they want to customize:
"The default recording configuration is:
- Sampling rate: 10% (0.1)
- Sampling mode: adaptive (automatically adjusts under load)
- Base sampling rate: 10% (0.1)
- Export spans: enabled
- Record environment variables: disabled

Press Enter to accept defaults, or type 'custom' to customize:"

3. **If customizing**: Ask for each value:
- Sampling rate (number between 0.0 and 1.0)
- Base sampling rate (number between 0.0 and 1.0)
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
- Export spans (yes/no)
- Record env vars (yes/no)

Expand All @@ -61,6 +68,7 @@ Since cloud users fetch traces from Tusk Cloud rather than storing them locally,

### Important Notes

- Lower sampling rates reduce performance overhead
- Adaptive mode is recommended for most deployments as it automatically reduces sampling under load to minimize performance overhead
- Lower base sampling rates reduce performance overhead
- Export spans must be true for cloud features to work
- Environment variable recording is useful for apps that depend on env vars for business logic
8 changes: 6 additions & 2 deletions internal/agent/prompts/phase_create_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ test_execution:
timeout: 30s

recording:
sampling_rate: 1.0
sampling:
mode: adaptive
base_rate: 1.0
export_spans: false
enable_env_var_recording: true
```
Expand Down Expand Up @@ -52,7 +54,9 @@ test_execution:
timeout: 30s

recording:
sampling_rate: 1.0
sampling:
mode: adaptive
base_rate: 1.0
export_spans: false
enable_env_var_recording: true
```
Expand Down
5 changes: 5 additions & 0 deletions internal/tui/onboard-cloud/save.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,15 @@ func SaveServiceIDToConfig(serviceID string) error {
func SaveRecordingConfig(samplingRate float64, exportSpans, enableEnvVarRecording bool) error {
return saveToConfig(func(cfg *config.Config, u *ConfigUpdater) error {
cfg.Recording.SamplingRate = samplingRate
cfg.Recording.Sampling.Mode = "adaptive"
baseRate := samplingRate
cfg.Recording.Sampling.BaseRate = &baseRate
cfg.Recording.ExportSpans = &exportSpans
cfg.Recording.EnableEnvVarRecording = &enableEnvVarRecording

u.Set([]string{"recording", "sampling_rate"}, samplingRate)
u.Set([]string{"recording", "sampling", "mode"}, "adaptive")
u.Set([]string{"recording", "sampling", "base_rate"}, samplingRate)
u.Set([]string{"recording", "export_spans"}, exportSpans)
u.Set([]string{"recording", "enable_env_var_recording"}, enableEnvVarRecording)
return nil
Expand Down
2 changes: 2 additions & 0 deletions internal/tui/onboard-cloud/save_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ recording:

result := string(data)
assert.Contains(t, result, "sampling_rate: 1")
assert.Contains(t, result, "mode: adaptive")
assert.Contains(t, result, "base_rate: 1")
assert.Contains(t, result, "export_spans: true")
assert.Contains(t, result, "enable_env_var_recording: true")
assert.NotContains(t, result, "!!float")
Expand Down
6 changes: 3 additions & 3 deletions internal/tui/onboard-cloud/steps.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,9 +508,9 @@ func (RecordingConfigStep) Heading(*Model) string { return "Configure recording
func (RecordingConfigStep) Description(m *Model) string {
return `Configure how Tusk records execution traces from your application:

• Sampling Rate: Percentage of requests to record (0.01 = 1%, 0.1 = 10%)
Lower rates reduce performance overhead. We recommend starting 10% for
dev/staging, and 1% for production environments.
• Sampling Rate: Base percentage of requests to record (0.01 = 1%, 0.1 = 10%)
Adaptive sampling mode is used by default, which automatically adjusts the rate
under load. We recommend starting at 10% for dev/staging, and 1% for production.

• Export Spans: Upload trace data to Tusk Drift Cloud (required for cloud features)
Disable only if using Tusk Drift locally without cloud integration.
Expand Down
16 changes: 12 additions & 4 deletions internal/tui/onboard/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,15 @@ type TestExecution struct {
Timeout string `yaml:"timeout"`
}

type RecordingSampling struct {
Mode string `yaml:"mode"`
BaseRate float64 `yaml:"base_rate"`
}

type Recording struct {
SamplingRate float64 `yaml:"sampling_rate"`
ExportSpans bool `yaml:"export_spans"`
EnableEnvVarRecording bool `yaml:"enable_env_var_recording"`
Sampling RecordingSampling `yaml:"sampling"`
ExportSpans bool `yaml:"export_spans"`
EnableEnvVarRecording bool `yaml:"enable_env_var_recording"`
}

type Traces struct {
Expand Down Expand Up @@ -106,7 +111,10 @@ func (m *Model) getCurrentConfig() Config {
Timeout: "30s",
},
Recording: Recording{
SamplingRate: samplingRate,
Sampling: RecordingSampling{
Mode: "adaptive",
BaseRate: samplingRate,
},
ExportSpans: false,
EnableEnvVarRecording: true,
},
Expand Down
65 changes: 65 additions & 0 deletions internal/tui/onboard/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package onboard

import (
"strings"
"testing"

"github.com/charmbracelet/bubbles/textinput"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
)

func TestGetCurrentConfig_UsesAdaptiveSamplingMode(t *testing.T) {
inputs := make([]textinput.Model, 1)
inputs[0] = textinput.New()

m := &Model{
ServiceName: "test-service",
ServicePort: "3000",
StartCmd: "npm start",
ReadinessCmd: "curl http://localhost:3000/health",
ReadinessTimeout: "30s",
ReadinessInterval: "1s",
SamplingRate: "1.0",
inputs: inputs,
}

cfg := m.getCurrentConfig()

assert.Equal(t, "adaptive", cfg.Recording.Sampling.Mode)
assert.Equal(t, 1.0, cfg.Recording.Sampling.BaseRate)

// Verify YAML output uses nested sampling config
var buf strings.Builder
enc := yaml.NewEncoder(&buf)
enc.SetIndent(2)
require.NoError(t, enc.Encode(cfg))
_ = enc.Close()
yamlStr := buf.String()

assert.Contains(t, yamlStr, "mode: adaptive")
assert.Contains(t, yamlStr, "base_rate: 1")
assert.NotContains(t, yamlStr, "sampling_rate:")
}

func TestGetCurrentConfig_CustomSamplingRate(t *testing.T) {
inputs := make([]textinput.Model, 1)
inputs[0] = textinput.New()

m := &Model{
ServiceName: "test-service",
ServicePort: "8080",
StartCmd: "python app.py",
ReadinessCmd: "curl http://localhost:8080/health",
ReadinessTimeout: "30s",
ReadinessInterval: "1s",
SamplingRate: "0.1",
inputs: inputs,
}

cfg := m.getCurrentConfig()

assert.Equal(t, "adaptive", cfg.Recording.Sampling.Mode)
assert.Equal(t, 0.1, cfg.Recording.Sampling.BaseRate)
}
Loading