-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Add structured log messages to CMAP. #1114
Conversation
@@ -497,7 +506,24 @@ private void initClient(final BsonDocument entity, final String id, | |||
MongoClientSettings clientSettings = clientSettingsBuilder.build(); | |||
|
|||
if (entity.containsKey("observeLogMessages")) { | |||
putEntity(id + "-logging-interceptor", new TestLoggingInterceptor(clientSettings.getApplicationName()), clientLoggingInterceptors); |
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 change below has been added in accordance with the spec observeLogMessages
The PR implements the spec changes from mongodb/specifications@d268119. As far as I understand, there are some changes in this commits that are either not reflected, or should be reflected differently in the PR:
|
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 have not reviewed DefaultConnectionPool
. Will wait until the new formatting approach is implemented.
driver-core/src/main/com/mongodb/internal/logging/StructuredLogMessage.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/logging/StructuredLogMessage.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/connection/InternalStreamConnection.java
Show resolved
Hide resolved
driver-sync/src/test/functional/com/mongodb/client/unified/TestLoggingInterceptor.java
Outdated
Show resolved
Hide resolved
driver-sync/src/test/functional/com/mongodb/client/unified/TestLoggingInterceptor.java
Outdated
Show resolved
Hide resolved
driver-sync/src/test/functional/com/mongodb/client/unified/TestLoggingInterceptor.java
Outdated
Show resolved
Hide resolved
driver-sync/src/test/functional/com/mongodb/client/unified/TestLoggingInterceptor.java
Outdated
Show resolved
Hide resolved
driver-sync/src/test/functional/com/mongodb/client/unified/ConnectionPoolLoggingTest.java
Outdated
Show resolved
Hide resolved
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 have not reviewed DefaultConnectionPool
. Will wait until the new formatting approach is implemented.
That makes sense. We can create a subfolder for the tests in our driver as in the spec repo The location for this subfolder would be: |
The current naming schema is confusing / does not seem to exist: sometimes we use subfolders, as in
and sometimes we use plain structure with suffixes, as in
So yeah, this PR can use subfolders as they seem much better than suffixes. |
String format = "Command \"{}\" succeeded in {} ms using a connection with driver-generated ID {}" + | ||
"[ and server-generated ID {}] to {}:{}[ with service ID {}]. The requestID is {} and the " + | ||
"operation ID is {}. Command reply: {}]"; | ||
return Stream.of( |
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.
You can see almost all the cases interpolation currently can handle
/** | ||
* <p>This class is not part of the public API and may be removed or changed at any time</p> | ||
*/ | ||
public final class LogMessage { |
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.
GitHub shows changes as if this is a new class, but actually that is renamed StructuredLogMessage class to LogMessage.
The reason for this change is that by design and specification, StructuredLogMessage only allows non-null entry values. However, we also need to preserve null values when interpolating a message to indicate which parts should be omitted.
To capture all entries, both null and non-null, new wrapper class (LogMessage) was introduced that allows to contain all entries with their corresponding values. Additionally, StructuredLogMessage is an inner class of LogMessage, so that LogMessage can be converted to StructuredLogMessage using the toStructuredLogMessage
method, which creates a null-free structured log message.
To handle message interpolation, UnstructuredLogMessage inner class class is introduced as well, which triggers interpolation logic lazily. Our Logger captures LogMessage and internally converts it to either an unstructured or structured log message.
At this time, we only emit unstructured logs to the user.
* @return the interpolated string with the values from the entries collection filled in the placeholders. | ||
* @throws NoSuchElementException – if the iteration has no more elements. | ||
*/ | ||
public String interpolate() { |
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.
@katcharov this is interpolation logic we discussed. You are welcome to review
Since this PR also implements JAVA-4962, let's add it to the PR description. |
I noticed that the |
@@ -473,10 +495,36 @@ private void connectionCreated(final ConnectionPoolListener connectionPoolListen | |||
*/ | |||
private void connectionClosed(final ConnectionPoolListener connectionPoolListener, final ConnectionId connectionId, | |||
final ConnectionClosedEvent.Reason reason) { | |||
ClusterId clusterId = serverId.getClusterId(); | |||
if (STRUCTURED_LOGGER.isRequired(DEBUG, clusterId)) { | |||
String errorReason = "There was a socket exception raised by this connection"; |
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 explicit exception is thrown to provide a comprehensive explanation of the error. However, according to the specification, it is mandatory to supply an error description when the reason for closure is an ERROR. Please refer to the specification available at Spec.
In the getReasonForClosing
method, there is a check if (connection.isClosed())
which returns an ERROR
type. Consequently, a corresponding check was implemented in the getReasonStringForClosing
method to elaborate in more detail on the cause of the connection closure. Therefore, the error message was derived from the getReasonStringForClosing
.
driver-core/src/test/unit/com/mongodb/internal/connection/AbstractConnectionPoolTest.java
Outdated
Show resolved
Hide resolved
driver-sync/src/test/functional/com/mongodb/client/unified/Entities.java
Outdated
Show resolved
Hide resolved
driver-core/src/test/unit/com/mongodb/internal/logging/LogMessageTest.java
Outdated
Show resolved
Hide resolved
driver-core/src/test/unit/com/mongodb/internal/logging/LogMessageTest.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/logging/LogMessage.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/logging/LogMessage.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/logging/StructuredLogger.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/logging/LogMessage.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/connection/DefaultConnectionPool.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/connection/LoggingCommandEventSender.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/connection/LoggingCommandEventSender.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/connection/DefaultConnectionPool.java
Outdated
Show resolved
Hide resolved
Additional tests will be added. Converted to draft |
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'd be great to introduce a new type for message ID constants (a enum appears to be the best choice) instead of using String
literals.
I approved, but static checks need to pass before merging.
driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java
Outdated
Show resolved
Hide resolved
driver-core/src/test/unit/com/mongodb/logging/TestLoggingInterceptor.java
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/connection/LoggingCommandEventSender.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/logging/StructuredLogger.java
Outdated
Show resolved
Hide resolved
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.
LGTM!
This pull request adds changes to logging in accordance with CMAP specification. The purpose of these changes is to introduce structured logging to the connection component, providing a uniform logging format across all drivers.
Additionally, this pull request removes unnecessary logging that is not widely used and therefore not necessary to maintain. This will help to simplify the codebase.
Furthermore, conditional logging statements have been improved for better readability. A special formatting approach has been introduced, allowing the omission of log sentences enclosed in conditionals when the corresponding value is null.
JAVA-4771
JAVA-4962
JAVA-4946