Repository: kubernetes-sigs/external-dns

Issue:
Tons of useless warning log messages for instrumented_http.Transport
**What happened**:

I was running smoke tests for this pull-request https://github.com/kubernetes-sigs/external-dns/pull/5135 with following arguments

```sh
go run main.go \
    --provider=aws-sd \
    --registry=aws-sd \
    --source=service \
    --aws-zone-type=private \
    --log-level=info \
    --domain-filter=company.local \
    --policy=sync \
    --interval=10s \
    --annotation-filter="dns.company.com/type=internal" \
    --fqdn-template='{{index .ObjectMeta.Annotations "dns.company.com/label"}}.company.local'
```

in the logs, miriads of entries similar to below appears 
```
W0304 00:50:46.042791   20487 transport.go:356] Unable to cancel request for *instrumented_http.Transport
```

Metrics not computed, or computed incorrectly

Setting the debug level to `info` and logs dissapearing.

Quick investigation, reveal, that this is a regression

- https://github.com/kubernetes-sigs/external-dns/issues/2348
- https://github.com/kubernetes-sigs/external-dns/pull/3870
- https://github.com/kubernetes-sigs/external-dns/pull/1328
- https://github.com/kubernetes-sigs/external-dns/issues/4960

Issue(root cause) is in non-maintained library and is here https://github.com/linki/instrumented_http

**What you expected to happen**:

The issue is fixed

**How to reproduce it (as minimally and precisely as possible)**:

Follow pull-request https://github.com/kubernetes-sigs/external-dns/pull/5135#issuecomment-2694092888

or deploy latest nightly build https://console.cloud.google.com/gcr/images/k8s-staging-external-dns/GLOBAL/external-dns?pli=1&inv=1&invt=AboL6Q with debug level is not

**Anything else we need to know?**:

**Environment**:

- External-DNS version (use `external-dns --version`): v0.15.2 (unreleased with go 1.24)
- DNS provider: aws
- Others: unreleased version


Discussion:
@hjoshi123: @ivankatliarchuk can I work on this?@ivankatliarchuk: Hi. I think I need to decide on the approach. Do you know how to write a unit test only to validate this incorrect behaviour, and proof a regression?@jkossis: Any update on this?@svdo: FYI: I'm also seeing this with master from April 21 (8e695e68b1b25bb84ce6a84da8b43205ee00de93), a version that I just happened to be testing because of unreleased provider-contributed code.@yesid-lopez: I am getting the same error@schollii: Same error. Even if it is benign, it could be confusing to someone who is troubleshooting and does not know that. One more thing for them to search for and read threads just to conclude "this error is not part of the problem I'm having".

Solution patch:
diff --git a/go.mod b/go.mod
index f2f93575..498acdeb 100644
--- a/go.mod
+++ b/go.mod
@@ -8,7 +8,7 @@ require (
 	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1
 	github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0
 	github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0
-	github.com/F5Networks/k8s-bigip-ctlr/v2 v2.20.0
+	github.com/F5Networks/k8s-bigip-ctlr/v2 v2.20.1
 	github.com/Yamashou/gqlgenc v0.33.0
 	github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2
 	github.com/alecthomas/kingpin/v2 v2.4.0
@@ -16,7 +16,7 @@ require (
 	github.com/aws/aws-sdk-go-v2 v1.36.5
 	github.com/aws/aws-sdk-go-v2/config v1.29.17
 	github.com/aws/aws-sdk-go-v2/credentials v1.17.70
-	github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.19.4
+	github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.19.5
 	github.com/aws/aws-sdk-go-v2/service/dynamodb v1.44.0
 	github.com/aws/aws-sdk-go-v2/service/route53 v1.53.0
 	github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.35.7
@@ -29,7 +29,7 @@ require (
 	github.com/cloudfoundry-community/go-cfclient v0.0.0-20190201205600-f136f9222381
 	github.com/datawire/ambassador v1.12.4
 	github.com/denverdino/aliyungo v0.0.0-20230411124812-ab98a9173ace
-	github.com/digitalocean/godo v1.157.0
+	github.com/digitalocean/godo v1.158.0
 	github.com/dnsimple/dnsimple-go v1.7.0
 	github.com/exoscale/egoscale v0.102.3
 	github.com/ffledgling/pdns-go v0.0.0-20180219074714-524e7daccd99
@@ -38,19 +38,19 @@ require (
 	github.com/goccy/go-yaml v1.18.0
 	github.com/google/go-cmp v0.7.0
 	github.com/google/uuid v1.6.0
-	github.com/linki/instrumented_http v0.3.0
 	github.com/linode/linodego v1.53.0
 	github.com/maxatome/go-testdeep v1.14.0
 	github.com/miekg/dns v1.1.67
 	github.com/openshift/api v0.0.0-20230607130528-611114dca681
 	github.com/openshift/client-go v0.0.0-20230607134213-3cd0021bbee3
-	github.com/oracle/oci-go-sdk/v65 v65.95.1
+	github.com/oracle/oci-go-sdk/v65 v65.95.2
 	github.com/ovh/go-ovh v1.9.0
 	github.com/patrickmn/go-cache v2.1.0+incompatible
 	github.com/pluralsh/gqlclient v1.12.2
 	github.com/projectcontour/contour v1.32.0
 	github.com/prometheus/client_golang v1.22.0
 	github.com/prometheus/client_model v0.6.2
+	github.com/prometheus/common v0.64.0
 	github.com/scaleway/scaleway-sdk-go v1.0.0-beta.34
 	github.com/sirupsen/logrus v1.9.3
 	github.com/stretchr/testify v1.10.0
@@ -63,13 +63,13 @@ require (
 	golang.org/x/sync v0.16.0
 	golang.org/x/text v0.27.0
 	golang.org/x/time v0.12.0
-	google.golang.org/api v0.241.0
+	google.golang.org/api v0.242.0
 	gopkg.in/ns1/ns1-go.v2 v2.14.4
 	istio.io/api v1.26.2
 	istio.io/client-go v1.26.2
-	k8s.io/api v0.33.2
-	k8s.io/apimachinery v0.33.2
-	k8s.io/client-go v0.33.2
+	k8s.io/api v0.33.3
+	k8s.io/apimachinery v0.33.3
+	k8s.io/client-go v0.33.3
 	k8s.io/klog/v2 v2.130.1
 	sigs.k8s.io/controller-runtime v0.21.0
 	sigs.k8s.io/gateway-api v1.3.0
@@ -89,7 +89,7 @@ require (
 	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 // indirect
 	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 // indirect
 	github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
-	github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.25.6 // indirect
+	github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.26.0 // indirect
 	github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect
 	github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.17 // indirect
 	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 // indirect
@@ -154,7 +154,6 @@ require (
 	github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
-	github.com/prometheus/common v0.64.0 // indirect
 	github.com/prometheus/procfs v0.15.1 // indirect
 	github.com/rivo/uniseg v0.2.0 // indirect
 	github.com/schollz/progressbar/v3 v3.8.6 // indirect
diff --git a/go.sum b/go.sum
index 702b715a..b7f9df37 100644
--- a/go.sum
+++ b/go.sum
@@ -48,8 +48,8 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
-github.com/F5Networks/k8s-bigip-ctlr/v2 v2.20.0 h1:WqsoU+5aA9kDypiBzWbLSkESQUA3NDLNvkjTFzipX3I=
-github.com/F5Networks/k8s-bigip-ctlr/v2 v2.20.0/go.mod h1:/lGdCgv0e1qrS4ithe2qTU6q23IT8kqZhMlFBQmuNi0=
+github.com/F5Networks/k8s-bigip-ctlr/v2 v2.20.1 h1:O4a7qJCbH2bQPzsk7NNIm9/2orkYEH7g4Uerdp0gzps=
+github.com/F5Networks/k8s-bigip-ctlr/v2 v2.20.1/go.mod h1:/lGdCgv0e1qrS4ithe2qTU6q23IT8kqZhMlFBQmuNi0=
 github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
 github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
 github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
@@ -120,8 +120,8 @@ github.com/aws/aws-sdk-go-v2/config v1.29.17 h1:jSuiQ5jEe4SAMH6lLRMY9OVC+TqJLP56
 github.com/aws/aws-sdk-go-v2/config v1.29.17/go.mod h1:9P4wwACpbeXs9Pm9w1QTh6BwWwJjwYvJ1iCt5QbCXh8=
 github.com/aws/aws-sdk-go-v2/credentials v1.17.70 h1:ONnH5CM16RTXRkS8Z1qg7/s2eDOhHhaXVd72mmyv4/0=
 github.com/aws/aws-sdk-go-v2/credentials v1.17.70/go.mod h1:M+lWhhmomVGgtuPOhO85u4pEa3SmssPTdcYpP/5J/xc=
-github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.19.4 h1:jKR2jpZqpmBSAVX7xxdOi1E3Z0E9WizMIlxlGI3Hh9o=
-github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.19.4/go.mod h1:ATyfcCpSMZuB/rnpFcVbiqrTiFzdwcTXeVbgEk6iXbY=
+github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.19.5 h1:oUEqVqonG3xuarrsze1KVJ30KagNYDemikTbdu8KlN8=
+github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.19.5/go.mod h1:VNM08cHlOsIbSHRqb6D/M2L4kKXfJv3A2/f0GNbOQSc=
 github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 h1:KAXP9JSHO1vKGCr5f4O6WmlVKLFFXgWYAGoJosorxzU=
 github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32/go.mod h1:h4Sg6FQdexC1yYG9RDnOvLbW1a/P986++/Y/a+GyEM8=
 github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 h1:SsytQyTMHMDPspp+spo7XwXTP44aJZZAC7fBV2C5+5s=
@@ -132,8 +132,8 @@ github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d
 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
 github.com/aws/aws-sdk-go-v2/service/dynamodb v1.44.0 h1:A99gjqZDbdhjtjJVZrmVzVKO2+p3MSg35bDWtbMQVxw=
 github.com/aws/aws-sdk-go-v2/service/dynamodb v1.44.0/go.mod h1:mWB0GE1bqcVSvpW7OtFA0sKuHk52+IqtnsYU2jUfYAs=
-github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.25.6 h1:QHaS/SHXfyNycuu4GiWb+AfW5T3bput6X5E3Ai/Q31M=
-github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.25.6/go.mod h1:He/RikglWUczbkV+fkdpcV/3GdL/rTRNVy7VaUiezMo=
+github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.26.0 h1:0wOCTKrmwkyC8Bk76hYH/B4IJn5MGt6gMkSXc0A2uyc=
+github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.26.0/go.mod h1:He/RikglWUczbkV+fkdpcV/3GdL/rTRNVy7VaUiezMo=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 h1:CXV68E2dNqhuynZJPB80bhPQwAKqBWVer887figW6Jc=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4/go.mod h1:/xFi9KtvBXP97ppCz1TAEvU1Uf66qvid89rbem3wCzQ=
 github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.17 h1:x187MqiHwBGjMGAed8Y8K1VGuCtFvQvXb24r+bwmSdo=
@@ -252,8 +252,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
-github.com/digitalocean/godo v1.157.0 h1:ReELaS6FxXNf8gryUiVH0wmyUmZN8/NCmBX4gXd3F0o=
-github.com/digitalocean/godo v1.157.0/go.mod h1:tYeiWY5ZXVpU48YaFv0M5irUFHXGorZpDNm7zzdWMzM=
+github.com/digitalocean/godo v1.158.0 h1:XW7UlJn2X2qH8JOm6N63Hk/PjPHjLdYgG4zPaSbmbGc=
+github.com/digitalocean/godo v1.158.0/go.mod h1:tYeiWY5ZXVpU48YaFv0M5irUFHXGorZpDNm7zzdWMzM=
 github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
 github.com/dnsimple/dnsimple-go v1.7.0 h1:JKu9xJtZ3SqOC+BuYgAWeab7+EEx0sz422vu8j611ZY=
 github.com/dnsimple/dnsimple-go v1.7.0/go.mod h1:EKpuihlWizqYafSnQHGCd/gyvy3HkEQJ7ODB4KdV8T8=
@@ -676,8 +676,6 @@ github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
 github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
 github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
-github.com/linki/instrumented_http v0.3.0 h1:dsN92+mXpfZtjJraartcQ99jnuw7fqsnPDjr85ma2dA=
-github.com/linki/instrumented_http v0.3.0/go.mod h1:pjYbItoegfuVi2GUOMhEqzvm/SJKuEL3H0tc8QRLRFk=
 github.com/linode/linodego v1.53.0 h1:UWr7bUUVMtcfsuapC+6blm6+jJLPd7Tf9MZUpdOERnI=
 github.com/linode/linodego v1.53.0/go.mod h1:bI949fZaVchjWyKIA08hNyvAcV6BAS+PM2op3p7PAWA=
 github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
@@ -821,8 +819,8 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS
 github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
 github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
-github.com/oracle/oci-go-sdk/v65 v65.95.1 h1:KCYeX+c+A0ezLVgXKpEcgXNukn6wBkD9oWoSV2FlaUs=
-github.com/oracle/oci-go-sdk/v65 v65.95.1/go.mod h1:u6XRPsw9tPziBh76K7GrrRXPa8P8W3BQeqJ6ZZt9VLA=
+github.com/oracle/oci-go-sdk/v65 v65.95.2 h1:0HJ0AgpLydp/DtvYrF2d4str2BjXOVAeNbuW7E07g94=
+github.com/oracle/oci-go-sdk/v65 v65.95.2/go.mod h1:u6XRPsw9tPziBh76K7GrrRXPa8P8W3BQeqJ6ZZt9VLA=
 github.com/ovh/go-ovh v1.9.0 h1:6K8VoL3BYjVV3In9tPJUdT7qMx9h0GExN9EXx1r2kKE=
 github.com/ovh/go-ovh v1.9.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c=
 github.com/oxtoacart/bpool v0.0.0-20150712133111-4e1c5567d7c2 h1:CXwSGu/LYmbjEab5aMCs5usQRVBGThelUKBNnoSOuso=
@@ -1352,8 +1350,8 @@ gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZ
 google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
 google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
-google.golang.org/api v0.241.0 h1:QKwqWQlkc6O895LchPEDUSYr22Xp3NCxpQRiWTB6avE=
-google.golang.org/api v0.241.0/go.mod h1:cOVEm2TpdAGHL2z+UwyS+kmlGr3bVWQQ6sYEqkKje50=
+google.golang.org/api v0.242.0 h1:7Lnb1nfnpvbkCiZek6IXKdJ0MFuAZNAJKQfA1ws62xg=
+google.golang.org/api v0.242.0/go.mod h1:cOVEm2TpdAGHL2z+UwyS+kmlGr3bVWQQ6sYEqkKje50=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -1461,16 +1459,16 @@ istio.io/client-go v1.26.2/go.mod h1:eAImguSJPdaDiSSS2CEsywNHE8WWfqd3WfS18Rj8ynI
 k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8=
 k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78=
 k8s.io/api v0.18.4/go.mod h1:lOIQAKYgai1+vz9J7YcDZwC26Z0zQewYOGWdyIPUUQ4=
-k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY=
-k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
+k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8=
+k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE=
 k8s.io/apiextensions-apiserver v0.18.0/go.mod h1:18Cwn1Xws4xnWQNC00FLq1E350b9lUF+aOdIWDOZxgo=
 k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY=
 k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio=
 k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
 k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
 k8s.io/apimachinery v0.18.4/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
-k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
-k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
+k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA=
+k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
 k8s.io/apiserver v0.18.0/go.mod h1:3S2O6FeBBd6XTo0njUrLxiqk8GNy6wWOftjhJcXYnjw=
 k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw=
 k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8=
@@ -1479,8 +1477,8 @@ k8s.io/cli-runtime v0.18.4/go.mod h1:9/hS/Cuf7NVzWR5F/5tyS6xsnclxoPLVtwhnkJG1Y4g
 k8s.io/client-go v0.18.0/go.mod h1:uQSYDYs4WhVZ9i6AIoEZuwUggLVEF64HOD37boKAtF8=
 k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU=
 k8s.io/client-go v0.18.4/go.mod h1:f5sXwL4yAZRkAtzOxRWUhA/N8XzGCb+nPZI8PfobZ9g=
-k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E=
-k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo=
+k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA=
+k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg=
 k8s.io/code-generator v0.18.0/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
 k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
 k8s.io/code-generator v0.18.4/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
diff --git a/pkg/http/http.go b/pkg/http/http.go
new file mode 100644
index 00000000..b6069f1a
--- /dev/null
+++ b/pkg/http/http.go
@@ -0,0 +1,97 @@
+/*
+Copyright 2025 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// ref: https://github.com/linki/instrumented_http/blob/master/client.go
+
+package http
+
+import (
+	"fmt"
+	"net/http"
+	"strings"
+	"time"
+
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+var (
+	requestDuration = prometheus.NewSummaryVec(
+		prometheus.SummaryOpts{
+			Name:        "request_duration_seconds",
+			Help:        "The HTTP request latencies in seconds.",
+			Subsystem:   "http",
+			ConstLabels: prometheus.Labels{"handler": "instrumented_http"},
+			Objectives:  map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
+		},
+		[]string{"scheme", "host", "path", "method", "status"},
+	)
+)
+
+func init() {
+	prometheus.MustRegister(requestDuration)
+}
+
+type CustomRoundTripper struct {
+	next http.RoundTripper
+}
+
+// CancelRequest is a no-op to satisfy interfaces that require it.
+// https://github.com/kubernetes/client-go/blob/34f52c14eaed7e50c845cc14e85e1c4c91e77470/transport/transport.go#L346
+func (r *CustomRoundTripper) CancelRequest(_ *http.Request) {
+}
+
+func (r *CustomRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
+	start := time.Now()
+	resp, err := r.next.RoundTrip(req)
+
+	status := ""
+	if resp != nil {
+		status = fmt.Sprintf("%d", resp.StatusCode)
+	}
+
+	labels := prometheus.Labels{
+		"scheme": req.URL.Scheme,
+		"host":   req.URL.Host,
+		"path":   pathProcessor(req.URL.Path),
+		"method": req.Method,
+		"status": status,
+	}
+	requestDuration.With(labels).Observe(time.Since(start).Seconds())
+	return resp, err
+}
+
+func NewInstrumentedClient(next *http.Client) *http.Client {
+	if next == nil {
+		next = http.DefaultClient
+	}
+
+	next.Transport = NewInstrumentedTransport(next.Transport)
+
+	return next
+}
+
+func NewInstrumentedTransport(next http.RoundTripper) http.RoundTripper {
+	if next == nil {
+		next = http.DefaultTransport
+	}
+
+	return &CustomRoundTripper{next: next}
+}
+
+func pathProcessor(path string) string {
+	parts := strings.Split(path, "/")
+	return parts[len(parts)-1]
+}
diff --git a/provider/aws/config.go b/provider/aws/config.go
index 5908150e..ecc53c90 100644
--- a/provider/aws/config.go
+++ b/provider/aws/config.go
@@ -20,16 +20,16 @@ import (
 	"context"
 	"fmt"
 	"net/http"
-	"strings"
 
 	awsv2 "github.com/aws/aws-sdk-go-v2/aws"
 	"github.com/aws/aws-sdk-go-v2/aws/retry"
 	"github.com/aws/aws-sdk-go-v2/config"
 	stscredsv2 "github.com/aws/aws-sdk-go-v2/credentials/stscreds"
 	"github.com/aws/aws-sdk-go-v2/service/sts"
-	"github.com/linki/instrumented_http"
 	"github.com/sirupsen/logrus"
 
+	extdnshttp "sigs.k8s.io/external-dns/pkg/http"
+
 	"sigs.k8s.io/external-dns/pkg/apis/externaldns"
 )
 
@@ -84,12 +84,7 @@ func newV2Config(awsConfig AWSSessionConfig) (awsv2.Config, error) {
 		config.WithRetryer(func() awsv2.Retryer {
 			return retry.AddWithMaxAttempts(retry.NewStandard(), awsConfig.APIRetries)
 		}),
-		config.WithHTTPClient(instrumented_http.NewClient(&http.Client{}, &instrumented_http.Callbacks{
-			PathProcessor: func(path string) string {
-				parts := strings.Split(path, "/")
-				return parts[len(parts)-1]
-			},
-		})),
+		config.WithHTTPClient(extdnshttp.NewInstrumentedClient(&http.Client{})),
 		config.WithSharedConfigProfile(awsConfig.Profile),
 	}
 
diff --git a/provider/google/google.go b/provider/google/google.go
index 68217e37..fd521fc0 100644
--- a/provider/google/google.go
+++ b/provider/google/google.go
@@ -20,17 +20,17 @@ import (
 	"context"
 	"fmt"
 	"sort"
-	"strings"
 	"time"
 
 	"cloud.google.com/go/compute/metadata"
-	"github.com/linki/instrumented_http"
 	log "github.com/sirupsen/logrus"
 	"golang.org/x/oauth2/google"
 	dns "google.golang.org/api/dns/v1"
 	googleapi "google.golang.org/api/googleapi"
 	"google.golang.org/api/option"
 
+	extdnshttp "sigs.k8s.io/external-dns/pkg/http"
+
 	"sigs.k8s.io/external-dns/endpoint"
 	"sigs.k8s.io/external-dns/plan"
 	"sigs.k8s.io/external-dns/provider"
@@ -131,12 +131,7 @@ func NewGoogleProvider(ctx context.Context, project string, domainFilter *endpoi
 		return nil, err
 	}
 
-	gcloud = instrumented_http.NewClient(gcloud, &instrumented_http.Callbacks{
-		PathProcessor: func(path string) string {
-			parts := strings.Split(path, "/")
-			return parts[len(parts)-1]
-		},
-	})
+	gcloud = extdnshttp.NewInstrumentedClient(gcloud)
 
 	dnsClient, err := dns.NewService(ctx, option.WithHTTPClient(gcloud))
 	if err != nil {
diff --git a/provider/pihole/client.go b/provider/pihole/client.go
index cccf8523..f133735d 100644
--- a/provider/pihole/client.go
+++ b/provider/pihole/client.go
@@ -28,10 +28,11 @@ import (
 	"net/url"
 	"strings"
 
-	"github.com/linki/instrumented_http"
 	log "github.com/sirupsen/logrus"
 	"golang.org/x/net/html"
 
+	extdnshttp "sigs.k8s.io/external-dns/pkg/http"
+
 	"sigs.k8s.io/external-dns/endpoint"
 	"sigs.k8s.io/external-dns/provider"
 )
@@ -71,7 +72,8 @@ func newPiholeClient(cfg PiholeConfig) (piholeAPI, error) {
 			},
 		},
 	}
-	cl := instrumented_http.NewClient(httpClient, &instrumented_http.Callbacks{})
+
+	cl := extdnshttp.NewInstrumentedClient(httpClient)
 
 	p := &piholeClient{
 		cfg:        cfg,
diff --git a/provider/pihole/clientV6.go b/provider/pihole/clientV6.go
index 0d220b03..3168b497 100644
--- a/provider/pihole/clientV6.go
+++ b/provider/pihole/clientV6.go
@@ -30,9 +30,10 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/linki/instrumented_http"
 	log "github.com/sirupsen/logrus"
 
+	extdnshttp "sigs.k8s.io/external-dns/pkg/http"
+
 	"sigs.k8s.io/external-dns/endpoint"
 	"sigs.k8s.io/external-dns/provider"
 )
@@ -65,7 +66,7 @@ func newPiholeClientV6(cfg PiholeConfig) (piholeAPI, error) {
 		},
 	}
 
-	cl := instrumented_http.NewClient(httpClient, &instrumented_http.Callbacks{})
+	cl := extdnshttp.NewInstrumentedClient(httpClient)
 
 	p := &piholeClientV6{
 		cfg:        cfg,
@@ -164,17 +165,17 @@ func (p *piholeClientV6) listRecords(ctx context.Context, rtype string) ([]*endp
 		DNSName, Target = recs[1], recs[0]
 		switch rtype {
 		case endpoint.RecordTypeA:
-			//PiHole return A and AAAA records. Filter to only keep the A records
+			// PiHole return A and AAAA records. Filter to only keep the A records
 			if !isValidIPv4(Target) {
 				continue
 			}
 		case endpoint.RecordTypeAAAA:
-			//PiHole return A and AAAA records. Filter to only keep the AAAA records
+			// PiHole return A and AAAA records. Filter to only keep the AAAA records
 			if !isValidIPv6(Target) {
 				continue
 			}
 		case endpoint.RecordTypeCNAME:
-			//PiHole return only CNAME records.
+			// PiHole return only CNAME records.
 			// CNAME format is DNSName,target, ttl?
 			DNSName, Target = recs[0], recs[1]
 			if len(recs) == 3 { // TTL is present
diff --git a/source/node.go b/source/node.go
index 53a438d4..28c879f9 100644
--- a/source/node.go
+++ b/source/node.go
@@ -27,7 +27,6 @@ import (
 	kubeinformers "k8s.io/client-go/informers"
 	coreinformers "k8s.io/client-go/informers/core/v1"
 	"k8s.io/client-go/kubernetes"
-	"k8s.io/client-go/tools/cache"
 
 	"sigs.k8s.io/external-dns/endpoint"
 	"sigs.k8s.io/external-dns/source/annotations"
@@ -69,13 +68,7 @@ func NewNodeSource(
 	nodeInformer := informerFactory.Core().V1().Nodes()
 
 	// Add default resource event handler to properly initialize informer.
-	nodeInformer.Informer().AddEventHandler(
-		cache.ResourceEventHandlerFuncs{
-			AddFunc: func(obj interface{}) {
-				log.Debug("node added")
-			},
-		},
-	)
+	_, _ = nodeInformer.Informer().AddEventHandler(informers.DefaultEventHandler())
 
 	informerFactory.Start(ctx.Done())
 
@@ -172,7 +165,8 @@ func (ns *nodeSource) Endpoints(_ context.Context) ([]*endpoint.Endpoint, error)
 	return endpointsSlice, nil
 }
 
-func (ns *nodeSource) AddEventHandler(_ context.Context, _ func()) {
+func (ns *nodeSource) AddEventHandler(_ context.Context, handler func()) {
+	_, _ = ns.nodeInformer.Informer().AddEventHandler(eventHandlerFunc(handler))
 }
 
 // nodeAddress returns the node's externalIP and if that's not found, the node's internalIP
diff --git a/source/pod.go b/source/pod.go
index 25597fde..baa0e58e 100644
--- a/source/pod.go
+++ b/source/pod.go
@@ -29,7 +29,6 @@ import (
 	kubeinformers "k8s.io/client-go/informers"
 	coreinformers "k8s.io/client-go/informers/core/v1"
 	"k8s.io/client-go/kubernetes"
-	"k8s.io/client-go/tools/cache"
 
 	"sigs.k8s.io/external-dns/endpoint"
 	"sigs.k8s.io/external-dns/source/annotations"
@@ -76,18 +75,8 @@ func NewPodSource(
 		return nil, fmt.Errorf("failed to add indexers to pod informer: %w", err)
 	}
 
-	_, _ = podInformer.Informer().AddEventHandler(
-		cache.ResourceEventHandlerFuncs{
-			AddFunc: func(obj interface{}) {
-			},
-		},
-	)
-	_, _ = nodeInformer.Informer().AddEventHandler(
-		cache.ResourceEventHandlerFuncs{
-			AddFunc: func(obj interface{}) {
-			},
-		},
-	)
+	_, _ = podInformer.Informer().AddEventHandler(informers.DefaultEventHandler())
+	_, _ = nodeInformer.Informer().AddEventHandler(informers.DefaultEventHandler())
 
 	informerFactory.Start(ctx.Done())
 
@@ -114,7 +103,8 @@ func NewPodSource(
 	}, nil
 }
 
-func (*podSource) AddEventHandler(_ context.Context, _ func()) {
+func (ps *podSource) AddEventHandler(_ context.Context, handler func()) {
+	_, _ = ps.podInformer.Informer().AddEventHandler(eventHandlerFunc(handler))
 }
 
 func (ps *podSource) Endpoints(_ context.Context) ([]*endpoint.Endpoint, error) {
diff --git a/source/store.go b/source/store.go
index 8d69a31b..c77e89c3 100644
--- a/source/store.go
+++ b/source/store.go
@@ -22,12 +22,11 @@ import (
 	"fmt"
 	"net/http"
 	"os"
-	"strings"
+
 	"sync"
 	"time"
 
 	"github.com/cloudfoundry-community/go-cfclient"
-	"github.com/linki/instrumented_http"
 	openshift "github.com/openshift/client-go/route/clientset/versioned"
 	log "github.com/sirupsen/logrus"
 	istioclient "istio.io/client-go/pkg/clientset/versioned"
@@ -38,6 +37,8 @@ import (
 	"k8s.io/client-go/tools/clientcmd"
 	gateway "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned"
 
+	extdnshttp "sigs.k8s.io/external-dns/pkg/http"
+
 	"sigs.k8s.io/external-dns/pkg/apis/externaldns"
 )
 
@@ -623,14 +624,11 @@ func instrumentedRESTConfig(kubeConfig, apiServerURL string, requestTimeout time
 	if err != nil {
 		return nil, err
 	}
+
 	config.WrapTransport = func(rt http.RoundTripper) http.RoundTripper {
-		return instrumented_http.NewTransport(rt, &instrumented_http.Callbacks{
-			PathProcessor: func(path string) string {
-				parts := strings.Split(path, "/")
-				return parts[len(parts)-1]
-			},
-		})
+		return extdnshttp.NewInstrumentedTransport(rt)
 	}
+
 	config.Timeout = requestTimeout
 	return config, nil
 }



Test patch:
diff --git a/pkg/http/http_test.go b/pkg/http/http_test.go
new file mode 100644
index 00000000..cd17f387
--- /dev/null
+++ b/pkg/http/http_test.go
@@ -0,0 +1,81 @@
+/*
+Copyright 2025 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package http
+
+import (
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+type dummyTransport struct{}
+
+func (d *dummyTransport) RoundTrip(req *http.Request) (*http.Response, error) {
+	return nil, fmt.Errorf("dummy error")
+}
+
+func TestNewInstrumentedTransport(t *testing.T) {
+	dt := &dummyTransport{}
+	rt := NewInstrumentedTransport(dt)
+	crt, ok := rt.(*CustomRoundTripper)
+	require.True(t, ok)
+	require.Equal(t, dt, crt.next)
+
+	// Should default to http.DefaultTransport if nil
+	rt2 := NewInstrumentedTransport(nil)
+	crt2, ok := rt2.(*CustomRoundTripper)
+	require.True(t, ok)
+	require.Equal(t, http.DefaultTransport, crt2.next)
+}
+
+func TestNewInstrumentedClient(t *testing.T) {
+	client := &http.Client{Transport: &dummyTransport{}}
+	result := NewInstrumentedClient(client)
+	require.Equal(t, client, result)
+	_, ok := result.Transport.(*CustomRoundTripper)
+	require.True(t, ok)
+
+	// Should default to http.DefaultClient if nil
+	result2 := NewInstrumentedClient(nil)
+	require.Equal(t, http.DefaultClient, result2)
+	_, ok = result2.Transport.(*CustomRoundTripper)
+	require.True(t, ok)
+}
+
+func TestPathProcessor(t *testing.T) {
+	tests := []struct {
+		input    string
+		expected string
+	}{
+		{"/foo/bar", "bar"},
+		{"/foo/", ""},
+		{"/", ""},
+		{"", ""},
+		{"/foo/bar/baz", "baz"},
+		{"foo/bar", "bar"},
+		{"foo", "foo"},
+		{"foo/", ""},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.input, func(t *testing.T) {
+			require.Equal(t, tt.expected, pathProcessor(tt.input))
+		})
+	}
+}
diff --git a/source/node_test.go b/source/node_test.go
index 160d5994..b362cdfd 100644
--- a/source/node_test.go
+++ b/source/node_test.go
@@ -26,7 +26,10 @@ import (
 
 	log "github.com/sirupsen/logrus"
 	"github.com/sirupsen/logrus/hooks/test"
+	"github.com/stretchr/testify/mock"
 	"k8s.io/client-go/kubernetes"
+	corev1lister "k8s.io/client-go/listers/core/v1"
+	"k8s.io/client-go/tools/cache"
 
 	"sigs.k8s.io/external-dns/internal/testutils"
 
@@ -619,6 +622,39 @@ func TestResourceLabelIsSetForEachNodeEndpoint(t *testing.T) {
 	}
 }
 
+func TestNodeSource_AddEventHandler(t *testing.T) {
+	fakeInformer := new(fakeNodeInformer)
+	inf := testInformer{}
+	fakeInformer.On("Informer").Return(&inf)
+
+	nSource := &nodeSource{
+		nodeInformer: fakeInformer,
+	}
+
+	handlerCalled := false
+	handler := func() { handlerCalled = true }
+
+	nSource.AddEventHandler(t.Context(), handler)
+
+	fakeInformer.AssertNumberOfCalls(t, "Informer", 1)
+	assert.False(t, handlerCalled)
+	assert.Equal(t, 1, inf.times)
+}
+
+type fakeNodeInformer struct {
+	mock.Mock
+	informer cache.SharedIndexInformer
+}
+
+func (f *fakeNodeInformer) Informer() cache.SharedIndexInformer {
+	args := f.Called()
+	return args.Get(0).(cache.SharedIndexInformer)
+}
+
+func (f *fakeNodeInformer) Lister() corev1lister.NodeLister {
+	return corev1lister.NewNodeLister(f.Informer().GetIndexer())
+}
+
 type nodeListBuilder struct {
 	nodes []v1.Node
 }
diff --git a/source/pod_test.go b/source/pod_test.go
index f2d67da5..e6e0f8b0 100644
--- a/source/pod_test.go
+++ b/source/pod_test.go
@@ -23,9 +23,13 @@ import (
 	"testing"
 
 	log "github.com/sirupsen/logrus"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/mock"
 	"github.com/stretchr/testify/require"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	corev1lister "k8s.io/client-go/listers/core/v1"
+	"k8s.io/client-go/tools/cache"
 
 	"sigs.k8s.io/external-dns/endpoint"
 	"sigs.k8s.io/external-dns/internal/testutils"
@@ -909,6 +913,39 @@ func TestPodSourceLogs(t *testing.T) {
 	}
 }
 
+func TestPodSource_AddEventHandler(t *testing.T) {
+	fakeInformer := new(fakePodInformer)
+	inf := testInformer{}
+	fakeInformer.On("Informer").Return(&inf)
+
+	pSource := &podSource{
+		podInformer: fakeInformer,
+	}
+
+	handlerCalled := false
+	handler := func() { handlerCalled = true }
+
+	pSource.AddEventHandler(t.Context(), handler)
+
+	fakeInformer.AssertNumberOfCalls(t, "Informer", 1)
+	assert.False(t, handlerCalled)
+	assert.Equal(t, 1, inf.times)
+}
+
+type fakePodInformer struct {
+	mock.Mock
+	informer cache.SharedIndexInformer
+}
+
+func (f *fakePodInformer) Informer() cache.SharedIndexInformer {
+	args := f.Called()
+	return args.Get(0).(cache.SharedIndexInformer)
+}
+
+func (f *fakePodInformer) Lister() corev1lister.PodLister {
+	return corev1lister.NewPodLister(f.Informer().GetIndexer())
+}
+
 func nodesFixturesIPv6() []*corev1.Node {
 	return []*corev1.Node{
 		{