Use
A practical guide to ApplicationTracing: how to create the tracer, record events, control what shows up in the console and where records are saved.
On this page
ApplicationTracing is the entry point to BetterAI’s logging system. This page covers day-to-day use; the full reference for each class is in Tracing Core, Logger Engine and Payload Builder.
#Create the tracer
Across the platform’s code, each module creates its tracer once, at the top of the file, and reuses it in every function:
from src.tracing.tracing_core import ApplicationTracing
tracer = ApplicationTracing(
flag="DocumentParse", # logger name and database collection name
file_name="document_parse.py", # shows up in every record as file=
log_file_name="parse", # logs/parse.log file, when save_logs is on
)flag: identifies where the records come from. It becomes the logger name in the console and the collection name when the record is saved to the database. Default:"ApplicationTracing".file_name: name of the source file, appended to every message.log_file_name: name of the.logfile inlogs/. Default:"app".log_id: identifier attached to every record of the instance. If omitted, it is generated from the current time, in the formlog_1791458846159946500JItJ. Pass a fixed value to correlate records across instances.
#Record events
The five levels share the same signature: func_name, message and an optional metadata dictionary.
def run(job_id: str):
tracer.INFO(func_name="run", message=f"Processing job {job_id}")
try:
...
except Exception as exc:
# Structured data goes in metadata, not in the message text
tracer.ERROR(
func_name="run",
message="Failed to extract content",
metadata={"job_id": job_id, "error": str(exc)},
)
raise| Method | When to use it | Examples |
|---|---|---|
INFO | Normal application flow. | A process starting, an operation completing successfully. |
DEBUG | Detailed diagnostics, useful during development. | Variable values, function inputs and outputs. |
WARNING | An unexpected situation that does not stop execution. | Deprecated usage, fallback logic, missing optional data. |
ERROR | An operation failed and affects expected functionality. | A failed API call, a caught exception. |
CRITICAL | A severe error that can bring the application down. | A critical dependency unavailable, risk of data corruption. |
#What shows up in the console
Each record becomes one line on stderr, with its parts separated by |: time, level, flag, function, message, metadata, file and log_id.
2026-10-08 08:27:26,159 | ERROR | DocumentParse | run() | Failed to extract content | file=document_parse.py | log_id=log_1791458846159946500JItJBy default, only ERROR and CRITICAL show up. With show_info_logs=False (the default), the console drops INFO, DEBUG and WARNING too. Turn on show_info_logs to see every level.
Metadata only makes it into the line with show_metadata=True; without it, metadata is left out even on an ERROR:
2026-10-08 08:27:26,159 | INFO | DocumentParse | run() | Completed processing | metadata={'job_id': 'job_42'} | file=document_parse.py | log_id=log_1234With format_metadata=True, metadata is printed as indented JSON over several lines instead of a one-line dictionary.
#Save the records
#To a file
With save_logs=True, each record is also written to logs/<log_file_name>.log. The logs/ folder is created in the directory the process was started from. The file receives every level, regardless of show_info_logs, and the text is the same line as in the console, without colors.
#To the NoSQL database
With save_mongo=True, each record is also sent to the DocumentStore, in the application_tracings database, in a collection named after the flag. NOSQL_BACKEND picks the backend:
mongo: writes to MongoDB.local(default): writes JSON todata/application_tracings/<flag>.json.
The saved document carries the full metadata, even with show_metadata=False:
{
"log_id": "log_1234",
"level": "ERROR",
"flag": "DocumentParse",
"func_name": "run",
"message": "Failed to extract content",
"metadata": {"job_id": "job_42"},
"file_name": "document_parse.py",
"time": "2026-10-08 08:27:26,159"
}The local backend adds the _id and _created_at fields.
#Configure through environment variables
The display and saving options can also come from the .env, without changing the code:
| Variable | Parameter |
|---|---|
SHOW_INFO_LOGS | show_info_logs |
SHOW_METADATA | show_metadata |
SAVE_LOGS | save_logs |
SAVE_MONGO | save_mongo |
FORMAT_METADATA | format_metadata |
NOSQL_BACKEND | Backend for save_mongo: mongo or local (default). |
When the same option is set in more than one place, the first one in this list wins:
- The argument passed to the log call, for that call only.
- A
Trueargument in the constructor: it ignores the environment variable. - The environment variable, when the constructor received
False(the default). False, if nothing was set.
The SHOW_*, SAVE_* and FORMAT_METADATA variables are read once, when the tracer is created: changing the environment afterwards does not affect an existing tracer. NOSQL_BACKEND is read on every save.
Only true and false. The accepted values are true and false, case-insensitive. Any other value, such as 1 or yes, raises KeyError when the tracer is created.
#Override in a single call
The log methods accept show_info_logs, show_metadata and save_logs, which apply to that call only:
# Show this INFO even with show_info_logs=False on the instance
tracer.INFO(func_name="run", message="Checkpoint", show_info_logs=True)
# Write only this record to the file, with the metadata in the line
tracer.ERROR(
func_name="process_payment",
message="Payment failed",
metadata={"user_id": 123},
save_logs=True,
show_metadata=True,
)save_mongo does not work per call. The parameter is in the methods’ signature, but saving to the database always follows the instance value: save_mongo=True on a call does not save, and save_mongo=False does not prevent saving.
#Try it
The src/tracing/tracing_test.py file emits one record per level. Run it from the project root:
python -m src.tracing.tracing_testWith the default configuration, only the ERROR and CRITICAL records show up. Set SHOW_INFO_LOGS=true in the .env to see all five.
#See also
Source: src/tracing/tracing_test.py