...

Source file src/github.com/Microsoft/hcsshim/internal/log/format.go

Documentation: github.com/Microsoft/hcsshim/internal/log

     1  package log
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"encoding/json"
     7  	"fmt"
     8  	"net"
     9  	"reflect"
    10  	"time"
    11  )
    12  
    13  // TimeFormat is [time.RFC3339Nano] with nanoseconds padded using
    14  // zeros to ensure the formatted time is always the same number of
    15  // characters.
    16  // Based on RFC3339NanoFixed from github.com/containerd/log
    17  const TimeFormat = "2006-01-02T15:04:05.000000000Z07:00"
    18  
    19  func FormatTime(t time.Time) string {
    20  	return t.Format(TimeFormat)
    21  }
    22  
    23  // DurationFormat formats a [time.Duration] log entry.
    24  //
    25  // A nil value signals an error with the formatting.
    26  type DurationFormat func(time.Duration) interface{}
    27  
    28  func DurationFormatString(d time.Duration) interface{}       { return d.String() }
    29  func DurationFormatSeconds(d time.Duration) interface{}      { return d.Seconds() }
    30  func DurationFormatMilliseconds(d time.Duration) interface{} { return d.Milliseconds() }
    31  
    32  // FormatIO formats net.Conn and other types that have an `Addr()` or `Name()`.
    33  //
    34  // See FormatEnabled for more information.
    35  func FormatIO(ctx context.Context, v interface{}) string {
    36  	m := make(map[string]string)
    37  	m["type"] = reflect.TypeOf(v).String()
    38  
    39  	switch t := v.(type) {
    40  	case net.Conn:
    41  		m["localAddress"] = formatAddr(t.LocalAddr())
    42  		m["remoteAddress"] = formatAddr(t.RemoteAddr())
    43  	case interface{ Addr() net.Addr }:
    44  		m["address"] = formatAddr(t.Addr())
    45  	default:
    46  		return Format(ctx, t)
    47  	}
    48  
    49  	return Format(ctx, m)
    50  }
    51  
    52  func formatAddr(a net.Addr) string {
    53  	return a.Network() + "://" + a.String()
    54  }
    55  
    56  // Format formats an object into a JSON string, without any indendtation or
    57  // HTML escapes.
    58  // Context is used to output a log waring if the conversion fails.
    59  //
    60  // This is intended primarily for `trace.StringAttribute()`
    61  func Format(ctx context.Context, v interface{}) string {
    62  	b, err := encode(v)
    63  	if err != nil {
    64  		G(ctx).WithError(err).Warning("could not format value")
    65  		return ""
    66  	}
    67  
    68  	return string(b)
    69  }
    70  
    71  func encode(v interface{}) ([]byte, error) {
    72  	return encodeBuffer(&bytes.Buffer{}, v)
    73  }
    74  
    75  func encodeBuffer(buf *bytes.Buffer, v interface{}) ([]byte, error) {
    76  	enc := json.NewEncoder(buf)
    77  	enc.SetEscapeHTML(false)
    78  	enc.SetIndent("", "")
    79  
    80  	if err := enc.Encode(v); err != nil {
    81  		err = fmt.Errorf("could not marshall %T to JSON for logging: %w", v, err)
    82  		return nil, err
    83  	}
    84  
    85  	// encoder.Encode appends a newline to the end
    86  	return bytes.TrimSpace(buf.Bytes()), nil
    87  }
    88  

View as plain text