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 "google.golang.org/protobuf/encoding/protojson"
28 "google.golang.org/protobuf/protoadapt"
29 )
30 31 const jsonIndent = " "
32 33 // ToJSON marshals the input into a json string.
34 //
35 // If marshal fails, it falls back to fmt.Sprintf("%+v").
36 func ToJSON(e any) string {
37 if ee, ok := e.(protoadapt.MessageV1); ok {
38 e = protoadapt.MessageV2Of(ee)
39 }
40 41 if ee, ok := e.(protoadapt.MessageV2); ok {
42 mm := protojson.MarshalOptions{
43 Indent: jsonIndent,
44 Multiline: true,
45 }
46 ret, err := mm.Marshal(ee)
47 if err != nil {
48 // This may fail for proto.Anys, e.g. for xDS v2, LDS, the v2
49 // messages are not imported, and this will fail because the message
50 // is not found.
51 return fmt.Sprintf("%+v", ee)
52 }
53 return string(ret)
54 }
55 56 ret, err := json.MarshalIndent(e, "", jsonIndent)
57 if err != nil {
58 return fmt.Sprintf("%+v", e)
59 }
60 return string(ret)
61 }
62 63 // FormatJSON formats the input json bytes with indentation.
64 //
65 // If Indent fails, it returns the unchanged input as string.
66 func FormatJSON(b []byte) string {
67 var out bytes.Buffer
68 err := json.Indent(&out, b, "", jsonIndent)
69 if err != nil {
70 return string(b)
71 }
72 return out.String()
73 }
74