mirror of
https://github.com/blackboxprogramming/blackroad-os-kpis.git
synced 2026-03-18 06:34:02 -05:00
v2: 9 collectors, 60+ KPIs — cloudflare, services, local mac, github-deep, autonomy bars
RoadChain-SHA2048: f59eb7b3bb74e603 RoadChain-Identity: alexa@sovereign RoadChain-Full: f59eb7b3bb74e60325e3dc2bde2dce2d3f77e4afdadb4b559bf44b95318aac5e44854cc056bec1414243177e469feccdf8a5bf21697916f004706ac784fc70a9ce221703ff29c91581884e5903b5d4a6127a3b570eda54801cf7641a17b13490bb8a3d3be04ee01a96030087800f62f02f47e6ca3d76a3e832c8cdfbeefa3ffbd57acc133d9a7d684161e565dd53636a48410cd38d322620c3fac516a79e5831edf3dab2e81c484f583628c617f85f066351f403163cea6e939484ab33bdaaaa27b23695999aa0e68ae9bff10bf9dfbabcd2785b286600e940359f8e2122c708ed62e7a358accafd224da40151104d77017d4c91fa5b35cce8ca7a728d1b37e0
This commit is contained in:
3
.wrangler/cache/pages.json
vendored
Normal file
3
.wrangler/cache/pages.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"account_id": "848cf0b18d51e0170e0d1537aec3505a"
|
||||
}
|
||||
6
.wrangler/cache/wrangler-account.json
vendored
Normal file
6
.wrangler/cache/wrangler-account.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"account": {
|
||||
"id": "848cf0b18d51e0170e0d1537aec3505a",
|
||||
"name": "Amundsonalexa@gmail.com's Account"
|
||||
}
|
||||
}
|
||||
81
collectors/cloudflare.sh
Normal file
81
collectors/cloudflare.sh
Normal file
@@ -0,0 +1,81 @@
|
||||
#!/bin/bash
|
||||
# Collect Cloudflare KPIs: D1, KV, R2, Workers, Pages, Tunnels
|
||||
|
||||
source "$(dirname "$0")/../lib/common.sh"
|
||||
|
||||
log "Collecting Cloudflare KPIs..."
|
||||
|
||||
OUT=$(snapshot_file cloudflare)
|
||||
|
||||
CF_ACCOUNT="848cf0b18d51e0170e0d1537aec3505a"
|
||||
|
||||
# D1 databases
|
||||
d1_count=0
|
||||
d1_total_size=0
|
||||
d1_json="[]"
|
||||
d1_raw=$(npx wrangler d1 list --json 2>/dev/null || echo '[]')
|
||||
if [ -n "$d1_raw" ]; then
|
||||
d1_count=$(echo "$d1_raw" | python3 -c "import json,sys; d=json.load(sys.stdin); print(len(d))" 2>/dev/null || echo 0)
|
||||
d1_json=$(echo "$d1_raw" | python3 -c "
|
||||
import json, sys
|
||||
dbs = json.load(sys.stdin)
|
||||
print(json.dumps([{'name': d.get('name',''), 'uuid': d.get('uuid','')} for d in dbs]))
|
||||
" 2>/dev/null || echo '[]')
|
||||
fi
|
||||
ok "D1: $d1_count databases"
|
||||
|
||||
# KV namespaces
|
||||
kv_count=0
|
||||
kv_raw=$(npx wrangler kv namespace list 2>/dev/null || echo '[]')
|
||||
if [ -n "$kv_raw" ]; then
|
||||
kv_count=$(echo "$kv_raw" | python3 -c "import json,sys; print(len(json.load(sys.stdin)))" 2>/dev/null || echo 0)
|
||||
fi
|
||||
ok "KV: $kv_count namespaces"
|
||||
|
||||
# R2 buckets
|
||||
r2_count=0
|
||||
# R2 outputs text, not JSON — count "name:" lines
|
||||
r2_count=$(npx wrangler r2 bucket list 2>/dev/null | grep -c "^name:" || echo 0)
|
||||
ok "R2: $r2_count buckets"
|
||||
|
||||
# Pages projects (table output, count data rows)
|
||||
pages_count=$(npx wrangler pages project list 2>/dev/null | grep -c "│" || echo 0)
|
||||
# Subtract header rows (2 per table: header + separator)
|
||||
pages_count=$((pages_count > 2 ? pages_count - 2 : 0))
|
||||
ok "Pages: $pages_count projects"
|
||||
|
||||
# D1 total size
|
||||
d1_total_size_kb=0
|
||||
if [ -n "$d1_raw" ] && [ "$d1_raw" != "[]" ]; then
|
||||
d1_total_size_kb=$(echo "$d1_raw" | python3 -c "
|
||||
import json, sys
|
||||
dbs = json.load(sys.stdin)
|
||||
total = sum(d.get('file_size', 0) for d in dbs)
|
||||
print(total // 1024)
|
||||
" 2>/dev/null || echo 0)
|
||||
fi
|
||||
|
||||
cat > "$OUT" << ENDJSON
|
||||
{
|
||||
"source": "cloudflare",
|
||||
"collected_at": "$TIMESTAMP",
|
||||
"date": "$TODAY",
|
||||
"d1": {
|
||||
"count": $d1_count,
|
||||
"total_size_kb": $d1_total_size_kb,
|
||||
"databases": $d1_json
|
||||
},
|
||||
"kv": {
|
||||
"count": $kv_count
|
||||
},
|
||||
"r2": {
|
||||
"count": $r2_count
|
||||
},
|
||||
"pages": {
|
||||
"count": $pages_count
|
||||
},
|
||||
"account_id": "$CF_ACCOUNT"
|
||||
}
|
||||
ENDJSON
|
||||
|
||||
ok "Cloudflare: ${d1_count} D1, ${kv_count} KV, ${r2_count} R2, ${pages_count} Pages"
|
||||
@@ -11,7 +11,7 @@ log "═════════════════════════
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
|
||||
# Run all collectors
|
||||
for collector in github gitea fleet autonomy loc; do
|
||||
for collector in github github-deep gitea fleet services autonomy loc local cloudflare; do
|
||||
log "Running $collector collector..."
|
||||
bash "$SCRIPT_DIR/$collector.sh" 2>&1 || err "Collector $collector failed"
|
||||
echo
|
||||
@@ -37,31 +37,109 @@ for f in glob.glob(f'{data_dir}/snapshots/{today}-*.json'):
|
||||
|
||||
# Build daily summary
|
||||
gh = snapshots.get('github', {})
|
||||
ghd = snapshots.get('github-deep', {})
|
||||
gt = snapshots.get('gitea', {})
|
||||
fl = snapshots.get('fleet', {})
|
||||
sv = snapshots.get('services', {})
|
||||
au = snapshots.get('autonomy', {})
|
||||
lc = snapshots.get('loc', {})
|
||||
lo = snapshots.get('local', {})
|
||||
cf = snapshots.get('cloudflare', {})
|
||||
|
||||
daily = {
|
||||
'date': today,
|
||||
'collected_at': '$TIMESTAMP',
|
||||
'summary': {
|
||||
# Code velocity
|
||||
'commits_today': gh.get('commits', {}).get('today', 0) + gt.get('commits', {}).get('today', 0),
|
||||
'push_events_today': gh.get('commits', {}).get('push_events_today', 0),
|
||||
'prs_open': gh.get('pull_requests', {}).get('open', 0),
|
||||
'prs_merged_today': gh.get('pull_requests', {}).get('merged_today', 0),
|
||||
'prs_merged_total': gh.get('pull_requests', {}).get('merged_total', 0),
|
||||
'github_events_today': gh.get('activity', {}).get('events_today', 0),
|
||||
|
||||
# Repos
|
||||
'repos_github': gh.get('repos', {}).get('total', 0),
|
||||
'repos_gitea': gt.get('repos', {}).get('total', 0),
|
||||
'repos_total': gh.get('repos', {}).get('total', 0) + gt.get('repos', {}).get('total', 0),
|
||||
'repos_active': ghd.get('repos', {}).get('active', 0),
|
||||
'repos_archived': ghd.get('repos', {}).get('archived', 0),
|
||||
|
||||
# GitHub profile
|
||||
'github_stars': ghd.get('repos', {}).get('total_stars', 0),
|
||||
'github_forks': ghd.get('repos', {}).get('total_forks', 0),
|
||||
'github_followers': ghd.get('profile', {}).get('followers', 0),
|
||||
'github_following': ghd.get('profile', {}).get('following', 0),
|
||||
'github_open_issues': ghd.get('repos', {}).get('total_open_issues', 0),
|
||||
'github_size_mb': ghd.get('repos', {}).get('total_size_mb', 0),
|
||||
'github_languages': ghd.get('repos', {}).get('languages', {}),
|
||||
|
||||
# Fleet
|
||||
'fleet_online': fl.get('fleet', {}).get('online', 0),
|
||||
'fleet_total': fl.get('fleet', {}).get('total_nodes', 4),
|
||||
'autonomy_score': au.get('autonomy_score', 0),
|
||||
'total_loc': lc.get('total_estimated_loc', 0),
|
||||
'docker_containers': fl.get('totals', {}).get('docker_containers', 0),
|
||||
'ollama_models': fl.get('totals', {}).get('ollama_models', 0),
|
||||
'fleet_offline': fl.get('fleet', {}).get('offline_nodes', []),
|
||||
'avg_temp_c': fl.get('totals', {}).get('cpu_avg_temp_c', 0),
|
||||
'failed_units': fl.get('totals', {}).get('systemd_failed', 0),
|
||||
'throttled_nodes': fl.get('totals', {}).get('throttled_nodes', [])
|
||||
'throttled_nodes': fl.get('totals', {}).get('throttled_nodes', []),
|
||||
'fleet_mem_used_mb': fl.get('totals', {}).get('mem_used_mb', 0),
|
||||
'fleet_mem_total_mb': fl.get('totals', {}).get('mem_total_mb', 0),
|
||||
'fleet_disk_used_gb': fl.get('totals', {}).get('disk_used_gb', 0),
|
||||
'fleet_disk_total_gb': fl.get('totals', {}).get('disk_total_gb', 0),
|
||||
|
||||
# Services
|
||||
'docker_containers': sv.get('totals', {}).get('docker_containers', fl.get('totals', {}).get('docker_containers', 0)),
|
||||
'docker_images': sv.get('totals', {}).get('docker_images', 0),
|
||||
'ollama_models': sv.get('totals', {}).get('ollama_models', fl.get('totals', {}).get('ollama_models', 0)),
|
||||
'ollama_size_gb': sv.get('totals', {}).get('ollama_size_gb', 0),
|
||||
'postgres_dbs': sv.get('totals', {}).get('postgres_dbs', 0),
|
||||
'nginx_sites': sv.get('totals', {}).get('nginx_sites', 0),
|
||||
'systemd_services': sv.get('totals', {}).get('systemd_services', 0),
|
||||
'systemd_timers': sv.get('totals', {}).get('systemd_timers', 0),
|
||||
'failed_units': sv.get('totals', {}).get('systemd_failed', fl.get('totals', {}).get('systemd_failed', 0)),
|
||||
'fleet_processes': sv.get('totals', {}).get('processes', 0),
|
||||
'fleet_connections': sv.get('totals', {}).get('network_connections', 0),
|
||||
'fleet_swap_used_mb': sv.get('totals', {}).get('swap_used_mb', 0),
|
||||
'fleet_swap_total_mb': sv.get('totals', {}).get('swap_total_mb', 0),
|
||||
'tailscale_peers': sv.get('totals', {}).get('tailscale_peers', 0),
|
||||
|
||||
# Autonomy
|
||||
'autonomy_score': au.get('autonomy_score', 0),
|
||||
'heal_events_today': au.get('totals', {}).get('heal_events_today', 0),
|
||||
'service_restarts_today': au.get('totals', {}).get('service_restarts_today', 0),
|
||||
'fleet_cron_jobs': au.get('totals', {}).get('total_cron_jobs', 0),
|
||||
'fleet_timers': au.get('totals', {}).get('active_timers', 0),
|
||||
'max_uptime_days': au.get('totals', {}).get('max_uptime_days', 0),
|
||||
|
||||
# LOC
|
||||
'total_loc': lc.get('total_estimated_loc', 0),
|
||||
'local_repos': lc.get('local', {}).get('repos', 0),
|
||||
'local_files': lc.get('local', {}).get('files', 0),
|
||||
'local_scripts': lc.get('local', {}).get('scripts', 0),
|
||||
'local_script_lines': lc.get('local', {}).get('script_lines', 0),
|
||||
|
||||
# Local Mac
|
||||
'bin_tools': lo.get('scripts', {}).get('bin_tools', 0),
|
||||
'bin_size_mb': lo.get('scripts', {}).get('bin_size_mb', 0),
|
||||
'home_scripts': lo.get('scripts', {}).get('home_scripts', 0),
|
||||
'templates': lo.get('scripts', {}).get('templates', 0),
|
||||
'sqlite_dbs': lo.get('databases', {}).get('sqlite_count', 0),
|
||||
'blackroad_dir_mb': lo.get('databases', {}).get('blackroad_dir_mb', 0),
|
||||
'fts5_entries': lo.get('databases', {}).get('fts5_entries', 0),
|
||||
'systems_registered': lo.get('databases', {}).get('systems_registered', 0),
|
||||
'brew_packages': lo.get('packages', {}).get('homebrew', 0),
|
||||
'pip_packages': lo.get('packages', {}).get('pip3', 0),
|
||||
'npm_global_packages': lo.get('packages', {}).get('npm_global', 0),
|
||||
'mac_cron_jobs': lo.get('automation', {}).get('cron_jobs', 0),
|
||||
'local_git_repos': lo.get('automation', {}).get('local_git_repos', 0),
|
||||
'mac_disk_pct': lo.get('disk', {}).get('pct', 0),
|
||||
'mac_disk_used_gb': lo.get('disk', {}).get('used_gb', 0),
|
||||
'mac_processes': lo.get('system', {}).get('processes', 0),
|
||||
|
||||
# Cloudflare
|
||||
'cf_d1_databases': cf.get('d1', {}).get('count', 0),
|
||||
'cf_kv_namespaces': cf.get('kv', {}).get('count', 0),
|
||||
'cf_r2_buckets': cf.get('r2', {}).get('count', 0),
|
||||
'cf_pages': cf.get('pages', {}).get('count', 0),
|
||||
'cf_d1_size_kb': cf.get('d1', {}).get('total_size_kb', 0),
|
||||
},
|
||||
'sources': snapshots
|
||||
}
|
||||
|
||||
108
collectors/github-deep.sh
Normal file
108
collectors/github-deep.sh
Normal file
@@ -0,0 +1,108 @@
|
||||
#!/bin/bash
|
||||
# Deep GitHub metrics: stars, forks, traffic, languages, profile stats
|
||||
|
||||
source "$(dirname "$0")/../lib/common.sh"
|
||||
|
||||
log "Collecting deep GitHub metrics..."
|
||||
|
||||
OUT=$(snapshot_file github-deep)
|
||||
|
||||
# Profile stats
|
||||
profile=$(gh api users/$GITHUB_USER 2>/dev/null || echo '{}')
|
||||
followers=$(echo "$profile" | python3 -c "import json,sys; print(json.load(sys.stdin).get('followers',0))" 2>/dev/null || echo 0)
|
||||
following=$(echo "$profile" | python3 -c "import json,sys; print(json.load(sys.stdin).get('following',0))" 2>/dev/null || echo 0)
|
||||
public_repos=$(echo "$profile" | python3 -c "import json,sys; print(json.load(sys.stdin).get('public_repos',0))" 2>/dev/null || echo 0)
|
||||
public_gists=$(echo "$profile" | python3 -c "import json,sys; print(json.load(sys.stdin).get('public_gists',0))" 2>/dev/null || echo 0)
|
||||
|
||||
ok "Profile: $public_repos repos, $followers followers"
|
||||
|
||||
# Aggregate stars, forks, sizes across all repos
|
||||
repo_stats=$(gh api "users/$GITHUB_USER/repos?per_page=100&type=owner" --paginate 2>/dev/null | python3 -c "
|
||||
import json, sys
|
||||
|
||||
repos = []
|
||||
for line in sys.stdin:
|
||||
try:
|
||||
repos.extend(json.loads(line))
|
||||
except:
|
||||
pass
|
||||
|
||||
total_stars = sum(r.get('stargazers_count', 0) for r in repos)
|
||||
total_forks = sum(r.get('forks_count', 0) for r in repos)
|
||||
total_watchers = sum(r.get('watchers_count', 0) for r in repos)
|
||||
total_size_kb = sum(r.get('size', 0) for r in repos)
|
||||
total_open_issues = sum(r.get('open_issues_count', 0) for r in repos)
|
||||
archived = sum(1 for r in repos if r.get('archived'))
|
||||
active = len(repos) - archived
|
||||
|
||||
# Languages
|
||||
langs = {}
|
||||
for r in repos:
|
||||
l = r.get('language')
|
||||
if l:
|
||||
langs[l] = langs.get(l, 0) + 1
|
||||
|
||||
# Most recently updated
|
||||
recent = sorted(repos, key=lambda r: r.get('updated_at', ''), reverse=True)[:10]
|
||||
recent_names = [r['full_name'] for r in recent]
|
||||
|
||||
# Largest repos
|
||||
largest = sorted(repos, key=lambda r: r.get('size', 0), reverse=True)[:10]
|
||||
largest_info = [{r['full_name']: round(r['size']/1024, 1)} for r in largest]
|
||||
|
||||
print(json.dumps({
|
||||
'total_stars': total_stars,
|
||||
'total_forks': total_forks,
|
||||
'total_watchers': total_watchers,
|
||||
'total_size_mb': round(total_size_kb / 1024, 1),
|
||||
'total_open_issues': total_open_issues,
|
||||
'archived': archived,
|
||||
'active': active,
|
||||
'languages': langs,
|
||||
'top_10_recent': recent_names,
|
||||
'top_10_largest_mb': largest_info
|
||||
}))
|
||||
" 2>/dev/null || echo '{}')
|
||||
|
||||
# Org stats
|
||||
org_stats='{'
|
||||
first=true
|
||||
for org in $GITHUB_ORGS; do
|
||||
org_repos=$(gh api "orgs/$org/repos?per_page=100" --paginate --jq 'length' 2>/dev/null || echo 0)
|
||||
org_members=$(gh api "orgs/$org/members?per_page=100" --jq 'length' 2>/dev/null || echo 0)
|
||||
if [ "$first" = true ]; then
|
||||
org_stats="$org_stats\"$org\": {\"repos\": $org_repos, \"members\": $org_members}"
|
||||
first=false
|
||||
else
|
||||
org_stats="$org_stats, \"$org\": {\"repos\": $org_repos, \"members\": $org_members}"
|
||||
fi
|
||||
done
|
||||
org_stats="$org_stats}"
|
||||
|
||||
ok "Orgs: $org_stats"
|
||||
|
||||
python3 -c "
|
||||
import json
|
||||
|
||||
repo_stats = json.loads('''$repo_stats''')
|
||||
org_stats = json.loads('''$org_stats''')
|
||||
|
||||
output = {
|
||||
'source': 'github-deep',
|
||||
'collected_at': '$TIMESTAMP',
|
||||
'date': '$TODAY',
|
||||
'profile': {
|
||||
'followers': $followers,
|
||||
'following': $following,
|
||||
'public_repos': $public_repos,
|
||||
'public_gists': $public_gists
|
||||
},
|
||||
'repos': repo_stats,
|
||||
'orgs': org_stats
|
||||
}
|
||||
|
||||
with open('$OUT', 'w') as f:
|
||||
json.dump(output, f, indent=2)
|
||||
" 2>/dev/null
|
||||
|
||||
ok "Deep GitHub metrics collected"
|
||||
120
collectors/local.sh
Normal file
120
collectors/local.sh
Normal file
@@ -0,0 +1,120 @@
|
||||
#!/bin/bash
|
||||
# Collect local Mac KPIs: scripts, databases, packages, disk, processes
|
||||
|
||||
source "$(dirname "$0")/../lib/common.sh"
|
||||
|
||||
log "Collecting local Mac KPIs..."
|
||||
|
||||
OUT=$(snapshot_file local)
|
||||
|
||||
# Scripts in ~/bin
|
||||
bin_count=$(ls -1 ~/bin/ 2>/dev/null | wc -l | tr -d ' ')
|
||||
bin_size_mb=$(du -sm ~/bin/ 2>/dev/null | cut -f1 || echo 0)
|
||||
|
||||
# Shell scripts in home
|
||||
home_scripts=$(ls -1 ~/*.sh 2>/dev/null | wc -l | tr -d ' ')
|
||||
|
||||
# Templates
|
||||
template_count=$(ls -1 ~/Desktop/templates/ 2>/dev/null | wc -l | tr -d ' ')
|
||||
|
||||
# SQLite databases
|
||||
db_count=$(find ~/.blackroad -name "*.db" -type f 2>/dev/null | wc -l | tr -d ' ')
|
||||
db_size_mb=$(du -sm ~/.blackroad/ 2>/dev/null | cut -f1 || echo 0)
|
||||
|
||||
# Package managers
|
||||
brew_count=$(brew list 2>/dev/null | wc -l | tr -d ' ' || echo 0)
|
||||
pip_count=$(pip3 list 2>/dev/null | tail -n +3 | wc -l | tr -d ' ' || echo 0)
|
||||
npm_global=$(npm list -g --depth=0 2>/dev/null | tail -n +2 | wc -l | tr -d ' ' || echo 0)
|
||||
|
||||
# Cron jobs
|
||||
cron_count=$(crontab -l 2>/dev/null | grep -cv '^#\|^$' || echo 0)
|
||||
|
||||
# Git repos (local)
|
||||
git_repos=$(find ~/ -maxdepth 3 -name ".git" -type d 2>/dev/null | wc -l | tr -d ' ')
|
||||
|
||||
# Disk usage
|
||||
disk_used=$(df -g / | tail -1 | awk '{print $3}')
|
||||
disk_total=$(df -g / | tail -1 | awk '{print $2}')
|
||||
disk_pct=$(df / | tail -1 | awk '{print $5}' | tr -d '%')
|
||||
|
||||
# Processes
|
||||
process_count=$(ps aux | wc -l | tr -d ' ')
|
||||
|
||||
# Network connections
|
||||
net_connections=$(netstat -an 2>/dev/null | grep ESTABLISHED | wc -l | tr -d ' ' || echo 0)
|
||||
|
||||
# Downloads & Documents
|
||||
downloads_count=$(ls -1 ~/Downloads/ 2>/dev/null | wc -l | tr -d ' ')
|
||||
documents_count=$(ls -1 ~/Documents/ 2>/dev/null | wc -l | tr -d ' ')
|
||||
|
||||
# FTS5 memory index
|
||||
fts_entries=0
|
||||
if [ -f ~/.blackroad/markdown.db ]; then
|
||||
fts_entries=$(python3 -c "
|
||||
import sqlite3
|
||||
c = sqlite3.connect('$HOME/.blackroad/markdown.db')
|
||||
try:
|
||||
r = c.execute('SELECT count(*) FROM markdown_fts').fetchone()
|
||||
print(r[0])
|
||||
except:
|
||||
print(0)
|
||||
" 2>/dev/null || echo 0)
|
||||
fi
|
||||
|
||||
# Systems.db count
|
||||
systems_count=0
|
||||
if [ -f ~/.blackroad/systems.db ]; then
|
||||
systems_count=$(python3 -c "
|
||||
import sqlite3
|
||||
c = sqlite3.connect('$HOME/.blackroad/systems.db')
|
||||
try:
|
||||
r = c.execute('SELECT count(*) FROM systems').fetchone()
|
||||
print(r[0])
|
||||
except:
|
||||
print(0)
|
||||
" 2>/dev/null || echo 0)
|
||||
fi
|
||||
|
||||
cat > "$OUT" << ENDJSON
|
||||
{
|
||||
"source": "local",
|
||||
"collected_at": "$TIMESTAMP",
|
||||
"date": "$TODAY",
|
||||
"scripts": {
|
||||
"bin_tools": $bin_count,
|
||||
"bin_size_mb": $bin_size_mb,
|
||||
"home_scripts": $home_scripts,
|
||||
"templates": $template_count
|
||||
},
|
||||
"databases": {
|
||||
"sqlite_count": $db_count,
|
||||
"blackroad_dir_mb": $db_size_mb,
|
||||
"fts5_entries": $fts_entries,
|
||||
"systems_registered": $systems_count
|
||||
},
|
||||
"packages": {
|
||||
"homebrew": $brew_count,
|
||||
"pip3": $pip_count,
|
||||
"npm_global": $npm_global
|
||||
},
|
||||
"automation": {
|
||||
"cron_jobs": $cron_count,
|
||||
"local_git_repos": $git_repos
|
||||
},
|
||||
"disk": {
|
||||
"used_gb": $disk_used,
|
||||
"total_gb": $disk_total,
|
||||
"pct": $disk_pct
|
||||
},
|
||||
"system": {
|
||||
"processes": $process_count,
|
||||
"net_connections": $net_connections
|
||||
},
|
||||
"files": {
|
||||
"downloads": $downloads_count,
|
||||
"documents": $documents_count
|
||||
}
|
||||
}
|
||||
ENDJSON
|
||||
|
||||
ok "Local: ${bin_count} tools, ${db_count} DBs, ${brew_count} brew, ${cron_count} crons, ${disk_pct}% disk"
|
||||
92
collectors/services-probe.py
Normal file
92
collectors/services-probe.py
Normal file
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Deep service probe — runs on each Pi via SSH"""
|
||||
import json, subprocess, os
|
||||
|
||||
def run(cmd):
|
||||
try:
|
||||
return subprocess.check_output(cmd, shell=True, stderr=subprocess.DEVNULL, timeout=10).decode().strip()
|
||||
except:
|
||||
return ""
|
||||
|
||||
# Ollama
|
||||
ollama = {"count": 0, "size_gb": 0, "models": []}
|
||||
try:
|
||||
import urllib.request
|
||||
r = urllib.request.urlopen("http://localhost:11434/api/tags", timeout=3)
|
||||
data = json.loads(r.read())
|
||||
models = data.get("models", [])
|
||||
ollama["count"] = len(models)
|
||||
ollama["size_gb"] = round(sum(m.get("size", 0) for m in models) / 1e9, 1)
|
||||
ollama["models"] = [m.get("name", "") for m in models]
|
||||
except:
|
||||
pass
|
||||
|
||||
# Docker
|
||||
docker = {"running": 0, "images": 0, "containers_total": 0, "names": []}
|
||||
docker["running"] = int(run("docker ps -q 2>/dev/null | wc -l").strip() or "0")
|
||||
docker["images"] = int(run("docker images -q 2>/dev/null | wc -l").strip() or "0")
|
||||
docker["containers_total"] = int(run("docker ps -aq 2>/dev/null | wc -l").strip() or "0")
|
||||
names = run("docker ps --format '{{.Names}}' 2>/dev/null")
|
||||
docker["names"] = names.split("\n") if names else []
|
||||
|
||||
# PostgreSQL
|
||||
postgres = {"databases": 0}
|
||||
pg_count = run("sudo -u postgres psql -tc 'SELECT count(*) FROM pg_database' 2>/dev/null").strip()
|
||||
if pg_count and pg_count.isdigit():
|
||||
postgres["databases"] = int(pg_count)
|
||||
|
||||
# Nginx
|
||||
nginx = {"sites": 0, "active": False}
|
||||
nginx["sites"] = int(run("ls /etc/nginx/sites-enabled/ 2>/dev/null | wc -l").strip() or "0")
|
||||
nginx["active"] = run("systemctl is-active nginx 2>/dev/null") == "active"
|
||||
|
||||
# Systemd
|
||||
systemd = {"services": 0, "timers": 0, "failed": 0}
|
||||
systemd["services"] = int(run("systemctl list-units --type=service --no-legend 2>/dev/null | wc -l").strip() or "0")
|
||||
systemd["timers"] = int(run("systemctl list-timers --no-legend 2>/dev/null | wc -l").strip() or "0")
|
||||
systemd["failed"] = int(run("systemctl --failed --no-legend 2>/dev/null | wc -l").strip() or "0")
|
||||
|
||||
# Processes & connections
|
||||
processes = int(run("ps aux 2>/dev/null | wc -l").strip() or "0")
|
||||
connections = int(run("ss -tunp 2>/dev/null | wc -l").strip() or "0")
|
||||
|
||||
# Swap
|
||||
swap = {"used_mb": 0, "total_mb": 0}
|
||||
swap_line = run("free -m | grep Swap")
|
||||
if swap_line:
|
||||
parts = swap_line.split()
|
||||
if len(parts) >= 3:
|
||||
swap["total_mb"] = int(parts[1])
|
||||
swap["used_mb"] = int(parts[2])
|
||||
|
||||
# Cloudflared
|
||||
cloudflared = run("systemctl is-active cloudflared 2>/dev/null") == "active"
|
||||
|
||||
# Tailscale peers
|
||||
tailscale_peers = int(run("tailscale status 2>/dev/null | wc -l").strip() or "0")
|
||||
|
||||
# Hailo
|
||||
hailo = os.path.exists("/dev/hailo0")
|
||||
|
||||
# Crons (all users)
|
||||
cron_root = int(run("crontab -l 2>/dev/null | grep -cv '^#\\|^$'") or "0")
|
||||
cron_users = 0
|
||||
for u in run("ls /home/ 2>/dev/null").split():
|
||||
c = run(f"sudo crontab -u {u} -l 2>/dev/null | grep -cv '^#\\|^$'")
|
||||
cron_users += int(c) if c and c.isdigit() else 0
|
||||
|
||||
d = {
|
||||
"ollama": ollama,
|
||||
"docker": docker,
|
||||
"postgres": postgres,
|
||||
"nginx": nginx,
|
||||
"systemd": systemd,
|
||||
"processes": processes,
|
||||
"connections": connections,
|
||||
"swap": swap,
|
||||
"cloudflared": cloudflared,
|
||||
"tailscale_peers": tailscale_peers,
|
||||
"hailo": hailo,
|
||||
"crons": {"root": cron_root, "users": cron_users, "total": cron_root + cron_users},
|
||||
}
|
||||
print(json.dumps(d))
|
||||
81
collectors/services.sh
Normal file
81
collectors/services.sh
Normal file
@@ -0,0 +1,81 @@
|
||||
#!/bin/bash
|
||||
# Collect service-level KPIs from fleet: Ollama, Docker, PostgreSQL, Nginx, systemd
|
||||
|
||||
source "$(dirname "$0")/../lib/common.sh"
|
||||
set +e
|
||||
|
||||
log "Collecting service KPIs..."
|
||||
|
||||
OUT=$(snapshot_file services)
|
||||
PROBE_SCRIPT="$(dirname "$0")/services-probe.py"
|
||||
|
||||
nodes_json='{'
|
||||
first=true
|
||||
|
||||
for entry in $FLEET_NODES; do
|
||||
node=$(echo "$entry" | cut -d: -f1)
|
||||
ip=$(echo "$entry" | cut -d: -f2)
|
||||
user=$(get_ssh_user "$node")
|
||||
|
||||
log "Probing services on $node..."
|
||||
|
||||
result=$(ssh -o ConnectTimeout=3 -o ServerAliveInterval=3 -o ServerAliveCountMax=2 \
|
||||
-o StrictHostKeyChecking=no -o BatchMode=yes \
|
||||
"$user@$ip" "python3 -" < "$PROBE_SCRIPT" 2>/dev/null || echo '')
|
||||
|
||||
if [ -n "$result" ]; then
|
||||
if [ "$first" = true ]; then
|
||||
nodes_json="$nodes_json\"$node\": $result"
|
||||
first=false
|
||||
else
|
||||
nodes_json="$nodes_json, \"$node\": $result"
|
||||
fi
|
||||
ok "$node: services probed"
|
||||
else
|
||||
if [ "$first" = true ]; then
|
||||
nodes_json="$nodes_json\"$node\": {\"status\": \"offline\"}"
|
||||
first=false
|
||||
else
|
||||
nodes_json="$nodes_json, \"$node\": {\"status\": \"offline\"}"
|
||||
fi
|
||||
err "$node: offline"
|
||||
fi
|
||||
done
|
||||
|
||||
nodes_json="$nodes_json}"
|
||||
|
||||
# Aggregate
|
||||
python3 -c "
|
||||
import json
|
||||
|
||||
nodes = json.loads('''$nodes_json''')
|
||||
online = {k: v for k, v in nodes.items() if v.get('status') != 'offline'}
|
||||
|
||||
output = {
|
||||
'source': 'services',
|
||||
'collected_at': '$TIMESTAMP',
|
||||
'date': '$TODAY',
|
||||
'totals': {
|
||||
'ollama_models': sum(v.get('ollama', {}).get('count', 0) for v in online.values()),
|
||||
'ollama_size_gb': round(sum(v.get('ollama', {}).get('size_gb', 0) for v in online.values()), 1),
|
||||
'docker_containers': sum(v.get('docker', {}).get('running', 0) for v in online.values()),
|
||||
'docker_images': sum(v.get('docker', {}).get('images', 0) for v in online.values()),
|
||||
'postgres_dbs': sum(v.get('postgres', {}).get('databases', 0) for v in online.values()),
|
||||
'nginx_sites': sum(v.get('nginx', {}).get('sites', 0) for v in online.values()),
|
||||
'systemd_services': sum(v.get('systemd', {}).get('services', 0) for v in online.values()),
|
||||
'systemd_timers': sum(v.get('systemd', {}).get('timers', 0) for v in online.values()),
|
||||
'systemd_failed': sum(v.get('systemd', {}).get('failed', 0) for v in online.values()),
|
||||
'processes': sum(v.get('processes', 0) for v in online.values()),
|
||||
'network_connections': sum(v.get('connections', 0) for v in online.values()),
|
||||
'swap_used_mb': sum(v.get('swap', {}).get('used_mb', 0) for v in online.values()),
|
||||
'swap_total_mb': sum(v.get('swap', {}).get('total_mb', 0) for v in online.values()),
|
||||
'tailscale_peers': max((v.get('tailscale_peers', 0) for v in online.values()), default=0)
|
||||
},
|
||||
'nodes': nodes
|
||||
}
|
||||
|
||||
with open('$OUT', 'w') as f:
|
||||
json.dump(output, f, indent=2)
|
||||
" 2>/dev/null
|
||||
|
||||
ok "Services collected"
|
||||
@@ -1,38 +1,108 @@
|
||||
{
|
||||
"date": "2026-03-12",
|
||||
"collected_at": "2026-03-13T03:46:49Z",
|
||||
"collected_at": "2026-03-13T04:43:38Z",
|
||||
"summary": {
|
||||
"commits_today": 349,
|
||||
"commits_today": 326,
|
||||
"push_events_today": 67,
|
||||
"prs_open": 16,
|
||||
"prs_merged_today": 0,
|
||||
"prs_merged_total": 4019,
|
||||
"repos_github": 101,
|
||||
"github_events_today": 100,
|
||||
"repos_github": 102,
|
||||
"repos_gitea": 0,
|
||||
"repos_total": 101,
|
||||
"repos_total": 102,
|
||||
"repos_active": 73,
|
||||
"repos_archived": 85,
|
||||
"github_stars": 4,
|
||||
"github_forks": 0,
|
||||
"github_followers": 2,
|
||||
"github_following": 22,
|
||||
"github_open_issues": 160,
|
||||
"github_size_mb": 3748.7,
|
||||
"github_languages": {
|
||||
"Python": 26,
|
||||
"HTML": 21,
|
||||
"Dockerfile": 7,
|
||||
"Shell": 10,
|
||||
"JavaScript": 32,
|
||||
"TypeScript": 14,
|
||||
"Go": 2,
|
||||
"MDX": 1,
|
||||
"C": 2,
|
||||
"CSS": 1
|
||||
},
|
||||
"fleet_online": 3,
|
||||
"fleet_total": 0,
|
||||
"autonomy_score": 50,
|
||||
"total_loc": 7212320,
|
||||
"fleet_total": 4,
|
||||
"fleet_offline": [
|
||||
"octavia"
|
||||
],
|
||||
"avg_temp_c": 44.8,
|
||||
"throttled_nodes": [],
|
||||
"fleet_mem_used_mb": 13050,
|
||||
"fleet_mem_total_mb": 19915,
|
||||
"fleet_disk_used_gb": 159,
|
||||
"fleet_disk_total_gb": 707,
|
||||
"docker_containers": 14,
|
||||
"docker_images": 15,
|
||||
"ollama_models": 27,
|
||||
"avg_temp_c": 43.3,
|
||||
"ollama_size_gb": 48.1,
|
||||
"postgres_dbs": 11,
|
||||
"nginx_sites": 48,
|
||||
"systemd_services": 256,
|
||||
"systemd_timers": 35,
|
||||
"failed_units": 12,
|
||||
"throttled_nodes": []
|
||||
"fleet_processes": 867,
|
||||
"fleet_connections": 106,
|
||||
"fleet_swap_used_mb": 4704,
|
||||
"fleet_swap_total_mb": 10849,
|
||||
"tailscale_peers": 9,
|
||||
"autonomy_score": 50,
|
||||
"heal_events_today": 0,
|
||||
"service_restarts_today": 0,
|
||||
"fleet_cron_jobs": 0,
|
||||
"fleet_timers": 0,
|
||||
"max_uptime_days": 0,
|
||||
"total_loc": 7212320,
|
||||
"local_repos": 73,
|
||||
"local_files": 1723,
|
||||
"local_scripts": 300,
|
||||
"local_script_lines": 576887,
|
||||
"bin_tools": 212,
|
||||
"bin_size_mb": 121,
|
||||
"home_scripts": 91,
|
||||
"templates": 75,
|
||||
"sqlite_dbs": 230,
|
||||
"blackroad_dir_mb": 1390,
|
||||
"fts5_entries": 0,
|
||||
"systems_registered": 111,
|
||||
"brew_packages": 293,
|
||||
"pip_packages": 35,
|
||||
"npm_global_packages": 14,
|
||||
"mac_cron_jobs": 17,
|
||||
"local_git_repos": 12,
|
||||
"mac_disk_pct": 16,
|
||||
"mac_disk_used_gb": 12,
|
||||
"mac_processes": 526,
|
||||
"cf_d1_databases": 22,
|
||||
"cf_kv_namespaces": 46,
|
||||
"cf_r2_buckets": 11,
|
||||
"cf_pages": 99,
|
||||
"cf_d1_size_kb": 40708
|
||||
},
|
||||
"sources": {
|
||||
"loc": {
|
||||
"source": "loc",
|
||||
"collected_at": "2026-03-13T03:47:07Z",
|
||||
"collected_at": "2026-03-13T04:44:06Z",
|
||||
"date": "2026-03-12",
|
||||
"local": {
|
||||
"total_code_lines": 4608051,
|
||||
"repos": 73,
|
||||
"files": 1723,
|
||||
"scripts": 298,
|
||||
"script_lines": 575777
|
||||
"scripts": 300,
|
||||
"script_lines": 576887
|
||||
},
|
||||
"projects": {
|
||||
"blackroad-os-kpis": 1226,
|
||||
"blackroad-os-kpis": 2953,
|
||||
"images-blackroad": 2562,
|
||||
"roadnet": 5064
|
||||
},
|
||||
@@ -46,15 +116,15 @@
|
||||
},
|
||||
"github": {
|
||||
"source": "github",
|
||||
"collected_at": "2026-03-13T03:46:49Z",
|
||||
"collected_at": "2026-03-13T04:43:38Z",
|
||||
"date": "2026-03-12",
|
||||
"repos": {
|
||||
"total": 101,
|
||||
"total": 102,
|
||||
"total_size_mb": 2650.9,
|
||||
"languages": {
|
||||
"Python": 23,
|
||||
"HTML": 22,
|
||||
"Shell": 9,
|
||||
"Shell": 10,
|
||||
"TypeScript": 8,
|
||||
"JavaScript": 7,
|
||||
"Dockerfile": 6,
|
||||
@@ -63,8 +133,8 @@
|
||||
}
|
||||
},
|
||||
"commits": {
|
||||
"today": 349,
|
||||
"push_events_today": 68
|
||||
"today": 326,
|
||||
"push_events_today": 67
|
||||
},
|
||||
"pull_requests": {
|
||||
"open": 16,
|
||||
@@ -77,7 +147,7 @@
|
||||
},
|
||||
"autonomy": {
|
||||
"source": "autonomy",
|
||||
"collected_at": "2026-03-13T03:47:03Z",
|
||||
"collected_at": "2026-03-13T04:44:03Z",
|
||||
"date": "2026-03-12",
|
||||
"autonomy_score": 50,
|
||||
"totals": {
|
||||
@@ -94,9 +164,431 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"source": "services",
|
||||
"collected_at": "2026-03-13T04:43:55Z",
|
||||
"date": "2026-03-12",
|
||||
"totals": {
|
||||
"ollama_models": 27,
|
||||
"ollama_size_gb": 48.1,
|
||||
"docker_containers": 14,
|
||||
"docker_images": 15,
|
||||
"postgres_dbs": 11,
|
||||
"nginx_sites": 48,
|
||||
"systemd_services": 256,
|
||||
"systemd_timers": 35,
|
||||
"systemd_failed": 12,
|
||||
"processes": 867,
|
||||
"network_connections": 106,
|
||||
"swap_used_mb": 4704,
|
||||
"swap_total_mb": 10849,
|
||||
"tailscale_peers": 9
|
||||
},
|
||||
"nodes": {
|
||||
"alice": {
|
||||
"ollama": {
|
||||
"count": 6,
|
||||
"size_gb": 10.1,
|
||||
"models": [
|
||||
"qwen2.5:3b",
|
||||
"nomic-embed-text:latest",
|
||||
"lucidia:latest",
|
||||
"llama3.2:1b",
|
||||
"tinyllama:latest",
|
||||
"qwen2.5:1.5b"
|
||||
]
|
||||
},
|
||||
"docker": {
|
||||
"running": 0,
|
||||
"images": 0,
|
||||
"containers_total": 0,
|
||||
"names": []
|
||||
},
|
||||
"postgres": {
|
||||
"databases": 4
|
||||
},
|
||||
"nginx": {
|
||||
"sites": 30,
|
||||
"active": true
|
||||
},
|
||||
"systemd": {
|
||||
"services": 87,
|
||||
"timers": 11,
|
||||
"failed": 3
|
||||
},
|
||||
"processes": 226,
|
||||
"connections": 13,
|
||||
"swap": {
|
||||
"used_mb": 0,
|
||||
"total_mb": 99
|
||||
},
|
||||
"cloudflared": true,
|
||||
"tailscale_peers": 0,
|
||||
"hailo": false,
|
||||
"crons": {
|
||||
"root": 5,
|
||||
"users": 8,
|
||||
"total": 13
|
||||
}
|
||||
},
|
||||
"cecilia": {
|
||||
"ollama": {
|
||||
"count": 15,
|
||||
"size_gb": 27.9,
|
||||
"models": [
|
||||
"deepseek-r1:1.5b",
|
||||
"nomic-embed-text:latest",
|
||||
"hf.co/mradermacher/OpenELM-1_1B-Instruct-GGUF:Q4_K_M",
|
||||
"hf.co/mradermacher/OpenELM-3B-Instruct-GGUF:Q4_K_M",
|
||||
"cece2:latest",
|
||||
"qwen3:8b",
|
||||
"llama3:8b-instruct-q4_K_M",
|
||||
"cece:latest",
|
||||
"deepseek-coder:1.3b",
|
||||
"qwen2.5-coder:3b",
|
||||
"llama3.2:3b",
|
||||
"tinyllama:latest",
|
||||
"llama3.2:latest",
|
||||
"codellama:7b",
|
||||
"llama3.2:1b"
|
||||
]
|
||||
},
|
||||
"docker": {
|
||||
"running": 0,
|
||||
"images": 0,
|
||||
"containers_total": 0,
|
||||
"names": []
|
||||
},
|
||||
"postgres": {
|
||||
"databases": 3
|
||||
},
|
||||
"nginx": {
|
||||
"sites": 15,
|
||||
"active": false
|
||||
},
|
||||
"systemd": {
|
||||
"services": 80,
|
||||
"timers": 11,
|
||||
"failed": 5
|
||||
},
|
||||
"processes": 254,
|
||||
"connections": 34,
|
||||
"swap": {
|
||||
"used_mb": 2039,
|
||||
"total_mb": 2047
|
||||
},
|
||||
"cloudflared": true,
|
||||
"tailscale_peers": 0,
|
||||
"hailo": true,
|
||||
"crons": {
|
||||
"root": 12,
|
||||
"users": 14,
|
||||
"total": 26
|
||||
}
|
||||
},
|
||||
"octavia": {
|
||||
"status": "offline"
|
||||
},
|
||||
"lucidia": {
|
||||
"ollama": {
|
||||
"count": 6,
|
||||
"size_gb": 10.1,
|
||||
"models": [
|
||||
"qwen2.5:3b",
|
||||
"nomic-embed-text:latest",
|
||||
"lucidia:latest",
|
||||
"llama3.2:1b",
|
||||
"tinyllama:latest",
|
||||
"qwen2.5:1.5b"
|
||||
]
|
||||
},
|
||||
"docker": {
|
||||
"running": 14,
|
||||
"images": 15,
|
||||
"containers_total": 15,
|
||||
"names": [
|
||||
"blackroad-gitea",
|
||||
"road-pdns-admin",
|
||||
"road-pdns",
|
||||
"road-dns-db",
|
||||
"roadauth",
|
||||
"roadapi",
|
||||
"blackroad-edge-agent",
|
||||
"blackroad.systems",
|
||||
"blackroadai.com",
|
||||
"blackroad-auth-gateway",
|
||||
"blackroad-metaverse",
|
||||
"blackroad-os",
|
||||
"blackroad-os-carpool",
|
||||
"pi-my-agent-1"
|
||||
]
|
||||
},
|
||||
"postgres": {
|
||||
"databases": 4
|
||||
},
|
||||
"nginx": {
|
||||
"sites": 3,
|
||||
"active": true
|
||||
},
|
||||
"systemd": {
|
||||
"services": 89,
|
||||
"timers": 13,
|
||||
"failed": 4
|
||||
},
|
||||
"processes": 387,
|
||||
"connections": 59,
|
||||
"swap": {
|
||||
"used_mb": 2665,
|
||||
"total_mb": 8703
|
||||
},
|
||||
"cloudflared": true,
|
||||
"tailscale_peers": 9,
|
||||
"hailo": false,
|
||||
"crons": {
|
||||
"root": 11,
|
||||
"users": 21,
|
||||
"total": 32
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cloudflare": {
|
||||
"source": "cloudflare",
|
||||
"collected_at": "2026-03-13T04:44:34Z",
|
||||
"date": "2026-03-12",
|
||||
"d1": {
|
||||
"count": 22,
|
||||
"total_size_kb": 40708,
|
||||
"databases": [
|
||||
{
|
||||
"name": "blackroad-auth",
|
||||
"uuid": "761ccc7a-f2b5-43d5-b0df-aeedc212d382"
|
||||
},
|
||||
{
|
||||
"name": "images-blackroad",
|
||||
"uuid": "98ddb91d-4705-4531-969e-a0b3fb8a4c57"
|
||||
},
|
||||
{
|
||||
"name": "index-blackroad",
|
||||
"uuid": "5599c9ac-5bb9-430a-9743-c32d873b9e78"
|
||||
},
|
||||
{
|
||||
"name": "blackboard",
|
||||
"uuid": "bcc78f33-b052-4cb2-bcfb-db5cd3c08472"
|
||||
},
|
||||
{
|
||||
"name": "openapi-template-db",
|
||||
"uuid": "4c14af7a-9ddf-44fd-a67a-21585d5e2101"
|
||||
},
|
||||
{
|
||||
"name": "blackroad-verification",
|
||||
"uuid": "e781869d-962c-459d-91c3-f0edbf111815"
|
||||
},
|
||||
{
|
||||
"name": "blackroad-db",
|
||||
"uuid": "b768c5de-b9a3-4337-8c26-b2e9ff230829"
|
||||
},
|
||||
{
|
||||
"name": "blackroad-billing",
|
||||
"uuid": "147604cc-6c0e-45e4-985b-3b3fd19f688b"
|
||||
},
|
||||
{
|
||||
"name": "blackroad-api-gateway",
|
||||
"uuid": "16353ffd-17fa-4c5b-95b7-b02a4cd3d228"
|
||||
},
|
||||
{
|
||||
"name": "blackroad-analytics-db",
|
||||
"uuid": "3175e028-d45a-4d98-9675-8de70c49fc7f"
|
||||
},
|
||||
{
|
||||
"name": "blackroad-memory-db",
|
||||
"uuid": "1f981017-629b-41cb-a4fb-42cebee9f17e"
|
||||
},
|
||||
{
|
||||
"name": "blackroad-agents-db",
|
||||
"uuid": "2b17625c-4eb3-4c2e-8134-cb617a41ec7d"
|
||||
},
|
||||
{
|
||||
"name": "blackroad-dialer",
|
||||
"uuid": "38337a08-6de3-4688-8daf-f2b0c0d40131"
|
||||
},
|
||||
{
|
||||
"name": "blackroad-repos",
|
||||
"uuid": "324e793e-20c6-4917-b034-ef0ee86e6760"
|
||||
},
|
||||
{
|
||||
"name": "blackroad-registry",
|
||||
"uuid": "9acf402f-6338-41e9-b909-a0317ea5e8bc"
|
||||
},
|
||||
{
|
||||
"name": "blackroad-continuity",
|
||||
"uuid": "f0721506-cb52-41ee-b587-38f7b42b97d9"
|
||||
},
|
||||
{
|
||||
"name": "lucidia-world",
|
||||
"uuid": "aa8ac8d2-cc7f-4718-a15b-e7e39586a0ce"
|
||||
},
|
||||
{
|
||||
"name": "blackroad-saas",
|
||||
"uuid": "c7bec6d8-42fa-49fb-9d8c-57d626dde6b9"
|
||||
},
|
||||
{
|
||||
"name": "apollo-agent-registry",
|
||||
"uuid": "79f8b80d-3bb5-4dd4-beee-a77a1084b574"
|
||||
},
|
||||
{
|
||||
"name": "blackroad_revenue",
|
||||
"uuid": "8744905a-cf6c-4e16-9661-4c67d340813f"
|
||||
},
|
||||
{
|
||||
"name": "blackroad-logs",
|
||||
"uuid": "2bea6826-d4cb-4877-8d78-aa7a8fd3c1b0"
|
||||
},
|
||||
{
|
||||
"name": "blackroad-os-main",
|
||||
"uuid": "e2c6dcd9-c21a-48ac-8807-7b3a6881c4f7"
|
||||
}
|
||||
]
|
||||
},
|
||||
"kv": {
|
||||
"count": 46
|
||||
},
|
||||
"r2": {
|
||||
"count": 11
|
||||
},
|
||||
"pages": {
|
||||
"count": 99
|
||||
},
|
||||
"account_id": "848cf0b18d51e0170e0d1537aec3505a"
|
||||
},
|
||||
"github-deep": {
|
||||
"source": "github-deep",
|
||||
"collected_at": "2026-03-13T04:43:45Z",
|
||||
"date": "2026-03-12",
|
||||
"profile": {
|
||||
"followers": 2,
|
||||
"following": 22,
|
||||
"public_repos": 158,
|
||||
"public_gists": 1
|
||||
},
|
||||
"repos": {
|
||||
"total_stars": 4,
|
||||
"total_forks": 0,
|
||||
"total_watchers": 4,
|
||||
"total_size_mb": 3748.7,
|
||||
"total_open_issues": 160,
|
||||
"archived": 85,
|
||||
"active": 73,
|
||||
"languages": {
|
||||
"Python": 26,
|
||||
"HTML": 21,
|
||||
"Dockerfile": 7,
|
||||
"Shell": 10,
|
||||
"JavaScript": 32,
|
||||
"TypeScript": 14,
|
||||
"Go": 2,
|
||||
"MDX": 1,
|
||||
"C": 2,
|
||||
"CSS": 1
|
||||
},
|
||||
"top_10_recent": [
|
||||
"blackboxprogramming/blackroad-os-kpis",
|
||||
"blackboxprogramming/pi-mono",
|
||||
"blackboxprogramming/system-prompts-and-models-of-ai-tools",
|
||||
"blackboxprogramming/openclaw",
|
||||
"blackboxprogramming/skills",
|
||||
"blackboxprogramming/OpenSandbox",
|
||||
"blackboxprogramming/OpenViking",
|
||||
"blackboxprogramming/rowboat",
|
||||
"blackboxprogramming/learn-claude-code",
|
||||
"blackboxprogramming/superpowers"
|
||||
],
|
||||
"top_10_largest_mb": [
|
||||
{
|
||||
"blackboxprogramming/openapi-generator": 876.1
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/docs": 694.2
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/blackroad": 385.9
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/hindsight": 344.7
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/git": 276.8
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/openclaw": 276.6
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/A2UI": 122.8
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/clerk-docs": 91.1
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/OpenSandbox": 78.2
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/rowboat": 76.1
|
||||
}
|
||||
]
|
||||
},
|
||||
"orgs": {
|
||||
"Blackbox-Enterprises": {
|
||||
"repos": 8,
|
||||
"members": 1
|
||||
},
|
||||
"blackroad-os-inc": {
|
||||
"repos": 22,
|
||||
"members": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"local": {
|
||||
"source": "local",
|
||||
"collected_at": "2026-03-13T04:44:10Z",
|
||||
"date": "2026-03-12",
|
||||
"scripts": {
|
||||
"bin_tools": 212,
|
||||
"bin_size_mb": 121,
|
||||
"home_scripts": 91,
|
||||
"templates": 75
|
||||
},
|
||||
"databases": {
|
||||
"sqlite_count": 230,
|
||||
"blackroad_dir_mb": 1390,
|
||||
"fts5_entries": 0,
|
||||
"systems_registered": 111
|
||||
},
|
||||
"packages": {
|
||||
"homebrew": 293,
|
||||
"pip3": 35,
|
||||
"npm_global": 14
|
||||
},
|
||||
"automation": {
|
||||
"cron_jobs": 17,
|
||||
"local_git_repos": 12
|
||||
},
|
||||
"disk": {
|
||||
"used_gb": 12,
|
||||
"total_gb": 460,
|
||||
"pct": 16
|
||||
},
|
||||
"system": {
|
||||
"processes": 526,
|
||||
"net_connections": 40
|
||||
},
|
||||
"files": {
|
||||
"downloads": 94,
|
||||
"documents": 4
|
||||
}
|
||||
},
|
||||
"fleet": {
|
||||
"source": "fleet",
|
||||
"collected_at": "2026-03-13T03:47:00Z",
|
||||
"collected_at": "2026-03-13T04:43:53Z",
|
||||
"date": "2026-03-12",
|
||||
"fleet": {
|
||||
"total_nodes": 4,
|
||||
@@ -107,8 +599,8 @@
|
||||
]
|
||||
},
|
||||
"totals": {
|
||||
"cpu_avg_temp_c": 43.3,
|
||||
"mem_used_mb": 13130,
|
||||
"cpu_avg_temp_c": 44.8,
|
||||
"mem_used_mb": 13050,
|
||||
"mem_total_mb": 19915,
|
||||
"disk_used_gb": 159,
|
||||
"disk_total_gb": 707,
|
||||
@@ -120,12 +612,12 @@
|
||||
"nodes": [
|
||||
{
|
||||
"hostname": "alice",
|
||||
"uptime_seconds": 113325,
|
||||
"load_1m": 0.84,
|
||||
"load_5m": 1.88,
|
||||
"uptime_seconds": 116737,
|
||||
"load_1m": 0.82,
|
||||
"load_5m": 1.13,
|
||||
"cpu_temp": 34563,
|
||||
"mem_total_mb": 3794,
|
||||
"mem_used_mb": 360,
|
||||
"mem_used_mb": 363,
|
||||
"disk_total_gb": 15,
|
||||
"disk_used_gb": 11,
|
||||
"disk_pct": 76,
|
||||
@@ -136,19 +628,19 @@
|
||||
"throttle_hex": "0x0",
|
||||
"governor": "ondemand",
|
||||
"cpu_temp_c": 34.6,
|
||||
"mem_pct": 9.5,
|
||||
"mem_pct": 9.6,
|
||||
"status": "online",
|
||||
"node": "alice",
|
||||
"ip": "192.168.4.49"
|
||||
},
|
||||
{
|
||||
"hostname": "cecilia",
|
||||
"uptime_seconds": 113411,
|
||||
"load_1m": 0.29,
|
||||
"load_5m": 0.39,
|
||||
"uptime_seconds": 116823,
|
||||
"load_1m": 1.11,
|
||||
"load_5m": 0.63,
|
||||
"cpu_temp": 38050,
|
||||
"mem_total_mb": 8062,
|
||||
"mem_used_mb": 7306,
|
||||
"mem_used_mb": 7310,
|
||||
"disk_total_gb": 457,
|
||||
"disk_used_gb": 76,
|
||||
"disk_pct": 18,
|
||||
@@ -159,7 +651,7 @@
|
||||
"throttle_hex": "unknown",
|
||||
"governor": "conservative",
|
||||
"cpu_temp_c": 38.0,
|
||||
"mem_pct": 90.6,
|
||||
"mem_pct": 90.7,
|
||||
"status": "online",
|
||||
"node": "cecilia",
|
||||
"ip": "192.168.4.96"
|
||||
@@ -171,12 +663,12 @@
|
||||
},
|
||||
{
|
||||
"hostname": "octavia",
|
||||
"uptime_seconds": 113380,
|
||||
"load_1m": 14.11,
|
||||
"load_5m": 7.17,
|
||||
"cpu_temp": 57300,
|
||||
"uptime_seconds": 116791,
|
||||
"load_1m": 3.58,
|
||||
"load_5m": 2.87,
|
||||
"cpu_temp": 61700,
|
||||
"mem_total_mb": 8059,
|
||||
"mem_used_mb": 5464,
|
||||
"mem_used_mb": 5377,
|
||||
"disk_total_gb": 235,
|
||||
"disk_used_gb": 72,
|
||||
"disk_pct": 33,
|
||||
@@ -186,8 +678,8 @@
|
||||
"ollama_models": 6,
|
||||
"throttle_hex": "unknown",
|
||||
"governor": "ondemand",
|
||||
"cpu_temp_c": 57.3,
|
||||
"mem_pct": 67.8,
|
||||
"cpu_temp_c": 61.7,
|
||||
"mem_pct": 66.7,
|
||||
"status": "online",
|
||||
"node": "lucidia",
|
||||
"ip": "192.168.4.38"
|
||||
@@ -196,7 +688,7 @@
|
||||
},
|
||||
"gitea": {
|
||||
"source": "gitea",
|
||||
"collected_at": "2026-03-13T03:46:55Z",
|
||||
"collected_at": "2026-03-13T04:43:48Z",
|
||||
"date": "2026-03-12",
|
||||
"status": "unreachable",
|
||||
"repos": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"source": "autonomy",
|
||||
"collected_at": "2026-03-13T03:47:03Z",
|
||||
"collected_at": "2026-03-13T04:44:03Z",
|
||||
"date": "2026-03-12",
|
||||
"autonomy_score": 50,
|
||||
"totals": {
|
||||
|
||||
20
data/snapshots/2026-03-12-cloudflare.json
Normal file
20
data/snapshots/2026-03-12-cloudflare.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"source": "cloudflare",
|
||||
"collected_at": "2026-03-13T04:44:34Z",
|
||||
"date": "2026-03-12",
|
||||
"d1": {
|
||||
"count": 22,
|
||||
"total_size_kb": 40708,
|
||||
"databases": [{"name": "blackroad-auth", "uuid": "761ccc7a-f2b5-43d5-b0df-aeedc212d382"}, {"name": "images-blackroad", "uuid": "98ddb91d-4705-4531-969e-a0b3fb8a4c57"}, {"name": "index-blackroad", "uuid": "5599c9ac-5bb9-430a-9743-c32d873b9e78"}, {"name": "blackboard", "uuid": "bcc78f33-b052-4cb2-bcfb-db5cd3c08472"}, {"name": "openapi-template-db", "uuid": "4c14af7a-9ddf-44fd-a67a-21585d5e2101"}, {"name": "blackroad-verification", "uuid": "e781869d-962c-459d-91c3-f0edbf111815"}, {"name": "blackroad-db", "uuid": "b768c5de-b9a3-4337-8c26-b2e9ff230829"}, {"name": "blackroad-billing", "uuid": "147604cc-6c0e-45e4-985b-3b3fd19f688b"}, {"name": "blackroad-api-gateway", "uuid": "16353ffd-17fa-4c5b-95b7-b02a4cd3d228"}, {"name": "blackroad-analytics-db", "uuid": "3175e028-d45a-4d98-9675-8de70c49fc7f"}, {"name": "blackroad-memory-db", "uuid": "1f981017-629b-41cb-a4fb-42cebee9f17e"}, {"name": "blackroad-agents-db", "uuid": "2b17625c-4eb3-4c2e-8134-cb617a41ec7d"}, {"name": "blackroad-dialer", "uuid": "38337a08-6de3-4688-8daf-f2b0c0d40131"}, {"name": "blackroad-repos", "uuid": "324e793e-20c6-4917-b034-ef0ee86e6760"}, {"name": "blackroad-registry", "uuid": "9acf402f-6338-41e9-b909-a0317ea5e8bc"}, {"name": "blackroad-continuity", "uuid": "f0721506-cb52-41ee-b587-38f7b42b97d9"}, {"name": "lucidia-world", "uuid": "aa8ac8d2-cc7f-4718-a15b-e7e39586a0ce"}, {"name": "blackroad-saas", "uuid": "c7bec6d8-42fa-49fb-9d8c-57d626dde6b9"}, {"name": "apollo-agent-registry", "uuid": "79f8b80d-3bb5-4dd4-beee-a77a1084b574"}, {"name": "blackroad_revenue", "uuid": "8744905a-cf6c-4e16-9661-4c67d340813f"}, {"name": "blackroad-logs", "uuid": "2bea6826-d4cb-4877-8d78-aa7a8fd3c1b0"}, {"name": "blackroad-os-main", "uuid": "e2c6dcd9-c21a-48ac-8807-7b3a6881c4f7"}]
|
||||
},
|
||||
"kv": {
|
||||
"count": 46
|
||||
},
|
||||
"r2": {
|
||||
"count": 11
|
||||
},
|
||||
"pages": {
|
||||
"count": 99
|
||||
},
|
||||
"account_id": "848cf0b18d51e0170e0d1537aec3505a"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"source": "fleet",
|
||||
"collected_at": "2026-03-13T03:47:00Z",
|
||||
"collected_at": "2026-03-13T04:43:53Z",
|
||||
"date": "2026-03-12",
|
||||
"fleet": {
|
||||
"total_nodes": 4,
|
||||
@@ -11,8 +11,8 @@
|
||||
]
|
||||
},
|
||||
"totals": {
|
||||
"cpu_avg_temp_c": 43.3,
|
||||
"mem_used_mb": 13130,
|
||||
"cpu_avg_temp_c": 44.8,
|
||||
"mem_used_mb": 13050,
|
||||
"mem_total_mb": 19915,
|
||||
"disk_used_gb": 159,
|
||||
"disk_total_gb": 707,
|
||||
@@ -24,12 +24,12 @@
|
||||
"nodes": [
|
||||
{
|
||||
"hostname": "alice",
|
||||
"uptime_seconds": 113325,
|
||||
"load_1m": 0.84,
|
||||
"load_5m": 1.88,
|
||||
"uptime_seconds": 116737,
|
||||
"load_1m": 0.82,
|
||||
"load_5m": 1.13,
|
||||
"cpu_temp": 34563,
|
||||
"mem_total_mb": 3794,
|
||||
"mem_used_mb": 360,
|
||||
"mem_used_mb": 363,
|
||||
"disk_total_gb": 15,
|
||||
"disk_used_gb": 11,
|
||||
"disk_pct": 76,
|
||||
@@ -40,19 +40,19 @@
|
||||
"throttle_hex": "0x0",
|
||||
"governor": "ondemand",
|
||||
"cpu_temp_c": 34.6,
|
||||
"mem_pct": 9.5,
|
||||
"mem_pct": 9.6,
|
||||
"status": "online",
|
||||
"node": "alice",
|
||||
"ip": "192.168.4.49"
|
||||
},
|
||||
{
|
||||
"hostname": "cecilia",
|
||||
"uptime_seconds": 113411,
|
||||
"load_1m": 0.29,
|
||||
"load_5m": 0.39,
|
||||
"uptime_seconds": 116823,
|
||||
"load_1m": 1.11,
|
||||
"load_5m": 0.63,
|
||||
"cpu_temp": 38050,
|
||||
"mem_total_mb": 8062,
|
||||
"mem_used_mb": 7306,
|
||||
"mem_used_mb": 7310,
|
||||
"disk_total_gb": 457,
|
||||
"disk_used_gb": 76,
|
||||
"disk_pct": 18,
|
||||
@@ -63,7 +63,7 @@
|
||||
"throttle_hex": "unknown",
|
||||
"governor": "conservative",
|
||||
"cpu_temp_c": 38.0,
|
||||
"mem_pct": 90.6,
|
||||
"mem_pct": 90.7,
|
||||
"status": "online",
|
||||
"node": "cecilia",
|
||||
"ip": "192.168.4.96"
|
||||
@@ -75,12 +75,12 @@
|
||||
},
|
||||
{
|
||||
"hostname": "octavia",
|
||||
"uptime_seconds": 113380,
|
||||
"load_1m": 14.11,
|
||||
"load_5m": 7.17,
|
||||
"cpu_temp": 57300,
|
||||
"uptime_seconds": 116791,
|
||||
"load_1m": 3.58,
|
||||
"load_5m": 2.87,
|
||||
"cpu_temp": 61700,
|
||||
"mem_total_mb": 8059,
|
||||
"mem_used_mb": 5464,
|
||||
"mem_used_mb": 5377,
|
||||
"disk_total_gb": 235,
|
||||
"disk_used_gb": 72,
|
||||
"disk_pct": 33,
|
||||
@@ -90,8 +90,8 @@
|
||||
"ollama_models": 6,
|
||||
"throttle_hex": "unknown",
|
||||
"governor": "ondemand",
|
||||
"cpu_temp_c": 57.3,
|
||||
"mem_pct": 67.8,
|
||||
"cpu_temp_c": 61.7,
|
||||
"mem_pct": 66.7,
|
||||
"status": "online",
|
||||
"node": "lucidia",
|
||||
"ip": "192.168.4.38"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"source": "gitea",
|
||||
"collected_at": "2026-03-13T03:46:55Z",
|
||||
"collected_at": "2026-03-13T04:43:48Z",
|
||||
"date": "2026-03-12",
|
||||
"status": "unreachable",
|
||||
"repos": { "total": 0 },
|
||||
|
||||
86
data/snapshots/2026-03-12-github-deep.json
Normal file
86
data/snapshots/2026-03-12-github-deep.json
Normal file
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"source": "github-deep",
|
||||
"collected_at": "2026-03-13T04:43:45Z",
|
||||
"date": "2026-03-12",
|
||||
"profile": {
|
||||
"followers": 2,
|
||||
"following": 22,
|
||||
"public_repos": 158,
|
||||
"public_gists": 1
|
||||
},
|
||||
"repos": {
|
||||
"total_stars": 4,
|
||||
"total_forks": 0,
|
||||
"total_watchers": 4,
|
||||
"total_size_mb": 3748.7,
|
||||
"total_open_issues": 160,
|
||||
"archived": 85,
|
||||
"active": 73,
|
||||
"languages": {
|
||||
"Python": 26,
|
||||
"HTML": 21,
|
||||
"Dockerfile": 7,
|
||||
"Shell": 10,
|
||||
"JavaScript": 32,
|
||||
"TypeScript": 14,
|
||||
"Go": 2,
|
||||
"MDX": 1,
|
||||
"C": 2,
|
||||
"CSS": 1
|
||||
},
|
||||
"top_10_recent": [
|
||||
"blackboxprogramming/blackroad-os-kpis",
|
||||
"blackboxprogramming/pi-mono",
|
||||
"blackboxprogramming/system-prompts-and-models-of-ai-tools",
|
||||
"blackboxprogramming/openclaw",
|
||||
"blackboxprogramming/skills",
|
||||
"blackboxprogramming/OpenSandbox",
|
||||
"blackboxprogramming/OpenViking",
|
||||
"blackboxprogramming/rowboat",
|
||||
"blackboxprogramming/learn-claude-code",
|
||||
"blackboxprogramming/superpowers"
|
||||
],
|
||||
"top_10_largest_mb": [
|
||||
{
|
||||
"blackboxprogramming/openapi-generator": 876.1
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/docs": 694.2
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/blackroad": 385.9
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/hindsight": 344.7
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/git": 276.8
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/openclaw": 276.6
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/A2UI": 122.8
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/clerk-docs": 91.1
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/OpenSandbox": 78.2
|
||||
},
|
||||
{
|
||||
"blackboxprogramming/rowboat": 76.1
|
||||
}
|
||||
]
|
||||
},
|
||||
"orgs": {
|
||||
"Blackbox-Enterprises": {
|
||||
"repos": 8,
|
||||
"members": 1
|
||||
},
|
||||
"blackroad-os-inc": {
|
||||
"repos": 22,
|
||||
"members": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"source": "github",
|
||||
"collected_at": "2026-03-13T03:46:49Z",
|
||||
"collected_at": "2026-03-13T04:43:38Z",
|
||||
"date": "2026-03-12",
|
||||
"repos": {
|
||||
"total": 101,
|
||||
"total": 102,
|
||||
"total_size_mb": 2650.9,
|
||||
"languages": {"Python": 23, "HTML": 22, "Shell": 9, "TypeScript": 8, "JavaScript": 7, "Dockerfile": 6, "Go": 2, "CSS": 1}
|
||||
"languages": {"Python": 23, "HTML": 22, "Shell": 10, "TypeScript": 8, "JavaScript": 7, "Dockerfile": 6, "Go": 2, "CSS": 1}
|
||||
},
|
||||
"commits": {
|
||||
"today": 349,
|
||||
"push_events_today": 68
|
||||
"today": 326,
|
||||
"push_events_today": 67
|
||||
},
|
||||
"pull_requests": {
|
||||
"open": 16,
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"source": "loc",
|
||||
"collected_at": "2026-03-13T03:47:07Z",
|
||||
"collected_at": "2026-03-13T04:44:06Z",
|
||||
"date": "2026-03-12",
|
||||
"local": {
|
||||
"total_code_lines": 4608051,
|
||||
"repos": 73,
|
||||
"files": 1723,
|
||||
"scripts": 298,
|
||||
"script_lines": 575777
|
||||
"scripts": 300,
|
||||
"script_lines": 576887
|
||||
},
|
||||
"projects": {
|
||||
"blackroad-os-kpis": 1226,
|
||||
"blackroad-os-kpis": 2953,
|
||||
"images-blackroad": 2562,
|
||||
"roadnet": 5064
|
||||
},
|
||||
|
||||
39
data/snapshots/2026-03-12-local.json
Normal file
39
data/snapshots/2026-03-12-local.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"source": "local",
|
||||
"collected_at": "2026-03-13T04:44:10Z",
|
||||
"date": "2026-03-12",
|
||||
"scripts": {
|
||||
"bin_tools": 212,
|
||||
"bin_size_mb": 121,
|
||||
"home_scripts": 91,
|
||||
"templates": 75
|
||||
},
|
||||
"databases": {
|
||||
"sqlite_count": 230,
|
||||
"blackroad_dir_mb": 1390,
|
||||
"fts5_entries": 0,
|
||||
"systems_registered": 111
|
||||
},
|
||||
"packages": {
|
||||
"homebrew": 293,
|
||||
"pip3": 35,
|
||||
"npm_global": 14
|
||||
},
|
||||
"automation": {
|
||||
"cron_jobs": 17,
|
||||
"local_git_repos": 12
|
||||
},
|
||||
"disk": {
|
||||
"used_gb": 12,
|
||||
"total_gb": 460,
|
||||
"pct": 16
|
||||
},
|
||||
"system": {
|
||||
"processes": 526,
|
||||
"net_connections": 40
|
||||
},
|
||||
"files": {
|
||||
"downloads": 94,
|
||||
"documents": 4
|
||||
}
|
||||
}
|
||||
188
data/snapshots/2026-03-12-services.json
Normal file
188
data/snapshots/2026-03-12-services.json
Normal file
@@ -0,0 +1,188 @@
|
||||
{
|
||||
"source": "services",
|
||||
"collected_at": "2026-03-13T04:43:55Z",
|
||||
"date": "2026-03-12",
|
||||
"totals": {
|
||||
"ollama_models": 27,
|
||||
"ollama_size_gb": 48.1,
|
||||
"docker_containers": 14,
|
||||
"docker_images": 15,
|
||||
"postgres_dbs": 11,
|
||||
"nginx_sites": 48,
|
||||
"systemd_services": 256,
|
||||
"systemd_timers": 35,
|
||||
"systemd_failed": 12,
|
||||
"processes": 867,
|
||||
"network_connections": 106,
|
||||
"swap_used_mb": 4704,
|
||||
"swap_total_mb": 10849,
|
||||
"tailscale_peers": 9
|
||||
},
|
||||
"nodes": {
|
||||
"alice": {
|
||||
"ollama": {
|
||||
"count": 6,
|
||||
"size_gb": 10.1,
|
||||
"models": [
|
||||
"qwen2.5:3b",
|
||||
"nomic-embed-text:latest",
|
||||
"lucidia:latest",
|
||||
"llama3.2:1b",
|
||||
"tinyllama:latest",
|
||||
"qwen2.5:1.5b"
|
||||
]
|
||||
},
|
||||
"docker": {
|
||||
"running": 0,
|
||||
"images": 0,
|
||||
"containers_total": 0,
|
||||
"names": []
|
||||
},
|
||||
"postgres": {
|
||||
"databases": 4
|
||||
},
|
||||
"nginx": {
|
||||
"sites": 30,
|
||||
"active": true
|
||||
},
|
||||
"systemd": {
|
||||
"services": 87,
|
||||
"timers": 11,
|
||||
"failed": 3
|
||||
},
|
||||
"processes": 226,
|
||||
"connections": 13,
|
||||
"swap": {
|
||||
"used_mb": 0,
|
||||
"total_mb": 99
|
||||
},
|
||||
"cloudflared": true,
|
||||
"tailscale_peers": 0,
|
||||
"hailo": false,
|
||||
"crons": {
|
||||
"root": 5,
|
||||
"users": 8,
|
||||
"total": 13
|
||||
}
|
||||
},
|
||||
"cecilia": {
|
||||
"ollama": {
|
||||
"count": 15,
|
||||
"size_gb": 27.9,
|
||||
"models": [
|
||||
"deepseek-r1:1.5b",
|
||||
"nomic-embed-text:latest",
|
||||
"hf.co/mradermacher/OpenELM-1_1B-Instruct-GGUF:Q4_K_M",
|
||||
"hf.co/mradermacher/OpenELM-3B-Instruct-GGUF:Q4_K_M",
|
||||
"cece2:latest",
|
||||
"qwen3:8b",
|
||||
"llama3:8b-instruct-q4_K_M",
|
||||
"cece:latest",
|
||||
"deepseek-coder:1.3b",
|
||||
"qwen2.5-coder:3b",
|
||||
"llama3.2:3b",
|
||||
"tinyllama:latest",
|
||||
"llama3.2:latest",
|
||||
"codellama:7b",
|
||||
"llama3.2:1b"
|
||||
]
|
||||
},
|
||||
"docker": {
|
||||
"running": 0,
|
||||
"images": 0,
|
||||
"containers_total": 0,
|
||||
"names": []
|
||||
},
|
||||
"postgres": {
|
||||
"databases": 3
|
||||
},
|
||||
"nginx": {
|
||||
"sites": 15,
|
||||
"active": false
|
||||
},
|
||||
"systemd": {
|
||||
"services": 80,
|
||||
"timers": 11,
|
||||
"failed": 5
|
||||
},
|
||||
"processes": 254,
|
||||
"connections": 34,
|
||||
"swap": {
|
||||
"used_mb": 2039,
|
||||
"total_mb": 2047
|
||||
},
|
||||
"cloudflared": true,
|
||||
"tailscale_peers": 0,
|
||||
"hailo": true,
|
||||
"crons": {
|
||||
"root": 12,
|
||||
"users": 14,
|
||||
"total": 26
|
||||
}
|
||||
},
|
||||
"octavia": {
|
||||
"status": "offline"
|
||||
},
|
||||
"lucidia": {
|
||||
"ollama": {
|
||||
"count": 6,
|
||||
"size_gb": 10.1,
|
||||
"models": [
|
||||
"qwen2.5:3b",
|
||||
"nomic-embed-text:latest",
|
||||
"lucidia:latest",
|
||||
"llama3.2:1b",
|
||||
"tinyllama:latest",
|
||||
"qwen2.5:1.5b"
|
||||
]
|
||||
},
|
||||
"docker": {
|
||||
"running": 14,
|
||||
"images": 15,
|
||||
"containers_total": 15,
|
||||
"names": [
|
||||
"blackroad-gitea",
|
||||
"road-pdns-admin",
|
||||
"road-pdns",
|
||||
"road-dns-db",
|
||||
"roadauth",
|
||||
"roadapi",
|
||||
"blackroad-edge-agent",
|
||||
"blackroad.systems",
|
||||
"blackroadai.com",
|
||||
"blackroad-auth-gateway",
|
||||
"blackroad-metaverse",
|
||||
"blackroad-os",
|
||||
"blackroad-os-carpool",
|
||||
"pi-my-agent-1"
|
||||
]
|
||||
},
|
||||
"postgres": {
|
||||
"databases": 4
|
||||
},
|
||||
"nginx": {
|
||||
"sites": 3,
|
||||
"active": true
|
||||
},
|
||||
"systemd": {
|
||||
"services": 89,
|
||||
"timers": 13,
|
||||
"failed": 4
|
||||
},
|
||||
"processes": 387,
|
||||
"connections": 59,
|
||||
"swap": {
|
||||
"used_mb": 2665,
|
||||
"total_mb": 8703
|
||||
},
|
||||
"cloudflared": true,
|
||||
"tailscale_peers": 9,
|
||||
"hailo": false,
|
||||
"crons": {
|
||||
"root": 11,
|
||||
"users": 21,
|
||||
"total": 32
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
package.json
11
package.json
@@ -1,16 +1,21 @@
|
||||
{
|
||||
"name": "blackroad-os-kpis",
|
||||
"version": "1.0.0",
|
||||
"description": "BlackRoad OS KPI tracking — commits, PRs, autonomy, LOC, fleet health",
|
||||
"version": "2.0.0",
|
||||
"description": "BlackRoad OS KPI tracking — 60+ metrics across code, fleet, services, autonomy, Cloudflare, LOC",
|
||||
"scripts": {
|
||||
"collect": "bash collectors/collect-all.sh",
|
||||
"collect:github": "bash collectors/github.sh",
|
||||
"collect:github-deep": "bash collectors/github-deep.sh",
|
||||
"collect:gitea": "bash collectors/gitea.sh",
|
||||
"collect:fleet": "bash collectors/fleet.sh",
|
||||
"collect:services": "bash collectors/services.sh",
|
||||
"collect:autonomy": "bash collectors/autonomy.sh",
|
||||
"collect:loc": "bash collectors/loc.sh",
|
||||
"collect:local": "bash collectors/local.sh",
|
||||
"collect:cloudflare": "bash collectors/cloudflare.sh",
|
||||
"report": "bash reports/daily-report.sh",
|
||||
"report:slack": "bash reports/slack-notify.sh",
|
||||
"dashboard": "node dashboards/serve.js"
|
||||
"report:md": "bash reports/markdown-report.sh"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
# Generate formatted daily KPI report
|
||||
# Generate formatted daily KPI report — FULL NUMBERS
|
||||
|
||||
source "$(dirname "$0")/../lib/common.sh"
|
||||
|
||||
@@ -10,76 +10,164 @@ if [ ! -f "$DAILY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get yesterday's data for deltas
|
||||
YESTERDAY=$(date -v-1d +%Y-%m-%d 2>/dev/null || date -d '1 day ago' +%Y-%m-%d)
|
||||
YESTERDAY_FILE="$DATA_DIR/daily/${YESTERDAY}.json"
|
||||
|
||||
export DAILY YESTERDAY_FILE
|
||||
python3 << 'PYEOF'
|
||||
import json, os, sys
|
||||
import json, os
|
||||
|
||||
today_file = os.environ.get('DAILY', '')
|
||||
yesterday_file = os.environ.get('YESTERDAY_FILE', '')
|
||||
|
||||
with open(today_file) as f:
|
||||
with open(os.environ['DAILY']) as f:
|
||||
data = json.load(f)
|
||||
|
||||
yesterday = {}
|
||||
if os.path.exists(yesterday_file or ''):
|
||||
with open(yesterday_file) as f:
|
||||
yf = os.environ.get('YESTERDAY_FILE', '')
|
||||
if yf and os.path.exists(yf):
|
||||
with open(yf) as f:
|
||||
yesterday = json.load(f)
|
||||
|
||||
s = data['summary']
|
||||
ys = yesterday.get('summary', {})
|
||||
|
||||
def delta(key):
|
||||
def d(key):
|
||||
"""Delta indicator"""
|
||||
curr = s.get(key, 0)
|
||||
prev = ys.get(key, 0)
|
||||
if not prev:
|
||||
if not prev or not isinstance(curr, (int, float)):
|
||||
return ''
|
||||
diff = curr - prev
|
||||
if diff > 0:
|
||||
return f' \033[38;5;82m(+{diff})\033[0m'
|
||||
elif diff < 0:
|
||||
return f' \033[38;5;196m({diff})\033[0m'
|
||||
return ' (=)'
|
||||
return ' \033[38;5;240m(=)\033[0m'
|
||||
|
||||
def pct(used, total):
|
||||
if not total:
|
||||
return '0%'
|
||||
return f"{round(used/total*100)}%"
|
||||
|
||||
def bar(value, max_val, width=20):
|
||||
if not max_val:
|
||||
return '░' * width
|
||||
filled = int(value / max_val * width)
|
||||
return '█' * filled + '░' * (width - filled)
|
||||
|
||||
P = '\033[38;5;205m'
|
||||
A = '\033[38;5;214m'
|
||||
B = '\033[38;5;69m'
|
||||
G = '\033[38;5;82m'
|
||||
V = '\033[38;5;135m'
|
||||
W = '\033[1;37m'
|
||||
DIM = '\033[38;5;240m'
|
||||
R = '\033[0m'
|
||||
|
||||
# Compute some derived metrics
|
||||
fleet_mem_pct = pct(s.get('fleet_mem_used_mb', 0), s.get('fleet_mem_total_mb', 1))
|
||||
fleet_disk_pct = pct(s.get('fleet_disk_used_gb', 0), s.get('fleet_disk_total_gb', 1))
|
||||
fleet_swap_pct = pct(s.get('fleet_swap_used_mb', 0), s.get('fleet_swap_total_mb', 1))
|
||||
|
||||
# Total infrastructure count
|
||||
total_infra = (
|
||||
s.get('cf_d1_databases', 0) +
|
||||
s.get('cf_kv_namespaces', 0) +
|
||||
s.get('cf_r2_buckets', 0) +
|
||||
s.get('cf_pages', 0) +
|
||||
s.get('docker_containers', 0) +
|
||||
s.get('postgres_dbs', 0) +
|
||||
s.get('sqlite_dbs', 0)
|
||||
)
|
||||
|
||||
# Total automation
|
||||
total_automation = (
|
||||
s.get('mac_cron_jobs', 0) +
|
||||
s.get('fleet_cron_jobs', 0) +
|
||||
s.get('systemd_timers', 0)
|
||||
)
|
||||
|
||||
print(f"""
|
||||
{P}╔══════════════════════════════════════════════════╗{R}
|
||||
{P}║{R} {A}BlackRoad OS — Daily KPIs{R} {P}║{R}
|
||||
{P}║{R} {B}{data['date']}{R} {P}║{R}
|
||||
{P}╠══════════════════════════════════════════════════╣{R}
|
||||
{P}╔══════════════════════════════════════════════════════════════╗{R}
|
||||
{P}║{R} {W}B L A C K R O A D O S{R} — {A}Daily KPIs{R} {P}║{R}
|
||||
{P}║{R} {B}{data['date']}{R} {DIM}collected {data['collected_at']}{R} {P}║{R}
|
||||
{P}╠══════════════════════════════════════════════════════════════╣{R}
|
||||
|
||||
{A}📊 CODE{R}
|
||||
Commits today: {G}{s['commits_today']}{R}{delta('commits_today')}
|
||||
PRs open: {s['prs_open']}{delta('prs_open')}
|
||||
PRs merged today: {s['prs_merged_today']}{delta('prs_merged_today')}
|
||||
PRs merged total: {s['prs_merged_total']}{delta('prs_merged_total')}
|
||||
Total LOC: {s['total_loc']:,}{delta('total_loc')}
|
||||
{A}═══ CODE VELOCITY ══════════════════════════════════════════════{R}
|
||||
Commits today {G}{s['commits_today']:>6}{R}{d('commits_today')}
|
||||
Push events {s.get('push_events_today', 0):>6}{d('push_events_today')}
|
||||
GitHub events {s.get('github_events_today', 0):>6}{d('github_events_today')}
|
||||
PRs open {s['prs_open']:>6}{d('prs_open')}
|
||||
PRs merged today {s['prs_merged_today']:>6}{d('prs_merged_today')}
|
||||
PRs merged total {s['prs_merged_total']:>6}{d('prs_merged_total')}
|
||||
Open issues {s.get('github_open_issues', 0):>6}{d('github_open_issues')}
|
||||
Total LOC {G}{s['total_loc']:>10,}{R}{d('total_loc')}
|
||||
|
||||
{A}📦 REPOS{R}
|
||||
GitHub: {s['repos_github']}{delta('repos_github')}
|
||||
Gitea: {s['repos_gitea']}{delta('repos_gitea')}
|
||||
Total: {s['repos_total']}{delta('repos_total')}
|
||||
{A}═══ REPOSITORIES ══════════════════════════════════════════════{R}
|
||||
GitHub repos {s['repos_github']:>6}{d('repos_github')}
|
||||
Gitea repos {s['repos_gitea']:>6}{d('repos_gitea')}
|
||||
Total repos {W}{s['repos_total']:>6}{R}{d('repos_total')}
|
||||
Active {s.get('repos_active', 0):>6}
|
||||
Archived {s.get('repos_archived', 0):>6}
|
||||
Total size {s.get('github_size_mb', 0):>7.0f} MB{d('github_size_mb')}
|
||||
Stars {s.get('github_stars', 0):>6} Forks {s.get('github_forks', 0)}
|
||||
Followers {s.get('github_followers', 0):>6} Following {s.get('github_following', 0)}
|
||||
|
||||
{A}🖥 FLEET{R}
|
||||
Nodes online: {s['fleet_online']}/{s['fleet_total']}
|
||||
Docker containers: {s['docker_containers']}{delta('docker_containers')}
|
||||
Ollama models: {s['ollama_models']}{delta('ollama_models')}
|
||||
Avg temp: {s['avg_temp_c']}°C
|
||||
Failed units: {s['failed_units']}{delta('failed_units')}
|
||||
Throttled: {', '.join(s.get('throttled_nodes', [])) or 'none'}
|
||||
{A}═══ FLEET ({s['fleet_online']}/{s['fleet_total']} online) ══════════════════════════════════════{R}
|
||||
Nodes online {G}{s['fleet_online']:>6}{R}/{s['fleet_total']}{d('fleet_online')}
|
||||
Offline {', '.join(s.get('fleet_offline', [])) or 'none'}
|
||||
Avg temp {s['avg_temp_c']:>7.1f}°C
|
||||
Throttled {', '.join(s.get('throttled_nodes', [])) or 'none'}
|
||||
Memory {s.get('fleet_mem_used_mb', 0):>5} / {s.get('fleet_mem_total_mb', 0)} MB {DIM}({fleet_mem_pct}){R}
|
||||
Disk {s.get('fleet_disk_used_gb', 0):>5} / {s.get('fleet_disk_total_gb', 0)} GB {DIM}({fleet_disk_pct}){R}
|
||||
Swap {s.get('fleet_swap_used_mb', 0):>5} / {s.get('fleet_swap_total_mb', 0)} MB {DIM}({fleet_swap_pct}){R}
|
||||
Processes {s.get('fleet_processes', 0):>6}
|
||||
Net connections {s.get('fleet_connections', 0):>6}
|
||||
Tailscale peers {s.get('tailscale_peers', 0):>6}
|
||||
|
||||
{A}🤖 AUTONOMY{R}
|
||||
Score: {V}{s['autonomy_score']}/100{R}{delta('autonomy_score')}
|
||||
{A}═══ SERVICES ═══════════════════════════════════════════════════{R}
|
||||
Ollama models {V}{s.get('ollama_models', 0):>6}{R} {DIM}({s.get('ollama_size_gb', 0):.1f} GB){R}{d('ollama_models')}
|
||||
Docker containers {s.get('docker_containers', 0):>6}{d('docker_containers')}
|
||||
Docker images {s.get('docker_images', 0):>6}{d('docker_images')}
|
||||
PostgreSQL DBs {s.get('postgres_dbs', 0):>6}{d('postgres_dbs')}
|
||||
Nginx sites {s.get('nginx_sites', 0):>6}{d('nginx_sites')}
|
||||
Systemd services {s.get('systemd_services', 0):>6}{d('systemd_services')}
|
||||
Systemd timers {s.get('systemd_timers', 0):>6}{d('systemd_timers')}
|
||||
Failed units {s.get('failed_units', 0):>6}{d('failed_units')}
|
||||
|
||||
{P}╚══════════════════════════════════════════════════╝{R}
|
||||
{A}═══ AUTONOMY ═══════════════════════════════════════════════════{R}
|
||||
Score {V}{s.get('autonomy_score', 0):>5}/100{R} {bar(s.get('autonomy_score', 0), 100, 30)}{d('autonomy_score')}
|
||||
Heal events today {s.get('heal_events_today', 0):>6}
|
||||
Service restarts {s.get('service_restarts_today', 0):>6}
|
||||
Fleet cron jobs {s.get('fleet_cron_jobs', 0):>6}
|
||||
Max uptime {s.get('max_uptime_days', 0):>5} days
|
||||
|
||||
{A}═══ LOCAL MAC ═══════════════════════════════════════════════════{R}
|
||||
CLI tools (~/bin) {s.get('bin_tools', 0):>6} {DIM}({s.get('bin_size_mb', 0)} MB){R}{d('bin_tools')}
|
||||
Home scripts {s.get('home_scripts', 0):>6}
|
||||
Templates {s.get('templates', 0):>6}
|
||||
Local git repos {s.get('local_git_repos', 0):>6}
|
||||
SQLite databases {s.get('sqlite_dbs', 0):>6} {DIM}({s.get('blackroad_dir_mb', 0)} MB){R}
|
||||
FTS5 entries {s.get('fts5_entries', 0):>8,}
|
||||
Systems registered {s.get('systems_registered', 0):>6}
|
||||
Cron jobs {s.get('mac_cron_jobs', 0):>6}
|
||||
Mac disk {s.get('mac_disk_used_gb', 0):>5} GB {DIM}({s.get('mac_disk_pct', 0)}%){R}
|
||||
Mac processes {s.get('mac_processes', 0):>6}
|
||||
Brew packages {s.get('brew_packages', 0):>6}
|
||||
pip packages {s.get('pip_packages', 0):>6}
|
||||
npm global {s.get('npm_global_packages', 0):>6}
|
||||
|
||||
{A}═══ CLOUDFLARE ═════════════════════════════════════════════════{R}
|
||||
Pages projects {s.get('cf_pages', 0):>6}{d('cf_pages')}
|
||||
D1 databases {s.get('cf_d1_databases', 0):>6} {DIM}({s.get('cf_d1_size_kb', 0)} KB){R}{d('cf_d1_databases')}
|
||||
KV namespaces {s.get('cf_kv_namespaces', 0):>6}{d('cf_kv_namespaces')}
|
||||
R2 buckets {s.get('cf_r2_buckets', 0):>6}{d('cf_r2_buckets')}
|
||||
|
||||
{P}═══ TOTALS ═════════════════════════════════════════════════════{R}
|
||||
{W}Total repos {s['repos_total']:>6}{R}
|
||||
{W}Total LOC {s['total_loc']:>10,}{R}
|
||||
{W}Total databases {total_infra:>6}{R} {DIM}(D1+KV+R2+Pages+SQLite+PG+Docker){R}
|
||||
{W}Total automation {total_automation:>5}{R} {DIM}(crons+timers){R}
|
||||
{W}Total AI models {s.get('ollama_models', 0):>6}{R} {DIM}({s.get('ollama_size_gb', 0):.1f} GB){R}
|
||||
|
||||
{P}╚══════════════════════════════════════════════════════════════╝{R}
|
||||
""")
|
||||
PYEOF
|
||||
|
||||
Reference in New Issue
Block a user