diff --git a/config/statistics.yml b/config/statistics.yml
index 4a07b0e..2f9226e 100644
--- a/config/statistics.yml
+++ b/config/statistics.yml
@@ -264,6 +264,163 @@
{{ end }}
+ - type: custom-api
+ title: Dockhand
+ title-url: https://dockhand.${GROUND_DOMAIN}
+ cache: 1h
+ url: https://dockhand.${GROUND_DOMAIN}/api/environments?env=1
+ headers:
+ Authorization: Bearer ${DOCKHAND_API_TOKEN}
+ subrequests:
+ containers:
+ url: https://dockhand.${GROUND_DOMAIN}/api/containers?env=1
+ headers:
+ Authorization: Bearer ${DOCKHAND_API_TOKEN}
+ images:
+ url: https://dockhand.${GROUND_DOMAIN}/api/images?env=1
+ headers:
+ Authorization: Bearer ${DOCKHAND_API_TOKEN}
+ networks:
+ url: https://dockhand.${GROUND_DOMAIN}/api/networks?env=1
+ headers:
+ Authorization: Bearer ${DOCKHAND_API_TOKEN}
+ volumes:
+ url: https://dockhand.${GROUND_DOMAIN}/api/volumes?env=1
+ headers:
+ Authorization: Bearer ${DOCKHAND_API_TOKEN}
+ stacks:
+ url: https://dockhand.${GROUND_DOMAIN}/api/stacks?env=1
+ headers:
+ Authorization: Bearer ${DOCKHAND_API_TOKEN}
+ template: |
+
+
+ {{ $containers := (.Subrequest "containers").JSON.Array "" }}
+ {{ $images := (.Subrequest "images").JSON.Array "" }}
+ {{ $networks := (.Subrequest "networks").JSON.Array "" }}
+ {{ $volumes := (.Subrequest "volumes").JSON.Array "" }}
+ {{ $stacks := (.Subrequest "stacks").JSON.Array "" }}
+
+ {{ $running := 0 }}
+ {{ $stopped := 0 }}
+ {{ range $containers }}
+ {{ if eq (.String "state") "running" }}
+ {{ $running = add $running 1 }}
+ {{ else }}
+ {{ $stopped = add $stopped 1 }}
+ {{ end }}
+ {{ end }}
+
+
+
+
{{ $running }}
+
+
+
+
+
{{ $stopped }}
+
+
+
+
+
{{ len $images }}
+
+
Images
+ {{ $unused := 0 }}
+ {{ $totalBytes := 0 }}
+ {{ range $images }}
+ {{ if eq (.Int "containers") 0 }}
+ {{ $unused = add $unused 1 }}
+ {{ end }}
+ {{ $totalBytes = add $totalBytes (.Int "size") }}
+ {{ end }}
+ {{ $totalGB := div $totalBytes 1073741824 }}
+ {{ $decimal := mod (div $totalBytes 1048576) 1024 }}
+
+
Unused images:
+
{{ $unused }}
+
+
+
Total size:
+
{{ printf "%d.%02d GB" $totalGB $decimal }}
+
+
+
+
+
+
+
{{ len $volumes }}
+
+
+
+
+
+
Networks
+ {{ range $networks }}
+
+
{{ .String "name" }}
+
+ {{ $cfg := .Array "ipam.config" }}
+ {{ if gt (len $cfg) 0 }}
+ {{ (index $cfg 0).String "subnet" }}
+ {{ else }}
+ --
+ {{ end }}
+
+
+ {{ end }}
+
+
{{ len $networks }}
+
+
+
+
+
{{ len $stacks }}
+
+
+
+
- size: full
widgets:
- type: split-column
@@ -343,6 +500,97 @@
{{ end }}
{{ end }}
+ - type: custom-api
+ title: Immich Stats
+ hide-header: true
+ cache: 10m
+ url: https://immich.${GROUND_DOMAIN}/api/server/statistics
+ headers:
+ x-api-key: ${IMMICH_API_KEY}
+ subrequests:
+ storage:
+ url: https://immich.${GROUND_DOMAIN}/api/server/storage
+ headers:
+ x-api-key: ${IMMICH_API_KEY}
+ options:
+ show-cards: true
+ show-storage-bar: true
+ template: |
+ {{ $photos := .JSON.Int "photos" }}
+ {{ $videos := .JSON.Int "videos" }}
+ {{ $usageBytes := .JSON.Int "usage" }}
+ {{ $usageGiB := div (toFloat $usageBytes) 1073741824.0 }}
+ {{ $storage := .Subrequest "storage" }}
+ {{ $storage_ok := and (ge $storage.Response.StatusCode 200) (le $storage.Response.StatusCode 299) }}
+ {{ $totalGiB := 0.0 }}
+ {{ $percentage := 0.0 }}
+ {{ $storageError := "" }}
+ {{ if $storage_ok }}
+ {{ $totalGiB = div (toFloat ($storage.JSON.Int "diskSizeRaw")) 1073741824.0 }}
+ {{ $percentage = $storage.JSON.Float "diskUsagePercentage" }}
+ {{ else }}
+ {{ $storageError = printf "%d %s" $storage.Response.StatusCode $storage.Response.Status }}
+ {{ end }}
+ {{ $showCards := .Options.BoolOr "show-cards" true }}
+ {{ $showStorageBar := .Options.BoolOr "show-storage-bar" true }}
+
+ {{ if $showCards }}
+
+
+
+
+ {{ if lt $photos 10 }}000000000{{ else if lt $photos 100 }}00000000{{ else if lt $photos 1000 }}0000000{{ else if lt $photos 10000 }}000000{{ else if lt $photos 100000 }}00000{{ else if lt $photos 1000000 }}0000{{ end }}{{ $photos }}
+
+
+
+
+
+
+ {{ if lt $videos 10 }}000000000{{ else if lt $videos 100 }}00000000{{ else if lt $videos 1000 }}0000000{{ else if lt $videos 10000 }}000000{{ else if lt $videos 100000 }}00000{{ else if lt $videos 1000000 }}0000{{ end }}{{ $videos }}
+
+
+
+
+
+
+ {{ $gib := printf "%.0f" $usageGiB }}
+ {{ if lt $usageGiB 10.0 }}000000000{{ else if lt $usageGiB 100.0 }}00000000{{ else if lt $usageGiB 1000.0 }}0000000{{ end }}{{ $gib }}GiB
+
+
+
+ {{ end }}
+
+ {{ if $showStorageBar }}
+
+
Storage space
+ {{ if gt $totalGiB 0.0 }}
+
{{ printf "%.1f" $usageGiB }} GiB of {{ printf "%.1f" $totalGiB }} GiB used
+
{{ printf "%.1f" $percentage }}% full
+ {{ else }}
+
{{ printf "%.1f" $usageGiB }} GiB used
+
Total storage unavailable ({{ $storageError }}). Ensure API key has permissions for /api/server/storage.
+ {{ end }}
+
+
+ {{ end }}
+
- type: custom-api
title: Server Stats
cache: 5m