Skip to content

Commit

Permalink
metrics: overhaul, extract server package
Browse files Browse the repository at this point in the history
overhaul the metrics package, renaming it from `prometheus`
(even though the impl will be prometheus based with no plans
to change it) and extract the server package, which will be
augmented to support the TLS serving later on

Signed-off-by: Francesco Romani <[email protected]>
  • Loading branch information
ffromani committed Nov 6, 2023
1 parent e155d3f commit 820900e
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 91 deletions.
11 changes: 8 additions & 3 deletions cmd/resource-topology-exporter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import (

"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/config"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/k8shelpers"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/metrics"
metricssrv "github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/metrics/server"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/podres"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/podres/middleware/podexclude"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/podres/middleware/sharedcpuspool"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/podres/middleware/terminalpods"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/prometheus"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/resourcemonitor"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/resourcetopologyexporter"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/version"
Expand Down Expand Up @@ -77,9 +78,13 @@ func main() {
}
}

err = prometheus.InitPrometheus(parsedArgs.RTE.PrometheusMode)
err = metrics.Setup("")
if err != nil {
klog.Fatalf("failed to start prometheus server: %v", err)
klog.Fatalf("failed to setup metrics: %v", err)
}
err = metricssrv.Setup(parsedArgs.RTE.MetricsMode, metricssrv.NewDefaultConfig())
if err != nil {
klog.Fatalf("failed to setup metrics server: %v", err)
}

hnd := resourcemonitor.Handle{
Expand Down
8 changes: 4 additions & 4 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ import (

"github.com/k8stopologyawareschedwg/podfingerprint"

metricssrv "github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/metrics/server"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/nrtupdater"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/podres/middleware/podexclude"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/podres/middleware/sharedcpuspool"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/prometheus"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/resourcemonitor"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/resourcetopologyexporter"
"github.com/k8stopologyawareschedwg/resource-topology-exporter/pkg/version"
Expand Down Expand Up @@ -87,7 +87,7 @@ func LoadArgs(args ...string) (ProgArgs, error) {

var configPath string
var pfpMethod string
var promMode string
var metricsMode string
flags := flag.NewFlagSet(version.ProgramName, flag.ExitOnError)

klog.InitFlags(flags)
Expand Down Expand Up @@ -115,7 +115,7 @@ func LoadArgs(args ...string) (ProgArgs, error) {
flags.StringVar(&pArgs.RTE.PodResourcesSocketPath, "podresources-socket", "unix:///podresources/kubelet.sock", "Pod Resource Socket path to use.")
flags.BoolVar(&pArgs.RTE.PodReadinessEnable, "podreadiness", true, "Custom condition injection using Podreadiness.")
flags.BoolVar(&pArgs.RTE.AddNRTOwnerEnable, "add-nrt-owner", true, "RTE will inject NRT's related node as OwnerReference to ensure cleanup if the node is deleted.")
flags.StringVar(&promMode, "metrics-mode", prometheus.ServingDisabled, fmt.Sprintf("Select the mode to expose metrics endpoint. Valid options: %s", prometheus.ServingModeSupported()))
flags.StringVar(&metricsMode, "metrics-mode", metricssrv.ServingDisabled, fmt.Sprintf("Select the mode to expose metrics endpoint. Valid options: %s", metricssrv.ServingModeSupported()))

refCnt := flags.String("reference-container", "", "Reference container, used to learn about the shared cpu pool\n See: https://github.com/kubernetes/kubernetes/issues/102190\n format of spec is namespace/podname/containername.\n Alternatively, you can use the env vars REFERENCE_NAMESPACE, REFERENCE_POD_NAME, REFERENCE_CONTAINER_NAME.")

Expand Down Expand Up @@ -153,7 +153,7 @@ Special targets:
pArgs.RTE.ReferenceContainer = sharedcpuspool.ContainerIdentFromEnv()
}

pArgs.RTE.PrometheusMode, err = prometheus.ServingModeIsSupported(promMode)
pArgs.RTE.MetricsMode, err = metricssrv.ServingModeIsSupported(metricsMode)
if err != nil {
return pArgs, err
}
Expand Down
102 changes: 30 additions & 72 deletions pkg/prometheus/prometheus.go → pkg/metrics/metrics.go
Original file line number Diff line number Diff line change
@@ -1,46 +1,28 @@
package prometheus
/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package metrics

import (
"fmt"
"net/http"
"os"
"strconv"
"strings"

"k8s.io/klog/v2"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

const prometheusDefaultPort = "2112"

const (
ServingDisabled = "disabled"
ServingHTTP = "http" // plaintext
)

func ServingModeIsSupported(value string) (string, error) {
val := strings.ToLower(value)
switch val {
case ServingDisabled:
return val, nil
case ServingHTTP:
return val, nil
default:
return val, fmt.Errorf("unsupported method %q", value)
}
}

func ServingModeSupported() string {
modes := []string{
ServingDisabled,
ServingHTTP,
}
return strings.Join(modes, ",")
}

var nodeName string

var (
Expand All @@ -65,19 +47,6 @@ var (
}, []string{"node", "trigger"})
)

func getNodeName() (string, error) {
var err error

val, ok := os.LookupEnv("NODE_NAME")
if !ok {
val, err = os.Hostname()
if err != nil {
return "", err
}
}
return val, nil
}

func UpdateNodeResourceTopologyWritesMetric(operation, trigger string) {
NodeResourceTopologyWrites.With(prometheus.Labels{
"node": nodeName,
Expand Down Expand Up @@ -108,35 +77,24 @@ func UpdateWakeupDelayMetric(trigger string, wakeupDelay float64) {
}).Set(wakeupDelay)
}

func InitPrometheus(mode string) error {
if mode == ServingDisabled {
klog.Infof("prometheus endpoint disabled")
return nil
}

func Setup(nname string) error {
var err error
var port = prometheusDefaultPort

if envValue, ok := os.LookupEnv("METRICS_PORT"); ok {
if _, err = strconv.Atoi(envValue); err != nil {
return fmt.Errorf("the env variable PROMETHEUS_PORT has inccorrect value %q: %w", envValue, err)
var ok bool
var val string = nname
if val == "" {
val, ok = os.LookupEnv("NODE_NAME")
if !ok {
val, err = os.Hostname()
}
port = envValue
}

nodeName, err = getNodeName()
if err != nil {
return err
}

http.Handle("/metrics", promhttp.Handler())
addr := fmt.Sprintf("0.0.0.0:%s", port)

go func() {
if err = http.ListenAndServe(addr, nil); err != nil {
klog.Fatalf("failed to run prometheus server; %v", err)
}
}()

nodeName = val
return nil
}

// GetNodeName is meant for testing purposes
func GetNodeName() string {
return nodeName
}
77 changes: 77 additions & 0 deletions pkg/metrics/metrics_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package metrics

import (
"os"
"testing"
)

func TestSetup(t *testing.T) {
type testCase struct {
name string
arg string
env string
expected string
}

for _, tcase := range []testCase{
{
name: "all empty",
expected: mustHostname(),
},
{
name: "from arg",
arg: "arg.localtest.it",
expected: "arg.localtest.it",
},
{
name: "from env",
env: "env.localtest.it",
expected: "env.localtest.it",
},
{
name: "overriding order",
arg: "arg.localtest.it",
env: "env.localtest.it",
expected: "arg.localtest.it",
},
} {
t.Run(tcase.name, func(t *testing.T) {
if tcase.env != "" {
t.Setenv("NODE_NAME", tcase.env)
}

err := Setup(tcase.arg)
if err != nil {
t.Fatalf("Setup failed: %v", err)
}
got := GetNodeName()
if got != tcase.expected {
t.Errorf("invalid hostname: got %q expected %q", got, tcase.expected)
}
})
}
}

func mustHostname() string {
val, err := os.Hostname()
if err != nil {
panic(err)
}
return val
}
Loading

0 comments on commit 820900e

Please sign in to comment.