OptixLog Docs
Python SDKRecipes

Export Audit Log

Filter audit events by time range, level, and action, iterate all pages, and serialize the results to JSON or CSV.

The Management API exposes every audited action taken against your project. This recipe shows you how to filter events by time range, level, and action category, then export them to JSON or CSV.

Setup

export_audit.py
from datetime import datetime, timezone
from optixlog import SDKClient
from optixlog.management import Management

client = SDKClient(
    base_url="https://optixlog.leidos.com",
    api_key="sk-opt-xxxx",
)
mgmt = Management(client)
project = mgmt.project("proj_grating_7f3a")

Filtering audit events

All filters are AND-combined. The most common filters are since, until, and level:

from datetime import datetime, timezone

events_page = project.audit_events.list(
    since=datetime(2026, 1, 1, tzinfo=timezone.utc),
    until=datetime(2026, 6, 1, tzinfo=timezone.utc),
    level="warn",
    limit=100,
    order_by="timestamp",
    order="asc",
)

print(f"Found {events_page.total} warn events in range")

Available filters:

Prop

Type

Iterating all matching events

Use iter() to walk all pages without tracking cursors:

from datetime import datetime, timezone

events = list(project.audit_events.iter(
    since=datetime(2026, 5, 1, tzinfo=timezone.utc),
    level="error",
    order_by="timestamp",
    order="asc",
))

print(f"Collected {len(events)} error events")

Exporting to JSON

export_audit.py
import json
from datetime import datetime, timezone

events = list(project.audit_events.iter(
    since=datetime(2026, 1, 1, tzinfo=timezone.utc),
    order_by="timestamp",
    order="asc",
))

records = [
    {
        "id": e.id,
        "timestamp": e.timestamp.isoformat(),
        "action": e.action,
        "description": e.description,
        "category": e.category,
        "level": e.level,
        "actor_id": e.actor_ref.id if e.actor_ref else None,
        "actor_name": e.actor_ref.name if e.actor_ref else None,
        "target_ids": [t.id for t in e.target_refs],
        "request_id": e.request_id,
    }
    for e in events
]

with open("audit_export.json", "w") as f:
    json.dump(records, f, indent=2)

print(f"Exported {len(records)} events to audit_export.json")

Exporting to CSV

export_audit_csv.py
import csv
from datetime import datetime, timezone

events = list(project.audit_events.iter(
    since=datetime(2026, 1, 1, tzinfo=timezone.utc),
    order_by="timestamp",
    order="asc",
))

fieldnames = ["id", "timestamp", "action", "description", "category",
              "level", "actor_id", "actor_name", "request_id"]

with open("audit_export.csv", "w", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()
    for e in events:
        writer.writerow({
            "id": e.id,
            "timestamp": e.timestamp.isoformat(),
            "action": e.action,
            "description": e.description,
            "category": e.category,
            "level": e.level,
            "actor_id": e.actor_ref.id if e.actor_ref else "",
            "actor_name": e.actor_ref.name if e.actor_ref else "",
            "request_id": e.request_id or "",
        })

print(f"Exported {len(events)} events to audit_export.csv")

Counting events without fetching them

warn_count = project.audit_events.count(level="warn")
error_count = project.audit_events.count(level="error")
print(f"Warnings: {warn_count}, Errors: {error_count}")

Looking up a single event

# By id.
event = project.audit_events.get("audit-event-id")

# Find the most recent project update.
latest_update = project.audit_events.first(action="project.updated")
if latest_update:
    print(f"Last updated at {latest_update.timestamp}")

# Find exactly one event matching a request_id.
exact = project.audit_events.one(request_id="req-abc123")

Audit event order

The default order for audit_events is "desc" (newest first). Pass order="asc" when you want chronological order for export.

On this page