Application Tracing

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 .log file in logs/. Default: "app".
    • log_id: identifier attached to every record of the instance. If omitted, it is generated from the current time, in the form log_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
    MethodWhen to use itExamples
    INFONormal application flow.A process starting, an operation completing successfully.
    DEBUGDetailed diagnostics, useful during development.Variable values, function inputs and outputs.
    WARNINGAn unexpected situation that does not stop execution.Deprecated usage, fallback logic, missing optional data.
    ERRORAn operation failed and affects expected functionality.A failed API call, a caught exception.
    CRITICALA 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.

    Console
    2026-10-08 08:27:26,159 | ERROR | DocumentParse | run() | Failed to extract content | file=document_parse.py | log_id=log_1791458846159946500JItJ

    By 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:

    Console
    2026-10-08 08:27:26,159 | INFO | DocumentParse | run() | Completed processing | metadata={'job_id': 'job_42'} | file=document_parse.py | log_id=log_1234

    With 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 to data/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:

    VariableParameter
    SHOW_INFO_LOGSshow_info_logs
    SHOW_METADATAshow_metadata
    SAVE_LOGSsave_logs
    SAVE_MONGOsave_mongo
    FORMAT_METADATAformat_metadata
    NOSQL_BACKENDBackend 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:

    1. The argument passed to the log call, for that call only.
    2. A True argument in the constructor: it ignores the environment variable.
    3. The environment variable, when the constructor received False (the default).
    4. 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_test

    With 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

    Esc
    ↑↓navigate Enteropen