Conversation
Port the Node agent's mongo hook to the Java driver's synchronous
MongoCollection API (mongodb-driver-sync 3.x, 4.x and 5.x). Each hooked
operation is recorded as a function call on the driver's collection class,
with parameters named the way the Node agent names them (filter, update,
doc, pipeline, ...), and, nested under it, a sql_query event with
database_type "mongodb" whose statement is the operation in shell form
with a normalized argument shape:
db.people.updateOne({"name": ?}, {"$set": {"age": ?}, "$inc": {"visits": ?}})
MongoQueryShape implements the same rules as src/hooks/mongoQuery.ts in
appmap-node, so both agents render the same statement for the same
operation: keys and operators kept in order, leaves replaced with `?`,
arrays collapsed to their distinct element shapes, pipelines kept in
order, name arguments verbatim, and limits on depth, cycles and array
length. Formatting never throws.
The hook has no compile-time dependency on the driver. MongoDocumentConverter
reaches the collection's namespace and codec registry by reflection, turns
Bson filters and updates into documents with the collection's registry,
renders WriteModels the way the Node driver's bulkWrite operations look,
and encodes POJO documents with the collection's codec so their fields are
the shape. Options objects are opaque and render as `?`. A leading
ClientSession and a trailing result Class are recorded as parameters and
left out of the statement. The mongo_operation unique key records only the
outermost operation on a thread, so a wrapper collection that delegates to
the driver is recorded once.
The agent/test/mongo fixture runs JUnit tests against mongo-java-server, an
in-process MongoDB, so CI needs no service. It pins driver 4.11.5 and
mongo-java-server 1.43.0: later server releases need Java 11 or 17, and
driver 5.x refuses the wire protocol version 1.43 speaks. mongo.bats
asserts the statements, parameter names, nesting and exceptions.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LntddoBsqjRDRBepBx7oLZ
This was referenced Sep 17, 2026
Draft
MONGODB_URI points the tests at an external server instead of the in-process mongo-java-server, and -PmongoDriverVersion selects the driver. The session overloads are exercised only against a real server, since mongo-java-server does not support sessions. Run against MongoDB 8.0.4 with drivers 4.11.5 and 5.6.1: all tests pass, and the statements match the in-process run. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LntddoBsqjRDRBepBx7oLZ
evlawler
marked this pull request as ready for review
September 17, 2026 16:16
Author
|
Back to draft. The discussion on getappmap/appmap-node#239 concluded that recording Mongo operations as Generated by Claude Code |
evlawler
marked this pull request as draft
September 17, 2026 16:26
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Java agent has no MongoDB support. This ports the Node agent's mongo hook to the driver's synchronous
MongoCollectionAPI (mongodb-driver-sync 3.x, 4.x and 5.x) and, as in the Node change, records each operation as a query-style event so that Mongo lands in the same digests and diffs as SQL.What is recorded
For every hooked
MongoCollectionmethod, two events:filter,update,doc,docs,pipeline,replacement,key,indexSpec, ...) rather than with the driver's own names. A leadingClientSessionis a parameter namedsessionand a trailing resultClassisresultClass.sql_queryevent withdatabase_type: "mongodb"whose statement is the normalized shape, for exampledb.people.updateOne({"name": ?}, {"$set": {"age": ?}, "$inc": {"visits": ?}}). A thrownMongoWriteExceptionbecomes an exception on both events.Methods: insertOne, insertMany, bulkWrite, updateOne, updateMany, replaceOne, deleteOne, deleteMany, findOneAndDelete, findOneAndReplace, findOneAndUpdate, find, aggregate, watch, distinct, countDocuments, estimatedDocumentCount, createIndex, createIndexes, dropIndex, dropIndexes, listIndexes, renameCollection, drop. That is the Node list, minus the methods the Java driver does not have (
findOne,options,isCapped,indexes,indexExists,indexInformation,count).The shape rules
MongoQueryShapeimplements the same rules assrc/hooks/mongoQuery.tsin appmap-node, and its unit tests assert the same strings: keys and operators kept in order, leaves replaced by?, arrays collapsed to distinct element shapes, pipelines kept in order, name arguments verbatim,db.getCollection("...")for non-identifier names, and limits on depth, cycles and array length. Formatting never throws.Where Java differs from Node
MongoDocumentConverterreaches the collection's namespace and codec registry, and converts values, by reflection:Bsonfilters and updates throughtoBsonDocumentwith the collection's registry (falling back to the no-argument overload on bson 4.2+),WriteModels into the shape Node'sbulkWriteoperations have ({"insertOne": {"document": ...}}),IndexModels into{"key": ...}, and aMongoNamespaceinto its full name. Any failure degrades that value to?.Bsonor aMap(a POJO, a record, a Kotlin data class) is encoded with the collection's codec registry, the way the driver will encode it, soinsertOne(new Person("grace", 35))isdb.people.insertOne({"age": ?, "name": ?}). Node renders class instances as?.UpdateOptions,IndexOptions, ...) are opaque and render as?. Node renders the keys of its options document.mongo_operationunique key. A wrapper collection that delegates to the driver's implementation is recorded once.Test
MongoQueryShapeTest(16 tests) andMongoOperationTest(4 tests, covering the session and result class overloads with a stand-inClientSessioninterface) in the agent's unit suite.agent/test/mongo: a Gradle fixture with JUnit tests. By default they run against mongo-java-server, an in-process MongoDB, so CI needs no service.mongo.batsasserts the exact statements, the parameter names, the nesting, the exception on a duplicate insert, POJO encoding and a non-identifier collection name. It is picked up bybin/test_runlike the other suites. All six bats tests pass locally on Java 21.MONGODB_URI=... ../gradlew test -PmongoDriverVersion=...), with driver 4.11.5 and with driver 5.6.1. All pass with both drivers, the statements are identical to the in-process run, and the session test, which only runs against a real server, recordssessionas a parameter and leaves it out of the statement. Pipeline updates, which the in-process server rejects, succeed there and record the same statement../gradlew :agent:checkpasses except for three tests that fail identically on master in this environment (GitUtilTestandAppMapSerializerTestreject the globalgpg.format=sshgit setting,AppMapConfigTest.loadBadDirectoryruns as root).Not covered
DBCollectionAPI, the reactive streams driver, and the Atlas Search index methods.Companion changes
normalizeSQLleavesdatabase_type: "mongodb"alone. Without it the digest showsdb.people.updateOne({?: ?}, {?.Written by Claude in a Claude Code session for Elizabeth Lawler. The commit carries Claude as author.
🤖 Generated with Claude Code
https://claude.ai/code/session_01LntddoBsqjRDRBepBx7oLZ