google.golang.org/grpc@v1.62.1/internal/pretty/pretty.go (about)

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