...block that contains 'thrpt' updated_files = [] for path in glob.glob(os.path.join(module, "**"), recursive=True): if os.path.isdir(path): continue + content = None try: with open(path, "r", encoding="utf-8") as f: content = f.read() - except Exception: + except (OSError, UnicodeError): + pass + if content is None: continue # quick filter if "
" not in content or "thrpt" not in content:
@@ -188,10 +190,10 @@ def update_pre_blocks_under_module(module: str, table: str) -> List[str]:
# This will match patterns like: " * ...
" and capture the prefix (e.g. " * ")
pattern = re.compile(r"(?m)^(?P[ \t]*\*[ \t]*)[\s\S]*?
")
- def repl(m: re.Match) -> str:
+ def repl(m: re.Match, replacement_table: str = filtered_table) -> str:
prefix = m.group("prefix")
# Build the new block with the same prefix on each line
- lines = filtered_table.splitlines()
+ lines = replacement_table.splitlines()
replaced = prefix + "\n"
for ln in lines:
replaced += prefix + ln.rstrip() + "\n"
@@ -207,7 +209,7 @@ def repl(m: re.Match) -> str:
return updated_files
-def main(argv: List[str]):
+def main(argv: list[str]):
parser = argparse.ArgumentParser()
parser.add_argument("--mvnw", default="./mvnw", help="Path to maven wrapper")
parser.add_argument(
diff --git a/mise.lock b/mise.lock
index 179dfef1d..8809f7764 100644
--- a/mise.lock
+++ b/mise.lock
@@ -172,43 +172,43 @@ url_api = "https://api.github.com/repos/grafana/oats/releases/assets/487171324"
provenance = "github-attestations"
[[tools."aqua:jonwiggins/xmloxide"]]
-version = "v0.4.3"
+version = "v0.4.4"
backend = "aqua:jonwiggins/xmloxide"
[tools."aqua:jonwiggins/xmloxide"."platforms.linux-arm64"]
-checksum = "sha256:abb840c558fdc94b4c1eddb1e4a3901d6c8129dcb76f387428dc2b30a7364967"
-url = "https://github.com/jonwiggins/xmloxide/releases/download/v0.4.3/xmllint_linux-aarch64"
-url_api = "https://api.github.com/repos/jonwiggins/xmloxide/releases/assets/411587060"
+checksum = "sha256:ec79d70f3e0483a54f1873b5ba36c3908c10eb77dd6c764363d232ed30c07809"
+url = "https://github.com/jonwiggins/xmloxide/releases/download/v0.4.4/xmllint_linux-aarch64"
+url_api = "https://api.github.com/repos/jonwiggins/xmloxide/releases/assets/484020867"
[tools."aqua:jonwiggins/xmloxide"."platforms.linux-arm64-musl"]
-checksum = "sha256:abb840c558fdc94b4c1eddb1e4a3901d6c8129dcb76f387428dc2b30a7364967"
-url = "https://github.com/jonwiggins/xmloxide/releases/download/v0.4.3/xmllint_linux-aarch64"
-url_api = "https://api.github.com/repos/jonwiggins/xmloxide/releases/assets/411587060"
+checksum = "sha256:ec79d70f3e0483a54f1873b5ba36c3908c10eb77dd6c764363d232ed30c07809"
+url = "https://github.com/jonwiggins/xmloxide/releases/download/v0.4.4/xmllint_linux-aarch64"
+url_api = "https://api.github.com/repos/jonwiggins/xmloxide/releases/assets/484020867"
[tools."aqua:jonwiggins/xmloxide"."platforms.linux-x64"]
-checksum = "sha256:46ccd30ff3a242b3d01ab72366cc3b6762882be604ebceaa32123a40d0af2dfc"
-url = "https://github.com/jonwiggins/xmloxide/releases/download/v0.4.3/xmllint_linux-x86-64"
-url_api = "https://api.github.com/repos/jonwiggins/xmloxide/releases/assets/411587058"
+checksum = "sha256:43220f57c69d0b8b10b883f11c2da17f66e854639aab84d331631d02ac220ff2"
+url = "https://github.com/jonwiggins/xmloxide/releases/download/v0.4.4/xmllint_linux-x86-64"
+url_api = "https://api.github.com/repos/jonwiggins/xmloxide/releases/assets/484020866"
[tools."aqua:jonwiggins/xmloxide"."platforms.linux-x64-musl"]
-checksum = "sha256:46ccd30ff3a242b3d01ab72366cc3b6762882be604ebceaa32123a40d0af2dfc"
-url = "https://github.com/jonwiggins/xmloxide/releases/download/v0.4.3/xmllint_linux-x86-64"
-url_api = "https://api.github.com/repos/jonwiggins/xmloxide/releases/assets/411587058"
+checksum = "sha256:43220f57c69d0b8b10b883f11c2da17f66e854639aab84d331631d02ac220ff2"
+url = "https://github.com/jonwiggins/xmloxide/releases/download/v0.4.4/xmllint_linux-x86-64"
+url_api = "https://api.github.com/repos/jonwiggins/xmloxide/releases/assets/484020866"
[tools."aqua:jonwiggins/xmloxide"."platforms.macos-arm64"]
-checksum = "sha256:6a2cb055e63ae97d75cd346c34138a9e31626e1dfc0983006c422c203b5cc288"
-url = "https://github.com/jonwiggins/xmloxide/releases/download/v0.4.3/xmllint_darwin-aarch64"
-url_api = "https://api.github.com/repos/jonwiggins/xmloxide/releases/assets/411587063"
+checksum = "sha256:bc93bca8c3d64d1aac2d0844966750b8d4529902624a46e42ea9b5ee9a99b0df"
+url = "https://github.com/jonwiggins/xmloxide/releases/download/v0.4.4/xmllint_darwin-aarch64"
+url_api = "https://api.github.com/repos/jonwiggins/xmloxide/releases/assets/484020870"
[tools."aqua:jonwiggins/xmloxide"."platforms.macos-x64"]
-checksum = "sha256:e83cbba88862d009405b5ce9e48025ff84b683a39a0832dde2db5395cb54734f"
-url = "https://github.com/jonwiggins/xmloxide/releases/download/v0.4.3/xmllint_darwin-x86-64"
-url_api = "https://api.github.com/repos/jonwiggins/xmloxide/releases/assets/411587061"
+checksum = "sha256:0f1d5955e8af0197e17f0da199321ef5f54adeb9c0f6a5acc35e122559239cb3"
+url = "https://github.com/jonwiggins/xmloxide/releases/download/v0.4.4/xmllint_darwin-x86-64"
+url_api = "https://api.github.com/repos/jonwiggins/xmloxide/releases/assets/484020868"
[tools."aqua:jonwiggins/xmloxide"."platforms.windows-x64"]
-checksum = "sha256:22872cad20b8ce8ccab28c42ce17acc9aa64b82cbad7d130ee74196cd74cd414"
-url = "https://github.com/jonwiggins/xmloxide/releases/download/v0.4.3/xmllint_windows-x86-64.exe"
-url_api = "https://api.github.com/repos/jonwiggins/xmloxide/releases/assets/411587062"
+checksum = "sha256:be3928e8d12e791996e1746a78ad61370d2ad83ea3036a30bb882205575f6823"
+url = "https://github.com/jonwiggins/xmloxide/releases/download/v0.4.4/xmllint_windows-x86-64.exe"
+url_api = "https://api.github.com/repos/jonwiggins/xmloxide/releases/assets/484020865"
[[tools."aqua:owenlamont/ryl"]]
version = "0.21.0"
@@ -251,49 +251,49 @@ url_api = "https://api.github.com/repos/owenlamont/ryl/releases/assets/454375990
provenance = "github-attestations"
[[tools.biome]]
-version = "2.5.3"
+version = "2.5.5"
backend = "aqua:biomejs/biome"
[tools.biome."platforms.linux-arm64"]
-checksum = "sha256:b642ded43aebcad738926b40eefd4dc2187a206d1fbfb37a45f1db4986804dbd"
-url = "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.5.3/biome-linux-arm64"
-url_api = "https://api.github.com/repos/biomejs/biome/releases/assets/470058837"
+checksum = "sha256:836d16eea672a4e92966e019582f606ef4a687496abbf6d547f31a5ef8a33548"
+url = "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.5.5/biome-linux-arm64"
+url_api = "https://api.github.com/repos/biomejs/biome/releases/assets/484416084"
provenance = "github-attestations"
[tools.biome."platforms.linux-arm64-musl"]
-checksum = "sha256:1a69ea4eb55baaec0bedd7d6ada3b1e626e2b430ecfc9a8f1b90373ca78aeb70"
-url = "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.5.3/biome-linux-arm64-musl"
-url_api = "https://api.github.com/repos/biomejs/biome/releases/assets/470058836"
+checksum = "sha256:0f487c28eca2c87e0eb79b73ad84c9fc0bbab6a6cf3513f5fedbc74ef2ca2d0b"
+url = "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.5.5/biome-linux-arm64-musl"
+url_api = "https://api.github.com/repos/biomejs/biome/releases/assets/484416087"
provenance = "github-attestations"
[tools.biome."platforms.linux-x64"]
-checksum = "sha256:ab8e74af2366127306e250652d2f32bd193601f208fcd0604112080c0ca3245b"
-url = "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.5.3/biome-linux-x64"
-url_api = "https://api.github.com/repos/biomejs/biome/releases/assets/470058832"
+checksum = "sha256:12ecb833102c8bf8ab6ede7ecd5b6e6fc76e8af95b3ef356933a1f5330afc028"
+url = "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.5.5/biome-linux-x64"
+url_api = "https://api.github.com/repos/biomejs/biome/releases/assets/484416085"
provenance = "github-attestations"
[tools.biome."platforms.linux-x64-musl"]
-checksum = "sha256:03cf125720b1d791093c9c68be34875d08638c314b3e1e63db1a45f2b418b1ca"
-url = "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.5.3/biome-linux-x64-musl"
-url_api = "https://api.github.com/repos/biomejs/biome/releases/assets/470058833"
+checksum = "sha256:549fea27c74212aaeb2c737346028facbcca7a93f66cf4aa145388dd8b18d7bc"
+url = "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.5.5/biome-linux-x64-musl"
+url_api = "https://api.github.com/repos/biomejs/biome/releases/assets/484416086"
provenance = "github-attestations"
[tools.biome."platforms.macos-arm64"]
-checksum = "sha256:610d3e1e770d373368d4ccee5a19c5e1735b0235024fcbed6ae07eb080d3bb09"
-url = "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.5.3/biome-darwin-arm64"
-url_api = "https://api.github.com/repos/biomejs/biome/releases/assets/470058834"
+checksum = "sha256:6072d68d3a4faf74c2802c106654904f2052f85675a3d1632213dd977a4b64bb"
+url = "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.5.5/biome-darwin-arm64"
+url_api = "https://api.github.com/repos/biomejs/biome/releases/assets/484416090"
provenance = "github-attestations"
[tools.biome."platforms.macos-x64"]
-checksum = "sha256:4df90556830ed35e6238e4b976b942d369a5378447c8d68b260b7a38e08b26f9"
-url = "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.5.3/biome-darwin-x64"
-url_api = "https://api.github.com/repos/biomejs/biome/releases/assets/470058835"
+checksum = "sha256:81f7f09a1ffacd225a65a29e2506ad02013b95964e684554cc5cc7ae9db005b4"
+url = "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.5.5/biome-darwin-x64"
+url_api = "https://api.github.com/repos/biomejs/biome/releases/assets/484416089"
provenance = "github-attestations"
[tools.biome."platforms.windows-x64"]
-checksum = "sha256:04c9ca46af43a0d060b22b21f94c7e1a9e8c57963a09778b8ff1d808ed536b31"
-url = "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.5.3/biome-win32-x64.exe"
-url_api = "https://api.github.com/repos/biomejs/biome/releases/assets/470058831"
+checksum = "sha256:f24c77f79d02dff42bfa4ee62e31b0522754d87eaaa3202435c7126cdb30ebd2"
+url = "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.5.5/biome-win32-x64.exe"
+url_api = "https://api.github.com/repos/biomejs/biome/releases/assets/484416083"
provenance = "github-attestations"
[[tools.editorconfig-checker]]
@@ -512,7 +512,7 @@ checksum = "sha256:0ae68406b42d7725661da979b1403ec9926da205c6770827f33aac9d8f26e
url = "https://nodejs.org/dist/v24.18.0/node-v24.18.0-win-x64.zip"
[[tools."npm:renovate"]]
-version = "43.257.4"
+version = "43.279.1"
backend = "npm:renovate"
[[tools.protoc]]
@@ -555,95 +555,95 @@ url = "https://github.com/protocolbuffers/protobuf/releases/download/v35.1/proto
url_api = "https://api.github.com/repos/protocolbuffers/protobuf/releases/assets/445060259"
[[tools.ruff]]
-version = "0.15.21"
+version = "0.16.0"
backend = "aqua:astral-sh/ruff"
[tools.ruff."platforms.linux-arm64"]
-checksum = "sha256:2ec7c0077431f96f74c3c72aea6505e902bc2ff47127653c8de1389ee30a3cb3"
-url = "https://github.com/astral-sh/ruff/releases/download/0.15.21/ruff-aarch64-unknown-linux-musl.tar.gz"
-url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/471700003"
+checksum = "sha256:7a6add3d38768dfa00c6d3853e9bd940b5526f3fbb76f02b1fe77ec0653f1e0e"
+url = "https://github.com/astral-sh/ruff/releases/download/0.16.0/ruff-aarch64-unknown-linux-musl.tar.gz"
+url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/487540070"
provenance = "github-attestations"
[tools.ruff."platforms.linux-arm64-musl"]
-checksum = "sha256:2ec7c0077431f96f74c3c72aea6505e902bc2ff47127653c8de1389ee30a3cb3"
-url = "https://github.com/astral-sh/ruff/releases/download/0.15.21/ruff-aarch64-unknown-linux-musl.tar.gz"
-url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/471700003"
+checksum = "sha256:7a6add3d38768dfa00c6d3853e9bd940b5526f3fbb76f02b1fe77ec0653f1e0e"
+url = "https://github.com/astral-sh/ruff/releases/download/0.16.0/ruff-aarch64-unknown-linux-musl.tar.gz"
+url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/487540070"
provenance = "github-attestations"
[tools.ruff."platforms.linux-x64"]
-checksum = "sha256:7e157ff9a2e13676118c587e6db0ec02d040e415b21014346d230e64789c0e78"
-url = "https://github.com/astral-sh/ruff/releases/download/0.15.21/ruff-x86_64-unknown-linux-musl.tar.gz"
-url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/471700081"
+checksum = "sha256:2138b7bc58ff877f5bba09aea4cc984ad5699433b6a3f811003527b8cff8e9ad"
+url = "https://github.com/astral-sh/ruff/releases/download/0.16.0/ruff-x86_64-unknown-linux-musl.tar.gz"
+url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/487540129"
provenance = "github-attestations"
[tools.ruff."platforms.linux-x64-musl"]
-checksum = "sha256:7e157ff9a2e13676118c587e6db0ec02d040e415b21014346d230e64789c0e78"
-url = "https://github.com/astral-sh/ruff/releases/download/0.15.21/ruff-x86_64-unknown-linux-musl.tar.gz"
-url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/471700081"
+checksum = "sha256:2138b7bc58ff877f5bba09aea4cc984ad5699433b6a3f811003527b8cff8e9ad"
+url = "https://github.com/astral-sh/ruff/releases/download/0.16.0/ruff-x86_64-unknown-linux-musl.tar.gz"
+url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/487540129"
provenance = "github-attestations"
[tools.ruff."platforms.macos-arm64"]
-checksum = "sha256:0452f9d5da6e8051d332cf21ae82a608d8e2cfeec5a71a46ffa9e50adbb2381d"
-url = "https://github.com/astral-sh/ruff/releases/download/0.15.21/ruff-aarch64-apple-darwin.tar.gz"
-url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/471699864"
+checksum = "sha256:ce6564491a2cc4b0659f45ee174dbef17e4dec24e03a9c03d313b5430bc21099"
+url = "https://github.com/astral-sh/ruff/releases/download/0.16.0/ruff-aarch64-apple-darwin.tar.gz"
+url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/487540064"
provenance = "github-attestations"
[tools.ruff."platforms.macos-x64"]
-checksum = "sha256:7e6ff3bd585b5b7c47634c957ac84fb5806d3c7ab4ef0e5ec1c53ce272f489da"
-url = "https://github.com/astral-sh/ruff/releases/download/0.15.21/ruff-x86_64-apple-darwin.tar.gz"
-url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/471700061"
+checksum = "sha256:3d9ef6228c4eeb26d593c398b2dc5250e0f6d6425933db2993fcf30d49c78b69"
+url = "https://github.com/astral-sh/ruff/releases/download/0.16.0/ruff-x86_64-apple-darwin.tar.gz"
+url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/487540116"
provenance = "github-attestations"
[tools.ruff."platforms.windows-x64"]
-checksum = "sha256:035c59abfd7bd1102e0b656f5771e6ae7a712a45ef54b5ab575541c7ff7d1eb0"
-url = "https://github.com/astral-sh/ruff/releases/download/0.15.21/ruff-x86_64-pc-windows-msvc.zip"
-url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/471700068"
+checksum = "sha256:c5d1185c47261f86361d03b547da25be79120226a6f1721d623b2aba9d27668b"
+url = "https://github.com/astral-sh/ruff/releases/download/0.16.0/ruff-x86_64-pc-windows-msvc.zip"
+url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/487540121"
provenance = "github-attestations"
[[tools.rumdl]]
-version = "v0.2.31"
+version = "v0.2.43"
backend = "aqua:rvben/rumdl"
[tools.rumdl."platforms.linux-arm64"]
-checksum = "sha256:d5aa4ac3f94de9b6508021f70d78be592c6dc8b67ea499c6e203c1e3daf044b0"
-url = "https://github.com/rvben/rumdl/releases/download/v0.2.31/rumdl-v0.2.31-aarch64-unknown-linux-musl.tar.gz"
-url_api = "https://api.github.com/repos/rvben/rumdl/releases/assets/474381480"
+checksum = "sha256:d5388225fa5e87c558c8d9bdc78dba515ce5ac2cbf8213fcc56ecdeabe534776"
+url = "https://github.com/rvben/rumdl/releases/download/v0.2.43/rumdl-v0.2.43-aarch64-unknown-linux-musl.tar.gz"
+url_api = "https://api.github.com/repos/rvben/rumdl/releases/assets/488745474"
provenance = "github-attestations"
[tools.rumdl."platforms.linux-arm64-musl"]
-checksum = "sha256:d5aa4ac3f94de9b6508021f70d78be592c6dc8b67ea499c6e203c1e3daf044b0"
-url = "https://github.com/rvben/rumdl/releases/download/v0.2.31/rumdl-v0.2.31-aarch64-unknown-linux-musl.tar.gz"
-url_api = "https://api.github.com/repos/rvben/rumdl/releases/assets/474381480"
+checksum = "sha256:d5388225fa5e87c558c8d9bdc78dba515ce5ac2cbf8213fcc56ecdeabe534776"
+url = "https://github.com/rvben/rumdl/releases/download/v0.2.43/rumdl-v0.2.43-aarch64-unknown-linux-musl.tar.gz"
+url_api = "https://api.github.com/repos/rvben/rumdl/releases/assets/488745474"
provenance = "github-attestations"
[tools.rumdl."platforms.linux-x64"]
-checksum = "sha256:5550f7954457248c6e29715b69d4ec2e9394613de51f98b50fa81f197a29af92"
-url = "https://github.com/rvben/rumdl/releases/download/v0.2.31/rumdl-v0.2.31-x86_64-unknown-linux-musl.tar.gz"
-url_api = "https://api.github.com/repos/rvben/rumdl/releases/assets/474381477"
+checksum = "sha256:e74e580aaf32698f61081ef1f6b9748f5c3fc1df311c14ab47ad3548a6a62f81"
+url = "https://github.com/rvben/rumdl/releases/download/v0.2.43/rumdl-v0.2.43-x86_64-unknown-linux-musl.tar.gz"
+url_api = "https://api.github.com/repos/rvben/rumdl/releases/assets/488745475"
provenance = "github-attestations"
[tools.rumdl."platforms.linux-x64-musl"]
-checksum = "sha256:5550f7954457248c6e29715b69d4ec2e9394613de51f98b50fa81f197a29af92"
-url = "https://github.com/rvben/rumdl/releases/download/v0.2.31/rumdl-v0.2.31-x86_64-unknown-linux-musl.tar.gz"
-url_api = "https://api.github.com/repos/rvben/rumdl/releases/assets/474381477"
+checksum = "sha256:e74e580aaf32698f61081ef1f6b9748f5c3fc1df311c14ab47ad3548a6a62f81"
+url = "https://github.com/rvben/rumdl/releases/download/v0.2.43/rumdl-v0.2.43-x86_64-unknown-linux-musl.tar.gz"
+url_api = "https://api.github.com/repos/rvben/rumdl/releases/assets/488745475"
provenance = "github-attestations"
[tools.rumdl."platforms.macos-arm64"]
-checksum = "sha256:368a02639247be530043abc36c40310090c09ef69b32f5744f9a0d9cc2673be5"
-url = "https://github.com/rvben/rumdl/releases/download/v0.2.31/rumdl-v0.2.31-aarch64-apple-darwin.tar.gz"
-url_api = "https://api.github.com/repos/rvben/rumdl/releases/assets/474381484"
+checksum = "sha256:43b19e0783b68135029b4f58dcb5bb7bf571f498107f6dae107e08bc6fe07214"
+url = "https://github.com/rvben/rumdl/releases/download/v0.2.43/rumdl-v0.2.43-aarch64-apple-darwin.tar.gz"
+url_api = "https://api.github.com/repos/rvben/rumdl/releases/assets/488745481"
provenance = "github-attestations"
[tools.rumdl."platforms.macos-x64"]
-checksum = "sha256:bc8933e04b5c83b8b14c21793c7f7902bc8b1a841bb1f1964c5f177b3cf7d05f"
-url = "https://github.com/rvben/rumdl/releases/download/v0.2.31/rumdl-v0.2.31-x86_64-apple-darwin.tar.gz"
-url_api = "https://api.github.com/repos/rvben/rumdl/releases/assets/474381479"
+checksum = "sha256:9ae902fa12b095911a7568457afdcde73a5295b168a063cdf8d478a3728d6411"
+url = "https://github.com/rvben/rumdl/releases/download/v0.2.43/rumdl-v0.2.43-x86_64-apple-darwin.tar.gz"
+url_api = "https://api.github.com/repos/rvben/rumdl/releases/assets/488745471"
provenance = "github-attestations"
[tools.rumdl."platforms.windows-x64"]
-checksum = "sha256:f8a4b2abf774301fd4ffd04f56e12fb0b2bf4357b28c63ec355405d57f0cfe88"
-url = "https://github.com/rvben/rumdl/releases/download/v0.2.31/rumdl-v0.2.31-x86_64-pc-windows-msvc.zip"
-url_api = "https://api.github.com/repos/rvben/rumdl/releases/assets/474381488"
+checksum = "sha256:7cef2e64bba950f5425c2c46983b1ca4a5122a33ff60e2cf3ff001e24d0beb30"
+url = "https://github.com/rvben/rumdl/releases/download/v0.2.43/rumdl-v0.2.43-x86_64-pc-windows-msvc.zip"
+url_api = "https://api.github.com/repos/rvben/rumdl/releases/assets/488745485"
provenance = "github-attestations"
[[tools.shellcheck]]
@@ -796,41 +796,41 @@ url = "https://github.com/crate-ci/typos/releases/download/v1.48.0/typos-v1.48.0
url_api = "https://api.github.com/repos/crate-ci/typos/releases/assets/462430871"
[[tools.zizmor]]
-version = "1.26.1"
+version = "1.28.0"
backend = "aqua:zizmorcore/zizmor"
[tools.zizmor."platforms.linux-arm64"]
-checksum = "sha256:711f5af366b299128f9a04b1470e37d990b41fbd21f14a1a4148d25004a83762"
-url = "https://github.com/zizmorcore/zizmor/releases/download/v1.26.1/zizmor-aarch64-unknown-linux-gnu.tar.gz"
-url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/453417983"
+checksum = "sha256:324e43770cfacf4216f8aefb287263b5b5c733c85b03bf7583b5cc4a0460239e"
+url = "https://github.com/zizmorcore/zizmor/releases/download/v1.28.0/zizmor-aarch64-unknown-linux-gnu.tar.gz"
+url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/485211654"
provenance = "github-attestations"
[tools.zizmor."platforms.linux-arm64-musl"]
provenance = "github-attestations"
[tools.zizmor."platforms.linux-x64"]
-checksum = "sha256:8556289a64e7aaf2400cd516f61a471aa91c5902cc56ad96a82fd12f90c2ef73"
-url = "https://github.com/zizmorcore/zizmor/releases/download/v1.26.1/zizmor-x86_64-unknown-linux-gnu.tar.gz"
-url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/453417985"
+checksum = "sha256:e87b67160194884e375a46a12c57ccc904f762b53845f254fab7f17d98809c09"
+url = "https://github.com/zizmorcore/zizmor/releases/download/v1.28.0/zizmor-x86_64-unknown-linux-gnu.tar.gz"
+url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/485211657"
provenance = "github-attestations"
[tools.zizmor."platforms.linux-x64-musl"]
provenance = "github-attestations"
[tools.zizmor."platforms.macos-arm64"]
-checksum = "sha256:68ab2b37836bbd44f6cfffcc102b9ffffbc20c5d67d84293dafb63bd2775a1da"
-url = "https://github.com/zizmorcore/zizmor/releases/download/v1.26.1/zizmor-aarch64-apple-darwin.tar.gz"
-url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/453417984"
+checksum = "sha256:54949bbd6b4c8527046bb8990bac9e0dab3eec787640f4e6199ae121dd1040be"
+url = "https://github.com/zizmorcore/zizmor/releases/download/v1.28.0/zizmor-aarch64-apple-darwin.tar.gz"
+url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/485211655"
provenance = "github-attestations"
[tools.zizmor."platforms.macos-x64"]
-checksum = "sha256:2967414a561f8c1264121e8f723c3b5abcf3d1bf7ce5063114df99985dd75801"
-url = "https://github.com/zizmorcore/zizmor/releases/download/v1.26.1/zizmor-x86_64-apple-darwin.tar.gz"
-url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/453417982"
+checksum = "sha256:40a58d8560d65c71357b3977d0da425773bf8f10bf1ffd38099d963d3afdf3aa"
+url = "https://github.com/zizmorcore/zizmor/releases/download/v1.28.0/zizmor-x86_64-apple-darwin.tar.gz"
+url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/485211652"
provenance = "github-attestations"
[tools.zizmor."platforms.windows-x64"]
-checksum = "sha256:c6cea156935e3b9d36faeca4fd8f622d23f7a7578da26adb34e6456abd9beb9a"
-url = "https://github.com/zizmorcore/zizmor/releases/download/v1.26.1/zizmor-x86_64-pc-windows-msvc.zip"
-url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/453417981"
+checksum = "sha256:06e5b2345323201ed4c55897651862fee3b43f79ddced799f1236f0f0d1c1c0f"
+url = "https://github.com/zizmorcore/zizmor/releases/download/v1.28.0/zizmor-x86_64-pc-windows-msvc.zip"
+url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/485211651"
provenance = "github-attestations"
diff --git a/mise.toml b/mise.toml
index 94c3beb17..497c10f19 100644
--- a/mise.toml
+++ b/mise.toml
@@ -9,20 +9,20 @@ protoc = "35.1"
# Linters
actionlint = "1.7.12"
"aqua:grafana/flint" = "0.22.9"
-"aqua:jonwiggins/xmloxide" = "v0.4.3"
+"aqua:jonwiggins/xmloxide" = "v0.4.4"
"aqua:owenlamont/ryl" = "0.21.0"
-biome = "2.5.3"
+biome = "2.5.5"
editorconfig-checker = "3.8.0"
google-java-format = "1.35.0"
lychee = "0.24.2"
-"npm:renovate" = "43.257.4"
-ruff = "0.15.21"
-rumdl = "v0.2.31"
+"npm:renovate" = "43.279.1"
+ruff = "0.16.0"
+rumdl = "v0.2.43"
shellcheck = "v0.11.0"
shfmt = "3.13.1"
taplo = "0.10.0"
typos = "1.48.0"
-zizmor = "1.26.1"
+zizmor = "1.28.0"
[env]
FLINT_CONFIG_DIR = ".github/config"
From 5757c412fa58e3d664d4b4af6c0e6db40f7855b1 Mon Sep 17 00:00:00 2001
From: Gregor Zeitlinger
Date: Tue, 28 Jul 2026 16:34:19 +0200
Subject: [PATCH 27/83] ci: limit release job to Java toolchain (#2347)
## What changed
- Restrict the Maven Central release job to the mise-managed Java
toolchain.
- Preserve the existing no-cache release configuration.
## Why
The artifact release should not install unrelated development and
linting tools from `mise.toml`. This keeps release execution focused and
prevents unrelated tool resolution failures from blocking publication.
## Validation
- `mise run lint:fix`
- `actionlint .github/workflows/release.yml`
- `git diff --check`
---
.github/workflows/release.yml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index a30db041e..2970100fc 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -15,6 +15,9 @@ jobs:
if: ${{ github.repository == 'prometheus/client_java' }}
environment: release
runs-on: ubuntu-24.04
+ env:
+ # Artifact releases pair a focused tool allowlist with cache: false.
+ MISE_ENABLE_TOOLS: java
permissions:
actions: write # required to trigger bump-api-diff-baseline.yml via `gh workflow run`
From 9b0ede830fcf233fb9f9c4cb08ed91ef21fbd667 Mon Sep 17 00:00:00 2001
From: Subhramit Basu
Date: Tue, 28 Jul 2026 20:11:29 +0530
Subject: [PATCH 28/83] feat: support metric name filtering in OpenTelemetry
exporter (#2344)
Closes the last pending high-priority item in
https://github.com/prometheus/client_java/issues/1816 (as all others
have already been addressed).
Currently, `PrometheusMetricProducer` always exported all metrics in the
registry unconditionally. The code already had a TODO sketching how
filtering could be added:
https://github.com/prometheus/client_java/blob/9432fdc1933611d34d944d4640ebca3bf91f8ee4/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusMetricProducer.java#L47-L54
this PR implements that by reusing `ExporterFilterProperties` and
`MetricNameFilter`, as already done by `PrometheusScrapeHandler`.
As a result, the OpenTelemetry exporter now honors the shared
`io.prometheus.exporter.filter.*` configuration, making its behavior
consistent with the HTTP/Servlet exporters.
---------
Signed-off-by: subhramit
---
docs/content/otel/otlp.md | 4 +
.../opentelemetry/OtelAutoConfig.java | 6 +-
.../PrometheusMetricProducer.java | 94 ++++++++++++++++---
.../exporter/opentelemetry/ExportTest.java | 89 ++++++++++++++----
.../opentelemetry/OtelAutoConfigTest.java | 88 ++++++++++++++---
5 files changed, 234 insertions(+), 47 deletions(-)
diff --git a/docs/content/otel/otlp.md b/docs/content/otel/otlp.md
index 31aacfcbd..e2ea987dd 100644
--- a/docs/content/otel/otlp.md
+++ b/docs/content/otel/otlp.md
@@ -44,6 +44,9 @@ By default, the `OpenTelemetryExporter` will push metrics every 60 seconds to
the [OpenTelemetryExporter.Builder][builder-javadoc], or at runtime via
[`io.prometheus.exporter.opentelemetry.*`][otel-properties] properties.
+The OpenTelemetry exporter also honors the shared [`io.prometheus.exporter.filter.*`][exporter-filter-properties] metric-name
+filter properties.
+
In addition to the Prometheus Java client configuration, the exporter also recognizes standard
OpenTelemetry configuration. For example, you can set
the [OTEL_EXPORTER_OTLP_METRICS_ENDPOINT](https://opentelemetry.io/docs/concepts/sdk-configuration/otlp-exporter-configuration/#otel_exporter_otlp_metrics_endpoint)
@@ -62,4 +65,5 @@ OTel collector, and a Prometheus server.
[builder-javadoc]: /client_java/api/io/prometheus/metrics/exporter/opentelemetry/OpenTelemetryExporter.Builder.html
[opentelemetry-example]: https://github.com/prometheus/client_java/tree/main/examples/example-exporter-opentelemetry
[otel-pipeline]: /client_java/images/otel-pipeline.png
+[exporter-filter-properties]: {{< relref "../config/config.md#exporter-filter-properties" >}}
[otel-properties]: {{< relref "../config/config.md#exporter-opentelemetry-properties" >}}
diff --git a/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/OtelAutoConfig.java b/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/OtelAutoConfig.java
index 2ea96e3c3..267ff23ad 100644
--- a/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/OtelAutoConfig.java
+++ b/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/OtelAutoConfig.java
@@ -40,8 +40,10 @@ static MetricReader createReader(
MetricReader reader = requireNonNull(readerRef.get());
boolean preserveNames = resolvePreserveNames(builder, config);
reader.register(
- new PrometheusMetricProducer(
- registry, instrumentationScopeInfo, getResourceField(sdk), preserveNames));
+ PrometheusMetricProducer.builder(
+ registry, instrumentationScopeInfo, getResourceField(sdk), preserveNames)
+ .exporterFilterProperties(config.getExporterFilterProperties())
+ .build());
return reader;
}
diff --git a/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusMetricProducer.java b/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusMetricProducer.java
index 886cdd85c..2c3e399f7 100644
--- a/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusMetricProducer.java
+++ b/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusMetricProducer.java
@@ -7,7 +7,9 @@
import io.opentelemetry.sdk.metrics.export.CollectionRegistration;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.resources.ResourceBuilder;
+import io.prometheus.metrics.config.ExporterFilterProperties;
import io.prometheus.metrics.exporter.opentelemetry.otelmodel.MetricDataFactory;
+import io.prometheus.metrics.model.registry.MetricNameFilter;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
import io.prometheus.metrics.model.snapshots.CounterSnapshot;
import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
@@ -22,6 +24,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.function.Predicate;
import javax.annotation.Nullable;
class PrometheusMetricProducer implements CollectionRegistration {
@@ -30,29 +33,65 @@ class PrometheusMetricProducer implements CollectionRegistration {
private final Resource resource;
private final InstrumentationScopeInfo instrumentationScopeInfo;
private final boolean preserveNames;
+ @Nullable private final Predicate nameFilter;
- public PrometheusMetricProducer(
+ private PrometheusMetricProducer(
PrometheusRegistry registry,
InstrumentationScopeInfo instrumentationScopeInfo,
Resource resource,
- boolean preserveNames) {
+ boolean preserveNames,
+ @Nullable Predicate nameFilter) {
this.registry = registry;
this.instrumentationScopeInfo = instrumentationScopeInfo;
this.resource = resource;
this.preserveNames = preserveNames;
+ this.nameFilter = nameFilter;
+ }
+
+ /**
+ * Creates a builder for a producer with no metric name filtering by default, i.e. all metrics in
+ * {@code registry} are exported unless filter properties are configured on the builder.
+ */
+ static Builder builder(
+ PrometheusRegistry registry,
+ InstrumentationScopeInfo instrumentationScopeInfo,
+ Resource resource,
+ boolean preserveNames) {
+ return new Builder(registry, instrumentationScopeInfo, resource, preserveNames);
+ }
+
+ /**
+ * Builds a name filter from {@code io.prometheus.exporter.filter.*} properties, mirroring how
+ * {@code PrometheusScrapeHandler} builds its filter for the Servlet/HTTPServer exporters so that
+ * filtering config behaves consistently across exporters.
+ *
+ * OpenTelemetry's own Views API also supports filtering and aggregation, and may be preferable
+ * for OpenTelemetry-specific deployments; this filter is intended for users who want the same
+ * {@code io.prometheus.exporter.filter.*} config to apply regardless of which exporter they use.
+ *
+ * @return {@code null} if no filter properties are set, to avoid the overhead of testing every
+ * metric name against a filter that matches everything.
+ */
+ @Nullable
+ private static Predicate makeNameFilter(ExporterFilterProperties props) {
+ if (props.getAllowedMetricNames() == null
+ && props.getExcludedMetricNames() == null
+ && props.getAllowedMetricNamePrefixes() == null
+ && props.getExcludedMetricNamePrefixes() == null) {
+ return null;
+ }
+ return MetricNameFilter.builder()
+ .nameMustBeEqualTo(props.getAllowedMetricNames())
+ .nameMustNotBeEqualTo(props.getExcludedMetricNames())
+ .nameMustStartWith(props.getAllowedMetricNamePrefixes())
+ .nameMustNotStartWith(props.getExcludedMetricNamePrefixes())
+ .build();
}
@Override
public Collection collectAllMetrics() {
- // Note: Currently all metrics from the registry are exported. To add metric filtering
- // similar to the Servlet exporter, one could:
- // 1. Add filter properties to ExporterOpenTelemetryProperties (allowedNames, excludedNames,
- // etc.)
- // 2. Convert these properties to a Predicate using MetricNameFilter.builder()
- // 3. Call registry.scrape(filter) instead of registry.scrape()
- // OpenTelemetry also provides its own Views API for filtering and aggregation, which may be
- // preferred for OpenTelemetry-specific deployments.
- MetricSnapshots snapshots = registry.scrape();
+ MetricSnapshots snapshots =
+ nameFilter != null ? registry.scrape(nameFilter) : registry.scrape();
Resource resourceWithTargetInfo = resource.merge(resourceFromTargetInfo(snapshots));
InstrumentationScopeInfo scopeFromInfo = instrumentationScopeFromOtelScopeInfo(snapshots);
List result = new ArrayList<>(snapshots.size());
@@ -142,4 +181,37 @@ private void addUnlessNull(List result, @Nullable MetricData data) {
result.add(data);
}
}
+
+ static class Builder {
+ private final PrometheusRegistry registry;
+ private final Resource resource;
+ private final InstrumentationScopeInfo instrumentationScopeInfo;
+ private final boolean preserveNames;
+ private ExporterFilterProperties filterProperties = ExporterFilterProperties.builder().build();
+
+ private Builder(
+ PrometheusRegistry registry,
+ InstrumentationScopeInfo instrumentationScopeInfo,
+ Resource resource,
+ boolean preserveNames) {
+ this.registry = registry;
+ this.instrumentationScopeInfo = instrumentationScopeInfo;
+ this.resource = resource;
+ this.preserveNames = preserveNames;
+ }
+
+ Builder exporterFilterProperties(ExporterFilterProperties filterProperties) {
+ this.filterProperties = filterProperties;
+ return this;
+ }
+
+ PrometheusMetricProducer build() {
+ return new PrometheusMetricProducer(
+ registry,
+ instrumentationScopeInfo,
+ resource,
+ preserveNames,
+ makeNameFilter(filterProperties));
+ }
+ }
}
diff --git a/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/ExportTest.java b/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/ExportTest.java
index 0332eb574..4329df4b8 100644
--- a/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/ExportTest.java
+++ b/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/ExportTest.java
@@ -12,6 +12,7 @@
import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions;
import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader;
import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension;
+import io.prometheus.metrics.config.ExporterFilterProperties;
import io.prometheus.metrics.core.metrics.Counter;
import io.prometheus.metrics.core.metrics.Gauge;
import io.prometheus.metrics.core.metrics.Histogram;
@@ -46,11 +47,12 @@ void setUp() throws IllegalAccessException, NoSuchFieldException {
MetricReader reader = (MetricReader) field.get(testing);
PrometheusMetricProducer prometheusMetricProducer =
- new PrometheusMetricProducer(
- registry,
- InstrumentationScopeInfo.create("test"),
- Resource.create(Attributes.builder().put("staticRes", "value").build()),
- false);
+ PrometheusMetricProducer.builder(
+ registry,
+ InstrumentationScopeInfo.create("test"),
+ Resource.create(Attributes.builder().put("staticRes", "value").build()),
+ false)
+ .build();
reader.register(prometheusMetricProducer);
}
@@ -332,11 +334,12 @@ void preserveNamesWithUnit() {
InMemoryMetricReader reader = InMemoryMetricReader.create();
PrometheusRegistry preserveRegistry = new PrometheusRegistry();
reader.register(
- new PrometheusMetricProducer(
- preserveRegistry,
- InstrumentationScopeInfo.create("test"),
- Resource.create(Attributes.builder().put("staticRes", "value").build()),
- true));
+ PrometheusMetricProducer.builder(
+ preserveRegistry,
+ InstrumentationScopeInfo.create("test"),
+ Resource.create(Attributes.builder().put("staticRes", "value").build()),
+ true)
+ .build());
Counter.builder().name("req").unit(Unit.BYTES).register(preserveRegistry).inc();
@@ -350,11 +353,12 @@ void preserveNamesWithUnitAlreadyInName() {
InMemoryMetricReader reader = InMemoryMetricReader.create();
PrometheusRegistry preserveRegistry = new PrometheusRegistry();
reader.register(
- new PrometheusMetricProducer(
- preserveRegistry,
- InstrumentationScopeInfo.create("test"),
- Resource.create(Attributes.builder().put("staticRes", "value").build()),
- true));
+ PrometheusMetricProducer.builder(
+ preserveRegistry,
+ InstrumentationScopeInfo.create("test"),
+ Resource.create(Attributes.builder().put("staticRes", "value").build()),
+ true)
+ .build());
Counter.builder().name("req_bytes").unit(Unit.BYTES).register(preserveRegistry).inc();
@@ -368,11 +372,12 @@ void preserveNamesWithoutUnit() {
InMemoryMetricReader reader = InMemoryMetricReader.create();
PrometheusRegistry preserveRegistry = new PrometheusRegistry();
reader.register(
- new PrometheusMetricProducer(
- preserveRegistry,
- InstrumentationScopeInfo.create("test"),
- Resource.create(Attributes.builder().put("staticRes", "value").build()),
- true));
+ PrometheusMetricProducer.builder(
+ preserveRegistry,
+ InstrumentationScopeInfo.create("test"),
+ Resource.create(Attributes.builder().put("staticRes", "value").build()),
+ true)
+ .build());
Counter.builder().name("events_total").register(preserveRegistry).inc();
@@ -381,6 +386,50 @@ void preserveNamesWithoutUnit() {
OpenTelemetryAssertions.assertThat(metrics.get(0)).hasName("events_total");
}
+ @Test
+ void metricNameFilterExcludedNames() {
+ InMemoryMetricReader reader = InMemoryMetricReader.create();
+ PrometheusRegistry filteredRegistry = new PrometheusRegistry();
+ reader.register(
+ PrometheusMetricProducer.builder(
+ filteredRegistry,
+ InstrumentationScopeInfo.create("test"),
+ Resource.create(Attributes.builder().put("staticRes", "value").build()),
+ false)
+ .exporterFilterProperties(
+ ExporterFilterProperties.builder().excludedNames("secret_total").build())
+ .build());
+
+ Counter.builder().name("secret").register(filteredRegistry).inc();
+ Counter.builder().name("public").register(filteredRegistry).inc();
+
+ List metrics = new ArrayList<>(reader.collectAllMetrics());
+ assertThat(metrics).hasSize(1);
+ OpenTelemetryAssertions.assertThat(metrics.get(0)).hasName("public");
+ }
+
+ @Test
+ void metricNameFilterAllowedPrefixes() {
+ InMemoryMetricReader reader = InMemoryMetricReader.create();
+ PrometheusRegistry filteredRegistry = new PrometheusRegistry();
+ reader.register(
+ PrometheusMetricProducer.builder(
+ filteredRegistry,
+ InstrumentationScopeInfo.create("test"),
+ Resource.create(Attributes.builder().put("staticRes", "value").build()),
+ false)
+ .exporterFilterProperties(
+ ExporterFilterProperties.builder().allowedPrefixes("http_").build())
+ .build());
+
+ Counter.builder().name("http_requests").register(filteredRegistry).inc();
+ Counter.builder().name("jvm_threads").register(filteredRegistry).inc();
+
+ List metrics = new ArrayList<>(reader.collectAllMetrics());
+ assertThat(metrics).hasSize(1);
+ OpenTelemetryAssertions.assertThat(metrics.get(0)).hasName("http_requests");
+ }
+
private MetricAssert metricAssert() {
List metrics = testing.getMetrics();
assertThat(metrics).hasSize(1);
diff --git a/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/OtelAutoConfigTest.java b/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/OtelAutoConfigTest.java
index a81aec440..19a737122 100644
--- a/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/OtelAutoConfigTest.java
+++ b/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/OtelAutoConfigTest.java
@@ -7,11 +7,21 @@
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
+import io.opentelemetry.sdk.metrics.data.MetricData;
+import io.opentelemetry.sdk.metrics.export.CollectionRegistration;
+import io.opentelemetry.sdk.metrics.export.MetricReader;
+import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions;
+import io.prometheus.metrics.config.ExporterFilterProperties;
import io.prometheus.metrics.config.ExporterOpenTelemetryProperties;
import io.prometheus.metrics.config.PrometheusProperties;
import io.prometheus.metrics.config.PrometheusPropertiesLoader;
+import io.prometheus.metrics.core.metrics.Counter;
+import io.prometheus.metrics.model.registry.PrometheusRegistry;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
@@ -67,21 +77,16 @@ public static Stream testCases() {
"values from builder",
new TestCase()
.expectedProperties(
- Map.of(
- "otel.exporter.otlp.protocol",
- Optional.of("http/protobuf"),
- "otel.exporter.otlp.endpoint",
- Optional.of("http://builder:4318"),
- "otel.exporter.otlp.headers",
- Optional.of("h=builder-v"),
- "otel.metric.export.interval",
- Optional.of("2s"),
- "otel.exporter.otlp.timeout",
- Optional.of("3s"),
- "otel.service.name",
- Optional.of("builder-service")))
+ ImmutableMap.>builder()
+ .put("otel.exporter.otlp.protocol", Optional.of("http/protobuf"))
+ .put("otel.exporter.otlp.endpoint", Optional.of("http://builder:4318"))
+ .put("otel.exporter.otlp.headers", Optional.of("h=builder-v"))
+ .put("otel.metric.export.interval", Optional.of("2s"))
+ .put("otel.exporter.otlp.timeout", Optional.of("3s"))
+ .put("otel.service.name", Optional.of("builder-service"))
+ .build())
.expectedResourceAttributes(
- Map.of(
+ ImmutableMap.of(
"key",
"builder-value",
"service.name",
@@ -316,6 +321,61 @@ void resolvePreserveNamesFromConfig() {
assertThat(OtelAutoConfig.resolvePreserveNames(builder, config)).isTrue();
}
+ @Test
+ void createReaderUsesExporterFilterProperties() throws IllegalAccessException {
+ PrometheusRegistry registry = new PrometheusRegistry();
+ PrometheusProperties config =
+ PrometheusProperties.builder()
+ .exporterFilterProperties(
+ ExporterFilterProperties.builder().excludedNames("secret_total").build())
+ .build();
+ OpenTelemetryExporter.Builder builder =
+ OpenTelemetryExporter.builder(config).registry(registry);
+ MetricReader reader = OtelAutoConfig.createReader(builder, config, registry);
+
+ try {
+ Counter.builder().name("secret").register(registry).inc();
+ Counter.builder().name("public").register(registry).inc();
+
+ PrometheusMetricProducer producer = findPrometheusMetricProducer(reader);
+ List metrics = new ArrayList<>(producer.collectAllMetrics());
+ assertThat(metrics).hasSize(1);
+ OpenTelemetryAssertions.assertThat(metrics.get(0)).hasName("public");
+ } finally {
+ reader.shutdown();
+ }
+ }
+
+ // MetricReader does not expose registered CollectionRegistrations, so this test locates the
+ // registered PrometheusMetricProducer reflectively to verify that OtelAutoConfig wires exporter
+ // filter properties through to it.
+ private static PrometheusMetricProducer findPrometheusMetricProducer(Object object)
+ throws IllegalAccessException {
+ assertThat(object).isNotNull();
+ for (Field field : object.getClass().getDeclaredFields()) {
+ field.setAccessible(true);
+ Object value = field.get(object);
+ if (value instanceof PrometheusMetricProducer) {
+ return (PrometheusMetricProducer) value;
+ }
+ if (value instanceof CollectionRegistration) {
+ return findPrometheusMetricProducer(value);
+ }
+ if (value instanceof Iterable>) {
+ for (Object element : (Iterable>) value) {
+ if (element instanceof PrometheusMetricProducer) {
+ return (PrometheusMetricProducer) element;
+ }
+ if (element instanceof CollectionRegistration) {
+ return findPrometheusMetricProducer(element);
+ }
+ }
+ }
+ }
+ throw new AssertionError(
+ "Did not find PrometheusMetricProducer in " + object.getClass().getName());
+ }
+
private static ExporterOpenTelemetryProperties getExporterOpenTelemetryProperties(
TestCase testCase) {
if (testCase.propertiesBuilder == null) {
From c78e5e147bb54f03776e52719bb796b7a0e003f7 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 28 Jul 2026 17:12:19 +0200
Subject: [PATCH 29/83] chore(deps): update dependency aqua:grafana/gcx to v1
(#2349)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [aqua:grafana/gcx](https://redirect.github.com/grafana/gcx) | major |
`0.6.0` → `1.0.0` |
---
### Release Notes
grafana/gcx (aqua:grafana/gcx)
###
[`v1.0.0`](https://redirect.github.com/grafana/gcx/blob/HEAD/CHANGELOG.md#v100-2026-07-28)
[Compare
Source](https://redirect.github.com/grafana/gcx/compare/v0.6.0...v1.0.0)
##### Features
- alert: add ruler subtree for datasource-managed rule writes
- kg: add `entities correlate` to resolve entities from alert labels
- kg: add entity quality reports (`kg quality`), folded into `kg
diagnose`
##### Fixes
- alert: make GMA alert rules modifiable via the resources tier
- cloud: drop status/createdAt/updatedAt from stack regions output
- aio11y: point plugin id at renamed grafana-agento11y-app
##### Docs
- GA: remove public preview warnings, add GA notes across docs and
README
- skills: harden agento11y-instrument and agento11y-prod-setup guidance
- stop prescribing Editor/Admin for service-account tokens; installation
fixes
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/prometheus/client_java).
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
mise.lock | 44 ++++++++++++++++++++++----------------------
mise.toml | 2 +-
2 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/mise.lock b/mise.lock
index 8809f7764..f09cb34a5 100644
--- a/mise.lock
+++ b/mise.lock
@@ -87,43 +87,43 @@ url_api = "https://api.github.com/repos/grafana/flint/releases/assets/476892021"
provenance = "github-attestations"
[[tools."aqua:grafana/gcx"]]
-version = "v0.6.0"
+version = "v1.0.0"
backend = "aqua:grafana/gcx"
[tools."aqua:grafana/gcx"."platforms.linux-arm64"]
-checksum = "sha256:4678cce06fc9d6cc364c460f67be0bb06861e00e3c058e48697ae7428938efcb"
-url = "https://github.com/grafana/gcx/releases/download/v0.6.0/gcx_0.6.0_linux_arm64.tar.gz"
-url_api = "https://api.github.com/repos/grafana/gcx/releases/assets/488386380"
+checksum = "sha256:605f6bb7406d144bd11c72ff25649ab17229699be585a253460b77396dc57585"
+url = "https://github.com/grafana/gcx/releases/download/v1.0.0/gcx_1.0.0_linux_arm64.tar.gz"
+url_api = "https://api.github.com/repos/grafana/gcx/releases/assets/492677496"
[tools."aqua:grafana/gcx"."platforms.linux-arm64-musl"]
-checksum = "sha256:4678cce06fc9d6cc364c460f67be0bb06861e00e3c058e48697ae7428938efcb"
-url = "https://github.com/grafana/gcx/releases/download/v0.6.0/gcx_0.6.0_linux_arm64.tar.gz"
-url_api = "https://api.github.com/repos/grafana/gcx/releases/assets/488386380"
+checksum = "sha256:605f6bb7406d144bd11c72ff25649ab17229699be585a253460b77396dc57585"
+url = "https://github.com/grafana/gcx/releases/download/v1.0.0/gcx_1.0.0_linux_arm64.tar.gz"
+url_api = "https://api.github.com/repos/grafana/gcx/releases/assets/492677496"
[tools."aqua:grafana/gcx"."platforms.linux-x64"]
-checksum = "sha256:5e76c064f14d9ec360cc48c46251b06a47762ab0dc755e4275e14ce2f67e8dbe"
-url = "https://github.com/grafana/gcx/releases/download/v0.6.0/gcx_0.6.0_linux_amd64.tar.gz"
-url_api = "https://api.github.com/repos/grafana/gcx/releases/assets/488386396"
+checksum = "sha256:c88c65958d19d83dc3a192a2a5037e08307a9c776019f24249b89f369c9c4d41"
+url = "https://github.com/grafana/gcx/releases/download/v1.0.0/gcx_1.0.0_linux_amd64.tar.gz"
+url_api = "https://api.github.com/repos/grafana/gcx/releases/assets/492677459"
[tools."aqua:grafana/gcx"."platforms.linux-x64-musl"]
-checksum = "sha256:5e76c064f14d9ec360cc48c46251b06a47762ab0dc755e4275e14ce2f67e8dbe"
-url = "https://github.com/grafana/gcx/releases/download/v0.6.0/gcx_0.6.0_linux_amd64.tar.gz"
-url_api = "https://api.github.com/repos/grafana/gcx/releases/assets/488386396"
+checksum = "sha256:c88c65958d19d83dc3a192a2a5037e08307a9c776019f24249b89f369c9c4d41"
+url = "https://github.com/grafana/gcx/releases/download/v1.0.0/gcx_1.0.0_linux_amd64.tar.gz"
+url_api = "https://api.github.com/repos/grafana/gcx/releases/assets/492677459"
[tools."aqua:grafana/gcx"."platforms.macos-arm64"]
-checksum = "sha256:7192ec16aef172d03031aa156c155eb351f230dae86e64e1ed337503fe45a1eb"
-url = "https://github.com/grafana/gcx/releases/download/v0.6.0/gcx_0.6.0_darwin_arm64.tar.gz"
-url_api = "https://api.github.com/repos/grafana/gcx/releases/assets/488386379"
+checksum = "sha256:5c27ac08d0d6d82a63468d75f41bfe83536e17efa89b6329076fcb2da046a672"
+url = "https://github.com/grafana/gcx/releases/download/v1.0.0/gcx_1.0.0_darwin_arm64.tar.gz"
+url_api = "https://api.github.com/repos/grafana/gcx/releases/assets/492677461"
[tools."aqua:grafana/gcx"."platforms.macos-x64"]
-checksum = "sha256:b5174d5c47ffeaf21c1a65c83b908538cf664649199bd017d5f3addb537fc4aa"
-url = "https://github.com/grafana/gcx/releases/download/v0.6.0/gcx_0.6.0_darwin_amd64.tar.gz"
-url_api = "https://api.github.com/repos/grafana/gcx/releases/assets/488386377"
+checksum = "sha256:383feee2eade5d941412b49d3c508bad2cbc5088a016c7f77bfad0eb9afe1984"
+url = "https://github.com/grafana/gcx/releases/download/v1.0.0/gcx_1.0.0_darwin_amd64.tar.gz"
+url_api = "https://api.github.com/repos/grafana/gcx/releases/assets/492677498"
[tools."aqua:grafana/gcx"."platforms.windows-x64"]
-checksum = "sha256:de456400960e2405de01dc493f7659e6a2a6168ea2c26b02e08ccbd06fa22385"
-url = "https://github.com/grafana/gcx/releases/download/v0.6.0/gcx_0.6.0_windows_amd64.zip"
-url_api = "https://api.github.com/repos/grafana/gcx/releases/assets/488386381"
+checksum = "sha256:9c8dcccbc1712463ebce92b8c9f07f05ca55d6d096b2219dcc7e0761f832fef9"
+url = "https://github.com/grafana/gcx/releases/download/v1.0.0/gcx_1.0.0_windows_amd64.zip"
+url_api = "https://api.github.com/repos/grafana/gcx/releases/assets/492677462"
[[tools."aqua:grafana/oats"]]
version = "0.8.0"
diff --git a/mise.toml b/mise.toml
index 497c10f19..569a2f3bd 100644
--- a/mise.toml
+++ b/mise.toml
@@ -1,5 +1,5 @@
[tools]
-"aqua:grafana/gcx" = "v0.6.0"
+"aqua:grafana/gcx" = "v1.0.0"
"aqua:grafana/oats" = "0.8.0"
hugo = "0.164.0"
java = "temurin-25.0.3+9.0.LTS"
From 62d2443f639e2f643f04c0073920cb2b2c416116 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 29 Jul 2026 15:43:11 +0200
Subject: [PATCH 30/83] chore(deps): update dependency aqua:grafana/oats to
v0.9.0 (#2352)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [aqua:grafana/oats](https://redirect.github.com/grafana/oats) | minor
| `0.8.0` → `0.10.0` |
---
### Release Notes
grafana/oats (aqua:grafana/oats)
###
[`v0.10.0`](https://redirect.github.com/grafana/oats/blob/HEAD/CHANGELOG.md#0100-2026-07-28)
[Compare
Source](https://redirect.github.com/grafana/oats/compare/v0.9.0...v0.10.0)
##### Features
- add opt-in HTTP input retries
([#453](https://redirect.github.com/grafana/oats/issues/453))
([82a973d](https://redirect.github.com/grafana/oats/commit/82a973d528a9dab8b8ac69091db53e41b92cf8b6))
##### Bug Fixes
- **release:** ensure gcx updates trigger releases
([#454](https://redirect.github.com/grafana/oats/issues/454))
([8e52488](https://redirect.github.com/grafana/oats/commit/8e52488956da7273f36937a8cbdfe97918e67278))
###
[`v0.9.0`](https://redirect.github.com/grafana/oats/blob/HEAD/CHANGELOG.md#090-2026-07-28)
[Compare
Source](https://redirect.github.com/grafana/oats/compare/v0.8.0...v0.9.0)
##### Features
- support one-shot Compose inputs
([#451](https://redirect.github.com/grafana/oats/issues/451))
([c43e6cb](https://redirect.github.com/grafana/oats/commit/c43e6cb6964d486c8a27df9f2d43b821f5a1ac62))
##### Bug Fixes
- **deps:** update module go.opentelemetry.io/collector/pdata to v1.63.0
([#438](https://redirect.github.com/grafana/oats/issues/438))
([6f3524a](https://redirect.github.com/grafana/oats/commit/6f3524a215886baf03e78e2493d235d1fb8ac131))
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/prometheus/client_java).
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
mise.lock | 44 ++++++++++++++++++++++----------------------
mise.toml | 2 +-
2 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/mise.lock b/mise.lock
index f09cb34a5..ba618bcba 100644
--- a/mise.lock
+++ b/mise.lock
@@ -126,49 +126,49 @@ url = "https://github.com/grafana/gcx/releases/download/v1.0.0/gcx_1.0.0_windows
url_api = "https://api.github.com/repos/grafana/gcx/releases/assets/492677462"
[[tools."aqua:grafana/oats"]]
-version = "0.8.0"
+version = "0.10.0"
backend = "aqua:grafana/oats"
[tools."aqua:grafana/oats"."platforms.linux-arm64"]
-checksum = "sha256:82eaf1e836cea916b96cef6745423efd8256ceab64bbabd1fa8f13b3883a1212"
-url = "https://github.com/grafana/oats/releases/download/v0.8.0/oats_0.8.0_linux_arm64.tar.gz"
-url_api = "https://api.github.com/repos/grafana/oats/releases/assets/487171323"
+checksum = "sha256:be195aeeafce644c8a59438bbc8c472f5ca51df6f9570c6b646373a703d686b0"
+url = "https://github.com/grafana/oats/releases/download/v0.10.0/oats_0.10.0_linux_arm64.tar.gz"
+url_api = "https://api.github.com/repos/grafana/oats/releases/assets/493772122"
provenance = "github-attestations"
[tools."aqua:grafana/oats"."platforms.linux-arm64-musl"]
-checksum = "sha256:82eaf1e836cea916b96cef6745423efd8256ceab64bbabd1fa8f13b3883a1212"
-url = "https://github.com/grafana/oats/releases/download/v0.8.0/oats_0.8.0_linux_arm64.tar.gz"
-url_api = "https://api.github.com/repos/grafana/oats/releases/assets/487171323"
+checksum = "sha256:be195aeeafce644c8a59438bbc8c472f5ca51df6f9570c6b646373a703d686b0"
+url = "https://github.com/grafana/oats/releases/download/v0.10.0/oats_0.10.0_linux_arm64.tar.gz"
+url_api = "https://api.github.com/repos/grafana/oats/releases/assets/493772122"
provenance = "github-attestations"
[tools."aqua:grafana/oats"."platforms.linux-x64"]
-checksum = "sha256:ea4368c6d7f62244ce959ba60512f271d46d133b50350077257e2bb81c03a5ca"
-url = "https://github.com/grafana/oats/releases/download/v0.8.0/oats_0.8.0_linux_amd64.tar.gz"
-url_api = "https://api.github.com/repos/grafana/oats/releases/assets/487171351"
+checksum = "sha256:b72a7a587148d1eaa15ccea3ce1adfd67e040d1cd9f9e267c850154035ef9a18"
+url = "https://github.com/grafana/oats/releases/download/v0.10.0/oats_0.10.0_linux_amd64.tar.gz"
+url_api = "https://api.github.com/repos/grafana/oats/releases/assets/493772131"
provenance = "github-attestations"
[tools."aqua:grafana/oats"."platforms.linux-x64-musl"]
-checksum = "sha256:ea4368c6d7f62244ce959ba60512f271d46d133b50350077257e2bb81c03a5ca"
-url = "https://github.com/grafana/oats/releases/download/v0.8.0/oats_0.8.0_linux_amd64.tar.gz"
-url_api = "https://api.github.com/repos/grafana/oats/releases/assets/487171351"
+checksum = "sha256:b72a7a587148d1eaa15ccea3ce1adfd67e040d1cd9f9e267c850154035ef9a18"
+url = "https://github.com/grafana/oats/releases/download/v0.10.0/oats_0.10.0_linux_amd64.tar.gz"
+url_api = "https://api.github.com/repos/grafana/oats/releases/assets/493772131"
provenance = "github-attestations"
[tools."aqua:grafana/oats"."platforms.macos-arm64"]
-checksum = "sha256:156bb14787a09093de8ad0370c95e8104b771ca0b3ede382541f9837db797f27"
-url = "https://github.com/grafana/oats/releases/download/v0.8.0/oats_0.8.0_darwin_arm64.tar.gz"
-url_api = "https://api.github.com/repos/grafana/oats/releases/assets/487171322"
+checksum = "sha256:570d5c3b43c0cbe0d88c527d2fcecb9ee565e2f9d1a4d49fb4b6bbf5c3fa47e5"
+url = "https://github.com/grafana/oats/releases/download/v0.10.0/oats_0.10.0_darwin_arm64.tar.gz"
+url_api = "https://api.github.com/repos/grafana/oats/releases/assets/493772124"
provenance = "github-attestations"
[tools."aqua:grafana/oats"."platforms.macos-x64"]
-checksum = "sha256:034bc120d0d8bbf8aff05f61a6b569efec821df19bd25bb602ee77d4a6368235"
-url = "https://github.com/grafana/oats/releases/download/v0.8.0/oats_0.8.0_darwin_amd64.tar.gz"
-url_api = "https://api.github.com/repos/grafana/oats/releases/assets/487171352"
+checksum = "sha256:c3579f73928df56d1cf6d6bbb90d20424649ff08c228daa4810914017f8620d8"
+url = "https://github.com/grafana/oats/releases/download/v0.10.0/oats_0.10.0_darwin_amd64.tar.gz"
+url_api = "https://api.github.com/repos/grafana/oats/releases/assets/493772123"
provenance = "github-attestations"
[tools."aqua:grafana/oats"."platforms.windows-x64"]
-checksum = "sha256:166a5577c66efa9e4d677856ae1780212ee27c081042c8d54db0c996019adbc0"
-url = "https://github.com/grafana/oats/releases/download/v0.8.0/oats_0.8.0_windows_amd64.zip"
-url_api = "https://api.github.com/repos/grafana/oats/releases/assets/487171324"
+checksum = "sha256:b52112bf0932ea8dea1fb051bc04e29efa5ef138f67d09d775c4eb716d3d92f9"
+url = "https://github.com/grafana/oats/releases/download/v0.10.0/oats_0.10.0_windows_amd64.zip"
+url_api = "https://api.github.com/repos/grafana/oats/releases/assets/493772125"
provenance = "github-attestations"
[[tools."aqua:jonwiggins/xmloxide"]]
diff --git a/mise.toml b/mise.toml
index 569a2f3bd..eb899bbe5 100644
--- a/mise.toml
+++ b/mise.toml
@@ -1,6 +1,6 @@
[tools]
"aqua:grafana/gcx" = "v1.0.0"
-"aqua:grafana/oats" = "0.8.0"
+"aqua:grafana/oats" = "0.10.0"
hugo = "0.164.0"
java = "temurin-25.0.3+9.0.LTS"
node = "24.18.0"
From 23ae29aa71825c2a83abf249fc45cca2a46e3c8b Mon Sep 17 00:00:00 2001
From: Subhramit Basu
Date: Thu, 30 Jul 2026 05:13:15 +0530
Subject: [PATCH 31/83] docs: add API design guideline to contributing docs
(#2350)
---
AGENTS.md | 7 +++++++
CONTRIBUTING.md | 7 +++++++
2 files changed, 14 insertions(+)
diff --git a/AGENTS.md b/AGENTS.md
index 24481b8e5..9c229117a 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -125,6 +125,13 @@ commits. CI will fail if these checks fail.
- Build succeeds (tests are skipped;
run `mise run test` or `mise run test-all` for tests)
+## API Design
+
+- For internal or SDK-facing classes, prefer static factories and builders
+ over adding new public constructors.
+- Keep constructors non-public unless they are intentionally part of the
+ stable API.
+
## Testing
- JUnit 5 (Jupiter) with `@Test` annotations
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 519b98fea..ece7e11e5 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -73,6 +73,13 @@ This requires native lint tools,
which you can install with `mise run setup:native-lint-tools`.
These are optional but catch formatting and lint issues before CI.
+## API Design
+
+For internal or SDK-facing classes, prefer static factories and builders over
+adding new public constructors. Constructors are difficult to evolve
+compatibly, so keep them non-public unless they are intentionally part of the
+stable API.
+
## Running Tests
If you're getting errors when running tests:
From ee64917c53c0c8698a2b70ad48342f3bb2ca535d Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 29 Jul 2026 19:43:44 -0400
Subject: [PATCH 32/83] chore(deps): update dependency
org.mock-server:mockserver-netty-no-dependencies to v7.5.0 (#2354)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
> ℹ️ **Note**
>
> This PR body was truncated due to platform limits.
This PR contains the following updates:
| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
|
[org.mock-server:mockserver-netty-no-dependencies](https://www.mock-server.com)
([source](https://redirect.github.com/mock-server/mockserver-monorepo))
| `7.4.0` → `7.5.0` |

|

|
---
### Release Notes
mock-server/mockserver-monorepo
(org.mock-server:mockserver-netty-no-dependencies)
###
[`v7.5.0`](https://redirect.github.com/mock-server/mockserver-monorepo/blob/HEAD/changelog.md#750---2026-07-29)
##### Security
- **BREAKING: response templates can no longer reach arbitrary Java
classes by default, closing the
template remote-code-execution path reported as
[GHSA-7pwj-xvc2-hfpc](https://redirect.github.com/mock-server/mockserver-monorepo/security/advisories/GHSA-7pwj-xvc2-hfpc).**
A caller who can reach the management API can register an expectation,
and a response template was able
to load `java.lang.Runtime` and execute OS commands in the MockServer
process. Both engines that could
do this are now sandboxed out of the box:
- `velocityDisallowClassLoading` now defaults to **`true`** (was
`false`), installing Velocity's
`SecureUberspector` so a template cannot reach classes through
`$request.class.classLoader.loadClass(...)`.
This is the more exposed half of the issue, and the half the report did
not cover: Velocity ships in
the DEFAULT distribution, whereas the JavaScript engine does not.
- JavaScript templates now resolve **no** Java classes unless an
operator grants them. Previously an
empty `javascriptAllowedClasses` *and* empty
`javascriptDisallowedClasses` meant unrestricted
`Java.type(...)` access; that combination — the out-of-the-box state —
now denies every class.
- The GraalJS guest context no longer grants access to the members of
`java.lang.Class` or
`java.lang.ClassLoader`. Denying classes at `Java.type(...)` alone was
**not** sufficient: real host
objects are bound into the context (`faker` and the other built-in
helpers), and under the previous
`HostAccess.ALL` a template could walk from one of them to a classloader
—
`faker.getClass().getClassLoader().loadClass('java.lang.Runtime')` —
reaching `Runtime` without the
class filter ever being consulted. That walk is now closed, so
host-class lookup is the single complete
gate; a regression test drives four such walks (including through
`request`) and fails if any resolves.
Velocity's `SecureUberspector` already blocked the equivalent walk
through its own bound helpers, which
is now covered by a test too.
Both flips are fully reversible with one property and remove no
functionality: set
`mockserver.velocityDisallowClassLoading=false`, or list the classes
your templates need in
`mockserver.javascriptAllowedClasses` (the single entry `*` lets any
class resolve again). Templates that
do not touch Java classes are unaffected, which is the overwhelming
majority — JavaScript templates have
the full ES2023 standard library available regardless of this setting. A
refused class is logged once at
WARN naming the class and the property to set, because GraalJS otherwise
surfaces a refusal only as the
class being undefined ("... is not a function"); the log is bounded and
de-duplicated so a hostile
template cannot flood it. `mockserver.javascriptAllowedClasses` is now
also settable through the Spring
test listener's `@MockServerTest` properties, which it was not before —
it was a nice-to-have while the
default was unrestricted, and is the only way to grant a class now that
it is not. The insecure-mode WARN
now fires when an operator has explicitly opened the
sandbox rather than when it is closed. Proven end-to-end by a Netty
integration test that registers the
reported payload through the real management API and asserts the OS
command creates no marker file, with
a negative control on a deliberately unsandboxed server that DOES create
it — so a regression cannot pass
as an inert payload. This lands DEF-2 and DEF-3 of
`docs/plans/later/security-defaults.md` ahead of the
other default flips listed there; JavaScript went further than that plan
proposed (deny everything, not a
built-in "safe types" allow-list) because deny-by-default is the only
form that stays safe as the JDK
grows new reachable classes.
##### Fixed
- **A property file that cannot be read is now reported instead of
ignored in silence
([#2358](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2358)).**
When a
`mockserver.propertyFile` an operator had explicitly configured could
not be read, MockServer applied
none of its properties and said nothing about it — at any log level. The
only symptom was that every
property in the file appeared to be at its default, which surfaces far
downstream as unexplained
behaviour: in the reported case an unreadable (but present) mounted file
meant `initializationJsonPath`
was never set, so no expectations loaded, no `loading JSON
initialization file:` line appeared, and no
error was logged either. The message existed but was unreachable in
practice — gated at DEBUG *and*
emitted during static initialisation, before any log level has been
applied, so neither
`-Dmockserver.logLevel=DEBUG` nor a `-logLevel` argument could surface
it. Such a file is now logged at
WARN, naming the path and the underlying reason verbatim; because
`FileNotFoundException` covers "not
there" and "not allowed to read it" alike, that reason is usually the
whole answer (`Permission denied`
in the reported case, typically SELinux labelling or a
rootless/user-namespace UID mismatch). A property
file that is merely absent at its default location stays quiet, as does
the Docker image's built-in
`-Dmockserver.propertyFile=/config/mockserver.properties`, which the
entrypoint always passes and which
therefore expresses no intent — otherwise every container started
without a mounted config would warn.
Inside the image, only `MOCKSERVER_PROPERTY_FILE` can express that
intent, and it does.
- **The `mockserver-node` launcher suite no longer fails intermittently
on a TLS handshake reset.** The
two tests that exercise `jvmOptions` did so over HTTPS against a server
started with
`dynamicallyCreateCertificateAuthorityCertificate=true`, and issued that
HTTPS request as soon as
`start_mockserver` resolved. `start_mockserver` only proves the HTTP
control plane is answering — it
polls `PUT /mockserver/retrieve` over plain HTTP — but with a
dynamically created certificate
authority the server still has to generate a CA key pair and a leaf
certificate before it can serve
TLS on that same (port-unified) port. A handshake arriving in that
window was closed mid-negotiation
and surfaced as `ECONNRESET` "Client network socket disconnected before
secure TLS connection was
established", failing whichever of the two tests lost the race. This
accounted for every
`mockserver-node` failure on `master` over the preceding 40 builds (5 of
40, \~12%), so it was the sole
cause of the pipeline's intermittent red. Both tests now wait for an
actual TLS handshake to complete
before asserting, which gates them on the condition they really depend
on rather than retrying the
assertions. The new `waitForTlsReady` helper is verified to reject — not
resolve — both when nothing
is listening and when a listener accepts the TCP connection then
destroys it mid-handshake, which is
exactly the failure signature it exists to absorb. The readiness budget
is deliberately generous
(120s): waiting costs nothing when the server is healthy, since a ready
server completes the
handshake on the first attempt in milliseconds, so the limit only
decides how much CI contention is
tolerated before a slow start is misreported as a fault. An earlier 30s
budget went green five builds
running and then expired on a loaded agent — the same flake wearing a
clearer error message. A start
that takes over 5s is now reported even when it passes, because
readiness creeping towards the limit
is the signal that the next run will not make it.
- **`archiver.glob()` works again in `@mockserver/testcontainers`
(Node), and CVE-2026-14257 stays
closed.** The previous remedy for the `brace-expansion` denial of
service (GHSA-mh99-v99m-4gvg,
patched only in 5.0.8) was a blanket `"brace-expansion": "^5.0.8"`
override. That resolved the whole
tree to a single hoisted 5.0.8 and `npm audit` reported zero
vulnerabilities — but 5.x changed the
CommonJS export from a callable function to an object (`{ expand,
EXPANSION_MAX, ... }`), while the
minimatch copies actually installed (3.1.5, 5.1.9, 9.0.9) all call it as
`expand(pattern)`. Every
glob containing a brace therefore threw `TypeError: expand is not a
function`, crashing
`archiver.glob()`. The blast radius is narrower than it first looks —
`testcontainers` copies files
with `archiver.directory()`/`.append()`, which pass no brace pattern and
still work — so what broke
is brace globbing for anything in this module's runtime tree that does
use it. The failure was
invisible because minimatch short-circuits patterns with no `{`, so
plain globs kept working and the
unit suite stayed green. The override is now targeted: `readdir-glob`
and `archiver-utils`' `glob`
take `minimatch@^10.2.5`, which depends on `brace-expansion@^5.0.5` and
is written against the new
API, so both runtime copies land on the patched 5.0.8 with a matching
minimatch. jest keeps its own
`minimatch@3.1.5` + `brace-expansion@1.1.16` pairing and is untouched.
`npm audit --omit=dev` still
reports 0 vulnerabilities, and a new `dependency-integrity` unit test
drives a brace pattern through
both runtime minimatch copies and through a real `archiver.glob()` tar,
plus asserts expansion stays
bounded — it fails against the blanket override, so the silent half of
this cannot return.
- **A forward `responseOverride` that replaces the body no longer
inherits the upstream response's
`Content-Length`, which truncated the response on the wire.** The
override swapped the body but left the
upstream header in place, so the client read only as many bytes as the
body it replaced — a 34-byte
override behind an upstream `Content-Length: 13` arrived as 13 bytes —
or hung waiting for bytes that
never came. The stale header is now dropped so the encoder recomputes it
from what is actually written;
a `Content-Length` set by the override itself, and
`connectionOptions.contentLengthHeaderOverride`, are
still honoured, and a header-only override (one that sets no body) is
untouched. This affects every body
override, and it was the remaining reason a `FILE` response body
returned from a `responseOverride`
still reached the client wrong after
[#2450](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2450):
the file was materialised
correctly and then cut short by the stale length. Covered by a Netty
integration test that drives a real
forward-with-override through a real upstream and asserts the bytes the
client receives.
- **The JetBrains plugin's LLM tool window now sends a valid expectation
([#2455](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2455)).**
"Load into Server" was
rejected with `400 incorrect expectation json format` because the
builder emitted a shape that never
existed on the server: a flat `completion` string, a top-level
`finishReason`, `stream`, and `usage`,
and a `provider` of `OPEN_AI`. The completion text, streaming flag, stop
reason, and token usage
belong INSIDE the `completion` object (`text`, `streaming`,
`stopReason`, `usage.inputTokens` /
`usage.outputTokens`), and providers are the `Provider` enum names
(`OPENAI`, `AZURE_OPENAI`, …). The
provider and field catalogues shared with the VS Code extension are
corrected the same way — they
offered `OPEN_AI`, `VERTEX_AI`, `messages`, `stream`, `finishReason` and
a top-level `usage`, none of
which the server accepts — and completion inside a `completion` object
now offers the nested fields.
The plugin has always bundled the correct schema; it simply never
validated its own output against it,
and the previous tests asserted the builder matched the same invented
shape it produced. Both editors
now validate against the bundled schema in their test suites.
- **`httpLlmResponse.provider` now accepts every provider MockServer
implements.** The JSON Schema enum
listed 9 of the 14 `org.mockserver.model.Provider` constants, so
`MISTRAL`, `XAI`, `DEEPSEEK`, `GROQ`,
and `OPENROUTER` were rejected with `400 incorrect expectation json
format` even though each has a
fully registered response codec. The five missing values are added to
the core schema, the generated
VS Code and JetBrains schemas, and both copies of the OpenAPI
specification, and a new parity test
fails if the enum and `Provider` ever diverge again in either direction.
The provider list on the
LLM response mocking documentation and in the Rust client's field docs
is updated to match.
- **The cloud blob-store, async-broker and transparent-proxy CI steps no
longer OOM-kill their own build
before any test runs.** Each ran its Docker container with
`--memory=4g`, but `mockserver/.mvn/jvm.config`
pins the Maven JVM to `-Xmx6144m` and the wrapper prepends it to
`MAVEN_OPTS`, so the `-am` dependency
build was permitted a 6 GB heap inside a 4 GB cgroup and the kernel
intermittently killed it with exit 137
— losing the very coverage those fail-closed steps exist to guarantee.
Raised each to `--memory=7g`, the
value every other `./mvnw` step already uses and which fits the
single-agent `c5.2xlarge`/`m5.2xlarge`
default-queue instances with margin.
##### Added
- **A cassette is now auto-registered when a fixture is loaded or
recorded via the MCP tools, so it
appears under `GET /mockserver/cassettes` without a separate `PUT
/mockserver/cassettes` call.**
Previously the server-side cassette registry was populated only by an
explicit
`PUT /mockserver/cassettes`, so a fixture loaded with the
`load_expectations_from_file` MCP tool, or
written with `record_llm_fixtures`, never showed up in the dashboard's
Cassettes tab unless the
caller also registered it by hand. Both MCP tool handlers now register
the fixture in
`CassetteRegistry` at the point the file is loaded/written — the file
path as the key, the loaded/
written expectation count, and an `origin` of `loaded` or `recorded`
respectively — so
`GET /mockserver/cassettes` (which serialises that registry) lists it
automatically. Re-loading or
re-recording the same path updates the existing entry in place rather
than duplicating it.
- **Clustered (Infinispan) expectation reload-on-startup is now proven
end-to-end.** A new test
(`ClusteredExpectationPersistenceReloadTest` in
`mockserver-state-infinispan`) forms an in-JVM
JGroups cluster consisting of a bare "fleet keeper"
`InfinispanStateBackend` that stays up for the
whole test plus a full MockServer node started with
`stateBackend=infinispan`,
`clusterEnabled=true` and `persistExpectations=true`. An expectation is
created on that node over
the wire, the persisted document is polled for through the *keeper's*
backend (proving it really
replicated across the REPL\_SYNC blob cache), the node is then stopped
completely, and a fresh node
is started against the same cluster and the same
`persistedExpectationsPath` — which must restore
the expectation and MATCH a real HTTP request with it. The local
persisted file is asserted to be
empty first, so the restore cannot be coming from the
filesystem-initializer route. The reload path
in `ExpectationFileSystemPersistence` was already covered at unit level
in `mockserver-core`
(`ExpectationBlobStoreRestoreTest`, against an `InMemoryBlobStore`, with
no server and no cluster)
and end-to-end only against S3/MinIO behind a Docker gate; what no test
proved is that a clustered
node's `InfinispanBlobStore` is the store `HttpState` wires into that
restore, nor that a real
restarted member of a live cluster recovers the fleet's shared
expectations. A second test sets
`blobStoreRestoreTimeoutSeconds=0` (the documented way to skip the
restore) and asserts the fresh
node does NOT serve the expectation, which permanently pins the fact
that no other mechanism —
JGroups state transfer of the expectations cache, a stray invalidation
event, or the local file —
restores expectations when a node starts. Verified by a positive
control: disabling the reload
path in production makes the restarted node answer with an empty body
and turns the test red.
- **The response-aware arm of the eviction false-green guard is now
proven end-to-end over HTTP.** A new
Netty integration test (`EvictedResponseVerificationIntegrationTest`)
boots a real server with
`maxLogEntries=2` and `failVerificationOnEvictedLog=true`, registers an
expectation so a `GET
/was-responded` exchange is recorded as a real `EXPECTATION_RESPONSE`
request-response pair, then floods
the bounded event log with further unmatched traffic so that pair is
evicted. A subsequent
`verify(request("/was-responded"), response().withStatusCode(418),
never())` through the Java client must
throw an `AssertionError` saying the **response** "could not be
verified" because entries were discarded
after reaching `maxLogEntries`. `MockServerEventLog` implements this
guard twice — once in `verifyRequest`
and once, through a completely separate counting path over recorded
pairs, in `verifyResponse` — and only
the request arm had an `*IntegrationTest`; the response arm was covered
solely by an engine-level test
against an in-process event log. The test uses `never()` because it is
the simplest shape that reaches
the guard: the guard sits on the PASS branch behind any asserted upper
bound (`getAtMost() != -1` — so
`atMost(n)`, `between(0,n)` and `exactly(0)` reach it too), whereas an
`atLeast(1)`/`once()` verification
of an evicted pair fails earlier with an ordinary "Response not found"
message and proves nothing.
`never()` is exactly the case a guard-less server would answer with a
silent false green. The assertion pins the message to `Response could
not be verified` so it cannot be
satisfied by the request-side arm. Verified by a positive control
(disabling only the response-side guard
in production makes the verification pass silently and turns the test
red).
- **The eviction false-green guard is now proven end-to-end over HTTP.**
A new Netty integration test
(`EvictedLogVerificationIntegrationTest`) boots a real server with
`maxLogEntries=2` and
`failVerificationOnEvictedLog=true`, records a `GET /was-called`
request, then floods the bounded
request-log ring with further traffic so the `/was-called` entry is
evicted. A subsequent
`verify(request("/was-called"), never())` through the Java client must
throw an `AssertionError` whose
message says the log "could not be verified" because entries were
discarded after reaching
`maxLogEntries` — proving the guard refuses to certify absence it can no
longer see, rather than
silently passing. Previously the guard was only covered by an
engine-level test against an in-process
`MockServerEventLog` and no `*IntegrationTest` exercised it across the
wire. Verified by a positive
control (disabling the guard in production makes `verify(never())` pass
silently and turns the test
red).
- **Custom gRPC response metadata and trailing metadata are now proven
against a real `grpc-java`
client.** Two new tests in `GrpcUnaryClientIntegrationTest` register an
expectation whose gRPC
response carries both custom response metadata authored with
`withHeader(...)` and custom trailing
metadata authored with `withTrailer(...)`, drive it with a live
`grpc-java` client, and read the
values back off the real `io.grpc.Metadata` objects the client receives
(via a capturing
`ClientInterceptor`, and via `StatusRuntimeException.getTrailers()` on
the error path). The
assertions are deliberately discriminating: the response metadata must
arrive in the *initial
headers* and not in the trailers, the trailing metadata must arrive in
the *trailers* and not be
folded into the initial headers, and both values must round-trip
byte-for-byte including a value
carrying `=`, `;`, `,` and spaces. Previously this behaviour was
exercised only structurally
(`EmbeddedChannel` / model-level assertions, which cannot tell a trailer
emitted as a trailer from
one folded into the headers) and by the existing `-bin` metadata tests,
which deliberately accept
the value from either side because a body-less unary response may
legitimately collapse to
Trailers-Only. Verified by positive controls: dropping the user-authored
trailers turns both tests
red, and dropping the user-authored response headers turns the header
assertion red.
- **The `maxResponseBodySize` limit is now proven behaviourally against
a real upstream.** A new
integration test (`MaxResponseBodySizeIntegrationTest`) boots a
forwarding MockServer configured with a
4KB `maxResponseBodySize`, points it at a raw upstream socket that
returns a 64KB body, and drives it
over a plain client socket: the oversized body fails the forward and the
client receives **502 Bad
Gateway** with none of the payload relayed, while a control request
whose body sits under the limit is
forwarded intact. A third case repeats the oversized body with
`Transfer-Encoding: chunked` and no
`Content-Length`, proving the cap is enforced against the bytes actually
accumulated by the forward
client's aggregator rather than merely against a declared header.
Previously this documented,
memory-protecting bound — read whenever a forward-client pipeline is
built — had no behavioural
coverage at all, so a regression that dropped the wiring (or passed an
unbounded value) would have
removed the limit silently; only the inbound analogue
`maxRequestBodySize` was verified. The new test
covers the HTTP/1.1 forward aggregator; the HTTP/2 forward path reads
the same property (for the
per-stream aggregator and to derive the client's `maxFrameSize`) and
remains uncovered.
`maxResponseBodySize` accordingly moves from `ENFORCEMENT_EXEMPT` to
`ENFORCEMENT_VERIFIED` in
`ConfigurationEnforcementClassificationTest`. Verified by a positive
control (restoring an unbounded
aggregator lets the oversized body through with a 200 and turns both
over-limit assertions red).
- **The Ruby client now proves live SSE stream consumption over the
wire.** New integration examples
(`spec/integration_spec.rb` → `SSE streaming`) register an
`httpSseResponse` expectation via the Ruby
client against a running MockServer, then open a real streaming HTTP
consumer and assert every `data:`
frame arrives in order, that the reconstructed multi-delta message
matches, and that a multi-line
`data:` payload survives the framing intact (`Content-Type:
text/event-stream`). Previously the Ruby
suite only asserted the JSON keys of a built streaming expectation
(`a2a_spec`) and never consumed a
live SSE stream, so a silent server-emission or client-parsing drop
would have gone uncaught. Verified
by a positive control (dropping events from the emitted stream turns the
received-frames assertion red).
- **The `assumeAllRequestsAreHttp` protocol-detection fallback now has
direct unit coverage.** Two
paired `EmbeddedChannel` tests in `DirectProxyUnificationHandlerTest`
drive
`PortUnificationHandler.decode()` with an HTTP request using a
non-standard method (`PURGE`, which is
not one of GET/POST/PUT/HEAD/OPTIONS/PATCH/DELETE/TRACE/CONNECT): with
`assumeAllRequestsAreHttp=true` the full HTTP pipeline is added (rather
than falling to binary request
proxying), and with the flag disabled the HTTP codec is not added —
proving the flag is the only
difference. Previously the fallback branch was exercised only by a
live-socket integration test and
the config getter's own unit test, so the `EmbeddedChannel`
protocol-detection path for the flag was
unexercised.
- **HTTP/3 streaming response bodies are now proven end-to-end through
the action pipeline with a real
QUIC client.** A new integration test
(`Http3StreamingForwardIntegrationTest`) registers a `forward`
expectation on the HTTP/3 port (with `streamingResponsesEnabled`)
pointing at an upstream Server-Sent
Events stream that serves an early event immediately and withholds the
late event for 1.5s, then drives
it with a live Netty QUIC client and asserts both events arrive as
SEPARATE DATA frames spread across
that delay — proving the streaming relay funnels through
`HttpActionHandler` ->
`ResponseWriter.writeResponse` ->
`Http3ResponseWriter.writeStreamingResponse` and emits chunks
incrementally. Previously `Http3StreamingIntegrationTest` drove
`Http3ResponseWriter` directly from a
hand-built QUIC server (bypassing expectation matching), and
`Http3MockingMatrixIntegrationTest`
exercised the real pipeline over QUIC but only with non-streaming
actions, so incremental delivery of a
streamed body through the full pipeline was untested. QUIC-gated like
the sibling HTTP/3 tests so it
skips cleanly where the native transport is unavailable.
- **The dashboard's Monaco code editor is now proven in a real browser
end-to-end.** A new Playwright
e2e test (`mockserver-ui/e2e/dashboard.spec.ts`) drives the actual
bundled Monaco editor in the
served dashboard's composer against a live MockServer: it asserts
Monaco's own DOM
(`.monaco-editor` / `.view-lines`) renders, authors a JSON response body
via real editor input,
raises and clears a live validation marker from Monaco's JSON language
web worker, then registers
the mock and confirms the Monaco-authored body round-trips to the server
(present in
`PUT /mockserver/retrieve` and served verbatim on the matching request).
Previously the 178
jsdom/vitest specs globally replaced Monaco with a bare `
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/prometheus/client_java).
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
prometheus-metrics-exporter-pushgateway/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/prometheus-metrics-exporter-pushgateway/pom.xml b/prometheus-metrics-exporter-pushgateway/pom.xml
index b83119bbb..b51d7c622 100644
--- a/prometheus-metrics-exporter-pushgateway/pom.xml
+++ b/prometheus-metrics-exporter-pushgateway/pom.xml
@@ -35,7 +35,7 @@
org.mock-server
mockserver-netty-no-dependencies
- 7.4.0
+ 7.5.0
test
From ed46db842f136bac47e29bd23fbc335e81eadd53 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 29 Jul 2026 20:39:34 -0400
Subject: [PATCH 33/83] chore(deps): update node.js to v24.18.1 (#2353)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [node](https://nodejs.org)
([source](https://redirect.github.com/nodejs/node)) | patch | `24.18.0`
→ `24.18.1` |
---
### Release Notes
nodejs/node (node)
###
[`v24.18.1`](https://redirect.github.com/nodejs/node/releases/tag/v24.18.1):
2026-07-29, Version 24.18.1 'Krypton' (LTS), @juanarbol
[Compare
Source](https://redirect.github.com/nodejs/node/compare/v24.18.0...v24.18.1)
This is a security release.
##### Notable Changes
- (CVE-2026-56846) http2: retain header memory in session accounting
(Matteo Collina) – High
- (CVE-2026-56848) http2: defer rst stream while in scope (Matteo
Collina) – High
- (CVE-2026-58043) permission: avoid granting radix split nodes
(RafaelGSS) – High
- (CVE-2026-56850) https: distinguish PFX object-array agent keys
(RafaelGSS) – Medium
- (CVE-2026-58040) https: bind identity checks to session reuse (Matteo
Collina) – Medium
- (CVE-2026-58041) sqlite: invalidate tag store iterators on statement
reset (Matteo Collina) – Medium
- (CVE-2026-58042) dns: handle large resolveAny address replies
(RafaelGSS) – Medium
- (CVE-2026-58045) zlib: throw on out-of-bounds write buffers
(RafaelGSS) – Medium
- (CVE-2026-56847) permission: enforce fs write permission for trace
events (RafaelGSS) – Low
- (CVE-2026-58039) permission: check final report output path
(RafaelGSS) – Low
- (CVE-2026-58044) http: reject requests exceeding max header count
(Matteo Collina) – Low
- deps: update llhttp to 9.4.3 (Paolo Insogna)
- deps: update undici to 7.29.0 (Node.js GitHub Bot)
##### Commits
-
\[[`6cb0475751`](https://redirect.github.com/nodejs/node/commit/6cb0475751)]
- **deps**: update llhttp to 9.4.3 (Paolo Insogna)
[nodejs-private/node-private#935](https://redirect.github.com/nodejs-private/node-private/pull/935)
-
\[[`bcfe21d3dc`](https://redirect.github.com/nodejs/node/commit/bcfe21d3dc)]
- **deps**: update undici to 7.29.0 (Node.js GitHub Bot)
[#64713](https://redirect.github.com/nodejs/node/pull/64713)
-
\[[`9d0d36cffd`](https://redirect.github.com/nodejs/node/commit/9d0d36cffd)]
- **(CVE-2026-58042)** **dns**: handle large resolveAny address replies
(RafaelGSS)
[nodejs-private/node-private#929](https://redirect.github.com/nodejs-private/node-private/pull/929)
-
\[[`8a008fb523`](https://redirect.github.com/nodejs/node/commit/8a008fb523)]
- **(CVE-2026-58044)** **http**: reject requests exceeding max header
count (Matteo Collina)
[nodejs-private/node-private#922](https://redirect.github.com/nodejs-private/node-private/pull/922)
-
\[[`a77c7f7354`](https://redirect.github.com/nodejs/node/commit/a77c7f7354)]
- **(CVE-2026-56848)** **http2**: defer rst stream while in scope
(Matteo Collina)
[nodejs-private/node-private#921](https://redirect.github.com/nodejs-private/node-private/pull/921)
-
\[[`34ed88a069`](https://redirect.github.com/nodejs/node/commit/34ed88a069)]
- **(CVE-2026-56846)** **http2**: retain header memory in session
accounting (Matteo Collina)
[#63752](https://redirect.github.com/nodejs/node/pull/63752)
-
\[[`95ba2cfde7`](https://redirect.github.com/nodejs/node/commit/95ba2cfde7)]
- **(CVE-2026-58040)** **https**: bind identity checks to session reuse
(Matteo Collina)
[nodejs-private/node-private#904](https://redirect.github.com/nodejs-private/node-private/pull/904)
-
\[[`fcbdbe47ea`](https://redirect.github.com/nodejs/node/commit/fcbdbe47ea)]
- **(CVE-2026-56850)** **https**: distinguish PFX object-array agent
keys (RafaelGSS)
[nodejs-private/node-private#930](https://redirect.github.com/nodejs-private/node-private/pull/930)
-
\[[`ea26c12b56`](https://redirect.github.com/nodejs/node/commit/ea26c12b56)]
- **(CVE-2026-58043)** **permission**: avoid granting radix split nodes
(RafaelGSS)
[nodejs-private/node-private#911](https://redirect.github.com/nodejs-private/node-private/pull/911)
-
\[[`9a6b7e343a`](https://redirect.github.com/nodejs/node/commit/9a6b7e343a)]
- **(CVE-2026-58039)** **permission**: check final report output path
(RafaelGSS)
[nodejs-private/node-private#926](https://redirect.github.com/nodejs-private/node-private/pull/926)
-
\[[`6c0c990880`](https://redirect.github.com/nodejs/node/commit/6c0c990880)]
- **(CVE-2026-56847)** **permission**: enforce fs write permission for
trace events (RafaelGSS)
[nodejs-private/node-private#927](https://redirect.github.com/nodejs-private/node-private/pull/927)
-
\[[`af9ff0490c`](https://redirect.github.com/nodejs/node/commit/af9ff0490c)]
- **(CVE-2026-58041)** **sqlite**: invalidate tag store iterators on
statement reset (Matteo Collina)
[nodejs-private/node-private#896](https://redirect.github.com/nodejs-private/node-private/pull/896)
-
\[[`05f541b5c0`](https://redirect.github.com/nodejs/node/commit/05f541b5c0)]
- **(CVE-2026-58045)** **zlib**: throw on out-of-bounds write buffers
(RafaelGSS)
[nodejs-private/node-private#931](https://redirect.github.com/nodejs-private/node-private/pull/931)
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/prometheus/client_java).
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
mise.lock | 28 +++++++++++++---------------
mise.toml | 2 +-
2 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/mise.lock b/mise.lock
index ba618bcba..0dff26c57 100644
--- a/mise.lock
+++ b/mise.lock
@@ -480,36 +480,34 @@ url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.24.2/ly
url_api = "https://api.github.com/repos/lycheeverse/lychee/releases/assets/409959491"
[[tools.node]]
-version = "24.18.0"
+version = "24.18.1"
backend = "core:node"
[tools.node."platforms.linux-arm64"]
-checksum = "sha256:6b4484c2190274175df9aa8f28e2d758a819cb1c1fe6ab481e2f95b463ab8508"
-url = "https://nodejs.org/dist/v24.18.0/node-v24.18.0-linux-arm64.tar.gz"
+checksum = "sha256:df224555a083b918e46260cc969838501b9f9a87140c1195e5b9597b56d5dae2"
+url = "https://nodejs.org/dist/v24.18.1/node-v24.18.1-linux-arm64.tar.gz"
[tools.node."platforms.linux-arm64-musl"]
-checksum = "sha256:b1c6c2dc31b46dd8fb2322f4fe75b07e775c5120bc37251deeea28f529d4567b"
-url = "https://unofficial-builds.nodejs.org/download/release/v24.18.0/node-v24.18.0-linux-arm64-musl.tar.gz"
+url = "https://unofficial-builds.nodejs.org/download/release/v24.18.1/node-v24.18.1-linux-arm64-musl.tar.gz"
[tools.node."platforms.linux-x64"]
-checksum = "sha256:783130984963db7ba9cbd01089eaf2c2efb055c7c1693c943174b967b3050cb8"
-url = "https://nodejs.org/dist/v24.18.0/node-v24.18.0-linux-x64.tar.gz"
+checksum = "sha256:9f5eb6ac21845a66c493c91a253b1da32fd684e89e9b7202d4936982336be4ca"
+url = "https://nodejs.org/dist/v24.18.1/node-v24.18.1-linux-x64.tar.gz"
[tools.node."platforms.linux-x64-musl"]
-checksum = "sha256:ea58409911e141ec6b19d9178efa2d9185a13295005b1cbf5521b3157eed1d95"
-url = "https://unofficial-builds.nodejs.org/download/release/v24.18.0/node-v24.18.0-linux-x64-musl.tar.gz"
+url = "https://unofficial-builds.nodejs.org/download/release/v24.18.1/node-v24.18.1-linux-x64-musl.tar.gz"
[tools.node."platforms.macos-arm64"]
-checksum = "sha256:e1a97e14c99c803e96c7339403282ea05a499c32f8d83defe9ef5ec66f979ed1"
-url = "https://nodejs.org/dist/v24.18.0/node-v24.18.0-darwin-arm64.tar.gz"
+checksum = "sha256:eb02f7fab96d3d67de40c5ec8566096fcb4c2026728787683ae5a97eb612b941"
+url = "https://nodejs.org/dist/v24.18.1/node-v24.18.1-darwin-arm64.tar.gz"
[tools.node."platforms.macos-x64"]
-checksum = "sha256:dfd0dbd3e721503434df7b7205e719f61b3a3a31b2bcf9729b8b91fea240f080"
-url = "https://nodejs.org/dist/v24.18.0/node-v24.18.0-darwin-x64.tar.gz"
+checksum = "sha256:6fb20fceacbb157c2f95825b80df4a454a0f6d81cdcd7bb81eeae9147e0e76ec"
+url = "https://nodejs.org/dist/v24.18.1/node-v24.18.1-darwin-x64.tar.gz"
[tools.node."platforms.windows-x64"]
-checksum = "sha256:0ae68406b42d7725661da979b1403ec9926da205c6770827f33aac9d8f26e821"
-url = "https://nodejs.org/dist/v24.18.0/node-v24.18.0-win-x64.zip"
+checksum = "sha256:ec56b84a7551893ab2324ebdfdc4ab974a63b4781162600b68a1293cc3e53765"
+url = "https://nodejs.org/dist/v24.18.1/node-v24.18.1-win-x64.zip"
[[tools."npm:renovate"]]
version = "43.279.1"
diff --git a/mise.toml b/mise.toml
index eb899bbe5..1ab071d68 100644
--- a/mise.toml
+++ b/mise.toml
@@ -3,7 +3,7 @@
"aqua:grafana/oats" = "0.10.0"
hugo = "0.164.0"
java = "temurin-25.0.3+9.0.LTS"
-node = "24.18.0"
+node = "24.18.1"
protoc = "35.1"
# Linters
From e5198bd5f89425c63a6c627d24d5ab349b933eeb Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 30 Jul 2026 07:16:55 -0400
Subject: [PATCH 34/83] chore(deps): update github/codeql-action action to
v4.37.4 (#2355)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
|
[github/codeql-action](https://redirect.github.com/github/codeql-action)
| action | patch | `v4.37.3` → `v4.37.4` |
---
### Release Notes
github/codeql-action (github/codeql-action)
###
[`v4.37.4`](https://redirect.github.com/github/codeql-action/compare/v4.37.3...v4.37.4)
[Compare
Source](https://redirect.github.com/github/codeql-action/compare/v4.37.3...v4.37.4)
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/prometheus/client_java).
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
.github/workflows/codeql.yml | 4 ++--
.github/workflows/scorecard.yml | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 4d0950bed..db005e80c 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -37,7 +37,7 @@ jobs:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-codeql-${{ hashFiles('**/pom.xml') }}
- name: Initialize CodeQL
- uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
+ uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
with:
languages: java
tools: linked
@@ -56,6 +56,6 @@ jobs:
-Djavadoc.skip=true
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
+ uses: github/codeql-action/analyze@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
with:
category: /language:java
diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml
index a2512f957..dd43bbaf5 100644
--- a/.github/workflows/scorecard.yml
+++ b/.github/workflows/scorecard.yml
@@ -41,6 +41,6 @@ jobs:
retention-days: 5
- name: Upload to code scanning
- uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
+ uses: github/codeql-action/upload-sarif@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
with:
sarif_file: results.sarif
From 34045542970750463b2956e426388fdaca0d3b07 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 30 Jul 2026 07:17:11 -0400
Subject: [PATCH 35/83] chore(deps): update dependency
org.apache.felix:maven-bundle-plugin to v6.1.0 (#2356)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This PR contains the following updates:
| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
|
[org.apache.felix:maven-bundle-plugin](http://felix.apache.org/components/bundle-plugin/)
([source](https://gitbox.apache.org/repos/asf?p=felix-dev.git)) |
`6.0.2` → `6.1.0` |

|

|
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/prometheus/client_java).
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index d03c6cd6c..32e30634c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -281,7 +281,7 @@
org.apache.felix
maven-bundle-plugin
- 6.0.2
+ 6.1.0
true
From 2d315426771022eb7d81e442767adb6183d98579 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 31 Jul 2026 08:42:48 -0400
Subject: [PATCH 36/83] chore(deps): update prom/prometheus docker tag to
v3.13.2 (#2357)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [prom/prometheus](https://redirect.github.com/prometheus/prometheus) |
patch | `v3.13.1` → `v3.13.2` |
---
### Release Notes
prometheus/prometheus (prom/prometheus)
###
[`v3.13.2`](https://redirect.github.com/prometheus/prometheus/compare/v3.13.1...v3.13.2)
[Compare
Source](https://redirect.github.com/prometheus/prometheus/compare/v3.13.1...v3.13.2)
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/prometheus/client_java).
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
examples/example-custom-buckets/docker-compose.yaml | 2 +-
examples/example-exemplars-tail-sampling/docker-compose.yaml | 2 +-
examples/example-exporter-opentelemetry/docker-compose.yaml | 2 +-
examples/example-native-histogram/docker-compose.yaml | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/examples/example-custom-buckets/docker-compose.yaml b/examples/example-custom-buckets/docker-compose.yaml
index 509ef6f3d..4f7bdd5e6 100644
--- a/examples/example-custom-buckets/docker-compose.yaml
+++ b/examples/example-custom-buckets/docker-compose.yaml
@@ -10,7 +10,7 @@ services:
- -jar
- /example-custom-buckets.jar
prometheus:
- image: prom/prometheus:v3.13.1@sha256:3c42b892cf723fa54d2f262c37a0e1f80aa8c8ddb1da7b9b0df9455a35a7f893
+ image: prom/prometheus:v3.13.2@sha256:508729e0e2d18e11fd742a5a5ca70e557b940a93948c3c95fd0123a6fd538b69
network_mode: host
volumes:
- ./docker-compose/prometheus.yml:/prometheus.yml
diff --git a/examples/example-exemplars-tail-sampling/docker-compose.yaml b/examples/example-exemplars-tail-sampling/docker-compose.yaml
index f03204807..780431624 100644
--- a/examples/example-exemplars-tail-sampling/docker-compose.yaml
+++ b/examples/example-exemplars-tail-sampling/docker-compose.yaml
@@ -43,7 +43,7 @@ services:
command:
- --config=file:/config.yaml
prometheus:
- image: prom/prometheus:v3.13.1@sha256:3c42b892cf723fa54d2f262c37a0e1f80aa8c8ddb1da7b9b0df9455a35a7f893
+ image: prom/prometheus:v3.13.2@sha256:508729e0e2d18e11fd742a5a5ca70e557b940a93948c3c95fd0123a6fd538b69
network_mode: host
volumes:
- ./config/prometheus.yaml:/prometheus.yaml
diff --git a/examples/example-exporter-opentelemetry/docker-compose.yaml b/examples/example-exporter-opentelemetry/docker-compose.yaml
index 4e526c3fb..7ab385bb3 100644
--- a/examples/example-exporter-opentelemetry/docker-compose.yaml
+++ b/examples/example-exporter-opentelemetry/docker-compose.yaml
@@ -20,7 +20,7 @@ services:
command:
- --config=file:/config.yaml
prometheus:
- image: prom/prometheus:v3.13.1@sha256:3c42b892cf723fa54d2f262c37a0e1f80aa8c8ddb1da7b9b0df9455a35a7f893
+ image: prom/prometheus:v3.13.2@sha256:508729e0e2d18e11fd742a5a5ca70e557b940a93948c3c95fd0123a6fd538b69
network_mode: host
volumes:
- ./config/prometheus.yaml:/prometheus.yaml
diff --git a/examples/example-native-histogram/docker-compose.yaml b/examples/example-native-histogram/docker-compose.yaml
index 5e2d70398..899ff275c 100644
--- a/examples/example-native-histogram/docker-compose.yaml
+++ b/examples/example-native-histogram/docker-compose.yaml
@@ -10,7 +10,7 @@ services:
- -jar
- /example-native-histogram.jar
prometheus:
- image: prom/prometheus:v3.13.1@sha256:3c42b892cf723fa54d2f262c37a0e1f80aa8c8ddb1da7b9b0df9455a35a7f893
+ image: prom/prometheus:v3.13.2@sha256:508729e0e2d18e11fd742a5a5ca70e557b940a93948c3c95fd0123a6fd538b69
network_mode: host
volumes:
- ./docker-compose/prometheus.yml:/prometheus.yml
From 7e7e53364496a1dd6d21d2c01c59219166d7826d Mon Sep 17 00:00:00 2001
From: Gregor Zeitlinger
Date: Fri, 31 Jul 2026 14:45:13 +0200
Subject: [PATCH 37/83] fix: redact invalid configuration values (#2335)
---
.../config/ExporterPushgatewayProperties.java | 12 +++++-------
.../config/PrometheusPropertiesLoader.java | 3 +--
.../java/io/prometheus/metrics/config/Util.java | 14 +++++++++-----
.../metrics/config/ExporterPropertiesTest.java | 9 +++------
.../ExporterPushgatewayPropertiesTest.java | 4 ++--
.../config/OpenMetrics2PropertiesTest.java | 17 +++++------------
.../config/PrometheusPropertiesLoaderTest.java | 5 ++---
.../io/prometheus/metrics/config/UtilTest.java | 14 +++++++++++++-
.../exporter/pushgateway/PushGateway.java | 4 ++--
.../exporter/pushgateway/PushGatewayTest.java | 10 ++++++++++
10 files changed, 52 insertions(+), 40 deletions(-)
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java
index 10e8c0f33..e97ade191 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java
@@ -94,9 +94,8 @@ static ExporterPushgatewayProperties load(PropertySource propertySource)
if (scheme != null) {
if (!scheme.equals("http") && !scheme.equals("https")) {
throw new PrometheusPropertiesException(
- String.format(
- "%s.%s: Illegal value. Expecting 'http' or 'https'. Found: %s",
- PREFIX, SCHEME, scheme));
+ Util.invalidValueMessage(
+ PREFIX + "." + SCHEME, "Illegal value. Expecting 'http' or 'https'."));
}
}
@@ -119,10 +118,9 @@ static ExporterPushgatewayProperties load(PropertySource propertySource)
return EscapingScheme.DOTS_ESCAPING;
default:
throw new PrometheusPropertiesException(
- String.format(
- "%s.%s: Illegal value. Expecting 'allow-utf-8', 'values', 'underscores', "
- + "or 'dots'. Found: %s",
- PREFIX, ESCAPING_SCHEME, scheme));
+ Util.invalidValueMessage(
+ PREFIX + "." + ESCAPING_SCHEME,
+ "Illegal value. Expecting 'allow-utf-8', 'values', 'underscores', or 'dots'."));
}
}
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesLoader.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesLoader.java
index 6d52b71ef..04bbfe4a5 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesLoader.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesLoader.java
@@ -169,8 +169,7 @@ private static Properties loadPropertiesFromFile() throws PrometheusPropertiesEx
try (InputStream stream = Files.newInputStream(Paths.get(path))) {
properties.load(stream);
} catch (IOException e) {
- throw new PrometheusPropertiesException(
- "Failed to read Prometheus properties from " + path + ": " + e.getMessage(), e);
+ throw new PrometheusPropertiesException("Failed to read Prometheus properties file.", e);
}
}
return properties;
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/Util.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/Util.java
index 20bd75699..d90810faf 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/Util.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/Util.java
@@ -24,7 +24,7 @@ static Boolean loadBoolean(String prefix, String propertyName, PropertySource pr
String fullKey = prefix.isEmpty() ? propertyName : prefix + "." + propertyName;
if (!"true".equalsIgnoreCase(property) && !"false".equalsIgnoreCase(property)) {
throw new PrometheusPropertiesException(
- String.format("%s: Expecting 'true' or 'false'. Found: %s", fullKey, property));
+ invalidValueMessage(fullKey, "Expecting 'true' or 'false'."));
}
return Boolean.parseBoolean(property);
}
@@ -88,7 +88,7 @@ static List loadDoubleList(
}
} catch (NumberFormatException e) {
throw new PrometheusPropertiesException(
- fullKey + "=" + property + ": Expecting comma separated list of double values");
+ invalidValueMessage(fullKey, "Expecting comma separated list of double values"));
}
}
return Arrays.asList(result);
@@ -130,7 +130,7 @@ static Integer loadInteger(String prefix, String propertyName, PropertySource pr
return Integer.parseInt(property);
} catch (NumberFormatException e) {
throw new PrometheusPropertiesException(
- fullKey + "=" + property + ": Expecting integer value");
+ invalidValueMessage(fullKey, "Expecting integer value"));
}
}
return null;
@@ -146,7 +146,7 @@ static Double loadDouble(String prefix, String propertyName, PropertySource prop
return Double.parseDouble(property);
} catch (NumberFormatException e) {
throw new PrometheusPropertiesException(
- fullKey + "=" + property + ": Expecting double value");
+ invalidValueMessage(fullKey, "Expecting double value"));
}
}
return null;
@@ -162,7 +162,7 @@ static Long loadLong(String prefix, String propertyName, PropertySource property
return Long.parseLong(property);
} catch (NumberFormatException e) {
throw new PrometheusPropertiesException(
- fullKey + "=" + property + ": Expecting long value");
+ invalidValueMessage(fullKey, "Expecting long value"));
}
}
return null;
@@ -197,4 +197,8 @@ static void assertValue(
throw new PrometheusPropertiesException(fullMessage);
}
}
+
+ static String invalidValueMessage(String fullKey, String message) {
+ return fullKey + ": " + message;
+ }
}
diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPropertiesTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPropertiesTest.java
index 514c5ff52..2f912ff77 100644
--- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPropertiesTest.java
+++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPropertiesTest.java
@@ -27,8 +27,7 @@ void load() {
new HashMap<>(
Map.of("io.prometheus.exporter.include_created_timestamps", "invalid"))))
.withMessage(
- "io.prometheus.exporter.include_created_timestamps: Expecting 'true' or 'false'. Found:"
- + " invalid");
+ "io.prometheus.exporter.include_created_timestamps: Expecting 'true' or 'false'.");
assertThatExceptionOfType(PrometheusPropertiesException.class)
.isThrownBy(
() ->
@@ -36,8 +35,7 @@ void load() {
new HashMap<>(
Map.of("io.prometheus.exporter.exemplars_on_all_metric_types", "invalid"))))
.withMessage(
- "io.prometheus.exporter.exemplars_on_all_metric_types: Expecting 'true' or 'false'."
- + " Found: invalid");
+ "io.prometheus.exporter.exemplars_on_all_metric_types: Expecting 'true' or 'false'.");
}
private static ExporterProperties load(Map map) {
@@ -84,7 +82,6 @@ void prometheusTimestampsInMs() {
new HashMap<>(
Map.of("io.prometheus.exporter.prometheus_timestamps_in_ms", "invalid"))))
.withMessage(
- "io.prometheus.exporter.prometheus_timestamps_in_ms: Expecting 'true' or 'false'."
- + " Found: invalid");
+ "io.prometheus.exporter.prometheus_timestamps_in_ms: Expecting 'true' or 'false'.");
}
}
diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPushgatewayPropertiesTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPushgatewayPropertiesTest.java
index c92e6f2f9..4715662f3 100644
--- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPushgatewayPropertiesTest.java
+++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPushgatewayPropertiesTest.java
@@ -27,7 +27,7 @@ void load() {
.isThrownBy(() -> load(Map.of("io.prometheus.exporter.pushgateway.scheme", "foo")))
.withMessage(
"io.prometheus.exporter.pushgateway.scheme: Illegal value. Expecting 'http' or 'https'."
- + " Found: foo");
+ + "");
}
@Test
@@ -60,7 +60,7 @@ void loadWithInvalidEscapingScheme() {
() -> load(Map.of("io.prometheus.exporter.pushgateway.escaping_scheme", "invalid")))
.withMessage(
"io.prometheus.exporter.pushgateway.escaping_scheme: Illegal value. Expecting"
- + " 'allow-utf-8', 'values', 'underscores', or 'dots'. Found: invalid");
+ + " 'allow-utf-8', 'values', 'underscores', or 'dots'.");
}
@Test
diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/OpenMetrics2PropertiesTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/OpenMetrics2PropertiesTest.java
index e7a273464..0546a138f 100644
--- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/OpenMetrics2PropertiesTest.java
+++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/OpenMetrics2PropertiesTest.java
@@ -37,8 +37,7 @@ void loadInvalidValue() {
assertThatExceptionOfType(PrometheusPropertiesException.class)
.isThrownBy(
() -> load(new HashMap<>(Map.of("io.prometheus.openmetrics2.enabled", "invalid"))))
- .withMessage(
- "io.prometheus.openmetrics2.enabled: Expecting 'true' or 'false'. Found: invalid");
+ .withMessage("io.prometheus.openmetrics2.enabled: Expecting 'true' or 'false'.");
assertThatExceptionOfType(PrometheusPropertiesException.class)
.isThrownBy(
() ->
@@ -46,17 +45,14 @@ void loadInvalidValue() {
new HashMap<>(
Map.of("io.prometheus.openmetrics2.content_negotiation", "invalid"))))
.withMessage(
- "io.prometheus.openmetrics2.content_negotiation: Expecting 'true' or 'false'. Found:"
- + " invalid");
+ "io.prometheus.openmetrics2.content_negotiation: Expecting 'true' or 'false'.");
assertThatExceptionOfType(PrometheusPropertiesException.class)
.isThrownBy(
() ->
load(
new HashMap<>(
Map.of("io.prometheus.openmetrics2.composite_values", "invalid"))))
- .withMessage(
- "io.prometheus.openmetrics2.composite_values: Expecting 'true' or 'false'. Found:"
- + " invalid");
+ .withMessage("io.prometheus.openmetrics2.composite_values: Expecting 'true' or 'false'.");
assertThatExceptionOfType(PrometheusPropertiesException.class)
.isThrownBy(
() ->
@@ -64,17 +60,14 @@ void loadInvalidValue() {
new HashMap<>(
Map.of("io.prometheus.openmetrics2.exemplar_compliance", "invalid"))))
.withMessage(
- "io.prometheus.openmetrics2.exemplar_compliance: Expecting 'true' or 'false'. Found:"
- + " invalid");
+ "io.prometheus.openmetrics2.exemplar_compliance: Expecting 'true' or 'false'.");
assertThatExceptionOfType(PrometheusPropertiesException.class)
.isThrownBy(
() ->
load(
new HashMap<>(
Map.of("io.prometheus.openmetrics2.native_histograms", "invalid"))))
- .withMessage(
- "io.prometheus.openmetrics2.native_histograms: Expecting 'true' or 'false'. Found:"
- + " invalid");
+ .withMessage("io.prometheus.openmetrics2.native_histograms: Expecting 'true' or 'false'.");
}
private static OpenMetrics2Properties load(Map map) {
diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/PrometheusPropertiesLoaderTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/PrometheusPropertiesLoaderTest.java
index 532b00295..8f910cceb 100644
--- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/PrometheusPropertiesLoaderTest.java
+++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/PrometheusPropertiesLoaderTest.java
@@ -31,9 +31,8 @@ void propertiesShouldBeLoadedFromPropertiesFile() {
void cantLoadPropertiesFile() {
assertThatExceptionOfType(PrometheusPropertiesException.class)
.isThrownBy(() -> PrometheusPropertiesLoader.load(new Properties()))
- .withMessage(
- "Failed to read Prometheus properties from nonexistent.properties:"
- + " nonexistent.properties");
+ .withMessage("Failed to read Prometheus properties file.")
+ .withMessageNotContaining("nonexistent.properties");
}
@Test
diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/UtilTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/UtilTest.java
index e4d7fa829..c3ed65ec7 100644
--- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/UtilTest.java
+++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/UtilTest.java
@@ -51,6 +51,18 @@ void loadOptionalDuration_invalidNumber_throws() {
assertThatExceptionOfType(PrometheusPropertiesException.class)
.isThrownBy(() -> Util.loadOptionalDuration("", "foo", propertySource))
- .withMessage("foo=abc: Expecting long value");
+ .withMessage("foo: Expecting long value");
+ }
+
+ @Test
+ void invalidValueMessageRedactsRawValue() {
+ String secret = "bad\n\"secret-value";
+ Map
{area}
{/each} ``` Valid: ```svelte {#each boxes as box} {const area = $derived(box.width * box.height)}{area}
{/each} ``` - [#11252](https://redirect.github.com/biomejs/biome/pull/11252) [`d5f5704`](https://redirect.github.com/biomejs/biome/commit/d5f570414fdcdddf62372e35c05f6dababad9287) Thanks [@Turtle-Hwan](https://redirect.github.com/Turtle-Hwan)! - Fixed [#11250](https://redirect.github.com/biomejs/biome/issues/11250): [`useAwait`](https://biomejs.dev/linter/rules/use-await/) no longer reports async functions that contain an `await using` declaration. - [#11143](https://redirect.github.com/biomejs/biome/pull/11143) [`6be7be1`](https://redirect.github.com/biomejs/biome/commit/6be7be1b147d7b4352ff5625a78bd54a48958950) Thanks [@vznh](https://redirect.github.com/vznh)! - Fixed [#11017](https://redirect.github.com/biomejs/biome/issues/11017): [`noUselessUndefined`](https://biomejs.dev/linter/rules/no-useless-undefined/) no longer reports `return undefined` when the enclosing function has a return type annotation other than `undefined` or `void`. - [#11234](https://redirect.github.com/biomejs/biome/pull/11234) [`caefe39`](https://redirect.github.com/biomejs/biome/commit/caefe393c66340914c481f7ccfc82979cf76b61b) Thanks [@subotac](https://redirect.github.com/subotac)! - Fixed [#11228](https://redirect.github.com/biomejs/biome/issues/11228): CSS block comments between a declaration colon and value now preserve their source indentation. ```diff :root { --font-stack: -/* comment */ + /* comment */ system-ui; } ``` - [#11285](https://redirect.github.com/biomejs/biome/pull/11285) [`bca1f73`](https://redirect.github.com/biomejs/biome/commit/bca1f73d939423056337bfd0a42cbdcb66bb1e3f) Thanks [@denbezrukov](https://redirect.github.com/denbezrukov)! - Fixed [#11280](https://redirect.github.com/biomejs/biome/issues/11280): CSS formatting keeps comments inside functional pseudo-classes and pseudo-elements instead of moving them before the function name. ```diff -:/* comment */ where(div) {} +:where(/* comment */ div) {} ``` - [#11080](https://redirect.github.com/biomejs/biome/pull/11080) [`af16a0b`](https://redirect.github.com/biomejs/biome/commit/af16a0bf884c48bad2caab70e7930096e81e1c99) Thanks [@dyc3](https://redirect.github.com/dyc3)! - HTML `style` attribute values are now parsed as CSS. All Biome CSS lint rules are applied to the `style` attributes. - [#11195](https://redirect.github.com/biomejs/biome/pull/11195) [`6a85588`](https://redirect.github.com/biomejs/biome/commit/6a85588578725195625281984a47c9a8563bf103) Thanks [@dyc3](https://redirect.github.com/dyc3)! - Fixed Svelte files failing to parse when an expression begins with an object literal. Now the following snippet is correctly parsed: ```svelte{{ a: true }}
``` - [#11173](https://redirect.github.com/biomejs/biome/pull/11173) [`481d008`](https://redirect.github.com/biomejs/biome/commit/481d008f6e8872a78749496fbbf1f9c761d9a770) Thanks [@Austin1serb](https://redirect.github.com/Austin1serb)! - Fixed [#10242](https://redirect.github.com/biomejs/biome/issues/10242): JavaScript GritQL patterns with multiple metavariables now match snippets consistently in WebAssembly. - [#11187](https://redirect.github.com/biomejs/biome/pull/11187) [`23c0369`](https://redirect.github.com/biomejs/biome/commit/23c0369c43b59284ca68c65883d6ede4228b6fb8) Thanks [@ematipico](https://redirect.github.com/ematipico)! - Added the nursery rule [`noInvalidPropertyInitValue`](https://biomejs.dev/linter/rules/no-invalid-property-init-value/), which reports an `@property` whose `initial-value` does not match its `syntax` descriptor. For example, the following declaration triggers the rule because `red` is not a `