import datetime
from collections import defaultdict
from encord import EncordUserClient
from encord.analytics import TaskActionType
SSH_PATH = "<your_private_key>"
PROJECT_ID = "<project_id>"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
domain="https://api.encord.com",
)
# Get the project
project = user_client.get_project(PROJECT_ID)
# Define time range
start_time = datetime.datetime.now() - datetime.timedelta(days=29)
# Fetch only approve and reject actions
actions = list(project.get_task_actions(
after=start_time,
action_type=[TaskActionType.APPROVE, TaskActionType.REJECT],
))
# --- Overall rates ---
total = len(actions)
approvals = [a for a in actions if a.action_type == TaskActionType.APPROVE]
rejections = [a for a in actions if a.action_type == TaskActionType.REJECT]
print("=== Overall Review Rates ===")
if not total:
print("No actions found.")
else:
print(f"Total review actions : {total}")
print(f"Approvals : {len(approvals)} ({len(approvals) / total * 100:.1f}%)")
print(f"Rejections : {len(rejections)} ({len(rejections) / total * 100:.1f}%)")
# --- Per-reviewer breakdown ---
reviewer_stats = defaultdict(lambda: {"approved": 0, "rejected": 0})
for action in actions:
email = action.actor_email
if action.action_type == TaskActionType.APPROVE:
reviewer_stats[email]["approved"] += 1
elif action.action_type == TaskActionType.REJECT:
reviewer_stats[email]["rejected"] += 1
print("\n=== Per-Reviewer Breakdown ===")
print(f"{'Reviewer':<35} {'Approved':>10} {'Rejected':>10} {'Approval Rate':>15}")
print("-" * 72)
for email, stats in sorted(reviewer_stats.items()):
total_by_reviewer = stats["approved"] + stats["rejected"]
rate = stats["approved"] / total_by_reviewer * 100 if total_by_reviewer else 0
print(f"{email:<35} {stats['approved']:>10} {stats['rejected']:>10} {rate:>14.1f}%")