hi there
# ask-ai
b
hi there
t
Thanks for reaching out, Jupiter. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Hi — welcome to LiveKit! How can I help you today? • Are you setting up a project, joining a room, troubleshooting a connection, or something else? • If you have an error message, room ID, or project ID, please share it and I’ll help troubleshoot.
b
I have duplicate log when I tried to write to a local file, it seems the reason due to cli.run_app creates a logger also:
Copy code
cli.run_app(
        WorkerOptions(
            entrypoint_fnc=entrypoint,
            agent_name=agent_name,
            prewarm_fnc=AgentEntrypoint.prewarm,
            initialize_process_timeout=float(os.getenv("INITIALIZE_PROCESS_TIMEOUT", 30)),
            job_memory_warn_mb=float(os.getenv("MEMORY_WARN_MB", 2500)),
            job_memory_limit_mb=float(os.getenv("MEMORY_LIMIT_MB", 3000)),
        ),
    )
t
Thanks — I’m sorry you’re seeing duplicate log lines. I’m happy to help troubleshoot. A few quick questions so I can recommend the safest fix: 1. Do you configure logging yourself before calling
cli.run_app
(e.g., create handlers, call
logging.basicConfig
, or add a
FileHandler
)? 2. Which logger/name are you attaching your file handler to (root logger or a named logger)? 3. Are the duplicates written to both console and file, or only file? 4. Which agent/CLI mode are you running (
start
or
dev
) and how do you invoke it (command line flags)? 5. Can you paste the minimal logging setup code you use (the few lines that add handlers or set levels)? Based on your answers I’ll show the minimal change to prevent double-handlers (examples include checking existing handlers before adding, removing duplicate handlers, or configuring logging after
cli.run_app
). Sources: Agent server options | LiveKit docs | Simple Call Answering Agent | LiveKit docs
b
this is my setup_logging:
Copy code
_logging_configured = False  
  
def setup_logging():  
    """Configure file logging without duplicates"""  
    global _logging_configured  
      
    if _logging_configured:  
        return  
      
    root = logging.getLogger()  
      
    # Check if we already have a file handler for livekit.log  
    has_file_handler = any(  
        isinstance(h, logging.FileHandler) and h.baseFilename.endswith('livekit.log')  
        for h in root.handlers  
    )  
      
    if not has_file_handler:  
        # Remove only file handlers pointing to livekit.log to prevent duplicates  
        for handler in root.handlers[:]:  
            if isinstance(handler, logging.FileHandler) and handler.baseFilename.endswith('livekit.log'):  
                root.removeHandler(handler)  
          
        # Add file handler  
        file_handler = logging.FileHandler('livekit.log')  
        file_handler.setLevel(<http://logging.INFO|logging.INFO>)  
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')  
        file_handler.setFormatter(formatter)  
          
        root.addHandler(file_handler)  
      
    _logging_configured = True 

setup_logging()
t
Thanks — this is helpful. You’re right to suspect duplicate handlers. Based on your
setup_logging
and what you described, here are concise, safe next steps to eliminate duplicates and confirm whether
cli.run_app
is adding handlers. 1) Quick checks (run before and after calling
cli.run_app
) • Print current handlers to see what’s being added:
Copy code
import logging
root = logging.getLogger()
print([type(h).__name__ + ":" + getattr(h, "baseFilename", "stream") for h in root.handlers])
If you see another
FileHandler
or handlers added after
cli.run_app
, that confirms duplication. 2) Low-risk fixes you can try • Configure logging after
cli.run_app
returns (so your file handler is only added once). • Or, remove duplicate handlers just before adding yours:
Copy code
for handler in root.handlers[:]:
    if isinstance(handler, logging.FileHandler) and handler.baseFilename.endswith('livekit.log'):
        root.removeHandler(handler)
# then add your file handler
Your code already does this removal check — ensure it runs after
cli.run_app
if
cli.run_app
is the one adding handlers. 3) Use a named logger instead of the root logger • Avoid side effects on framework logging by attaching your file handler to a module-specific logger:
Copy code
logger = logging.getLogger("<http://my.app|my.app>")
logger.addHandler(file_handler)
Log via that logger (
<http://logger.info|logger.info>(...)
) and leave framework logs on the root logger. 4) Prevent double propagation (if you use a child logger) • If you attach to a named logger and still see duplicates, disable propagation:
Copy code
logger.propagate = False
5) If you prefer detecting additions automatically • Keep your
_logging_configured
guard but detect new handlers after
cli.run_app
and remove them, or record handler identities before calling
cli.run_app
and remove any new ones that match file targets. If you’d like, tell me: • The handler list output from step 1 (before/after
cli.run_app
), and • Whether you can move your
setup_logging()
call to run after
cli.run_app
returns. I’ll recommend the exact code change once I see that output. Sources: Simple Call Answering Agent | LiveKit docs