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

     1  package message
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"time"
     7  
     8  	"github.com/mongodb/grip/level"
     9  )
    10  
    11  // Base provides a simple embeddable implementation of some common
    12  // aspects of a message.Composer. Additionally the Collect() method
    13  // collects some simple metadata, that may be useful for some more
    14  // structured logging applications.
    15  type Base struct {
    16  	Level    level.Priority `bson:"level,omitempty" json:"level,omitempty" yaml:"level,omitempty"`
    17  	Hostname string         `bson:"hostname,omitempty" json:"hostname,omitempty" yaml:"hostname,omitempty"`
    18  	Time     time.Time      `bson:"time,omitempty" json:"time,omitempty" yaml:"time,omitempty"`
    19  	Process  string         `bson:"process,omitempty" json:"process,omitempty" yaml:"process,omitempty"`
    20  	Pid      int            `bson:"pid,omitempty" json:"pid,omitempty" yaml:"pid,omitempty"`
    21  	Context  Fields         `bson:"context,omitempty" json:"context,omitempty" yaml:"context,omitempty"`
    22  }
    23  
    24  // IsZero returns true when Base is nil or it is non-nil and none of
    25  // its fields are set.
    26  func (b *Base) IsZero() bool {
    27  	return b == nil || b.Level == level.Invalid && b.Hostname == "" && b.Time.IsZero() && b.Process == "" && b.Pid == 0 && b.Context == nil
    28  }
    29  
    30  // Collect records the message time. If includeExtended is true, it also
    31  // includes, the process ID, process name, and hostname. Useful for logging
    32  // extended metadata information.
    33  func (b *Base) Collect(includeExtended bool) error {
    34  	if !b.Time.IsZero() {
    35  		return nil
    36  	}
    37  	b.Time = time.Now()
    38  
    39  	if !includeExtended {
    40  		return nil
    41  	}
    42  
    43  	if b.Pid > 0 {
    44  		return nil
    45  	}
    46  
    47  	var err error
    48  	b.Hostname, err = os.Hostname()
    49  	if err != nil {
    50  		return err
    51  	}
    52  
    53  	b.Process = os.Args[0]
    54  	b.Pid = os.Getpid()
    55  
    56  	return nil
    57  }
    58  
    59  // Priority returns the configured priority of the message.
    60  func (b *Base) Priority() level.Priority {
    61  	return b.Level
    62  }
    63  
    64  // SetPriority allows you to configure the priority of the
    65  // message. Returns an error if the priority is not valid.
    66  func (b *Base) SetPriority(l level.Priority) error {
    67  	if !l.IsValid() {
    68  		return fmt.Errorf("%s (%d) is not a valid priority", l, l)
    69  	}
    70  
    71  	b.Level = l
    72  
    73  	return nil
    74  }
    75  
    76  // Annotate makes it possible for callers and senders to add
    77  // structured data to a message. This may be overridden for some
    78  // implementations
    79  func (b *Base) Annotate(key string, value interface{}) error {
    80  	if b.Context == nil {
    81  		b.Context = Fields{
    82  			key: value,
    83  		}
    84  
    85  		return nil
    86  	}
    87  
    88  	if _, ok := b.Context[key]; ok {
    89  		return fmt.Errorf("key '%s' already exists", key)
    90  	}
    91  
    92  	b.Context[key] = value
    93  
    94  	return nil
    95  }