Node interface metrics application server code
This commit adds code in GO language to expose Physical Function interface device info and statistics (metrics) of a node using REST API service. NIC Statistics provided by Netlink. Following APIs are implemented: /metrics -- all statistics in OpenMetrics format /metrics/device/{DeviceName} -- particular device statistics in OpenMetrics format /metrics/pci-addr/{PciAddr} -- particular pci-address statistics in OpenMetrics format /json/metrics -- all metrics in json format /json/metrics/device/{DeviceName} -- particular device statistics in json format /json/metrics/pci-addr/{PciAddr} -- particular pci-address statistics in json format Test Plan: PASS: GO linting PASS: Unit test PASS: Api test. PASS: Docker image build process defined here [1] PASS: Created container image of this app, pushed to local registry and deployed on AIO-SX lab using sample deployment file. Then tested the APIs and validated the results. Story: 2010918 Task: 48794 [1]https://docs.starlingx.io/developer_resources/build_docker_image.html Change-Id: I5229b338b9e9afff3b02fe2389cfcd0c4e0590f6 Signed-off-by: AbhishekJ <abhishek.jaiswal@windriver.com>
This commit is contained in:
parent
b718b0e230
commit
4af59c5c7d
4
.gitignore
vendored
4
.gitignore
vendored
@ -33,3 +33,7 @@ cover
|
||||
AUTHORS
|
||||
ChangeLog
|
||||
*.sqlite
|
||||
**bin
|
||||
**go-compose
|
||||
*.log
|
||||
coverage.*
|
70
README.md
Normal file
70
README.md
Normal file
@ -0,0 +1,70 @@
|
||||
# app-node-interface-metrics-exporter
|
||||
app-node-interface-metrics-exporter flux cd app
|
||||
|
||||
#### Top Level Directory Structure
|
||||
```bash
|
||||
├── app-node-interface-metrics-exporter # Root Folder
|
||||
│ ├── debian_build_layer.cfg
|
||||
│ ├── debian_iso_image.inc
|
||||
│ ├── debian_pkg_dirs
|
||||
│ ├── metrics-exporter-api # Go code for api server which will expose Metrics for NIC .
|
||||
│ ├── python3-k8sapp-node-interface-metrics-exporter # lifecycle managemnt code to support flux apps
|
||||
│ ├── README.md
|
||||
│ ├── requirements.txt
|
||||
│ ├── stx-node-interface-metrics-exporter-helm # helm Package manager for the app
|
||||
│ ├── test-requirements.txt
|
||||
│ └── tox.ini
|
||||
```
|
||||
|
||||
> all command related to go code should run from `app-node-interface-metrics-exporter/metrics-exporter-api/docker/metrics-exporter-api`
|
||||
### About metrics-exporter-api
|
||||
It is Simple Http Server which reads network interface (PCI devices) and exposes following API's
|
||||
|
||||
1) http://{hostname}:{port}/metrics -- all node metrics in [OpenMetrics] format
|
||||
2) http://{hostname}:{port}/metrics/device/{DeviceName} -- specified interface metrics identified by device name in [OpenMetrics] format
|
||||
3) http://{hostname}:{port}/metrics/pci-addr/{PciAddr} -- specified interface metrics identified by PCI address in [OpenMetrics] format
|
||||
4) http://{hostname}:{port}/json/metrics -- all node metrics in [JSON] format
|
||||
5) http://{hostname}:{port}/json/metrics/device/{DeviceName} -- specified interface metrics identified by device name in [JSON] format
|
||||
6) http://{hostname}:{port}/json/metrics/pci-addr/{PciAddr} -- specified interface metrics identified by PCI address in [JSON] format
|
||||
|
||||
#### Makefile Support
|
||||
```bash
|
||||
$ make
|
||||
help: Show this help.
|
||||
install_dep: install go dependency
|
||||
run: run app on host machine
|
||||
test: run go unit test
|
||||
testcov: run go coverage test
|
||||
vet: run go vet
|
||||
lint: run go lint
|
||||
build_linux: Build application
|
||||
build_image: Build docker image
|
||||
```
|
||||
> `$ make run ` will start go dev http server
|
||||
|
||||
#### Run time Options / params for the metrics-exporter-app usage
|
||||
| Options | Help |
|
||||
| ------ | ------ |
|
||||
| `-log.file` | Log file name (default "node_metrics_api.log") |
|
||||
| `-log.level` | log level. (default "info"). Valid options trace, debug, info, warning, error, fatal and panic |
|
||||
| `-log.file` | Log file name (default "node_metrics_api.log") |
|
||||
| `-web.listen-address` | Port to listen on for web interface. (default ":9110") |
|
||||
| `-path.sys` | mounted path for host /sys inside container (default "/sys") |
|
||||
|
||||
#### Local / Devlopment Set UP for metrics-exporter-api
|
||||
`pre requisite go 1.21.0`
|
||||
|
||||
#### Container image reference for helm
|
||||
[Dockerfile](/metrics-exporter-api/debian/Dockerfile)
|
||||
|
||||
[Build Reference](/metrics-exporter-api/debian/metrics-exporter-api.stable_docker_image)
|
||||
|
||||
#### References
|
||||
[StarlingX](https://www.starlingx.io/)
|
||||
|
||||
[How to add a FluxCD App to Starlingx](https://wiki.openstack.org/wiki/StarlingX/Containers/HowToAddNewFluxCDAppInSTX)
|
||||
|
||||
[OpenMetrics](https://openmetrics.io/)
|
||||
|
||||
[JSON]: <https://www.json.org/>
|
||||
[OpenMetrics]: <https://openmetrics.io/>
|
1
debian_stable_docker_images.inc
Normal file
1
debian_stable_docker_images.inc
Normal file
@ -0,0 +1 @@
|
||||
metrics-exporter-api
|
41
metrics-exporter-api/debian/Dockerfile
Normal file
41
metrics-exporter-api/debian/Dockerfile
Normal file
@ -0,0 +1,41 @@
|
||||
#
|
||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# All Rights Reserved.
|
||||
#
|
||||
|
||||
# ARG BASE
|
||||
# FROM ${BASE}
|
||||
|
||||
# Build Stage
|
||||
FROM golang:alpine3.17 as buildstage
|
||||
|
||||
# Set destination for COPY
|
||||
WORKDIR /app
|
||||
|
||||
COPY metrics-exporter-api /app/
|
||||
|
||||
RUN go mod download
|
||||
|
||||
# Build
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -o /metrics-api-server
|
||||
|
||||
# Deploy binary which will make image size smaller
|
||||
FROM alpine:latest
|
||||
|
||||
# Set workdir context of current path wrt image
|
||||
WORKDIR /
|
||||
|
||||
COPY --from=buildstage /metrics-api-server /metrics-api-server
|
||||
|
||||
# Optional:
|
||||
# To bind to a TCP port, runtime parameters must be supplied to the
|
||||
# docker command.
|
||||
# But we can document in the Dockerfile what ports
|
||||
# the application is going to listen on by default.
|
||||
# https://docs.docker.com/engine/reference/builder/#expose
|
||||
EXPOSE 9110
|
||||
|
||||
ENTRYPOINT ["/metrics-api-server"]
|
@ -0,0 +1,4 @@
|
||||
BUILDER=docker
|
||||
LABEL=metrics-exporter-api
|
||||
DOCKER_CONTEXT=../docker
|
||||
DOCKER_FILE=./Dockerfile
|
@ -0,0 +1,45 @@
|
||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
||||
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# All Rights Reserved.
|
||||
run:
|
||||
deadline: 5m
|
||||
tests: true
|
||||
skip-dirs-use-default: true
|
||||
skip-files-use-default: true
|
||||
skip-dirs:
|
||||
- vendor
|
||||
skip-files:
|
||||
- bindata.go
|
||||
linters:
|
||||
enable-all: false
|
||||
enable:
|
||||
- unused
|
||||
- revive
|
||||
- deadcode
|
||||
- gosec
|
||||
- govet
|
||||
- goimports
|
||||
- gomodguard
|
||||
- dupword
|
||||
- godox
|
||||
- misspell
|
||||
- decorder
|
||||
- gofmt
|
||||
- sloglint
|
||||
- tagalign
|
||||
# Enable presets.
|
||||
# https://golangci-lint.run/usage/linters
|
||||
presets:
|
||||
- bugs
|
||||
- complexity
|
||||
- error
|
||||
- metalinter
|
||||
- performance
|
||||
- sql
|
||||
- test
|
||||
- unused
|
||||
# Run only fast linters from enabled linters set (first run won't be fast)
|
||||
# Default: false
|
||||
fast: true
|
45
metrics-exporter-api/docker/metrics-exporter-api/Makefile
Normal file
45
metrics-exporter-api/docker/metrics-exporter-api/Makefile
Normal file
@ -0,0 +1,45 @@
|
||||
#
|
||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# All Rights Reserved.
|
||||
#
|
||||
|
||||
# variables
|
||||
GO ?= go
|
||||
GOCOVER ?= $(GO) tool cover
|
||||
LABEL ?= metrics-exporter-api
|
||||
|
||||
# Targets
|
||||
help: ## Show this help.
|
||||
@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//'
|
||||
|
||||
apphelp: ## Show this help.
|
||||
$(GO) run . -h
|
||||
|
||||
install_dep: ## install go dependency
|
||||
$(GO) mod tidy
|
||||
|
||||
run: ## run app on host machine
|
||||
$(GO) run .
|
||||
|
||||
test: ## run go unit test
|
||||
$(GO) test ./...
|
||||
|
||||
testcov: ## run go coverage test
|
||||
$(GO) test -coverprofile=coverage.out ./...
|
||||
$(GO) tool cover -func=coverage.out
|
||||
$(GO) tool cover -html=coverage.out -o coverage.html
|
||||
|
||||
vet: ## run go vet
|
||||
$(GO) vet
|
||||
|
||||
lint: ## run go lint
|
||||
golangci-lint run
|
||||
|
||||
build_linux: ## Build application
|
||||
CGO_ENABLED=0 GOOS=linux go build -o metrics-api-server
|
||||
|
||||
build_image: ## Build docker image
|
||||
docker build -f ../../debian/Dockerfile -t starlingx/metrics-exporter-api ../
|
33
metrics-exporter-api/docker/metrics-exporter-api/go.mod
Normal file
33
metrics-exporter-api/docker/metrics-exporter-api/go.mod
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2023 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// All Rights Reserved.
|
||||
|
||||
|
||||
module opendev.org/starlingx/app-node-interface-metrics-exporter/metrics-exporter-api/docker/metrics-exporter-api
|
||||
|
||||
go 1.21.0
|
||||
|
||||
require (
|
||||
github.com/bsm/openmetrics v0.3.1
|
||||
github.com/gorilla/handlers v1.5.1
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/iancoleman/strcase v0.3.0
|
||||
github.com/rs/cors v1.10.1
|
||||
github.com/safchain/ethtool v0.3.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/vishvananda/netlink v1.1.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||
)
|
50
metrics-exporter-api/docker/metrics-exporter-api/go.sum
Normal file
50
metrics-exporter-api/docker/metrics-exporter-api/go.sum
Normal file
@ -0,0 +1,50 @@
|
||||
github.com/bsm/openmetrics v0.3.1 h1:nhR6QgaKaDmnbnvVP9R0JyPExt8Qa+n1cJk/ouGC4FY=
|
||||
github.com/bsm/openmetrics v0.3.1/go.mod h1:tabLMhjVjhdhFuwm9YenEVx0s54uvu56faEwYgD6L2g=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
|
||||
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo=
|
||||
github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0=
|
||||
github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7 h1:EBZoQjiKKPaLbPrbpssUfuHtwM6KV/vb4U85g/cigFY=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
63
metrics-exporter-api/docker/metrics-exporter-api/handler.go
Normal file
63
metrics-exporter-api/docker/metrics-exporter-api/handler.go
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright (c) 2023 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/rs/cors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Function to create route/handler for web request
|
||||
func allHandlers() http.Handler {
|
||||
router := mux.NewRouter()
|
||||
// allowed CORS
|
||||
// more info https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
|
||||
handler := cors.Default().Handler(router)
|
||||
|
||||
router.HandleFunc("/", rootGet).Methods("GET")
|
||||
router.HandleFunc("/healthz", healthzGet).Methods("GET")
|
||||
// Openmetrics endpoints
|
||||
router.HandleFunc("/metrics", metricsGet).Methods("GET")
|
||||
router.HandleFunc("/metrics/device/{DeviceName}", deviceGet).Methods("GET")
|
||||
router.HandleFunc("/metrics/pci-addr/{PciAddr}", pciAddrGet).Methods("GET")
|
||||
// json metrics endpoints
|
||||
router.HandleFunc("/json/metrics", metricsGetJSON).Methods("GET")
|
||||
router.HandleFunc("/json/metrics/device/{DeviceName}", deviceGetJSON).Methods("GET")
|
||||
router.HandleFunc("/json/metrics/pci-addr/{PciAddr}", pciAddrGetJSON).Methods("GET")
|
||||
|
||||
return handler
|
||||
}
|
||||
|
||||
// this endpoint shows the uptime of the application
|
||||
// it may be helpful to create probes in K8s
|
||||
func healthzGet(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
response := fmt.Sprintf("uptime: %s\n", time.Since(time.Unix(0, StartupTime)))
|
||||
_, err := w.Write([]byte(response))
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Since nothing is to show on root handler
|
||||
func rootGet(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
response := fmt.Sprintf("/ root uptime: %s\n", time.Since(time.Unix(0, StartupTime)))
|
||||
_, err := w.Write([]byte(response))
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright (c) 2023 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRootGet(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
r, _ := http.NewRequest("GET", "/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
rootGet(w, r)
|
||||
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
}
|
||||
|
||||
func TestHealthzGet(t *testing.T) {
|
||||
t.Parallel()
|
||||
r, _ := http.NewRequest("GET", "/healthz", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
healthzGet(w, r)
|
||||
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
}
|
||||
|
||||
func TestHandlerFunc(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
}
|
120
metrics-exporter-api/docker/metrics-exporter-api/json_handler.go
Normal file
120
metrics-exporter-api/docker/metrics-exporter-api/json_handler.go
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright (c) 2023 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// endpoint to get network metric of a node on which it is resides
|
||||
// http://<hostname>:<port>/json/metrics
|
||||
func metricsGetJSON(w http.ResponseWriter, _ *http.Request) {
|
||||
|
||||
DeviceStat := ListAllNetDev()
|
||||
// convert the map to a JSON encoded byte slice
|
||||
jsonContent, mErr := json.Marshal(DeviceStat)
|
||||
if mErr != nil {
|
||||
fmt.Println(mErr)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, err := w.Write(jsonContent)
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// endpoint to fetch metrics related to given network
|
||||
// device by name
|
||||
// http://<hostname>:<port>/json/device/<DeviceName>
|
||||
func deviceGetJSON(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
params := mux.Vars(r)
|
||||
DeviceName := params["DeviceName"]
|
||||
allDeviceStat := ListAllNetDev()
|
||||
|
||||
devStats, ok := allDeviceStat[DeviceName]
|
||||
|
||||
// If the key exists
|
||||
if ok {
|
||||
// convert the map to a JSON encoded byte slice
|
||||
jsonContent, mErr := json.Marshal(devStats)
|
||||
if mErr != nil {
|
||||
log.Error(mErr)
|
||||
return
|
||||
}
|
||||
|
||||
// convert the byte slice to a string
|
||||
// jsonString := string(jsonContent)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, err := w.Write(jsonContent)
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
} else {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
fmt.Fprintf(w, " %s Device Not Found ", DeviceName)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// endpoint to fetch metrics related to given network
|
||||
// device by pci addr
|
||||
// http://<hostname>:<port>/json/pci-addr/<PciAddr>
|
||||
func pciAddrGetJSON(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
found := false
|
||||
params := mux.Vars(r)
|
||||
PciAddr := params["PciAddr"]
|
||||
allDeviceStat := ListAllNetDev()
|
||||
|
||||
for _, dev := range allDeviceStat {
|
||||
|
||||
if dev.Pciaddr == PciAddr {
|
||||
found = true
|
||||
// convert the map to a JSON encoded byte slice
|
||||
jsonContent, mErr := json.Marshal(dev)
|
||||
if mErr != nil {
|
||||
log.Error(mErr)
|
||||
return
|
||||
}
|
||||
|
||||
// convert the byte slice to a string
|
||||
// jsonString := string(jsonContent)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
_, err := w.Write(jsonContent)
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
fmt.Fprintf(w, " %s Pci Addr Not found ", PciAddr)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
Copyright (c) 2023 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMetricsGetJson(t *testing.T) {
|
||||
t.Parallel()
|
||||
// /device/{DeviceName}
|
||||
r, _ := http.NewRequest("GET", "/json/metrics/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
metricsGetJSON(w, r)
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
assert.Equal(t, w.Header().Get("Content-Type"), "application/json")
|
||||
}
|
||||
|
||||
func TestDeviceGetJson(t *testing.T) {
|
||||
t.Parallel()
|
||||
// /device/{DeviceName}
|
||||
r, _ := http.NewRequest("GET", "/json/device/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
// Hack to try to fake gorilla/mux vars
|
||||
vars := map[string]string{
|
||||
"DeviceName": "eth0",
|
||||
}
|
||||
|
||||
r = mux.SetURLVars(r, vars)
|
||||
|
||||
deviceGetJSON(w, r)
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
assert.Equal(t, w.Header().Get("Content-Type"), "application/json")
|
||||
}
|
||||
|
||||
func TestDeviceGetJsonNeg(t *testing.T) {
|
||||
t.Parallel()
|
||||
// /device/{DeviceName}
|
||||
r, _ := http.NewRequest("GET", "/json/device/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
// Hack to try to fake gorilla/mux vars
|
||||
vars := map[string]string{
|
||||
"DeviceName": "404",
|
||||
}
|
||||
|
||||
r = mux.SetURLVars(r, vars)
|
||||
|
||||
deviceGetJSON(w, r)
|
||||
assert.Equal(t, http.StatusNotFound, w.Code)
|
||||
}
|
||||
|
||||
func TestPciAddrGetJsonNeg(t *testing.T) {
|
||||
t.Parallel()
|
||||
r, _ := http.NewRequest("GET", "/json/pci-addr/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
// Hack to try to fake gorilla/mux vars
|
||||
vars := map[string]string{
|
||||
"PciAddr": "11:00:00",
|
||||
}
|
||||
|
||||
r = mux.SetURLVars(r, vars)
|
||||
|
||||
pciAddrGetJSON(w, r)
|
||||
|
||||
assert.Equal(t, http.StatusNotFound, w.Code)
|
||||
}
|
61
metrics-exporter-api/docker/metrics-exporter-api/main.go
Normal file
61
metrics-exporter-api/docker/metrics-exporter-api/main.go
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright (c) 2023 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/handlers"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
handler := allHandlers()
|
||||
|
||||
// StartUp Time used to calculate Uptime for the App
|
||||
atomic.StoreInt64(&StartupTime, time.Now().UnixNano())
|
||||
|
||||
// Parse the flags or commandline arguments
|
||||
flag.Parse()
|
||||
|
||||
// log setup
|
||||
logFile := OpenFile(*logFileName)
|
||||
// close file on exit
|
||||
defer logFile.Close()
|
||||
logOutput := io.MultiWriter(os.Stdout, logFile)
|
||||
log.SetOutput(logOutput)
|
||||
logLevel, _ := log.ParseLevel(*logLevel)
|
||||
// Only log the debug severity or above
|
||||
log.SetLevel(logLevel)
|
||||
|
||||
// Print all flags what valuse is used
|
||||
flag.VisitAll(func(f *flag.Flag) {
|
||||
log.Infof("%s: %s", f.Name, f.Value)
|
||||
})
|
||||
|
||||
loggedRouter := handlers.LoggingHandler(os.Stdout, handler)
|
||||
server := &http.Server{
|
||||
Addr: *addr,
|
||||
ReadHeaderTimeout: 3 * time.Second,
|
||||
Handler: loggedRouter,
|
||||
}
|
||||
// Starting Http server
|
||||
err := server.ListenAndServe()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// on exit log
|
||||
log.Info("Server stopped\n")
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
/*
|
||||
Copyright (c) 2023 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"github.com/bsm/openmetrics"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/iancoleman/strcase"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// endpoint to get all network metric of a node on which it is resides
|
||||
// http://<hostname>:<port>/metrics
|
||||
func metricsGet(w http.ResponseWriter, _ *http.Request) {
|
||||
|
||||
openMetContent := allDevInfoOpenMet()
|
||||
w.Header().Set("Content-Type", OpenMetContentType)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
_, err := w.Write([]byte(openMetContent))
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// endpoint to fetch metrics related to given network
|
||||
// device by name
|
||||
// http://<hostname>:<port>/device/<DeviceName>
|
||||
func deviceGet(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
params := mux.Vars(r)
|
||||
devName := params["DeviceName"]
|
||||
allDeviceStat := ListAllNetDev()
|
||||
|
||||
devStats, ok := allDeviceStat[devName]
|
||||
|
||||
// If the key exists
|
||||
if ok {
|
||||
devStatOpnFmt := devStatOpenMet(devStats)
|
||||
w.Header().Set("Content-Type", OpenMetContentType)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, err := w.Write([]byte(devStatOpnFmt))
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
} else {
|
||||
w.Header().Set("Content-Type", OpenMetContentType)
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
fmt.Fprintf(w, " %s Device Not Found ", devName)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// endpoint to fetch metrics related to given network
|
||||
// device by pci addr
|
||||
// http://<hostname>:<port>/pci-addr/<PciAddr>
|
||||
func pciAddrGet(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
found := false
|
||||
params := mux.Vars(r)
|
||||
PciAddr := params["PciAddr"]
|
||||
allDeviceStat := ListAllNetDev()
|
||||
|
||||
for _, devStats := range allDeviceStat {
|
||||
|
||||
if devStats.Pciaddr == PciAddr {
|
||||
found = true
|
||||
DevStatOpnFmt := devStatOpenMet(devStats)
|
||||
w.Header().Set("Content-Type", OpenMetContentType)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, err := w.Write([]byte(DevStatOpnFmt))
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
w.Header().Set("Content-Type", OpenMetContentType)
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
fmt.Fprintf(w, " %s Pci Addr Not found ", PciAddr)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// function to register and update network device info
|
||||
// and statistics to Openmetrics format
|
||||
func allDevInfoOpenMet() string {
|
||||
|
||||
// get all device info from lspci command
|
||||
allDeviceInfo := ListAllNetDev()
|
||||
// store stats data in openmetrics
|
||||
var openMetContent string
|
||||
|
||||
for _, device := range allDeviceInfo {
|
||||
openMetContent += devStatOpenMet(device)
|
||||
}
|
||||
|
||||
return openMetContent
|
||||
}
|
||||
|
||||
func devStatOpenMet(devInfo DevInfo) string {
|
||||
var reg = openmetrics.NewRegistry()
|
||||
var openMetVar = regDevInfo(reg)
|
||||
|
||||
openMetVar.With(
|
||||
devInfo.Name,
|
||||
devInfo.HardwareAddr,
|
||||
devInfo.Broadcast,
|
||||
// devInfo.duplex,
|
||||
devInfo.Alias,
|
||||
devInfo.OperState,
|
||||
devInfo.Pciaddr,
|
||||
)
|
||||
|
||||
// convert all netlink.LinkStatistics Struct to map
|
||||
fields := reflect.TypeOf(*devInfo.Statistics)
|
||||
// valPtr := reflect.ValueOf(devInfo.Statistics)
|
||||
values := reflect.Indirect(reflect.ValueOf(devInfo.Statistics))
|
||||
// get the number of field for looping n times
|
||||
num := fields.NumField()
|
||||
for i := 0; i < num; i++ {
|
||||
field := fields.Field(i)
|
||||
value := values.Field(i)
|
||||
log.Debug("Type:", field.Type, ",", field.Name, "=", value, "\n")
|
||||
|
||||
// register counter
|
||||
name := "network_interface_" + strcase.ToSnake(field.Name)
|
||||
var newInfo = reg.Counter(openmetrics.Desc{
|
||||
Name: name,
|
||||
Help: name,
|
||||
Labels: []string{"device"},
|
||||
})
|
||||
newInfo.With(
|
||||
devInfo.Name,
|
||||
).Add(float64(value.Uint()))
|
||||
}
|
||||
|
||||
// create buffer to return
|
||||
var buf bytes.Buffer
|
||||
if _, err := reg.WriteTo(&buf); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// buffer.String()
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// function to create Informational Openmetrics paramater / variable
|
||||
// for Network Interface Device Info
|
||||
func regDevInfo(reg *openmetrics.Registry) openmetrics.InfoFamily {
|
||||
|
||||
var deviceInfo = reg.Info(openmetrics.Desc{
|
||||
Name: "network_interface_device",
|
||||
Help: "network_interface_device ",
|
||||
Labels: []string{"name", "address", "broadcast", "ifalias", "operstate", "pciaddr"},
|
||||
})
|
||||
|
||||
return deviceInfo
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
Copyright (c) 2023 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMetricsGet(t *testing.T) {
|
||||
t.Parallel()
|
||||
// /device/{DeviceName}
|
||||
r, _ := http.NewRequest("GET", "/json/metrics/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
metricsGet(w, r)
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
}
|
||||
|
||||
func TestDeviceGet(t *testing.T) {
|
||||
t.Parallel()
|
||||
// /device/{DeviceName}
|
||||
r, _ := http.NewRequest("GET", "/json/device/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
// Hack to try to fake gorilla/mux vars
|
||||
vars := map[string]string{
|
||||
"DeviceName": "eth0",
|
||||
}
|
||||
|
||||
r = mux.SetURLVars(r, vars)
|
||||
|
||||
deviceGet(w, r)
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
}
|
||||
|
||||
func TestDeviceGetNeg(t *testing.T) {
|
||||
t.Parallel()
|
||||
// /device/{DeviceName}
|
||||
r, _ := http.NewRequest("GET", "/json/device/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
// Hack to try to fake gorilla/mux vars
|
||||
vars := map[string]string{
|
||||
"DeviceName": "404",
|
||||
}
|
||||
|
||||
r = mux.SetURLVars(r, vars)
|
||||
|
||||
deviceGet(w, r)
|
||||
assert.Equal(t, http.StatusNotFound, w.Code)
|
||||
}
|
||||
|
||||
func TestPciAddrGetNeg(t *testing.T) {
|
||||
t.Parallel()
|
||||
r, _ := http.NewRequest("GET", "/json/pci-addr/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
// Hack to try to fake gorilla/mux vars
|
||||
vars := map[string]string{
|
||||
"PciAddr": "11:00:00",
|
||||
}
|
||||
|
||||
r = mux.SetURLVars(r, vars)
|
||||
|
||||
pciAddrGet(w, r)
|
||||
|
||||
assert.Equal(t, http.StatusNotFound, w.Code)
|
||||
}
|
92
metrics-exporter-api/docker/metrics-exporter-api/util.go
Normal file
92
metrics-exporter-api/docker/metrics-exporter-api/util.go
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright (c) 2023 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/safchain/ethtool"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
// DevInfo Data structures to store Device info.
|
||||
type DevInfo struct {
|
||||
Name string
|
||||
Type string
|
||||
HardwareAddr string
|
||||
OperState string
|
||||
EncapType string
|
||||
Alias string
|
||||
Pciaddr string
|
||||
Broadcast string
|
||||
Statistics *netlink.LinkStatistics
|
||||
}
|
||||
|
||||
// OpenFile function
|
||||
func OpenFile(fileName string) *os.File {
|
||||
logFile := fileName
|
||||
// Open logfile
|
||||
f, err := os.OpenFile(logFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
log.Info("Failed to create logfile" + logFile)
|
||||
log.Error(err)
|
||||
panic(err)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// ListAllNetDev func to findout all the Pcie Devices and its statistics
|
||||
// which have network or ethernet in Classname
|
||||
// func ListAllPciNetDev(sysPath string) map[string]map[string]string {
|
||||
func ListAllNetDev() map[string]DevInfo {
|
||||
|
||||
// make the list of dict containing DevInfo
|
||||
allDeviceInfo := make(map[string]DevInfo)
|
||||
|
||||
allNetDevices, _ := netlink.LinkList()
|
||||
for _, dev := range allNetDevices {
|
||||
deviceName := dev.Attrs().Name
|
||||
|
||||
pciaddr, err := ethtool.BusInfo(dev.Attrs().Name)
|
||||
if err != nil {
|
||||
log.Infof(
|
||||
"Unable to fetch Info from ethtool for %s, err: %s",
|
||||
deviceName, err,
|
||||
)
|
||||
}
|
||||
|
||||
var broadcast string
|
||||
// try to fetch Broadcast Address
|
||||
addr, err := netlink.AddrList(dev, netlink.NewRule().Family)
|
||||
|
||||
// we know that all device will not have Broadcast addr
|
||||
// so just logged the name of devices which are not
|
||||
if err != nil {
|
||||
log.Info("Unable to fetch AddrList ", err)
|
||||
}
|
||||
if len(addr) > 0 {
|
||||
broadcast = addr[0].Broadcast.String()
|
||||
}
|
||||
|
||||
allDeviceInfo[deviceName] = DevInfo{
|
||||
Name: deviceName,
|
||||
Type: dev.Type(),
|
||||
HardwareAddr: dev.Attrs().HardwareAddr.String(),
|
||||
OperState: dev.Attrs().OperState.String(),
|
||||
EncapType: dev.Attrs().EncapType,
|
||||
Alias: dev.Attrs().Alias,
|
||||
Pciaddr: pciaddr,
|
||||
Broadcast: broadcast,
|
||||
Statistics: dev.Attrs().Statistics,
|
||||
}
|
||||
|
||||
}
|
||||
return allDeviceInfo
|
||||
}
|
31
metrics-exporter-api/docker/metrics-exporter-api/variable.go
Normal file
31
metrics-exporter-api/docker/metrics-exporter-api/variable.go
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright (c) 2023 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import "flag"
|
||||
|
||||
var (
|
||||
addr = flag.String(
|
||||
"web.listen-address", ":9110", "Port to listen on for web interface.",
|
||||
)
|
||||
logLevel = flag.String(
|
||||
"log.level", "info", "log level. Valid options trace,"+
|
||||
" debug, info, warning, error, fatal and panic",
|
||||
)
|
||||
logFileName = flag.String(
|
||||
"log.file", "node_metrics_api.log", "Log file name",
|
||||
)
|
||||
|
||||
// StartupTime string
|
||||
StartupTime int64
|
||||
|
||||
// OpenMetContentType content Type
|
||||
// OpenMetContentType = "application/openmetrics-text; version=1.0.0; charset=utf-8"
|
||||
OpenMetContentType = "text/plain"
|
||||
)
|
Loading…
Reference in New Issue
Block a user