Sustainability Metrics
Bead: beads-hub-n56 | Date: 2026-02-20 | Author: PltOps
LOOPY Model Nodes & Metrics
Each node from the LOOPY sustainability model maps to concrete, trackable metrics.
Node Definitions
| # | Node | Metrics | Collection Method | Frequency |
|---|---|---|---|---|
| 1 | Donation Volume | Total € donated, donor count, avg donation size | Open Collective API, GitHub Sponsors API, bank statements | Monthly |
| 2 | Compute Spend | Total € infra cost, cost per service, cost per user | Cloud billing APIs, invoices | Monthly |
| 3 | Active Users | MAU, DAU, session count, retention rate | Application logs, auth provider stats | Monthly (MAU), Weekly (WAU) |
| 4 | Community Contributors | Unique contributors/month, new contributors, returning contributors | Git log analysis (git shortlog), Codeberg/GitHub API | Monthly |
| 5 | PR Count | PRs opened, merged, closed, avg time-to-merge | Codeberg/GitHub API (/repos/{owner}/{repo}/pulls) | Monthly |
| 6 | Ops Drag (B2) | Toil hours, incident count, manual deployment count | Time tracking, incident log, deployment log | Monthly |
| 7 | Community Engagement | Forum posts, chat messages, event attendance | Signal/Discord message counts, event logs | Monthly |
| 8 | Project Velocity | Issues closed, story points completed, release frequency | Beads-hub stats (bd CLI), git tags | Monthly |
Metric Details
1. Donation Volume
donation_total_eur = sum(all donations in period)
donor_count = count(distinct donors in period)
avg_donation = donation_total_eur / donor_count
donation_growth_rate = (this_month - last_month) / last_month
2. Compute Spend
compute_total_eur = sum(all infra invoices in period)
cost_per_user = compute_total_eur / active_users
cost_per_service = compute_total_eur / service_count
3. Active Users
mau = count(distinct users with activity in 30d window)
retention = returning_users / previous_month_users
churn = 1 - retention
4. Community Contributors
contributors = count(distinct git authors in period)
new_contributors = contributors NOT IN previous_period_contributors
bus_factor = min N contributors covering 50% of commits
5. PR Count
prs_opened = count(PRs created in period)
prs_merged = count(PRs merged in period)
avg_ttm = mean(merge_date - open_date) for merged PRs
review_turnaround = mean(first_review_date - open_date)
Dashboard Specification
Recommended tool: Grafana dashboard or static markdown report (start simple).
Dashboard Layout
| Panel | Type | Data |
|---|---|---|
| Sustainability Ratio (SR) | Gauge | Current SR with color thresholds |
| SR Trend | Line chart | SR over last 12 months |
| Revenue vs Cost | Stacked bar | Monthly donations vs compute spend |
| Active Users | Line chart | MAU over time |
| Contributors | Bar chart | Monthly unique contributors |
| PR Velocity | Line chart | PRs merged/month, avg TTM |
| Cost per User | Line chart | Trend over time |
Data Collection Script (Skeleton)
#!/bin/bash
# collect-sustainability-metrics.sh
# Run monthly, outputs JSON for dashboard ingestion
MONTH=${1:-$(date +%Y-%m)}
OUTPUT="metrics/${MONTH}.json"
# Donations (manual input or API)
DONATIONS_EUR=${DONATIONS:-0}
# Compute cost (manual input or billing API)
COMPUTE_EUR=${COMPUTE:-0}
# Active users (from logs)
ACTIVE_USERS=$(grep -c "unique-session" /var/log/app/${MONTH}*.log 2>/dev/null || echo 0)
# Contributors (from git)
CONTRIBUTORS=$(cd /path/to/repos && git shortlog -sn --since="${MONTH}-01" --until="${MONTH}-31" | wc -l)
# PRs (from API)
PRS_MERGED=$(curl -s "https://codeberg.org/api/v1/repos/ORG/REPO/pulls?state=closed&sort=updated&limit=50" | jq "[.[] | select(.merged)] | length")
cat > "$OUTPUT" <<EOF
{
"month": "${MONTH}",
"donations_eur": ${DONATIONS_EUR},
"compute_eur": ${COMPUTE_EUR},
"active_users": ${ACTIVE_USERS},
"contributors": ${CONTRIBUTORS},
"prs_merged": ${PRS_MERGED},
"sustainability_ratio": $(echo "scale=2; ${DONATIONS_EUR} / ${ACTIVE_USERS} / (${COMPUTE_EUR} / ${ACTIVE_USERS})" | bc 2>/dev/null || echo 0)
}
EOF
echo "Metrics written to ${OUTPUT}"
Implementation Phases
- Phase 1 (Now): Manual monthly data collection into markdown report (see sustainability-ratio.md template)
- Phase 2 (Month 2): Automate git-based metrics (contributors, PRs) via script
- Phase 3 (Month 3): Connect billing APIs for compute cost automation
- Phase 4 (Month 4+): Grafana dashboard with automated data pipeline