diff --git a/go.mod b/go.mod index a4275a0..3572163 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.26.0 require ( github.com/alecthomas/kingpin/v2 v2.4.0 github.com/prometheus/client_golang v1.24.1 - github.com/prometheus/prometheus v0.314.0 + github.com/prometheus/prometheus v0.315.0 github.com/sirupsen/logrus v1.10.2 golang.org/x/crypto v0.56.0 ) @@ -21,7 +21,6 @@ require ( github.com/prometheus/common v0.71.0 // indirect github.com/prometheus/procfs v0.22.0 // indirect github.com/xhit/go-str2duration/v2 v2.1.0 // indirect - go.yaml.in/yaml/v2 v2.4.4 // indirect golang.org/x/sys v0.47.0 // indirect golang.org/x/text v0.41.0 // indirect google.golang.org/protobuf v1.36.12 // indirect diff --git a/go.sum b/go.sum index d5f755d..67bb1a3 100644 --- a/go.sum +++ b/go.sum @@ -1,80 +1,49 @@ -cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA= -cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q= +cloud.google.com/go/auth v0.23.2 h1:pxSCpfiji41hpzpPdMCftEUCezpgpqmmDdYiAjCKXxo= +cloud.google.com/go/auth v0.23.2/go.mod h1:4DhBRcqvtljQN3dJ57qtqbib5ZGCYE5f2crfiiC2EM0= cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.1 h1:jHb/wfvRikGdxMXYV3QG/SzUOPYN9KEUUuC0Yd0/vC0= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.1/go.mod h1:pzBXCYn05zvYIrwLgtK8Ap8QcjRg+0i76tMQdWN6wOk= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.22.0 h1:aokoqcHvaGjiM3VpjKDfMMnF/8epJ+Q1HLJ7CudztqE= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 h1:Hk5QBxZQC1jb2Fwj6mpzme37xbCDdNTxU7O9eb5+LB4= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1/go.mod h1:IYus9qsFobWIc2YVwe/WPjcnyCkPKtnHAqUYeebc8z0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.14.0 h1:CU4+EJeJi3TKYWEcYuSdWsjzw0nVsK/H0MSQOiPcymU= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.23.1 h1:zvXfGJCWvywnCA814d8ZiVyt+fm9nnTE8xSb99zRyfo= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.23.1/go.mod h1:iptorS+VYKFL2N6PnebpS91dubG35eAOEERnT4PJbQU= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.14.1 h1:u93s+zU2JD62im61Bm5CZIc1ZrOJaIAWEg0WOrMVkEo= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.14.1/go.mod h1:oXtinPO4OLj9d1DOTrqrL1oRwGhcqadvAmrl6wTeGlk= github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0 h1:fhqpLE3UEXi9lPaBRpQ6XuRW0nU7hgg4zlmZZa+a9q4= github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0/go.mod h1:7dCRMLwisfRH3dBupKeNCioWYUZ4SS09Z14H+7i8ZoY= -github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs= -github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= -github.com/AzureAD/microsoft-authentication-library-for-go v1.7.2 h1:RHK7bS+HQMslb1sZpAokUt+zTVmue0hKSs2C791hhzU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.8.0 h1:Nljr4q1GRA/5vCrMONS+g4u4LRHNgOXVSh3O43J2CnI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.8.0/go.mod h1:Y33QHnf0FfdVewFFISOGe20mkZbxX4H839o955/PoeI= github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0= github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= -github.com/aws/aws-sdk-go-v2 v1.41.7 h1:DWpAJt66FmnnaRIOT/8ASTucrvuDPZASqhhLey6tLY8= -github.com/aws/aws-sdk-go-v2 v1.41.7/go.mod h1:4LAfZOPHNVNQEckOACQx60Y8pSRjIkNZQz1w92xpMJc= -github.com/aws/aws-sdk-go-v2 v1.42.0 h1:XvXMJTkFQtpBKIWZnmr9ZEOc2InWM2yldjXEJ/bymhA= -github.com/aws/aws-sdk-go-v2 v1.43.0 h1:fharf/WhbRAVZ1du0QL7roNFxZ6T/sWr+4Ni617bwSI= -github.com/aws/aws-sdk-go-v2/config v1.32.18 h1:Hcia46bxhGgF3BaSnG8nSNCWmqTK6bj9xN9/FJ3WK6Q= -github.com/aws/aws-sdk-go-v2/config v1.32.18/go.mod h1:zEjCAYmxqDadH1WX8CdBvmLKhUEUVFgKRQG38zjDmrY= -github.com/aws/aws-sdk-go-v2/config v1.32.25 h1:ACCejvStYoilgwrfegSt5ZntCbPrk52qfwyNcnl3omM= -github.com/aws/aws-sdk-go-v2/config v1.32.31 h1:n4nY9O3QKoHIkL85EX+V8RcMFtOhlpTFhGArg915PXk= -github.com/aws/aws-sdk-go-v2/credentials v1.19.17 h1:gP2nkGsS+KMvF/jfFz2Vv2qiiOqWKyPACSzPsqHgoW8= -github.com/aws/aws-sdk-go-v2/credentials v1.19.17/go.mod h1:Bsew3S/moG5iT77giPj1q8wb/s0RE5/QfH+ASjYtuQc= -github.com/aws/aws-sdk-go-v2/credentials v1.19.24 h1:2hQqYCV9yqyePQ9o6dCrZc/zO8U3TwPr9mIKlZnPu/I= -github.com/aws/aws-sdk-go-v2/credentials v1.19.30 h1:TTCvvzFU6gXa4iJecNG/0F/B0oYTiazoRECr2XyLHrY= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23 h1:UuSfcORqNSz/ey3VPRS8TcVH2Ikf0/sC+Hdj400QI6U= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23/go.mod h1:+G/OSGiOFnSOkYloKj/9M35s74LgVAdJBSD5lsFfqKg= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.29 h1:r6qZHbT+wxgWO/e9vYNUEtg7lv5+UN3pRqKhLXvnArg= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.31 h1:kfVL5wAunCJycL6MOQ6aNh6PlAYEymflcjuKmrWUA0o= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 h1:GpT/TrnBYuE5gan2cZbTtvP+JlHsutdmlV2YfEyNde0= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23/go.mod h1:xYWD6BS9ywC5bS3sz9Xh04whO/hzK2plt2Zkyrp4JuA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29 h1:f3vKqSo13fhTYb+JEcXwXefZQE26I1FB5eTSniU67ko= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.31 h1:Z8F3hfCY33IGpJjFAnv0wvtv1FIKj1GHmRDEYqy64tw= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 h1:bpd8vxhlQi2r1hiueOw02f/duEPTMK59Q4QMAoTTtTo= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23/go.mod h1:15DfR2nw+CRHIk0tqNyifu3G1YdAOy68RftkhMDDwYk= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29 h1:RdwIf/CuUsvJX3RgJagbOyotl/cxoLY4xviKuE7p2GY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.31 h1:hyOxUyXdh3AyjE93gBgsfziJag9ACwcs+ZpDBLzi8mw= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 h1:OQqn11BtaYv1WLUowvcA30MpzIu8Ti4pcLPIIyoKZrA= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24/go.mod h1:X5ZJyfwVrWA96GzPmUCWFQaEARPR7gCrpq2E92PJwAE= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.30 h1:VTGy885W5DKBxWRUJbym9hytNaYzsyaPkCHGRRMAOhU= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.32 h1:0MrUL35H/Y4kdFfItoR5jCgtDQ4Z/8LudAoIHRfA4hE= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 h1:FLudkZLt5ci0ozzgkVo8BJGwvqNaZbTWb3UcucAateA= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9/go.mod h1:w7wZ/s9qK7c8g4al+UyoF1Sp/Z45UwMGcqIzLWVQHWk= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.12 h1:ZD2+BSw9vFsNlKYIasSNt3uDbjqqXIBcM13UJv/Lx2k= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.13 h1:mbRIur/BiHK6SKPjoBIXSE/hJ6g6JGRLuxQy1jGjlN4= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23 h1:pbrxO/kuIwgEsOPLkaHu0O+m4fNgLU8B3vxQ+72jTPw= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23/go.mod h1:/CMNUqoj46HpS3MNRDEDIwcgEnrtZlKRaHNaHxIFpNA= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.29 h1:DRebniUGZ2MqiiIVmQJ04vIXr918hubdHMnarSLEWyU= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.31 h1:w2SIhW92DZPFrSL4ksVCr8IYff5OZwIcxg8+95tzvAI= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.11 h1:TdJ+HdzOBhU8+iVAOGUTU63VXopcumCOF1paFulHWZc= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.11/go.mod h1:R82ZRExE/nheo0N+T8zHPcLRTcH8MGsnR3BiVGX0TwI= -github.com/aws/aws-sdk-go-v2/service/signin v1.2.0 h1:3nXpRcFwRCW8n7HgO2QGy0Dc20eQNfBuUemGQhpF8m8= -github.com/aws/aws-sdk-go-v2/service/signin v1.5.0 h1:OHH5iTQvVGmfHjX/5Q+vFuA/Rf2x6/95aJ/75QCQSm4= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.17 h1:7byT8HUWrgoRp6sXjxtZwgOKfhss5fW6SkLBtqzgRoE= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.17/go.mod h1:xNWknVi4Ezm1vg1QsB/5EWpAJURq22uqd38U8qKvOJc= -github.com/aws/aws-sdk-go-v2/service/sso v1.31.3 h1:ey1XLTYXb9PcLt4535632o5kCGXNXEhNb620Dqwuylo= -github.com/aws/aws-sdk-go-v2/service/sso v1.33.0 h1:CaJyYhxBE0M/HJX/YvSaSmQlsI91VHB0lKU8LtLxL3A= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.0 h1:nDARhv/oF55bcxF7rCI/4PDxOKnVXVWwDuDwCs2I2SQ= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.0/go.mod h1:4vIRDq+CJB2xFAXZ+YgGUTiEft7oAQlhIs71xcSeuVg= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.6 h1:yLr03zQE/5Eu5l3QU0Si+xMbLMbSDF2YXsigqXngs6g= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.0 h1:tC323YV77QdafeBr6LUhLDTsboyuyHLNRwAyCP44kGU= -github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 h1:F/M5Y9I3nwr2IEpshZgh1GeHpOItExNM9L1euNuh/fk= -github.com/aws/aws-sdk-go-v2/service/sts v1.42.1/go.mod h1:mTNxImtovCOEEuD65mKW7DCsL+2gjEH+RPEAexAzAio= -github.com/aws/aws-sdk-go-v2/service/sts v1.43.3 h1:VrIhKRCSK1umelSgB9RghvA9RTUYeQffyAS5ApXehNI= -github.com/aws/aws-sdk-go-v2/service/sts v1.45.0 h1:Pd6PNlp4t8PTXxqzstICl52Wsy78vpjFZ7PRUj44mJc= -github.com/aws/smithy-go v1.26.0 h1:9ouqbi+NyKP7fV3Te7UElCwdAb6Y8uk7LGwPE5tVe/s= -github.com/aws/smithy-go v1.26.0/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= -github.com/aws/smithy-go v1.27.2 h1:y9NPmSE6am6LjEFPfqHqG/jJk7AauQvhCJONKh7kpzk= -github.com/aws/smithy-go v1.27.4 h1:JQcphmBN4f0q/sPqXqROIItRNV/hy10cgu7CsFy616M= +github.com/aws/aws-sdk-go-v2 v1.46.0 h1:1kt7m/EKcEHt5mlyyxx9cSlMddRPIKbjb6DIQsu4HPk= +github.com/aws/aws-sdk-go-v2 v1.46.0/go.mod h1:bttEH6JqnUL8LepvDVfdrds/fZ5bCIxzpe3abyUrhDU= +github.com/aws/aws-sdk-go-v2/config v1.33.3 h1:h090b3O5S17bF87/0ysHZuIT/7DCb4EBRFQX2PMVPCw= +github.com/aws/aws-sdk-go-v2/config v1.33.3/go.mod h1:YYDB1kTejxbfAbEVUqgCtkVp26xvNCHev9cLKABMGAk= +github.com/aws/aws-sdk-go-v2/credentials v1.20.3 h1:tToOYM/LXev4NpfWlIYGDvBvjHmJ3HXpRU9ppl+pM6k= +github.com/aws/aws-sdk-go-v2/credentials v1.20.3/go.mod h1:wfGneWyncO7p67wqXV2IQhPk14JqIc25woKlaArT3WI= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.19.2 h1:Ldv7RPHs7qwwTscRjAl3YBud32f3BvdAGRmSvAx5L38= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.19.2/go.mod h1:XyK6UV8xbo66ysVqLd2783C09pBYHOm8aKTRV5DVJ30= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.5.2 h1:q/PSLGuRWCChWg+dLnb9dWOnrCxJtnboXbBtFoqqRrI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.5.2/go.mod h1:TD1jvU2LvXkJexct5vBqcd8QlNXh5EmRUeL/Z32p0n4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.8.2 h1:6fl86IPqKEXoySqiOWdfgbEp9OVbn44zTfEICNEBDhY= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.8.2/go.mod h1:63HDfhFkdzBpI8WGXTSKUHPKS6mqldj4u3LJW7RZtSU= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.5.2 h1:XMgIRS+uW9F3yFKnXGRrI9pkHi99CXTmoz2kz2/TGBA= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.5.2/go.mod h1:vorxDzK+n3jiv9a5ST/LG0Eu9cSv1CRdKTpG6pDMs+M= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.19 h1:bAdDl/HkGCcGPoe25ToSHEw23VIxt6CT5fLcg111BKg= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.19/go.mod h1:KaUzbLxv4CeSxh6ZCl9B4m7CuFenS8kUEaDs+f/DQr4= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.14.2 h1:ZtHYnumr6QyxhzEzNZwzQTFJEXOswrZqTTkRxthwvr4= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.14.2/go.mod h1:a1NXrYpBd311gBzn1UI5UzJyyvXktM4xNh/ydPiPpqY= +github.com/aws/aws-sdk-go-v2/service/signin v1.9.0 h1:c3k+k/CS4L+sAIH6fxikL+g5g2LpeNczaoyjjw1iMKI= +github.com/aws/aws-sdk-go-v2/service/signin v1.9.0/go.mod h1:AGIoQg99fBrOIQnF78TLx4lj18mc4gZ0hJx1UaLIFM4= +github.com/aws/aws-sdk-go-v2/service/sso v1.37.0 h1:+rqBaOq7jzInjY8M12hr+zEe85JpRll9BjMx38r33Ok= +github.com/aws/aws-sdk-go-v2/service/sso v1.37.0/go.mod h1:XFlVwUsw3sYh8Hw37umYVJnrcWrwXWRxbNw/JY0bblw= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.42.0 h1:hzM3GslEAOBcLn3DHH6ENToFi+vXP+n02W+x6zejAIM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.42.0/go.mod h1:588e7skMkYIYkSUseT8E3WKFfbAfrA1bj3Zf+qxJtJY= +github.com/aws/aws-sdk-go-v2/service/sts v1.49.0 h1:N7Ey8obY3uSui+cxl0OUzFlFmkxSucoJnrniFhw+cLc= +github.com/aws/aws-sdk-go-v2/service/sts v1.49.0/go.mod h1:zMBwjSf4Pt8a1OHYiZ5rPD0PJRK1kQrUaxhS/Dbld8E= +github.com/aws/smithy-go v1.28.1 h1:R/nXH00c8qcfCzQVELtRw+eLQWtzv+VAIEFJ1/xxXlQ= +github.com/aws/smithy-go v1.28.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= 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/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= @@ -83,13 +52,10 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.1.0 h1:3YtUj32ZZkqZtt3sZZsClsymw/QDuVfpNhoA31zeORc= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/felixge/httpsnoop v1.1.0/go.mod h1:Zqxgdd+1Rkcz8euOqdr7lqgCRJztwr5hp9vDSi5UZCE= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/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/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -102,21 +68,18 @@ github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= 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/googleapis/enterprise-certificate-proxy v0.3.15 h1:xolVQTEXusUcAA5UgtyRLjelpFFHWlPQ4XfWGc7MBas= -github.com/googleapis/enterprise-certificate-proxy v0.3.15/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= -github.com/googleapis/enterprise-certificate-proxy v0.3.18 h1:hvVi34VucdrV1IIsiWuqYM8kutw/92MxNEFxCJZEh0k= -github.com/googleapis/gax-go/v2 v2.22.0 h1:PjIWBpgGIVKGoCXuiCoP64altEJCj3/Ei+kSU5vlZD4= -github.com/googleapis/gax-go/v2 v2.22.0/go.mod h1:irWBbALSr0Sk3qlqb9SyJ1h68WjgeFuiOzI4Rqw5+aY= -github.com/googleapis/gax-go/v2 v2.23.0 h1:Tchl7qkvE7Ip3y+ztvNufYFvkfqTe7NfLTYGIdJRLuE= +github.com/googleapis/enterprise-certificate-proxy v0.3.20 h1:t/xL64VUoN69MuMRQuJETqYGOw4Z9mSRJK9epIEtwFk= +github.com/googleapis/enterprise-certificate-proxy v0.3.20/go.mod h1:L3D/IQExI6LqEjBdXcZQ1WluSgigQmSwBboFstVPM4w= +github.com/googleapis/gax-go/v2 v2.24.0 h1:myMaPYyF9MecEmvQqMqomIwn9t/4KCZN9qnwsS76wlg= +github.com/googleapis/gax-go/v2 v2.24.0/go.mod h1:IaTHBDd7NHxSCiu0vEs8pQZu4dGZrWwuSoxCnk16OFM= github.com/grafana/regexp v0.0.0-20250905093917-f7b3be9d1853 h1:cLN4IBkmkYZNnk7EAJ0BHIethd+J6LqxFNw5mSiI2bM= github.com/grafana/regexp v0.0.0-20250905093917-f7b3be9d1853/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= 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.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao= -github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= -github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= +github.com/klauspost/compress v1.20.0 h1:a3C1ke2ohxFymNlb2HWAHjDeKCI90scRskErZkR0ezA= +github.com/klauspost/compress v1.20.0/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= 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/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= @@ -126,44 +89,22 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -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_golang v1.24.1 h1:JnJkREXzWxUdCuPFpIWZiPispT9xVV59uiuyR2bPlnU= github.com/prometheus/client_golang v1.24.1/go.mod h1:F+oSRECHg4sse5ucfYpYDeIv/hu68Zo0uoHKetWnzcE= -github.com/prometheus/client_golang/exp v0.0.0-20260518105423-c9d5bc4c50a9 h1:e33IfrrwrJkylWwAGcQ2jMvbWVv13lv0suTXjGNeiqY= -github.com/prometheus/client_golang/exp v0.0.0-20260518105423-c9d5bc4c50a9/go.mod h1:vW/EVguzbNw6xMRmozJQWbY60/+Zsg0TgVJOSXGx2iI= -github.com/prometheus/client_golang/exp v0.0.0-20260602051030-3537b20ac86b h1:633sracZPrB7O7T6r5skFtwqXDOrXlQkE9Wr5DnYVJE= -github.com/prometheus/client_golang/exp v0.0.0-20260724065723-ecdb8254ba61 h1:SgKx/5u9SwqzZ27E1T4bfuisjTOkI3GagC6WtdEE5lg= -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/client_golang/exp v0.0.0-20260907100614-57bb367da472 h1:4qeIiKMiaj1CH85S6mShB3nHtz1Ti1zg8lg3IQLsAhk= +github.com/prometheus/client_golang/exp v0.0.0-20260907100614-57bb367da472/go.mod h1:7cN4zh+WBVVoFdl124VnR0F9bcpJluTebOnYYSHgyq8= github.com/prometheus/client_model v0.6.3 h1:O0jaTVAYNxTHYInEPFJt5I3+sN8zqBtVMPTB1qyxiEo= github.com/prometheus/client_model v0.6.3/go.mod h1:gpN5P9S7Rr6Yr92PiQ+Ixvhf6JZEkF1dnxsYL2aPBEM= -github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= -github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= -github.com/prometheus/common v0.70.0 h1:bcpru3tWPVnxGnETLgOV5jbp/JRXgYEyv65CuBLAMMI= -github.com/prometheus/common v0.70.0/go.mod h1:S/SFasQmgGiYH6C81LKCtYa8QACgthGg5zxL2udV7SY= github.com/prometheus/common v0.71.0 h1:9KDAKb7Mj3HEVKyFCK6Dc/HIwlBzZIN2l7/lrHl3KK8= github.com/prometheus/common v0.71.0/go.mod h1:CLJ5H8TEsGX8bl31BdMkfhIZ+QmZ9tBPPotUxUbfcmk= github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos= github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM= -github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= -github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= -github.com/prometheus/procfs v0.21.1 h1:GljZCt+zSTS+NZq88cyQ1LjZ+RCHp3uVuabBWA5+OJI= -github.com/prometheus/procfs v0.21.1/go.mod h1:aB55Cww9pdSJVHk0hUf0inxWyyjPogFIjmHKYgMKmtY= github.com/prometheus/procfs v0.22.0 h1:6q9+/JL9IKAPbCmBrv9n5O5Ty3NKnciV5X7YGw0oics= github.com/prometheus/procfs v0.22.0/go.mod h1:CvmFr/GVhIjIvWJZW3tgkODBQMRIf0EyWMQLHCHab58= -github.com/prometheus/prometheus v0.312.0 h1:f9jdv2fQhQ1fks9a9YwlGZrKr4hih0rRP/rh0mu3Q18= -github.com/prometheus/prometheus v0.312.0/go.mod h1:8oAYd2XPgHXLP4fFKam594R/ZLlPicrrBkVdaWt74Sw= -github.com/prometheus/prometheus v0.313.1 h1:BOyoPuxCL+58NpuZ0ovKuKo8ALmVLTCTIM7r8znt6z8= -github.com/prometheus/prometheus v0.313.1/go.mod h1:Kq9A+EPun2WyVusbQxO7Tx1RxKqLKFclfiBGJA1mFkk= -github.com/prometheus/prometheus v0.314.0 h1:YjsimqsIi6/mOtzZcrPEYUALO6zpfaht9O5sXqDz2vg= -github.com/prometheus/prometheus v0.314.0/go.mod h1:zjg3pMTAkY0/JG8jy/h8/YgSQUVB+aCXMhUqN6l64jg= -github.com/prometheus/sigv4 v0.4.1 h1:EIc3j+8NBea9u1iV6O5ZAN8uvPq2xOIUPcqCTivHuXs= -github.com/prometheus/sigv4 v0.4.1/go.mod h1:eu+ZbRvsc5TPiHwqh77OWuCnWK73IdkETYY46P4dXOU= -github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= -github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= +github.com/prometheus/prometheus v0.315.0 h1:sFGZWmC2Hk9N1NBJGCnXYZb5hyLCq8yuAMoEjLAg6ac= +github.com/prometheus/prometheus v0.315.0/go.mod h1:B+80h4JO0zXpoFCiWStHtpsAWrEOwY24B9/CLgzUIuc= +github.com/prometheus/sigv4 v0.5.0 h1:WWZDeiCPFTBJIniIa+pv3edYtPHtZxDAa5w5Tmp+UuQ= +github.com/prometheus/sigv4 v0.5.0/go.mod h1:oLsQ72mP5bVxsIrFgv/gT2jY1devyRLZhAvrsWG4SEk= github.com/sirupsen/logrus v1.10.2 h1:G2SED73/qrAu6YwbdxOD6peLkCBI3z7L+ykJFTXJBBo= github.com/sirupsen/logrus v1.10.2/go.mod h1:SLEg8TqYulVKKfIGHldVp2K2aYz2DKSVBq4g/H5bR7Q= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -174,36 +115,33 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.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/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= +github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg= github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 h1:8tvICD4vSTOOsNrsI4Ljf6C+6UKvpTEH5XY3JMoyPoo= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0/go.mod h1:z9+yiacE0IHRqM4qFfkbt/JYlmYXgss8GY/jXoNuPJI= -go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= -go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= -go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= -go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= -go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= -go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 h1:3g7B90UzBltIDKq1/5mrTGxTnOFDV0ICOhLoxiZ8jlg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU= +go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc= +go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE= +go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8= +go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o= +go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c= +go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= 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.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988= -golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc= -golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw= -golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk= golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -212,31 +150,24 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn 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.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= -golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= -golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= +golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= 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.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= +golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= 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-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= -golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= -golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= +golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= 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.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= -golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= -golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= -golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= @@ -249,31 +180,23 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.278.0 h1:W7jiRvRi53VYFfZ/HoZjQBtJk7gOFbHD8ot1RzVZU6E= -google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ= -google.golang.org/api v0.290.0 h1:eMw0Xo+IfbbMlKmW7aHvpyQRv9RCXuWx/vs8AD+0x9A= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260610212136-7ab31c22f7ad h1:45WmJvIV6C2+O/jjLkPUH+F3aOj/1miDoU2DD0+NWbg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260720155508-bb71a54f79dc h1:3TtNq/QbJNrSY1nVdjcikfBw6ujnaNbdrd88wNr1OW4= -google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ= -google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= -google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE= -google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/api v0.297.0 h1:WktxTsnnx0yZNnsR6j0q6hR21RnnK81FHTOPy/ux4OE= +google.golang.org/api v0.297.0/go.mod h1:S4m8x0M6OkQpkOzGk1y9JG2sm4fFQrMh6dxzjCTszhE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA= +google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= +google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/apimachinery v0.35.3 h1:MeaUwQCV3tjKP4bcwWGgZ/cp/vpsRnQzqO6J6tJyoF8= -k8s.io/apimachinery v0.35.3/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= -k8s.io/client-go v0.35.3 h1:s1lZbpN4uI6IxeTM2cpdtrwHcSOBML1ODNTCCfsP1pg= -k8s.io/client-go v0.35.3/go.mod h1:RzoXkc0mzpWIDvBrRnD+VlfXP+lRzqQjCmKtiwZ8Q9c= +k8s.io/apimachinery v0.37.0 h1:Np2AbDtf8x6RDHiD8T9LbKJ9gaegeVNa8yNm5FuGKm0= +k8s.io/apimachinery v0.37.0/go.mod h1:RN3nhprFSCxOi5Selxd7oMTXOe/c+ZbcE7Im+TS2zkE= +k8s.io/client-go v0.37.0 h1:nsN31fy8wBySuZ+QRnKmrjRSQLOG2rvoGN0tKd12zhQ= +k8s.io/client-go v0.37.0/go.mod h1:FcGqw+Ll/gNQiq+nPGY1Oyt9y7SgDh1d3MW3RFDEbn0= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= -k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= -k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU= +k8s.io/utils v0.0.0-20260626114624-be93311217bd h1:Ea7fgQ5we8Y9T0OX5o0dAHzQOBRI07D/dEYRaB9ZZEs= +k8s.io/utils v0.0.0-20260626114624-be93311217bd/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= diff --git a/vendor/github.com/prometheus/prometheus/model/histogram/float_histogram.go b/vendor/github.com/prometheus/prometheus/model/histogram/float_histogram.go index f28eece..bb6e0e7 100644 --- a/vendor/github.com/prometheus/prometheus/model/histogram/float_histogram.go +++ b/vendor/github.com/prometheus/prometheus/model/histogram/float_histogram.go @@ -17,6 +17,7 @@ import ( "errors" "fmt" "math" + "slices" "strings" "github.com/prometheus/prometheus/util/kahansum" @@ -184,8 +185,8 @@ func (h *FloatHistogram) String() string { nBuckets = append(nBuckets, it.At()) } } - for i := len(nBuckets) - 1; i >= 0; i-- { - fmt.Fprintf(&sb, ", %s", nBuckets[i].String()) + for _, v := range slices.Backward(nBuckets) { + fmt.Fprintf(&sb, ", %s", v.String()) } if h.ZeroCount != 0 { @@ -380,7 +381,8 @@ func (h *FloatHistogram) Add(other *FloatHistogram) (res *FloatHistogram, counte false, hPositiveSpans, hPositiveBuckets, h.CustomValues, otherPositiveSpans, otherPositiveBuckets, other.CustomValues, - nil, intersectedBounds) + nil, intersectedBounds, + ) h.CustomValues = intersectedBounds } return h, counterResetCollision, nhcbBoundsReconciled, nil @@ -457,7 +459,8 @@ func (h *FloatHistogram) KahanAdd(other, c *FloatHistogram) (updatedC *FloatHist false, hPositiveSpans, hPositiveBuckets, h.CustomValues, otherPositiveSpans, otherPositiveBuckets, other.CustomValues, - cPositiveBuckets, intersectedBounds) + cPositiveBuckets, intersectedBounds, + ) h.CustomValues = intersectedBounds c.CustomValues = intersectedBounds } @@ -565,7 +568,8 @@ func (h *FloatHistogram) Sub(other *FloatHistogram) (res *FloatHistogram, counte true, hPositiveSpans, hPositiveBuckets, h.CustomValues, otherPositiveSpans, otherPositiveBuckets, other.CustomValues, - nil, intersectedBounds) + nil, intersectedBounds, + ) h.CustomValues = intersectedBounds } return h, counterResetCollision, nhcbBoundsReconciled, nil @@ -821,6 +825,7 @@ func detectReset(currIt, prevIt *floatBucketIterator) bool { if !prevIt.Next() { return false } + prevBucket = prevIt.strippedAt() } } currBucket := currIt.strippedAt() @@ -840,6 +845,7 @@ func detectReset(currIt, prevIt *floatBucketIterator) bool { if !prevIt.Next() { return false } + prevBucket = prevIt.strippedAt() } } currBucket = currIt.strippedAt() @@ -2133,135 +2139,36 @@ func (h *FloatHistogram) TrimBuckets(rhs float64, isUpperTrim bool) *FloatHistog hasPositive, hasNegative bool ) - if isUpperTrim { - // Calculate the fraction to keep for buckets that contain the trim value. - // For TRIM_UPPER, we keep observations below the trim point (rhs). - // Example: histogram / float. - for i, iter := 0, h.PositiveBucketIterator(); iter.Next(); i++ { - bucket := iter.At() - if bucket.Count == 0 { - continue - } - hasPositive = true - - switch { - case bucket.Lower >= rhs: - // Bucket is entirely below the trim point - keep all. - updatedCount += bucket.Count - bucketMidpoint := computeMidpoint(bucket.Lower, bucket.Upper, true, isCustomBucket) - updatedSum += bucketMidpoint * bucket.Count - - case bucket.Upper > rhs: - // Bucket contains the trim point - interpolate. - keepCount, bucketMidpoint := computeBucketTrim(bucket, rhs, isUpperTrim, true, isCustomBucket) - - updatedCount += keepCount - updatedSum += bucketMidpoint * keepCount - if h.PositiveBuckets[i] != keepCount { - h.PositiveBuckets[i] = keepCount - trimmedBuckets = true - } + } - default: - h.PositiveBuckets[i] = 0 - trimmedBuckets = true - } + for i, iter := 0, h.NegativeBucketIterator(); iter.Next(); i++ { + bucket := iter.At() + if bucket.Count == 0 { + continue } + hasNegative = true - for i, iter := 0, h.NegativeBucketIterator(); iter.Next(); i++ { - bucket := iter.At() - if bucket.Count == 0 { - continue - } - hasNegative = true - - switch { - case bucket.Lower >= rhs: - // Bucket is entirely below the trim point - keep all. - updatedCount += bucket.Count - bucketMidpoint := computeMidpoint(bucket.Lower, bucket.Upper, false, isCustomBucket) - updatedSum += bucketMidpoint * bucket.Count - - case bucket.Upper > rhs: - // Bucket contains the trim point - interpolate. - keepCount, bucketMidpoint := computeBucketTrim(bucket, rhs, isUpperTrim, false, isCustomBucket) - - updatedCount += keepCount - updatedSum += bucketMidpoint * keepCount - if h.NegativeBuckets[i] != keepCount { - h.NegativeBuckets[i] = keepCount - trimmedBuckets = true - } - - default: - h.NegativeBuckets[i] = 0 - trimmedBuckets = true - } + keepCount, bucketMidpoint := trimBucket(bucket, rhs, isUpperTrim, false, isCustomBucket) + updatedCount += keepCount + updatedSum += bucketMidpoint * keepCount + if h.NegativeBuckets[i] != keepCount { + h.NegativeBuckets[i] = keepCount + trimmedBuckets = true } } @@ -2288,6 +2195,33 @@ func (h *FloatHistogram) TrimBuckets(rhs float64, isUpperTrim bool) *FloatHistog return h } +// trimBucket returns the portion of b's count to keep against trim point rhs (isUpperTrim keeps values below rhs, else above) and the midpoint for the retained sum. +func trimBucket(b Bucket[float64], rhs float64, isUpperTrim, isPositive, isCustomBucket bool) (keepCount, bucketMidpoint float64) { + var keepAll, containsTrimPoint bool + + if isUpperTrim { + keepAll = b.Upper <= rhs + containsTrimPoint = b.Lower < rhs + } else { + keepAll = b.Lower >= rhs + containsTrimPoint = b.Upper > rhs + } + + switch { + case keepAll: + // Bucket is entirely on the kept side of the trim point - keep all. + return b.Count, computeMidpoint(b.Lower, b.Upper, isPositive, isCustomBucket) + + case containsTrimPoint: + // Bucket contains the trim point - interpolate. + return computeBucketTrim(b, rhs, isUpperTrim, isPositive, isCustomBucket) + + default: + // Bucket is entirely on the discarded side of the trim point. + return 0, 0 + } +} + func handleInfinityBuckets(isUpperTrim bool, b Bucket[float64], rhs float64) (underCount, bucketMidpoint float64) { zeroIfInf := func(x float64) float64 { if math.IsInf(x, 0) { diff --git a/vendor/github.com/prometheus/prometheus/model/histogram/generic.go b/vendor/github.com/prometheus/prometheus/model/histogram/generic.go index f6ba80a..82559b5 100644 --- a/vendor/github.com/prometheus/prometheus/model/histogram/generic.go +++ b/vendor/github.com/prometheus/prometheus/model/histogram/generic.go @@ -270,7 +270,8 @@ func compactBuckets[IBC InternalBucketCount]( } else if compensationBuckets != nil && len(primaryBuckets) != len(compensationBuckets) { panic(fmt.Errorf( "primary buckets layout (%v) mismatch against associated compensation buckets layout (%v)", - primaryBuckets, compensationBuckets), + primaryBuckets, compensationBuckets, + ), ) } // Fast path: If there are no empty buckets AND no offset in any span is @@ -476,6 +477,7 @@ func compactBuckets[IBC InternalBucketCount]( } // Merge span with previous one and insert empty buckets. offset := int(spans[iSpan].Offset) + l := int(spans[iSpan].Length) spans[iSpan-1].Length += uint32(offset) + spans[iSpan].Length spans = append(spans[:iSpan], spans[iSpan+1:]...) newPrimaryBuckets := make([]IBC, len(primaryBuckets)+offset) @@ -493,7 +495,18 @@ func compactBuckets[IBC InternalBucketCount]( compensationBuckets = newCompensationBuckets } iBucket += offset - currentBucketAbsolute = primaryBuckets[iBucket] + // The buckets of the merged span are now part of the previous span, so + // iBucket has to skip them as well to keep pointing at the first bucket + // of the span we look at next. The inserted empty buckets have reset the + // running absolute count to zero, so the deltas of the merged span add up + // to the absolute count of its last bucket. + if deltaBuckets { + currentBucketAbsolute = 0 + for _, bucket := range primaryBuckets[iBucket : iBucket+l] { + currentBucketAbsolute += bucket + } + } + iBucket += l // Note that with many merges, it would be more efficient to // first record all the chunks of empty buckets to insert and // then do it in one go through all the buckets. diff --git a/vendor/github.com/prometheus/prometheus/model/histogram/histogram.go b/vendor/github.com/prometheus/prometheus/model/histogram/histogram.go index 6ed02ae..6ffbb76 100644 --- a/vendor/github.com/prometheus/prometheus/model/histogram/histogram.go +++ b/vendor/github.com/prometheus/prometheus/model/histogram/histogram.go @@ -178,8 +178,8 @@ func (h *Histogram) String() string { nBuckets = append(nBuckets, it.At()) } } - for i := len(nBuckets) - 1; i >= 0; i-- { - fmt.Fprintf(&sb, ", %s", nBuckets[i].String()) + for _, v := range slices.Backward(nBuckets) { + fmt.Fprintf(&sb, ", %s", v.String()) } if h.ZeroCount != 0 { diff --git a/vendor/github.com/prometheus/prometheus/model/labels/labels_dedupelabels.go b/vendor/github.com/prometheus/prometheus/model/labels/labels_dedupelabels.go index 66ba899..91898b9 100644 --- a/vendor/github.com/prometheus/prometheus/model/labels/labels_dedupelabels.go +++ b/vendor/github.com/prometheus/prometheus/model/labels/labels_dedupelabels.go @@ -670,8 +670,8 @@ func (b *Builder) Labels() Labels { func marshalNumbersToSizedBuffer(nums []int, data []byte) int { i := len(data) - for index := len(nums) - 1; index >= 0; index-- { - i = encodeVarint(data, i, nums[index]) + for _, v := range slices.Backward(nums) { + i = encodeVarint(data, i, v) } return len(data) - i } diff --git a/vendor/github.com/prometheus/prometheus/model/labels/labels_stringlabels.go b/vendor/github.com/prometheus/prometheus/model/labels/labels_stringlabels.go index 4cb4f24..5944190 100644 --- a/vendor/github.com/prometheus/prometheus/model/labels/labels_stringlabels.go +++ b/vendor/github.com/prometheus/prometheus/model/labels/labels_stringlabels.go @@ -522,8 +522,8 @@ func (b *Builder) Labels() Labels { func marshalLabelsToSizedBuffer(lbls []Label, data []byte) int { i := len(data) - for index := len(lbls) - 1; index >= 0; index-- { - size := marshalLabelToSizedBuffer(&lbls[index], data[:i]) + for _, v := range slices.Backward(lbls) { + size := marshalLabelToSizedBuffer(&v, data[:i]) i -= size } return len(data) - i diff --git a/vendor/github.com/prometheus/prometheus/model/labels/regexp.go b/vendor/github.com/prometheus/prometheus/model/labels/regexp.go index 9b4b667..3276635 100644 --- a/vendor/github.com/prometheus/prometheus/model/labels/regexp.go +++ b/vendor/github.com/prometheus/prometheus/model/labels/regexp.go @@ -375,11 +375,7 @@ func optimizeAlternatingLiterals(s string) (StringMatcher, []string) { multiMatcher := newEqualMultiStringMatcher(true, estimatedAlternates, 0, 0) - for end := strings.IndexByte(s, '|'); end > -1; end = strings.IndexByte(s, '|') { - // Split the string into the next literal and the remainder - subMatch := s[:end] - s = s[end+1:] - + for subMatch := range strings.SplitSeq(s, "|") { // break if any of the submatches are not literals if regexp.QuoteMeta(subMatch) != subMatch { return nil, nil @@ -388,12 +384,6 @@ func optimizeAlternatingLiterals(s string) (StringMatcher, []string) { multiMatcher.add(subMatch) } - // break if the remainder is not a literal - if regexp.QuoteMeta(s) != s { - return nil, nil - } - multiMatcher.add(s) - return multiMatcher, multiMatcher.setMatches() } @@ -648,25 +638,25 @@ func stringMatcherFromRegexpInternal(re *syntax.Regexp) StringMatcher { } // isSimpleConcatenationPattern returns true if re contains only literals or wildcard matchers, -// and starts and ends with a wildcard matcher (eg. .*-.*-.*). +// and starts and ends with a wildcard matcher (eg. .*-.*-.*), with wildcards between every literal. func isSimpleConcatenationPattern(re *syntax.Regexp) bool { if re.Op != syntax.OpConcat { return false } - if len(re.Sub) < 2 { - return false - } - - first := re.Sub[0] - last := re.Sub[len(re.Sub)-1] - if !isMatchAny(first) || !isMatchAny(last) { + if len(re.Sub) < 3 || len(re.Sub)%2 == 0 { return false } - for _, re := range re.Sub[1 : len(re.Sub)-1] { - if !isMatchAny(re) && !isCaseSensitiveLiteral(re) { - return false + for i, sub := range re.Sub { + if i%2 == 0 { + if !isMatchAny(sub) { + return false + } + } else { + if !isCaseSensitiveLiteral(sub) { + return false + } } } diff --git a/vendor/github.com/prometheus/prometheus/model/textparse/interface.go b/vendor/github.com/prometheus/prometheus/model/textparse/interface.go index d2a3c94..ca77bf2 100644 --- a/vendor/github.com/prometheus/prometheus/model/textparse/interface.go +++ b/vendor/github.com/prometheus/prometheus/model/textparse/interface.go @@ -86,40 +86,57 @@ type Parser interface { Next() (Entry, error) } +// openMetrics2Version is the value of the Content-Type version parameter that +// selects the OpenMetrics 2.0 parser. +const openMetrics2Version = "2.0.0" + // extractMediaType returns the mediaType of a required parser. It tries first to // extract a valid and supported mediaType from contentType. If that fails, // the provided fallbackType (possibly an empty string) is returned, together with // an error. fallbackType is used as-is without further validation. -func extractMediaType(contentType, fallbackType string) (string, error) { +// A contentType OpenMetrics 2.0.0 without the appropriate feature flag set fails +// to fallback. +// TODO(r.bizos): remove this constraint when OM2 is GA in Prometheus. +func extractMediaType(contentType, fallbackType string, enableOpenMetrics2 bool) (mediaType, version string, err error) { if contentType == "" { if fallbackType == "" { - return "", errors.New("non-compliant scrape target sending blank Content-Type and no fallback_scrape_protocol specified for target") + return "", "", errors.New("non-compliant scrape target sending blank Content-Type and no fallback_scrape_protocol specified for target") } - return fallbackType, fmt.Errorf("non-compliant scrape target sending blank Content-Type, using fallback_scrape_protocol %q", fallbackType) + return fallbackType, "", fmt.Errorf("non-compliant scrape target sending blank Content-Type, using fallback_scrape_protocol %q", fallbackType) } // We have a contentType, parse it. - mediaType, _, err := mime.ParseMediaType(contentType) + mediaType, params, err := mime.ParseMediaType(contentType) if err != nil { if fallbackType == "" { retErr := fmt.Errorf("cannot parse Content-Type %q and no fallback_scrape_protocol for target", contentType) - return "", errors.Join(retErr, err) + return "", "", errors.Join(retErr, err) } retErr := fmt.Errorf("could not parse received Content-Type %q, using fallback_scrape_protocol %q", contentType, fallbackType) - return fallbackType, errors.Join(retErr, err) + return fallbackType, "", errors.Join(retErr, err) + } + version = params["version"] + + // OpenMetrics 2.0 is experimental, so it is only usable when explicitly + // enabled. + if mediaType == "application/openmetrics-text" && version == openMetrics2Version && !enableOpenMetrics2 { + if fallbackType == "" { + return "", "", fmt.Errorf("received OpenMetrics 2.0 Content-Type %q, but the openmetrics2 feature flag is not enabled and no fallback_scrape_protocol specified for target", contentType) + } + return fallbackType, "", fmt.Errorf("received OpenMetrics 2.0 Content-Type %q, but the openmetrics2 feature flag is not enabled, using fallback_scrape_protocol %q", contentType, fallbackType) } // We have a valid media type, either we recognise it and can use it // or we have to error. switch mediaType { case "application/openmetrics-text", "application/vnd.google.protobuf", "text/plain": - return mediaType, nil + return mediaType, version, nil } // We're here because we have no recognised mediaType. if fallbackType == "" { - return "", fmt.Errorf("received unsupported Content-Type %q and no fallback_scrape_protocol specified for target", contentType) + return "", "", fmt.Errorf("received unsupported Content-Type %q and no fallback_scrape_protocol specified for target", contentType) } - return fallbackType, fmt.Errorf("received unsupported Content-Type %q, using fallback_scrape_protocol %q", contentType, fallbackType) + return fallbackType, "", fmt.Errorf("received unsupported Content-Type %q, using fallback_scrape_protocol %q", contentType, fallbackType) } type ParserOptions struct { @@ -143,13 +160,20 @@ type ParserOptions struct { ConvertClassicHistogramsToNHCB bool // KeepClassicOnClassicAndNativeHistograms causes parser to output classic histogram - // that is also present as a native histogram. (Proto parsing only). + // that is also present as a native histogram. Supported by the protobuf + // parser and by the OpenMetrics 2.0 parser (where both representations + // can appear in a single composite value). KeepClassicOnClassicAndNativeHistograms bool // OpenMetricsSkipSTSeries determines whether to skip `_created` timestamp series // during (OpenMetrics parsing only). OpenMetricsSkipSTSeries bool + // EnableOpenMetrics2 enables the OpenMetrics 2.0 parser. When + // it is false, a Content-Type OpenMetrics 2.0 is treated as + // unsupported, so the fallback or failing if not set. + EnableOpenMetrics2 bool + // FallbackContentType specifies the fallback content type to use when the provided // Content-Type header cannot be parsed or is not supported. FallbackContentType string @@ -168,16 +192,20 @@ func New(b []byte, contentType string, st *labels.SymbolTable, opts ParserOption st = labels.NewSymbolTable() } - mediaType, err := extractMediaType(contentType, opts.FallbackContentType) + mediaType, version, err := extractMediaType(contentType, opts.FallbackContentType, opts.EnableOpenMetrics2) // err may be nil or something we want to warn about. var baseParser Parser switch mediaType { case "application/openmetrics-text": - baseParser = NewOpenMetricsParser(b, st, func(o *openMetricsParserOptions) { - o.skipSTSeries = opts.OpenMetricsSkipSTSeries - o.enableTypeAndUnitLabels = opts.EnableTypeAndUnitLabels - }) + if version == openMetrics2Version { + baseParser = NewOpenMetrics2Parser(b, st, opts) + } else { + baseParser = NewOpenMetricsParser(b, st, func(o *openMetricsParserOptions) { + o.skipSTSeries = opts.OpenMetricsSkipSTSeries + o.enableTypeAndUnitLabels = opts.EnableTypeAndUnitLabels + }) + } case "application/vnd.google.protobuf": return NewProtobufParser( b, @@ -194,7 +222,10 @@ func New(b []byte, contentType string, st *labels.SymbolTable, opts ParserOption } if baseParser != nil && opts.ConvertClassicHistogramsToNHCB { - baseParser = NewNHCBParser(baseParser, st, opts.KeepClassicOnClassicAndNativeHistograms) + // OpenMetricsSkipSTSeries is set to true when the scrape loop + // wants start timestamps. NHCBParser uses it to decide if + // StartTimestamp calls are necessary. + baseParser = NewNHCBParser(baseParser, st, opts.KeepClassicOnClassicAndNativeHistograms, opts.OpenMetricsSkipSTSeries) } return baseParser, err diff --git a/vendor/github.com/prometheus/prometheus/model/textparse/nhcbparse.go b/vendor/github.com/prometheus/prometheus/model/textparse/nhcbparse.go index 3a5288f..ed5f98d 100644 --- a/vendor/github.com/prometheus/prometheus/model/textparse/nhcbparse.go +++ b/vendor/github.com/prometheus/prometheus/model/textparse/nhcbparse.go @@ -52,6 +52,9 @@ type NHCBParser struct { parser Parser // Option to keep classic histograms along with converted histograms. keepClassicHistograms bool + // parseST tells if the caller needs start timestamps. When false, + // StartTimestamp calls are skipped because they are expensive. + parseST bool // Labels builder. builder labels.ScratchBuilder @@ -103,10 +106,11 @@ type NHCBParser struct { hBuffer []byte } -func NewNHCBParser(p Parser, st *labels.SymbolTable, keepClassicHistograms bool) Parser { +func NewNHCBParser(p Parser, st *labels.SymbolTable, keepClassicHistograms, parseST bool) Parser { return &NHCBParser{ parser: p, keepClassicHistograms: keepClassicHistograms, + parseST: parseST, builder: labels.NewScratchBuilderWithSymbolTable(st, 16), tempNHCB: convertnhcb.NewTempHistogram(), } @@ -319,7 +323,11 @@ func (p *NHCBParser) handleClassicHistogramSeries(lset labels.Labels) bool { func (p *NHCBParser) processClassicHistogramSeries(lset labels.Labels, name string, updateHist func(*convertnhcb.TempHistogram)) { if p.state != stateCollecting { p.storeClassicLabels(name) - p.tempST = p.parser.StartTimestamp() + if p.parseST { + p.tempST = p.parser.StartTimestamp() + } else { + p.tempST = 0 + } p.state = stateCollecting p.tempLsetNHCB = convertnhcb.GetHistogramMetricBase(lset, name) } diff --git a/vendor/github.com/prometheus/prometheus/model/textparse/openmetrics2lex.l b/vendor/github.com/prometheus/prometheus/model/textparse/openmetrics2lex.l new file mode 100644 index 0000000..1e2c0e3 --- /dev/null +++ b/vendor/github.com/prometheus/prometheus/model/textparse/openmetrics2lex.l @@ -0,0 +1,86 @@ +%{ +// Copyright The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package textparse + +import ( + "fmt" +) + +// Lex is called by the parser generated by "go tool yacc" to obtain each +// token. The method is opened before the matching rules block and closed at +// the end of the file. +func (l *openMetrics2Lexer) Lex() token { + if l.i >= len(l.b) { + return tEOF + } + c := l.b[l.i] + l.start = l.i + +%} + +D [0-9] +L [a-zA-Z_] +M [a-zA-Z_:] +C [^\n] +S [ ] + +%x sComment sMeta1 sMeta2 sLabels sLValue sValue sTimestamp sExemplar sEValue sETimestamp + +%yyc c +%yyn c = l.next() +%yyt l.state + + +%% + +#{S} l.state = sComment +HELP{S} l.state = sMeta1; return tHelp +TYPE{S} l.state = sMeta1; return tType +UNIT{S} l.state = sMeta1; return tUnit +"EOF"\n? l.state = sInit; return tEOFWord +\"(\\.|[^\\"])*\" l.state = sMeta2; return tMName +{M}({M}|{D})* l.state = sMeta2; return tMName +{S}{C}*\n l.state = sInit; return tText + +{M}({M}|{D})* l.state = sValue; return tMName +\{ l.state = sLabels; return tBraceOpen +\{ l.state = sLabels; return tBraceOpen +{L}({L}|{D})* return tLName +\"(\\.|[^\\"])*\" l.state = sLabels; return tQString +\} l.state = sValue; return tBraceClose += l.state = sLValue; return tEqual +, return tComma +\"(\\.|[^\\"\n])*\" l.state = sLabels; return tLValue +{S}[^ \n]+ l.state = sTimestamp; return tValue +{S}st@[^ \n]+ l.state = sTimestamp; return tStartTimestamp +{S}[^ \n]+ return tTimestamp +\n l.state = sInit; return tLinebreak +{S}#{S}\{ l.state = sExemplar; return tComment + +{L}({L}|{D})* return tLName +\"(\\.|[^\\"\n])*\" l.state = sExemplar; return tQString +\} l.state = sEValue; return tBraceClose += l.state = sEValue; return tEqual +\"(\\.|[^\\"\n])*\" l.state = sExemplar; return tLValue +, return tComma +{S}[^ \n]+ l.state = sETimestamp; return tValue +{S}[^ \n]+ return tTimestamp +\n l.state = sInit; return tLinebreak +{S}#{S}\{ l.state = sExemplar; return tComment + +%% + + return tInvalid +} diff --git a/vendor/github.com/prometheus/prometheus/model/textparse/openmetrics2lex.l.go b/vendor/github.com/prometheus/prometheus/model/textparse/openmetrics2lex.l.go new file mode 100644 index 0000000..8f2d46e --- /dev/null +++ b/vendor/github.com/prometheus/prometheus/model/textparse/openmetrics2lex.l.go @@ -0,0 +1,984 @@ +// Code generated by golex. DO NOT EDIT. + +// Copyright The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package textparse + +import ( + "fmt" +) + +// Lex is called by the parser generated by "go tool yacc" to obtain each +// token. The method is opened before the matching rules block and closed at +// the end of the file. +func (l *openMetrics2Lexer) Lex() token { + if l.i >= len(l.b) { + return tEOF + } + c := l.b[l.i] + l.start = l.i + +yystate0: + + switch yyt := l.state; yyt { + default: + panic(fmt.Errorf(`invalid start condition %d`, yyt)) + case 0: // start condition: INITIAL + goto yystart1 + case 1: // start condition: sComment + goto yystart6 + case 2: // start condition: sMeta1 + goto yystart26 + case 3: // start condition: sMeta2 + goto yystart31 + case 4: // start condition: sLabels + goto yystart34 + case 5: // start condition: sLValue + goto yystart42 + case 6: // start condition: sValue + goto yystart46 + case 7: // start condition: sTimestamp + goto yystart50 + case 8: // start condition: sExemplar + goto yystart61 + case 9: // start condition: sEValue + goto yystart69 + case 10: // start condition: sETimestamp + goto yystart75 + } + +yystate1: + c = l.next() +yystart1: + switch { + default: + goto yyabort + case c == '#': + goto yystate2 + case c == ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate4 + case c == '{': + goto yystate5 + } + +yystate2: + c = l.next() + switch { + default: + goto yyabort + case c == ' ': + goto yystate3 + } + +yystate3: + c = l.next() + goto yyrule1 + +yystate4: + c = l.next() + switch { + default: + goto yyrule9 + case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate4 + } + +yystate5: + c = l.next() + goto yyrule11 + +yystate6: + c = l.next() +yystart6: + switch { + default: + goto yyabort + case c == 'E': + goto yystate7 + case c == 'H': + goto yystate11 + case c == 'T': + goto yystate16 + case c == 'U': + goto yystate21 + } + +yystate7: + c = l.next() + switch { + default: + goto yyabort + case c == 'O': + goto yystate8 + } + +yystate8: + c = l.next() + switch { + default: + goto yyabort + case c == 'F': + goto yystate9 + } + +yystate9: + c = l.next() + switch { + default: + goto yyrule5 + case c == '\n': + goto yystate10 + } + +yystate10: + c = l.next() + goto yyrule5 + +yystate11: + c = l.next() + switch { + default: + goto yyabort + case c == 'E': + goto yystate12 + } + +yystate12: + c = l.next() + switch { + default: + goto yyabort + case c == 'L': + goto yystate13 + } + +yystate13: + c = l.next() + switch { + default: + goto yyabort + case c == 'P': + goto yystate14 + } + +yystate14: + c = l.next() + switch { + default: + goto yyabort + case c == ' ': + goto yystate15 + } + +yystate15: + c = l.next() + goto yyrule2 + +yystate16: + c = l.next() + switch { + default: + goto yyabort + case c == 'Y': + goto yystate17 + } + +yystate17: + c = l.next() + switch { + default: + goto yyabort + case c == 'P': + goto yystate18 + } + +yystate18: + c = l.next() + switch { + default: + goto yyabort + case c == 'E': + goto yystate19 + } + +yystate19: + c = l.next() + switch { + default: + goto yyabort + case c == ' ': + goto yystate20 + } + +yystate20: + c = l.next() + goto yyrule3 + +yystate21: + c = l.next() + switch { + default: + goto yyabort + case c == 'N': + goto yystate22 + } + +yystate22: + c = l.next() + switch { + default: + goto yyabort + case c == 'I': + goto yystate23 + } + +yystate23: + c = l.next() + switch { + default: + goto yyabort + case c == 'T': + goto yystate24 + } + +yystate24: + c = l.next() + switch { + default: + goto yyabort + case c == ' ': + goto yystate25 + } + +yystate25: + c = l.next() + goto yyrule4 + +yystate26: + c = l.next() +yystart26: + switch { + default: + goto yyabort + case c == '"': + goto yystate27 + case c == ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate30 + } + +yystate27: + c = l.next() + switch { + default: + goto yyabort + case c == '"': + goto yystate28 + case c == '\\': + goto yystate29 + case c >= '\x01' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ': + goto yystate27 + } + +yystate28: + c = l.next() + goto yyrule6 + +yystate29: + c = l.next() + switch { + default: + goto yyabort + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ': + goto yystate27 + } + +yystate30: + c = l.next() + switch { + default: + goto yyrule7 + case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate30 + } + +yystate31: + c = l.next() +yystart31: + switch { + default: + goto yyabort + case c == ' ': + goto yystate32 + } + +yystate32: + c = l.next() + switch { + default: + goto yyabort + case c == '\n': + goto yystate33 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ': + goto yystate32 + } + +yystate33: + c = l.next() + goto yyrule8 + +yystate34: + c = l.next() +yystart34: + switch { + default: + goto yyabort + case c == '"': + goto yystate35 + case c == ',': + goto yystate38 + case c == '=': + goto yystate39 + case c == '}': + goto yystate41 + case c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate40 + } + +yystate35: + c = l.next() + switch { + default: + goto yyabort + case c == '"': + goto yystate36 + case c == '\\': + goto yystate37 + case c >= '\x01' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ': + goto yystate35 + } + +yystate36: + c = l.next() + goto yyrule13 + +yystate37: + c = l.next() + switch { + default: + goto yyabort + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ': + goto yystate35 + } + +yystate38: + c = l.next() + goto yyrule16 + +yystate39: + c = l.next() + goto yyrule15 + +yystate40: + c = l.next() + switch { + default: + goto yyrule12 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate40 + } + +yystate41: + c = l.next() + goto yyrule14 + +yystate42: + c = l.next() +yystart42: + switch { + default: + goto yyabort + case c == '"': + goto yystate43 + } + +yystate43: + c = l.next() + switch { + default: + goto yyabort + case c == '"': + goto yystate44 + case c == '\\': + goto yystate45 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ': + goto yystate43 + } + +yystate44: + c = l.next() + goto yyrule17 + +yystate45: + c = l.next() + switch { + default: + goto yyabort + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ': + goto yystate43 + } + +yystate46: + c = l.next() +yystart46: + switch { + default: + goto yyabort + case c == ' ': + goto yystate47 + case c == '{': + goto yystate49 + } + +yystate47: + c = l.next() + switch { + default: + goto yyabort + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'ÿ': + goto yystate48 + } + +yystate48: + c = l.next() + switch { + default: + goto yyrule18 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'ÿ': + goto yystate48 + } + +yystate49: + c = l.next() + goto yyrule10 + +yystate50: + c = l.next() +yystart50: + switch { + default: + goto yyabort + case c == ' ': + goto yystate52 + case c == '\n': + goto yystate51 + } + +yystate51: + c = l.next() + goto yyrule21 + +yystate52: + c = l.next() + switch { + default: + goto yyabort + case c == '#': + goto yystate54 + case c == 's': + goto yystate57 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '\x1f' || c == '!' || c == '"' || c >= '$' && c <= 'r' || c >= 't' && c <= 'ÿ': + goto yystate53 + } + +yystate53: + c = l.next() + switch { + default: + goto yyrule20 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'ÿ': + goto yystate53 + } + +yystate54: + c = l.next() + switch { + default: + goto yyrule20 + case c == ' ': + goto yystate55 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'ÿ': + goto yystate53 + } + +yystate55: + c = l.next() + switch { + default: + goto yyabort + case c == '{': + goto yystate56 + } + +yystate56: + c = l.next() + goto yyrule22 + +yystate57: + c = l.next() + switch { + default: + goto yyrule20 + case c == 't': + goto yystate58 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 's' || c >= 'u' && c <= 'ÿ': + goto yystate53 + } + +yystate58: + c = l.next() + switch { + default: + goto yyrule20 + case c == '@': + goto yystate59 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= '?' || c >= 'A' && c <= 'ÿ': + goto yystate53 + } + +yystate59: + c = l.next() + switch { + default: + goto yyrule20 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'ÿ': + goto yystate60 + } + +yystate60: + c = l.next() + switch { + default: + goto yyrule19 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'ÿ': + goto yystate60 + } + +yystate61: + c = l.next() +yystart61: + switch { + default: + goto yyabort + case c == '"': + goto yystate62 + case c == ',': + goto yystate65 + case c == '=': + goto yystate66 + case c == '}': + goto yystate68 + case c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate67 + } + +yystate62: + c = l.next() + switch { + default: + goto yyabort + case c == '"': + goto yystate63 + case c == '\\': + goto yystate64 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ': + goto yystate62 + } + +yystate63: + c = l.next() + goto yyrule24 + +yystate64: + c = l.next() + switch { + default: + goto yyabort + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ': + goto yystate62 + } + +yystate65: + c = l.next() + goto yyrule28 + +yystate66: + c = l.next() + goto yyrule26 + +yystate67: + c = l.next() + switch { + default: + goto yyrule23 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate67 + } + +yystate68: + c = l.next() + goto yyrule25 + +yystate69: + c = l.next() +yystart69: + switch { + default: + goto yyabort + case c == ' ': + goto yystate70 + case c == '"': + goto yystate72 + } + +yystate70: + c = l.next() + switch { + default: + goto yyabort + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'ÿ': + goto yystate71 + } + +yystate71: + c = l.next() + switch { + default: + goto yyrule29 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'ÿ': + goto yystate71 + } + +yystate72: + c = l.next() + switch { + default: + goto yyabort + case c == '"': + goto yystate73 + case c == '\\': + goto yystate74 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ': + goto yystate72 + } + +yystate73: + c = l.next() + goto yyrule27 + +yystate74: + c = l.next() + switch { + default: + goto yyabort + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ': + goto yystate72 + } + +yystate75: + c = l.next() +yystart75: + switch { + default: + goto yyabort + case c == ' ': + goto yystate77 + case c == '\n': + goto yystate76 + } + +yystate76: + c = l.next() + goto yyrule31 + +yystate77: + c = l.next() + switch { + default: + goto yyabort + case c == '#': + goto yystate79 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '\x1f' || c == '!' || c == '"' || c >= '$' && c <= 'ÿ': + goto yystate78 + } + +yystate78: + c = l.next() + switch { + default: + goto yyrule30 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'ÿ': + goto yystate78 + } + +yystate79: + c = l.next() + switch { + default: + goto yyrule30 + case c == ' ': + goto yystate80 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'ÿ': + goto yystate78 + } + +yystate80: + c = l.next() + switch { + default: + goto yyabort + case c == '{': + goto yystate81 + } + +yystate81: + c = l.next() + goto yyrule32 + +yyrule1: // #{S} + { + l.state = sComment + goto yystate0 + } +yyrule2: // HELP{S} + { + l.state = sMeta1 + return tHelp + goto yystate0 + } +yyrule3: // TYPE{S} + { + l.state = sMeta1 + return tType + goto yystate0 + } +yyrule4: // UNIT{S} + { + l.state = sMeta1 + return tUnit + goto yystate0 + } +yyrule5: // "EOF"\n? + { + l.state = sInit + return tEOFWord + goto yystate0 + } +yyrule6: // \"(\\.|[^\\"])*\" + { + l.state = sMeta2 + return tMName + goto yystate0 + } +yyrule7: // {M}({M}|{D})* + { + l.state = sMeta2 + return tMName + goto yystate0 + } +yyrule8: // {S}{C}*\n + { + l.state = sInit + return tText + goto yystate0 + } +yyrule9: // {M}({M}|{D})* + { + l.state = sValue + return tMName + goto yystate0 + } +yyrule10: // \{ + { + l.state = sLabels + return tBraceOpen + goto yystate0 + } +yyrule11: // \{ + { + l.state = sLabels + return tBraceOpen + goto yystate0 + } +yyrule12: // {L}({L}|{D})* + { + return tLName + } +yyrule13: // \"(\\.|[^\\"])*\" + { + l.state = sLabels + return tQString + goto yystate0 + } +yyrule14: // \} + { + l.state = sValue + return tBraceClose + goto yystate0 + } +yyrule15: // = + { + l.state = sLValue + return tEqual + goto yystate0 + } +yyrule16: // , + { + return tComma + } +yyrule17: // \"(\\.|[^\\"\n])*\" + { + l.state = sLabels + return tLValue + goto yystate0 + } +yyrule18: // {S}[^ \n]+ + { + l.state = sTimestamp + return tValue + goto yystate0 + } +yyrule19: // {S}st@[^ \n]+ + { + l.state = sTimestamp + return tStartTimestamp + goto yystate0 + } +yyrule20: // {S}[^ \n]+ + { + return tTimestamp + } +yyrule21: // \n + { + l.state = sInit + return tLinebreak + goto yystate0 + } +yyrule22: // {S}#{S}\{ + { + l.state = sExemplar + return tComment + goto yystate0 + } +yyrule23: // {L}({L}|{D})* + { + return tLName + } +yyrule24: // \"(\\.|[^\\"\n])*\" + { + l.state = sExemplar + return tQString + goto yystate0 + } +yyrule25: // \} + { + l.state = sEValue + return tBraceClose + goto yystate0 + } +yyrule26: // = + { + l.state = sEValue + return tEqual + goto yystate0 + } +yyrule27: // \"(\\.|[^\\"\n])*\" + { + l.state = sExemplar + return tLValue + goto yystate0 + } +yyrule28: // , + { + return tComma + } +yyrule29: // {S}[^ \n]+ + { + l.state = sETimestamp + return tValue + goto yystate0 + } +yyrule30: // {S}[^ \n]+ + { + return tTimestamp + } +yyrule31: // \n + { + l.state = sInit + return tLinebreak + goto yystate0 + } +yyrule32: // {S}#{S}\{ + if true { // avoid go vet determining the below panic will not be reached + l.state = sExemplar + return tComment + goto yystate0 + } + panic("unreachable") + +yyabort: // no lexem recognized + // silence unused label errors for build and satisfy go vet reachability analysis + { + if false { + goto yyabort + } + if false { + goto yystate0 + } + if false { + goto yystate1 + } + if false { + goto yystate6 + } + if false { + goto yystate26 + } + if false { + goto yystate31 + } + if false { + goto yystate34 + } + if false { + goto yystate42 + } + if false { + goto yystate46 + } + if false { + goto yystate50 + } + if false { + goto yystate61 + } + if false { + goto yystate69 + } + if false { + goto yystate75 + } + } + + return tInvalid +} diff --git a/vendor/github.com/prometheus/prometheus/model/textparse/openmetrics2parse.go b/vendor/github.com/prometheus/prometheus/model/textparse/openmetrics2parse.go new file mode 100644 index 0000000..0da7059 --- /dev/null +++ b/vendor/github.com/prometheus/prometheus/model/textparse/openmetrics2parse.go @@ -0,0 +1,1494 @@ +// Copyright The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:generate go get -u modernc.org/golex +//go:generate golex -o=openmetrics2lex.l.go openmetrics2lex.l + +package textparse + +import ( + "bytes" + "errors" + "fmt" + "io" + "iter" + "math" + "strconv" + "strings" + "unicode/utf8" + + "github.com/prometheus/common/model" + + "github.com/prometheus/prometheus/model/exemplar" + "github.com/prometheus/prometheus/model/histogram" + "github.com/prometheus/prometheus/model/labels" + "github.com/prometheus/prometheus/model/value" + "github.com/prometheus/prometheus/schema" +) + +// openMetrics2Lexer is the lexer for the OpenMetrics 2.0 text format. +type openMetrics2Lexer struct { + b []byte + i int + start int + err error + state int +} + +// buf returns the bytes of the current token. +func (l *openMetrics2Lexer) buf() []byte { + return l.b[l.start:l.i] +} + +// next advances the openMetrics2Lexer to the next character and returns it. +func (l *openMetrics2Lexer) next() byte { + l.i++ + if l.i >= len(l.b) { + l.err = io.EOF + return byte(tEOF) + } + // Lex struggles with null bytes. If we are in a label value or help + // string, where they are allowed, consume them here immediately. + for l.b[l.i] == 0 && (l.state == sLValue || l.state == sMeta2 || l.state == sComment) { + l.i++ + if l.i >= len(l.b) { + l.err = io.EOF + return byte(tEOF) + } + } + return l.b[l.i] +} + +// Error satisfies the golex interface for openMetrics2Lexer. +func (l *openMetrics2Lexer) Error(es string) { + l.err = errors.New(es) +} + +// pendingEntry holds a single exploded flat series to be drained from the +// pending queue that is built when a composite value (summary or classic +// histogram) is parsed. +type pendingEntry struct { + series []byte + lset labels.Labels + val float64 + ts *int64 +} + +// om2Exemplar holds a fully parsed exemplar. +type om2Exemplar struct { + e exemplar.Exemplar +} + +// OpenMetrics2Parser parses samples from a byte slice in the OpenMetrics 2.0 +// text exposition format. +// Specification: https://prometheus.io/docs/specs/om/open_metrics_spec_2_0/ +// +// Note for exposer and client library implementers: this parser is not a +// conformance test for OpenMetrics 2.0. It is not yet generally available +// thus it might be stricter in the future. + +type OpenMetrics2Parser struct { + l *openMetrics2Lexer + builder labels.ScratchBuilder + + // Metadata for the current metric family. Reset by resetOnFamilyChange. + mtype model.MetricType + unit string + text []byte + + // Current sample position in the input. + series []byte + + // curFamilyName is a slice into l.b holding the last metric name seen by + // resetOnFamilyChange. + curFamilyName []byte + + // offsets encodes the metric name and label positions as absolute byte + // offsets into l.b. Layout: [nameStart, nameEnd, k1Start, k1End, + // v1Start, v1End, k2Start, k2End, v2Start, v2End, ...]. Labels() uses + // these to slice strings without allocating during the hot parse path. + offsets []int + start int + + // Scalar sample value, timestamp. + val float64 + hasTS bool + ts int64 + + // Inline start timestamp from "st@"; O(1) — no forward scan. + st int64 + hasST bool + + // Native histogram value; set when the composite value contains schema/spans. + h *histogram.Histogram + fh *histogram.FloatHistogram + + // Multiple exemplars per sample (OM 2.0 allows zero or more). + exemplars []om2Exemplar + exemplarIdx int + + // Pending queue for composite values exploded into flat EntrySeries. + // pending[0..pendingIdx-1] are waiting to be served; Next() increments + // pendingIdx and Series()/Labels() read pending[pendingIdx-1]. + pending []pendingEntry + pendingIdx int + + // seriesBuf backs pendingEntry.series; reused across entries to avoid + // allocating one identity per entry. + seriesBuf []byte + + enableTypeAndUnitLabels bool + + // When true, a composite histogram that exposes both native fields and a + // classic bucket list emits the native histogram followed by classic + // _count/_sum/_bucket flat series. Mirrors the protobuf parser's + // KeepClassicOnClassicAndNativeHistograms option. + keepClassicOnNativeHist bool +} + +// NewOpenMetrics2Parser returns a new parser for the OpenMetrics 2.0 text +// format. +func NewOpenMetrics2Parser(b []byte, st *labels.SymbolTable, opts ParserOptions) Parser { + return &OpenMetrics2Parser{ + l: &openMetrics2Lexer{b: b}, + builder: labels.NewScratchBuilderWithSymbolTable(st, 16), + enableTypeAndUnitLabels: opts.EnableTypeAndUnitLabels, + keepClassicOnNativeHist: opts.KeepClassicOnClassicAndNativeHistograms, + } +} + +// resetOnFamilyChange resets mtype/unit when name differs from curFamilyName. +func (p *OpenMetrics2Parser) resetOnFamilyChange(name []byte) { + if !bytes.Equal(name, p.curFamilyName) { + p.mtype = model.MetricTypeUnknown + p.unit = "" + } + p.curFamilyName = name +} + +// hasFamilyNameLabel reports whether the current sample's labelsinclude a label key matching +// p.curFamilyName. Used to enforce the OM2 stateset requirements. +func (p *OpenMetrics2Parser) hasFamilyNameLabel() bool { + for i := 2; i < len(p.offsets); i += 4 { + if bytes.Equal(p.l.b[p.offsets[i]:p.offsets[i+1]], p.curFamilyName) { + return true + } + } + return false +} + +// Series returns the bytes of the current series, the timestamp if set, and +// the sample value. +func (p *OpenMetrics2Parser) Series() ([]byte, *int64, float64) { + if p.pendingIdx > 0 { + pe := p.pending[p.pendingIdx-1] + return pe.series, pe.ts, pe.val + } + if p.hasTS { + ts := p.ts + return p.series, &ts, p.val + } + return p.series, nil, p.val +} + +// Histogram returns the bytes of the current series, the timestamp if set, +// and the native histogram value. +func (p *OpenMetrics2Parser) Histogram() ([]byte, *int64, *histogram.Histogram, *histogram.FloatHistogram) { + if p.hasTS { + ts := p.ts + return p.series, &ts, p.h, p.fh + } + return p.series, nil, p.h, p.fh +} + +// Help returns the metric name and help text of the current entry. +// Must only be called after Next returned EntryHelp. +func (p *OpenMetrics2Parser) Help() ([]byte, []byte) { + m := p.l.b[p.offsets[0]:p.offsets[1]] + if bytes.IndexByte(p.text, byte('\\')) >= 0 { + return m, []byte(lvalReplacer.Replace(string(p.text))) + } + return m, p.text +} + +// Type returns the metric name and type of the current entry. +// Must only be called after Next returned EntryType. +func (p *OpenMetrics2Parser) Type() ([]byte, model.MetricType) { + return p.l.b[p.offsets[0]:p.offsets[1]], p.mtype +} + +// Unit returns the metric name and unit of the current entry. +// Must only be called after Next returned EntryUnit. +func (p *OpenMetrics2Parser) Unit() ([]byte, []byte) { + return p.l.b[p.offsets[0]:p.offsets[1]], []byte(p.unit) +} + +// Comment returns the text of the current comment. +// Must only be called after Next returned EntryComment. +func (p *OpenMetrics2Parser) Comment() []byte { + return p.text +} + +// Labels writes the labels of the current sample into l. +func (p *OpenMetrics2Parser) Labels(l *labels.Labels) { + if p.pendingIdx > 0 { + *l = p.pending[p.pendingIdx-1].lset + return + } + s := string(p.series) + p.builder.Reset() + metricName := unreplace(s[p.offsets[0]-p.start : p.offsets[1]-p.start]) + m := schema.Metadata{ + Name: metricName, + Type: p.mtype, + Unit: p.unit, + } + if p.enableTypeAndUnitLabels { + m.AddToLabels(&p.builder) + } else { + p.builder.Add(model.MetricNameLabel, metricName) + } + for i := 2; i < len(p.offsets); i += 4 { + a := p.offsets[i] - p.start + b := p.offsets[i+1] - p.start + label := unreplace(s[a:b]) + if p.enableTypeAndUnitLabels && !m.IsEmptyFor(label) { + continue + } + c := p.offsets[i+2] - p.start + d := p.offsets[i+3] - p.start + v := normalizeFloatsInLabelValues(p.mtype, label, unreplace(s[c:d])) + p.builder.Add(label, v) + } + p.builder.Sort() + *l = p.builder.Labels() +} + +// Exemplar writes the next exemplar of the current sample into e and returns +// true. Returns false when all exemplars have been consumed. +func (p *OpenMetrics2Parser) Exemplar(e *exemplar.Exemplar) bool { + if p.exemplarIdx >= len(p.exemplars) { + return false + } + *e = p.exemplars[p.exemplarIdx].e + p.exemplarIdx++ + return true +} + +// StartTimestamp returns the inline start timestamp for the current sample +// (from the "st@" token), or 0 if none was present. This is O(1); there +// is no forward scan. +func (p *OpenMetrics2Parser) StartTimestamp() int64 { + if p.hasST { + return p.st + } + return 0 +} + +func (p *OpenMetrics2Parser) nextToken() token { + return p.l.Lex() +} + +func (p *OpenMetrics2Parser) parseError(exp string, got token) error { + e := min(len(p.l.b), p.l.i+1) + return fmt.Errorf("%s, got %q (%q) while parsing: %q", exp, p.l.b[p.l.start:e], got, p.l.b[p.start:e]) +} + +// Next advances the parser to the next entry. +// It returns (EntryInvalid, io.EOF) when there are no more entries. +func (p *OpenMetrics2Parser) Next() (Entry, error) { + // Drain pending composite-value entries. + if p.pendingIdx < len(p.pending) { + p.pendingIdx++ + return EntrySeries, nil + } + p.pending = p.pending[:0] + p.pendingIdx = 0 + p.seriesBuf = p.seriesBuf[:0] + + var err error + p.start = p.l.i + p.offsets = p.offsets[:0] + p.exemplars = p.exemplars[:0] + p.exemplarIdx = 0 + p.hasTS = false + p.hasST = false + p.h = nil + p.fh = nil + + switch t := p.nextToken(); t { + case tEOFWord: + if t := p.nextToken(); t != tEOF { + return EntryInvalid, errors.New("unexpected data after # EOF") + } + return EntryInvalid, io.EOF + case tEOF: + return EntryInvalid, errors.New("data does not end with # EOF") + + case tHelp, tType, tUnit: + switch t2 := p.nextToken(); t2 { + case tMName: + mStart := p.l.start + mEnd := p.l.i + if p.l.b[mStart] == '"' && p.l.b[mEnd-1] == '"' { + mStart++ + mEnd-- + } + if mStart == mEnd { + return EntryInvalid, errors.New("metric name must not be empty") + } + if !utf8.Valid(p.l.b[mStart:mEnd]) { + return EntryInvalid, fmt.Errorf("invalid UTF-8 metric name: %q", p.l.b[mStart:mEnd]) + } + p.offsets = append(p.offsets, mStart, mEnd) + p.resetOnFamilyChange(p.l.b[mStart:mEnd]) + default: + return EntryInvalid, p.parseError("expected metric name after "+t.String(), t2) + } + switch t2 := p.nextToken(); t2 { + case tText: + if len(p.l.buf()) > 1 { + p.text = p.l.buf()[1 : len(p.l.buf())-1] + } else { + p.text = []byte{} + } + default: + return EntryInvalid, fmt.Errorf("expected text in %s", t.String()) + } + switch t { + case tType: + switch s := yoloString(p.text); s { + case "counter": + p.mtype = model.MetricTypeCounter + case "gauge": + p.mtype = model.MetricTypeGauge + case "histogram": + p.mtype = model.MetricTypeHistogram + case "gaugehistogram": + p.mtype = model.MetricTypeGaugeHistogram + case "summary": + p.mtype = model.MetricTypeSummary + case "info": + p.mtype = model.MetricTypeInfo + case "stateset": + p.mtype = model.MetricTypeStateset + case "unknown": + p.mtype = model.MetricTypeUnknown + default: + return EntryInvalid, fmt.Errorf("invalid metric type %q", s) + } + case tHelp: + if !utf8.Valid(p.text) { + return EntryInvalid, fmt.Errorf("help text %q is not a valid utf8 string", p.text) + } + } + switch t { + case tHelp: + return EntryHelp, nil + case tType: + return EntryType, nil + case tUnit: + // OM2 only RECOMMENDS the unit be an underscore-separated suffix + // of the MetricFamily name; it is not a hard requirement. + p.unit = string(p.text) + return EntryUnit, nil + } + + case tBraceOpen: + // UTF-8 metric name inside braces. + if len(p.offsets) == 0 { + p.offsets = []int{-1, -1} + } + if p.offsets, err = p.parseLVals(p.offsets, false); err != nil { + return EntryInvalid, err + } + if p.offsets[0] != -1 { + p.resetOnFamilyChange(p.l.b[p.offsets[0]:p.offsets[1]]) + } + p.series = p.l.b[p.start:p.l.i] + return p.parseSeriesEndOfLine(p.nextToken()) + + case tMName: + p.offsets = append(p.offsets, p.start, p.l.i) + p.resetOnFamilyChange(p.l.b[p.start:p.l.i]) + p.series = p.l.b[p.start:p.l.i] + + t2 := p.nextToken() + if t2 == tBraceOpen { + p.offsets, err = p.parseLVals(p.offsets, false) + if err != nil { + return EntryInvalid, err + } + p.series = p.l.b[p.start:p.l.i] + t2 = p.nextToken() + } + return p.parseSeriesEndOfLine(t2) + + default: + err = p.parseError("expected a valid start token", t) + } + return EntryInvalid, err +} + +// parseSeriesEndOfLine parses the rest of a data line starting from the value +// token. It dispatches to composite or scalar value parsing. +func (p *OpenMetrics2Parser) parseSeriesEndOfLine(t token) (Entry, error) { + if p.offsets[0] == -1 { + return EntryInvalid, fmt.Errorf("metric name not set while parsing: %q", p.l.b[p.start:p.l.i]) + } + if t != tValue { + return EntryInvalid, p.parseError("expected value after metric", t) + } + + // raw is " {..." or " "; strip the leading space. + raw := p.l.buf() + if len(raw) > 1 && raw[0] == ' ' { + raw = raw[1:] + } + + if len(raw) > 0 && raw[0] == '{' { + return p.parseCompositeValue(raw) + } + + // Histogram, GaugeHistogram, and Summary Samples MUST use a composite + // value. + switch p.mtype { + case model.MetricTypeHistogram, model.MetricTypeGaugeHistogram, model.MetricTypeSummary: + return EntryInvalid, fmt.Errorf( + "composite value required for metric type %q while parsing: %q", + p.mtype, p.l.b[p.start:p.l.i], + ) + } + + // Plain float value. + var err error + p.val, err = parseFloat(yoloString(raw)) + if err != nil { + return EntryInvalid, fmt.Errorf("%w while parsing: %q", err, p.l.b[p.start:p.l.i]) + } + if math.IsNaN(p.val) { + if p.mtype == model.MetricTypeCounter { + return EntryInvalid, fmt.Errorf("counter sample value must not be NaN while parsing: %q", p.l.b[p.start:p.l.i]) + } + p.val = math.Float64frombits(value.NormalNaN) + } + + if p.mtype == model.MetricTypeStateset { + if p.val != 0 && p.val != 1 { + return EntryInvalid, fmt.Errorf("stateset sample value must be 0 or 1, got %v while parsing: %q", p.val, p.l.b[p.start:p.l.i]) + } + if !p.hasFamilyNameLabel() { + return EntryInvalid, fmt.Errorf("stateset sample must have a label matching the metric family name %q while parsing: %q", p.curFamilyName, p.l.b[p.start:p.l.i]) + } + } + + if err := p.parseAfterValue(); err != nil { + return EntryInvalid, err + } + return EntrySeries, nil +} + +// parseAfterValue consumes the optional sequence after the metric value: +// +// [tTimestamp] [tStartTimestamp] [*tComment exemplar] tLinebreak +// +// It returns after consuming tLinebreak (either directly or via exemplar +// parsing). +func (p *OpenMetrics2Parser) parseAfterValue() error { + for { + switch t := p.nextToken(); t { + case tEOF: + return errors.New("data does not end with # EOF") + case tLinebreak: + return nil + case tTimestamp: + if p.hasTS { + return fmt.Errorf("duplicate timestamp: %q", p.l.b[p.start:p.l.i]) + } + if p.hasST { + return fmt.Errorf("timestamp must precede start timestamp: %q", p.l.b[p.start:p.l.i]) + } + p.hasTS = true + var ts float64 + var err error + if ts, err = parseFloat(yoloString(p.l.buf()[1:])); err != nil { + return fmt.Errorf("%w while parsing: %q", err, p.l.b[p.start:p.l.i]) + } + if math.IsNaN(ts) || math.IsInf(ts, 0) { + return fmt.Errorf("invalid timestamp %f", ts) + } + p.ts = int64(ts * 1000) + case tStartTimestamp: + if p.hasST { + return fmt.Errorf("duplicate start timestamp: %q", p.l.b[p.start:p.l.i]) + } + // buf is " st@"; skip the leading " st@" (4 bytes). + raw := p.l.buf() + if len(raw) < 4 { + return fmt.Errorf("invalid start timestamp token %q", raw) + } + var st float64 + var err error + if st, err = parseFloat(yoloString(raw[4:])); err != nil { + return fmt.Errorf("%w while parsing start timestamp: %q", err, p.l.b[p.start:p.l.i]) + } + if math.IsNaN(st) || math.IsInf(st, 0) { + return fmt.Errorf("invalid start timestamp %f", st) + } + p.st = int64(st * 1000) + p.hasST = true + case tComment: + // Parse all exemplars on this line; parseExemplars consumes + // up to and including the tLinebreak. + return p.parseExemplars() + default: + return p.parseError("unexpected token after value", t) + } + } +} + +// parseExemplars parses one or more exemplars up to and including the +// tLinebreak. It is called after tComment has been consumed. +func (p *OpenMetrics2Parser) parseExemplars() error { + for { + done, err := p.parseSingleExemplar() + if err != nil { + return err + } + if done { + // tLinebreak was consumed inside parseSingleExemplar. + return nil + } + // tComment was consumed; another exemplar follows. + } +} + +// parseSingleExemplar parses one exemplar label set + value + optional +// timestamp. It reads one token after (from sETimestamp state): +// - tLinebreak → done=true +// - tComment → done=false (caller loops for next exemplar) +func (p *OpenMetrics2Parser) parseSingleExemplar() (done bool, err error) { + var ex om2Exemplar + + // Parse exemplar label set (the "{" was opened by the tComment token). + eOffsets, err := p.parseLVals(nil, true) + if err != nil { + return false, err + } + + // Parse exemplar value. + if t := p.nextToken(); t != tValue { + return false, p.parseError("expected exemplar value", t) + } + ex.e.Value, err = parseFloat(yoloString(p.l.buf()[1:])) + if err != nil { + return false, fmt.Errorf("%w while parsing exemplar value: %q", err, p.l.b[p.start:p.l.i]) + } + if math.IsNaN(ex.e.Value) { + ex.e.Value = math.Float64frombits(value.NormalNaN) + } + + // Build exemplar labels from the byte offsets collected above. + p.builder.Reset() + for i := 0; i < len(eOffsets); i += 4 { + a := eOffsets[i] + b := eOffsets[i+1] + c := eOffsets[i+2] + d := eOffsets[i+3] + p.builder.Add(string(p.l.b[a:b]), unreplace(string(p.l.b[c:d]))) + } + p.builder.Sort() + ex.e.Labels = p.builder.Labels() + + // Read the token following the exemplar value. OM2 requires every + // exemplar to carry a timestamp, so anything other than tTimestamp here + // (including end-of-line or the start of another exemplar) is an error. + switch t2 := p.nextToken(); t2 { + case tEOF: + return false, errors.New("data does not end with # EOF") + case tTimestamp: + ex.e.HasTs = true + var ts float64 + if ts, err = parseFloat(yoloString(p.l.buf()[1:])); err != nil { + return false, fmt.Errorf("%w while parsing exemplar timestamp: %q", err, p.l.b[p.start:p.l.i]) + } + if math.IsNaN(ts) || math.IsInf(ts, 0) { + return false, fmt.Errorf("invalid exemplar timestamp %f", ts) + } + ex.e.Ts = int64(ts * 1000) + p.exemplars = append(p.exemplars, ex) + // After the exemplar timestamp, the line may end (tLinebreak) or + // another exemplar may follow (tComment). + switch t3 := p.nextToken(); t3 { + case tEOF: + return false, errors.New("data does not end with # EOF") + case tLinebreak: + return true, nil + case tComment: + return false, nil // caller loops + default: + return false, p.parseError("expected end of line or next exemplar", t3) + } + default: + return false, p.parseError("expected exemplar timestamp", t2) + } +} + +// parseLVals parses the label set "{k="v",...}" and appends byte offsets. +func (p *OpenMetrics2Parser) parseLVals(offsets []int, isExemplar bool) ([]int, error) { + t := p.nextToken() + first := true + for { + isFirst := first + first = false + curTStart := p.l.start + curTI := p.l.i + var isQString bool + switch t { + case tBraceClose: + return offsets, nil + case tLName: + case tQString: + isQString = true + default: + return nil, p.parseError("expected label name", t) + } + + t = p.nextToken() + if isQString && (t == tComma || t == tBraceClose) { + if isExemplar { + return nil, p.parseError("expected label name", t) + } + if !isFirst { + return nil, errors.New("metric name must be the first item in the label set") + } + if offsets[0] != -1 || offsets[1] != -1 { + return nil, fmt.Errorf("metric name already set while parsing: %q", p.l.b[p.start:p.l.i]) + } + offsets[0] = curTStart + 1 + offsets[1] = curTI - 1 + if offsets[0] == offsets[1] { + return nil, errors.New("metric name must not be empty") + } + if !utf8.Valid(p.l.b[offsets[0]:offsets[1]]) { + return nil, fmt.Errorf("invalid UTF-8 metric name: %q", p.l.b[offsets[0]:offsets[1]]) + } + if t == tBraceClose { + return offsets, nil + } + t = p.nextToken() + continue + } + if p.l.b[curTStart] == '"' { + curTStart++ + curTI-- + } + if !utf8.Valid(p.l.b[curTStart:curTI]) { + return nil, fmt.Errorf("invalid UTF-8 label name: %q", p.l.b[curTStart:curTI]) + } + offsets = append(offsets, curTStart, curTI) + + if t != tEqual { + return nil, p.parseError("expected equal", t) + } + if t := p.nextToken(); t != tLValue { + return nil, p.parseError("expected label value", t) + } + if !utf8.Valid(p.l.buf()) { + return nil, fmt.Errorf("invalid UTF-8 label value: %q", p.l.buf()) + } + offsets = append(offsets, p.l.start+1, p.l.i-1) + + t = p.nextToken() + if t == tComma { + t = p.nextToken() + } else if t != tBraceClose { + return nil, p.parseError("expected comma or brace close", t) + } + } +} + +// parseCompositeValue dispatches on the current metric type and builds either +// a native histogram (EntryHistogram) or a list of pending flat series +// (EntrySeries) from the composite value token. +// +// raw is the raw composite value bytes including the surrounding {}. +func (p *OpenMetrics2Parser) parseCompositeValue(raw []byte) (Entry, error) { + // Consume the rest of the line (timestamp, st@, exemplars) before building + // the pending entries, so the exemplar and ST fields are set correctly. + if err := p.parseAfterValue(); err != nil { + return EntryInvalid, err + } + + switch p.mtype { + case model.MetricTypeHistogram, model.MetricTypeGaugeHistogram: + return p.parseHistogramComposite(raw) + case model.MetricTypeSummary: + return p.parseSummaryComposite(raw) + default: + return EntryInvalid, fmt.Errorf( + "composite value not supported for metric type %q while parsing: %q", + p.mtype, raw, + ) + } +} + +// kvMap parses "{k:v,...}" into a string map. Values are returned verbatim +// (not unquoted). Nested brackets in values are supported. +func kvMap(raw []byte) (map[string]string, error) { + if len(raw) < 2 || raw[0] != '{' || raw[len(raw)-1] != '}' { + return nil, fmt.Errorf("composite value must be wrapped in {}: %q", raw) + } + inner := raw[1 : len(raw)-1] + m := map[string]string{} + for part := range splitCompositeFields(inner) { + part = bytes.TrimSpace(part) + if len(part) == 0 { + continue + } + before, after, ok := bytes.Cut(part, []byte{':'}) + if !ok { + return nil, fmt.Errorf("invalid composite field (missing ':'): %q", part) + } + k := string(bytes.TrimSpace(before)) + v := string(bytes.TrimSpace(after)) + if _, dup := m[k]; dup { + return nil, fmt.Errorf("duplicate composite field %q: %q", k, raw) + } + m[k] = v + } + return m, nil +} + +// histogramCompositeFields are the field names recognized in a Histogram or +// GaugeHistogram composite value, across both the classic-bucket and native +// qq representations. +var histogramCompositeFields = map[string]struct{}{ + "count": {}, "sum": {}, "gcount": {}, "gsum": {}, "bucket": {}, + "schema": {}, "zero_threshold": {}, "zero_count": {}, + "positive_spans": {}, "positive_buckets": {}, + "negative_spans": {}, "negative_buckets": {}, +} + +// summaryCompositeFields are the field names recognised in a Summary +// composite value. +var summaryCompositeFields = map[string]struct{}{ + "count": {}, "sum": {}, "quantile": {}, +} + +// validateCompositeFields rejects any key in kv not present in allowed — +// the ABNF for composite values is a closed grammar with no unknown fields, +// so an unrecognised key (e.g. a typo) must be rejected rather than silently +// ignored. +func validateCompositeFields(kv map[string]string, allowed map[string]struct{}, raw []byte) error { + for k := range kv { + if _, ok := allowed[k]; !ok { + return fmt.Errorf("unknown composite field %q: %q", k, raw) + } + } + return nil +} + +// splitCompositeFields yields each top-level field of b (split at commas not +// inside brackets) as a sub-slice of b. +func splitCompositeFields(b []byte) iter.Seq[[]byte] { + return func(yield func([]byte) bool) { + depth := 0 + start := 0 + for i, ch := range b { + switch ch { + case '[', '(': + depth++ + case ']', ')': + depth-- + case ',': + if depth == 0 { + if !yield(b[start:i]) { + return + } + start = i + 1 + } + } + } + yield(b[start:]) + } +} + +// parseHistogramComposite parses a composite histogram value such as: +// +// {count:12,sum:5.5,schema:0,zero_threshold:0.001,zero_count:2, +// positive_spans:[0:3,2:1],positive_buckets:[1,1,-1,2], +// negative_spans:[],negative_buckets:[]} +// +// or a classic histogram: +// +// {count:12,sum:5.5,bucket:[+Inf:12,1.0:3,2.0:7]} +// +// When native buckets are present it returns EntryHistogram. Otherwise it +// populates the pending queue and returns EntrySeries for the first entry. +func (p *OpenMetrics2Parser) parseHistogramComposite(raw []byte) (Entry, error) { + kv, err := kvMap(raw) + if err != nil { + return EntryInvalid, err + } + if err := validateCompositeFields(kv, histogramCompositeFields, raw); err != nil { + return EntryInvalid, err + } + + // schema is mandatory for native histograms and absent from classic + // ones, so its presence is the sole reliable signal. + _, isNative := kv["schema"] + + if isNative { + h, fh, err := buildNativeHistogram(kv, p.mtype == model.MetricTypeGaugeHistogram) + if err != nil { + return EntryInvalid, fmt.Errorf("error parsing native histogram composite: %w", err) + } + p.h = h + p.fh = fh + // When the composite also carries a classic bucket list and the + // caller asked to keep it, queue the classic flat series so that + // subsequent Next() calls drain them after the EntryHistogram. + if _, hasBucket := kv["bucket"]; hasBucket && p.keepClassicOnNativeHist { + pending, err := p.buildClassicHistogramPending(kv, p.hasTS, p.ts) + if err != nil { + return EntryInvalid, fmt.Errorf("error parsing classic histogram composite: %w", err) + } + p.pending = pending + p.pendingIdx = 0 + } + return EntryHistogram, nil + } + + // Classic histogram: explode into flat pending entries. + pending, err := p.buildClassicHistogramPending(kv, p.hasTS, p.ts) + if err != nil { + return EntryInvalid, fmt.Errorf("error parsing classic histogram composite: %w", err) + } + return p.servePending(pending) +} + +// parseSummaryComposite parses a composite summary value such as: +// +// {count:12,sum:5.5,quantile:[0.5:1.0,0.9:2.0,0.99:3.0]} +func (p *OpenMetrics2Parser) parseSummaryComposite(raw []byte) (Entry, error) { + kv, err := kvMap(raw) + if err != nil { + return EntryInvalid, err + } + if err := validateCompositeFields(kv, summaryCompositeFields, raw); err != nil { + return EntryInvalid, err + } + + pending, err := p.buildSummaryPending(kv, p.hasTS, p.ts) + if err != nil { + return EntryInvalid, fmt.Errorf("error parsing summary composite: %w", err) + } + return p.servePending(pending) +} + +// servePending stores pending and returns the first entry. +func (p *OpenMetrics2Parser) servePending(pending []pendingEntry) (Entry, error) { + if len(pending) == 0 { + return EntryInvalid, errors.New("composite value produced no series") + } + p.pending = pending + p.pendingIdx = 1 // we are about to serve pending[0] + return EntrySeries, nil +} + +func buildNativeHistogram(kv map[string]string, isGauge bool) (*histogram.Histogram, *histogram.FloatHistogram, error) { + getFloat := func(key string) (float64, bool, error) { + v, ok := kv[key] + if !ok { + return 0, false, nil + } + f, err := strconv.ParseFloat(v, 64) + return f, true, err + } + getInt := func(key string) (int64, bool, error) { + v, ok := kv[key] + if !ok { + return 0, false, nil + } + n, err := strconv.ParseInt(v, 10, 64) + return n, true, err + } + + // schema is guaranteed present: the caller only reaches buildNativeHistogram + // when kv["schema"] exists. + schema64, _, err := getInt("schema") + if err != nil { + return nil, nil, fmt.Errorf("invalid schema: %w", err) + } + // Schema values outside [-4, 8] are reserved for future use and MUST NOT + // be used. + if schema64 < -4 || schema64 > 8 { + return nil, nil, fmt.Errorf("schema must be between -4 and 8, got %d", schema64) + } + + countKey, sumKey := "count", "sum" + if isGauge { + countKey, sumKey = "gcount", "gsum" + } + count, ok, err := getFloat(countKey) + if err != nil { + return nil, nil, fmt.Errorf("invalid %s: %w", countKey, err) + } + if !ok { + return nil, nil, fmt.Errorf("missing required field: %s", countKey) + } + sum, ok, err := getFloat(sumKey) + if err != nil { + return nil, nil, fmt.Errorf("invalid %s: %w", sumKey, err) + } + if !ok { + return nil, nil, fmt.Errorf("missing required field: %s", sumKey) + } + zeroThreshold, ok, err := getFloat("zero_threshold") + if err != nil { + return nil, nil, fmt.Errorf("invalid zero_threshold: %w", err) + } + if !ok { + return nil, nil, errors.New("missing required field: zero_threshold") + } + + if math.IsNaN(zeroThreshold) || math.IsInf(zeroThreshold, 0) || zeroThreshold < 0 { + return nil, nil, fmt.Errorf("zero_threshold must be a non-negative, finite number, got %v", zeroThreshold) + } + zeroCount, ok, err := getFloat("zero_count") + if err != nil { + return nil, nil, fmt.Errorf("invalid zero_count: %w", err) + } + if !ok { + return nil, nil, errors.New("missing required field: zero_count") + } + + // Treat as FloatHistogram if count, zero_count, or any bucket value is non-integer. + // sum is always float64 in both histogram types and does not determine the kind. + // Bucket strings are scanned for '.', 'e', or 'E' since OM2 emits floats with + // decimals or exponent notation; the cheap pre-scan avoids parsing buckets twice. + isFloat := count != math.Trunc(count) || zeroCount != math.Trunc(zeroCount) || + bucketsHaveFloat(kv["positive_buckets"]) || bucketsHaveFloat(kv["negative_buckets"]) + + posSpans, err := parseSpans(kv["positive_spans"]) + if err != nil { + return nil, nil, fmt.Errorf("invalid positive_spans: %w", err) + } + negSpans, err := parseSpans(kv["negative_spans"]) + if err != nil { + return nil, nil, fmt.Errorf("invalid negative_spans: %w", err) + } + + if isFloat { + posBuckets, err := parseFloatBuckets(kv["positive_buckets"]) + if err != nil { + return nil, nil, fmt.Errorf("invalid positive_buckets: %w", err) + } + negBuckets, err := parseFloatBuckets(kv["negative_buckets"]) + if err != nil { + return nil, nil, fmt.Errorf("invalid negative_buckets: %w", err) + } + fh := &histogram.FloatHistogram{ + Schema: int32(schema64), + ZeroThreshold: zeroThreshold, + ZeroCount: zeroCount, + Count: count, + Sum: sum, + PositiveSpans: posSpans, + NegativeSpans: negSpans, + PositiveBuckets: posBuckets, + NegativeBuckets: negBuckets, + } + if isGauge { + fh.CounterResetHint = histogram.GaugeType + } + if err := fh.Validate(); err != nil { + return nil, nil, fmt.Errorf("invalid float histogram: %w", err) + } + return nil, fh, nil + } + + posBuckets, err := parseIntBuckets(kv["positive_buckets"]) + if err != nil { + return nil, nil, fmt.Errorf("invalid positive_buckets: %w", err) + } + negBuckets, err := parseIntBuckets(kv["negative_buckets"]) + if err != nil { + return nil, nil, fmt.Errorf("invalid negative_buckets: %w", err) + } + absoluteToIntDeltas(posBuckets) + absoluteToIntDeltas(negBuckets) + h := &histogram.Histogram{ + Schema: int32(schema64), + ZeroThreshold: zeroThreshold, + ZeroCount: uint64(zeroCount), + Count: uint64(count), + Sum: sum, + PositiveSpans: posSpans, + NegativeSpans: negSpans, + PositiveBuckets: posBuckets, + NegativeBuckets: negBuckets, + } + if isGauge { + h.CounterResetHint = histogram.GaugeType + } + if err := h.Validate(); err != nil { + return nil, nil, fmt.Errorf("invalid histogram: %w", err) + } + return h, nil, nil +} + +// absoluteToIntDeltas converts a slice of absolute bucket counts (OM2 format) +// to the delta-encoded form expected by Prometheus internally. Operates in-place +// back-to-front to avoid overwriting values still needed. +func absoluteToIntDeltas(abs []int64) { + for i := len(abs) - 1; i > 0; i-- { + abs[i] -= abs[i-1] + } +} + +// parseSpans parses "[offset:length,...]" into a []histogram.Span. +func parseSpans(s string) ([]histogram.Span, error) { + s = strings.TrimSpace(s) + if s == "" || s == "[]" { + return nil, nil + } + if len(s) < 2 || s[0] != '[' || s[len(s)-1] != ']' { + return nil, fmt.Errorf("spans must be wrapped in []: %q", s) + } + inner := s[1 : len(s)-1] + if strings.TrimSpace(inner) == "" { + return nil, nil + } + var spans []histogram.Span + for part := range strings.SplitSeq(inner, ",") { + part = strings.TrimSpace(part) + if part == "" { + continue + } + before, after, ok := strings.Cut(part, ":") + if !ok { + return nil, fmt.Errorf("span missing ':': %q", part) + } + offset, err := strconv.ParseInt(strings.TrimSpace(before), 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid span offset %q: %w", before, err) + } + length, err := strconv.ParseUint(strings.TrimSpace(after), 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid span length %q: %w", after, err) + } + spans = append(spans, histogram.Span{Offset: int32(offset), Length: uint32(length)}) + } + return spans, nil +} + +// bucketsHaveFloat reports whether the raw bucket string contains any non-integer +// value. OM2 formats floats with a decimal point or exponent, so a byte-level scan +// for '.', 'e', or 'E' is sufficient to discriminate integer from float buckets. +func bucketsHaveFloat(s string) bool { + for i := 0; i < len(s); i++ { + switch s[i] { + case '.', 'e', 'E': + return true + } + } + return false +} + +// parseIntBuckets parses "[b1,b2,...]" into delta-encoded []int64 buckets. +func parseIntBuckets(s string) ([]int64, error) { + s = strings.TrimSpace(s) + if s == "" || s == "[]" { + return nil, nil + } + if len(s) < 2 || s[0] != '[' || s[len(s)-1] != ']' { + return nil, fmt.Errorf("buckets must be wrapped in []: %q", s) + } + inner := s[1 : len(s)-1] + if strings.TrimSpace(inner) == "" { + return nil, nil + } + var buckets []int64 + for part := range strings.SplitSeq(inner, ",") { + part = strings.TrimSpace(part) + if part == "" { + continue + } + b, err := strconv.ParseInt(part, 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid bucket %q: %w", part, err) + } + buckets = append(buckets, b) + } + return buckets, nil +} + +// parseFloatBuckets parses "[b1,b2,...]" into []float64 bucket values. +func parseFloatBuckets(s string) ([]float64, error) { + s = strings.TrimSpace(s) + if s == "" || s == "[]" { + return nil, nil + } + if len(s) < 2 || s[0] != '[' || s[len(s)-1] != ']' { + return nil, fmt.Errorf("float buckets must be wrapped in []: %q", s) + } + inner := s[1 : len(s)-1] + if strings.TrimSpace(inner) == "" { + return nil, nil + } + var buckets []float64 + for part := range strings.SplitSeq(inner, ",") { + part = strings.TrimSpace(part) + if part == "" { + continue + } + b, err := strconv.ParseFloat(part, 64) + if err != nil { + return nil, fmt.Errorf("invalid float bucket %q: %w", part, err) + } + buckets = append(buckets, b) + } + return buckets, nil +} + +func (p *OpenMetrics2Parser) buildClassicHistogramPending( + kv map[string]string, + hasTS bool, + ts int64, +) ([]pendingEntry, error) { + mfName, extraLabels := p.nameAndExtraLabelsFromOffsets() + + var tsPtr *int64 + if hasTS { + tsPtr = &ts + } + + // p.pending has been reset to [:0] by Next() before any parsing begins, + // so we reuse its backing array across composite parses. + pending := p.pending + + // GaugeHistogram Samples with Classic Buckets expose count/sum as + // gcount/gsum, mirroring Count/Sum's role for a plain Histogram. + // https://prometheus.io/docs/specs/om/open_metrics_spec_2_0/#gaugehistogram-1 + countKey, sumKey := "count", "sum" + countSuffix, sumSuffix := "_count", "_sum" + if p.mtype == model.MetricTypeGaugeHistogram { + countKey, sumKey = "gcount", "gsum" + countSuffix, sumSuffix = "_gcount", "_gsum" + } + + cv, ok := kv[countKey] + if !ok { + return nil, fmt.Errorf("missing required field: %s", countKey) + } + v, err := strconv.ParseFloat(cv, 64) + if err != nil { + return nil, fmt.Errorf("invalid %s: %w", countKey, err) + } + name := mfName + countSuffix + lset := p.buildPendingLabels(name, extraLabels, "", "") + pending = append(pending, pendingEntry{ + series: p.appendSeriesBytes(lset), + lset: lset, + val: v, + ts: tsPtr, + }) + + sv, ok := kv[sumKey] + if !ok { + return nil, fmt.Errorf("missing required field: %s", sumKey) + } + v, err = strconv.ParseFloat(sv, 64) + if err != nil { + return nil, fmt.Errorf("invalid %s: %w", sumKey, err) + } + name = mfName + sumSuffix + lset = p.buildPendingLabels(name, extraLabels, "", "") + pending = append(pending, pendingEntry{ + series: p.appendSeriesBytes(lset), + lset: lset, + val: v, + ts: tsPtr, + }) + + // _bucket entries. The spec requires a Classic Bucket list to include a + // +Inf threshold. + bv, ok := kv["bucket"] + if !ok { + return nil, errors.New("missing required field: bucket") + } + name = mfName + "_bucket" + hasPosInf := false + for b, err := range parseBuckets(bv) { + if err != nil { + return nil, fmt.Errorf("invalid bucket: %w", err) + } + if b.le == "+Inf" { + hasPosInf = true + } + lset := p.buildPendingLabels(name, extraLabels, "le", b.le) + pending = append(pending, pendingEntry{ + series: p.appendSeriesBytes(lset), + lset: lset, + val: b.count, + ts: tsPtr, + }) + } + if !hasPosInf { + return nil, errors.New("classic histogram buckets must include a +Inf threshold") + } + + return pending, nil +} + +func (p *OpenMetrics2Parser) buildSummaryPending( + kv map[string]string, + hasTS bool, + ts int64, +) ([]pendingEntry, error) { + mfName, extraLabels := p.nameAndExtraLabelsFromOffsets() + + var tsPtr *int64 + if hasTS { + tsPtr = &ts + } + + // p.pending has been reset to [:0] by Next() before any parsing begins, + // so we reuse its backing array across composite parses. + pending := p.pending + + cv, ok := kv["count"] + if !ok { + return nil, errors.New("missing required field: count") + } + v, err := strconv.ParseFloat(cv, 64) + if err != nil { + return nil, fmt.Errorf("invalid count: %w", err) + } + name := mfName + "_count" + lset := p.buildPendingLabels(name, extraLabels, "", "") + pending = append(pending, pendingEntry{ + series: p.appendSeriesBytes(lset), + lset: lset, + val: v, + ts: tsPtr, + }) + + sv, ok := kv["sum"] + if !ok { + return nil, errors.New("missing required field: sum") + } + v, err = strconv.ParseFloat(sv, 64) + if err != nil { + return nil, fmt.Errorf("invalid sum: %w", err) + } + name = mfName + "_sum" + lset = p.buildPendingLabels(name, extraLabels, "", "") + pending = append(pending, pendingEntry{ + series: p.appendSeriesBytes(lset), + lset: lset, + val: v, + ts: tsPtr, + }) + + qv, ok := kv["quantile"] + if !ok { + return nil, errors.New("missing required field: quantile") + } + for q, err := range parseQuantiles(qv) { + if err != nil { + return nil, fmt.Errorf("invalid quantile: %w", err) + } + lset := p.buildPendingLabels(mfName, extraLabels, "quantile", q.q) + pending = append(pending, pendingEntry{ + series: p.appendSeriesBytes(lset), + lset: lset, + val: q.val, + ts: tsPtr, + }) + } + + return pending, nil +} + +// nameAndExtraLabelsFromOffsets returns the metric family name and the extra +// (non metric name) labels for the line currently being parsed, reusing the +// offsets parseLVals already computed. +func (p *OpenMetrics2Parser) nameAndExtraLabelsFromOffsets() (string, []labels.Label) { + s := string(p.series) + name := unreplace(s[p.offsets[0]-p.start : p.offsets[1]-p.start]) + if len(p.offsets) <= 2 { + return name, nil + } + extra := make([]labels.Label, 0, (len(p.offsets)-2)/4) + for i := 2; i < len(p.offsets); i += 4 { + k := unreplace(s[p.offsets[i]-p.start : p.offsets[i+1]-p.start]) + v := unreplace(s[p.offsets[i+2]-p.start : p.offsets[i+3]-p.start]) + extra = append(extra, labels.Label{Name: k, Value: v}) + } + return name, extra +} + +// appendSeriesBytes returns a byte identity for lset, unique per distinct +// label set, appended into the shared p.seriesBuf (reset per batch in Next(), +// so sub-slices stay valid until then). Mirrors +// ProtobufParser.onSeriesOrHistogramUpdate's entryBytes. +func (p *OpenMetrics2Parser) appendSeriesBytes(lset labels.Labels) []byte { + start := len(p.seriesBuf) + lset.Range(func(l labels.Label) { + if l.Name == labels.MetricName { + p.seriesBuf = append(p.seriesBuf, l.Value...) + return + } + p.seriesBuf = append(p.seriesBuf, model.SeparatorByte) + p.seriesBuf = append(p.seriesBuf, l.Name...) + p.seriesBuf = append(p.seriesBuf, model.SeparatorByte) + p.seriesBuf = append(p.seriesBuf, l.Value...) + }) + return p.seriesBuf[start:len(p.seriesBuf):len(p.seriesBuf)] +} + +// buildPendingLabels builds labels for a pending entry, reusing p.builder so +// successive calls (one per bucket/quantile) avoid allocating a fresh Builder +// each time. injectKey and injectVal are the extra label to inject (e.g. +// "le"/"quantile") — pass empty strings for _count and _sum series. +// +// p.builder must not be in use elsewhere while this runs; it is safe to call +// once parseAfterValue has finished consuming the line (any exemplar labels +// have already been materialised into their own labels.Labels values). +func (p *OpenMetrics2Parser) buildPendingLabels(name string, extra []labels.Label, injectKey, injectVal string) labels.Labels { + p.builder.Reset() + m := schema.Metadata{Name: name, Type: p.mtype, Unit: p.unit} + if p.enableTypeAndUnitLabels { + m.AddToLabels(&p.builder) + } else { + p.builder.Add(model.MetricNameLabel, name) + } + for _, l := range extra { + if p.enableTypeAndUnitLabels && !m.IsEmptyFor(l.Name) { + continue + } + p.builder.Add(l.Name, l.Value) + } + if injectKey != "" { + p.builder.Add(injectKey, injectVal) + } + p.builder.Sort() + return p.builder.Labels() +} + +// bucketEntry holds one parsed classic histogram bucket. +type bucketEntry struct { + le string + count float64 +} + +// parseBuckets yields each entry from "[+Inf:12,1.0:3,2.0:7]" without +// materialising an intermediate slice. +func parseBuckets(s string) iter.Seq2[bucketEntry, error] { + return func(yield func(bucketEntry, error) bool) { + s = strings.TrimSpace(s) + if s == "" || s == "[]" { + return + } + if len(s) < 2 || s[0] != '[' || s[len(s)-1] != ']' { + yield(bucketEntry{}, fmt.Errorf("bucket must be wrapped in []: %q", s)) + return + } + inner := s[1 : len(s)-1] + prevLe := math.Inf(-1) + for part := range strings.SplitSeq(inner, ",") { + part = strings.TrimSpace(part) + if part == "" { + continue + } + idx := strings.LastIndexByte(part, ':') + if idx < 0 { + yield(bucketEntry{}, fmt.Errorf("bucket missing ':': %q", part)) + return + } + le := strings.TrimSpace(part[:idx]) + count, err := strconv.ParseFloat(strings.TrimSpace(part[idx+1:]), 64) + if err != nil { + yield(bucketEntry{}, fmt.Errorf("invalid bucket count %q: %w", part[idx+1:], err)) + return + } + // Normalise le to OpenMetrics float format. + if lef, err := strconv.ParseFloat(le, 64); err == nil { + if lef <= prevLe { + yield(bucketEntry{}, fmt.Errorf("classic histogram buckets must be sorted in increasing order: %q", part)) + return + } + prevLe = lef + le = labels.FormatOpenMetricsFloat(lef) + } + if !yield(bucketEntry{le: le, count: count}, nil) { + return + } + } + } +} + +// quantileEntry holds one parsed summary quantile. +type quantileEntry struct { + q string + val float64 +} + +// parseQuantiles yields each entry from "[0.5:1.0,0.9:2.0]" without +// materialising an intermediate slice. +func parseQuantiles(s string) iter.Seq2[quantileEntry, error] { + return func(yield func(quantileEntry, error) bool) { + s = strings.TrimSpace(s) + if s == "" || s == "[]" { + return + } + if len(s) < 2 || s[0] != '[' || s[len(s)-1] != ']' { + yield(quantileEntry{}, fmt.Errorf("quantile must be wrapped in []: %q", s)) + return + } + inner := s[1 : len(s)-1] + prevQ := math.Inf(-1) + for part := range strings.SplitSeq(inner, ",") { + part = strings.TrimSpace(part) + if part == "" { + continue + } + before, after, ok := strings.Cut(part, ":") + if !ok { + yield(quantileEntry{}, fmt.Errorf("quantile missing ':': %q", part)) + return + } + q := strings.TrimSpace(before) + val, err := strconv.ParseFloat(strings.TrimSpace(after), 64) + if err != nil { + yield(quantileEntry{}, fmt.Errorf("invalid quantile value %q: %w", after, err)) + return + } + // Normalise quantile label to OpenMetrics float format. + if qf, err := strconv.ParseFloat(q, 64); err == nil { + if qf <= prevQ { + yield(quantileEntry{}, fmt.Errorf("quantiles must be sorted in increasing order: %q", part)) + return + } + prevQ = qf + q = labels.FormatOpenMetricsFloat(qf) + } + if !yield(quantileEntry{q: q, val: val}, nil) { + return + } + } + } +} diff --git a/vendor/github.com/prometheus/prometheus/model/textparse/promparse.go b/vendor/github.com/prometheus/prometheus/model/textparse/promparse.go index 24211c4..8264f06 100644 --- a/vendor/github.com/prometheus/prometheus/model/textparse/promparse.go +++ b/vendor/github.com/prometheus/prometheus/model/textparse/promparse.go @@ -68,6 +68,7 @@ const ( tEqual tTimestamp tValue + tStartTimestamp ) func (t token) String() string { @@ -114,6 +115,8 @@ func (t token) String() string { return "TIMESTAMP" case tValue: return "VALUE" + case tStartTimestamp: + return "STARTTIMESTAMP" } return fmt.Sprintf("", t) } diff --git a/vendor/github.com/prometheus/prometheus/model/textparse/protobufparse.go b/vendor/github.com/prometheus/prometheus/model/textparse/protobufparse.go index f0537b2..95d78c7 100644 --- a/vendor/github.com/prometheus/prometheus/model/textparse/protobufparse.go +++ b/vendor/github.com/prometheus/prometheus/model/textparse/protobufparse.go @@ -498,6 +498,7 @@ func (p *ProtobufParser) Next() (Entry, error) { // Potentially a second series in the metric family. t := p.dec.GetType() decodeNext := true + mustCheckNextSeriesKind := false if t == dto.MetricType_SUMMARY || t == dto.MetricType_HISTOGRAM || t == dto.MetricType_GAUGE_HISTOGRAM { @@ -523,18 +524,13 @@ func (p *ProtobufParser) Next() (Entry, error) { p.fieldsDone = false p.exemplarPos = 0 - // If this is a metric family containing native - // histograms, it means we are here thanks to redoClassic state. - // Return to native histograms for the consistent flow. - // If this is a metric family containing classic histograms, - // it means we might need to do NHCB conversion. + // If this is a metric family containing classic histograms + // and NHCB conversion is enabled, emit the NHCB for the + // current series without advancing. We do not advance + // because the NHCB is derived from the current series and + // must be emitted before moving to the next one. if t == dto.MetricType_HISTOGRAM || t == dto.MetricType_GAUGE_HISTOGRAM { - if !isClassicHistogram { - if err := checkNativeHistogramConsistency(p.dec.GetHistogram()); err != nil { - return EntryInvalid, fmt.Errorf("histogram %q: %w", p.dec.GetName(), err) - } - p.state = EntryHistogram - } else if p.convertClassicHistogramsToNHCB { + if isClassicHistogram && p.convertClassicHistogramsToNHCB { // We still need to spit out the NHCB. var err error p.nhcbH, p.nhcbFH, err = p.convertToNHCB(t) @@ -544,6 +540,10 @@ func (p *ProtobufParser) Next() (Entry, error) { p.state = EntryHistogram // We have an NHCB to emit, no need to decode the next series. decodeNext = false + } else { + // The next series in this metric family may be native or + // classic-only, and we cannot tell which without advancing it. + mustCheckNextSeriesKind = true } } } @@ -556,6 +556,25 @@ func (p *ProtobufParser) Next() (Entry, error) { } return EntryInvalid, err } + if mustCheckNextSeriesKind { + // The previous series was a native histogram whose + // classic fields were emitted via redoClassic. + // + // If the current series is classic only then we need to + // iterate _count, _sum, and all buckets, emitting a + // series per each. + if p.ignoreNativeHistograms || !isNativeHistogram(p.dec.GetHistogram()) { + p.fieldPos = -3 + p.fieldsDone = false + return p.Next() + } + // If the current series is a native histogram then we + // simply emit it. + if err := checkNativeHistogramConsistency(p.dec.GetHistogram()); err != nil { + return EntryInvalid, fmt.Errorf("histogram %q: %w", p.dec.GetName(), err) + } + p.state = EntryHistogram + } } if err := p.onSeriesOrHistogramUpdate(); err != nil { return EntryInvalid, err diff --git a/vendor/github.com/prometheus/prometheus/prompb/io/prometheus/client/metrics.pb.go b/vendor/github.com/prometheus/prometheus/prompb/io/prometheus/client/metrics.pb.go index 5b47756..e94019b 100644 --- a/vendor/github.com/prometheus/prometheus/prompb/io/prometheus/client/metrics.pb.go +++ b/vendor/github.com/prometheus/prometheus/prompb/io/prometheus/client/metrics.pb.go @@ -982,69 +982,68 @@ func init() { } var fileDescriptor_d1e5ddb18987a258 = []byte{ - // 982 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xdf, 0x6e, 0xe3, 0xc4, - 0x1b, 0x5d, 0x6f, 0xfe, 0xfa, 0x4b, 0x93, 0x66, 0xe7, 0x17, 0xad, 0xac, 0xfe, 0x68, 0x13, 0x2c, - 0x21, 0x15, 0x84, 0x12, 0x01, 0x8b, 0x40, 0x4b, 0x91, 0x68, 0xbb, 0xdd, 0x2e, 0x5a, 0xb2, 0xbb, - 0x4c, 0x92, 0x8b, 0xe5, 0xc6, 0x9a, 0xa4, 0xd3, 0xc4, 0xc2, 0xf6, 0x18, 0x7b, 0xbc, 0xa2, 0xdc, - 0xf3, 0x0c, 0xdc, 0xf2, 0x20, 0x5c, 0xa3, 0xbd, 0x44, 0x3c, 0x00, 0x42, 0x7d, 0x0a, 0x2e, 0xd1, - 0xfc, 0xb3, 0xd3, 0x95, 0x53, 0x88, 0xb8, 0xf3, 0x1c, 0x9f, 0x33, 0x73, 0xbe, 0x63, 0xfb, 0xfb, - 0x0c, 0xae, 0xcf, 0x46, 0x71, 0xc2, 0x42, 0xca, 0x57, 0x34, 0x4b, 0x47, 0x8b, 0xc0, 0xa7, 0x11, - 0x1f, 0x85, 0x94, 0x27, 0xfe, 0x22, 0x1d, 0xc6, 0x09, 0xe3, 0x0c, 0xf5, 0x7c, 0x36, 0x2c, 0x38, - 0x43, 0xc5, 0xd9, 0xeb, 0x2d, 0xd9, 0x92, 0x49, 0xc2, 0x48, 0x5c, 0x29, 0xee, 0x5e, 0x7f, 0xc9, - 0xd8, 0x32, 0xa0, 0x23, 0xb9, 0x9a, 0x67, 0x97, 0x23, 0xee, 0x87, 0x34, 0xe5, 0x24, 0x8c, 0x15, - 0xc1, 0xfd, 0x18, 0xec, 0xaf, 0xc8, 0x9c, 0x06, 0x2f, 0x88, 0x9f, 0x20, 0x04, 0xd5, 0x88, 0x84, - 0xd4, 0xb1, 0x06, 0xd6, 0xa1, 0x8d, 0xe5, 0x35, 0xea, 0x41, 0xed, 0x15, 0x09, 0x32, 0xea, 0xdc, - 0x95, 0xa0, 0x5a, 0xb8, 0xfb, 0x50, 0x3b, 0x27, 0xd9, 0x72, 0xed, 0xb6, 0xd0, 0x58, 0xe6, 0xf6, - 0xcf, 0x16, 0x34, 0x4e, 0x59, 0x16, 0x71, 0x9a, 0x94, 0x33, 0xd0, 0x43, 0x68, 0xd2, 0xef, 0x69, - 0x18, 0x07, 0x24, 0x91, 0x3b, 0xb7, 0x3e, 0x3c, 0x18, 0x96, 0xd5, 0x35, 0x3c, 0xd3, 0x2c, 0x9c, - 0xf3, 0xd1, 0x29, 0xec, 0xa6, 0x9c, 0x24, 0xdc, 0xcb, 0x8b, 0x71, 0x2a, 0x72, 0x8b, 0xbd, 0xa1, - 0x2a, 0x77, 0x68, 0xca, 0x1d, 0x4e, 0x0d, 0x03, 0x77, 0xa4, 0x24, 0x5f, 0xbb, 0x47, 0xd0, 0xfc, - 0x3a, 0x23, 0x11, 0xf7, 0x03, 0x8a, 0xf6, 0xa0, 0xf9, 0x9d, 0xbe, 0xd6, 0x2e, 0xf3, 0xf5, 0xcd, - 0xfa, 0xf3, 0x02, 0x7f, 0xb7, 0xa0, 0x31, 0xc9, 0xc2, 0x90, 0x24, 0x57, 0xe8, 0x6d, 0xd8, 0x49, - 0x49, 0x18, 0x07, 0xd4, 0x5b, 0x88, 0x92, 0xe5, 0x0e, 0x55, 0xdc, 0x52, 0x98, 0x4c, 0x01, 0xed, - 0x03, 0x68, 0x4a, 0x9a, 0x85, 0x7a, 0x27, 0x5b, 0x21, 0x93, 0x2c, 0x44, 0x5f, 0xac, 0x9d, 0x5f, - 0x19, 0x54, 0x36, 0x87, 0x61, 0x1c, 0x9f, 0x54, 0x5f, 0xff, 0xd1, 0xbf, 0xb3, 0xe6, 0xb2, 0x24, - 0x92, 0xea, 0xd6, 0x91, 0xf4, 0xa1, 0x31, 0x8b, 0xf8, 0x55, 0x4c, 0x2f, 0x36, 0x3c, 0xd6, 0xbf, - 0x6a, 0x60, 0x3f, 0xf1, 0x53, 0xce, 0x96, 0x09, 0x09, 0xff, 0x4d, 0xdd, 0xef, 0x03, 0x5a, 0xa7, - 0x78, 0x97, 0x01, 0x23, 0x5c, 0x3a, 0xb3, 0x70, 0x77, 0x8d, 0xf8, 0x58, 0xe0, 0xff, 0x94, 0xd2, - 0x43, 0xa8, 0xcf, 0xb3, 0xc5, 0xb7, 0x94, 0xeb, 0x8c, 0xde, 0x2a, 0xcf, 0xe8, 0x44, 0x72, 0x74, - 0x42, 0x5a, 0x51, 0x96, 0xcf, 0xee, 0xb6, 0xf9, 0xa0, 0xfb, 0x50, 0x4f, 0x17, 0x2b, 0x1a, 0x12, - 0xa7, 0x36, 0xb0, 0x0e, 0xef, 0x61, 0xbd, 0x42, 0xef, 0x40, 0xe7, 0x07, 0x9a, 0x30, 0x8f, 0xaf, - 0x12, 0x9a, 0xae, 0x58, 0x70, 0xe1, 0xd4, 0xa5, 0xf7, 0xb6, 0x40, 0xa7, 0x06, 0x14, 0xe5, 0x49, - 0x9a, 0x4a, 0xab, 0x21, 0xd3, 0xb2, 0x05, 0xa2, 0xb2, 0x3a, 0x84, 0x6e, 0x71, 0x5b, 0x27, 0xd5, - 0x94, 0xfb, 0x74, 0x72, 0x92, 0xca, 0xe9, 0x29, 0xb4, 0x23, 0xba, 0x24, 0xdc, 0x7f, 0x45, 0xbd, - 0x34, 0x26, 0x91, 0x63, 0xcb, 0x3c, 0x06, 0xb7, 0xe5, 0x31, 0x89, 0x49, 0xa4, 0x33, 0xd9, 0x31, - 0x62, 0x81, 0x09, 0xf3, 0xf9, 0x66, 0x17, 0x34, 0xe0, 0xc4, 0x81, 0x41, 0xe5, 0x10, 0xe1, 0xfc, - 0x88, 0x47, 0x02, 0xbc, 0x41, 0x53, 0x05, 0xb4, 0x06, 0x15, 0x51, 0xa3, 0x41, 0x55, 0x11, 0x4f, - 0xa1, 0x1d, 0xb3, 0xd4, 0x2f, 0xac, 0xed, 0x6c, 0x67, 0xcd, 0x88, 0x8d, 0xb5, 0x7c, 0x33, 0x65, - 0xad, 0xad, 0xac, 0x19, 0x34, 0xb7, 0x96, 0xd3, 0x94, 0xb5, 0x8e, 0xb2, 0x66, 0x50, 0x65, 0xed, - 0x08, 0x6c, 0xd3, 0x41, 0x52, 0xa7, 0x7b, 0xdb, 0x57, 0x96, 0xb7, 0x9c, 0x42, 0xe0, 0xfe, 0x6a, - 0x41, 0x5d, 0xd9, 0x45, 0xef, 0x42, 0x77, 0x91, 0x85, 0x59, 0xb0, 0x1e, 0x86, 0x7a, 0xf7, 0x77, - 0x0b, 0x5c, 0x9d, 0xf9, 0x00, 0xee, 0xbf, 0x49, 0xbd, 0xf1, 0x0d, 0xf4, 0xde, 0x10, 0xa8, 0xe7, - 0xdb, 0x87, 0x56, 0x16, 0xc7, 0x34, 0xf1, 0xe6, 0x2c, 0x8b, 0x2e, 0xf4, 0x87, 0x00, 0x12, 0x3a, - 0x11, 0xc8, 0x8d, 0xe6, 0x59, 0xd9, 0xae, 0x79, 0xba, 0x47, 0x00, 0x45, 0xec, 0xe2, 0x95, 0x66, - 0x97, 0x97, 0x29, 0x55, 0x15, 0xdc, 0xc3, 0x7a, 0x25, 0xf0, 0x80, 0x46, 0x4b, 0xbe, 0x92, 0xa7, - 0xb7, 0xb1, 0x5e, 0xb9, 0x3f, 0x59, 0xd0, 0x34, 0x9b, 0xa2, 0xcf, 0xa0, 0x16, 0x88, 0xd9, 0xe1, - 0x58, 0x32, 0xcd, 0x7e, 0xb9, 0x87, 0x7c, 0xbc, 0xe8, 0x67, 0xac, 0x34, 0xe5, 0x7d, 0x15, 0x7d, - 0x0a, 0xf6, 0x36, 0x4d, 0xbd, 0x20, 0xbb, 0x3f, 0x56, 0xa0, 0x3e, 0x96, 0x73, 0xf2, 0xbf, 0xf9, - 0xfa, 0x00, 0x6a, 0x4b, 0x31, 0xd9, 0xf4, 0x54, 0xfa, 0x7f, 0xb9, 0x58, 0x0e, 0x3f, 0xac, 0x98, - 0xe8, 0x13, 0x68, 0x2c, 0xd4, 0xb0, 0xd3, 0x96, 0xf7, 0xcb, 0x45, 0x7a, 0x22, 0x62, 0xc3, 0x16, - 0xc2, 0x54, 0x0d, 0x11, 0xdd, 0xad, 0x37, 0x08, 0xf5, 0xa4, 0xc1, 0x86, 0x2d, 0x84, 0x99, 0xea, - 0xd4, 0xb2, 0x15, 0x6d, 0x14, 0xea, 0x76, 0x8e, 0x0d, 0x1b, 0x7d, 0x0e, 0xf6, 0xca, 0x34, 0x70, - 0xd9, 0x82, 0x36, 0xc6, 0x93, 0xf7, 0x79, 0x5c, 0x28, 0x44, 0xcb, 0xcf, 0x13, 0xf7, 0xc2, 0x54, - 0xf6, 0xb9, 0x0a, 0x6e, 0xe5, 0xd8, 0x38, 0x75, 0x7f, 0xb1, 0x60, 0x47, 0x3d, 0x87, 0xc7, 0x24, - 0xf4, 0x83, 0xab, 0xd2, 0x9f, 0x0a, 0x04, 0xd5, 0x15, 0x0d, 0x62, 0xfd, 0x4f, 0x21, 0xaf, 0xd1, - 0x03, 0xa8, 0x0a, 0x8f, 0x32, 0xc2, 0xce, 0xa6, 0x8e, 0xa1, 0x76, 0x9e, 0x5e, 0xc5, 0x14, 0x4b, - 0xb6, 0x18, 0x0a, 0xea, 0xef, 0xc8, 0xa9, 0xde, 0x36, 0x14, 0x94, 0xce, 0x0c, 0x05, 0xa5, 0x10, - 0x2e, 0xb2, 0xc8, 0xe7, 0x32, 0x42, 0x1b, 0xcb, 0xeb, 0xf7, 0xe6, 0x00, 0xc5, 0x19, 0xa8, 0x05, - 0x8d, 0xd3, 0xe7, 0xb3, 0x67, 0xd3, 0x33, 0xdc, 0xbd, 0x83, 0x6c, 0xa8, 0x9d, 0x1f, 0xcf, 0xce, - 0xcf, 0xba, 0x96, 0xc0, 0x27, 0xb3, 0xf1, 0xf8, 0x18, 0xbf, 0xec, 0xde, 0x15, 0x8b, 0xd9, 0xb3, - 0xe9, 0xcb, 0x17, 0x67, 0x8f, 0xba, 0x15, 0xd4, 0x06, 0xfb, 0xc9, 0x97, 0x93, 0xe9, 0xf3, 0x73, - 0x7c, 0x3c, 0xee, 0x56, 0xd1, 0xff, 0x60, 0x57, 0x6a, 0xbc, 0x02, 0xac, 0x9d, 0xb8, 0xaf, 0xaf, - 0x0f, 0xac, 0xdf, 0xae, 0x0f, 0xac, 0x3f, 0xaf, 0x0f, 0xac, 0x6f, 0x7a, 0x3e, 0xf3, 0x0a, 0xc3, - 0x9e, 0x32, 0x3c, 0xaf, 0xcb, 0xb7, 0xfd, 0xa3, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xc9, 0xb8, - 0x2d, 0xa0, 0x11, 0x0a, 0x00, 0x00, + // 976 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xdd, 0x6e, 0xe3, 0x44, + 0x14, 0x5e, 0xaf, 0xf3, 0xe7, 0x93, 0x26, 0xcd, 0x0e, 0xd1, 0xca, 0x2a, 0xb4, 0x09, 0x96, 0x90, + 0x0a, 0x42, 0x89, 0x80, 0x45, 0xa0, 0xa5, 0x48, 0xb4, 0xdd, 0x6e, 0x17, 0x2d, 0xd9, 0x5d, 0x26, + 0xc9, 0xc5, 0x72, 0x63, 0x4d, 0xd2, 0xa9, 0x63, 0xe1, 0x3f, 0xec, 0xf1, 0x8a, 0x72, 0xcf, 0x33, + 0x70, 0xcb, 0x83, 0x70, 0x8d, 0xf6, 0x12, 0xf1, 0x00, 0x08, 0xf5, 0x29, 0xb8, 0x44, 0xf3, 0x67, + 0xa7, 0x2b, 0xb7, 0x34, 0xe2, 0x6e, 0xe6, 0xf3, 0x77, 0xce, 0x7c, 0xe7, 0x1b, 0xfb, 0x1c, 0x83, + 0xe3, 0xc7, 0xe3, 0x24, 0x8d, 0x43, 0xca, 0x56, 0x34, 0xcf, 0xc6, 0xcb, 0xc0, 0xa7, 0x11, 0x1b, + 0x87, 0x94, 0xa5, 0xfe, 0x32, 0x1b, 0x25, 0x69, 0xcc, 0x62, 0xd4, 0xf7, 0xe3, 0x51, 0xc9, 0x19, + 0x49, 0xce, 0x4e, 0xdf, 0x8b, 0xbd, 0x58, 0x10, 0xc6, 0x7c, 0x25, 0xb9, 0x3b, 0x03, 0x2f, 0x8e, + 0xbd, 0x80, 0x8e, 0xc5, 0x6e, 0x91, 0x9f, 0x8f, 0x99, 0x1f, 0xd2, 0x8c, 0x91, 0x30, 0x91, 0x04, + 0xe7, 0x53, 0xb0, 0xbe, 0x21, 0x0b, 0x1a, 0xbc, 0x20, 0x7e, 0x8a, 0x10, 0xd4, 0x22, 0x12, 0x52, + 0xdb, 0x18, 0x1a, 0xfb, 0x16, 0x16, 0x6b, 0xd4, 0x87, 0xfa, 0x2b, 0x12, 0xe4, 0xd4, 0xbe, 0x2b, + 0x40, 0xb9, 0x71, 0x76, 0xa1, 0x7e, 0x4a, 0x72, 0x6f, 0xed, 0x31, 0x8f, 0x31, 0xf4, 0xe3, 0x5f, + 0x0d, 0x68, 0x1e, 0xc7, 0x79, 0xc4, 0x68, 0x5a, 0xcd, 0x40, 0x0f, 0xa1, 0x45, 0x7f, 0xa4, 0x61, + 0x12, 0x90, 0x54, 0x64, 0x6e, 0x7f, 0xbc, 0x37, 0xaa, 0xaa, 0x6b, 0x74, 0xa2, 0x58, 0xb8, 0xe0, + 0xa3, 0x63, 0xd8, 0xce, 0x18, 0x49, 0x99, 0x5b, 0x14, 0x63, 0x9b, 0x22, 0xc5, 0xce, 0x48, 0x96, + 0x3b, 0xd2, 0xe5, 0x8e, 0x66, 0x9a, 0x81, 0xbb, 0x22, 0xa4, 0xd8, 0x3b, 0x07, 0xd0, 0xfa, 0x36, + 0x27, 0x11, 0xf3, 0x03, 0x8a, 0x76, 0xa0, 0xf5, 0x83, 0x5a, 0x2b, 0x95, 0xc5, 0xfe, 0x6a, 0xfd, + 0x45, 0x81, 0x7f, 0x1a, 0xd0, 0x9c, 0xe6, 0x61, 0x48, 0xd2, 0x0b, 0xf4, 0x2e, 0x6c, 0x65, 0x24, + 0x4c, 0x02, 0xea, 0x2e, 0x79, 0xc9, 0x22, 0x43, 0x0d, 0xb7, 0x25, 0x26, 0x5c, 0x40, 0xbb, 0x00, + 0x8a, 0x92, 0xe5, 0xa1, 0xca, 0x64, 0x49, 0x64, 0x9a, 0x87, 0xe8, 0xab, 0xb5, 0xf3, 0xcd, 0xa1, + 0x79, 0xbd, 0x19, 0x5a, 0xf1, 0x51, 0xed, 0xf5, 0x5f, 0x83, 0x3b, 0x6b, 0x2a, 0x2b, 0x2c, 0xa9, + 0x6d, 0x6c, 0xc9, 0x00, 0x9a, 0xf3, 0x88, 0x5d, 0x24, 0xf4, 0xec, 0x9a, 0x6b, 0xfd, 0xa7, 0x0e, + 0xd6, 0x13, 0x3f, 0x63, 0xb1, 0x97, 0x92, 0xf0, 0x36, 0x75, 0x7f, 0x08, 0x68, 0x9d, 0xe2, 0x9e, + 0x07, 0x31, 0x61, 0x42, 0x99, 0x81, 0x7b, 0x6b, 0xc4, 0xc7, 0x1c, 0xff, 0x2f, 0x97, 0x1e, 0x42, + 0x63, 0x91, 0x2f, 0xbf, 0xa7, 0x4c, 0x79, 0xf4, 0x4e, 0xb5, 0x47, 0x47, 0x82, 0xa3, 0x1c, 0x52, + 0x11, 0x55, 0xfe, 0x6c, 0x6f, 0xea, 0x0f, 0xba, 0x0f, 0x8d, 0x6c, 0xb9, 0xa2, 0x21, 0xb1, 0xeb, + 0x43, 0x63, 0xff, 0x1e, 0x56, 0x3b, 0xf4, 0x1e, 0x74, 0x7f, 0xa2, 0x69, 0xec, 0xb2, 0x55, 0x4a, + 0xb3, 0x55, 0x1c, 0x9c, 0xd9, 0x0d, 0xa1, 0xbd, 0xc3, 0xd1, 0x99, 0x06, 0x79, 0x79, 0x82, 0x26, + 0xdd, 0x6a, 0x0a, 0xb7, 0x2c, 0x8e, 0x48, 0xaf, 0xf6, 0xa1, 0x57, 0x3e, 0x56, 0x4e, 0xb5, 0x44, + 0x9e, 0x6e, 0x41, 0x92, 0x3e, 0x3d, 0x85, 0x4e, 0x44, 0x3d, 0xc2, 0xfc, 0x57, 0xd4, 0xcd, 0x12, + 0x12, 0xd9, 0x96, 0xf0, 0x63, 0x78, 0x93, 0x1f, 0xd3, 0x84, 0x44, 0xca, 0x93, 0x2d, 0x1d, 0xcc, + 0x31, 0x2e, 0xbe, 0x48, 0x76, 0x46, 0x03, 0x46, 0x6c, 0x18, 0x9a, 0xfb, 0x08, 0x17, 0x47, 0x3c, + 0xe2, 0xe0, 0x15, 0x9a, 0x2c, 0xa0, 0x3d, 0x34, 0x79, 0x8d, 0x1a, 0x95, 0x45, 0x3c, 0x85, 0x4e, + 0x12, 0x67, 0x7e, 0x29, 0x6d, 0x6b, 0x33, 0x69, 0x3a, 0x58, 0x4b, 0x2b, 0x92, 0x49, 0x69, 0x1d, + 0x29, 0x4d, 0xa3, 0x85, 0xb4, 0x82, 0x26, 0xa5, 0x75, 0xa5, 0x34, 0x8d, 0x4a, 0x69, 0x07, 0x60, + 0xe9, 0x0e, 0x92, 0xd9, 0xbd, 0xa1, 0x79, 0x8b, 0x96, 0x53, 0x06, 0x38, 0xbf, 0x1b, 0xd0, 0x90, + 0x72, 0xd1, 0xfb, 0xd0, 0x5b, 0xe6, 0x61, 0x1e, 0xac, 0x9b, 0x21, 0xdf, 0xfd, 0xed, 0x12, 0x97, + 0x67, 0x3e, 0x80, 0xfb, 0x6f, 0x52, 0xaf, 0x7c, 0x03, 0xfd, 0x37, 0x02, 0xe4, 0xfd, 0x0e, 0xa0, + 0x9d, 0x27, 0x09, 0x4d, 0xdd, 0x45, 0x9c, 0x47, 0x67, 0xea, 0x43, 0x00, 0x01, 0x1d, 0x71, 0xe4, + 0x4a, 0xf3, 0x34, 0x37, 0x6b, 0x9e, 0xce, 0x01, 0x40, 0x69, 0x3b, 0x7f, 0xa5, 0xe3, 0xf3, 0xf3, + 0x8c, 0xca, 0x0a, 0xee, 0x61, 0xb5, 0xe3, 0x78, 0x40, 0x23, 0x8f, 0xad, 0xc4, 0xe9, 0x1d, 0xac, + 0x76, 0xce, 0x2f, 0x06, 0xb4, 0x74, 0x52, 0xf4, 0x05, 0xd4, 0x03, 0x3e, 0x3b, 0x6c, 0x43, 0xb8, + 0x39, 0xa8, 0xd6, 0x50, 0x8c, 0x17, 0x75, 0xc7, 0x32, 0xa6, 0xba, 0xaf, 0xa2, 0xcf, 0xc1, 0xda, + 0xa4, 0xa9, 0x97, 0x64, 0xe7, 0x67, 0x13, 0x1a, 0x13, 0x31, 0x27, 0xff, 0x9f, 0xae, 0x8f, 0xa0, + 0xee, 0xf1, 0xc9, 0xa6, 0xa6, 0xd2, 0xdb, 0xd5, 0xc1, 0x62, 0xf8, 0x61, 0xc9, 0x44, 0x9f, 0x41, + 0x73, 0x29, 0x87, 0x9d, 0x92, 0xbc, 0x5b, 0x1d, 0xa4, 0x26, 0x22, 0xd6, 0x6c, 0x1e, 0x98, 0xc9, + 0x21, 0x62, 0xd7, 0x6e, 0x0a, 0x54, 0x93, 0x06, 0x6b, 0x36, 0x0f, 0xcc, 0x65, 0xa7, 0xb6, 0xeb, + 0x37, 0x05, 0xaa, 0x76, 0x8e, 0x35, 0x1b, 0x7d, 0x09, 0xd6, 0x4a, 0x37, 0x70, 0xd1, 0x82, 0xae, + 0xb5, 0xa7, 0xe8, 0xf3, 0xd8, 0x5a, 0xad, 0xb7, 0xfc, 0xc2, 0x71, 0x37, 0xcc, 0x44, 0x9f, 0x33, + 0x71, 0xbb, 0xc0, 0x26, 0x99, 0xf3, 0x9b, 0x01, 0x5b, 0xf2, 0x1e, 0x1e, 0x93, 0xd0, 0x0f, 0x2e, + 0x2a, 0x7f, 0x2a, 0x10, 0xd4, 0x56, 0x34, 0x48, 0xd4, 0x3f, 0x85, 0x58, 0xa3, 0x07, 0x50, 0xe3, + 0x1a, 0x85, 0x85, 0xdd, 0xeb, 0x3a, 0x86, 0xcc, 0x3c, 0xbb, 0x48, 0x28, 0x16, 0x6c, 0x3e, 0x14, + 0xe4, 0xdf, 0x91, 0x5d, 0xbb, 0x69, 0x28, 0xc8, 0x38, 0x3d, 0x14, 0x64, 0x04, 0x57, 0x91, 0x47, + 0x3e, 0x13, 0x16, 0x5a, 0x58, 0xac, 0x3f, 0x58, 0x00, 0x94, 0x67, 0xa0, 0x36, 0x34, 0x8f, 0x9f, + 0xcf, 0x9f, 0xcd, 0x4e, 0x70, 0xef, 0x0e, 0xb2, 0xa0, 0x7e, 0x7a, 0x38, 0x3f, 0x3d, 0xe9, 0x19, + 0x1c, 0x9f, 0xce, 0x27, 0x93, 0x43, 0xfc, 0xb2, 0x77, 0x97, 0x6f, 0xe6, 0xcf, 0x66, 0x2f, 0x5f, + 0x9c, 0x3c, 0xea, 0x99, 0xa8, 0x03, 0xd6, 0x93, 0xaf, 0xa7, 0xb3, 0xe7, 0xa7, 0xf8, 0x70, 0xd2, + 0xab, 0xa1, 0xb7, 0x60, 0x5b, 0xc4, 0xb8, 0x25, 0x58, 0x3f, 0x72, 0x5e, 0x5f, 0xee, 0x19, 0x7f, + 0x5c, 0xee, 0x19, 0x7f, 0x5f, 0xee, 0x19, 0xdf, 0xf5, 0xfd, 0xd8, 0x2d, 0x05, 0xbb, 0x52, 0xf0, + 0xa2, 0x21, 0xde, 0xf6, 0x4f, 0xfe, 0x1d, 0x00, 0xc9, 0xb8, 0x2d, 0xa0, 0x11, 0x0a, 0x00, 0x00, } func (m *LabelPair) Marshal() (dAtA []byte, err error) { diff --git a/vendor/modules.txt b/vendor/modules.txt index 263ef5a..ebc31f7 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -44,8 +44,8 @@ github.com/prometheus/common/model github.com/prometheus/procfs github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/parsers -# github.com/prometheus/prometheus v0.314.0 -## explicit; go 1.25.8 +# github.com/prometheus/prometheus v0.315.0 +## explicit; go 1.26.0 github.com/prometheus/prometheus/model/exemplar github.com/prometheus/prometheus/model/histogram github.com/prometheus/prometheus/model/labels @@ -61,8 +61,6 @@ github.com/sirupsen/logrus # github.com/xhit/go-str2duration/v2 v2.1.0 ## explicit; go 1.13 github.com/xhit/go-str2duration/v2 -# go.yaml.in/yaml/v2 v2.4.4 -## explicit; go 1.15 # golang.org/x/crypto v0.56.0 ## explicit; go 1.26.0 golang.org/x/crypto/blowfish