github.com/blend/go-sdk@v1.20220411.3/redis/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 redis
     9  
    10  import (
    11  	"context"
    12  	"fmt"
    13  	"io"
    14  	"strings"
    15  	"time"
    16  
    17  	"github.com/blend/go-sdk/ansi"
    18  	"github.com/blend/go-sdk/logger"
    19  	"github.com/blend/go-sdk/timeutil"
    20  )
    21  
    22  // Logger flags
    23  const (
    24  	Flag = "redis"
    25  )
    26  
    27  // these are compile time assertions
    28  var (
    29  	_ logger.Event        = (*Event)(nil)
    30  	_ logger.TextWritable = (*Event)(nil)
    31  	_ logger.JSONWritable = (*Event)(nil)
    32  )
    33  
    34  // NewEvent creates a new query event.
    35  func NewEvent(op string, args []string, elapsed time.Duration, options ...EventOption) Event {
    36  	qe := Event{
    37  		Op:      op,
    38  		Args:    args,
    39  		Elapsed: elapsed,
    40  	}
    41  	for _, opt := range options {
    42  		opt(&qe)
    43  	}
    44  	return qe
    45  }
    46  
    47  // NewEventListener returns a new listener for events.
    48  func NewEventListener(listener func(context.Context, Event)) logger.Listener {
    49  	return func(ctx context.Context, e logger.Event) {
    50  		if typed, isTyped := e.(Event); isTyped {
    51  			listener(ctx, typed)
    52  		}
    53  	}
    54  }
    55  
    56  // NewEventFilter returns a new event filter.
    57  func NewEventFilter(filter func(context.Context, Event) (Event, bool)) logger.Filter {
    58  	return func(ctx context.Context, e logger.Event) (logger.Event, bool) {
    59  		if typed, isTyped := e.(Event); isTyped {
    60  			return filter(ctx, typed)
    61  		}
    62  		return e, false
    63  	}
    64  }
    65  
    66  // EventOption mutates an event.
    67  type EventOption func(*Event)
    68  
    69  // OptEventNetwork sets a field on the event.
    70  func OptEventNetwork(value string) EventOption {
    71  	return func(e *Event) { e.Network = value }
    72  }
    73  
    74  // OptEventAddr sets a field on the event.
    75  func OptEventAddr(value string) EventOption {
    76  	return func(e *Event) { e.Addr = value }
    77  }
    78  
    79  // OptEventDB sets a field on the event.
    80  func OptEventDB(value string) EventOption {
    81  	return func(e *Event) { e.DB = value }
    82  }
    83  
    84  // OptEventAuthUser sets a field on the event.
    85  func OptEventAuthUser(value string) EventOption {
    86  	return func(e *Event) { e.AuthUser = value }
    87  }
    88  
    89  // OptEventOp sets a field on the event.
    90  func OptEventOp(value string) EventOption {
    91  	return func(e *Event) { e.Op = value }
    92  }
    93  
    94  // OptEventArgs sets a field on the event.
    95  func OptEventArgs(values ...string) EventOption {
    96  	return func(e *Event) { e.Args = values }
    97  }
    98  
    99  // OptEventElapsed sets a field on the event.
   100  func OptEventElapsed(value time.Duration) EventOption {
   101  	return func(e *Event) { e.Elapsed = value }
   102  }
   103  
   104  // OptEventErr sets a field on the event.
   105  func OptEventErr(value error) EventOption {
   106  	return func(e *Event) { e.Err = value }
   107  }
   108  
   109  // Event represents a call to redis.
   110  type Event struct {
   111  	Network  string
   112  	Addr     string
   113  	AuthUser string
   114  	DB       string
   115  	Op       string
   116  	Args     []string
   117  	Elapsed  time.Duration
   118  	Err      error
   119  }
   120  
   121  // GetFlag implements Event.
   122  func (e Event) GetFlag() string { return Flag }
   123  
   124  // WriteText writes the event text to the output.
   125  func (e Event) WriteText(tf logger.TextFormatter, wr io.Writer) {
   126  	fmt.Fprint(wr, "[")
   127  	if len(e.AuthUser) > 0 {
   128  		fmt.Fprint(wr, tf.Colorize(e.AuthUser, ansi.ColorLightWhite))
   129  		fmt.Fprint(wr, "@")
   130  	}
   131  	if len(e.Addr) > 0 {
   132  		fmt.Fprint(wr, tf.Colorize(e.Addr, ansi.ColorLightWhite))
   133  	}
   134  	if e.DB != "" {
   135  		fmt.Fprint(wr, "/")
   136  		fmt.Fprint(wr, tf.Colorize(fmt.Sprint(e.DB), ansi.ColorLightWhite))
   137  	}
   138  	fmt.Fprint(wr, "]")
   139  
   140  	if len(e.Op) > 0 {
   141  		fmt.Fprint(wr, logger.Space)
   142  		fmt.Fprintf(wr, "[%s]", tf.Colorize(e.Op, ansi.ColorLightBlue))
   143  	}
   144  	if len(e.Args) > 0 {
   145  		fmt.Fprint(wr, logger.Space)
   146  		fmt.Fprintf(wr, "%s", strings.Join(e.Args, ", "))
   147  	}
   148  
   149  	fmt.Fprint(wr, logger.Space)
   150  	fmt.Fprint(wr, e.Elapsed.String())
   151  
   152  	if e.Err != nil {
   153  		fmt.Fprint(wr, logger.Space)
   154  		fmt.Fprint(wr, tf.Colorize("failed", ansi.ColorRed))
   155  	}
   156  }
   157  
   158  // Decompose implements JSONWritable.
   159  func (e Event) Decompose() map[string]interface{} {
   160  	return map[string]interface{}{
   161  		"addr":    e.Addr,
   162  		"db":      e.DB,
   163  		"op":      e.Op,
   164  		"args":    e.Args,
   165  		"elapsed": timeutil.Milliseconds(e.Elapsed),
   166  		"err":     e.Err,
   167  	}
   168  }