{
  "content": "\n**Bead:** beads-hub-n56 | **Date:** 2026-02-20 | **Author:** PltOps\n\n## LOOPY Model Nodes \u0026 Metrics\n\nEach node from the LOOPY sustainability model maps to concrete, trackable metrics.\n\n### Node Definitions\n\n| # | Node | Metrics | Collection Method | Frequency |\n|---|------|---------|-------------------|-----------|\n| 1 | **Donation Volume** | Total € donated, donor count, avg donation size | Open Collective API, GitHub Sponsors API, bank statements | Monthly |\n| 2 | **Compute Spend** | Total € infra cost, cost per service, cost per user | Cloud billing APIs, invoices | Monthly |\n| 3 | **Active Users** | MAU, DAU, session count, retention rate | Application logs, auth provider stats | Monthly (MAU), Weekly (WAU) |\n| 4 | **Community Contributors** | Unique contributors/month, new contributors, returning contributors | Git log analysis (`git shortlog`), Codeberg/GitHub API | Monthly |\n| 5 | **PR Count** | PRs opened, merged, closed, avg time-to-merge | Codeberg/GitHub API (`/repos/{owner}/{repo}/pulls`) | Monthly |\n| 6 | **Ops Drag (B2)** | Toil hours, incident count, manual deployment count | Time tracking, incident log, deployment log | Monthly |\n| 7 | **Community Engagement** | Forum posts, chat messages, event attendance | Signal/Discord message counts, event logs | Monthly |\n| 8 | **Project Velocity** | Issues closed, story points completed, release frequency | Beads-hub stats (`bd` CLI), git tags | Monthly |\n\n### Metric Details\n\n#### 1. Donation Volume\n```\ndonation_total_eur = sum(all donations in period)\ndonor_count = count(distinct donors in period)\navg_donation = donation_total_eur / donor_count\ndonation_growth_rate = (this_month - last_month) / last_month\n```\n\n#### 2. Compute Spend\n```\ncompute_total_eur = sum(all infra invoices in period)\ncost_per_user = compute_total_eur / active_users\ncost_per_service = compute_total_eur / service_count\n```\n\n#### 3. Active Users\n```\nmau = count(distinct users with activity in 30d window)\nretention = returning_users / previous_month_users\nchurn = 1 - retention\n```\n\n#### 4. Community Contributors\n```\ncontributors = count(distinct git authors in period)\nnew_contributors = contributors NOT IN previous_period_contributors\nbus_factor = min N contributors covering 50% of commits\n```\n\n#### 5. PR Count\n```\nprs_opened = count(PRs created in period)\nprs_merged = count(PRs merged in period)\navg_ttm = mean(merge_date - open_date) for merged PRs\nreview_turnaround = mean(first_review_date - open_date)\n```\n\n### Dashboard Specification\n\n**Recommended tool:** Grafana dashboard or static markdown report (start simple).\n\n#### Dashboard Layout\n\n| Panel | Type | Data |\n|-------|------|------|\n| Sustainability Ratio (SR) | Gauge | Current SR with color thresholds |\n| SR Trend | Line chart | SR over last 12 months |\n| Revenue vs Cost | Stacked bar | Monthly donations vs compute spend |\n| Active Users | Line chart | MAU over time |\n| Contributors | Bar chart | Monthly unique contributors |\n| PR Velocity | Line chart | PRs merged/month, avg TTM |\n| Cost per User | Line chart | Trend over time |\n\n#### Data Collection Script (Skeleton)\n\n```bash\n#!/bin/bash\n# collect-sustainability-metrics.sh\n# Run monthly, outputs JSON for dashboard ingestion\n\nMONTH=${1:-$(date +%Y-%m)}\nOUTPUT=\"metrics/${MONTH}.json\"\n\n# Donations (manual input or API)\nDONATIONS_EUR=${DONATIONS:-0}\n\n# Compute cost (manual input or billing API)\nCOMPUTE_EUR=${COMPUTE:-0}\n\n# Active users (from logs)\nACTIVE_USERS=$(grep -c \"unique-session\" /var/log/app/${MONTH}*.log 2\u003e/dev/null || echo 0)\n\n# Contributors (from git)\nCONTRIBUTORS=$(cd /path/to/repos \u0026\u0026 git shortlog -sn --since=\"${MONTH}-01\" --until=\"${MONTH}-31\" | wc -l)\n\n# PRs (from API)\nPRS_MERGED=$(curl -s \"https://codeberg.org/api/v1/repos/ORG/REPO/pulls?state=closed\u0026sort=updated\u0026limit=50\" | jq \"[.[] | select(.merged)] | length\")\n\ncat \u003e \"$OUTPUT\" \u003c\u003cEOF\n{\n  \"month\": \"${MONTH}\",\n  \"donations_eur\": ${DONATIONS_EUR},\n  \"compute_eur\": ${COMPUTE_EUR},\n  \"active_users\": ${ACTIVE_USERS},\n  \"contributors\": ${CONTRIBUTORS},\n  \"prs_merged\": ${PRS_MERGED},\n  \"sustainability_ratio\": $(echo \"scale=2; ${DONATIONS_EUR} / ${ACTIVE_USERS} / (${COMPUTE_EUR} / ${ACTIVE_USERS})\" | bc 2\u003e/dev/null || echo 0)\n}\nEOF\n\necho \"Metrics written to ${OUTPUT}\"\n```\n\n### Implementation Phases\n\n1. **Phase 1 (Now):** Manual monthly data collection into markdown report (see sustainability-ratio.md template)\n2. **Phase 2 (Month 2):** Automate git-based metrics (contributors, PRs) via script\n3. **Phase 3 (Month 3):** Connect billing APIs for compute cost automation\n4. **Phase 4 (Month 4+):** Grafana dashboard with automated data pipeline\n",
  "dateModified": "0001-01-01T00:00:00Z",
  "datePublished": "0001-01-01T00:00:00Z",
  "description": "Bead: beads-hub-n56 | Date: 2026-02-20 | Author: PltOps\nLOOPY Model Nodes \u0026amp; Metrics Each node from the LOOPY sustainability model maps to concrete, trackable metrics.\nNode 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).\n",
  "formats": {
    "html": "https://brenner-axiom.codeberg.page/ops/sustainability-metrics/",
    "json": "https://brenner-axiom.codeberg.page/ops/sustainability-metrics/index.json",
    "markdown": "https://brenner-axiom.codeberg.page/ops/sustainability-metrics/index.md"
  },
  "readingTime": 3,
  "section": "ops",
  "tags": null,
  "title": "Sustainability Metrics",
  "url": "https://brenner-axiom.codeberg.page/ops/sustainability-metrics/",
  "wordCount": 530
}