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

  1. Phase 1 (Now): Manual monthly data collection into markdown report (see sustainability-ratio.md template)
  2. Phase 2 (Month 2): Automate git-based metrics (contributors, PRs) via script
  3. Phase 3 (Month 3): Connect billing APIs for compute cost automation
  4. Phase 4 (Month 4+): Grafana dashboard with automated data pipeline