github.com/blend/go-sdk@v1.20220411.3/grpcutil/rpc_stream_message_event.go (about)

     1  /*
     2  
     3  Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file.
     5  
     6  */
     7  
     8  package grpcutil
     9  
    10  import (
    11  	"context"
    12  	"fmt"
    13  	"io"
    14  	"time"
    15  
    16  	"github.com/blend/go-sdk/ansi"
    17  	"github.com/blend/go-sdk/logger"
    18  	"github.com/blend/go-sdk/timeutil"
    19  )
    20  
    21  // Logger flags
    22  const (
    23  	FlagRPCStreamMessage = "rpc.stream.message"
    24  )
    25  
    26  // these are compile time assertions
    27  var (
    28  	_ logger.Event        = (*RPCStreamMessageEvent)(nil)
    29  	_ logger.TextWritable = (*RPCStreamMessageEvent)(nil)
    30  	_ logger.JSONWritable = (*RPCStreamMessageEvent)(nil)
    31  )
    32  
    33  // StreamMessageDirection is the direction the message was sent.
    34  type StreamMessageDirection string
    35  
    36  // constants
    37  const (
    38  	StreamMessageDirectionReceive = "recv"
    39  	StreamMessageDirectionSend    = "send"
    40  )
    41  
    42  // NewRPCStreamMessageEvent creates a new rpc stream message event.
    43  func NewRPCStreamMessageEvent(method string, direction StreamMessageDirection, elapsed time.Duration, options ...RPCStreamMessageEventOption) RPCStreamMessageEvent {
    44  	rpe := RPCStreamMessageEvent{
    45  		RPCEvent: RPCEvent{
    46  			Engine:  EngineGRPC,
    47  			Method:  method,
    48  			Elapsed: elapsed,
    49  		},
    50  		Direction: direction,
    51  	}
    52  	for _, opt := range options {
    53  		opt(&rpe)
    54  	}
    55  	return rpe
    56  }
    57  
    58  // NewRPCStreamMessageEventListener returns a new rpc stream message event event listener.
    59  func NewRPCStreamMessageEventListener(listener func(context.Context, RPCStreamMessageEvent)) logger.Listener {
    60  	return func(ctx context.Context, e logger.Event) {
    61  		if typed, isTyped := e.(RPCStreamMessageEvent); isTyped {
    62  			listener(ctx, typed)
    63  		}
    64  	}
    65  }
    66  
    67  // NewRPCStreamMessageEventFilter returns a new rpc stream message event filter.
    68  func NewRPCStreamMessageEventFilter(filter func(context.Context, RPCStreamMessageEvent) (RPCStreamMessageEvent, bool)) logger.Filter {
    69  	return func(ctx context.Context, e logger.Event) (logger.Event, bool) {
    70  		if typed, isTyped := e.(RPCStreamMessageEvent); isTyped {
    71  			return filter(ctx, typed)
    72  		}
    73  		return e, false
    74  	}
    75  }
    76  
    77  // RPCStreamMessageEventOption is a mutator for RPCEvents.
    78  type RPCStreamMessageEventOption func(*RPCStreamMessageEvent)
    79  
    80  // OptRPCStreamMessageEngine sets a field on the event.
    81  func OptRPCStreamMessageEngine(value string) RPCStreamMessageEventOption {
    82  	return func(e *RPCStreamMessageEvent) { e.Engine = value }
    83  }
    84  
    85  // OptRPCStreamMessagePeer sets a field on the event.
    86  func OptRPCStreamMessagePeer(value string) RPCStreamMessageEventOption {
    87  	return func(e *RPCStreamMessageEvent) { e.Peer = value }
    88  }
    89  
    90  // OptRPCStreamMessageMethod sets a field on the event.
    91  func OptRPCStreamMessageMethod(value string) RPCStreamMessageEventOption {
    92  	return func(e *RPCStreamMessageEvent) { e.Method = value }
    93  }
    94  
    95  // OptRPCStreamMessageDirection sets a field on the event.
    96  func OptRPCStreamMessageDirection(value StreamMessageDirection) RPCStreamMessageEventOption {
    97  	return func(e *RPCStreamMessageEvent) { e.Direction = value }
    98  }
    99  
   100  // OptRPCStreamMessageUserAgent sets a field on the event.
   101  func OptRPCStreamMessageUserAgent(value string) RPCStreamMessageEventOption {
   102  	return func(e *RPCStreamMessageEvent) { e.UserAgent = value }
   103  }
   104  
   105  // OptRPCStreamMessageAuthority sets a field on the event.
   106  func OptRPCStreamMessageAuthority(value string) RPCStreamMessageEventOption {
   107  	return func(e *RPCStreamMessageEvent) { e.Authority = value }
   108  }
   109  
   110  // OptRPCStreamMessageContentType sets a field on the event.
   111  func OptRPCStreamMessageContentType(value string) RPCStreamMessageEventOption {
   112  	return func(e *RPCStreamMessageEvent) { e.ContentType = value }
   113  }
   114  
   115  // OptRPCStreamMessageElapsed sets a field on the event.
   116  func OptRPCStreamMessageElapsed(value time.Duration) RPCStreamMessageEventOption {
   117  	return func(e *RPCStreamMessageEvent) { e.Elapsed = value }
   118  }
   119  
   120  // OptRPCStreamMessageErr sets a field on the event.
   121  func OptRPCStreamMessageErr(value error) RPCStreamMessageEventOption {
   122  	return func(e *RPCStreamMessageEvent) { e.Err = value }
   123  }
   124  
   125  // RPCStreamMessageEvent is an event type for rpc
   126  type RPCStreamMessageEvent struct {
   127  	RPCEvent
   128  	Direction StreamMessageDirection
   129  }
   130  
   131  // GetFlag implements Event.
   132  func (e RPCStreamMessageEvent) GetFlag() string { return FlagRPCStreamMessage }
   133  
   134  // WriteText implements TextWritable.
   135  func (e RPCStreamMessageEvent) WriteText(tf logger.TextFormatter, wr io.Writer) {
   136  	if e.Engine != "" {
   137  		fmt.Fprint(wr, "[")
   138  		fmt.Fprint(wr, tf.Colorize(e.Engine, ansi.ColorLightWhite))
   139  		fmt.Fprint(wr, "]")
   140  	}
   141  	if e.Method != "" {
   142  		if e.Engine != "" {
   143  			fmt.Fprint(wr, logger.Space)
   144  		}
   145  		fmt.Fprint(wr, tf.Colorize(e.Method, ansi.ColorBlue))
   146  	}
   147  	if e.Direction != "" {
   148  		fmt.Fprint(wr, logger.Space)
   149  		fmt.Fprint(wr, e.Direction)
   150  	}
   151  	if e.Peer != "" {
   152  		fmt.Fprint(wr, logger.Space)
   153  		fmt.Fprint(wr, e.Peer)
   154  	}
   155  	if e.Authority != "" {
   156  		fmt.Fprint(wr, logger.Space)
   157  		fmt.Fprint(wr, e.Authority)
   158  	}
   159  	if e.UserAgent != "" {
   160  		fmt.Fprint(wr, logger.Space)
   161  		fmt.Fprint(wr, e.UserAgent)
   162  	}
   163  	if e.ContentType != "" {
   164  		fmt.Fprint(wr, logger.Space)
   165  		fmt.Fprint(wr, e.ContentType)
   166  	}
   167  
   168  	fmt.Fprint(wr, logger.Space)
   169  	fmt.Fprint(wr, e.Elapsed.String())
   170  
   171  	if e.Err != nil {
   172  		fmt.Fprint(wr, logger.Space)
   173  		fmt.Fprint(wr, tf.Colorize("failed", ansi.ColorRed))
   174  	}
   175  }
   176  
   177  // Decompose implements JSONWritable.
   178  func (e RPCStreamMessageEvent) Decompose() map[string]interface{} {
   179  	return map[string]interface{}{
   180  		"engine":      e.Engine,
   181  		"peer":        e.Peer,
   182  		"method":      e.Method,
   183  		"direction":   e.Direction,
   184  		"userAgent":   e.UserAgent,
   185  		"authority":   e.Authority,
   186  		"contentType": e.ContentType,
   187  		"elapsed":     timeutil.Milliseconds(e.Elapsed),
   188  		"err":         e.Err,
   189  	}
   190  }