Skip to content

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