brief-vase-33757
08/18/2025, 3:33 PMtall-airline-16756
08/18/2025, 3:33 PMtall-airline-16756
08/18/2025, 3:33 PMlog_exceptions
decorator from LiveKit's agents repository. It’s super handy because it works with both synchronous and asynchronous functions, and it’ll log any exceptions along with the function name and a custom message you provide.
Here’s a simple example in Python to get you started:
import logging
from livekit.agents.utils.log import log_exceptions
# Set up your logger
logger = logging.getLogger(__name__)
@log_exceptions(msg="Error in call handling", logger=logger)
async def handle_call(*args, **kwargs):
# Your call handling logic here
try:
# Code that might raise exceptions
except Exception as e:
# You can choose to re-raise the exception after logging if you want
raise
Here’s how you can implement it step-by-step:
• First, import the log_exceptions
decorator from LiveKit’s utility module.
• Next, set up your logger so it sends logs wherever you want—whether that’s a file, a network location, or a logging service.
• Then, just add the @log_exceptions
decorator to your call-handling function. You can also add a custom message and pass your logger instance.
• Finally, wrap your call logic in a try-except block if you want extra control, or simply let the decorator handle exceptions for you automatically.
This way, you’ll have a neat and reliable system to log all exceptions during calls, making debugging and monitoring a whole lot easier. If you have any questions or want to chat more about it, I’m here to help!brief-vase-33757
08/18/2025, 3:34 PMtall-airline-16756
08/18/2025, 3:35 PMsetLogExtension
method from the LiveKit client SDK. It lets you send logs over to Bugsnag while still keeping the usual logging behavior intact.
Here’s a simple example to get you started:
setLogExtension((level, msg, context) => {
// Send logs to Bugsnag
bugsnagClient.notify(new Error(msg), {
severity: getSeverityFromLogLevel(level),
metadata: context
});
// Optionally, keep the default console logs too
console.log(level, msg, context);
}, true);
Here’s what you need to do:
• First, initialize Bugsnag in your app setup with your API key.
• Then, use setLogExtension
to forward logs to Bugsnag. You can also add room-specific info to the logs if you want.
• Adjust the logging detail with setLogLevel
to capture just what you need.
• Make sure to keep environment-specific settings like API keys safe by using environment variables.
This way, you’ll have solid error tracking and logging in Bugsnag, while still having the flexibility to debug and monitor your app easily.brief-vase-33757
08/18/2025, 3:36 PMtall-airline-16756
08/18/2025, 3:37 PMbugsnag({
apiKey: "your-api-key",
});
2. Capture LiveKit Errors:
Just listen for the error
event from LiveKit to grab any errors:
livekit.on('error', (error) => {
// Let Bugsnag know about the error
bugsnag.notify(error, (report) => {
report.context = 'LiveKit Error';
});
});
3. Global Error Handling (React Native):
If you’re working with React Native, setting up a global error handler helps catch those uncaught exceptions:
setJSExceptionHandler((error) => {
bugsnag.notify(error, (report) => {
report.context = 'React Native Error';
});
});
4. Add Error Context:
Adding some extra context can make it easier to figure out where the error came from:
bugsnag.notify(error, (report) => {
report.context = 'LiveKit Error';
// Feel free to add more metadata here if it helps
});
5. Handle Specific Error Types:
LiveKit has some specific error types you might want to handle differently:
livekit.on('error', (error) => {
if (error instanceof ConnectionError) {
bugsnag.notify(error, (report) => {
report.context = 'Connection Error';
});
} else if (error instanceof TrackInvalidError) {
bugsnag.notify(error, (report) => {
report.context = 'Track Invalid Error';
});
}
});
With this setup, you’ll have all your LiveKit and global errors nicely captured and sent to Bugsnag from one easy-to-manage place. If you need a hand setting it up or have any questions, just let me know!
Sources: Events and error handling | LiveKit Docs | example/src/utils/ErrorLogHandler.ts | ErrorEvent | LiveKit Agents | src/room/errors.tsbrief-vase-33757
08/18/2025, 3:44 PMtall-airline-16756
08/18/2025, 3:44 PMAgent
class, and its main job is to call the LLM to understand the chat context and come up with responses.
For instance, if you peek into livekit-agents/livekit/agents/voice/agent.py
, you’ll see the llm_node
method set up as a pipeline node. What’s cool is that subclasses can override this to tweak how the LLM behaves. Also, in the RetrievalAgent
class (like in livekit-agents/examples/voice_agents/llamaindex-rag/retrieval.py
), it connects with external knowledge bases to bring in extra info.
This method is really at the heart of how the LLM works here, giving developers the flexibility to customize how the agent processes chat and generates responses. Hope that helps clear things up!
Sources: examples/voice_agents/structured_output.pybrief-vase-33757
08/18/2025, 3:47 PMtall-airline-16756
08/18/2025, 3:47 PMimport asyncio
async def entrypoint(ctx: JobContext):
# Grab the default event loop
loop = asyncio.get_event_loop()
# Use the loop to create and run tasks
async def my_task():
# Your task logic here
pass
asyncio.create_task(my_task())
# Keep things moving with other operations
await ctx.connect()
Just a few things to keep in mind:
• You can use asyncio.get_event_loop()
to get the current event loop.
• If you ever need a fresh event loop, asyncio.new_event_loop()
lets you create one, and you can set it as default with asyncio.set_event_loop()
.
• But honestly, in most cases, the default event loop works just fine.
If you want to chat more about handling the event loop or have any other questions, just let me know—I’m here to help!
Sources: examples/primitives/participant_entrypoint.py | examples/video-stream/video_play.pybrief-vase-33757
08/18/2025, 3:48 PMtall-airline-16756
08/18/2025, 3:48 PMon('error')
Event Handler:
LiveKit emits an error
event whenever something goes wrong. You can listen for this event to catch all errors:
llm.on('error', callback_function)
This event gives you useful info like the timestamp, the error itself, and whether it’s something you can recover from.
2. Using the log_exceptions
Decorator:
Simply wrap your functions or coroutines with the log_exceptions
decorator to automatically log any exceptions:
@log_exceptions()
async def my_coroutine():
# Your code here
...
3. Recording Exceptions with OpenTelemetry:
You can also use OpenTelemetry’s record_exception
function to log exceptions within spans, which helps with observability:
from livekit.telemetry import record_exception
try:
# Your code here
except Exception as e:
record_exception(span, e) # where span is your OpenTelemetry span
Here’s a little example that brings these together:
import asyncio
from livekit import LLM
from livekit.telemetry import record_exception
from livekit.log import log_exceptions
@log_exceptions()
async def main():
try:
# Initialize your LLM or other LiveKit components
llm = LLM()
# Listen for the 'error' event
def handle_error(error_event):
print(f"Error occurred: {error_event.error}")
llm.on('error', handle_error)
# Your application logic here
await llm.chat("Your input here")
except Exception as e:
record_exception(span, e)
if __name__ == "__main__":
asyncio.run(main())
These tips make sure you’re covering all your bases when it comes to exception handling and logging in your event loop and app. If you have any questions or want to chat more about this, I’m here to help!
Sources: livekit-plugins/livekit-plugins-gladia/livekit/plugins/gladia/stt.py