github.com/mongodb/grip@v0.0.0-20240213223901-f906268d82b9/message/interface.go (about)

     1  package message
     2  
     3  import "github.com/mongodb/grip/level"
     4  
     5  // Composer defines an interface with a "String()" method that
     6  // returns the message in string format. Objects that implement this
     7  // interface, in combination to the Compose[*] operations, the
     8  // String() method is only caled if the priority of the method is
     9  // greater than the threshold priority. This makes it possible to
    10  // defer building log messages (that may be somewhat expensive to
    11  // generate) until it's certain that we're going to be outputting the
    12  // message.
    13  type Composer interface {
    14  	// Returns the content of the message as a string for use in
    15  	// line-printing logging engines.
    16  	String() string
    17  
    18  	// A "raw" format of the logging output for use by some Sender
    19  	// implementations that write logged items to interfaces that
    20  	// accept JSON or another structured format.
    21  	Raw() interface{}
    22  
    23  	// Returns "true" when the message has content and should be
    24  	// logged, and false otherwise. When false, the sender can
    25  	// (and should!) ignore messages even if they are otherwise
    26  	// above the logging threshold.
    27  	Loggable() bool
    28  
    29  	// Annotate makes it possible for Senders and Journalers to
    30  	// add structured data to a log message. May return an error
    31  	// when the key alrady exists.
    32  	Annotate(string, interface{}) error
    33  
    34  	// Priority returns the priority of the message.
    35  	Priority() level.Priority
    36  	SetPriority(level.Priority) error
    37  }
    38  
    39  // ErrorComposer defines an interface to a Composer that also includes an error.
    40  type ErrorComposer interface {
    41  	Composer
    42  	Error() string
    43  }
    44  
    45  // ConvertToComposer can coerce unknown objects into Composer
    46  // instances, as possible. This method will override the priority of
    47  // composers set to it.
    48  func ConvertToComposer(p level.Priority, message interface{}) Composer {
    49  	return convert(p, message, true)
    50  }
    51  
    52  // ConvertToComposerWithLevel can coerce unknown objects into
    53  // Composers, but will only override the priority of Composers.
    54  func ConvertToComposerWithLevel(p level.Priority, message interface{}) Composer {
    55  	return convert(p, message, false)
    56  }
    57  
    58  func convert(p level.Priority, message interface{}, overRideLevel bool) Composer {
    59  	switch message := message.(type) {
    60  	case Composer:
    61  		if overRideLevel || message.Priority() != level.Invalid {
    62  			_ = message.SetPriority(p)
    63  		}
    64  		return message
    65  	case []Composer:
    66  		out := NewGroupComposer(message)
    67  		// this only sets constituent
    68  		// messages priority when its not otherwise set.
    69  		_ = out.SetPriority(p)
    70  		return out
    71  	case string:
    72  		return NewDefaultMessage(p, message)
    73  	case error:
    74  		return NewErrorMessage(p, message)
    75  	case []string:
    76  		return newLinesFromStrings(p, message)
    77  	case []interface{}:
    78  		return NewLineMessage(p, message...)
    79  	case []byte:
    80  		return NewBytesMessage(p, message)
    81  	case Fields:
    82  		return NewFields(p, message)
    83  	case map[string]interface{}:
    84  		return NewFields(p, Fields(message))
    85  	case [][]string:
    86  		grp := make([]Composer, len(message))
    87  		for idx := range message {
    88  			grp[idx] = newLinesFromStrings(p, message[idx])
    89  		}
    90  		out := NewGroupComposer(grp)
    91  		return out
    92  	case [][]byte:
    93  		grp := make([]Composer, len(message))
    94  		for idx := range message {
    95  			grp[idx] = NewBytesMessage(p, message[idx])
    96  		}
    97  		out := NewGroupComposer(grp)
    98  		return out
    99  	case []map[string]interface{}:
   100  		grp := make([]Composer, len(message))
   101  		for idx := range message {
   102  			grp[idx] = NewFields(p, message[idx])
   103  		}
   104  		out := NewGroupComposer(grp)
   105  		return out
   106  	case []Fields:
   107  		grp := make([]Composer, len(message))
   108  		for idx := range message {
   109  			grp[idx] = NewFields(p, message[idx])
   110  		}
   111  		out := NewGroupComposer(grp)
   112  		return out
   113  	case nil:
   114  		return NewLineMessage(p)
   115  	default:
   116  		return NewFormattedMessage(p, "%+v", message)
   117  	}
   118  }