github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/config/struct_fields.go (about) 1 package config 2 3 import ( 4 "reflect" 5 "strings" 6 7 "github.com/treeverse/lakefs/pkg/logging" 8 ) 9 10 const ( 11 FieldMaskedValue = "******" 12 FieldMaskedNoValue = "------" 13 ) 14 15 // MapLoggingFields returns all logging.Fields formatted based on our configuration keys 'dot.name.key' with 16 // associated values. Supports squash, and secret to skip printing out secrets. 17 func MapLoggingFields(value interface{}) logging.Fields { 18 fields := make(logging.Fields) 19 structFieldsFunc(reflect.ValueOf(value), "mapstructure", ",squash", nil, func(key string, value interface{}) { 20 fields[key] = value 21 }) 22 return fields 23 } 24 25 func structFieldsFunc(value reflect.Value, tag, squashValue string, prefix []string, cb func(key string, value interface{})) { 26 // finite loop: Go types are well-founded. 27 for value.Kind() == reflect.Ptr { 28 if value.IsZero() { 29 // If required, would already have errored out. 30 return 31 } 32 value = value.Elem() 33 } 34 35 // Got to a value we like to call 'cb' with the key/value information 36 if value.Kind() != reflect.Struct { 37 key := strings.Join(prefix, sep) 38 cb(key, value) 39 return 40 } 41 42 // Scan the struct and 43 for i := 0; i < value.NumField(); i++ { 44 fieldType := value.Type().Field(i) 45 var ( 46 // fieldName is the name to use for the field 47 fieldName string 48 // squash the sub-struct no additional accessor when true 49 squash bool 50 ok bool 51 ) 52 if fieldName, ok = fieldType.Tag.Lookup(tag); ok { 53 if strings.HasSuffix(fieldName, squashValue) { 54 squash = true 55 fieldName = strings.TrimSuffix(fieldName, squashValue) 56 } 57 } else { 58 fieldName = strings.ToLower(fieldType.Name) 59 } 60 // Update prefix to recurse into this field. 61 if !squash { 62 prefix = append(prefix, fieldName) 63 } 64 fieldValue := value.Field(i) 65 66 switch fieldValue.Interface().(type) { 67 case SecureString: 68 // don't pass value of SecureString 69 key := strings.Join(prefix, sep) 70 val := FieldMaskedValue 71 if fieldValue.IsZero() { 72 val = FieldMaskedNoValue 73 } 74 cb(key, val) 75 default: 76 structFieldsFunc(fieldValue, tag, squashValue, prefix, cb) 77 } 78 // Restore prefix 79 if !squash { 80 prefix = prefix[:len(prefix)-1] 81 } 82 } 83 }