-
Notifications
You must be signed in to change notification settings - Fork 892
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GODRIVER-2572 Add log messages to Server selection spec #1325
Conversation
@@ -528,38 +549,40 @@ func setClientOptionsFromURIOptions(clientOpts *options.ClientOptions, uriOpts b | |||
var wcSet bool | |||
|
|||
for key, value := range uriOpts { | |||
switch key { | |||
switch strings.ToLower(key) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest using case insensitive matching. The motivation for this is that the "failCommand" specifications indicate that the application name field in spec tests should be "appName". However, there doesn't seem to be consistency in the unified spec tests, often "appname" is used, especially in logging. This update will ensure more consistent behavior.
|
||
// String returns the JSON string representation of the serverSelectorInfo. | ||
func (sss serverSelectorInfo) String() string { | ||
bytes, _ := json.Marshal(sss) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm concerned that the nested JSON created here will be difficult to use when output by a structured logger. Is there another format we can use to combine multiple points of info that works better when nested in JSON? Or maybe only produce JSON when the output is unstructured?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate on what you mean by this: "difficult to use when output by a structured logger" ? The output is the type of selector, associated data, and the child selectors (which is only relevant in the composite case). Here is an example:
{
"Type": "compositeSelector",
"Selectors": [
{
"Type": "writeSelector"
},
{
"Type": "latencySelector"
}
]
}
We could omit child selectors. I would argue that, in the context of logging, more information is better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern is actually that the server selector information is a string containing escaped JSON, rather than a JSON object. Consider the example:
{
"message": "Server selection started",
"operation": "find",
"operationId": 1,
"selector": "{\"Type\":\"compositeSelector\",\"Selectors\":[{\"Type\":\"readPrefSelector\",\"Data\":\"primary\"},{\"Type\":\"latencySelector\"}]}",
"timestamp": 1692071928112600000,
"topologyDescription": "Type: Unknown, Servers: [{ Addr: localhost:27017, Type: Unknown, State: Connected, Average RTT: 0s, Min RTT: 0s }, { Addr: localhost:27018, Type: Unknown, State: Connected, Average RTT: 0s, Min RTT: 0s }, { Addr: localhost:27019, Type: Unknown, State: Connected, Average RTT: 0s, Min RTT: 0s }, ]"
}
That selector information would be more usable and readable as a JSON object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The specifications require this field to be a string. This representation seems reasonable to me. However, if you want to unescape the string we can build this data directly, similar to what we do with the Server.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the spec requires it to be a string, the escaped JSON seems like a reasonable solution.
if startedInfo.cmdName != op.Name { | ||
op.Name = startedInfo.cmdName | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way we can prevent this inconsistency from ever happening? Does the command name ever depend on server info, or is it constant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICT command name is constant and is sourced from the command document when creating a wire message. Technically, these two values should never differ. However, one is sourced from the command function and the other from a field on the operation struct. Since their source differs, it is seems best to make this check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good.
observedEvents map[monitoringEventType]struct{} | ||
storedEvents map[monitoringEventType][]string | ||
eventsCount map[monitoringEventType]int32 | ||
serverDescriptionChangedEventsCount map[serverDescriptionChangedEvent]int32 | ||
|
||
eventsCountLock sync.RWMutex | ||
eventsCountLock sync.RWMutex | ||
serverDescriptionChangedEventsCountLock sync.RWMutex |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use sync.Map
for any of these to simplify the locking logic?
There also seems to be significant overlap in the recorded data. Is it possible to store all of the observed events and then calculate the required counts and other stats on-demand?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation for sync.Map states that it's intended use includes the following:
when the entry for a given key is only ever written once but read many times, as in caches that only grow.
This is not the case for any of these observation sets, as like-keys are written to as many times as an event being measured might occur.
API Change Report./x/mongo/drivercompatible changesOperation.Name: added |
|
||
// String returns the JSON string representation of the serverSelectorInfo. | ||
func (sss serverSelectorInfo) String() string { | ||
bytes, _ := json.Marshal(sss) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern is actually that the server selector information is a string containing escaped JSON, rather than a JSON object. Consider the example:
{
"message": "Server selection started",
"operation": "find",
"operationId": 1,
"selector": "{\"Type\":\"compositeSelector\",\"Selectors\":[{\"Type\":\"readPrefSelector\",\"Data\":\"primary\"},{\"Type\":\"latencySelector\"}]}",
"timestamp": 1692071928112600000,
"topologyDescription": "Type: Unknown, Servers: [{ Addr: localhost:27017, Type: Unknown, State: Connected, Average RTT: 0s, Min RTT: 0s }, { Addr: localhost:27018, Type: Unknown, State: Connected, Average RTT: 0s, Min RTT: 0s }, { Addr: localhost:27019, Type: Unknown, State: Connected, Average RTT: 0s, Min RTT: 0s }, ]"
}
That selector information would be more usable and readable as a JSON object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good 👍
|
||
// String returns the JSON string representation of the serverSelectorInfo. | ||
func (sss serverSelectorInfo) String() string { | ||
bytes, _ := json.Marshal(sss) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the spec requires it to be a string, the escaped JSON seems like a reasonable solution.
if startedInfo.cmdName != op.Name { | ||
op.Name = startedInfo.cmdName | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good.
GODRIVER-2572
Summary
Define structured log messages for server selection.
Add an explicit test to ensure that no extra server selection events are observed for session support in accordance with DRIVERS-2530.
This PR implements changes required as part of GODRIVER-2466 , specifically recording type-specific data for the expectedSdamEvent, referenced here.
Background & Motivation