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.
20package pretty
21
22import (
23 "bytes"
24 "encoding/json"
25 "fmt"
26
27 "google.golang.org/protobuf/encoding/protojson"
28 "google.golang.org/protobuf/protoadapt"
29)
30
31const jsonIndent = " "
32
33// ToJSON marshals the input into a json string.
34//
35// If marshal fails, it falls back to fmt.Sprintf("%+v").
36func 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.
66func 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}