pretty.go raw

   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