...

Source file src/go.mongodb.org/mongo-driver/internal/logger/component.go

Documentation: go.mongodb.org/mongo-driver/internal/logger

     1  // Copyright (C) MongoDB, Inc. 2023-present.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6  
     7  package logger
     8  
     9  import (
    10  	"os"
    11  	"strconv"
    12  
    13  	"go.mongodb.org/mongo-driver/bson/primitive"
    14  )
    15  
    16  const (
    17  	CommandFailed                    = "Command failed"
    18  	CommandStarted                   = "Command started"
    19  	CommandSucceeded                 = "Command succeeded"
    20  	ConnectionPoolCreated            = "Connection pool created"
    21  	ConnectionPoolReady              = "Connection pool ready"
    22  	ConnectionPoolCleared            = "Connection pool cleared"
    23  	ConnectionPoolClosed             = "Connection pool closed"
    24  	ConnectionCreated                = "Connection created"
    25  	ConnectionReady                  = "Connection ready"
    26  	ConnectionClosed                 = "Connection closed"
    27  	ConnectionCheckoutStarted        = "Connection checkout started"
    28  	ConnectionCheckoutFailed         = "Connection checkout failed"
    29  	ConnectionCheckedOut             = "Connection checked out"
    30  	ConnectionCheckedIn              = "Connection checked in"
    31  	ServerSelectionFailed            = "Server selection failed"
    32  	ServerSelectionStarted           = "Server selection started"
    33  	ServerSelectionSucceeded         = "Server selection succeeded"
    34  	ServerSelectionWaiting           = "Waiting for suitable server to become available"
    35  	TopologyClosed                   = "Stopped topology monitoring"
    36  	TopologyDescriptionChanged       = "Topology description changed"
    37  	TopologyOpening                  = "Starting topology monitoring"
    38  	TopologyServerClosed             = "Stopped server monitoring"
    39  	TopologyServerHeartbeatFailed    = "Server heartbeat failed"
    40  	TopologyServerHeartbeatStarted   = "Server heartbeat started"
    41  	TopologyServerHeartbeatSucceeded = "Server heartbeat succeeded"
    42  	TopologyServerOpening            = "Starting server monitoring"
    43  )
    44  
    45  const (
    46  	KeyAwaited             = "awaited"
    47  	KeyCommand             = "command"
    48  	KeyCommandName         = "commandName"
    49  	KeyDatabaseName        = "databaseName"
    50  	KeyDriverConnectionID  = "driverConnectionId"
    51  	KeyDurationMS          = "durationMS"
    52  	KeyError               = "error"
    53  	KeyFailure             = "failure"
    54  	KeyMaxConnecting       = "maxConnecting"
    55  	KeyMaxIdleTimeMS       = "maxIdleTimeMS"
    56  	KeyMaxPoolSize         = "maxPoolSize"
    57  	KeyMessage             = "message"
    58  	KeyMinPoolSize         = "minPoolSize"
    59  	KeyNewDescription      = "newDescription"
    60  	KeyOperation           = "operation"
    61  	KeyOperationID         = "operationId"
    62  	KeyPreviousDescription = "previousDescription"
    63  	KeyRemainingTimeMS     = "remainingTimeMS"
    64  	KeyReason              = "reason"
    65  	KeyReply               = "reply"
    66  	KeyRequestID           = "requestId"
    67  	KeySelector            = "selector"
    68  	KeyServerConnectionID  = "serverConnectionId"
    69  	KeyServerHost          = "serverHost"
    70  	KeyServerPort          = "serverPort"
    71  	KeyServiceID           = "serviceId"
    72  	KeyTimestamp           = "timestamp"
    73  	KeyTopologyDescription = "topologyDescription"
    74  	KeyTopologyID          = "topologyId"
    75  )
    76  
    77  // KeyValues is a list of key-value pairs.
    78  type KeyValues []interface{}
    79  
    80  // Add adds a key-value pair to an instance of a KeyValues list.
    81  func (kvs *KeyValues) Add(key string, value interface{}) {
    82  	*kvs = append(*kvs, key, value)
    83  }
    84  
    85  const (
    86  	ReasonConnClosedStale              = "Connection became stale because the pool was cleared"
    87  	ReasonConnClosedIdle               = "Connection has been available but unused for longer than the configured max idle time"
    88  	ReasonConnClosedError              = "An error occurred while using the connection"
    89  	ReasonConnClosedPoolClosed         = "Connection pool was closed"
    90  	ReasonConnCheckoutFailedTimout     = "Wait queue timeout elapsed without a connection becoming available"
    91  	ReasonConnCheckoutFailedError      = "An error occurred while trying to establish a new connection"
    92  	ReasonConnCheckoutFailedPoolClosed = "Connection pool was closed"
    93  )
    94  
    95  // Component is an enumeration representing the "components" which can be
    96  // logged against. A LogLevel can be configured on a per-component basis.
    97  type Component int
    98  
    99  const (
   100  	// ComponentAll enables logging for all components.
   101  	ComponentAll Component = iota
   102  
   103  	// ComponentCommand enables command monitor logging.
   104  	ComponentCommand
   105  
   106  	// ComponentTopology enables topology logging.
   107  	ComponentTopology
   108  
   109  	// ComponentServerSelection enables server selection logging.
   110  	ComponentServerSelection
   111  
   112  	// ComponentConnection enables connection services logging.
   113  	ComponentConnection
   114  )
   115  
   116  const (
   117  	mongoDBLogAllEnvVar             = "MONGODB_LOG_ALL"
   118  	mongoDBLogCommandEnvVar         = "MONGODB_LOG_COMMAND"
   119  	mongoDBLogTopologyEnvVar        = "MONGODB_LOG_TOPOLOGY"
   120  	mongoDBLogServerSelectionEnvVar = "MONGODB_LOG_SERVER_SELECTION"
   121  	mongoDBLogConnectionEnvVar      = "MONGODB_LOG_CONNECTION"
   122  )
   123  
   124  var componentEnvVarMap = map[string]Component{
   125  	mongoDBLogAllEnvVar:             ComponentAll,
   126  	mongoDBLogCommandEnvVar:         ComponentCommand,
   127  	mongoDBLogTopologyEnvVar:        ComponentTopology,
   128  	mongoDBLogServerSelectionEnvVar: ComponentServerSelection,
   129  	mongoDBLogConnectionEnvVar:      ComponentConnection,
   130  }
   131  
   132  // EnvHasComponentVariables returns true if the environment contains any of the
   133  // component environment variables.
   134  func EnvHasComponentVariables() bool {
   135  	for envVar := range componentEnvVarMap {
   136  		if os.Getenv(envVar) != "" {
   137  			return true
   138  		}
   139  	}
   140  
   141  	return false
   142  }
   143  
   144  // Command is a struct defining common fields that must be included in all
   145  // commands.
   146  type Command struct {
   147  	// TODO(GODRIVER-2824): change the DriverConnectionID type to int64.
   148  	DriverConnectionID uint64              // Driver's ID for the connection
   149  	Name               string              // Command name
   150  	DatabaseName       string              // Database name
   151  	Message            string              // Message associated with the command
   152  	OperationID        int32               // Driver-generated operation ID
   153  	RequestID          int64               // Driver-generated request ID
   154  	ServerConnectionID *int64              // Server's ID for the connection used for the command
   155  	ServerHost         string              // Hostname or IP address for the server
   156  	ServerPort         string              // Port for the server
   157  	ServiceID          *primitive.ObjectID // ID for the command  in load balancer mode
   158  }
   159  
   160  // SerializeCommand takes a command and a variable number of key-value pairs and
   161  // returns a slice of interface{} that can be passed to the logger for
   162  // structured logging.
   163  func SerializeCommand(cmd Command, extraKeysAndValues ...interface{}) KeyValues {
   164  	// Initialize the boilerplate keys and values.
   165  	keysAndValues := KeyValues{
   166  		KeyCommandName, cmd.Name,
   167  		KeyDatabaseName, cmd.DatabaseName,
   168  		KeyDriverConnectionID, cmd.DriverConnectionID,
   169  		KeyMessage, cmd.Message,
   170  		KeyOperationID, cmd.OperationID,
   171  		KeyRequestID, cmd.RequestID,
   172  		KeyServerHost, cmd.ServerHost,
   173  	}
   174  
   175  	// Add the extra keys and values.
   176  	for i := 0; i < len(extraKeysAndValues); i += 2 {
   177  		keysAndValues.Add(extraKeysAndValues[i].(string), extraKeysAndValues[i+1])
   178  	}
   179  
   180  	port, err := strconv.ParseInt(cmd.ServerPort, 10, 32)
   181  	if err == nil {
   182  		keysAndValues.Add(KeyServerPort, port)
   183  	}
   184  
   185  	// Add the "serverConnectionId" if it is not nil.
   186  	if cmd.ServerConnectionID != nil {
   187  		keysAndValues.Add(KeyServerConnectionID, *cmd.ServerConnectionID)
   188  	}
   189  
   190  	// Add the "serviceId" if it is not nil.
   191  	if cmd.ServiceID != nil {
   192  		keysAndValues.Add(KeyServiceID, cmd.ServiceID.Hex())
   193  	}
   194  
   195  	return keysAndValues
   196  }
   197  
   198  // Connection contains data that all connection log messages MUST contain.
   199  type Connection struct {
   200  	Message    string // Message associated with the connection
   201  	ServerHost string // Hostname or IP address for the server
   202  	ServerPort string // Port for the server
   203  }
   204  
   205  // SerializeConnection serializes a Connection message into a slice of keys and
   206  // values that can be passed to a logger.
   207  func SerializeConnection(conn Connection, extraKeysAndValues ...interface{}) KeyValues {
   208  	// Initialize the boilerplate keys and values.
   209  	keysAndValues := KeyValues{
   210  		KeyMessage, conn.Message,
   211  		KeyServerHost, conn.ServerHost,
   212  	}
   213  
   214  	// Add the optional keys and values.
   215  	for i := 0; i < len(extraKeysAndValues); i += 2 {
   216  		keysAndValues.Add(extraKeysAndValues[i].(string), extraKeysAndValues[i+1])
   217  	}
   218  
   219  	port, err := strconv.ParseInt(conn.ServerPort, 10, 32)
   220  	if err == nil {
   221  		keysAndValues.Add(KeyServerPort, port)
   222  	}
   223  
   224  	return keysAndValues
   225  }
   226  
   227  // Server contains data that all server messages MAY contain.
   228  type Server struct {
   229  	DriverConnectionID uint64             // Driver's ID for the connection
   230  	TopologyID         primitive.ObjectID // Driver's unique ID for this topology
   231  	Message            string             // Message associated with the topology
   232  	ServerConnectionID *int64             // Server's ID for the connection
   233  	ServerHost         string             // Hostname or IP address for the server
   234  	ServerPort         string             // Port for the server
   235  }
   236  
   237  // SerializeServer serializes a Server message into a slice of keys and
   238  // values that can be passed to a logger.
   239  func SerializeServer(srv Server, extraKV ...interface{}) KeyValues {
   240  	// Initialize the boilerplate keys and values.
   241  	keysAndValues := KeyValues{
   242  		KeyDriverConnectionID, srv.DriverConnectionID,
   243  		KeyMessage, srv.Message,
   244  		KeyServerHost, srv.ServerHost,
   245  		KeyTopologyID, srv.TopologyID.Hex(),
   246  	}
   247  
   248  	if connID := srv.ServerConnectionID; connID != nil {
   249  		keysAndValues.Add(KeyServerConnectionID, *connID)
   250  	}
   251  
   252  	port, err := strconv.ParseInt(srv.ServerPort, 10, 32)
   253  	if err == nil {
   254  		keysAndValues.Add(KeyServerPort, port)
   255  	}
   256  
   257  	// Add the optional keys and values.
   258  	for i := 0; i < len(extraKV); i += 2 {
   259  		keysAndValues.Add(extraKV[i].(string), extraKV[i+1])
   260  	}
   261  
   262  	return keysAndValues
   263  }
   264  
   265  // ServerSelection contains data that all server selection messages MUST
   266  // contain.
   267  type ServerSelection struct {
   268  	Selector            string
   269  	OperationID         *int32
   270  	Operation           string
   271  	TopologyDescription string
   272  }
   273  
   274  // SerializeServerSelection serializes a Topology message into a slice of keys
   275  // and values that can be passed to a logger.
   276  func SerializeServerSelection(srvSelection ServerSelection, extraKV ...interface{}) KeyValues {
   277  	keysAndValues := KeyValues{
   278  		KeySelector, srvSelection.Selector,
   279  		KeyOperation, srvSelection.Operation,
   280  		KeyTopologyDescription, srvSelection.TopologyDescription,
   281  	}
   282  
   283  	if srvSelection.OperationID != nil {
   284  		keysAndValues.Add(KeyOperationID, *srvSelection.OperationID)
   285  	}
   286  
   287  	// Add the optional keys and values.
   288  	for i := 0; i < len(extraKV); i += 2 {
   289  		keysAndValues.Add(extraKV[i].(string), extraKV[i+1])
   290  	}
   291  
   292  	return keysAndValues
   293  }
   294  
   295  // Topology contains data that all topology messages MAY contain.
   296  type Topology struct {
   297  	ID      primitive.ObjectID // Driver's unique ID for this topology
   298  	Message string             // Message associated with the topology
   299  }
   300  
   301  // SerializeTopology serializes a Topology message into a slice of keys and
   302  // values that can be passed to a logger.
   303  func SerializeTopology(topo Topology, extraKV ...interface{}) KeyValues {
   304  	keysAndValues := KeyValues{
   305  		KeyTopologyID, topo.ID.Hex(),
   306  	}
   307  
   308  	// Add the optional keys and values.
   309  	for i := 0; i < len(extraKV); i += 2 {
   310  		keysAndValues.Add(extraKV[i].(string), extraKV[i+1])
   311  	}
   312  
   313  	return keysAndValues
   314  }
   315  

View as plain text