How to Enable and Use Cypher Query Debugging in neomodel
Enable Cypher query debugging in neomodel by setting the NEOMODEL_CYPHER_DEBUG environment variable to true or programmatically setting config.CYPHER_DEBUG = True, then configure Python's logging system to output DEBUG level messages.
The neomodel library (from the neo4j-contrib/neomodel repository) provides a built-in mechanism for logging every Cypher query sent to Neo4j, including execution parameters and timing data. This Cypher query debugging feature is essential for performance optimization and troubleshooting database interactions in both synchronous and asynchronous applications.
Understanding the CYPHER_DEBUG Configuration Flag
The debugging capability is controlled through a centralized configuration system defined in neomodel/config.py. The flag is stored as a boolean field named cypher_debug within the NeomodelConfig dataclass, which automatically maps to the environment variable NEOMODEL_CYPHER_DEBUG.
# neomodel/config.py (lines 137-142)
cypher_debug: bool = field(
default=False,
metadata={
"env_var": "NEOMODEL_CYPHER_DEBUG",
"description": "Enable Cypher debug logging",
},
)
For backward compatibility, neomodel exposes this setting as a module-level property CYPHER_DEBUG on the config module. Accessing config.CYPHER_DEBUG invokes a getter that retrieves the value from the global configuration instance, while assigning to it updates the underlying cypher_debug field.
# neomodel/config.py (lines 89-95)
@property
def CYPHER_DEBUG(self) -> bool:
return _get_attr("cypher_debug")
How Query Logging Works Under the Hood
When enabled, the database drivers in neomodel/sync_/database.py and neomodel/async_/database.py intercept every Cypher execution to record timing and parameter data. After a query completes, the code calculates the elapsed time (tte) and checks two conditions before emitting a log entry:
- The
NEOMODEL_CYPHER_DEBUGenvironment variable (orconfig.CYPHER_DEBUG) evaluates toTrue. - The elapsed time exceeds the slow-query threshold defined by
NEOMODEL_SLOW_QUERIES(defaulting to 0 seconds).
If both conditions are satisfied, the driver calls logger.debug() with a formatted string containing the raw Cypher query, the parameters dictionary, and the execution time.
# neomodel/sync_/database.py (lines 38-48)
if os.environ.get("NEOMODEL_CYPHER_DEBUG", False) and tte > float(
os.environ.get("NEOMODEL_SLOW_QUERIES", 0)
):
logger.debug(
"query: " + query + "\nparams: " + repr(params) + f"\ntook: {tte:.2g}s\n"
)
The asynchronous implementation in neomodel/async_/database.py (lines 46-56) contains identical logic, ensuring consistent debugging behavior across both sync and async database operations.
The logger instance is created at module import time using Python's standard logging module:
# neomodel/sync_/database.py
logger = logging.getLogger(__name__)
This design allows you to control debug output destinations—whether stdout, stderr, or a file—by configuring Python's logging handlers and levels rather than modifying neomodel's internal behavior.
Enabling Cypher Query Debugging
You can activate debugging through environment variables before application startup or programmatically at runtime. Both methods ultimately toggle the same underlying configuration flag.
Method 1: Environment Variables
Set NEOMODEL_CYPHER_DEBUG to true before launching your Python process. To log every query regardless of execution time, set NEOMODEL_SLOW_QUERIES to 0.
export NEOMODEL_CYPHER_DEBUG=true
export NEOMODEL_SLOW_QUERIES=0
python my_application.py
Setting NEOMODEL_SLOW_QUERIES to a positive number (e.g., 0.5) filters the output to show only queries exceeding that duration in seconds, which is useful for identifying performance bottlenecks without cluttering logs with fast operations.
Method 2: Runtime Configuration
Import the configuration module and toggle the flag programmatically. This approach is useful when you need to enable debugging conditionally based on application state.
from neomodel import config
import logging
# Configure Python logging to capture DEBUG messages
logging.basicConfig(level=logging.DEBUG)
# Enable Cypher query debugging at runtime
config.CYPHER_DEBUG = True
# Optional: Set slow query threshold (seconds)
config.slow_queries = 0.0 # Log all queries
# config.slow_queries = 1.0 # Log only queries taking > 1 second
# Run your neomodel code as usual
# e.g., Person.create(name="Alice")
Note that config.CYPHER_DEBUG is a property that maps to the underlying cypher_debug field in the global configuration instance retrieved via get_config().
Configuring Python Logging
Since neomodel uses Python's standard logging module, you must configure a handler to see the debug output. Without this step, the debug messages are generated but suppressed by default logging settings.
import logging
# Option 1: Basic configuration to stdout
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Option 2: Configure specifically for neomodel
logger = logging.getLogger("neomodel")
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
logger.addHandler(handler)
Filtering Slow Queries with NEOMODEL_SLOW_QUERIES
The NEOMODEL_SLOW_QUERIES environment variable (and its programmatic equivalent config.slow_queries) acts as a duration threshold filter. When set to a value greater than zero, the debug logging logic in neomodel/sync_/database.py and neomodel/async_/database.py compares the elapsed execution time (tte) against this threshold before emitting the log entry.
This mechanism allows you to isolate performance issues by logging only queries that exceed a specific execution time, reducing noise in high-throughput applications while capturing expensive operations for optimization analysis.
Summary
- Cypher query debugging in neomodel is controlled by the
CYPHER_DEBUGconfiguration flag, which maps to theNEOMODEL_CYPHER_DEBUGenvironment variable. - The logging logic resides in
neomodel/sync_/database.pyandneomodel/async_/database.py, where the driver emits debug messages containing the raw Cypher string, parameters, and execution time. - Use
NEOMODEL_SLOW_QUERIESto filter output to queries exceeding a specific duration threshold. - Configure Python's standard
loggingmodule to captureDEBUGlevel messages from theneomodelnamespace to view the output.
Frequently Asked Questions
How do I disable Cypher query debugging after enabling it?
Set config.CYPHER_DEBUG = False in your code, or set the environment variable NEOMODEL_CYPHER_DEBUG to false before restarting your application. Since the configuration is checked at query execution time, changes take effect immediately for subsequent database operations.
Does Cypher query debugging work with async neomodel operations?
Yes. The asynchronous driver in neomodel/async_/database.py implements identical debug logging logic to the synchronous driver. When CYPHER_DEBUG is enabled, both sync and async queries emit debug messages through the standard Python logging system.
Where does the debug output go by default?
By default, debug output is handled by Python's standard logging module using the logger named neomodel.sync_.database or neomodel.async_.database. If you have not configured logging, Python's default configuration typically suppresses DEBUG messages. You must explicitly configure logging.basicConfig(level=logging.DEBUG) or add a handler to see the output in stdout or a file.
Can I filter to show only slow queries?
Yes. Set the NEOMODEL_SLOW_QUERIES environment variable (or config.slow_queries programmatically) to a positive number representing seconds. The debug logger will only emit messages for queries whose execution time exceeds this threshold, allowing you to focus on performance bottlenecks without logging fast, routine operations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →