-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
feat(NODE-4686): Add log messages to CLAM #3955
Conversation
2a2c26d
to
b60f216
Compare
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 rebase this quickly against main first so we have an accurate diff against the new connection class changes?
cbf0f92
to
f61c6c3
Compare
1e60e12
to
422c6a9
Compare
@durran rebase is done, TIA! |
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.
Note that the unit tests are failing because the test command failed event has no failure
on it.
Added in the failure field to the unit tests |
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 like we have the same failures with the extra pings here now on this PR. An extra 2 events are getting sent and the unified tests are failing.
I had a syntax error in emitAndLogCommand that made the output invalid, is fixed now. |
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.
There are still failures that need to be addressed both in unit tests:
And in the integration tests:
test/integration/command-logging-and-monitoring/command_logging_and_monitoring.prose.test.ts
Outdated
Show resolved
Hide resolved
test/integration/command-logging-and-monitoring/command_logging_and_monitoring.prose.test.ts
Show resolved
Hide resolved
test/integration/command-logging-and-monitoring/command_logging_and_monitoring.prose.test.ts
Outdated
Show resolved
Hide resolved
src/cmap/connection.ts
Outdated
@@ -174,6 +177,10 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> { | |||
private messageStream: Readable; | |||
private socketWrite: (buffer: Uint8Array) => Promise<void>; | |||
private clusterTime: Document | null = null; | |||
/** @internal */ | |||
override component = MongoLoggableComponent.COMMAND; |
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.
This is an interesting idea - I see it's used in TypedEventEmitter to know which logging component to use.
Will there ever be a case where emitAndLogCommand
will be used to log for a component that is not MongoLoggableComponent.COMMAND
?
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.
No, there won't. The extra this.component
check should ensure that an emitAndLog
or variant function (emitAndLogCommand, emitAndLogHeartbeat
) is not called from any class for which the logging component is not defined already.
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 can add in an extra check such as: this.component === MongoLoggableComponent.COMMAND
, remove the this.component
check for emitAndLogCommand
, or keep it the same. What do you think?
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.
It's strange to me that we have a dedicated method for logging commands, but to use it we also need to set the component on the class. I would expect that either:
- we only have
emitAndLogCommand()
, and not thecomponent
property. - we have a generic
emitAndLog()
method that uses thecomponent
property and no specialized methods on the TypedEventEmitter
No, there won't. The extra this.component check should ensure that an emitAndLog or variant function (emitAndLogCommand, emitAndLogHeartbeat) is not called from any class for which the logging component is not defined already.
If we want to prevent the emitAndLog functions from being called, maybe we could use inheritance for this? that way we could only define the log methods where they can be used
class TypedEventEmitter {
private logger: MongoLogger;
}
class CommandEventEmitter extends TypedEventEmitter {
emitAndLogCommand(..) {}
}
class HeartbeatEventEmitter extends TypedEventEmitter {
emitAndLogHeartbeat(..) {}
}
class Connection extends CommandEventEmitter { ...}
class Monitor extends HeartbeatEventEmitter { ...}
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.
That's true. For the sake of this PR, I'll just hardcode in the component in emitAndLogCommand
as MongoLoggableComponent.COMMAND.
Since I realize emitAndLogCommand
already implies that the command component is being utilized.
@@ -383,7 +413,8 @@ export function stringifyWithMaxLen( | |||
maxDocumentLength: number, | |||
options: EJSONOptions = {} | |||
): string { | |||
let strToTruncate: string; | |||
let strToTruncate = ''; |
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.
Non-blocking and definitely only tangentially related: the .slice()
call below can end up truncating strToTruncate
in the middle of a character. That won't happen a lot if the string mostly just contains ASCII data, but since this is a very low-level generic utility, it might be worth accounting for that case (e.g. if (strToTruncate.length > maxDocumentLength && strToTruncate.charCodeAt(maxDocumentLength-1) !== strToTruncate.codePointAt(maxDocumentLength-1)) maxDocumentLength--;
).
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.
This is something we will solve / take a further look at in NODE-5839.
* - mongodb handshake (saslStart, saslContinue), includes authentication | ||
* Once connection is established, command logging can log events (if enabled) | ||
*/ | ||
public established: boolean; |
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.
What is the expected behavior with command logging when we re-authenticate?
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.
Reauthentication will send commands we don't want to log I think. We may either need to
- add logic that more specifically determines whether or not a command should be logged
- set
established
to false when reauthenticating and then set it back to true after a successful reauthentication
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 agree, pinged you on slack for more info on reauth
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.
Sorry I didn't notice this earlier ( I didn't actually check ) but instead of modifying established
when we reauthenticate, could we just check the context.reauthenticating
field?
one idea is a getter on the connection class (or we could just inline it):
get shouldEmitAndLog(): boolean {
return this.monitorCommands ||
(this.established && !this.context.reauthenticating && this.mongoLogger?.willLog(SeverityLevel.DEBUG, MongoLoggableComponent.COMMAND))
}
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.
Isn't it more accurate to edit established as well, though? Since during authentication, the connection is not established.
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 understood established to mean that the connection had been established, not that it was "ready"/currently established. What I would like to avoid is duplicate data that might get out of sync. If established=false can also represent a connection reauthenticating, then it's possible for us to end up in a scenario context.reauthenticating=true with established=false (or vice versa) - which is a poorly defined state for the driver.
One way to avoid this is to define established as whether or not the connection was initially established and rely on context.reauthenticating (my suggestion).
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.
That sounds good. I've removed the extra auth changes to conn.established
and am using this.authContext?.authenticating
in the new getter shouldEmitAndLogCommand
instead.
8743dcb
to
cbb5df6
Compare
517a826
to
7892601
Compare
Description
Add logging to CLAM events, un-skip + add support for CLAM logging spec tests, and add in prose tests.
What is changing?
CLAM logging messages will be enabled when loggingClientOptions for component
MongoLoggableComponent.COMMAND >= SeverityLevel.DEBUG
.NOTE:
emitAndLogCommand
method.failureIsRedacted
is already supportedIs there new documentation needed for these changes?
Not until logging is released (NODE-5762)
What is the motivation for this change?
To allow users to see CLAM events through logging.
Double check the following
npm run check:lint
scripttype(NODE-xxxx)[!]: description
feat(NODE-1234)!: rewriting everything in coffeescript