pretty.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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. // Package pretty defines helper functions to pretty-print structs for logging.
  19. package pretty
  20. import (
  21. "bytes"
  22. "encoding/json"
  23. "fmt"
  24. "github.com/golang/protobuf/jsonpb"
  25. protov1 "github.com/golang/protobuf/proto"
  26. "google.golang.org/protobuf/encoding/protojson"
  27. protov2 "google.golang.org/protobuf/proto"
  28. )
  29. const jsonIndent = " "
  30. // ToJSON marshals the input into a json string.
  31. //
  32. // If marshal fails, it falls back to fmt.Sprintf("%+v").
  33. func ToJSON(e interface{}) string {
  34. switch ee := e.(type) {
  35. case protov1.Message:
  36. mm := jsonpb.Marshaler{Indent: jsonIndent}
  37. ret, err := mm.MarshalToString(ee)
  38. if err != nil {
  39. // This may fail for proto.Anys, e.g. for xDS v2, LDS, the v2
  40. // messages are not imported, and this will fail because the message
  41. // is not found.
  42. return fmt.Sprintf("%+v", ee)
  43. }
  44. return ret
  45. case protov2.Message:
  46. mm := protojson.MarshalOptions{
  47. Multiline: true,
  48. Indent: jsonIndent,
  49. }
  50. ret, err := mm.Marshal(ee)
  51. if err != nil {
  52. // This may fail for proto.Anys, e.g. for xDS v2, LDS, the v2
  53. // messages are not imported, and this will fail because the message
  54. // is not found.
  55. return fmt.Sprintf("%+v", ee)
  56. }
  57. return string(ret)
  58. default:
  59. ret, err := json.MarshalIndent(ee, "", jsonIndent)
  60. if err != nil {
  61. return fmt.Sprintf("%+v", ee)
  62. }
  63. return string(ret)
  64. }
  65. }
  66. // FormatJSON formats the input json bytes with indentation.
  67. //
  68. // If Indent fails, it returns the unchanged input as string.
  69. func FormatJSON(b []byte) string {
  70. var out bytes.Buffer
  71. err := json.Indent(&out, b, "", jsonIndent)
  72. if err != nil {
  73. return string(b)
  74. }
  75. return out.String()
  76. }