service/vendor/go.mongodb.org/mongo-driver/internal/logger/component.go

315 lines
11 KiB
Go

// Copyright (C) MongoDB, Inc. 2023-present.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
package logger
import (
"os"
"strconv"
"go.mongodb.org/mongo-driver/bson/primitive"
)
const (
CommandFailed = "Command failed"
CommandStarted = "Command started"
CommandSucceeded = "Command succeeded"
ConnectionPoolCreated = "Connection pool created"
ConnectionPoolReady = "Connection pool ready"
ConnectionPoolCleared = "Connection pool cleared"
ConnectionPoolClosed = "Connection pool closed"
ConnectionCreated = "Connection created"
ConnectionReady = "Connection ready"
ConnectionClosed = "Connection closed"
ConnectionCheckoutStarted = "Connection checkout started"
ConnectionCheckoutFailed = "Connection checkout failed"
ConnectionCheckedOut = "Connection checked out"
ConnectionCheckedIn = "Connection checked in"
ServerSelectionFailed = "Server selection failed"
ServerSelectionStarted = "Server selection started"
ServerSelectionSucceeded = "Server selection succeeded"
ServerSelectionWaiting = "Waiting for suitable server to become available"
TopologyClosed = "Stopped topology monitoring"
TopologyDescriptionChanged = "Topology description changed"
TopologyOpening = "Starting topology monitoring"
TopologyServerClosed = "Stopped server monitoring"
TopologyServerHeartbeatFailed = "Server heartbeat failed"
TopologyServerHeartbeatStarted = "Server heartbeat started"
TopologyServerHeartbeatSucceeded = "Server heartbeat succeeded"
TopologyServerOpening = "Starting server monitoring"
)
const (
KeyAwaited = "awaited"
KeyCommand = "command"
KeyCommandName = "commandName"
KeyDatabaseName = "databaseName"
KeyDriverConnectionID = "driverConnectionId"
KeyDurationMS = "durationMS"
KeyError = "error"
KeyFailure = "failure"
KeyMaxConnecting = "maxConnecting"
KeyMaxIdleTimeMS = "maxIdleTimeMS"
KeyMaxPoolSize = "maxPoolSize"
KeyMessage = "message"
KeyMinPoolSize = "minPoolSize"
KeyNewDescription = "newDescription"
KeyOperation = "operation"
KeyOperationID = "operationId"
KeyPreviousDescription = "previousDescription"
KeyRemainingTimeMS = "remainingTimeMS"
KeyReason = "reason"
KeyReply = "reply"
KeyRequestID = "requestId"
KeySelector = "selector"
KeyServerConnectionID = "serverConnectionId"
KeyServerHost = "serverHost"
KeyServerPort = "serverPort"
KeyServiceID = "serviceId"
KeyTimestamp = "timestamp"
KeyTopologyDescription = "topologyDescription"
KeyTopologyID = "topologyId"
)
// KeyValues is a list of key-value pairs.
type KeyValues []interface{}
// Add adds a key-value pair to an instance of a KeyValues list.
func (kvs *KeyValues) Add(key string, value interface{}) {
*kvs = append(*kvs, key, value)
}
const (
ReasonConnClosedStale = "Connection became stale because the pool was cleared"
ReasonConnClosedIdle = "Connection has been available but unused for longer than the configured max idle time"
ReasonConnClosedError = "An error occurred while using the connection"
ReasonConnClosedPoolClosed = "Connection pool was closed"
ReasonConnCheckoutFailedTimout = "Wait queue timeout elapsed without a connection becoming available"
ReasonConnCheckoutFailedError = "An error occurred while trying to establish a new connection"
ReasonConnCheckoutFailedPoolClosed = "Connection pool was closed"
)
// Component is an enumeration representing the "components" which can be
// logged against. A LogLevel can be configured on a per-component basis.
type Component int
const (
// ComponentAll enables logging for all components.
ComponentAll Component = iota
// ComponentCommand enables command monitor logging.
ComponentCommand
// ComponentTopology enables topology logging.
ComponentTopology
// ComponentServerSelection enables server selection logging.
ComponentServerSelection
// ComponentConnection enables connection services logging.
ComponentConnection
)
const (
mongoDBLogAllEnvVar = "MONGODB_LOG_ALL"
mongoDBLogCommandEnvVar = "MONGODB_LOG_COMMAND"
mongoDBLogTopologyEnvVar = "MONGODB_LOG_TOPOLOGY"
mongoDBLogServerSelectionEnvVar = "MONGODB_LOG_SERVER_SELECTION"
mongoDBLogConnectionEnvVar = "MONGODB_LOG_CONNECTION"
)
var componentEnvVarMap = map[string]Component{
mongoDBLogAllEnvVar: ComponentAll,
mongoDBLogCommandEnvVar: ComponentCommand,
mongoDBLogTopologyEnvVar: ComponentTopology,
mongoDBLogServerSelectionEnvVar: ComponentServerSelection,
mongoDBLogConnectionEnvVar: ComponentConnection,
}
// EnvHasComponentVariables returns true if the environment contains any of the
// component environment variables.
func EnvHasComponentVariables() bool {
for envVar := range componentEnvVarMap {
if os.Getenv(envVar) != "" {
return true
}
}
return false
}
// Command is a struct defining common fields that must be included in all
// commands.
type Command struct {
// TODO(GODRIVER-2824): change the DriverConnectionID type to int64.
DriverConnectionID uint64 // Driver's ID for the connection
Name string // Command name
DatabaseName string // Database name
Message string // Message associated with the command
OperationID int32 // Driver-generated operation ID
RequestID int64 // Driver-generated request ID
ServerConnectionID *int64 // Server's ID for the connection used for the command
ServerHost string // Hostname or IP address for the server
ServerPort string // Port for the server
ServiceID *primitive.ObjectID // ID for the command in load balancer mode
}
// SerializeCommand takes a command and a variable number of key-value pairs and
// returns a slice of interface{} that can be passed to the logger for
// structured logging.
func SerializeCommand(cmd Command, extraKeysAndValues ...interface{}) KeyValues {
// Initialize the boilerplate keys and values.
keysAndValues := KeyValues{
KeyCommandName, cmd.Name,
KeyDatabaseName, cmd.DatabaseName,
KeyDriverConnectionID, cmd.DriverConnectionID,
KeyMessage, cmd.Message,
KeyOperationID, cmd.OperationID,
KeyRequestID, cmd.RequestID,
KeyServerHost, cmd.ServerHost,
}
// Add the extra keys and values.
for i := 0; i < len(extraKeysAndValues); i += 2 {
keysAndValues.Add(extraKeysAndValues[i].(string), extraKeysAndValues[i+1])
}
port, err := strconv.ParseInt(cmd.ServerPort, 10, 32)
if err == nil {
keysAndValues.Add(KeyServerPort, port)
}
// Add the "serverConnectionId" if it is not nil.
if cmd.ServerConnectionID != nil {
keysAndValues.Add(KeyServerConnectionID, *cmd.ServerConnectionID)
}
// Add the "serviceId" if it is not nil.
if cmd.ServiceID != nil {
keysAndValues.Add(KeyServiceID, cmd.ServiceID.Hex())
}
return keysAndValues
}
// Connection contains data that all connection log messages MUST contain.
type Connection struct {
Message string // Message associated with the connection
ServerHost string // Hostname or IP address for the server
ServerPort string // Port for the server
}
// SerializeConnection serializes a Connection message into a slice of keys and
// values that can be passed to a logger.
func SerializeConnection(conn Connection, extraKeysAndValues ...interface{}) KeyValues {
// Initialize the boilerplate keys and values.
keysAndValues := KeyValues{
KeyMessage, conn.Message,
KeyServerHost, conn.ServerHost,
}
// Add the optional keys and values.
for i := 0; i < len(extraKeysAndValues); i += 2 {
keysAndValues.Add(extraKeysAndValues[i].(string), extraKeysAndValues[i+1])
}
port, err := strconv.ParseInt(conn.ServerPort, 10, 32)
if err == nil {
keysAndValues.Add(KeyServerPort, port)
}
return keysAndValues
}
// Server contains data that all server messages MAY contain.
type Server struct {
DriverConnectionID uint64 // Driver's ID for the connection
TopologyID primitive.ObjectID // Driver's unique ID for this topology
Message string // Message associated with the topology
ServerConnectionID *int64 // Server's ID for the connection
ServerHost string // Hostname or IP address for the server
ServerPort string // Port for the server
}
// SerializeServer serializes a Server message into a slice of keys and
// values that can be passed to a logger.
func SerializeServer(srv Server, extraKV ...interface{}) KeyValues {
// Initialize the boilerplate keys and values.
keysAndValues := KeyValues{
KeyDriverConnectionID, srv.DriverConnectionID,
KeyMessage, srv.Message,
KeyServerHost, srv.ServerHost,
KeyTopologyID, srv.TopologyID.Hex(),
}
if connID := srv.ServerConnectionID; connID != nil {
keysAndValues.Add(KeyServerConnectionID, *connID)
}
port, err := strconv.ParseInt(srv.ServerPort, 10, 32)
if err == nil {
keysAndValues.Add(KeyServerPort, port)
}
// Add the optional keys and values.
for i := 0; i < len(extraKV); i += 2 {
keysAndValues.Add(extraKV[i].(string), extraKV[i+1])
}
return keysAndValues
}
// ServerSelection contains data that all server selection messages MUST
// contain.
type ServerSelection struct {
Selector string
OperationID *int32
Operation string
TopologyDescription string
}
// SerializeServerSelection serializes a Topology message into a slice of keys
// and values that can be passed to a logger.
func SerializeServerSelection(srvSelection ServerSelection, extraKV ...interface{}) KeyValues {
keysAndValues := KeyValues{
KeySelector, srvSelection.Selector,
KeyOperation, srvSelection.Operation,
KeyTopologyDescription, srvSelection.TopologyDescription,
}
if srvSelection.OperationID != nil {
keysAndValues.Add(KeyOperationID, *srvSelection.OperationID)
}
// Add the optional keys and values.
for i := 0; i < len(extraKV); i += 2 {
keysAndValues.Add(extraKV[i].(string), extraKV[i+1])
}
return keysAndValues
}
// Topology contains data that all topology messages MAY contain.
type Topology struct {
ID primitive.ObjectID // Driver's unique ID for this topology
Message string // Message associated with the topology
}
// SerializeTopology serializes a Topology message into a slice of keys and
// values that can be passed to a logger.
func SerializeTopology(topo Topology, extraKV ...interface{}) KeyValues {
keysAndValues := KeyValues{
KeyTopologyID, topo.ID.Hex(),
}
// Add the optional keys and values.
for i := 0; i < len(extraKV); i += 2 {
keysAndValues.Add(extraKV[i].(string), extraKV[i+1])
}
return keysAndValues
}