mirror of
https://github.com/dcarrillo/whatismyip.git
synced 2025-11-26 10:04:10 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e8d3a20781 | |||
|
ec1de1fa81
|
|||
|
00749ae529
|
|||
|
|
9b87d28433 | ||
| 751e5f3885 | |||
|
f3216cdf21
|
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.24-alpine AS builder
|
||||
FROM golang:1.25-alpine AS builder
|
||||
|
||||
ARG ARG_VERSION
|
||||
ENV VERSION=$ARG_VERSION
|
||||
|
||||
4
Makefile
4
Makefile
@@ -52,6 +52,7 @@ docker-run: docker-build-dev
|
||||
docker run --tty --interactive --rm \
|
||||
--publish 8080:8080/tcp \
|
||||
--publish 8081:8081/tcp \
|
||||
--publish 9100:9100/tcp \
|
||||
--publish 8081:8081/udp \
|
||||
--volume ${PWD}/test:/test \
|
||||
${DOCKER_URL}:${VERSION} \
|
||||
@@ -61,4 +62,5 @@ docker-run: docker-build-dev
|
||||
-tls-bind :8081 \
|
||||
-tls-crt /test/server.pem \
|
||||
-tls-key /test/server.key \
|
||||
-enable-http3
|
||||
-enable-http3 \
|
||||
-metrics-bind :9100
|
||||
|
||||
45
README.md
45
README.md
@@ -6,31 +6,33 @@
|
||||
[](https://github.com/dcarrillo/whatismyip/releases/)
|
||||
[](./LICENSE)
|
||||
|
||||
- [What is my IP address](#what-is-my-ip-address)
|
||||
- [Features](#features)
|
||||
- [Endpoints](#endpoints)
|
||||
- [DNS discovery](#dns-discovery)
|
||||
- [Build](#build)
|
||||
- [Usage](#usage)
|
||||
- [Examples](#examples)
|
||||
- [Features](#features)
|
||||
- [Endpoints](#endpoints)
|
||||
- [DNS discovery](#dns-discovery)
|
||||
- [Build](#build)
|
||||
- [Usage](#usage)
|
||||
- [Examples](#examples)
|
||||
- [Run a default TCP server](#run-a-default-tcp-server)
|
||||
- [Run a default TCP server with geo information enabled](#run-a-default-tco-server-with-geo-information-enabled)
|
||||
- [Run a default TCP server with geo information enabled](#run-a-default-tcp-server-with-geo-information-enabled)
|
||||
- [Run a TLS (HTTP/2) and enable "what is my DNS" with geo information](#run-a-tls-http2-and-enable-what-is-my-dns-with-geo-information)
|
||||
- [Run an HTTP/3 server](#run-an-http3-server)
|
||||
- [Run a default TCP server with a custom template and trust a pair of custom headers set by an upstream proxy](#run-a-default-tcp-server-with-a-custom-template-and-trust-a-pair-of-custom-headers-set-by-an-upstream-proxy)
|
||||
- [Download](#download)
|
||||
- [Docker](#docker)
|
||||
- [Download](#download)
|
||||
- [Docker](#docker)
|
||||
- [Run a container locally using test databases](#run-a-container-locally-using-test-databases)
|
||||
- [From Docker Hub](#from-docker-hub)
|
||||
|
||||
> [!NOTE]
|
||||
> Since version 3.0.0, geodb database is not mandatory, not adding the flags will disable the geo feature.
|
||||
> Since version 2.3.0, the application includes an optional client [DNS discovery](#dns-discovery)
|
||||
> Since version 3.2.0, an optional prometheus metrics endpoint is available.
|
||||
>
|
||||
> Since version 3.0.0, the geodb database is not mandatory; not adding the flags will disable the geo feature.
|
||||
>
|
||||
> Since version 2.3.0, the application includes an optional client [DNS discovery](#dns-discovery) feature.
|
||||
|
||||
Just another "what is my IP address" service, including geolocation, TCP open port checking, and headers information. Written in go with high performance in mind,
|
||||
it uses [gin](https://github.com/gin-gonic/gin) which uses [httprouter](https://github.com/julienschmidt/httprouter) a lightweight high performance HTTP multiplexer.
|
||||
Just another "what is my IP address" service, including geolocation, TCP open port checking, and headers information. Written in Go with high performance in mind,
|
||||
it uses [gin](https://github.com/gin-gonic/gin) which uses [httprouter](https://github.com/julienschmidt/httprouter), a lightweight high-performance HTTP multiplexer.
|
||||
|
||||
Take a look at [ifconfig.es](https://ifconfig.es) a live site using `whatismyip` and the `DNS discovery` enabled.
|
||||
Take a look at [ifconfig.es](https://ifconfig.es), a live site using `whatismyip` with the `DNS discovery` feature enabled.
|
||||
|
||||
Get your public IP easily from the command line:
|
||||
|
||||
@@ -53,12 +55,13 @@ curl -L dns.ifconfig.es
|
||||
|
||||
- TLS and HTTP/2.
|
||||
- Experimental HTTP/3 support. HTTP/3 requires a TLS server running (`-tls-bind`), as HTTP/3 starts as a TLS connection that then gets upgraded to UDP. The UDP port is the same as the one used for the TLS server.
|
||||
- Beta DNS discovery: A best-effort approach to discovering the DNS server that is resolving the client's requests.
|
||||
- DNS discovery: A best-effort approach to discovering the DNS server that is resolving the client's requests.
|
||||
- Can run behind a proxy by trusting a custom header (usually `X-Real-IP`) to figure out the source IP address. It also supports a custom header to resolve the client port, if the proxy can only add a header for the IP (for example a fixed header from CDNs) the client port is shown as unknown.
|
||||
- IPv4 and IPv6.
|
||||
- Geolocation info including ASN. This feature is possible thanks to [maxmind](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data?lang=en) GeoLite2 databases. In order to use these databases, a license key is needed. Please visit Maxmind site for further instructions and get a free license.
|
||||
- Checking TCP open ports.
|
||||
- High performance.
|
||||
- Prometheus metrics endpoint: Exports metrics (on a separete process/port) for HTTP requests, request duration, geo lookups, port scans, and DNS queries.
|
||||
- Self-contained server that can reload GeoLite2 databases and/or SSL certificates without stop/start. The `hup` signal is honored.
|
||||
- HTML templates for the landing page.
|
||||
- Text plain and JSON output.
|
||||
@@ -87,7 +90,7 @@ curl -L dns.ifconfig.es
|
||||
|
||||
## DNS discovery
|
||||
|
||||
The DNS discovery works by forcing the client to make a request to `<uuid>.dns.ifconfig.es` this DNS request is handled by a microdns server
|
||||
The DNS discovery works by forcing the client to make a request to `<uuid>.dns.ifconfig.es`. This DNS request is handled by a microdns server
|
||||
included in the `whatismyip` binary. In order to run the discovery server, a configuration file in the following form has to be created:
|
||||
|
||||
```yaml
|
||||
@@ -117,7 +120,7 @@ curl $(cat /proc/sys/kernel/random/uuid).dns.ifconfig.es
|
||||
|
||||
## Build
|
||||
|
||||
Golang >= 1.22 is required.
|
||||
Golang >= 1.24 is required.
|
||||
|
||||
`make build`
|
||||
|
||||
@@ -127,6 +130,8 @@ Golang >= 1.22 is required.
|
||||
Usage of whatismyip:
|
||||
-bind string
|
||||
Listening address (see https://pkg.go.dev/net?#Listen) (default ":8080")
|
||||
-disable-scan
|
||||
Disable TCP port scanning functionality
|
||||
-enable-http3
|
||||
Enable HTTP/3 protocol. HTTP/3 requires --tls-bind set, as HTTP/3 starts as a TLS connection that then gets upgraded to UDP. The UDP port is the same as the one used for the TLS server.
|
||||
-enable-secure-headers
|
||||
@@ -135,6 +140,8 @@ Usage of whatismyip:
|
||||
Path to GeoIP2 ASN database. Enables ASN information. (--geoip2-city becomes mandatory)
|
||||
-geoip2-city string
|
||||
Path to GeoIP2 city database. Enables geo information (--geoip2-asn becomes mandatory)
|
||||
-metrics-bind string
|
||||
Listening address for Prometheus metrics endpoint (see https://pkg.go.dev/net?#Listen). It enables the metrics available at the given address/port via the /metrics endpoint.
|
||||
-resolver string
|
||||
Path to the resolver configuration. It actually enables the resolver for DNS client discovery.
|
||||
-template string
|
||||
@@ -195,7 +202,7 @@ Download the latest version from [github](https://github.com/dcarrillo/whatismyi
|
||||
|
||||
## Docker
|
||||
|
||||
An ultra-light (~4MB) image is available on [docker hub](https://hub.docker.com/r/dcarrillo/whatismyip). Since version `2.1.2`, the binary is compressed using [upx](https://github.com/upx/upx).
|
||||
An ultra-light (~6MB) image is available on [docker hub](https://hub.docker.com/r/dcarrillo/whatismyip). Since version `2.1.2`, the binary is compressed using [upx](https://github.com/upx/upx).
|
||||
|
||||
### Run a container locally using test databases
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/dcarrillo/whatismyip/internal/httputils"
|
||||
"github.com/dcarrillo/whatismyip/internal/metrics"
|
||||
"github.com/dcarrillo/whatismyip/internal/setting"
|
||||
"github.com/dcarrillo/whatismyip/resolver"
|
||||
"github.com/dcarrillo/whatismyip/server"
|
||||
@@ -54,6 +55,11 @@ func main() {
|
||||
router.Setup(engine, geoSvc)
|
||||
servers = slices.Concat(servers, setupHTTPServers(context.Background(), engine.Handler()))
|
||||
|
||||
if setting.App.PrometheusAddress != "" {
|
||||
prometheusServer := server.NewPrometheusServer(context.Background())
|
||||
servers = append(servers, prometheusServer)
|
||||
}
|
||||
|
||||
whatismyip := server.Setup(servers, geoSvc)
|
||||
whatismyip.Run()
|
||||
}
|
||||
@@ -65,6 +71,10 @@ func setupEngine() *gin.Engine {
|
||||
}
|
||||
engine := gin.New()
|
||||
engine.Use(gin.LoggerWithFormatter(httputils.GetLogFormatter), gin.Recovery())
|
||||
if setting.App.PrometheusAddress != "" {
|
||||
metrics.Enable()
|
||||
engine.Use(metrics.GinMiddleware())
|
||||
}
|
||||
if setting.App.EnableSecureHeaders {
|
||||
engine.Use(secure.New(secure.Config{
|
||||
BrowserXssFilter: true,
|
||||
|
||||
73
go.mod
73
go.mod
@@ -1,29 +1,35 @@
|
||||
module github.com/dcarrillo/whatismyip
|
||||
|
||||
go 1.24
|
||||
go 1.25
|
||||
|
||||
require (
|
||||
github.com/docker/docker v28.0.4+incompatible
|
||||
github.com/gin-contrib/secure v1.1.2
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/gin-gonic/gin v1.11.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/miekg/dns v1.1.65
|
||||
github.com/miekg/dns v1.1.68
|
||||
github.com/oschwald/maxminddb-golang v1.13.1
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/quic-go/quic-go v0.50.1
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
github.com/quic-go/quic-go v0.55.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/testcontainers/testcontainers-go v0.36.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
codeberg.org/chavacava/garif v0.2.0 // indirect
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/bytedance/sonic v1.13.2 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.4 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bytedance/gopkg v0.1.3 // indirect
|
||||
github.com/bytedance/sonic v1.14.2 // indirect
|
||||
github.com/bytedance/sonic/loader v0.4.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/cloudwego/base64x v0.1.5 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/platforms v0.2.1 // indirect
|
||||
github.com/cpuguy83/dockercfg v0.3.2 // indirect
|
||||
@@ -32,26 +38,32 @@ require (
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/ebitengine/purego v0.8.2 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/fatih/structtag v1.2.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.11 // indirect
|
||||
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // 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.26.0 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.28.0 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/goccy/go-yaml v1.18.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/magiconair/properties v1.8.9 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mgechev/dots v1.0.0 // indirect
|
||||
github.com/mgechev/revive v1.12.0 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/patternmatcher v0.6.0 // indirect
|
||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||
@@ -61,20 +73,24 @@ require (
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.23.4 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.19.2 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.25.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/spf13/afero v1.15.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // 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.12 // indirect
|
||||
github.com/ugorji/go/codec v1.3.1 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
|
||||
@@ -84,17 +100,16 @@ require (
|
||||
go.opentelemetry.io/otel/sdk v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
|
||||
go.uber.org/automaxprocs v1.6.0 // indirect
|
||||
go.uber.org/mock v0.5.1 // indirect
|
||||
golang.org/x/arch v0.16.0 // indirect
|
||||
golang.org/x/crypto v0.37.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/net v0.39.0 // indirect
|
||||
golang.org/x/sync v0.13.0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
golang.org/x/tools v0.32.0 // indirect
|
||||
go.uber.org/mock v0.6.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
golang.org/x/arch v0.22.0 // indirect
|
||||
golang.org/x/crypto v0.43.0 // indirect
|
||||
golang.org/x/mod v0.29.0 // indirect
|
||||
golang.org/x/net v0.46.0 // indirect
|
||||
golang.org/x/sync v0.17.0 // indirect
|
||||
golang.org/x/sys v0.37.0 // indirect
|
||||
golang.org/x/text v0.30.0 // indirect
|
||||
golang.org/x/tools v0.38.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
google.golang.org/protobuf v1.36.10 // indirect
|
||||
)
|
||||
|
||||
162
go.sum
162
go.sum
@@ -1,21 +1,29 @@
|
||||
codeberg.org/chavacava/garif v0.2.0 h1:F0tVjhYbuOCnvNcU3YSpO6b3Waw6Bimy4K0mM8y6MfY=
|
||||
codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0GiPTJmEqBQ=
|
||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
|
||||
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
|
||||
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||
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/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
|
||||
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
||||
github.com/bytedance/sonic v1.14.2 h1:k1twIoe97C1DtYUo+fZQy865IuHia4PR5RPiuGPPIIE=
|
||||
github.com/bytedance/sonic v1.14.2/go.mod h1:T80iDELeHiHKSc0C9tubFygiuXoGzrkjKzX2quAx980=
|
||||
github.com/bytedance/sonic/loader v0.4.0 h1:olZ7lEqcxtZygCK9EKYKADnpQoYkRQxaeY2NYzevs+o=
|
||||
github.com/bytedance/sonic/loader v0.4.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
|
||||
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
|
||||
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
|
||||
@@ -37,19 +45,23 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I=
|
||||
github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
|
||||
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/gabriel-vasile/mimetype v1.4.11 h1:AQvxbp830wPhHTqc1u7nzoLT+ZFxGY7emj5DR5DYFik=
|
||||
github.com/gabriel-vasile/mimetype v1.4.11/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
github.com/gin-contrib/secure v1.1.2 h1:6G8/NCOTSywWY7TeaH/0Yfaa6bfkE5ukkqtIm7lK11U=
|
||||
github.com/gin-contrib/secure v1.1.2/go.mod h1:xI3jI5/BpOYMCBtjgmIVrMA3kI7y9LwCFxs+eLf5S3w=
|
||||
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
|
||||
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk=
|
||||
github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
@@ -60,48 +72,54 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
|
||||
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.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
|
||||
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688=
|
||||
github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
||||
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
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/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
|
||||
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
|
||||
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
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/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
|
||||
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM=
|
||||
github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/miekg/dns v1.1.65 h1:0+tIPHzUW0GCge7IiK3guGP57VAw7hoPDfApjkMD1Fc=
|
||||
github.com/miekg/dns v1.1.65/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck=
|
||||
github.com/mgechev/dots v1.0.0 h1:o+4OJ3OjWzgQHGJXKfJ8rbH4dqDugu5BiEy84nxg0k4=
|
||||
github.com/mgechev/dots v1.0.0/go.mod h1:rykuMydC9t3wfkM+ccYH3U3ss03vZGg6h3hmOznXLH0=
|
||||
github.com/mgechev/revive v1.12.0 h1:Q+/kkbbwerrVYPv9d9efaPGmAO/NsxwW/nE6ahpQaCU=
|
||||
github.com/mgechev/revive v1.12.0/go.mod h1:VXsY2LsTigk8XU9BpZauVLjVrhICMOV3k1lpB3CXrp8=
|
||||
github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
|
||||
github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
||||
@@ -121,10 +139,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
|
||||
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
|
||||
github.com/onsi/gomega v1.36.3 h1:hID7cr8t3Wp26+cYnfcjR6HpJ00fdogN6dqZ1t6IylU=
|
||||
github.com/onsi/gomega v1.36.3/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
@@ -141,18 +157,26 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
|
||||
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.50.1 h1:unsgjFIUqW8a2oopkY7YNONpV1gYND6Nt9hnt1PN94Q=
|
||||
github.com/quic-go/quic-go v0.50.1/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E=
|
||||
github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk=
|
||||
github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs=
|
||||
github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
|
||||
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=
|
||||
@@ -162,9 +186,10 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||
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.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/testcontainers/testcontainers-go v0.36.0 h1:YpffyLuHtdp5EUsI5mT4sRw8GZhO/5ozyDT1xWGXt00=
|
||||
github.com/testcontainers/testcontainers-go v0.36.0/go.mod h1:yk73GVJ0KUZIHUtFna6MO7QS144qYpoY8lEEtU9Hed0=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
@@ -173,8 +198,8 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F
|
||||
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.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
|
||||
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
@@ -197,34 +222,34 @@ go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
|
||||
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
|
||||
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
||||
go.uber.org/mock v0.5.1 h1:ASgazW/qBmR+A32MYFDB6E2POoTgOwT509VP0CT/fjs=
|
||||
go.uber.org/mock v0.5.1/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||
golang.org/x/arch v0.16.0 h1:foMtLTdyOmIniqWCHjY6+JxuC54XP1fDwx4N0ASyW+U=
|
||||
golang.org/x/arch v0.16.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||
golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI=
|
||||
golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
||||
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.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
|
||||
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
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-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.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-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-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -235,22 +260,22 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
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.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
|
||||
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
|
||||
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
|
||||
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/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.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
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/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -261,8 +286,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e h1:
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU=
|
||||
google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
@@ -271,4 +296,3 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
||||
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
|
||||
@@ -98,6 +98,7 @@ func TestContainerIntegration(t *testing.T) {
|
||||
"8000:8000",
|
||||
"8001:8001",
|
||||
"8001:8001/udp",
|
||||
"9100:9100",
|
||||
"53531:53/udp",
|
||||
},
|
||||
Cmd: []string{
|
||||
@@ -110,6 +111,7 @@ func TestContainerIntegration(t *testing.T) {
|
||||
"-trusted-header", "X-Real-IP",
|
||||
"-enable-secure-headers",
|
||||
"-enable-http3",
|
||||
"-metrics-bind", ":9100",
|
||||
"-resolver", "/resolver.yml",
|
||||
},
|
||||
Files: []tc.ContainerFile{
|
||||
@@ -232,9 +234,92 @@ func TestContainerIntegration(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("RequestMetricsEndpoint", func(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "http://localhost:9100/metrics", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
assert.NoError(t, err)
|
||||
bodyStr := string(body)
|
||||
|
||||
assert.Contains(t, bodyStr, "whatismyip_http_requests_total")
|
||||
assert.Contains(t, bodyStr, "whatismyip_http_request_duration_seconds")
|
||||
assert.Contains(t, bodyStr, "# HELP")
|
||||
assert.Contains(t, bodyStr, "# TYPE")
|
||||
})
|
||||
|
||||
testWhatIsMyDNS(t)
|
||||
}
|
||||
|
||||
// TODO If other flags like this one are implemented we should think of a better approach
|
||||
func TestContainerIntegrationDisableScan(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skiping integration tests")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
c, err := tc.GenericContainer(ctx, tc.GenericContainerRequest{
|
||||
ContainerRequest: tc.ContainerRequest{
|
||||
FromDockerfile: tc.FromDockerfile{
|
||||
Context: "../",
|
||||
Dockerfile: "./test/Dockerfile",
|
||||
PrintBuildLog: true,
|
||||
KeepImage: false,
|
||||
BuildOptionsModifier: func(buildOptions *types.ImageBuildOptions) {
|
||||
buildOptions.Target = "test"
|
||||
},
|
||||
},
|
||||
ExposedPorts: []string{
|
||||
"8000:8000",
|
||||
},
|
||||
Cmd: []string{
|
||||
"-geoip2-city", "/GeoIP2-City-Test.mmdb",
|
||||
"-geoip2-asn", "/GeoLite2-ASN-Test.mmdb",
|
||||
"-bind", ":8000",
|
||||
"-trusted-header", "X-Real-IP",
|
||||
"-enable-secure-headers",
|
||||
"-disable-scan",
|
||||
},
|
||||
Files: []tc.ContainerFile{
|
||||
{
|
||||
HostFilePath: "./../test/GeoIP2-City-Test.mmdb",
|
||||
ContainerFilePath: "/GeoIP2-City-Test.mmdb",
|
||||
},
|
||||
{
|
||||
HostFilePath: "./../test/GeoLite2-ASN-Test.mmdb",
|
||||
ContainerFilePath: "/GeoLite2-ASN-Test.mmdb",
|
||||
},
|
||||
},
|
||||
WaitingFor: wait.ForLog("Starting TCP server"),
|
||||
AutoRemove: true,
|
||||
},
|
||||
Started: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { c.Terminate(ctx) })
|
||||
|
||||
t.Run("RequestScanEndpointWithDisabledScan", func(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "http://localhost:8000/scan/tcp/8000", nil)
|
||||
assert.NoError(t, err)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
req.Header.Set("X-Real-IP", "127.0.0.1")
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, body)
|
||||
})
|
||||
}
|
||||
|
||||
func doQuicRequest(req *http.Request) (*http.Response, []byte, error) {
|
||||
roundTripper := &http3.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
|
||||
122
internal/metrics/metrics.go
Normal file
122
internal/metrics/metrics.go
Normal file
@@ -0,0 +1,122 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
)
|
||||
|
||||
var (
|
||||
enabled bool
|
||||
initOnce sync.Once
|
||||
requestsTotal *prometheus.CounterVec
|
||||
requestDuration *prometheus.HistogramVec
|
||||
requestsInFlight prometheus.Gauge
|
||||
geoLookups *prometheus.CounterVec
|
||||
portScans prometheus.Counter
|
||||
dnsQueries *prometheus.CounterVec
|
||||
)
|
||||
|
||||
func Enable() {
|
||||
initOnce.Do(func() {
|
||||
enabled = true
|
||||
|
||||
requestsTotal = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "whatismyip_http_requests_total",
|
||||
Help: "Total number of HTTP requests",
|
||||
},
|
||||
[]string{"method", "path", "status"},
|
||||
)
|
||||
|
||||
requestDuration = promauto.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "whatismyip_http_request_duration_seconds",
|
||||
Help: "HTTP request latency in seconds",
|
||||
Buckets: prometheus.DefBuckets,
|
||||
},
|
||||
[]string{"method", "path"},
|
||||
)
|
||||
|
||||
requestsInFlight = promauto.NewGauge(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "whatismyip_http_requests_in_flight",
|
||||
Help: "Current number of HTTP requests being processed",
|
||||
},
|
||||
)
|
||||
|
||||
geoLookups = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "whatismyip_geo_lookups_total",
|
||||
Help: "Total number of geo lookups",
|
||||
},
|
||||
[]string{"type"},
|
||||
)
|
||||
|
||||
portScans = promauto.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "whatismyip_port_scans_total",
|
||||
Help: "Total number of port scan requests",
|
||||
},
|
||||
)
|
||||
|
||||
dnsQueries = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "whatismyip_dns_queries_total",
|
||||
Help: "Total number of DNS queries",
|
||||
},
|
||||
[]string{"query_type", "rcode"},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
func GinMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if !enabled {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
path := c.FullPath()
|
||||
if path == "" {
|
||||
path = "/404" // group 404s
|
||||
}
|
||||
|
||||
requestsInFlight.Inc()
|
||||
defer requestsInFlight.Dec()
|
||||
|
||||
c.Next()
|
||||
|
||||
duration := time.Since(start).Seconds()
|
||||
status := c.Writer.Status()
|
||||
|
||||
requestsTotal.WithLabelValues(c.Request.Method, path, fmt.Sprintf("%dxx", status/100)).Inc()
|
||||
requestDuration.WithLabelValues(c.Request.Method, path).Observe(duration)
|
||||
}
|
||||
}
|
||||
|
||||
func RecordGeoLookup(lookupType string) {
|
||||
if !enabled {
|
||||
return
|
||||
}
|
||||
geoLookups.WithLabelValues(lookupType).Inc()
|
||||
}
|
||||
|
||||
func RecordPortScan() {
|
||||
if !enabled {
|
||||
return
|
||||
}
|
||||
portScans.Inc()
|
||||
}
|
||||
|
||||
func RecordDNSQuery(queryType string, rcode string) {
|
||||
if !enabled {
|
||||
return
|
||||
}
|
||||
dnsQueries.WithLabelValues(queryType, rcode).Inc()
|
||||
}
|
||||
200
internal/metrics/metrics_test.go
Normal file
200
internal/metrics/metrics_test.go
Normal file
@@ -0,0 +1,200 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/prometheus/client_golang/prometheus/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDisabledMetrics_Middleware(t *testing.T) {
|
||||
if enabled {
|
||||
t.Skip("Skipping disabled test - metrics already enabled")
|
||||
}
|
||||
|
||||
gin.SetMode(gin.TestMode)
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
|
||||
c.Request = httptest.NewRequest("GET", "/test", nil)
|
||||
|
||||
middleware := GinMiddleware()
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
middleware(c)
|
||||
})
|
||||
}
|
||||
|
||||
func TestDisabledMetrics_GeoLookup(t *testing.T) {
|
||||
if enabled {
|
||||
t.Skip("Skipping disabled test - metrics already enabled")
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
RecordGeoLookup("city")
|
||||
})
|
||||
}
|
||||
|
||||
func TestDisabledMetrics_PortScan(t *testing.T) {
|
||||
if enabled {
|
||||
t.Skip("Skipping disabled test - metrics already enabled")
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
RecordPortScan()
|
||||
})
|
||||
}
|
||||
|
||||
func TestDisabledMetrics_DNSQuery(t *testing.T) {
|
||||
if enabled {
|
||||
t.Skip("Skipping disabled test - metrics already enabled")
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
RecordDNSQuery("A", "NOERROR")
|
||||
})
|
||||
}
|
||||
|
||||
func TestEnable(t *testing.T) {
|
||||
Enable()
|
||||
|
||||
assert.True(t, enabled, "Enable() should set enabled to true")
|
||||
assert.NotNil(t, requestsTotal, "requestsTotal should be initialized")
|
||||
assert.NotNil(t, requestDuration, "requestDuration should be initialized")
|
||||
assert.NotNil(t, requestsInFlight, "requestsInFlight should be initialized")
|
||||
assert.NotNil(t, geoLookups, "geoLookups should be initialized")
|
||||
assert.NotNil(t, portScans, "portScans should be initialized")
|
||||
assert.NotNil(t, dnsQueries, "dnsQueries should be initialized")
|
||||
}
|
||||
|
||||
func TestEnableIdempotent(t *testing.T) {
|
||||
Enable()
|
||||
firstRequestsTotal := requestsTotal
|
||||
|
||||
Enable()
|
||||
Enable()
|
||||
|
||||
assert.Equal(t, firstRequestsTotal, requestsTotal, "Enable() should be idempotent")
|
||||
}
|
||||
|
||||
func TestGinMiddleware_StatusCategories(t *testing.T) {
|
||||
Enable()
|
||||
|
||||
testCases := []struct {
|
||||
status int
|
||||
category string
|
||||
}{
|
||||
{200, "2xx"},
|
||||
{201, "2xx"},
|
||||
{301, "3xx"},
|
||||
{404, "4xx"},
|
||||
{500, "5xx"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
gin.SetMode(gin.TestMode)
|
||||
router := gin.New()
|
||||
router.Use(GinMiddleware())
|
||||
router.GET("/test-status", func(c *gin.Context) {
|
||||
c.Status(tc.status)
|
||||
})
|
||||
|
||||
initialCount := testutil.ToFloat64(requestsTotal.WithLabelValues("GET", "/test-status", tc.category))
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req := httptest.NewRequest("GET", "/test-status", nil)
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
count := testutil.ToFloat64(requestsTotal.WithLabelValues("GET", "/test-status", tc.category))
|
||||
assert.Equal(t, initialCount+1, count, "Expected count for category %s to increase by 1", tc.category)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGinMiddleware_404(t *testing.T) {
|
||||
Enable()
|
||||
|
||||
gin.SetMode(gin.TestMode)
|
||||
router := gin.New()
|
||||
router.Use(GinMiddleware())
|
||||
|
||||
initialCount := testutil.ToFloat64(requestsTotal.WithLabelValues("GET", "/404", "4xx"))
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req := httptest.NewRequest("GET", "/nonexistent-path", nil)
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
count := testutil.ToFloat64(requestsTotal.WithLabelValues("GET", "/404", "4xx"))
|
||||
assert.Equal(t, initialCount+1, count, "Expected count to increase by 1 for empty path (404)")
|
||||
}
|
||||
|
||||
func TestGinMiddleware_RecordsDuration(t *testing.T) {
|
||||
Enable()
|
||||
|
||||
gin.SetMode(gin.TestMode)
|
||||
router := gin.New()
|
||||
router.Use(GinMiddleware())
|
||||
router.GET("/test-duration", func(c *gin.Context) {
|
||||
c.Status(http.StatusOK)
|
||||
})
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req := httptest.NewRequest("GET", "/test-duration", nil)
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
metric := requestDuration.WithLabelValues("GET", "/test-duration")
|
||||
assert.NotNil(t, metric, "Expected histogram metric to exist")
|
||||
}
|
||||
|
||||
func TestRecordGeoLookup(t *testing.T) {
|
||||
Enable()
|
||||
|
||||
initialCityCount := testutil.ToFloat64(geoLookups.WithLabelValues("city"))
|
||||
initialCountryCount := testutil.ToFloat64(geoLookups.WithLabelValues("asn"))
|
||||
|
||||
RecordGeoLookup("city")
|
||||
RecordGeoLookup("city")
|
||||
RecordGeoLookup("asn")
|
||||
|
||||
cityCount := testutil.ToFloat64(geoLookups.WithLabelValues("city"))
|
||||
assert.Equal(t, initialCityCount+2, cityCount, "Expected city lookups to increase by 2")
|
||||
|
||||
countryCount := testutil.ToFloat64(geoLookups.WithLabelValues("asn"))
|
||||
assert.Equal(t, initialCountryCount+1, countryCount, "Expected country lookups to increase by 1")
|
||||
}
|
||||
|
||||
func TestRecordPortScan(t *testing.T) {
|
||||
Enable()
|
||||
|
||||
initialCount := testutil.ToFloat64(portScans)
|
||||
|
||||
RecordPortScan()
|
||||
RecordPortScan()
|
||||
|
||||
count := testutil.ToFloat64(portScans)
|
||||
assert.Equal(t, initialCount+2, count, "Expected port scans to increase by 2")
|
||||
}
|
||||
|
||||
func TestRecordDNSQuery(t *testing.T) {
|
||||
Enable()
|
||||
|
||||
initialACount := testutil.ToFloat64(dnsQueries.WithLabelValues("A", "NOERROR"))
|
||||
initialAAAACount := testutil.ToFloat64(dnsQueries.WithLabelValues("AAAA", "NOERROR"))
|
||||
initialNXDOMAINCount := testutil.ToFloat64(dnsQueries.WithLabelValues("A", "NXDOMAIN"))
|
||||
|
||||
RecordDNSQuery("A", "NOERROR")
|
||||
RecordDNSQuery("A", "NOERROR")
|
||||
RecordDNSQuery("AAAA", "NOERROR")
|
||||
RecordDNSQuery("A", "NXDOMAIN")
|
||||
|
||||
aCount := testutil.ToFloat64(dnsQueries.WithLabelValues("A", "NOERROR"))
|
||||
assert.Equal(t, initialACount+2, aCount, "Expected A NOERROR queries to increase by 2")
|
||||
|
||||
aaaaCount := testutil.ToFloat64(dnsQueries.WithLabelValues("AAAA", "NOERROR"))
|
||||
assert.Equal(t, initialAAAACount+1, aaaaCount, "Expected AAAA NOERROR queries to increase by 1")
|
||||
|
||||
nxdomainCount := testutil.ToFloat64(dnsQueries.WithLabelValues("A", "NXDOMAIN"))
|
||||
assert.Equal(t, initialNXDOMAINCount+1, nxdomainCount, "Expected A NXDOMAIN queries to increase by 1")
|
||||
}
|
||||
@@ -37,10 +37,12 @@ type settings struct {
|
||||
TLSAddress string
|
||||
TLSCrtPath string
|
||||
TLSKeyPath string
|
||||
PrometheusAddress string
|
||||
TrustedHeader string
|
||||
TrustedPortHeader string
|
||||
EnableSecureHeaders bool
|
||||
EnableHTTP3 bool
|
||||
DisableTCPScan bool
|
||||
Server serverSettings
|
||||
Resolver resolver
|
||||
version bool
|
||||
@@ -86,6 +88,12 @@ func Setup(args []string) (output string, err error) {
|
||||
)
|
||||
flags.StringVar(&App.TLSCrtPath, "tls-crt", "", "When using TLS, path to certificate file")
|
||||
flags.StringVar(&App.TLSKeyPath, "tls-key", "", "When using TLS, path to private key file")
|
||||
flags.StringVar(
|
||||
&App.PrometheusAddress,
|
||||
"metrics-bind",
|
||||
"",
|
||||
"Listening address for Prometheus metrics endpoint (see https://pkg.go.dev/net?#Listen). It enables the metrics available at the given address/port via the /metrics endpoint.",
|
||||
)
|
||||
flags.StringVar(
|
||||
&App.TrustedHeader,
|
||||
"trusted-header",
|
||||
@@ -111,6 +119,12 @@ func Setup(args []string) (output string, err error) {
|
||||
false,
|
||||
"Enable HTTP/3 protocol. HTTP/3 requires --tls-bind set, as HTTP/3 starts as a TLS connection that then gets upgraded to UDP. The UDP port is the same as the one used for the TLS server.",
|
||||
)
|
||||
flags.BoolVar(
|
||||
&App.DisableTCPScan,
|
||||
"disable-scan",
|
||||
false,
|
||||
"Disable TCP port scanning functionality",
|
||||
)
|
||||
|
||||
err = flags.Parse(args)
|
||||
if err != nil {
|
||||
|
||||
@@ -77,6 +77,17 @@ func TestParseFlags(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
[]string{"-disable-scan"},
|
||||
settings{
|
||||
BindAddress: ":8080",
|
||||
Server: serverSettings{
|
||||
ReadTimeout: 10 * time.Second,
|
||||
WriteTimeout: 10 * time.Second,
|
||||
},
|
||||
DisableTCPScan: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
[]string{"-bind", ":8001", "-geoip2-city", "/city-path", "-geoip2-asn", "/asn-path"},
|
||||
settings{
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/dcarrillo/whatismyip/internal/metrics"
|
||||
"github.com/dcarrillo/whatismyip/internal/setting"
|
||||
"github.com/dcarrillo/whatismyip/internal/validator/uuid"
|
||||
"github.com/miekg/dns"
|
||||
@@ -59,6 +60,7 @@ func (rsv *Resolver) blackHole(w dns.ResponseWriter, r *dns.Msg) {
|
||||
msg.SetRcode(r, dns.RcodeRefused)
|
||||
w.WriteMsg(msg)
|
||||
logger(w, r.Question[0], msg.Rcode)
|
||||
metrics.RecordDNSQuery(dns.TypeToString[r.Question[0].Qtype], dns.RcodeToString[msg.Rcode])
|
||||
}
|
||||
|
||||
func (rsv *Resolver) resolve(w dns.ResponseWriter, r *dns.Msg) {
|
||||
@@ -78,6 +80,7 @@ func (rsv *Resolver) resolve(w dns.ResponseWriter, r *dns.Msg) {
|
||||
logger(w, q, msg.Rcode)
|
||||
}
|
||||
w.WriteMsg(msg)
|
||||
metrics.RecordDNSQuery(dns.TypeToString[q.Qtype], dns.RcodeToString[msg.Rcode])
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -96,6 +99,7 @@ func (rsv *Resolver) resolve(w dns.ResponseWriter, r *dns.Msg) {
|
||||
|
||||
w.WriteMsg(msg)
|
||||
logger(w, q, msg.Rcode)
|
||||
metrics.RecordDNSQuery(dns.TypeToString[q.Qtype], dns.RcodeToString[msg.Rcode])
|
||||
}
|
||||
|
||||
func (rsv *Resolver) getIP(question dns.Question, msg *dns.Msg) int {
|
||||
|
||||
@@ -24,7 +24,9 @@ func SetupTemplate(r *gin.Engine) {
|
||||
func Setup(r *gin.Engine, geo *service.Geo) {
|
||||
geoSvc = geo
|
||||
r.GET("/", getRoot)
|
||||
if !setting.App.DisableTCPScan {
|
||||
r.GET("/scan/tcp/:port", scanTCPPort)
|
||||
}
|
||||
r.GET("/client-port", getClientPortAsString)
|
||||
r.GET("/geo", getGeoAsString)
|
||||
r.GET("/geo/:field", getGeoAsString)
|
||||
|
||||
48
server/prometheus.go
Normal file
48
server/prometheus.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/dcarrillo/whatismyip/internal/setting"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
type Prometheus struct {
|
||||
server *http.Server
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func NewPrometheusServer(ctx context.Context) *Prometheus {
|
||||
return &Prometheus{
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Prometheus) Start() {
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/metrics", promhttp.Handler())
|
||||
|
||||
p.server = &http.Server{
|
||||
Addr: setting.App.PrometheusAddress,
|
||||
Handler: mux,
|
||||
ReadTimeout: setting.App.Server.ReadTimeout,
|
||||
WriteTimeout: setting.App.Server.WriteTimeout,
|
||||
}
|
||||
|
||||
log.Printf("Starting Prometheus server listening on %s", setting.App.PrometheusAddress)
|
||||
go func() {
|
||||
if err := p.server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (p *Prometheus) Stop() {
|
||||
log.Print("Stopping Prometheus server...")
|
||||
if err := p.server.Shutdown(p.ctx); err != nil {
|
||||
log.Printf("Prometheus server forced to shutdown: %s", err)
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/dcarrillo/whatismyip/internal/metrics"
|
||||
"github.com/dcarrillo/whatismyip/models"
|
||||
)
|
||||
|
||||
@@ -41,6 +42,7 @@ func (g *Geo) LookUpCity(ip net.IP) *models.GeoRecord {
|
||||
return nil
|
||||
}
|
||||
|
||||
metrics.RecordGeoLookup("city")
|
||||
return record
|
||||
}
|
||||
|
||||
@@ -51,6 +53,7 @@ func (g *Geo) LookUpASN(ip net.IP) *models.ASNRecord {
|
||||
return nil
|
||||
}
|
||||
|
||||
metrics.RecordGeoLookup("asn")
|
||||
return record
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package service
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/dcarrillo/whatismyip/internal/metrics"
|
||||
)
|
||||
|
||||
const scannerTimeOut = 3 * time.Second
|
||||
@@ -20,5 +22,6 @@ func (p *PortScanner) IsPortOpen() (bool, error) {
|
||||
defer conn.Close()
|
||||
}
|
||||
|
||||
metrics.RecordPortScan()
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.24-alpine AS builder
|
||||
FROM golang:1.25-alpine AS builder
|
||||
|
||||
ARG ARG_VERSION
|
||||
ENV VERSION=$ARG_VERSION
|
||||
|
||||
Reference in New Issue
Block a user