Databases¶
SQLAlchemy¶
SQLAlchemy engine instrumentation (sync & async) with statement redaction.
- Hooks before/after_cursor_execute on Engine and AsyncEngine.sync_engine
- Emits DB metrics via Emitter with redacted statements and rowcount
- Redaction replaces string & numeric literals with '?' and trims to max length
instrument_async_engine(async_engine, emitter, *, redact=True, max_len=200)
¶
Attach hooks to an AsyncEngine by instrumenting its sync_engine.
instrument_engine(engine, emitter, *, redact=True, max_len=200)
¶
Attach before/after hooks to a synchronous SQLAlchemy Engine.
Emits DB with fields: query (redacted), dur_ns, rows
redact_statement(sql, *, max_len=200)
¶
Redact string and numeric literals and trim length.
Example
INSERT INTO users (name, age) VALUES ('Alice', 42) -> INSERT INTO users (name, age) VALUES (?, ?)
MongoDB (PyMongo / Motor)¶
MongoDB instrumentation (PyMongo + Motor) via pymongo.monitoring.CommandListener.
Records CommandStarted, CommandSucceeded and CommandFailed events and emits DB_META-like payloads via the provided Emitter.
ProfilisCommandListener
¶
Bases: CommandListener
A CommandListener that emits DB_META items via an Emitter.
Usage
listener = ProfilisCommandListener(emitter, MongoConfig(...)) client = MongoClient(..., event_listeners=[listener]) # sync PyMongo
or for Motor:¶
client = AsyncIOMotorClient(..., event_listeners=[listener]) # async Motor
Neo4j¶
Neo4j instrumentation (sync + async) — wraps Session.run / Tx.run and AsyncSession.run / AsyncTx.run.
Non-invasive: wraps session/transaction instance methods to preserve semantics. Emits metrics via Emitter and enqueues DB_META payloads with counters from summary.
instrument_neo4j_module(module, emitter, config=None)
¶
Optional convenience: instrument factory functions so newly-created sessions are instrumented.
Example
instrument_neo4j_module(neo4j, emitter, cfg) driver = neo4j.GraphDatabase.driver(...) session = driver.session() # session.run will be instrumented
instrument_neo4j_session(session, emitter, config=None)
¶
Wrap the session (or tx) instance so that its run() is instrumented.
Non-invasive: we only wrap methods on the given instance and set a marker
attribute _profilis_wrapped to avoid double-wrapping.
pyodbc¶
pyodbc raw wrapper (execute / executemany)
Non-invasive instrumentation: wrap cursor methods on a per-cursor basis.
instrument_pyodbc_connection(connection, emitter, config)
¶
Instrument a pyodbc connection by wrapping its .cursor() method.
On each .cursor() call we will return a cursor with wrapped execute/executemany. This avoids monkeypatching a module/class globally and is safe for tests/CI.
instrument_pyodbc_cursor(cursor, emitter, config)
¶
Wraps a cursor instance to instrument execute/executemany.
Returns the same cursor object but with wrapped methods (non-invasive).