github.com/grafana/pyroscope@v1.18.0/pkg/validation/relabeling_test.go (about) 1 package validation 2 3 import ( 4 "bytes" 5 "flag" 6 "testing" 7 8 "github.com/prometheus/prometheus/model/labels" 9 "github.com/prometheus/prometheus/model/relabel" 10 "github.com/stretchr/testify/require" 11 12 phlaremodel "github.com/grafana/pyroscope/pkg/model" 13 ) 14 15 type wrappedRuntimeConfig struct { 16 rc *RuntimeConfigValues 17 } 18 19 func (w *wrappedRuntimeConfig) TenantLimits(tenantID string) *Limits { 20 return w.rc.TenantLimits[tenantID] 21 } 22 23 func (w *wrappedRuntimeConfig) AllByTenantID() map[string]*Limits { 24 return w.rc.TenantLimits 25 } 26 27 func (w *wrappedRuntimeConfig) RuntimeConfig() *RuntimeConfigValues { 28 return w.rc 29 } 30 31 func newOverrides(rc *RuntimeConfigValues) (*Overrides, error) { 32 var defaultCfg Limits 33 fs := flag.NewFlagSet("test", flag.PanicOnError) 34 defaultCfg.RegisterFlags(fs) 35 return NewOverrides(defaultCfg, &wrappedRuntimeConfig{rc}) 36 } 37 38 const tenantOverrideConfig = ` 39 overrides: 40 nothing: {} 41 disabled: 42 ingestion_relabeling_default_rules_position: disabled 43 custom-rule-end: 44 ingestion_relabeling_rules: 45 - action: drop 46 custom-rule-start: 47 ingestion_relabeling_default_rules_position: last 48 ingestion_relabeling_rules: 49 - action: drop 50 custom-rule-only: 51 ingestion_relabeling_default_rules_position: disabled 52 ingestion_relabeling_rules: 53 - action: drop 54 55 ` 56 57 func Test_IngestionRelabelingRules(t *testing.T) { 58 rc, err := LoadRuntimeConfig(bytes.NewReader([]byte(tenantOverrideConfig))) 59 require.NoError(t, err) 60 61 o, err := newOverrides(rc) 62 require.NoError(t, err) 63 64 rules := o.IngestionRelabelingRules("xxxx") 65 require.Equal(t, len(defaultRelabelRules), len(rules)) 66 67 rules = o.IngestionRelabelingRules("nothing") 68 require.Equal(t, len(defaultRelabelRules), len(rules)) 69 70 rules = o.IngestionRelabelingRules("disabled") 71 require.Equal(t, 0, len(rules)) 72 73 rules = o.IngestionRelabelingRules("custom-rule-end") 74 require.Equal(t, len(defaultRelabelRules)+1, len(rules)) 75 require.Equal(t, relabel.Drop, rules[len(defaultRelabelRules)].Action) 76 77 rules = o.IngestionRelabelingRules("custom-rule-start") 78 require.Equal(t, len(defaultRelabelRules)+1, len(rules)) 79 require.Equal(t, relabel.Drop, rules[0].Action) 80 81 rules = o.IngestionRelabelingRules("custom-rule-only") 82 require.Equal(t, 1, len(rules)) 83 require.Equal(t, relabel.Drop, rules[0].Action) 84 85 _, err = LoadRuntimeConfig(bytes.NewReader([]byte(` 86 overrides: 87 wrong-mode: 88 ingestion_relabeling_default_rules_position: end 89 `))) 90 require.ErrorContains(t, err, "invalid ingestion_relabeling_default_rules_position: end") 91 92 _, err = LoadRuntimeConfig(bytes.NewReader([]byte(` 93 overrides: 94 wrong-rule-action: 95 ingestion_relabeling_rules: [{action: refund}] 96 `))) 97 require.ErrorContains(t, err, "unknown relabel action \"refund\"") 98 99 _, err = LoadRuntimeConfig(bytes.NewReader([]byte(` 100 overrides: 101 empty-rule: 102 ingestion_relabeling_rules: [{}] 103 `))) 104 require.ErrorContains(t, err, "relabel configuration for replace action requires 'target_label'") 105 106 } 107 108 func Test_SampleTypeRelabelRules_Set(t *testing.T) { 109 tests := []struct { 110 name string 111 config string 112 wantErr bool 113 errContains string 114 }{ 115 { 116 name: "valid drop action", 117 config: `[{"action": "drop", "source_labels": ["__type__"], "regex": "alloc_.*"}]`, 118 wantErr: false, 119 }, 120 { 121 name: "valid keep action", 122 config: `[{"action": "keep", "source_labels": ["__type__"], "regex": "cpu|wall"}]`, 123 wantErr: false, 124 }, 125 { 126 name: "invalid replace action", 127 config: `[{"action": "replace", "source_labels": ["__type__"], "target_label": "new_type", "replacement": "cpu"}]`, 128 wantErr: true, 129 errContains: "sample type relabeling only supports 'drop' and 'keep' actions, got 'replace'", 130 }, 131 { 132 name: "invalid labeldrop action", 133 config: `[{"action": "labeldrop", "regex": "temp_.*"}]`, 134 wantErr: true, 135 errContains: "sample type relabeling only supports 'drop' and 'keep' actions, got 'labeldrop'", 136 }, 137 { 138 name: "multiple rules with one invalid", 139 config: `[{"action": "keep", "source_labels": ["__type__"], "regex": "cpu"}, {"action": "replace", "source_labels": ["__type__"], "target_label": "new_type", "replacement": "cpu"}]`, 140 wantErr: true, 141 errContains: "rule at pos 1: sample type relabeling only supports 'drop' and 'keep' actions, got 'replace'", 142 }, 143 } 144 145 for _, tt := range tests { 146 t.Run(tt.name, func(t *testing.T) { 147 var rules SampleTypeRelabelRules 148 err := rules.Set(tt.config) 149 if tt.wantErr { 150 require.Error(t, err) 151 require.Contains(t, err.Error(), tt.errContains) 152 } else { 153 require.NoError(t, err) 154 } 155 }) 156 } 157 } 158 159 func Test_defaultRelabelRules(t *testing.T) { 160 for _, tc := range []struct { 161 name string 162 input labels.Labels 163 expected labels.Labels 164 kept bool 165 }{ 166 { 167 name: "let empty through", 168 input: labels.Labels{}, 169 expected: labels.Labels{}, 170 kept: true, 171 }, 172 { 173 name: "godelta prof remove prefix", 174 input: labels.FromStrings( 175 phlaremodel.LabelNameProfileName, "godeltaprof_memory", // TODO: Verify is this is really the prefix used 176 ), 177 expected: labels.FromStrings( 178 phlaremodel.LabelNameProfileName, "memory", 179 "__name_replaced__", "godeltaprof_memory", 180 "__delta__", "false", 181 ), 182 kept: true, 183 }, 184 { 185 name: "replace wall name with cpu type", 186 input: labels.FromStrings( 187 phlaremodel.LabelNameProfileName, "wall", 188 phlaremodel.LabelNameType, "cpu", 189 ), 190 expected: labels.FromStrings( 191 phlaremodel.LabelNameProfileName, "process_cpu", 192 "__name_replaced__", "wall", 193 phlaremodel.LabelNameType, "cpu", 194 ), 195 kept: true, 196 }, 197 } { 198 result, kept := relabel.Process(tc.input, defaultRelabelRules...) 199 require.Equal(t, tc.expected, result) 200 require.Equal(t, tc.kept, kept) 201 } 202 203 }