Merge branch 'prometheus:master' into master

pull/3007/head
Frederic 2 months ago committed by GitHub
commit eb7055d6bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      .circleci/config.yml
  2. 11
      .github/workflows/bsd.yml
  3. 2
      .promu-cgo.yml
  4. 2
      .promu.yml
  5. 1
      README.md
  6. 4
      collector/fixtures/e2e-output-darwin.txt
  7. 12
      collector/fixtures/e2e-output-freebsd.txt
  8. 2
      collector/fixtures/proc/swaps
  9. 82
      collector/perf_linux.go
  10. 129
      collector/swap_linux.go
  11. 58
      collector/swap_linux_test.go
  12. 27
      end-to-end-test.sh
  13. 6
      go.mod
  14. 12
      go.sum

@ -7,10 +7,10 @@ executors:
# should also be updated.
golang:
docker:
- image: cimg/go:1.24
- image: cimg/go:1.25
arm:
docker:
- image: cimg/go:1.24
- image: cimg/go:1.25
resource_class: arm.medium
jobs:
@ -70,7 +70,7 @@ jobs:
machine:
image: ubuntu-2404:current
environment:
DOCKER_TEST_IMAGE_NAME: quay.io/prometheus/golang-builder:1.24-base
DOCKER_TEST_IMAGE_NAME: quay.io/prometheus/golang-builder:1.25-base
REPO_PATH: github.com/prometheus/node_exporter
steps:
- prometheus/setup_environment

@ -13,11 +13,11 @@ permissions:
env:
GNU_TAR_VERSION: "1.35"
GO_VERSION_DRAGONFLY: "1.24.1"
GO_VERSION_FREEBSD: "123"
GO_VERSION_NETBSD: "1.24.1"
GO_VERSION_DRAGONFLY: "1.25.1"
GO_VERSION_FREEBSD: "125"
GO_VERSION_NETBSD: "1.25.1"
GO_VERSION_OPENBSD: "1.24.1"
GO_VERSION_SOLARIS: "1.24.1"
GO_VERSION_SOLARIS: "1.25.1"
# To spin up one of the VMs below, see the "Debug Shell" section here: https://github.com/vmactions
jobs:
@ -28,8 +28,9 @@ jobs:
- name: Checkout the repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: test-e2e
uses: vmactions/freebsd-vm@05856381fab64eeee9b038a0818f6cec649ca17a # v1.2.3
uses: vmactions/freebsd-vm@487ce35b96fae3e60d45b521735f5aa436ecfade # v1.2.4
with:
release: "15.0"
copyback: false
envs: 'GO_VERSION_FREEBSD GNU_TAR_VERSION'
usesh: true

@ -1,7 +1,7 @@
go:
# Whenever the Go version is updated here, .circle/config.yml and
# .promu.yml should also be updated.
version: 1.24
version: 1.25
cgo: true
repository:
path: github.com/prometheus/node_exporter

@ -1,7 +1,7 @@
go:
# Whenever the Go version is updated here, .circle/config.yml and
# .promu-cgo.yml should also be updated.
version: 1.24
version: 1.25
repository:
path: github.com/prometheus/node_exporter
build:

@ -208,6 +208,7 @@ qdisc | Exposes [queuing discipline](https://en.wikipedia.org/wiki/Network_sched
slabinfo | Exposes slab statistics from `/proc/slabinfo`. Note that permission of `/proc/slabinfo` is usually 0400, so set it appropriately. | Linux
softirqs | Exposes detailed softirq statistics from `/proc/softirqs`. | Linux
sysctl | Expose sysctl values from `/proc/sys`. Use `--collector.sysctl.include(-info)` to configure. | Linux
swap | Expose swap information from `/proc/swaps`. | Linux
systemd | Exposes service and system status from [systemd](http://www.freedesktop.org/wiki/Software/systemd/). | Linux
tcpstat | Exposes TCP connection status information from `/proc/net/tcp` and `/proc/net/tcp6`. (Warning: the current version has potential performance issues in high load situations.) | Linux
wifi | Exposes WiFi device and station statistics. | Linux

@ -94,15 +94,19 @@ node_buddyinfo_blocks{node="0",size="9",zone="Normal"} 0
# HELP node_disk_read_errors_total The total number of read errors.
# TYPE node_disk_read_errors_total counter
node_disk_read_errors_total{device="disk0"} 0
node_disk_read_errors_total{device="disk4"} 0
# HELP node_disk_read_retries_total The total number of read retries.
# TYPE node_disk_read_retries_total counter
node_disk_read_retries_total{device="disk0"} 0
node_disk_read_retries_total{device="disk4"} 0
# HELP node_disk_write_errors_total The total number of write errors.
# TYPE node_disk_write_errors_total counter
node_disk_write_errors_total{device="disk0"} 0
node_disk_write_errors_total{device="disk4"} 0
# HELP node_disk_write_retries_total The total number of write retries.
# TYPE node_disk_write_retries_total counter
node_disk_write_retries_total{device="disk0"} 0
node_disk_write_retries_total{device="disk4"} 0
# HELP node_exporter_build_info A metric with a constant '1' value labeled by version, revision, branch, goversion from which node_exporter was built, and the goos and goarch for the build.
# TYPE node_exporter_build_info gauge
# HELP node_memory_swap_total_bytes Memory information field swap_total_bytes.

@ -261,6 +261,18 @@ node_xfrm_out_state_proto_error_packets_total 4542
# HELP node_xfrm_out_state_seq_error_packets_total Sequence error i.e. Sequence number overflow
# TYPE node_xfrm_out_state_seq_error_packets_total counter
node_xfrm_out_state_seq_error_packets_total 543
# HELP node_zfs_arcstats_c_min_bytes ZFS ARC minimum size
# TYPE node_zfs_arcstats_c_min_bytes gauge
node_zfs_arcstats_c_min_bytes 1.99932544e+08
# HELP node_zfs_arcstats_mfu_ghost_size ZFS ARC MFU ghost size
# TYPE node_zfs_arcstats_mfu_ghost_size gauge
node_zfs_arcstats_mfu_ghost_size 0
# HELP node_zfs_arcstats_mru_ghost_hits_total ZFS ARC MRU ghost hits
# TYPE node_zfs_arcstats_mru_ghost_hits_total counter
node_zfs_arcstats_mru_ghost_hits_total 0
# HELP node_zfs_arcstats_pm_bytes ZFS ARC meta MRU target frac
# TYPE node_zfs_arcstats_pm_bytes gauge
node_zfs_arcstats_pm_bytes 2.147483648e+09
# HELP promhttp_metric_handler_errors_total Total number of internal errors encountered by the promhttp metric handler.
# TYPE promhttp_metric_handler_errors_total counter
promhttp_metric_handler_errors_total{cause="encoding"} 0

@ -0,0 +1,2 @@
Filename Type Size Used Priority
/dev/zram0 partition 8388604 76 100

@ -86,10 +86,10 @@ var (
"BPUReadHit": perf.BPUReadHitProfiler,
"BPUReadMiss": perf.BPUReadMissProfiler,
// "L1InstrReadHit": perf.L1InstrReadHitProfiler,
// "DataTLBReadHit": perf.DataTLBReadHitProfiler,
// "DataTLBReadMiss": perf.DataTLBReadMissProfiler,
// "DataTLBWriteHit": perf.DataTLBWriteHitProfiler,
// "DataTLBWriteMiss": perf.DataTLBWriteMissProfiler,
"DataTLBReadHit": perf.DataTLBReadHitProfiler,
"DataTLBReadMiss": perf.DataTLBReadMissProfiler,
"DataTLBWriteHit": perf.DataTLBWriteHitProfiler,
"DataTLBWriteMiss": perf.DataTLBWriteMissProfiler,
// "NodeCacheReadHit": perf.NodeCacheReadHitProfiler,
// "NodeCacheReadMiss": perf.NodeCacheReadMissProfiler,
// "NodeCacheWriteHit": perf.NodeCacheWriteHitProfiler,
@ -355,7 +355,7 @@ func NewPerfCollector(logger *slog.Logger) (Collector, error) {
}
}
}
cacheProfilers := perf.L1DataReadHitProfiler | perf.L1DataReadMissProfiler | perf.L1DataWriteHitProfiler | perf.L1InstrReadMissProfiler | perf.InstrTLBReadHitProfiler | perf.InstrTLBReadMissProfiler | perf.LLReadHitProfiler | perf.LLReadMissProfiler | perf.LLWriteHitProfiler | perf.LLWriteMissProfiler | perf.BPUReadHitProfiler | perf.BPUReadMissProfiler
cacheProfilers := perf.L1DataReadHitProfiler | perf.L1DataReadMissProfiler | perf.L1DataWriteHitProfiler | perf.L1InstrReadMissProfiler | perf.InstrTLBReadHitProfiler | perf.InstrTLBReadMissProfiler | perf.DataTLBReadHitProfiler | perf.DataTLBReadMissProfiler | perf.DataTLBWriteHitProfiler | perf.DataTLBWriteMissProfiler | perf.LLReadHitProfiler | perf.LLReadMissProfiler | perf.LLWriteHitProfiler | perf.LLWriteMissProfiler | perf.BPUReadHitProfiler | perf.BPUReadMissProfiler
if *perfCaProfilerFlag != nil && len(*perfCaProfilerFlag) > 0 {
cacheProfilers = 0
for _, cf := range *perfCaProfilerFlag {
@ -615,6 +615,46 @@ func NewPerfCollector(logger *slog.Logger) (Collector, error) {
[]string{"cpu"},
nil,
),
"cache_tlb_data_read_hits_total": prometheus.NewDesc(
prometheus.BuildFQName(
namespace,
perfSubsystem,
"cache_tlb_data_read_hits_total",
),
"Number of data TLB read hits",
[]string{"cpu"},
nil,
),
"cache_tlb_data_read_misses_total": prometheus.NewDesc(
prometheus.BuildFQName(
namespace,
perfSubsystem,
"cache_tlb_data_read_misses_total",
),
"Number of data TLB read misses",
[]string{"cpu"},
nil,
),
"cache_tlb_data_write_hits_total": prometheus.NewDesc(
prometheus.BuildFQName(
namespace,
perfSubsystem,
"cache_tlb_data_write_hits_total",
),
"Number of data TLB write hits",
[]string{"cpu"},
nil,
),
"cache_tlb_data_write_misses_total": prometheus.NewDesc(
prometheus.BuildFQName(
namespace,
perfSubsystem,
"cache_tlb_data_write_misses_total",
),
"Number of data TLB write misses",
[]string{"cpu"},
nil,
),
"cache_ll_read_hits_total": prometheus.NewDesc(
prometheus.BuildFQName(
namespace,
@ -895,6 +935,38 @@ func (c *perfCollector) updateCacheStats(ch chan<- prometheus.Metric) error {
)
}
if cacheProfile.DataTLBReadHit != nil {
ch <- prometheus.MustNewConstMetric(
c.desc["cache_tlb_data_read_hits_total"],
prometheus.CounterValue, float64(*cacheProfile.DataTLBReadHit),
cpuid,
)
}
if cacheProfile.DataTLBReadMiss != nil {
ch <- prometheus.MustNewConstMetric(
c.desc["cache_tlb_data_read_misses_total"],
prometheus.CounterValue, float64(*cacheProfile.DataTLBReadMiss),
cpuid,
)
}
if cacheProfile.DataTLBWriteHit != nil {
ch <- prometheus.MustNewConstMetric(
c.desc["cache_tlb_data_write_hits_total"],
prometheus.CounterValue, float64(*cacheProfile.DataTLBWriteHit),
cpuid,
)
}
if cacheProfile.DataTLBWriteMiss != nil {
ch <- prometheus.MustNewConstMetric(
c.desc["cache_tlb_data_write_misses_total"],
prometheus.CounterValue, float64(*cacheProfile.DataTLBWriteMiss),
cpuid,
)
}
if cacheProfile.LastLevelReadHit != nil {
ch <- prometheus.MustNewConstMetric(
c.desc["cache_ll_read_hits_total"],

@ -0,0 +1,129 @@
// Copyright The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !noswap
package collector
import (
"fmt"
"log/slog"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/procfs"
)
const (
swapSubsystem = "swap"
)
var swapLabelNames = []string{"device", "swap_type"}
type swapCollector struct {
fs procfs.FS
logger *slog.Logger
}
func init() {
registerCollector("swap", defaultDisabled, NewSwapCollector)
}
// NewSwapCollector returns a new Collector exposing swap device statistics.
func NewSwapCollector(logger *slog.Logger) (Collector, error) {
fs, err := procfs.NewFS(*procPath)
if err != nil {
return nil, fmt.Errorf("failed to open procfs: %w", err)
}
return &swapCollector{
fs: fs,
logger: logger,
}, nil
}
type SwapsEntry struct {
Device string
Type string
Priority int
Size int
Used int
}
func (c *swapCollector) getSwapInfo() ([]SwapsEntry, error) {
swaps, err := c.fs.Swaps()
if err != nil {
return nil, fmt.Errorf("couldn't get proc/swap information: %w", err)
}
metrics := make([]SwapsEntry, 0, len(swaps))
for _, swap := range swaps {
metrics = append(metrics, SwapsEntry{Device: swap.Filename, Type: swap.Type,
Priority: swap.Priority, Size: swap.Size, Used: swap.Used})
}
return metrics, nil
}
func (c *swapCollector) Update(ch chan<- prometheus.Metric) error {
swaps, err := c.getSwapInfo()
if err != nil {
return fmt.Errorf("couldn't get swap information: %w", err)
}
for _, swap := range swaps {
swapLabelValues := []string{swap.Device, swap.Type}
// Export swap size in bytes
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(namespace, swapSubsystem, "size_bytes"),
"Swap device size in bytes.",
[]string{"device", "swap_type"}, nil,
),
prometheus.GaugeValue,
// Size is provided in kbytes (not bytes), translate to bytes
// see https://github.com/torvalds/linux/blob/fd94619c43360eb44d28bd3ef326a4f85c600a07/mm/swapfile.c#L3079-L3080
float64(swap.Size*1024),
swapLabelValues...,
)
// Export swap used in bytes
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(namespace, swapSubsystem, "used_bytes"),
"Swap device used in bytes.",
swapLabelNames, nil,
),
prometheus.GaugeValue,
// Swap used is also provided in kbytes, translate to bytes
float64(swap.Used*1024),
swapLabelValues...,
)
// Export swap priority
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(namespace, swapSubsystem, "priority"),
"Swap device priority.",
swapLabelNames, nil,
),
prometheus.GaugeValue,
float64(swap.Priority),
swapLabelValues...,
)
}
return nil
}

@ -0,0 +1,58 @@
// Copyright The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !noswap
// +build !noswap
package collector
import (
"io"
"log/slog"
"testing"
)
func TestSwap(t *testing.T) {
*procPath = "fixtures/proc"
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
collector, err := NewSwapCollector(logger)
if err != nil {
panic(err)
}
swapInfo, err := collector.(*swapCollector).getSwapInfo()
if err != nil {
panic(err)
}
if want, got := "/dev/zram0", swapInfo[0].Device; want != got {
t.Errorf("want swap device %s, got %s", want, got)
}
if want, got := "partition", swapInfo[0].Type; want != got {
t.Errorf("want swap type %s, got %s", want, got)
}
if want, got := 100, swapInfo[0].Priority; want != got {
t.Errorf("want swap priority %d, got %d", want, got)
}
if want, got := 8388604, swapInfo[0].Size; want != got {
t.Errorf("want swap size %d, got %d", want, got)
}
if want, got := 76, swapInfo[0].Used; want != got {
t.Errorf("want swpa used %d, got %d", want, got)
}
}

@ -365,6 +365,33 @@ non_deterministic_metrics=$(cat << METRICS
node_network_receive_bytes_total
node_network_receive_multicast_total
node_network_transmit_multicast_total
node_zfs_abdstats_linear_count_total
node_zfs_abdstats_linear_data_bytes
node_zfs_abdstats_scatter_chunk_waste_bytes
node_zfs_abdstats_scatter_count_total
node_zfs_abdstats_scatter_data_bytes
node_zfs_abdstats_struct_bytes
node_zfs_arcstats_anon_bytes
node_zfs_arcstats_c_bytes
node_zfs_arcstats_c_max_bytes
node_zfs_arcstats_data_bytes
node_zfs_arcstats_demand_data_hits_total
node_zfs_arcstats_demand_data_misses_total
node_zfs_arcstats_demand_metadata_hits_total
node_zfs_arcstats_demand_metadata_misses_total
node_zfs_arcstats_hdr_bytes
node_zfs_arcstats_hits_total
node_zfs_arcstats_meta_bytes
node_zfs_arcstats_mfu_bytes
node_zfs_arcstats_mfu_ghost_hits_total
node_zfs_arcstats_misses_total
node_zfs_arcstats_mru_bytes
node_zfs_arcstats_mru_ghost_bytes
node_zfs_arcstats_other_bytes
node_zfs_arcstats_pd_bytes
node_zfs_arcstats_size_bytes
node_zfs_zfetchstats_hits_total
node_zfs_zfetchstats_misses_total
METRICS
)

@ -6,7 +6,7 @@ require (
github.com/alecthomas/kingpin/v2 v2.4.0
github.com/beevik/ntp v1.4.3
github.com/coreos/go-systemd/v22 v22.6.0
github.com/dennwc/btrfs v0.0.0-20240418142341-0167142bde7a
github.com/dennwc/btrfs v0.0.0-20241002142654-12ae127e0bf6
github.com/ema/qdisc v1.0.0
github.com/godbus/dbus/v5 v5.1.0
github.com/hashicorp/go-envparse v0.1.0
@ -27,7 +27,7 @@ require (
github.com/prometheus/exporter-toolkit v0.14.1
github.com/prometheus/procfs v0.17.0
github.com/safchain/ethtool v0.6.2
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0
golang.org/x/exp v0.0.0-20250911091902-df9299821621
golang.org/x/sys v0.36.0
howett.net/plist v1.0.1
)
@ -53,7 +53,7 @@ require (
golang.org/x/crypto v0.41.0 // indirect
golang.org/x/net v0.43.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/text v0.28.0 // indirect
google.golang.org/protobuf v1.36.8 // indirect
)

@ -15,8 +15,8 @@ github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X
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/dennwc/btrfs v0.0.0-20240418142341-0167142bde7a h1:KfFsGLJFVdCXlySUkV2FmxNtmiztpJb6tV+XYBmmv8E=
github.com/dennwc/btrfs v0.0.0-20240418142341-0167142bde7a/go.mod h1:MYsOV9Dgsec3FFSOjywi0QK5r6TeBbdWxdrMGtiYXHA=
github.com/dennwc/btrfs v0.0.0-20241002142654-12ae127e0bf6 h1:fV+JlCY0cCJh3l0jfE7iB3ZmrdfJSgfcjdrCQhPokGg=
github.com/dennwc/btrfs v0.0.0-20241002142654-12ae127e0bf6/go.mod h1:MYsOV9Dgsec3FFSOjywi0QK5r6TeBbdWxdrMGtiYXHA=
github.com/dennwc/ioctl v1.0.0 h1:DsWAAjIxRqNcLn9x6mwfuf2pet3iB7aK90K4tF16rLg=
github.com/dennwc/ioctl v1.0.0/go.mod h1:ellh2YB5ldny99SBU/VX7Nq0xiZbHphf1DrtHxxjMk0=
github.com/ema/qdisc v1.0.0 h1:EHLG08FVRbWLg8uRICa3xzC9Zm0m7HyMHfXobWFnXYg=
@ -105,14 +105,14 @@ go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU=
golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk=
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=

Loading…
Cancel
Save