pretty.go (2250B)
1 /* 2 * 3 * Copyright 2021 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 // Package pretty defines helper functions to pretty-print structs for logging. 20 package pretty 21 22 import ( 23 "bytes" 24 "encoding/json" 25 "fmt" 26 27 "github.com/golang/protobuf/jsonpb" 28 protov1 "github.com/golang/protobuf/proto" 29 "google.golang.org/protobuf/encoding/protojson" 30 protov2 "google.golang.org/protobuf/proto" 31 ) 32 33 const jsonIndent = " " 34 35 // ToJSON marshals the input into a json string. 36 // 37 // If marshal fails, it falls back to fmt.Sprintf("%+v"). 38 func ToJSON(e interface{}) string { 39 switch ee := e.(type) { 40 case protov1.Message: 41 mm := jsonpb.Marshaler{Indent: jsonIndent} 42 ret, err := mm.MarshalToString(ee) 43 if err != nil { 44 // This may fail for proto.Anys, e.g. for xDS v2, LDS, the v2 45 // messages are not imported, and this will fail because the message 46 // is not found. 47 return fmt.Sprintf("%+v", ee) 48 } 49 return ret 50 case protov2.Message: 51 mm := protojson.MarshalOptions{ 52 Multiline: true, 53 Indent: jsonIndent, 54 } 55 ret, err := mm.Marshal(ee) 56 if err != nil { 57 // This may fail for proto.Anys, e.g. for xDS v2, LDS, the v2 58 // messages are not imported, and this will fail because the message 59 // is not found. 60 return fmt.Sprintf("%+v", ee) 61 } 62 return string(ret) 63 default: 64 ret, err := json.MarshalIndent(ee, "", jsonIndent) 65 if err != nil { 66 return fmt.Sprintf("%+v", ee) 67 } 68 return string(ret) 69 } 70 } 71 72 // FormatJSON formats the input json bytes with indentation. 73 // 74 // If Indent fails, it returns the unchanged input as string. 75 func FormatJSON(b []byte) string { 76 var out bytes.Buffer 77 err := json.Indent(&out, b, "", jsonIndent) 78 if err != nil { 79 return string(b) 80 } 81 return out.String() 82 }