Skip to content

Log Streaming

When executing long-running processes in a sandbox, you’ll often want to access and process their logs in real time.

The Daytona SDK supports both:

  • Fetching log snapshot — retrieve all logs up to a certain point.
  • Log streaming — stream logs as they are being produced, while the process is still running.

This guide covers how to use log streaming in both asynchronous and synchronous modes. Real-time streaming is especially useful for debugging, monitoring, or integrating with observability tools.

Asynchronous

If your sandboxed process is part of a larger system and is expected to run for an extended period (or indefinitely), you can process logs asynchronously in the background, while the rest of your system continues executing.

This is ideal for:

  • Continuous monitoring
  • Debugging long-running jobs
  • Live log forwarding or visualizations
import asyncio
from daytona_sdk import Daytona, SessionExecuteRequest
async def main():
daytona = Daytona()
sandbox = daytona.create()
try:
session_id = "exec-session-1"
sandbox.process.create_session(session_id)
command = sandbox.process.execute_session_command(
session_id,
SessionExecuteRequest(
command='for i in {1..10}; do echo "Processing step $i..."; sleep 1; done',
var_async=True,
),
)
logs_task = asyncio.create_task(
sandbox.process.get_session_command_logs_async(
session_id, command.cmd_id, lambda chunk: print(f"Log chunk: {chunk}")
)
)
print("Continuing execution while logs are streaming...")
await asyncio.sleep(1)
print("Other operations completed!")
print("At the end wait for any asynchronous task to complete and clean up resources...")
await logs_task
except Exception as e:
print(f"Error: {e}")
finally:
print("Cleaning up sandbox...")
daytona.remove(sandbox)
if __name__ == "__main__":
asyncio.run(main())

Synchronous

If the command has a predictable duration, or if you don’t need to run it in the background, you can process log stream synchronously. For example, you can write logs to a file or some other storage.

import asyncio
import os
from daytona_sdk import Daytona, SessionExecuteRequest
async def main():
daytona = Daytona()
sandbox = daytona.create()
try:
session_id = "exec-session-1"
sandbox.process.create_session(session_id)
command = sandbox.process.execute_session_command(
session_id,
SessionExecuteRequest(
command='counter=1; while (( counter <= 5 )); do echo "Count: $counter"; ((counter++)); sleep 2; done',
var_async=True,
),
)
log_file_path = f"./logs/logs-session_{session_id}-command_{command.cmd_id}.log"
os.makedirs(os.path.dirname(log_file_path), exist_ok=True)
with open(log_file_path, "w") as log_file:
def handle_chunk(chunk: str):
# remove null bytes
clean_chunk = chunk.replace("\x00", "")
# write to file
log_file.write(clean_chunk)
log_file.flush()
await sandbox.process.get_session_command_logs_async(
session_id, command.cmd_id, handle_chunk
)
except Exception as e:
print(f"Error: {e}")
finally:
print("Cleaning up sandbox...")
daytona.remove(sandbox)
if __name__ == "__main__":
asyncio.run(main())