LOG_LEVEL.
How Logging Works in Cognee
When you import or start Cognee,setup_logging() is called automatically. The first call in a process configures two handlers:
- Console handler — writes colored output to
stderr, filtered byLOG_LEVEL(default:INFO) - File handler — writes plain text to a timestamped
.logfile, filtered by the sameLOG_LEVEL(turn it off withCOGNEE_LOG_FILE=false)
Logging Is Configured Once Per Process
setup_logging() is idempotent. Cognee calls it from four places during a normal server start — importing cognee, importing cognee.api.client, importing the vector embeddings utilities, and server startup — but only the first call does any configuration work. That call installs the console and file handlers, sets up the sys.excepthook, opens the log file, and emits the startup messages. Every later call, including one you write yourself, returns a structlog logger and changes nothing: the handlers, log file, and excepthook from the first call stay in place, and the startup banner is not repeated. Because the first call wins, arguments you pass to a later setup_logging(log_level=...) call are ignored — see Setting the Log Level for the supported way to control verbosity.
The guard is per interpreter. A sub-process starts fresh, configures its own handlers, and appends to the same log file, which is how one file ends up holding output from all of them.
Default log file locations
Default log file locations
The default Running from source (cloned repository):Using the MCP server:
The MCP server uses the same logging setup. The log directory is the same as above, depending on your environment. When a background task is launched, the MCP server returns the full path to the active log file in its response.
logs/ directory is created next to the cognee package directory, one level above it. The exact path depends on how Cognee is installed.Installed via pip (e.g. pip install cognee):Size-Based Rotation
The file handler also caps how large a single startup’s log can grow. Before writing each record it checks the current file size, and once the file has reachedCOGNEE_LOG_MAX_BYTES (default 50 MB) it rolls over: the active file is renamed to <name>.log.1, any existing backups shift up by one, and logging continues in a fresh file under the original name. At most COGNEE_LOG_BACKUP_COUNT backups (default 5) are kept, so on the defaults one startup’s logs occupy roughly 300 MB at the ceiling — one active 50 MB file plus five 50 MB backups.
Rotation and the keep-10 cleanup are independent mechanisms. Rotation bounds the size of one startup’s log; the keep-10 cleanup prunes old startups’ files. The cleanup only matches files ending in .log, so numbered rotation backups (.log.1, .log.2, …) are not counted by it and are not removed when their originating startup’s .log file is pruned. If you run with a large COGNEE_LOG_BACKUP_COUNT and restart often, prune the log directory yourself.
Controlling Logging
Environment Variables
COGNEE_LOGS_DIR— Absolute path to a custom log directory. Cognee creates it if it does not exist. Must be an absolute path — relative paths cause a startup error. Default:logs/next to thecogneepackage.LOG_LEVEL— Log verbosity. One ofDEBUG,INFO,WARNING,ERROR,CRITICAL. Default:INFO. Applies to both the console and the log file.COGNEE_LOG_FILE— Set tofalse(or0/no) to disable file logging entirely. Default:true.COGNEE_LOG_MAX_BYTES— Size in bytes at which the active log file is rotated. Default:52428800(50 MB). Set it to0to turn size-based rotation off and let a startup’s log file grow without a cap.COGNEE_LOG_BACKUP_COUNT— How many rotated backups to keep alongside the active file. Default:5. Backups are named<name>.log.1through<name>.log.<count>, oldest last.
Setting the Log Level
LOG_LEVEL is read when logging is configured, which happens on the first setup_logging() call — and import cognee makes that call for you. So the level must be in place before the import:
.env file works too, and takes precedence: Cognee loads .env with override=True at import time, just before configuring logging. If LOG_LEVEL is in your .env, change it there rather than in the shell or in code.
Configuration Examples
Fallback Behavior
If Cognee cannot write toCOGNEE_LOGS_DIR, it falls back to /tmp/cognee_logs. If that also fails, file logging is skipped silently and only console output is produced.
Log Files and Their Content
File Format
Log files use plain text, one entry per line. Timestamps are in UTC:Console Format
The console uses structlog’s colored renderer, written tostderr. Level colors: DEBUG blue, INFO green, WARNING yellow, ERROR and CRITICAL red.
Logged exception tracebacks are rendered without per-frame local variables (show_locals=False). The traceback itself is still shown, but the values of locals in each frame are omitted. This keeps memory bounded when exceptions are logged in the retrieval/search path, where frame locals can hold graph objects carrying embedding vectors and deep node/edge references — rendering those recursively could spike memory to multiple GB and OOM-kill the process.
Cognee also installs a safe sys.excepthook, so uncaught non-KeyboardInterrupt exceptions are logged through structlog before Python’s default traceback is printed. If rich traceback rendering fails, Cognee falls back to plain traceback output.
Exception Details
When an exception is logged, the structured log event includes the exception type inexception_type alongside the exception message. This makes error entries easier to interpret because they show both what failed and the exception class that raised it, for example ValueError.
What to Expect at Startup
Cognee initializes logging once per process, and importing the package logs the following five messages in order:- INFO — The full path to the log file created for this session.
- WARNING — The
Cognee 1.0 changesbanner: the new remember/recall/forget/improve API, session memory on by default, multi-user access control on by default, and agents auto-verified on registration. This is expected and not an error. - INFO —
Logging initialized, with system metadata attached as structured fields: Python version, structlog version, Cognee version, OS, and the database storage path. - INFO — The database storage path again, as a plain-text line.
- INFO — Which
.envfile was loaded:Loaded settings from <path>; its values take precedence over preset environment variables., orNo .env file found; using process environment variables only.when the search found nothing.
.env is resolved and loaded before logging is configured — LOG_LEVEL comes from it — so this line is emitted last even though the load happened first. It is the quickest way to confirm which file a deployment actually picked up; see How .env Is Loaded for the search order.
If the log file path message is missing from the console, file logging may have failed. Check whether the log directory is writable or set COGNEE_LOGS_DIR to a path you control.
The active graph, vector, and relational providers are not part of these messages. Cognee defers that configuration logging to the first actual pipeline call, because importing those configs pulls in heavy dependencies.
When migrations run, the alembic.env logger adds an INFO line of its own — Using database: <url> — with the password masked, so a Postgres connection string reaches the log as postgresql+asyncpg://cognee:***@localhost:5432/cognee_db.
The cognee_version Field
cognee_version is resolved at startup. Cognee first looks for a pyproject.toml one directory above the imported cognee package. If that file is there, its version value is reported with a -local suffix. If it is not, the version comes from the installed distribution metadata (importlib.metadata.version("cognee")) and is reported unchanged. If neither source resolves, the field reads unknown.
So cognee_version=1.6.0-local means the imported cognee package has a pyproject.toml next to it — not that the build is unreleased or modified. Two setups report it:
- A source checkout or editable install, where the repository root holds both
pyproject.tomlandcognee/. The number is whatever that checkout’spyproject.tomldeclares, which does not identify the revision — usegit rev-parse --short HEADin the checkout for that. - The
cognee/cogneeserver image, which setsPYTHONPATH=/appand ships/app/pyproject.tomlalongside/app/cognee. Containers therefore report-localeven when running a released image tag. Thecognee/cognee-mcpimage does not: it installscogneefrom PyPI intosite-packages, so it reports the bare version.
pip install cognee into site-packages has no neighboring pyproject.toml, so it reports the bare version — cognee_version=1.6.0.
To check which build you are running:
File Naming
Each log file is named after the startup timestamp:2025-02-14_15-32-47.log
When that file hits the size cap it is rotated, so a long-running startup leaves numbered backups next to it — 2025-02-14_15-32-47.log.1 is the most recent rotated segment, .log.2 the one before it, and so on.
Troubleshooting
Can't find the log file
Can't find the log file
Run this snippet after importing cognee to get the exact path:
No log file is created
No log file is created
Cognee falls back to console-only logging if the log directory is not writable. This is common in managed environments where
site-packages/ is read-only.Set COGNEE_LOGS_DIR to an absolute path you own:LOG_LEVEL is ignored
LOG_LEVEL is ignored
Logging is configured on the first
setup_logging() call, which import cognee triggers. If you set LOG_LEVEL after that import — or call setup_logging(log_level=...) yourself — the level is already fixed and your change does nothing. Set LOG_LEVEL in your .env file or in the environment before importing Cognee. See Setting the Log Level.Overview
Return to setup configuration overview
Relational Databases
Configure metadata and state storage
Installation
Install Cognee and set up your environment