Skip to content
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

Merged
merged 27 commits into from Jan 19, 2024

Conversation

aditi-khare-mongoDB
Copy link
Contributor

@aditi-khare-mongoDB aditi-khare-mongoDB commented Dec 20, 2023

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:

  • Command logging is enabled separate from command monitoring, and the command logging messages contain additional fields than command monitoring, resulting in the need for the additional emitAndLogCommand method.
  • More context can be found within the kickoff.
  • through inspection of the spec runner, failureIsRedacted is already supported
Is 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

  • Ran npm run check:lint script
  • Self-review completed using the steps outlined here
  • PR title follows the correct format: type(NODE-xxxx)[!]: description
    • Example: feat(NODE-1234)!: rewriting everything in coffeescript
  • Changes are covered by tests
  • New TODOs have a related JIRA ticket

@aditi-khare-mongoDB aditi-khare-mongoDB changed the title Node 4686/clam logging with server connectionid feat(NODE-4686): Add log messages to CLAM spec - final Dec 20, 2023
@aditi-khare-mongoDB aditi-khare-mongoDB marked this pull request as ready for review December 20, 2023 21:05
@aditi-khare-mongoDB aditi-khare-mongoDB changed the title feat(NODE-4686): Add log messages to CLAM spec - final feat(NODE-4686): Add log messages to CLAM spec Dec 20, 2023
@aditi-khare-mongoDB aditi-khare-mongoDB force-pushed the NODE-4686/CLAM-logging-with-serverConnectionid branch from 2a2c26d to b60f216 Compare December 21, 2023 15:18
Copy link
Member

@durran durran left a 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?

@durran durran self-assigned this Dec 21, 2023
@durran durran added the Primary Review In Review with primary reviewer, not yet ready for team's eyes label Dec 21, 2023
@aditi-khare-mongoDB aditi-khare-mongoDB force-pushed the NODE-4686/CLAM-logging-with-serverConnectionid branch from cbf0f92 to f61c6c3 Compare December 21, 2023 18:37
@aditi-khare-mongoDB aditi-khare-mongoDB force-pushed the NODE-4686/CLAM-logging-with-serverConnectionid branch from 1e60e12 to 422c6a9 Compare December 21, 2023 18:49
@aditi-khare-mongoDB
Copy link
Contributor Author

@durran rebase is done, TIA!

Copy link
Member

@durran durran left a 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.

src/cmap/connection.ts Outdated Show resolved Hide resolved
src/cmap/connection.ts Outdated Show resolved Hide resolved
src/cmap/connection.ts Outdated Show resolved Hide resolved
src/mongo_logger.ts Show resolved Hide resolved
src/mongo_types.ts Outdated Show resolved Hide resolved
@aditi-khare-mongoDB
Copy link
Contributor Author

Added in the failure field to the unit tests

Copy link
Member

@durran durran left a 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.

@aditi-khare-mongoDB
Copy link
Contributor Author

I had a syntax error in emitAndLogCommand that made the output invalid, is fixed now.

Copy link
Member

@durran durran left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/cmap/message_stream.ts Outdated Show resolved Hide resolved
src/mongo_types.ts Show resolved Hide resolved
package-lock.json Outdated Show resolved Hide resolved
@@ -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;
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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?

Copy link
Contributor

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 the component property.
  • we have a generic emitAndLog() method that uses the component 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 { ...} 

Copy link
Contributor Author

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 = '';
Copy link
Contributor

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--;).

Copy link
Contributor Author

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.

nbbeeken
nbbeeken previously approved these changes Jan 17, 2024
* - mongodb handshake (saslStart, saslContinue), includes authentication
* Once connection is established, command logging can log events (if enabled)
*/
public established: boolean;
Copy link
Contributor

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?

Copy link
Contributor

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

Copy link
Contributor Author

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

Copy link
Contributor

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))
}

Copy link
Contributor Author

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.

Copy link
Contributor

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).

Copy link
Contributor Author

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.

@aditi-khare-mongoDB aditi-khare-mongoDB force-pushed the NODE-4686/CLAM-logging-with-serverConnectionid branch from 517a826 to 7892601 Compare January 18, 2024 15:34
@aditi-khare-mongoDB aditi-khare-mongoDB self-assigned this Jan 18, 2024
@durran durran merged commit e3bfa30 into main Jan 19, 2024
21 of 27 checks passed
@durran durran deleted the NODE-4686/CLAM-logging-with-serverConnectionid branch January 19, 2024 14:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Team Review Needs review from team
Projects
None yet
6 participants