Skip to content

Commit

Permalink
Merge pull request #3 from chpc-uofu/metrics
Browse files Browse the repository at this point in the history
Serve metrics
  • Loading branch information
jay-mckay authored Sep 5, 2024
2 parents e534edf + a1e16f6 commit 64cc64b
Show file tree
Hide file tree
Showing 6 changed files with 314 additions and 62 deletions.
22 changes: 4 additions & 18 deletions control.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// Copyright (C) 2024 Center for High Performance Computing <[email protected]>

package main

import (
Expand All @@ -19,8 +17,6 @@ import (

const MAX_UINT64 uint64 = ^uint64(0)

// A subset of available properties to modify.
// See https://man7.org/linux/man-pages/man5/systemd.resource-control.5.html.
var (
CPUAccounting = "CPUAccounting"
CPUQuotaPerSecUSec = "CPUQuotaPerSecUSec"
Expand All @@ -29,17 +25,6 @@ var (
MemoryMax = "MemoryMax"
)

type systemdConn struct {
conn *systemd.Conn
ctx context.Context
}

func newSystemdConn() (systemdConn, error) {
ctx := context.Background()
conn, err := systemd.NewSystemConnectionContext(ctx)
return systemdConn{conn, ctx}, err
}

type controlProperty struct {
Name string `json:"name"`
Value string `json:"value"`
Expand Down Expand Up @@ -83,15 +68,16 @@ func controlHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
}

sysconn, err := newSystemdConn()
ctx := context.Background()
conn, err := systemd.NewSystemConnectionContext(ctx)
if err != nil {
slog.Warn("unable to connect to systemd", "err", err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer sysconn.conn.Close()
defer conn.Close()

err = sysconn.conn.SetUnitPropertiesContext(sysconn.ctx, unit, request.Runtime, property)
err = conn.SetUnitPropertiesContext(ctx, unit, request.Runtime, property)
if err != nil {
slog.Warn("unable to set property", "err", err.Error(), "property", property, "unit", unit)
http.Error(w, err.Error(), http.StatusInternalServerError)
Expand Down
29 changes: 0 additions & 29 deletions control_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package main

import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
)

Expand Down Expand Up @@ -82,28 +78,3 @@ func TestTransform(t *testing.T) {
t.Fail()
}
}

// this test requires priviledge
func _TestControlHandler(t *testing.T) {
mockControlRequest := map[string]interface{}{
"unit": "user-0.slice",
"property": map[string]interface{}{
"name": "CPUAccounting",
"value": "true",
},
"runtime": true,
}
payload, _ := json.Marshal(mockControlRequest)
req := httptest.NewRequest("POST", "/control", bytes.NewReader(payload))
w := httptest.NewRecorder()
ControlHandler(w, req)
resp := w.Result()
var cr controlResponse
err := json.NewDecoder(resp.Body).Decode(&cr)
if err != nil {
t.Fail()
}
if resp.StatusCode != http.StatusOK {
t.Fail()
}
}
15 changes: 15 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,19 @@ toolchain go1.22.5
require (
github.com/coreos/go-systemd/v22 v22.5.0
github.com/godbus/dbus/v5 v5.1.0
github.com/prometheus/client_golang v1.20.3
github.com/prometheus/procfs v0.15.1
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
golang.org/x/sys v0.22.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
)

replace github.com/coreos/go-systemd/v22 => github.com/jay-mckay/go-systemd/v22 v22.0.0
28 changes: 26 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/jay-mckay/go-systemd/v22 v22.0.0 h1:nXxwYusmnPs+IvtAPhMibtBpaiK6LAz2YnQFPUytMms=
github.com/jay-mckay/go-systemd/v22 v22.0.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4=
github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
24 changes: 11 additions & 13 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// Copyright (C) 2024 Center for High Performance Computing <[email protected]>

package main

import (
Expand All @@ -19,30 +17,32 @@ func authorize(next http.Handler, secret string) http.Handler {
})
}

func newHandler() http.Handler {
mux := http.NewServeMux()
mux.Handle("/control", ControlHandler)
mux.Handle("/", http.NotFoundHandler())
var handler http.Handler = mux
return handler
}

func main() {
var (
pattern string
listenAddr string
certFile string
keyFile string
bearerToken string
insecure bool
collectProc bool
)

flag.StringVar(&pattern, "pattern", "user-*.slice", "unit pattern to match units on")
flag.StringVar(&listenAddr, "listenAddr", ":2112", "address to listen on for telemetry")
flag.StringVar(&certFile, "certFile", "", "file containing certificate to use for tls")
flag.StringVar(&keyFile, "keyFile", "", "file containing key to use for tls")
flag.StringVar(&bearerToken, "bearerToken", "", "bearer token to use for authentication")
flag.BoolVar(&insecure, "insecure", false, "disable tls and bearer token authentication")
flag.BoolVar(&collectProc, "collectProc", false, "enable the collection of process metrics")
flag.Parse()

mux := http.NewServeMux()
mux.Handle("/control", ControlHandler)
mux.Handle("/metrics", MetricsHandler(pattern, collectProc))
mux.Handle("/", http.NotFoundHandler())
var handler http.Handler = mux

if !insecure {
if certFile == "" {
log.Fatal("certificate required for use with tls")
Expand All @@ -54,11 +54,9 @@ func main() {
log.Fatal("token of length > 16 required for authentication")
}

handler := authorize(newHandler(), bearerToken)
log.Fatal(http.ListenAndServeTLS(listenAddr, certFile, keyFile, handler))
log.Fatal(http.ListenAndServeTLS(listenAddr, certFile, keyFile, authorize(handler, bearerToken)))

} else {
handler := newHandler()
log.Println("running in insecure mode")
log.Fatal(http.ListenAndServe(listenAddr, handler))
}
Expand Down
Loading

0 comments on commit 64cc64b

Please sign in to comment.