github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/logging/loggers/sort_logger.go (about) 1 package loggers 2 3 import ( 4 "sort" 5 6 "github.com/go-kit/kit/log" 7 ) 8 9 type sortableKeyvals struct { 10 indices map[string]int 11 keyvals []interface{} 12 len int 13 } 14 15 func sortKeyvals(indices map[string]int, keyvals []interface{}) { 16 sort.Stable(sortable(indices, keyvals)) 17 } 18 19 func sortable(indices map[string]int, keyvals []interface{}) *sortableKeyvals { 20 return &sortableKeyvals{ 21 indices: indices, 22 keyvals: keyvals, 23 len: len(keyvals) / 2, 24 } 25 } 26 27 func (skv *sortableKeyvals) Len() int { 28 return skv.len 29 } 30 31 // Less reports whether the element with 32 // index i should sort before the element with index j. 33 func (skv *sortableKeyvals) Less(i, j int) bool { 34 return skv.keyRank(i) < skv.keyRank(j) 35 } 36 37 // Swap swaps the elements with indexes i and j. 38 func (skv *sortableKeyvals) Swap(i, j int) { 39 keyIdx, keyJdx := i*2, j*2 40 valIdx, valJdx := keyIdx+1, keyJdx+1 41 keyI, valI := skv.keyvals[keyIdx], skv.keyvals[valIdx] 42 skv.keyvals[keyIdx], skv.keyvals[valIdx] = skv.keyvals[keyJdx], skv.keyvals[valJdx] 43 skv.keyvals[keyJdx], skv.keyvals[valJdx] = keyI, valI 44 } 45 46 func (skv *sortableKeyvals) keyRank(i int) int { 47 // Check there is a key at this index 48 key, ok := skv.keyvals[i*2].(string) 49 if !ok { 50 // Sort keys not provided after those that have been but maintain relative order 51 return len(skv.indices) + i 52 } 53 // See if we have been provided an explicit rank/order for the key 54 idx, ok := skv.indices[key] 55 if !ok { 56 // Sort keys not provided after those that have been but maintain relative order 57 return len(skv.indices) + i 58 } 59 return idx 60 } 61 62 // Provides a logger that sorts key-values with keys in keys before other key-values 63 func SortLogger(outputLogger log.Logger, keys ...string) log.Logger { 64 indices := make(map[string]int, len(keys)) 65 for i, k := range keys { 66 indices[k] = i 67 } 68 return log.LoggerFunc(func(keyvals ...interface{}) error { 69 sortKeyvals(indices, keyvals) 70 return outputLogger.Log(keyvals...) 71 }) 72 }