From 8e8be09ed90d05755a9b638a2bbc41fa19a543a6 Mon Sep 17 00:00:00 2001 From: Thomas Gruber Date: Wed, 20 Nov 2024 16:22:39 +0100 Subject: [PATCH] Merge latest commits from `develop` to `main` branch (#114) * Add cpu_used (all-cpu_idle) to CpustatCollector * Update cc-metric-collector.init * Allow selection of timestamp precision in HttpSink * Add comment about precision requirement for cc-metric-store * Fix for API changes in gofish@v0.15.0 * Update requirements to latest version * Read sensors through redfish * Update golang toolchain to 1.21 * Remove stray error check * Update main config in configuration.md * Update Release action to use golang 1.22 stable release, no golang RPMs anymore * Update runonce action to use golang 1.22 stable release, no golang RPMs anymore * Update README.md Use right JSON type in configuration * Update sink's README * Test whether ipmitool or ipmi-sensors can be executed without errors --------- Co-authored-by: Holger Obermaier Co-authored-by: Holger Obermaier <40787752+ho-ob@users.noreply.github.com> --- .github/workflows/Release.yml | 22 +- .github/workflows/runonce.yml | 56 ++--- collectors/customCmdMetric.go | 10 +- collectors/ipmiMetric.go | 24 ++- docs/configuration.md | 4 +- go.mod | 106 ++-------- go.sum | 273 ++++-------------------- receivers/redfishReceiver.go | 343 +++++++++++++++++++++++-------- receivers/redfishReceiver.md | 23 ++- scripts/cc-metric-collector.init | 2 +- sinks/httpSink.go | 21 +- sinks/httpSink.md | 8 +- 12 files changed, 429 insertions(+), 463 deletions(-) diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml index 4356715..36b812e 100644 --- a/.github/workflows/Release.yml +++ b/.github/workflows/Release.yml @@ -44,16 +44,16 @@ jobs: # Use dnf to install build dependencies - name: Install build dependencies run: | - dnf --assumeyes install \ - http://mirror.centos.org/centos/8-stream/AppStream/x86_64/os/Packages/golang-1.20.6-2.module_el8+658+f14b2092.x86_64.rpm \ - http://mirror.centos.org/centos/8-stream/AppStream/x86_64/os/Packages/golang-bin-1.20.6-2.module_el8+658+f14b2092.x86_64.rpm \ - http://mirror.centos.org/centos/8-stream/AppStream/x86_64/os/Packages/golang-src-1.20.6-2.module_el8+658+f14b2092.noarch.rpm \ - http://mirror.centos.org/centos/8-stream/AppStream/x86_64/os/Packages/go-toolset-1.20.6-1.module_el8+602+8bb8a8d6.x86_64.rpm + wget -q https://go.dev/dl/go1.22.4.linux-amd64.tar.gz --output-document=- | \ + tar --directory=/usr/local --extract --gzip + export PATH=/usr/local/go/bin:/usr/local/go/pkg/tool/linux_amd64:$PATH + go version - name: RPM build MetricCollector id: rpmbuild run: | git config --global --add safe.directory /__w/cc-metric-collector/cc-metric-collector + export PATH=/usr/local/go/bin:/usr/local/go/pkg/tool/linux_amd64:$PATH make RPM # AlmaLinux 8 is a derivate of RedHat Enterprise Linux 8 (UBI8), @@ -114,16 +114,16 @@ jobs: # Use dnf to install build dependencies - name: Install build dependencies run: | - dnf --assumeyes --disableplugin=subscription-manager install \ - http://mirror.centos.org/centos/8-stream/AppStream/x86_64/os/Packages/golang-1.20.6-2.module_el8+658+f14b2092.x86_64.rpm \ - http://mirror.centos.org/centos/8-stream/AppStream/x86_64/os/Packages/golang-bin-1.20.6-2.module_el8+658+f14b2092.x86_64.rpm \ - http://mirror.centos.org/centos/8-stream/AppStream/x86_64/os/Packages/golang-src-1.20.6-2.module_el8+658+f14b2092.noarch.rpm \ - http://mirror.centos.org/centos/8-stream/AppStream/x86_64/os/Packages/go-toolset-1.20.6-1.module_el8+602+8bb8a8d6.x86_64.rpm + wget -q https://go.dev/dl/go1.22.4.linux-amd64.tar.gz --output-document=- | \ + tar --directory=/usr/local --extract --gzip + export PATH=/usr/local/go/bin:/usr/local/go/pkg/tool/linux_amd64:$PATH + go version - name: RPM build MetricCollector id: rpmbuild run: | git config --global --add safe.directory /__w/cc-metric-collector/cc-metric-collector + export PATH=/usr/local/go/bin:/usr/local/go/pkg/tool/linux_amd64:$PATH make RPM # See: https://github.com/actions/upload-artifact @@ -165,7 +165,7 @@ jobs: # Use official golang package - name: Install Golang run: | - wget -q https://go.dev/dl/go1.21.1.linux-amd64.tar.gz --output-document=- | \ + wget -q https://go.dev/dl/go1.22.4.linux-amd64.tar.gz --output-document=- | \ tar --directory=/usr/local --extract --gzip export PATH=/usr/local/go/bin:/usr/local/go/pkg/tool/linux_amd64:$PATH go version diff --git a/.github/workflows/runonce.yml b/.github/workflows/runonce.yml index 96a7a9f..ddc41b3 100644 --- a/.github/workflows/runonce.yml +++ b/.github/workflows/runonce.yml @@ -10,32 +10,6 @@ on: jobs: - # - # Job build-1-20 - # Build on latest Ubuntu using golang version 1.20 - # - build-1-20: - runs-on: ubuntu-latest - steps: - # See: https://github.com/marketplace/actions/checkout - # Checkout git repository and submodules - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: recursive - - # See: https://github.com/marketplace/actions/setup-go-environment - - name: Setup Golang - uses: actions/setup-go@v4 - with: - go-version: '1.20' - - - name: Build MetricCollector - run: make - - - name: Run MetricCollector once - run: ./cc-metric-collector --once --config .github/ci-config.json - # # Job build-1-21 # Build on latest Ubuntu using golang version 1.21 @@ -62,6 +36,32 @@ jobs: - name: Run MetricCollector once run: ./cc-metric-collector --once --config .github/ci-config.json + # + # Job build-1-22 + # Build on latest Ubuntu using golang version 1.22 + # + build-1-22: + runs-on: ubuntu-latest + steps: + # See: https://github.com/marketplace/actions/checkout + # Checkout git repository and submodules + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + # See: https://github.com/marketplace/actions/setup-go-environment + - name: Setup Golang + uses: actions/setup-go@v4 + with: + go-version: '1.22' + + - name: Build MetricCollector + run: make + + - name: Run MetricCollector once + run: ./cc-metric-collector --once --config .github/ci-config.json + # # Build on AlmaLinux 8 using go-toolset # @@ -98,6 +98,7 @@ jobs: id: rpmbuild run: | git config --global --add safe.directory /__w/cc-metric-collector/cc-metric-collector + export PATH=/usr/local/go/bin:/usr/local/go/pkg/tool/linux_amd64:$PATH make RPM # @@ -133,6 +134,7 @@ jobs: id: rpmbuild run: | git config --global --add safe.directory /__w/cc-metric-collector/cc-metric-collector + export PATH=/usr/local/go/bin:/usr/local/go/pkg/tool/linux_amd64:$PATH make RPM # @@ -157,11 +159,13 @@ jobs: submodules: recursive fetch-depth: 0 # Use official golang package + # See: https://github.com/marketplace/actions/setup-go-environment - name: Setup Golang uses: actions/setup-go@v4 with: go-version: '1.21' + - name: DEB build MetricCollector id: dpkg-build run: | diff --git a/collectors/customCmdMetric.go b/collectors/customCmdMetric.go index e89ea54..ae205f1 100644 --- a/collectors/customCmdMetric.go +++ b/collectors/customCmdMetric.go @@ -99,10 +99,7 @@ func (m *CustomCmdCollector) Read(interval time.Duration, output chan lp.CCMetri continue } - y := lp.FromInfluxMetric(c) - if err == nil { - output <- y - } + output <- lp.FromInfluxMetric(c) } } for _, file := range m.files { @@ -121,10 +118,7 @@ func (m *CustomCmdCollector) Read(interval time.Duration, output chan lp.CCMetri if skip { continue } - y := lp.FromInfluxMetric(f) - if err == nil { - output <- y - } + output <- lp.FromInfluxMetric(f) } } } diff --git a/collectors/ipmiMetric.go b/collectors/ipmiMetric.go index d53d8af..a4b4b88 100644 --- a/collectors/ipmiMetric.go +++ b/collectors/ipmiMetric.go @@ -12,6 +12,7 @@ import ( "strconv" "strings" "time" + cclog "github.com/ClusterCockpit/cc-metric-collector/pkg/ccLogger" lp "github.com/ClusterCockpit/cc-metric-collector/pkg/ccMetric" ) @@ -54,15 +55,30 @@ func (m *IpmiCollector) Init(config json.RawMessage) error { // Check if executables ipmitool or ipmisensors are found p, err := exec.LookPath(m.config.IpmitoolPath) if err == nil { - m.ipmitool = p + command := exec.Command(p) + err := command.Run() + if err != nil { + cclog.ComponentError(m.name, fmt.Sprintf("Failed to execute %s: %v", p, err.Error())) + m.ipmitool = "" + } else { + m.ipmitool = p + } } p, err = exec.LookPath(m.config.IpmisensorsPath) if err == nil { - m.ipmisensors = p + command := exec.Command(p) + err := command.Run() + if err != nil { + cclog.ComponentError(m.name, fmt.Sprintf("Failed to execute %s: %v", p, err.Error())) + m.ipmisensors = "" + } else { + m.ipmisensors = p + } } if len(m.ipmitool) == 0 && len(m.ipmisensors) == 0 { - return errors.New("no IPMI reader found") + return errors.New("no usable IPMI reader found") } + m.init = true return nil } @@ -119,8 +135,8 @@ func (m *IpmiCollector) readIpmiTool(cmd string, output chan lp.CCMetric) { cclog.ComponentError( m.name, fmt.Sprintf("readIpmiTool(): Failed to wait for the end of command \"%s\": %v\n", command.String(), err), - fmt.Sprintf("readIpmiTool(): command stderr: \"%s\"\n", string(errMsg)), ) + cclog.ComponentError(m.name, fmt.Sprintf("readIpmiTool(): command stderr: \"%s\"\n", strings.TrimSpace(string(errMsg)))) return } } diff --git a/docs/configuration.md b/docs/configuration.md index a13d3a5..93c8693 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -12,8 +12,8 @@ The global file contains the paths to the other four files and some global optio "collectors" : "collectors.json", "receivers" : "receivers.json", "router" : "router.json", - "interval": 10, - "duration": 1 + "interval": "10s", + "duration": "1s" } ``` diff --git a/go.mod b/go.mod index 9c3c228..f6b7275 100644 --- a/go.mod +++ b/go.mod @@ -1,105 +1,41 @@ module github.com/ClusterCockpit/cc-metric-collector -go 1.20 +go 1.21 require ( github.com/ClusterCockpit/cc-units v0.4.0 github.com/ClusterCockpit/go-rocm-smi v0.3.0 - github.com/NVIDIA/go-nvml v0.12.0-1 + github.com/NVIDIA/go-nvml v0.12.0-2 github.com/PaesslerAG/gval v1.2.2 - github.com/fsnotify/fsnotify v1.6.0 - github.com/gorilla/mux v1.8.0 - github.com/influxdata/influxdb-client-go/v2 v2.12.3 + github.com/fsnotify/fsnotify v1.7.0 + github.com/gorilla/mux v1.8.1 + github.com/influxdata/influxdb-client-go/v2 v2.13.0 github.com/influxdata/line-protocol v0.0.0-20210922203350-b1ad95c89adf github.com/influxdata/line-protocol/v2 v2.2.1 - github.com/nats-io/nats.go v1.30.2 - github.com/prometheus/client_golang v1.17.0 - github.com/stmcginnis/gofish v0.14.0 - github.com/tklauser/go-sysconf v0.3.12 + github.com/nats-io/nats.go v1.33.1 + github.com/prometheus/client_golang v1.19.0 + github.com/stmcginnis/gofish v0.15.0 + github.com/tklauser/go-sysconf v0.3.13 golang.design/x/thread v0.0.0-20210122121316-335e9adffdf1 - golang.org/x/exp v0.0.0-20231006140011-7918f672742d - golang.org/x/sys v0.13.0 + golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 + golang.org/x/sys v0.18.0 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect - github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect - github.com/CloudyKit/jet/v6 v6.2.0 // indirect - github.com/Joker/jade v1.1.3 // indirect - github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect - github.com/andybalholm/brotli v1.0.5 // indirect github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect - github.com/aymerick/douceur v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bytedance/sonic v1.10.2 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect - github.com/chenzhuoyu/iasm v0.9.0 // indirect - github.com/deepmap/oapi-codegen v1.15.0 // indirect - github.com/fatih/structs v1.1.0 // indirect - github.com/flosch/pongo2/v4 v4.0.2 // indirect - github.com/gabriel-vasile/mimetype v1.4.2 // indirect - github.com/gin-contrib/sse v0.1.0 // indirect - github.com/gin-gonic/gin v1.9.1 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.15.5 // indirect - github.com/goccy/go-json v0.10.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 // indirect - github.com/google/uuid v1.3.1 // indirect - github.com/gorilla/css v1.0.0 // indirect - github.com/iris-contrib/schema v0.0.6 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/kataras/blocks v0.0.8 // indirect - github.com/kataras/golog v0.1.9 // indirect - github.com/kataras/iris/v12 v12.2.7 // indirect - github.com/kataras/pio v0.0.12 // indirect - github.com/kataras/sitemap v0.0.6 // indirect - github.com/kataras/tunnel v0.0.4 // indirect - github.com/klauspost/compress v1.17.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.5 // indirect - github.com/labstack/echo/v4 v4.11.1 // indirect - github.com/labstack/gommon v0.4.0 // indirect - github.com/leodido/go-urn v1.2.4 // indirect - github.com/mailgun/raymond/v2 v2.0.48 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/microcosm-cc/bluemonday v1.0.25 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/nats-io/nats-server/v2 v2.8.4 // indirect - github.com/nats-io/nkeys v0.4.5 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nuid v1.0.1 // indirect - github.com/pelletier/go-toml/v2 v2.1.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.44.0 // indirect + github.com/oapi-codegen/runtime v1.1.1 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.49.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/schollz/closestmatch v2.1.0+incompatible // indirect github.com/shopspring/decimal v1.3.1 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect - github.com/tdewolff/minify/v2 v2.12.9 // indirect - github.com/tdewolff/parse/v2 v2.6.8 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect - github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.2.11 // indirect - github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasttemplate v1.2.2 // indirect - github.com/vmihailenco/msgpack/v5 v5.4.0 // indirect - github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - github.com/yosssi/ace v0.0.5 // indirect - golang.org/x/arch v0.5.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/net v0.16.0 // indirect - golang.org/x/text v0.13.0 // indirect - golang.org/x/time v0.3.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + github.com/tklauser/numcpus v0.7.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/net v0.22.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect ) diff --git a/go.sum b/go.sum index c40a1b8..896df0b 100644 --- a/go.sum +++ b/go.sum @@ -1,94 +1,37 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= -github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= -github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= -github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= github.com/ClusterCockpit/cc-units v0.4.0 h1:zP5DOu99GmErW0tCDf0gcLrlWt42RQ9dpoONEOh4cI0= github.com/ClusterCockpit/cc-units v0.4.0/go.mod h1:3S3PAhAayS3pbgcT4q9Vn9VJw22Op51X0YimtG77zBw= github.com/ClusterCockpit/go-rocm-smi v0.3.0 h1:1qZnSpG7/NyLtc7AjqnUL9Jb8xtqG1nMVgp69rJfaR8= github.com/ClusterCockpit/go-rocm-smi v0.3.0/go.mod h1:+I3UMeX3OlizXDf1WpGD43W4KGZZGVSGmny6rTeOnWA= -github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= -github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= -github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= github.com/NVIDIA/go-nvml v0.11.6-0/go.mod h1:hy7HYeQy335x6nEss0Ne3PYqleRa6Ct+VKD9RQ4nyFs= -github.com/NVIDIA/go-nvml v0.12.0-1 h1:6mdjtlFo+17dWL7VFPfuRMtf0061TF4DKls9pkSw6uM= -github.com/NVIDIA/go-nvml v0.12.0-1/go.mod h1:hy7HYeQy335x6nEss0Ne3PYqleRa6Ct+VKD9RQ4nyFs= +github.com/NVIDIA/go-nvml v0.12.0-2 h1:Sg239yy7jmopu/cuvYauoMj9fOpcGMngxVxxS1EBXeY= +github.com/NVIDIA/go-nvml v0.12.0-2/go.mod h1:7ruy85eOM73muOc/I37euONSwEyFqZsv5ED9AogD4G0= github.com/PaesslerAG/gval v1.2.2 h1:Y7iBzhgE09IGTt5QgGQ2IdaYYYOU134YGHBThD+wm9E= github.com/PaesslerAG/gval v1.2.2/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbVR+C6xac= github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8= github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= -github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= -github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= -github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= -github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= -github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= -github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= 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/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= -github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= -github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= -github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE= -github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= -github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= -github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= -github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo= -github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deepmap/oapi-codegen v1.15.0 h1:SQqViaeb4k2vMul8gx12oDOIadEtoRqTdLkxjzqtQ90= -github.com/deepmap/oapi-codegen v1.15.0/go.mod h1:a6KoHV7lMRwsPoEg2C6NDHiXYV3EQfiFocOlJ8dgJQE= -github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= -github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= github.com/frankban/quicktest v1.11.0/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s= github.com/frankban/quicktest v1.11.2/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s= github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= -github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= -github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 h1:EcQR3gusLHN46TAD+G+EbaaqJArt5vHhNpXAa12PQf4= -github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= -github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/influxdata/influxdb-client-go/v2 v2.12.3 h1:28nRlNMRIV4QbtIUvxhWqaxn0IpXeMSkY/uJa/O/vC4= -github.com/influxdata/influxdb-client-go/v2 v2.12.3/go.mod h1:IrrLUbCjjfkmRuaCiGQg4m2GbkaeJDcuWoxiWdQEbA0= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/influxdata/influxdb-client-go/v2 v2.13.0 h1:ioBbLmR5NMbAjP4UVA5r9b5xGjpABD7j65pI8kFphDM= +github.com/influxdata/influxdb-client-go/v2 v2.13.0/go.mod h1:k+spCbt9hcvqvUiz0sr5D8LolXHqAAOfPw9v/RIRHl4= github.com/influxdata/line-protocol v0.0.0-20210922203350-b1ad95c89adf h1:7JTmneyiNEwVBOHSjoMxiWAqB992atOeepeFYegn5RU= github.com/influxdata/line-protocol v0.0.0-20210922203350-b1ad95c89adf/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= github.com/influxdata/line-protocol-corpus v0.0.0-20210519164801-ca6fa5da0184/go.mod h1:03nmhxzZ7Xk2pdG+lmMd7mHDfeVOYFyhOgwO61qWU98= @@ -97,199 +40,63 @@ github.com/influxdata/line-protocol/v2 v2.0.0-20210312151457-c52fdecb625a/go.mod github.com/influxdata/line-protocol/v2 v2.1.0/go.mod h1:QKw43hdUBg3GTk2iC3iyCxksNj7PX9aUSeYOYE/ceHY= github.com/influxdata/line-protocol/v2 v2.2.1 h1:EAPkqJ9Km4uAxtMRgUubJyqAr6zgWM0dznKMLRauQRE= github.com/influxdata/line-protocol/v2 v2.2.1/go.mod h1:DmB3Cnh+3oxmG6LOBIxce4oaL4CPj3OmMPgvauXh+tM= -github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= -github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= -github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= -github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= -github.com/kataras/golog v0.1.9 h1:vLvSDpP7kihFGKFAvBSofYo7qZNULYSHOH2D7rPTKJk= -github.com/kataras/golog v0.1.9/go.mod h1:jlpk/bOaYCyqDqH18pgDHdaJab72yBE6i0O3s30hpWY= -github.com/kataras/iris/v12 v12.2.7 h1:C9KWZmZT5pB5f2ot1XYWDBdi5XeTz0CGweHRXCDARZg= -github.com/kataras/iris/v12 v12.2.7/go.mod h1:mD76k/tIBFy8pHTFIgUPrVrkI4lTKvFbIcfbStJSBnA= -github.com/kataras/pio v0.0.12 h1:o52SfVYauS3J5X08fNjlGS5arXHjW/ItLkyLcKjoH6w= -github.com/kataras/pio v0.0.12/go.mod h1:ODK/8XBhhQ5WqrAhKy+9lTPS7sBf6O3KcLhc9klfRcY= -github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= -github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= -github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= -github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/labstack/echo/v4 v4.11.1 h1:dEpLU2FLg4UVmvCGPuk/APjlH6GDpbEPti61srUUUs4= -github.com/labstack/echo/v4 v4.11.1/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ= -github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= -github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= -github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg= -github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/nats-io/nats-server/v2 v2.8.4/go.mod h1:8zZa+Al3WsESfmgSs98Fi06dRWLH5Bnq90m5bKD/eT4= -github.com/nats-io/nats.go v1.30.2 h1:aloM0TGpPorZKQhbAkdCzYDj+ZmsJDyeo3Gkbr72NuY= -github.com/nats-io/nats.go v1.30.2/go.mod h1:dcfhUgmQNN4GJEfIb2f9R7Fow+gzBF4emzDHrVBd5qM= -github.com/nats-io/nkeys v0.4.5 h1:Zdz2BUlFm4fJlierwvGK+yl20IAKUm7eV6AAZXEhkPk= -github.com/nats-io/nkeys v0.4.5/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64= +github.com/nats-io/nats.go v1.33.1 h1:8TxLZZ/seeEfR97qV0/Bl939tpDnt2Z2fK3HkPypj70= +github.com/nats-io/nats.go v1.33.1/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= +github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro= +github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.49.0 h1:ToNTdK4zSnPVJmh698mGFkDor9wBI/iGaJy5dbH1EgI= +github.com/prometheus/common v0.49.0/go.mod h1:Kxm+EULxRbUkjGU6WFsQqo3ORzB4tyKvlWFOE9mB2sE= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= -github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= -github.com/stmcginnis/gofish v0.14.0 h1:geECNAiG33JDB2x2xDkerpOOuXFqxp5YP3EFE3vd5iM= -github.com/stmcginnis/gofish v0.14.0/go.mod h1:BLDSFTp8pDlf/xDbLZa+F7f7eW0E/CHCboggsu8CznI= +github.com/stmcginnis/gofish v0.15.0 h1:8TG41+lvJk/0Nf8CIIYErxbMlQUy80W0JFRZP3Ld82A= +github.com/stmcginnis/gofish v0.15.0/go.mod h1:BLDSFTp8pDlf/xDbLZa+F7f7eW0E/CHCboggsu8CznI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/tdewolff/minify/v2 v2.12.9 h1:dvn5MtmuQ/DFMwqf5j8QhEVpPX6fi3WGImhv8RUB4zA= -github.com/tdewolff/minify/v2 v2.12.9/go.mod h1:qOqdlDfL+7v0/fyymB+OP497nIxJYSvX4MQWA8OoiXU= -github.com/tdewolff/parse/v2 v2.6.8 h1:mhNZXYCx//xG7Yq2e/kVLNZw4YfYmeHbhx+Zc0OvFMA= -github.com/tdewolff/parse/v2 v2.6.8/go.mod h1:XHDhaU6IBgsryfdnpzUXBlT6leW/l25yrFBTEb4eIyM= -github.com/tdewolff/test v1.0.9/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= -github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= -github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= -github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/vmihailenco/msgpack/v5 v5.4.0 h1:hRM0digJwyR6vll33NNAwCFguy5JuBD6jxDmQP3l608= -github.com/vmihailenco/msgpack/v5 v5.4.0/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= -github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= -github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= -github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4= +github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0= +github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4= +github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= golang.design/x/thread v0.0.0-20210122121316-335e9adffdf1 h1:P7S/GeHBAFEZIYp0ePPs2kHXoazz8q2KsyxHyQVGCJg= golang.design/x/thread v0.0.0-20210122121316-335e9adffdf1/go.mod h1:9CWpnTUmlQkfdpdutA1nNf4iE5lAVt3QZOu0Z6hahBE= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.5.0 h1:jpGode6huXQxcskEIpOCvrU+tzo81b6+oFLUYXWtH/Y= -golang.org/x/arch v0.5.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -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/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -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/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos= -golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sys v0.0.0-20210122093101-04d7465088b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/receivers/redfishReceiver.go b/receivers/redfishReceiver.go index 767a2de..7a712b5 100644 --- a/receivers/redfishReceiver.go +++ b/receivers/redfishReceiver.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "io" + "maps" "net/http" "strconv" "strings" @@ -32,10 +33,14 @@ type RedfishReceiverClientConfig struct { doPowerMetric bool doProcessorMetrics bool + doSensors bool doThermalMetrics bool skipProcessorMetricsURL map[string]bool + // readSensorURLs stores for each chassis ID a list of sensor URLs to read + readSensorURLs map[string][]string + gofish gofish.ClientConfig } @@ -56,7 +61,226 @@ type RedfishReceiver struct { wg sync.WaitGroup // wait group for redfish receiver } +// deleteEmptyTags removes tags or meta data tags with empty value +func deleteEmptyTags(tags map[string]string) { + maps.DeleteFunc( + tags, + func(key string, value string) bool { + return value == "" + }, + ) +} + +// setMetricValue sets the value entry in the fields map +func setMetricValue(value any) map[string]interface{} { + return map[string]interface{}{ + "value": value, + } +} + +// sendMetric sends the metric through the sink channel +func (r *RedfishReceiver) sendMetric(name string, tags map[string]string, meta map[string]string, value any, timestamp time.Time) { + + deleteEmptyTags(tags) + deleteEmptyTags(meta) + y, err := lp.New(name, tags, meta, setMetricValue(value), timestamp) + if err == nil { + r.sink <- y + } +} + +// readSensors reads sensors from a redfish device +// See: https://redfish.dmtf.org/schemas/v1/Sensor.json +// Redfish URI: /redfish/v1/Chassis/{ChassisId}/Sensors/{SensorId} +func (r *RedfishReceiver) readSensors( + clientConfig *RedfishReceiverClientConfig, + chassis *redfish.Chassis) error { + + writeTemperatureSensor := func(sensor *redfish.Sensor) { + tags := map[string]string{ + "hostname": clientConfig.Hostname, + "type": "node", + // ChassisType shall indicate the physical form factor for the type of chassis + "chassis_typ": string(chassis.ChassisType), + // Chassis name + "chassis_name": chassis.Name, + // ID uniquely identifies the resource + "sensor_id": sensor.ID, + // The area or device to which this sensor measurement applies + "temperature_physical_context": string(sensor.PhysicalContext), + // Name + "temperature_name": sensor.Name, + } + + // Set meta data tags + meta := map[string]string{ + "source": r.name, + "group": "Temperature", + "unit": "degC", + } + + r.sendMetric("temperature", tags, meta, sensor.Reading, time.Now()) + } + + writeFanSpeedSensor := func(sensor *redfish.Sensor) { + tags := map[string]string{ + "hostname": clientConfig.Hostname, + "type": "node", + // ChassisType shall indicate the physical form factor for the type of chassis + "chassis_typ": string(chassis.ChassisType), + // Chassis name + "chassis_name": chassis.Name, + // ID uniquely identifies the resource + "sensor_id": sensor.ID, + // The area or device to which this sensor measurement applies + "fan_physical_context": string(sensor.PhysicalContext), + // Name + "fan_name": sensor.Name, + } + + // Set meta data tags + meta := map[string]string{ + "source": r.name, + "group": "FanSpeed", + "unit": string(sensor.ReadingUnits), + } + + r.sendMetric("fan_speed", tags, meta, sensor.Reading, time.Now()) + } + + writePowerSensor := func(sensor *redfish.Sensor) { + // Set tags + tags := map[string]string{ + "hostname": clientConfig.Hostname, + "type": "node", + // ChassisType shall indicate the physical form factor for the type of chassis + "chassis_typ": string(chassis.ChassisType), + // Chassis name + "chassis_name": chassis.Name, + // ID uniquely identifies the resource + "sensor_id": sensor.ID, + // The area or device to which this sensor measurement applies + "power_physical_context": string(sensor.PhysicalContext), + // Name + "power_name": sensor.Name, + } + + // Set meta data tags + meta := map[string]string{ + "source": r.name, + "group": "Energy", + "unit": "watts", + } + + r.sendMetric("power", tags, meta, sensor.Reading, time.Now()) + } + + if _, ok := clientConfig.readSensorURLs[chassis.ID]; !ok { + // First time run of read sensors for this chassis + + clientConfig.readSensorURLs[chassis.ID] = make([]string, 0) + + // Get sensor information for this chassis + sensors, err := chassis.Sensors() + if err != nil { + return fmt.Errorf("readSensors: chassis.Sensors() failed: %v", err) + } + + // Skip empty sensors information + if sensors == nil { + return nil + } + + for _, sensor := range sensors { + + // Skip all sensors which are not in enabled state or which are unhealthy + if sensor.Status.State != common.EnabledState || sensor.Status.Health != common.OKHealth { + continue + } + + // Skip sensors with missing readings units or type + if sensor.ReadingUnits == "" || sensor.ReadingType == "" { + continue + } + + // Power readings + if (sensor.ReadingType == redfish.PowerReadingType && sensor.ReadingUnits == "Watts") || + (sensor.ReadingType == redfish.CurrentReadingType && sensor.ReadingUnits == "Watts") { + if clientConfig.isExcluded["power"] { + continue + } + + clientConfig.readSensorURLs[chassis.ID] = append(clientConfig.readSensorURLs[chassis.ID], sensor.ODataID) + writePowerSensor(sensor) + continue + } + + // Fan speed readings + if (sensor.ReadingType == redfish.AirFlowReadingType && sensor.ReadingUnits == "RPM") || + (sensor.ReadingType == redfish.AirFlowReadingType && sensor.ReadingUnits == "Percent") { + // Skip, when fan_speed metric is excluded + if clientConfig.isExcluded["fan_speed"] { + continue + } + + clientConfig.readSensorURLs[chassis.ID] = append(clientConfig.readSensorURLs[chassis.ID], sensor.ODataID) + writeFanSpeedSensor(sensor) + } + + // Temperature readings + if sensor.ReadingType == redfish.TemperatureReadingType && sensor.ReadingUnits == "C" { + if clientConfig.isExcluded["temperature"] { + continue + } + + clientConfig.readSensorURLs[chassis.ID] = append(clientConfig.readSensorURLs[chassis.ID], sensor.ODataID) + writeTemperatureSensor(sensor) + continue + } + } + } else { + + common.CollectCollection( + func(uri string) { + sensor, err := redfish.GetSensor(chassis.GetClient(), uri) + if err != nil { + cclog.ComponentError(r.name, "redfish.GetSensor() for uri '", uri, "' failed") + } + + // Power readings + if (sensor.ReadingType == redfish.PowerReadingType && sensor.ReadingUnits == "Watts") || + (sensor.ReadingType == redfish.CurrentReadingType && sensor.ReadingUnits == "Watts") { + + writePowerSensor(sensor) + return + } + + // Fan speed readings + if (sensor.ReadingType == redfish.AirFlowReadingType && sensor.ReadingUnits == "RPM") || + (sensor.ReadingType == redfish.AirFlowReadingType && sensor.ReadingUnits == "Percent") { + + writeFanSpeedSensor(sensor) + return + } + + // Temperature readings + if sensor.ReadingType == redfish.TemperatureReadingType && sensor.ReadingUnits == "C" { + + writeTemperatureSensor(sensor) + return + } + }, + clientConfig.readSensorURLs[chassis.ID]) + + } + return nil +} + // readThermalMetrics reads thermal metrics from a redfish device +// See: https://redfish.dmtf.org/schemas/v1/Thermal.json +// Redfish URI: /redfish/v1/Chassis/{ChassisId}/Thermal +// -> deprecated in favor of the ThermalSubsystem schema +// -> on Lenovo servers /redfish/v1/Chassis/{ChassisId}/ThermalSubsystem/ThermalMetrics links to /redfish/v1/Chassis/{ChassisId}/Sensors/{SensorId} func (r *RedfishReceiver) readThermalMetrics( clientConfig *RedfishReceiverClientConfig, chassis *redfish.Chassis) error { @@ -106,13 +330,6 @@ func (r *RedfishReceiver) readThermalMetrics( "temperature_name": temperature.Name, } - // Delete empty tags - for key, value := range tags { - if value == "" { - delete(tags, key) - } - } - // Set meta data tags meta := map[string]string{ "source": r.name, @@ -123,14 +340,7 @@ func (r *RedfishReceiver) readThermalMetrics( // ReadingCelsius shall be the current value of the temperature sensor's reading. value := temperature.ReadingCelsius - y, err := lp.New("temperature", tags, meta, - map[string]interface{}{ - "value": value, - }, - timestamp) - if err == nil { - r.sink <- y - } + r.sendMetric("temperature", tags, meta, value, timestamp) } for _, fan := range thermal.Fans { @@ -164,13 +374,6 @@ func (r *RedfishReceiver) readThermalMetrics( "fan_name": fan.Name, } - // Delete empty tags - for key, value := range tags { - if value == "" { - delete(tags, key) - } - } - // Set meta data tags meta := map[string]string{ "source": r.name, @@ -178,23 +381,16 @@ func (r *RedfishReceiver) readThermalMetrics( "unit": string(fan.ReadingUnits), } - // Reading shall be the current value of the fan sensor's reading - value := fan.Reading - - y, err := lp.New("fan_speed", tags, meta, - map[string]interface{}{ - "value": value, - }, - timestamp) - if err == nil { - r.sink <- y - } + r.sendMetric("fan_speed", tags, meta, fan.Reading, timestamp) } return nil } // readPowerMetrics reads power metrics from a redfish device +// See: https://redfish.dmtf.org/schemas/v1/Power.json +// Redfish URI: /redfish/v1/Chassis/{ChassisId}/Power +// -> deprecated in favor of the PowerSubsystem schema func (r *RedfishReceiver) readPowerMetrics( clientConfig *RedfishReceiverClientConfig, chassis *redfish.Chassis) error { @@ -274,13 +470,6 @@ func (r *RedfishReceiver) readPowerMetrics( "power_control_name": pc.Name, } - // Delete empty tags - for key, value := range tags { - if value == "" { - delete(tags, key) - } - } - // Set meta data tags meta := map[string]string{ "source": r.name, @@ -289,23 +478,8 @@ func (r *RedfishReceiver) readPowerMetrics( "unit": "watts", } - // Delete empty meta data tags - for key, value := range meta { - if value == "" { - delete(meta, key) - } - } - for name, value := range metrics { - - y, err := lp.New(name, tags, meta, - map[string]interface{}{ - "value": value, - }, - timestamp) - if err == nil { - r.sink <- y - } + r.sendMetric(name, tags, meta, value, timestamp) } } @@ -314,6 +488,7 @@ func (r *RedfishReceiver) readPowerMetrics( // readProcessorMetrics reads processor metrics from a redfish device // See: https://redfish.dmtf.org/schemas/v1/ProcessorMetrics.json +// Redfish URI: /redfish/v1/Systems/{ComputerSystemId}/Processors/{ProcessorId}/ProcessorMetrics func (r *RedfishReceiver) readProcessorMetrics( clientConfig *RedfishReceiverClientConfig, processor *redfish.Processor) error { @@ -328,7 +503,7 @@ func (r *RedfishReceiver) readProcessorMetrics( return nil } - resp, err := processor.Client.Get(URL) + resp, err := processor.GetClient().Get(URL) if err != nil { // Skip non existing URLs if statusCode := err.(*common.Error).HTTPReturnedStatusCode; statusCode == http.StatusNotFound { @@ -336,7 +511,7 @@ func (r *RedfishReceiver) readProcessorMetrics( return nil } - return fmt.Errorf("processor.Client.Get(%v) failed: %+w", URL, err) + return fmt.Errorf("processor.GetClient().Get(%v) failed: %+w", URL, err) } var processorMetrics struct { @@ -351,7 +526,7 @@ func (r *RedfishReceiver) readProcessorMetrics( } body, err := io.ReadAll(resp.Body) if err != nil { - return fmt.Errorf("unable to read JSON for processor metrics: %+w", err) + return fmt.Errorf("unable to read response body for processor metrics: %+w", err) } err = json.Unmarshal(body, &processorMetrics) if err != nil { @@ -361,7 +536,6 @@ func (r *RedfishReceiver) readProcessorMetrics( err, ) } - processorMetrics.SetClient(processor.Client) // Set tags tags := map[string]string{ @@ -375,13 +549,6 @@ func (r *RedfishReceiver) readProcessorMetrics( "processor_id": processor.ID, } - // Delete empty tags - for key, value := range tags { - if value == "" { - delete(tags, key) - } - } - // Set meta data tags metaPower := map[string]string{ "source": r.name, @@ -394,14 +561,7 @@ func (r *RedfishReceiver) readProcessorMetrics( if !clientConfig.isExcluded[namePower] && // Some servers return "ConsumedPowerWatt":65535 instead of "ConsumedPowerWatt":null processorMetrics.ConsumedPowerWatt != 65535 { - y, err := lp.New(namePower, tags, metaPower, - map[string]interface{}{ - "value": processorMetrics.ConsumedPowerWatt, - }, - timestamp) - if err == nil { - r.sink <- y - } + r.sendMetric(namePower, tags, metaPower, processorMetrics.ConsumedPowerWatt, timestamp) } // Set meta data tags metaThermal := map[string]string{ @@ -413,14 +573,7 @@ func (r *RedfishReceiver) readProcessorMetrics( nameThermal := "temperature" if !clientConfig.isExcluded[nameThermal] { - y, err := lp.New(nameThermal, tags, metaThermal, - map[string]interface{}{ - "value": processorMetrics.TemperatureCelsius, - }, - timestamp) - if err == nil { - r.sink <- y - } + r.sendMetric(nameThermal, tags, metaThermal, processorMetrics.TemperatureCelsius, timestamp) } return nil } @@ -453,7 +606,8 @@ func (r *RedfishReceiver) readMetrics(clientConfig *RedfishReceiverClientConfig) // Get all chassis managed by this service isChassisListRequired := - clientConfig.doThermalMetrics || + clientConfig.doSensors || + clientConfig.doThermalMetrics || clientConfig.doPowerMetric var chassisList []*redfish.Chassis if isChassisListRequired { @@ -473,6 +627,16 @@ func (r *RedfishReceiver) readMetrics(clientConfig *RedfishReceiverClientConfig) } } + // Read sensors + if clientConfig.doSensors { + for _, chassis := range chassisList { + err := r.readSensors(clientConfig, chassis) + if err != nil { + return err + } + } + } + // read thermal metrics if clientConfig.doThermalMetrics { for _, chassis := range chassisList { @@ -637,6 +801,7 @@ func NewRedfishReceiver(name string, config json.RawMessage) (Receiver, error) { // Globally disable collection of power, processor or thermal metrics DisablePowerMetrics bool `json:"disable_power_metrics"` DisableProcessorMetrics bool `json:"disable_processor_metrics"` + DisableSensors bool `json:"disable_sensors"` DisableThermalMetrics bool `json:"disable_thermal_metrics"` // Globally excluded metrics @@ -651,6 +816,7 @@ func NewRedfishReceiver(name string, config json.RawMessage) (Receiver, error) { // Per client disable collection of power,processor or thermal metrics DisablePowerMetrics bool `json:"disable_power_metrics"` DisableProcessorMetrics bool `json:"disable_processor_metrics"` + DisableSensors bool `json:"disable_sensors"` DisableThermalMetrics bool `json:"disable_thermal_metrics"` // Per client excluded metrics @@ -724,6 +890,7 @@ func NewRedfishReceiver(name string, config json.RawMessage) (Receiver, error) { clientConfigJSON := &configJSON.ClientConfigs[i] + // Redfish endpoint var endpoint_pattern string if clientConfigJSON.Endpoint != nil { endpoint_pattern = *clientConfigJSON.Endpoint @@ -735,6 +902,7 @@ func NewRedfishReceiver(name string, config json.RawMessage) (Receiver, error) { return nil, err } + // Redfish username var username string if clientConfigJSON.Username != nil { username = *clientConfigJSON.Username @@ -746,6 +914,7 @@ func NewRedfishReceiver(name string, config json.RawMessage) (Receiver, error) { return nil, err } + // Redfish password var password string if clientConfigJSON.Password != nil { password = *clientConfigJSON.Password @@ -764,6 +933,9 @@ func NewRedfishReceiver(name string, config json.RawMessage) (Receiver, error) { doProcessorMetrics := !(configJSON.DisableProcessorMetrics || clientConfigJSON.DisableProcessorMetrics) + doSensors := + !(configJSON.DisableSensors || + clientConfigJSON.DisableSensors) doThermalMetrics := !(configJSON.DisableThermalMetrics || clientConfigJSON.DisableThermalMetrics) @@ -796,8 +968,10 @@ func NewRedfishReceiver(name string, config json.RawMessage) (Receiver, error) { isExcluded: isExcluded, doPowerMetric: doPowerMetric, doProcessorMetrics: doProcessorMetrics, + doSensors: doSensors, doThermalMetrics: doThermalMetrics, skipProcessorMetricsURL: make(map[string]bool), + readSensorURLs: map[string][]string{}, gofish: gofish.ClientConfig{ Username: username, Password: password, @@ -816,6 +990,7 @@ func NewRedfishReceiver(name string, config json.RawMessage) (Receiver, error) { r.config.fanout = numClients } + // Check that at least on client config exists if numClients == 0 { err := fmt.Errorf("at least one client config is required") cclog.ComponentError(r.name, err) diff --git a/receivers/redfishReceiver.md b/receivers/redfishReceiver.md index 7eb6f34..9acc68e 100644 --- a/receivers/redfishReceiver.md +++ b/receivers/redfishReceiver.md @@ -17,15 +17,17 @@ The Redfish receiver uses the [Redfish (specification)](https://www.dmtf.org/sta "host_list": "n[1,2-4]" }, { - "host_list": "n5" - "disable_power_metrics": true + "host_list": "n5", + "disable_power_metrics": true, + "disable_processor_metrics": true, + "disable_thermal_metrics": true }, { "host_list": "n6" ], "username": "", "password": "", "endpoint": "https://%h-BMC", - "disable_thermal_metrics": true + "disable_sensor_metrics": true } ] } @@ -41,9 +43,18 @@ Global settings: Global and per redfish device settings (per redfish device settings overwrite the global settings): -- `disable_power_metrics`: disable collection of power metrics -- `disable_processor_metrics`: disable collection of processor metrics -- `disable_thermal_metrics`: disable collection of thermal metrics +- `disable_power_metrics`: + disable collection of power metrics + (`/redfish/v1/Chassis/{ChassisId}/Power`) +- `disable_processor_metrics`: + disable collection of processor metrics + (`/redfish/v1/Systems/{ComputerSystemId}/Processors/{ProcessorId}/ProcessorMetrics`) +- `disable_sensors`: + disable collection of fan, power and thermal sensor metrics + (`/redfish/v1/Chassis/{ChassisId}/Sensors/{SensorId}`) +- `disable_thermal_metrics`: + disable collection of thermal metrics + (`/redfish/v1/Chassis/{ChassisId}/Thermal`) - `exclude_metrics`: list of excluded metrics - `username`: User name to authenticate with - `password`: Password to use for authentication diff --git a/scripts/cc-metric-collector.init b/scripts/cc-metric-collector.init index 1a7993b..e7d87cf 100755 --- a/scripts/cc-metric-collector.init +++ b/scripts/cc-metric-collector.init @@ -25,7 +25,7 @@ CC_USER=clustercockpit CC_GROUP=clustercockpit CONF_DIR=/etc/cc-metric-collector PID_FILE=/var/run/$NAME.pid -DAEMON=/usr/sbin/$NAME +DAEMON=/usr/bin/$NAME CONF_FILE=${CONF_DIR}/cc-metric-collector.json umask 0027 diff --git a/sinks/httpSink.go b/sinks/httpSink.go index a9bcc96..5bad35a 100644 --- a/sinks/httpSink.go +++ b/sinks/httpSink.go @@ -45,6 +45,9 @@ type HttpSinkConfig struct { // Maximum number of retries to connect to the http server (default: 3) MaxRetries int `json:"max_retries,omitempty"` + + // Timestamp precision + Precision string `json:"precision,omitempty"` } type key_value_pair struct { @@ -141,7 +144,7 @@ func (s *HttpSink) Write(m lp.CCMetric) error { // Check that encoding worked if err != nil { - return fmt.Errorf("Encoding failed: %v", err) + return fmt.Errorf("encoding failed: %v", err) } if s.config.flushDelay == 0 { @@ -268,6 +271,7 @@ func NewHttpSink(name string, config json.RawMessage) (Sink, error) { s.config.Timeout = "5s" s.config.FlushDelay = "5s" s.config.MaxRetries = 3 + s.config.Precision = "ns" cclog.ComponentDebug(s.name, "Init()") // Read config @@ -315,6 +319,19 @@ func NewHttpSink(name string, config json.RawMessage) (Sink, error) { cclog.ComponentDebug(s.name, "Init(): flushDelay", t) } } + precision := influx.Nanosecond + if len(s.config.Precision) > 0 { + switch s.config.Precision { + case "s": + precision = influx.Second + case "ms": + precision = influx.Millisecond + case "us": + precision = influx.Microsecond + case "ns": + precision = influx.Nanosecond + } + } // Create http client s.client = &http.Client{ @@ -326,7 +343,7 @@ func NewHttpSink(name string, config json.RawMessage) (Sink, error) { } // Configure influx line protocol encoder - s.encoder.SetPrecision(influx.Nanosecond) + s.encoder.SetPrecision(precision) s.extended_tag_list = make([]key_value_pair, 0) return s, nil diff --git a/sinks/httpSink.md b/sinks/httpSink.md index ccb7c4b..7d77ddf 100644 --- a/sinks/httpSink.md +++ b/sinks/httpSink.md @@ -18,7 +18,8 @@ The `http` sink uses POST requests to a HTTP server to submit the metrics in the "timeout": "5s", "idle_connection_timeout" : "5s", "flush_delay": "2s", - "batch_size": 1000 + "batch_size": 1000, + "precision": "s" } } ``` @@ -34,3 +35,8 @@ The `http` sink uses POST requests to a HTTP server to submit the metrics in the - `idle_connection_timeout`: Timeout for idle connections (default '120s'). Should be larger than the measurement interval to keep the connection open - `flush_delay`: Batch all writes arriving in during this duration (default '1s', batching can be disabled by setting it to 0) - `batch_size`: Maximal batch size. If `batch_size` is reached before the end of `flush_delay`, the metrics are sent without further delay +- `precision`: Precision of the timestamp. Valid values are 's', 'ms', 'us' and 'ns'. (default is 'ns') + +### Using HttpSink for communication with cc-metric-store + +The cc-metric-store only accepts metrics with a timestamp precision in seconds, so it is required to set `"precision": "s"`. \ No newline at end of file