Project Snapshot Report
Use project.snapshot() to pull config, org, teams, members, nodes, and audit events in one call, then build a human-readable report.
ManagementProject.snapshot() batches multiple Management API reads into a single request. It is the most efficient way to get a full picture of a project when you need several resources at once.
How snapshot works
Pass a list of resource names in include and optional per-resource limit overrides. The server returns a ProjectSnapshot with optional fields — any resource not in include is None:
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")
snapshot = project.snapshot(
include=["config", "organization", "teams", "members", "workflow_nodes", "audit_events"],
team_limit=100,
member_limit=100,
node_limit=100,
audit_limit=50,
)snapshot returns a ProjectSnapshot dataclass with these optional fields:
Prop
Type
Building a text report
from datetime import datetime, timezone
from optixlog import SDKClient
from optixlog.management import Management
def build_report(project_id: str) -> str:
client = SDKClient(
base_url="https://optixlog.leidos.com",
api_key="sk-opt-xxxx",
)
mgmt = Management(client)
project = mgmt.project(project_id)
snap = project.snapshot(
include=["config", "organization", "teams", "members", "workflow_nodes", "audit_events"],
team_limit=50,
member_limit=200,
node_limit=100,
audit_limit=25,
)
client.close()
lines: list[str] = []
now = datetime.now(tz=timezone.utc).isoformat()
lines.append(f"# OptixLog Project Report — {now}")
lines.append("")
# Config section
if snap.config:
c = snap.config
lines.append("## Project")
lines.append(f"- **Name:** {c.name}")
lines.append(f"- **ID:** {c.id}")
lines.append(f"- **Status:** {c.status}")
lines.append(f"- **Category:** {c.category or '—'}")
if c.description:
lines.append(f"- **Description:** {c.description}")
lines.append(f"- **Last updated:** {c.updated_at.isoformat()}")
lines.append("")
# Organization section
if snap.organization:
o = snap.organization
lines.append("## Organization")
lines.append(f"- **Name:** {o.name}")
lines.append(f"- **Industry:** {o.industry or '—'}")
lines.append(f"- **Contact:** {o.contact_name or '—'} <{o.contact_email or '—'}>")
lines.append("")
# Teams section
if snap.teams is not None:
lines.append(f"## Teams ({len(snap.teams)})")
for team in snap.teams:
count = f"{team.member_count} members" if team.member_count is not None else "?"
lines.append(f"- {team.name} [{team.category or 'uncategorized'}] — {count}")
lines.append("")
# Members section
if snap.members is not None:
lines.append(f"## Members ({len(snap.members)})")
for member in snap.members:
name = member.user_ref.name or member.user_ref.id
lines.append(f"- {name}")
lines.append("")
# Workflow nodes section
if snap.workflow_nodes is not None:
lines.append(f"## Recent Workflow Nodes ({len(snap.workflow_nodes)})")
for node in snap.workflow_nodes:
label = node.label_ref.name if node.label_ref else "unlabeled"
lines.append(f"- [{label}] {node.display_name} ({node.id})")
lines.append("")
# Audit events section
if snap.audit_events is not None:
lines.append(f"## Recent Audit Events ({len(snap.audit_events)})")
for event in snap.audit_events:
actor = event.actor_ref.name or event.actor_ref.id if event.actor_ref else "system"
lines.append(
f"- {event.timestamp.strftime('%Y-%m-%d %H:%M')} "
f"[{event.level}] {event.action} — {actor}"
)
lines.append("")
return "\n".join(lines)
if __name__ == "__main__":
report = build_report("proj_grating_7f3a")
print(report)
with open("project_report.md", "w") as f:
f.write(report)
print("Report written to project_report.md")Requesting a partial snapshot
You can request only the fields you need to reduce response size:
# Only pull config and the most recent audit events.
snap = project.snapshot(
include=["config", "audit_events"],
audit_limit=10,
)
if snap.config:
print(snap.config.name)
for event in (snap.audit_events or []):
print(event.action, event.timestamp)snapshot vs. iterating collections
snapshot is efficient for generating reports or health checks because it batches several reads. If you need to page through large result sets (thousands of nodes or audit events), use the individual collection methods with iter() instead — snapshot is capped by the *_limit parameters.