diff --git a/.prettierignore b/.prettierignore index 9e0427c45..dad0d6013 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,3 @@ /build/ node_modules/ -/src/server_manager/messages/ +/src/shadowbox/prometheus/consoles/ diff --git a/package-lock.json b/package-lock.json index 131eb326e..bb8f54faa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "packages": { "": { "name": "outline-server", + "hasInstallScript": true, "workspaces": [ "src/*" ], diff --git a/src/shadowbox/Taskfile.yml b/src/shadowbox/Taskfile.yml index a7a7daf9a..31b49bb7d 100644 --- a/src/shadowbox/Taskfile.yml +++ b/src/shadowbox/Taskfile.yml @@ -20,6 +20,8 @@ tasks: - cp '{{joinPath .TASKFILE_DIR "package.json"}}' '{{.TARGET_DIR}}' # Build Node.js app - npx webpack --config='{{joinPath .TASKFILE_DIR "webpack.config.js"}}' --output-path='{{.NODE_DIR}}' ${BUILD_ENV:+--mode="${BUILD_ENV}"} + # Copy Prometheus Console files. + - cp -r '{{joinPath .TASKFILE_DIR "prometheus"}}' '{{.TARGET_DIR}}' # Copy third_party dependencies - task: ':third_party:prometheus:copy-{{.TARGET_OS}}-{{.GOARCH}}' vars: {TARGET_DIR: '{{.BIN_DIR}}'} diff --git a/src/shadowbox/prometheus/console_libraries/menu.lib b/src/shadowbox/prometheus/console_libraries/menu.lib new file mode 100644 index 000000000..0eef1bd1e --- /dev/null +++ b/src/shadowbox/prometheus/console_libraries/menu.lib @@ -0,0 +1,53 @@ +{{/* vim: set ft=html: */}} + +{{/* Navbar, should be passed . */}} +{{ define "navbar" }} + +{{ end }} + +{{/* LHS menu, should be passed . */}} +{{ define "menu" }} +
+ +
+{{ end }} + +{{/* Helper, pass (args . path name) */}} +{{ define "_menuItem" }} + +{{ end }} + diff --git a/src/shadowbox/prometheus/console_libraries/prom.lib b/src/shadowbox/prometheus/console_libraries/prom.lib new file mode 100644 index 000000000..d7d436f94 --- /dev/null +++ b/src/shadowbox/prometheus/console_libraries/prom.lib @@ -0,0 +1,138 @@ +{{/* vim: set ft=html: */}} +{{/* Load Prometheus console library JS/CSS. Should go in */}} +{{ define "prom_console_head" }} + + + + + + + + + + + + + +{{ end }} + +{{/* Top of all pages. */}} +{{ define "head" -}} + + + +{{ template "prom_console_head" }} + + +{{ template "navbar" . }} + +{{ template "menu" . }} +{{ end }} + +{{ define "__prom_query_drilldown_noop" }}{{ . }}{{ end }} +{{ define "humanize" }}{{ humanize . }}{{ end }} +{{ define "humanizeNoSmallPrefix" }}{{ if and (lt . 1.0) (gt . -1.0) }}{{ printf "%.3g" . }}{{ else }}{{ humanize . }}{{ end }}{{ end }} +{{ define "humanize1024" }}{{ humanize1024 . }}{{ end }} +{{ define "humanizeDuration" }}{{ humanizeDuration . }}{{ end }} +{{ define "humanizePercentage" }}{{ humanizePercentage . }}{{ end }} +{{ define "humanizeTimestamp" }}{{ humanizeTimestamp . }}{{ end }} +{{ define "printf.1f" }}{{ printf "%.1f" . }}{{ end }} +{{ define "printf.3g" }}{{ printf "%.3g" . }}{{ end }} + +{{/* prom_query_drilldown (args expr suffix? renderTemplate?) +Displays the result of the expression, with a link to /graph for it. + +renderTemplate is the name of the template to use to render the value. +*/}} +{{ define "prom_query_drilldown" }} +{{ $expr := .arg0 }}{{ $suffix := (or .arg1 "") }}{{ $renderTemplate := (or .arg2 "__prom_query_drilldown_noop") }} +{{ with query $expr }}{{tmpl $renderTemplate ( . | first | value )}}{{ $suffix }}{{ else }}-{{ end }} +{{ end }} + +{{ define "prom_path" }}/consoles/{{ .Path }}?{{ range $param, $value := .Params }}{{ $param }}={{ $value }}&{{ end }}{{ end }}" + +{{ define "prom_right_table_head" }} +
+ +{{ end }} +{{ define "prom_right_table_tail" }} +
+
+{{ end }} + +{{/* RHS table head, pass job name. Should be used after prom_right_table_head. */}} +{{ define "prom_right_table_job_head" }} + + {{ . }} + {{ template "prom_query_drilldown" (args (printf "sum(up{job='%s'})" .)) }} / {{ template "prom_query_drilldown" (args (printf "count(up{job='%s'})" .)) }} + + + CPU + {{ template "prom_query_drilldown" (args (printf "avg by(job)(irate(process_cpu_seconds_total{job='%s'}[5m]))" .) "s/s" "humanizeNoSmallPrefix") }} + + + Memory + {{ template "prom_query_drilldown" (args (printf "avg by(job)(process_resident_memory_bytes{job='%s'})" .) "B" "humanize1024") }} + +{{ end }} + + +{{ define "prom_content_head" }} +
+
+{{ template "prom_graph_timecontrol" . }} +{{ end }} +{{ define "prom_content_tail" }} +
+
+{{ end }} + +{{ define "prom_graph_timecontrol" }} +
+
+
+ +
+
+ +
+
+
+ + + +
+
+
+ +
+{{ end }} + +{{/* Bottom of all pages. */}} +{{ define "tail" }} + + +{{ end }} diff --git a/src/shadowbox/prometheus/consoles/index.html b/src/shadowbox/prometheus/consoles/index.html new file mode 100644 index 000000000..71758476d --- /dev/null +++ b/src/shadowbox/prometheus/consoles/index.html @@ -0,0 +1,5 @@ +{{ template "head" . }} {{ template "prom_right_table_head" }} {{ template "prom_right_table_tail" +}} {{ template "prom_content_head" . }} +

Overview

+

These are standard consoles for Outline metrics.

+{{ template "prom_content_tail" . }} {{ template "tail" }} diff --git a/src/shadowbox/prometheus/consoles/outline-overview.html b/src/shadowbox/prometheus/consoles/outline-overview.html new file mode 100644 index 000000000..f8f8d3ae5 --- /dev/null +++ b/src/shadowbox/prometheus/consoles/outline-overview.html @@ -0,0 +1,91 @@ +{{ template "head" . }} + +{{ template "prom_right_table_head" }} + + Overview + + + CPU + {{ template "prom_query_drilldown" (args (printf "irate(process_cpu_seconds_total{job='outline-server-ss',instance='%s'}[5m])" .Params.instance) "s/s" "humanizeNoSmallPrefix") }} + + + Memory + {{ template "prom_query_drilldown" (args (printf "process_resident_memory_bytes{job='outline-server-ss',instance='%s'}" .Params.instance) "B" "humanize1024") }} + + + Version + + + {{ with query (printf "shadowsocks_build_info{job='outline-server-ss',instance='%s'}" .Params.instance) }}{{. | first | label "version"}}{{end}} + + + + + + Shadowsocks + + + Keys + {{ template "prom_query_drilldown" (args (printf "shadowsocks_keys{job='outline-server-ss',instance='%s'}" .Params.instance) "" "humanize") }} + + + Ports + {{ template "prom_query_drilldown" (args (printf "shadowsocks_ports{job='outline-server-ss',instance='%s'}" .Params.instance) "" "humanize") }} + + + Bytes transferred + {{ template "prom_query_drilldown" (args (printf "sum by (instance) (shadowsocks_data_bytes{job='outline-server-ss',instance='%s'})" .Params.instance) "B" "humanize1024") }} + +{{ template "prom_right_table_tail" }} + +{{ template "prom_content_head" . }} +
+

Outline Overview - {{ .Params.instance }}

+ +

Data Bytes per Access Key

+
+ + +

TCP Connections by Location

+
+ + +

UDP Packets by Location

+
+ +
+{{ template "prom_content_tail" . }} + +{{ template "tail" }} diff --git a/src/shadowbox/prometheus/consoles/outline.html b/src/shadowbox/prometheus/consoles/outline.html new file mode 100644 index 000000000..2809523bb --- /dev/null +++ b/src/shadowbox/prometheus/consoles/outline.html @@ -0,0 +1,36 @@ +{{ template "head" . }} + +{{ template "prom_right_table_head" }} + + Outline Shadowsocks + {{ template "prom_query_drilldown" (args "sum(up{job='outline-server-ss'})") }} / {{ template "prom_query_drilldown" (args "count(up{job='outline-server-ss'})") }} + +{{ template "prom_right_table_tail" }} + +{{ template "prom_content_head" . }} +

Outline

+ + + + + + + + +{{ range query "up{job='outline-server-ss'}" | sortByLabel "instance" }} + + + + + + +{{ else }} + +{{ end }} +
ShadowsocksUpUptimeMemory
{{ .Labels.instance }}Yes{{ else }} class="alert-danger">No{{ end }} + {{ template "prom_query_drilldown" (args (printf "round((time() - process_start_time_seconds{job='outline-server-ss',instance='%s'})/(60*60*24), 1)" .Labels.instance) " days" "humanizeNoSmallPrefix") }} + {{ template "prom_query_drilldown" (args (printf "process_resident_memory_bytes{job='outline-server-ss',instance='%s'}" .Labels.instance) "B" "humanize1024")}}
No jobs found.
+ +{{ template "prom_content_tail" . }} + +{{ template "tail" }} diff --git a/src/shadowbox/server/main.ts b/src/shadowbox/server/main.ts index fe8dbcb53..7b6254ad7 100644 --- a/src/shadowbox/server/main.ts +++ b/src/shadowbox/server/main.ts @@ -190,6 +190,10 @@ async function main() { prometheusTsdbFilename, '--web.listen-address', prometheusLocation, + '--web.console.libraries', + path.join(APP_BASE_DIR, 'prometheus', 'console_libraries'), + '--web.console.templates', + path.join(APP_BASE_DIR, 'prometheus', 'consoles'), '--log.level', verbose ? 'debug' : 'info', ];