github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/settings/registry.go (about) 1 // Copyright 2017 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package settings 12 13 import ( 14 "fmt" 15 "sort" 16 "unicode" 17 "unicode/utf8" 18 ) 19 20 // registry contains all defined settings, their types and default values. 21 // 22 // The registry does not store the current values of the settings; those are 23 // stored separately in Values, allowing multiple independent instances 24 // of each setting in the registry. 25 // 26 // registry should never be mutated after creation (except in tests), as it is 27 // read concurrently by different callers. 28 var registry = make(map[string]extendedSetting) 29 30 // TestingSaveRegistry can be used in tests to save/restore the current 31 // contents of the registry. 32 func TestingSaveRegistry() func() { 33 var origRegistry = make(map[string]extendedSetting) 34 for k, v := range registry { 35 origRegistry[k] = v 36 } 37 return func() { 38 registry = origRegistry 39 } 40 } 41 42 // When a setting is removed, it should be added to this list so that we cannot 43 // accidentally reuse its name, potentially mis-handling older values. 44 var retiredSettings = map[string]struct{}{ 45 // removed as of 2.0. 46 "kv.gc.batch_size": {}, 47 "kv.transaction.max_intents": {}, 48 "diagnostics.reporting.report_metrics": {}, 49 // removed as of 2.1. 50 "kv.allocator.stat_based_rebalancing.enabled": {}, 51 "kv.allocator.stat_rebalance_threshold": {}, 52 // removed as of 19.1. 53 "kv.raft_log.synchronize": {}, 54 // removed as of 19.2. 55 "schemachanger.bulk_index_backfill.enabled": {}, 56 "rocksdb.ingest_backpressure.delay_l0_file": {}, // never used 57 "server.heap_profile.system_memory_threshold_fraction": {}, 58 "timeseries.storage.10s_resolution_ttl": {}, 59 "changefeed.push.enabled": {}, 60 "sql.defaults.optimizer": {}, 61 "kv.bulk_io_write.addsstable_max_rate": {}, 62 // removed as of 20.1. 63 "schemachanger.lease.duration": {}, 64 "schemachanger.lease.renew_fraction": {}, 65 // removed as of 20.2. 66 "rocksdb.ingest_backpressure.pending_compaction_threshold": {}, 67 "sql.distsql.temp_storage.joins": {}, 68 "sql.distsql.temp_storage.sorts": {}, 69 "sql.distsql.distribute_index_joins": {}, 70 "sql.distsql.merge_joins.enabled": {}, 71 } 72 73 // register adds a setting to the registry. 74 func register(key, desc string, s extendedSetting) { 75 if _, ok := retiredSettings[key]; ok { 76 panic(fmt.Sprintf("cannot reuse previously defined setting name: %s", key)) 77 } 78 if _, ok := registry[key]; ok { 79 panic(fmt.Sprintf("setting already defined: %s", key)) 80 } 81 if len(desc) == 0 { 82 panic(fmt.Sprintf("setting missing description: %s", key)) 83 } 84 if r, _ := utf8.DecodeRuneInString(desc); unicode.IsUpper(r) { 85 panic(fmt.Sprintf("setting descriptions should start with a lowercase letter: %q", desc)) 86 } 87 s.setDescription(desc) 88 registry[key] = s 89 s.setSlotIdx(len(registry)) 90 } 91 92 // NumRegisteredSettings returns the number of registered settings. 93 func NumRegisteredSettings() int { return len(registry) } 94 95 // Keys returns a sorted string array with all the known keys. 96 func Keys() (res []string) { 97 res = make([]string, 0, len(registry)) 98 for k := range registry { 99 if registry[k].isRetired() { 100 continue 101 } 102 res = append(res, k) 103 } 104 sort.Strings(res) 105 return res 106 } 107 108 // Lookup returns a Setting by name along with its description. 109 // For non-reportable setting, it instantiates a MaskedSetting 110 // to masquerade for the underlying setting. 111 func Lookup(name string, purpose LookupPurpose) (Setting, bool) { 112 v, ok := registry[name] 113 var setting Setting = v 114 if ok && purpose == LookupForReporting && !v.isReportable() { 115 setting = &MaskedSetting{setting: v} 116 } 117 return setting, ok 118 } 119 120 // LookupPurpose indicates what is being done with the setting. 121 type LookupPurpose int 122 123 const ( 124 // LookupForReporting indicates that a setting is being retrieved 125 // for reporting and sensitive values should be scrubbed. 126 LookupForReporting LookupPurpose = iota 127 // LookupForLocalAccess indicates that a setting is being 128 // retrieved for local processing within the cluster and 129 // all values should be accessible 130 LookupForLocalAccess 131 ) 132 133 // ReadableTypes maps our short type identifiers to friendlier names. 134 var ReadableTypes = map[string]string{ 135 "s": "string", 136 "i": "integer", 137 "f": "float", 138 "b": "boolean", 139 "z": "byte size", 140 "d": "duration", 141 "e": "enumeration", 142 "m": "custom validation", 143 } 144 145 // RedactedValue returns a string representation of the value for settings 146 // types the are not considered sensitive (numbers, bools, etc) or 147 // <redacted> for those with values could store sensitive things (i.e. strings). 148 func RedactedValue(name string, values *Values) string { 149 if setting, ok := Lookup(name, LookupForReporting); ok { 150 return setting.String(values) 151 } 152 return "<unknown>" 153 }