\n"
+ " */\n"
+ )
+
+ for cls in (
+ "CounterBenchmark",
+ "HistogramBenchmark",
+ "TextFormatUtilBenchmark",
+ ):
+ fname = os.path.join(self.module_path, f"{cls}.java")
+ with open(fname, "w", encoding="utf-8") as f:
+ f.write(javadoc_pre)
+ f.write(f"public class {cls} {{}}\n")
+ self.files[cls] = fname
+
+ def tearDown(self):
+ self.tmpdir.cleanup()
+
+ def _read_pre_contents(self, path):
+ with open(path, "r", encoding="utf-8") as f:
+ content = f.read()
+ m = re.search(r"
\n([\s\S]*?)
", content)
+ return m.group(1) if m else ""
+
+ def test_update_only_inserts_matching_class_lines(self):
+ updated = update_pre_blocks_under_module(self.module_path, self.table)
+ # All three files should be updated
+ self.assertEqual(
+ {os.path.basename(p) for p in updated},
+ {
+ os.path.basename(self.files["CounterBenchmark"]),
+ os.path.basename(self.files["HistogramBenchmark"]),
+ os.path.basename(self.files["TextFormatUtilBenchmark"]),
+ },
+ )
+
+ # Verify CounterBenchmark file contains only CounterBenchmark lines
+ cb_pre = self._read_pre_contents(self.files["CounterBenchmark"])
+ self.assertIn("CounterBenchmark.codahaleIncNoLabels", cb_pre)
+ self.assertIn("CounterBenchmark.prometheusInc", cb_pre)
+ self.assertNotIn("HistogramBenchmark.prometheusNative", cb_pre)
+ self.assertNotIn("TextFormatUtilBenchmark.prometheusWriteToNull", cb_pre)
+
+ # Verify HistogramBenchmark contains only its line
+ hb_pre = self._read_pre_contents(self.files["HistogramBenchmark"])
+ self.assertIn("HistogramBenchmark.prometheusNative", hb_pre)
+ self.assertNotIn("CounterBenchmark.codahaleIncNoLabels", hb_pre)
+ self.assertNotIn("TextFormatUtilBenchmark.prometheusWriteToNull", hb_pre)
+
+ # Verify TextFormatUtilBenchmark contains only its line
+ tf_pre = self._read_pre_contents(self.files["TextFormatUtilBenchmark"])
+ self.assertIn("TextFormatUtilBenchmark.prometheusWriteToNull", tf_pre)
+ self.assertNotIn("CounterBenchmark.prometheusInc", tf_pre)
+ self.assertNotIn("HistogramBenchmark.prometheusNative", tf_pre)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/.mise/tasks/update_benchmarks.py b/.mise/tasks/update_benchmarks.py
new file mode 100755
index 000000000..6f7f788dd
--- /dev/null
+++ b/.mise/tasks/update_benchmarks.py
@@ -0,0 +1,251 @@
+#!/usr/bin/env python3
+
+# [MISE] description="Run and update JMH benchmark outputs in the benchmarks module"
+# [MISE] alias="update-benchmarks"
+
+"""
+Run benchmarks for the `benchmarks` module, capture JMH text output, and update
+any
...
blocks containing "thrpt" under the `benchmarks/` module
+(files such as Java sources with embedded example output in javadocs).
+
+Usage: ./.mise/tasks/update_benchmarks.py [--mvnw ./mvnw] [--module benchmarks] [--java java]
+ [--jmh-args "-f 1 -wi 0 -i 1"]
+
+By default this will:
+ - run the maven wrapper to package the benchmarks: `./mvnw -pl benchmarks -am -DskipTests package`
+ - locate the shaded jar under `benchmarks/target/` (named containing "benchmarks")
+ - run `java -jar -rf text` (add extra JMH args with --jmh-args)
+ - parse the first JMH table (the block starting with the "Benchmark Mode" header)
+ - update all files under the `benchmarks/` directory which contain a `
` block with the substring "thrpt"
+
+This script is careful to preserve Javadoc comment prefixes like " * " when replacing the
+contents of the
block.
+"""
+
+import argparse
+import glob
+import os
+import re
+import shlex
+import subprocess
+import sys
+
+
+def run_cmd(cmd: list[str], cwd: str | None = None) -> str:
+ """Run a command, stream stdout/stderr to the console for progress, and return the full output.
+
+ This replaces the previous blocking subprocess.run approach so users can see build / JMH
+ progress in real time while the command runs.
+ """
+ try:
+ proc = subprocess.Popen(
+ cmd, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True
+ )
+ except FileNotFoundError:
+ # Helpful message if the executable is not found
+ print(f"Command not found: {cmd[0]}")
+ raise
+
+ output_lines: list[str] = []
+ try:
+ assert proc.stdout is not None
+ # Stream lines as they appear and capture them for returning
+ for line in proc.stdout:
+ # Print immediately so callers (and CI) can observe progress
+ print(line, end="", flush=True)
+ output_lines.append(line)
+ proc.wait()
+ except KeyboardInterrupt:
+ # If the user interrupts, ensure the child process is terminated
+ proc.kill()
+ proc.wait()
+ print("\nCommand interrupted by user.")
+ raise
+
+ output = "".join(output_lines)
+ if proc.returncode != 0:
+ print(
+ f"Command failed: {' '.join(cmd)}\nExit: {proc.returncode}\nOutput:\n{output}"
+ )
+ raise SystemExit(proc.returncode)
+ return output
+
+
+def build_benchmarks(mvnw: str, module: str) -> None:
+ print(f"Building Maven module '{module}' using {mvnw} (this may take a while)...")
+ cmd = [mvnw, "-pl", module, "-am", "-DskipTests", "clean", "package"]
+ run_cmd(cmd)
+ print("Build completed.")
+
+
+def find_benchmarks_jar(module: str) -> str:
+ pattern = os.path.join(module, "target", "*.jar")
+ jars = [p for p in glob.glob(pattern) if "original" not in p and p.endswith(".jar")]
+ # prefer jar whose basename contains module name
+ jars_pref = [j for j in jars if module in os.path.basename(j)]
+ chosen = (jars_pref or jars)[:1]
+ if not chosen:
+ raise FileNotFoundError(
+ f"No jar found in {os.path.join(module, 'target')} (tried: {pattern})"
+ )
+ jar = chosen[0]
+ print(f"Using jar: {jar}")
+ return jar
+
+
+def run_jmh(jar: str, java_cmd: str, extra_args: str | None) -> str:
+ args = [java_cmd, "-jar", jar, "-rf", "text"]
+ if extra_args:
+ args += shlex.split(extra_args)
+ print(f"Running JMH: {' '.join(args)}")
+ output = run_cmd(args)
+ print("JMH run completed.")
+ return output
+
+
+def extract_first_table(jmh_output: str) -> str:
+ # Try to extract the first table that starts with "Benchmark" header and continues until a blank line
+ m = re.search(r"(\nBenchmark\s+Mode[\s\S]*?)(?:\n\s*\n|\Z)", jmh_output)
+ if not m:
+ # fallback: collect all lines that contain 'thrpt' plus a header if present
+ lines = [line for line in jmh_output.splitlines() if "thrpt" in line]
+ if not lines:
+ raise ValueError('Could not find any "thrpt" lines in JMH output')
+ # try to find header
+ header = next(
+ (
+ line
+ for line in jmh_output.splitlines()
+ if line.startswith("Benchmark") and "Mode" in line
+ ),
+ "Benchmark Mode Cnt Score Error Units",
+ )
+ return header + "\n" + "\n".join(lines)
+ table = m.group(1).strip("\n")
+ # Ensure we return only the table lines (remove any leading iteration info lines that JMH sometimes prints)
+ # Normalize spaces: keep as-is
+ return table
+
+
+def filter_table_for_class(table: str, class_name: str) -> str | None:
+ """
+ Return a table string that contains only the header and the lines belonging to `class_name`.
+ If no matching lines are found, return None.
+ """
+ lines = table.splitlines()
+ # find header line index (starts with 'Benchmark' and contains 'Mode')
+ header_idx = None
+ for i, ln in enumerate(lines):
+ if ln.strip().startswith("Benchmark") and "Mode" in ln:
+ header_idx = i
+ break
+ header = (
+ lines[header_idx]
+ if header_idx is not None
+ else "Benchmark Mode Cnt Score Error Units"
+ )
+
+ matched = []
+ pattern = re.compile(r"^\s*" + re.escape(class_name) + r"\.")
+ for ln in lines[header_idx + 1 if header_idx is not None else 0 :]:
+ if "thrpt" in ln and pattern.search(ln):
+ matched.append(ln)
+
+ if not matched:
+ return None
+ return header + "\n" + "\n".join(matched)
+
+
+def update_pre_blocks_under_module(module: str, table: str) -> list[str]:
+ # Find files under module and update any
...
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 (OSError, UnicodeError):
+ pass
+ if content is None:
+ continue
+ # quick filter
+ if "
" not in content or "thrpt" not in content:
+ continue
+
+ original = content
+
+ # Determine the class name from the filename (e.g. TextFormatUtilBenchmark.java -> TextFormatUtilBenchmark)
+ base = os.path.basename(path)
+ class_name = os.path.splitext(base)[0]
+
+ # Build a filtered table for this class; if no matching lines, skip updating this file
+ filtered_table = filter_table_for_class(table, class_name)
+ if filtered_table is None:
+ # nothing to update for this class
+ continue
+
+ # Regex to find any line-starting Javadoc prefix like " * " before
+ # 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, replacement_table: str = filtered_table) -> str:
+ prefix = m.group("prefix")
+ # Build the new block with the same prefix on each line
+ lines = replacement_table.splitlines()
+ replaced = prefix + "
\n"
+ for ln in lines:
+ replaced += prefix + ln.rstrip() + "\n"
+ replaced += prefix + "
"
+ return replaced
+
+ new_content, nsubs = pattern.subn(repl, content)
+ if nsubs > 0 and new_content != original:
+ with open(path, "w", encoding="utf-8") as f:
+ f.write(new_content)
+ updated_files.append(path)
+ print(f"Updated {path}: replaced {nsubs}
block(s)")
+ return updated_files
+
+
+def main(argv: list[str]):
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--mvnw", default="./mvnw", help="Path to maven wrapper")
+ parser.add_argument(
+ "--module", default="benchmarks", help="Module directory to build/run"
+ )
+ parser.add_argument("--java", default="java", help="Java command")
+ parser.add_argument(
+ "--jmh-args",
+ default="",
+ help='Extra arguments to pass to the JMH main (e.g. "-f 1 -wi 0 -i 1")',
+ )
+ args = parser.parse_args(argv)
+
+ build_benchmarks(args.mvnw, args.module)
+ jar = find_benchmarks_jar(args.module)
+ output = run_jmh(jar, args.java, args.jmh_args)
+
+ # Print a short preview of the JMH output
+ preview = "\n".join(output.splitlines()[:120])
+ print("\n--- JMH output preview ---")
+ print(preview)
+ print("--- end preview ---\n")
+
+ table = extract_first_table(output)
+
+ updated = update_pre_blocks_under_module(args.module, table)
+
+ if not updated:
+ print(
+ 'No files were updated (no
blocks with "thrpt" found under the module).'
+ )
+ else:
+ print("\nUpdated files:")
+ for p in updated:
+ print(" -", p)
+
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
diff --git a/.mvn/jvm.config b/.mvn/jvm.config
new file mode 100644
index 000000000..32599cefe
--- /dev/null
+++ b/.mvn/jvm.config
@@ -0,0 +1,10 @@
+--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
+--add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
+--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..e788e5e69
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionType=only-script
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.16/apache-maven-3.9.16-bin.zip
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 294da3583..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: java
-
-script:
-- mvn test
-- mvn javadoc:aggregate
diff --git a/.yaml-lint.yml b/.yaml-lint.yml
new file mode 100644
index 000000000..a06ffeed5
--- /dev/null
+++ b/.yaml-lint.yml
@@ -0,0 +1,5 @@
+extends: relaxed
+
+rules:
+ line-length:
+ max: 120
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 000000000..2949d8089
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,163 @@
+# AGENTS.md
+
+This file provides guidance to AI coding agents when working
+with code in this repository.
+
+## Build Commands
+
+This project uses Maven with mise for task automation.
+The Maven wrapper (`./mvnw`) is used for all builds.
+
+```bash
+# Full CI build (clean + install + all checks)
+mise run ci
+
+# Quick compile without tests or checks (fastest)
+mise run compile
+
+# Run unit tests only (skips formatting and coverage)
+mise run test
+
+# Run all tests including integration tests
+mise run test-all
+
+# Run a single test class
+./mvnw test -Dtest=CounterTest \
+ -Dcoverage.skip=true
+
+# Run a single test method
+./mvnw test -Dtest=CounterTest#testIncrement \
+ -Dcoverage.skip=true
+
+# Run tests in a specific module
+./mvnw test -pl prometheus-metrics-core \
+ -Dcoverage.skip=true
+
+# Regenerate protobuf classes (after protobuf dep update)
+mise run generate
+```
+
+## Architecture
+
+The library follows a layered architecture where metrics
+flow from core types through a registry to exporters:
+
+```text
+prometheus-metrics-core (user-facing API)
+ │
+ ▼ collect()
+prometheus-metrics-model (immutable snapshots)
+ │
+ ▼
+prometheus-metrics-exposition-formats
+ │
+ ▼
+Exporters (httpserver, servlet, pushgateway, otel)
+```
+
+### Key Modules
+
+- **prometheus-metrics-core**: User-facing metric types
+ (Counter, Gauge, Histogram, Summary, Info, StateSet).
+ All metrics implement `Collector` with `collect()`.
+- **prometheus-metrics-model**: Internal read-only immutable
+ snapshot types returned by `collect()`.
+ Contains `PrometheusRegistry` for metric registration.
+- **prometheus-metrics-config**: Runtime configuration via
+ properties files or system properties.
+- **prometheus-metrics-exposition-formats**: Converts
+ snapshots to Prometheus exposition formats.
+- **prometheus-metrics-tracer**: Exemplar support with
+ OpenTelemetry tracing integration.
+- **prometheus-metrics-simpleclient-bridge**: Allows legacy
+ simpleclient 0.16.0 metrics to work with the new registry.
+
+### Instrumentation Modules
+
+Pre-built instrumentations:
+`prometheus-metrics-instrumentation-jvm`, `-caffeine`,
+`-guava`, `-dropwizard`, `-dropwizard5`.
+
+## Code Style
+
+- **Formatter**: Google Java Format (enforced via flint)
+- **Line length**: 100 characters
+ (enforced for ALL files including Markdown, Java, YAML)
+- **Indentation**: 2 spaces
+- **Static analysis**: `Error Prone` with NullAway
+ (`io.prometheus.metrics` package)
+- **Logger naming**: Logger fields must be named `logger`
+ (not `log`, `LOG`, or `LOGGER`)
+- **Assertions in tests**: Use static imports from AssertJ
+ (`import static ...Assertions.assertThat`)
+- **Empty catch blocks**: Use `ignored` as the variable name
+- **Markdown code blocks**: Always specify language
+ (e.g., ` ```java`, ` ```bash`, ` ```text`)
+
+## Pull Requests
+
+- PR titles must use semantic/conventional prefixes, for example
+ `feat: ...`, `fix: ...`, `docs: ...`, `chore: ...`, or
+ `test: ...`.
+- Do not prefix PR titles with `[codex]`.
+- Match the PR title type to the primary user-facing change.
+
+## Linting
+
+Run `mise run lint:fix` before committing changes.
+If output includes `fixed`, keep those changes.
+If output includes `partial` or `review`, address the remaining issues and
+run `mise run lint:fix` again.
+
+Example output:
+flint: fixed: gofmt — commit before pushing | partial: cargo-clippy
+
+**CRITICAL**: These checks MUST be run before creating any
+commits. CI will fail if these checks fail.
+
+### Java Files
+
+- **ALWAYS** run `mise run build` after modifying Java files
+ to ensure:
+ - Code formatting via flint
+ - Static analysis (`Error Prone` with NullAway)
+ - Checkstyle validation
+ - 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
+- AssertJ for fluent assertions
+- Mockito for mocking
+- **Test visibility**: Test classes and test methods must be
+ package-protected (no `public` modifier)
+- Integration tests are in `integration-tests/` and run
+ during `verify` phase
+- Acceptance tests use OATs framework:
+ `mise run acceptance-test`
+
+## Documentation
+
+- Docs live under `docs/content/` and use `$version` as a
+ placeholder for the library version
+- When publishing GitHub Pages,
+ `mise run set-release-version-github-pages` replaces
+ `$version` with the latest Git tag across all
+ `docs/content/**/*.md` files
+ (the published site is not versioned)
+- Use `$version` for the Prometheus client version and
+ `$otelVersion-alpha` for the OTel instrumentation
+ version — never hardcode them
+
+## Java Version
+
+Source compatibility: Java 8. Tests run on Java 25
+(configured in `mise.toml`).
diff --git a/AUTHORS.md b/AUTHORS.md
deleted file mode 100644
index 4b5814ef4..000000000
--- a/AUTHORS.md
+++ /dev/null
@@ -1,18 +0,0 @@
-The Prometheus project was started by Matt T. Proud (emeritus) and
-Julius Volz in 2012.
-
-Maintainers of this repository:
-
-* Björn Rabenstein
-* Brian Brazil
-
-The following individuals have contributed code to this repository
-(listed in alphabetical order):
-
-* Björn Rabenstein
-* Brian Brazil
-* Flavio W. Brasil
-* Julius Volz
-* Matt T. Proud
-* Michal Witkowski
-* Ursula Kallio
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 000000000..81ba1f52a
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,144 @@
+# Changelog
+
+## [1.8.0](https://github.com/prometheus/client_java/compare/v1.7.0...v1.8.0) (2026-06-11)
+
+
+### Features
+
+* Add custom labels to exemplars ([#2191](https://github.com/prometheus/client_java/issues/2191)) ([fd1f3e8](https://github.com/prometheus/client_java/commit/fd1f3e85177ec4d4e4922f22f3aa79dc2dd7e17e))
+* add MetricMetadata.Builder, deprecate wide constructors ([#2202](https://github.com/prometheus/client_java/issues/2202)) ([adeef32](https://github.com/prometheus/client_java/commit/adeef32f303a9dfadee9b7702b255db193c9c533))
+
+
+### Bug Fixes
+
+* Avoid unnuecessary exemplar allocations ([#2209](https://github.com/prometheus/client_java/issues/2209)) ([0b6a91f](https://github.com/prometheus/client_java/commit/0b6a91f2bafe0fa15f6fe828f315103d8c20f9f9))
+* **deps:** update spring boot to v4.1.0 ([#2213](https://github.com/prometheus/client_java/issues/2213)) ([df25c08](https://github.com/prometheus/client_java/commit/df25c0821605b7edf7b87b9874a65d3d529592a5))
+
+
+### Documentation
+
+* cover typed family descriptors and @StableApi since v1.6.1 ([#2181](https://github.com/prometheus/client_java/issues/2181)) ([7ca9f99](https://github.com/prometheus/client_java/commit/7ca9f99b8f1731315d2cf8f68247fc94174a8b3b))
+
+## [1.7.0](https://github.com/prometheus/client_java/compare/v1.6.1...v1.7.0) (2026-06-03)
+
+
+### Features
+
+* Add StableApi marker and API diff check ([#2168](https://github.com/prometheus/client_java/issues/2168)) ([768fd3a](https://github.com/prometheus/client_java/commit/768fd3a7aab5f11f3558a35c0d6257b5a217a078))
+* add typed metric family descriptors ([#2114](https://github.com/prometheus/client_java/issues/2114)) ([9c3b097](https://github.com/prometheus/client_java/commit/9c3b097f6842ffc08fb3a2ed00217c73a6c2b191))
+* track api-diff baseline via Renovate and store diffs in docs/apidiffs ([#2174](https://github.com/prometheus/client_java/issues/2174)) ([3adb890](https://github.com/prometheus/client_java/commit/3adb89078df4bf3d7739886612d4cf051176a6f3))
+
+
+### Bug Fixes
+
+* **deps:** update dependency com.github.ben-manes.caffeine:caffeine to v3.2.4 ([#2088](https://github.com/prometheus/client_java/issues/2088)) ([144eb61](https://github.com/prometheus/client_java/commit/144eb61030d412afe83631b8f341d2cb1595ab1c))
+* **deps:** update dependency io.dropwizard.metrics:metrics-core to v4.2.39 ([#2139](https://github.com/prometheus/client_java/issues/2139)) ([5817d13](https://github.com/prometheus/client_java/commit/5817d1395dc348b6634ea169264fd13f4ad56e82))
+* **deps:** update dependency io.dropwizard.metrics5:metrics-core to v5.0.7 ([#2140](https://github.com/prometheus/client_java/issues/2140)) ([261c451](https://github.com/prometheus/client_java/commit/261c4510eefe156ad688e019b9239cfcfd39bd2b))
+* **deps:** update dependency io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha to v2.28.0-alpha ([#2126](https://github.com/prometheus/client_java/issues/2126)) ([b62b5d0](https://github.com/prometheus/client_java/commit/b62b5d0ab4b8d3a1335286bd3d36e8c9ac5aa269))
+* **deps:** update dependency io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha to v2.28.0-alpha ([#2127](https://github.com/prometheus/client_java/issues/2127)) ([e11ce3d](https://github.com/prometheus/client_java/commit/e11ce3de19daf5acd2f73ffb90c96689c172f3c3))
+* **deps:** update dependency io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha to v2.28.1-alpha ([#2132](https://github.com/prometheus/client_java/issues/2132)) ([b09be38](https://github.com/prometheus/client_java/commit/b09be3882f0ad95ff299db41d706a2e52faa7525))
+* **deps:** update dependency io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha to v2.28.1-alpha ([#2133](https://github.com/prometheus/client_java/issues/2133)) ([a241c16](https://github.com/prometheus/client_java/commit/a241c165927d3cbb91b97eedd52de9c9eff595d0))
+* **deps:** update dependency org.apache.tomcat.embed:tomcat-embed-core to v11.0.22 ([#2099](https://github.com/prometheus/client_java/issues/2099)) ([22125c5](https://github.com/prometheus/client_java/commit/22125c5f531467030793fc48cb2308ff14bbcaa7))
+* **deps:** update jetty monorepo to v12.1.10 ([#2169](https://github.com/prometheus/client_java/issues/2169)) ([ddd3991](https://github.com/prometheus/client_java/commit/ddd3991096d409a3e58ae2003ce13457a51b8876))
+* **deps:** update jetty monorepo to v12.1.9 ([#2102](https://github.com/prometheus/client_java/issues/2102)) ([04bee70](https://github.com/prometheus/client_java/commit/04bee70efff866f8c4966643926905c28a4eae3a))
+* **deps:** update protobuf ([#2129](https://github.com/prometheus/client_java/issues/2129)) ([320538a](https://github.com/prometheus/client_java/commit/320538a09efad128c6d80bcc3d6eecca394603db))
+* Reduce allocations for classic histogram buckets ([#2081](https://github.com/prometheus/client_java/issues/2081)) ([edd160a](https://github.com/prometheus/client_java/commit/edd160ab93254c80250d7cf58a1dcb399fef67a1))
+* restore legacy suffix compatibility ([#2100](https://github.com/prometheus/client_java/issues/2100)) ([b2ae70f](https://github.com/prometheus/client_java/commit/b2ae70ffd4ac0830fb567319beae9d1c3ad8bc2f))
+* restore reserved suffix stripping in `PrometheusNaming.sanitizeMetricName()` ([#2124](https://github.com/prometheus/client_java/issues/2124)) ([2d0f508](https://github.com/prometheus/client_java/commit/2d0f508efd2f5e009b6f09f6a9ccb451cf9f3b6f))
+
+
+### Performance Improvements
+
+* Refactored sorting to use optimized sort algorithms ([#2161](https://github.com/prometheus/client_java/issues/2161)) ([25b94fc](https://github.com/prometheus/client_java/commit/25b94fc16273659892af0132cedb71f57597adf7))
+
+
+### Documentation
+
+* clarify downstream adapter validation requirements ([#2101](https://github.com/prometheus/client_java/issues/2101)) ([ef8c75c](https://github.com/prometheus/client_java/commit/ef8c75cf352bddd0d3a2052c3f1b0c8b6103a6f4))
+* Document OM2 ([#2059](https://github.com/prometheus/client_java/issues/2059)) ([45d753c](https://github.com/prometheus/client_java/commit/45d753c418f005fbb17bf7caca3dc94655717687))
+* document PushGateway shading workaround ([#2106](https://github.com/prometheus/client_java/issues/2106)) ([8ca0eb8](https://github.com/prometheus/client_java/commit/8ca0eb8d79b800ad8d7a08f10762ed631f4f2a70))
+
+## [1.6.1](https://github.com/prometheus/client_java/compare/v1.6.0...v1.6.1) (2026-04-27)
+
+> Note: With the OM2 metric-name preservation fix in this release, OpenMetrics 2.0 can now be
+> tested. It is still in progress and not ready for general use yet.
+
+### Bug Fixes
+
+* Preserve original metric names in OM2 output ([#2058](https://github.com/prometheus/client_java/issues/2058)) ([59a7a6d](https://github.com/prometheus/client_java/commit/59a7a6d4d5a9eb31c33167764b11ba96d6625b74))
+
+
+### Documentation
+
+* clarify 1.6.0 release notes ([#2062](https://github.com/prometheus/client_java/issues/2062)) ([9e5d591](https://github.com/prometheus/client_java/commit/9e5d591f4c2e8e0d39ce5141ac14fff057b09c67))
+* Document semantic PR title guidance ([#2060](https://github.com/prometheus/client_java/issues/2060)) ([7277889](https://github.com/prometheus/client_java/commit/727788942cccbecfa57d75eee9fb3e942083a95e))
+
+## [1.6.0](https://github.com/prometheus/client_java/compare/v1.5.1...v1.6.0) (2026-04-25)
+
+> Note: OpenMetrics 2.0 support is still in progress and not ready for general use yet.
+>
+> As part of the OM2 work, metric-name suffix handling moved from metric creation time to scrape
+> time. A positive side effect is that metric names are now more flexible across the board, for
+> example names ending in suffixes like `_total` are accepted where they were previously rejected.
+> To keep the Prometheus and OM1 output unambiguous, the registry tracks claimed exposition names
+> and still rejects registrations that would collide at scrape time.
+>
+> Downstream adapter libraries that implement `MultiCollector` need their registration-time
+> metadata to match the metric families they emit at scrape time. When upgrading to 1.6.0+, adapter
+> registration metadata needs to stay aligned with emitted names, types, label names, and suffix
+> behavior under the new collision model.
+> See also: [Validation at registration only](docs/content/getting-started/registry.md#validation-at-registration-only)
+>
+> | Example | Before 1.6.0 | Since 1.6.0 | Reason |
+> | --- | --- | --- | --- |
+> | `Gauge("foo_total")` | Rejected | Allowed | Not breaking because this previously failed at registration, so no working setup changes behavior, and safe because `_total` suffix expansion applies to counters, not gauges. |
+> | `Counter("events_total")` | Rejected | Allowed | Not breaking because the OM1 output is still `events_total`; only the builder now accepts the name. |
+> | `Gauge("foo_total")` + `Histogram("foo")` | Rejected | Allowed | Not breaking because this combination used to be blocked even though the exposed names do not overlap. |
+> | `Gauge("events_total")` + `Counter("events")` | Rejected | Rejected | Not breaking because the ambiguous OM1 output would still expose two `events_total` series. |
+> | `Gauge("foo_count")` + `Histogram("foo")` | Allowed | Rejected | Intentionally breaking because the old behavior could expose a conflicting `foo_count` name at scrape time. |
+
+### Features
+
+* Relax metric name validation in Dropwizard5 ([#1985](https://github.com/prometheus/client_java/issues/1985)) ([deb782f](https://github.com/prometheus/client_java/commit/deb782f9fce60ffb1308a98b661c0a1ccb79a82b))
+
+
+### Bug Fixes
+
+* **deps:** update dependency com.google.guava:guava to v33.6.0-jre ([#2021](https://github.com/prometheus/client_java/issues/2021)) ([1382693](https://github.com/prometheus/client_java/commit/13826930b9c2f566040a6929090ef23c94e81796))
+* **deps:** update dependency commons-io:commons-io to v2.22.0 ([#2044](https://github.com/prometheus/client_java/issues/2044)) ([9e05c1d](https://github.com/prometheus/client_java/commit/9e05c1d56b7b0de17ba5aaaa300eb6433cc70824))
+* **deps:** update dependency io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha to v2.27.0-alpha ([#2022](https://github.com/prometheus/client_java/issues/2022)) ([30ac534](https://github.com/prometheus/client_java/commit/30ac534d860fb7c60a1e7835723a6cf0035ea7f7))
+* **deps:** update dependency io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha to v2.27.0-alpha ([#2023](https://github.com/prometheus/client_java/issues/2023)) ([2d51a32](https://github.com/prometheus/client_java/commit/2d51a3251f6943cf1b03ba9ea8778ff052f83ef9))
+* **deps:** update dependency io.prometheus:prometheus-metrics-bom to v1.5.1 ([#2004](https://github.com/prometheus/client_java/issues/2004)) ([650ce4b](https://github.com/prometheus/client_java/commit/650ce4b677f2ca65f5877e77260e403fa85533db))
+* **deps:** update dependency org.apache.tomcat.embed:tomcat-embed-core to v11.0.21 ([#2005](https://github.com/prometheus/client_java/issues/2005)) ([7a36df7](https://github.com/prometheus/client_java/commit/7a36df7151e55adafd5bb5a72af81fd7bf8f1133))
+* **deps:** update dependency org.springframework.boot:spring-boot-starter-parent to v4.0.5 ([#2006](https://github.com/prometheus/client_java/issues/2006)) ([0106c18](https://github.com/prometheus/client_java/commit/0106c18adffd6d3e829f73979917bdf7cc5f53dd))
+* **deps:** update dependency org.springframework.boot:spring-boot-starter-parent to v4.0.6 ([#2046](https://github.com/prometheus/client_java/issues/2046)) ([40a9db8](https://github.com/prometheus/client_java/commit/40a9db868805e36fbaa0f9ac3d02becb17104cd0))
+* **deps:** update jetty monorepo to v12.1.8 ([#2007](https://github.com/prometheus/client_java/issues/2007)) ([acab5b2](https://github.com/prometheus/client_java/commit/acab5b213e7661818470716158b3cfe67caae9da))
+* **deps:** update protobuf ([#2024](https://github.com/prometheus/client_java/issues/2024)) ([8e2214e](https://github.com/prometheus/client_java/commit/8e2214e0a3ac2fe8a9194d9519dcee10f6c9a694))
+* pass release tag as input to deploy workflow ([#1982](https://github.com/prometheus/client_java/issues/1982)) ([165c921](https://github.com/prometheus/client_java/commit/165c921c2508e073baa8f403b30e536ba9b43df9))
+* pin grafana/otel-lgtm to 0.7.2 in OATs acceptance test ([#1992](https://github.com/prometheus/client_java/issues/1992)) ([f17ad9a](https://github.com/prometheus/client_java/commit/f17ad9ad9be2ed0a8519db094f9d8fe9a8a83c48))
+* stabilize flaky timer and thread count tests ([#1973](https://github.com/prometheus/client_java/issues/1973)) ([ce5867b](https://github.com/prometheus/client_java/commit/ce5867b3e25e10c68a6face275732b994a80ec98))
+* trigger Maven deploy from release-please via workflow_dispatch ([#1981](https://github.com/prometheus/client_java/issues/1981)) ([698f956](https://github.com/prometheus/client_java/commit/698f9565e825cdb0f58d2782131cb152cc13894a))
+
+## [1.5.1](https://github.com/prometheus/client_java/compare/v1.5.0...v1.5.1) (2026-03-20)
+
+
+### Bug Fixes
+
+* **deps:** update dependency io.prometheus:prometheus-metrics-bom to v1.5.0 ([#1877](https://github.com/prometheus/client_java/issues/1877)) ([043fc57](https://github.com/prometheus/client_java/commit/043fc5742752fdc2f67f0219418030a190c53bde))
+* **deps:** update dependency org.springframework.boot:spring-boot-starter-parent to v4.0.3 ([#1900](https://github.com/prometheus/client_java/issues/1900)) ([0d800d0](https://github.com/prometheus/client_java/commit/0d800d0a91578e48f34909472c183174fdf1d83e))
+* **deps:** update jetty monorepo to v12.1.7 ([#1932](https://github.com/prometheus/client_java/issues/1932)) ([5bd3b79](https://github.com/prometheus/client_java/commit/5bd3b7932f454f3ed2cf55f26d6e1e1908d9ad16))
+* **deps:** update junit-framework monorepo to v6.0.3 ([#1880](https://github.com/prometheus/client_java/issues/1880)) ([05ad751](https://github.com/prometheus/client_java/commit/05ad751a40053f11eae90b9e6cbd741814ca71a7))
+* exclude standalone examples from `mise run format` ([#1931](https://github.com/prometheus/client_java/issues/1931)) ([537fb88](https://github.com/prometheus/client_java/commit/537fb88aae4048ab36041268f902afbbdce54a96))
+* fix release-please PR title pattern and permissions ([#1978](https://github.com/prometheus/client_java/issues/1978)) ([d737978](https://github.com/prometheus/client_java/commit/d7379780f1351a1521c8d93d0544bffce49d02a6))
+* Handle empty datapoints in otel exporter ([#1898](https://github.com/prometheus/client_java/issues/1898)) ([59c8552](https://github.com/prometheus/client_java/commit/59c8552f3d67c06d82344383b45e07fea8ed88b9))
+* inline set-version logic in build-release.sh ([#1884](https://github.com/prometheus/client_java/issues/1884)) ([c050435](https://github.com/prometheus/client_java/commit/c050435a4153046c72d158991c4c8e064dfb24ec))
+* reduce lychee retries to avoid compounding GitHub 429s ([#1940](https://github.com/prometheus/client_java/issues/1940)) ([cc17d6e](https://github.com/prometheus/client_java/commit/cc17d6e4346c9d51e054010fddc75cf8935cbc7d))
+* remove version manipulation from build-release.sh ([#1886](https://github.com/prometheus/client_java/issues/1886)) ([93e2b6d](https://github.com/prometheus/client_java/commit/93e2b6da48abc03ba7d96ffff5020ab73c1ee8c1))
+* trigger Maven deploy on release-please published events ([#1966](https://github.com/prometheus/client_java/issues/1966)) ([643d0e7](https://github.com/prometheus/client_java/commit/643d0e70c274e2a55024611c73a53545a65e94a0))
+* use /tree/ instead of /blob/ for directory URL ([#1944](https://github.com/prometheus/client_java/issues/1944)) ([b81332e](https://github.com/prometheus/client_java/commit/b81332e3a09e465f956f118a2403e64b83771ae5))
+* use maven release type for release-please ([#1967](https://github.com/prometheus/client_java/issues/1967)) ([ff3bd2d](https://github.com/prometheus/client_java/commit/ff3bd2d329acdb6761044846559c353a526c0384))
+
+
+### Documentation
+
+* document DCO sign-off requirement for contributions ([#1937](https://github.com/prometheus/client_java/issues/1937)) ([0860e77](https://github.com/prometheus/client_java/commit/0860e7742b08ab019d129ea24c348191c3f9e0da))
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 000000000..6b5e23414
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,3 @@
+
+
+@AGENTS.md
diff --git a/CODEOWNERS b/CODEOWNERS
new file mode 100644
index 000000000..1f70593ce
--- /dev/null
+++ b/CODEOWNERS
@@ -0,0 +1,4 @@
+# https://help.github.com/articles/about-codeowners/
+# https://git-scm.com/docs/gitignore#_pattern_format
+
+* @fstab @dhoard @zeitlinger @jaydeluca
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000..d325872bd
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,3 @@
+# Prometheus Community Code of Conduct
+
+Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md).
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5c8ea596a..1b42bfaf4 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -2,11 +2,142 @@
Prometheus uses GitHub to manage reviews of pull requests.
-* If you have a trivial fix or improvement, go ahead and create a pull
- request, addressing (with `@...`) one or more of the maintainers
- (see [AUTHORS.md](AUTHORS.md)) in the description of the pull request.
+- If you have a trivial fix or improvement, go ahead and create a pull request,
+ addressing (with `@...`) the maintainer of this repository (see
+ [MAINTAINERS.md](MAINTAINERS.md)) in the
+ description of the pull request.
-* If you plan to do something more involved, first discuss your ideas
+- If you plan to do something more involved, first discuss your ideas
on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/prometheus-developers).
This will avoid unnecessary work and surely give you and us a good deal
of inspiration.
+
+## Pull Request Titles
+
+Use a [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary)-style
+title for pull requests:
+
+```text
+[optional scope]:
+```
+
+For example: `fix(metrics): handle empty scrapes`. Common types include `feat`, `fix`,
+`docs`, `test`, `refactor`, `perf`, `build`, `ci`, `chore`, and `revert`.
+
+## Signing Off Commits
+
+Every commit must include a `Signed-off-by` line, as required by the
+[Developer Certificate of Origin (DCO)](https://developercertificate.org/).
+
+Sign off each commit by passing `--signoff` (or `-s`) to `git commit`:
+
+```bash
+git commit --signoff -m "Your commit message"
+```
+
+To sign off only the most recent commit, use `--amend`:
+
+```bash
+git commit --amend --signoff --no-edit
+```
+
+To sign off multiple commits, rebase (replace `N` with the number of commits):
+
+```bash
+git rebase --signoff HEAD~N
+```
+
+Then force-push the branch:
+
+```bash
+git push --force-with-lease
+```
+
+## Formatting
+
+This repository uses flint to run formatting and lint checks.
+
+Run all the linters:
+
+`mise run lint`
+
+To autofix linting issues:
+
+`mise run lint:fix`
+
+### Pre-commit Hook (Optional)
+
+Run `mise run setup:pre-commit-hook` to install a git pre-commit hook
+that auto-lints changed files before each commit.
+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:
+
+- Make sure that the IDE uses only the "Maven Shade" dependency of "
+ prometheus-metrics-exposition-formats" and the "prometheus-metrics-tracer\*" dependencies.
+
+### Running native tests
+
+```shell
+mise --cd .mise/envs/native run native-test
+```
+
+### Avoid failures while running tests
+
+- Use `-Dcoverage.skip=true` to skip the coverage check during development.
+- Use `-Dwarnings=-nowarn` to skip the warnings during development.
+
+Combine all with
+
+```shell
+./mvnw install -DskipTests -Dcoverage.skip=true -Dwarnings=-nowarn
+```
+
+or simply
+
+```shell
+mise run compile
+```
+
+## Version Numbers in Examples
+
+Example `pom.xml` files (under `examples/`) should reference the latest
+**released** version, not a SNAPSHOT. After each release, Renovate
+updates these versions automatically.
+
+Only use a SNAPSHOT version in an example when it demonstrates a new
+feature that has not been released yet.
+
+## Updating the Protobuf Java Classes
+
+The generated protobuf `Metrics.java` lives in a versioned package
+(e.g., `...generated.com_google_protobuf_4_33_5`) that changes with each
+protobuf release. A stable extending class at
+`...generated/Metrics.java` reexports all types so that consumer code
+only imports from the version-free package. On protobuf upgrades only
+the `extends` clause in the stable class changes.
+
+In the failing PR from renovate, run:
+
+```shell
+mise run generate
+```
+
+The script will:
+
+1. Re-generate the protobuf sources with the new version.
+2. Update the versioned package name in all Java files
+ (including the stable `Metrics.java` extends clause).
+
+Add the updated files to Git and commit them.
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
new file mode 100644
index 000000000..a247eb14a
--- /dev/null
+++ b/MAINTAINERS.md
@@ -0,0 +1,10 @@
+# Maintainers
+
+- Fabian Stäber @fstab
+- Doug Hoard @dhoard
+- Gregor Zeitlinger @zeitlinger
+- Jay DeLuca @jaydeluca
+
+## Emeritus
+
+- Tom Wilkie @tomwilkie
diff --git a/NOTICE b/NOTICE
index b5846b48e..c920ec3fe 100644
--- a/NOTICE
+++ b/NOTICE
@@ -6,3 +6,6 @@ Boxever Ltd. (http://www.boxever.com/).
This product includes software developed at
SoundCloud Ltd. (http://soundcloud.com/).
+
+This product includes software developed as part of the
+Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/).
diff --git a/README.md b/README.md
index 653fee336..daef2ac3d 100644
--- a/README.md
+++ b/README.md
@@ -1,172 +1,35 @@
-# Prometheus JVM Client
-It supports Java, Clojure, Scala, JRuby, and anything else that runs on the JVM.
+# Prometheus Java Metrics Library
-## Using
-### Assets
-If you use Maven, you can simply reference the assets below. The latest
-version can be found on in the maven repository for
-[io.prometheus](http://mvnrepository.com/artifact/io.prometheus) and
-[io.prometheus.client.utility](http://mvnrepository.com/artifact/io.prometheus.client.utility).
+
-#### Simpleclient
+[![Build][build-badge]][build-workflow]
+
+
-```
-
-
- io.prometheus
- simpleclient
- 0.0.6
-
-
-
- io.prometheus
- simpleclient_hotspot
- 0.0.6
-
-
-
- io.prometheus
- simpleclient_servlet
- 0.0.6
-
-
-
- io.prometheus
- simpleclient_pushgateway
- 0.0.6
-
-```
+
-#### Original client
-```
-
-
- io.prometheus
- client
- 0.0.6
-
-
-
- io.prometheus.client.utility
- jvmstat
- 0.0.6
-
-
-
- io.prometheus.client.utility
- jvmstat
- 0.0.6
-
-
-
- io.prometheus.client.utility
- metrics
- 0.0.6
-
-
-
- io.prometheus.client.utility
- servlet
- 0.0.6
-
-```
-
-### Getting Started
-There are canonical examples defined in the class definition Javadoc of the client packages.
+[build-badge]: https://github.com/prometheus/client_java/actions/workflows/build.yml/badge.svg
+[build-workflow]: https://github.com/prometheus/client_java/actions/workflows/build.yml
## Documentation
-The client is canonically documented with Javadoc. Running the following will produce local documentation
-in _apidocs_ directories for you to read.
-
- $ mvn package
-
-If you use the Mavenized version of the Prometheus client, you can also instruct Maven to download the Javadoc and
-source artifacts.
-
-Alternatively, you can also look at the generated [Java Client
-Github Project Page](http://prometheus.github.io/client_java), but the raw
-Javadoc in Java source in version control should be treated as the canonical
-form of documentation.
-
-## Maintenance of this Library
-This suite is built and managed by [Maven](http://maven.apache.org), and the
-artifacts are hosted on the [Sonatype OSS Asset Repository](https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide).
-
-All contributions to this library must follow, as far as practical, the
-prevalent patterns in the library for consistency and the following style
-guide: [Google Java Style](http://goo.gl/FfwVsc). Depending upon your
-development environment, you may be able to find an automatic formatter
-and adherence checker that follows these rules.
-
-### Building
-
- $ mvn compile
-
-### Testing
-
- $ mvn test
-
-Please note that tests on Travis may be unreliable due to the absence of
-installed Maven artifacts. Ensure that the current snapshot version is
-deployed to Sonatype OSS Repository.
-
-### Deployment
-These steps below are only useful if you are in a release engineering capacity
-and want to publicize these changes for external users. You will also need to
-have your local Maven setup correctly along with valid and public GPG key and
-adequate authorization on the Sonatype OSS Repository to submit new artifacts,
-be they _staging_ or _release_ ones.
-
-You should read the [Sonatype OSS Apache Maven
-Guide](http://central.sonatype.org/pages/apache-maven.html) before performing any of the following:
-
-### Snapshot Deployment
- $ mvn clean deploy
-
-#### Staging
- $ mvn release:clean release:prepare -Prelease
- $ mvn release:perform -Prelease
-
-#### Release
-
-Go to https://oss.sonatype.org/#stagingRepositories and Close the `ioprometheus-XXX` release.
-Once it's closed, Release it. Wait for the new version to appear in
-[The Central Repository](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22io.prometheus%22).
-
-Send an email to the developer's mailing list announcing the release.
-
-
-#### Documentation
-Documentation can also be released to the public via the Github Pages subproduct
-through the magic _gh-pages_ branch for a Github project. Documentation is
-generated via the following command:
-
- $ mvn javadoc:aggregate
-It will need to be automatically merged into the _gh-pages_ branch, but that is
-as simple as this:
+[https://prometheus.github.io/client_java](https://prometheus.github.io/client_java)
- $ git checkout master
- $ mvn javadoc:aggregate
- $ git checkout gh-pages
- $ mv target/site/apidocs/ ./
- $ git status
- $ # Amend the branch as necessary.
- $ git commit
- $ git push
+## Contributing and community
-There is a Maven plugin to perform this work, but it is broken. The
-javadoc:aggregate step will emit documentation into
-_target/site/apidocs_. The reason that we use this aggregate step instead
-of bare javadoc is that we want one comprehensive Javadoc emission that includes
-all Maven submodules versus trying to manually concatenate this together.
+See [CONTRIBUTING.md](CONTRIBUTING.md) and
+the [community section](http://prometheus.io/community/)
+of the Prometheus homepage.
-Output documentation lives in the [Java Client Github Project
-Page](http://prometheus.github.io/client_java).
+The Prometheus Java community is present on the [CNCF Slack](https://cloud-native.slack.com) on
+`#prometheus-java`, and we have a fortnightly community call in
+the [Prometheus public calendar](https://prometheus.io/community/).
+## Previous Releases
-## Contact
- * All of the core developers are accessible via the [Prometheus Developers Mailinglist](https://groups.google.com/forum/?fromgroups#!forum/prometheus-developers).
+The source code for 0.16.0 and older is on
+the [simpleclient](https://github.com/prometheus/client_java/tree/simpleclient) branch.
+## License
-[](https://travis-ci.org/prometheus/client_java)
+Apache License 2.0, see [LICENSE](LICENSE).
diff --git a/RELEASING.md b/RELEASING.md
new file mode 100644
index 000000000..c5ae0ed4b
--- /dev/null
+++ b/RELEASING.md
@@ -0,0 +1,79 @@
+# Releasing Instructions for Prometheus Java Client
+
+Releases are automated via
+[release-please](https://github.com/googleapis/release-please).
+
+## How It Works
+
+1. Commits to `main` using
+ [Conventional Commits](https://www.conventionalcommits.org/) are
+ tracked by release-please.
+2. Release-please maintains a release PR that accumulates changes and
+ updates the changelog.
+3. When the release PR is merged, release-please creates a GitHub
+ release and a `vX.Y.Z` tag.
+4. The tag triggers the existing `release.yml` workflow, which deploys
+ to Maven Central.
+5. After tagging, release-please opens a follow-up PR to bump the
+ SNAPSHOT version in all `pom.xml` files.
+
+## Patch Release (default)
+
+Simply merge the release PR — release-please bumps the patch version
+by default (e.g. `1.5.0` -> `1.5.1`).
+
+## Minor or Major Release
+
+Add a `release-as: X.Y.0` footer to any commit on `main`:
+
+```text
+feat: add new feature
+
+release-as: 1.6.0
+```
+
+Alternatively, edit the release PR title to
+`chore(main): release 1.6.0`.
+
+## Before the Release
+
+If there have been significant changes since the last release, update
+the benchmarks before merging the release PR:
+
+```shell
+mise run update-benchmarks
+```
+
+## If the Sonatype Central Token is Invalid
+
+The release workflow verifies the token before deploy. If it fails:
+
+1. Sign in at and open
+ View Account -> Generate User Token.
+2. Copy the `username` and `password` values from the snippet.
+3. Update the secrets:
+ -
+ -
+4. Verify locally:
+
+ ```shell
+ curl -i -u "$USER:$PASS" \
+ "https://central.sonatype.com/api/v1/publisher/status?id=test"
+ ```
+
+ `{"error":{"message":"Invalid token"}}` means the token is still
+ wrong. Any other response (including 404 for the test id) means the
+ token works.
+
+## If the GPG Key Expired
+
+1. Generate a new key:
+
+2. Distribute the key:
+
+3. Use `gpg --armor --export-secret-keys YOUR_ID` to export
+ ([docs](https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#gpg))
+4. Update the passphrase:
+
+5. Update the GPG key:
+
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 000000000..5e6f976db
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,6 @@
+# Reporting a security issue
+
+The Prometheus security policy, including how to report vulnerabilities, can be
+found here:
+
+[https://prometheus.io/docs/operating/security/](https://prometheus.io/docs/operating/security/)
diff --git a/benchmark/README.md b/benchmark/README.md
deleted file mode 100644
index 628a4d444..000000000
--- a/benchmark/README.md
+++ /dev/null
@@ -1,161 +0,0 @@
-# Client Benchmarks
-
-This module contains microbenchmarks for client instrumentation operations.
-
-## Result Overview
-
-The main outcomes of the benchmarks:
-* Simpleclient Counters/Gauges have similar performance to Codahale Counters.
-* The original client is much slower than the Simpleclient or Codahale, especially when used concurrently.
-* Codahale Meters are slower than Codahale/Simpleclient Counters
-* Codahale and original client Summaries are 10x slower than other metrics.
-* Simpleclient Histograms are 10-100X faster than Codahale and original client Summaries.
-* Simpleclient `Gauge.Child.set` is relatively slow, especially when done concurrently.
-* Label lookups in both Prometheus clients are relatively slow.
-
-Accordingly, in terms of client instrumentation performance I suggest the following:
-* It's cheap to extensively instrument your code with Simpleclient Counters/Gauges/Summaries without labels, or Codahale Counters.
-* Avoid Codahale Meters, in favour of Codahale/Simpleclient Counters and calculating the rate in your monitoring system (e.g. the `rate()` function in Prometheus).
-* Use Simpleclient Histograms rather than original client Summaries and Codahale Histograms/Timers.
-* Avoid the original client.
-* For high update rate (>1000 per second) prometheus metrics using labels, you should cache the Child. Java 8 may make this better due to an improved ConcurrentHashMap implementation.
-* If a use case appears for high update rate use of SimpleClient's `Gauge.Child.set`, we should alter `DoubleAdder` to more efficiently handle this use case.
-
-## Benchmark Results
-
-These benchmarks were run using JMH on a 2-core MacBook Pro with a 2.5GHz i5 processor,
-with Oracle Java 64 1.7.0\_51.
-
-### Counters
- java -jar target/benchmarks.jar CounterBenchmark -wi 5 -i 5 -f 1 -t 1
- i.p.b.CounterBenchmark.codahaleCounterIncBenchmark avgt 5 11.554 ± 0.251 ns/op
- i.p.b.CounterBenchmark.codahaleMeterMarkBenchmark avgt 5 75.305 ± 7.147 ns/op
- i.p.b.CounterBenchmark.prometheusCounterChildIncBenchmark avgt 5 13.249 ± 0.029 ns/op
- i.p.b.CounterBenchmark.prometheusCounterIncBenchmark avgt 5 127.397 ± 4.072 ns/op
- i.p.b.CounterBenchmark.prometheusSimpleCounterChildIncBenchmark avgt 5 12.989 ± 0.285 ns/op
- i.p.b.CounterBenchmark.prometheusSimpleCounterIncBenchmark avgt 5 54.822 ± 7.994 ns/op
- i.p.b.CounterBenchmark.prometheusSimpleCounterNoLabelsIncBenchmark avgt 5 13.131 ± 1.661 ns/op
-
- java -jar target/benchmarks.jar CounterBenchmark -wi 5 -i 5 -f 1 -t 2
- i.p.b.CounterBenchmark.codahaleCounterIncBenchmark avgt 5 16.707 ± 2.116 ns/op
- i.p.b.CounterBenchmark.codahaleMeterMarkBenchmark avgt 5 107.346 ± 23.127 ns/op
- i.p.b.CounterBenchmark.prometheusCounterChildIncBenchmark avgt 5 41.912 ± 18.167 ns/op
- i.p.b.CounterBenchmark.prometheusCounterIncBenchmark avgt 5 170.860 ± 5.110 ns/op
- i.p.b.CounterBenchmark.prometheusSimpleCounterChildIncBenchmark avgt 5 17.782 ± 2.764 ns/op
- i.p.b.CounterBenchmark.prometheusSimpleCounterIncBenchmark avgt 5 89.656 ± 4.577 ns/op
- i.p.b.CounterBenchmark.prometheusSimpleCounterNoLabelsIncBenchmark avgt 5 16.109 ± 1.723 ns/op
-
- java -jar target/benchmarks.jar CounterBenchmark -wi 5 -i 5 -f 1 -t 4
- i.p.b.CounterBenchmark.codahaleCounterIncBenchmark avgt 5 17.628 ± 0.501 ns/op
- i.p.b.CounterBenchmark.codahaleMeterMarkBenchmark avgt 5 121.836 ± 15.888 ns/op
- i.p.b.CounterBenchmark.prometheusCounterChildIncBenchmark avgt 5 377.916 ± 7.965 ns/op
- i.p.b.CounterBenchmark.prometheusCounterIncBenchmark avgt 5 250.919 ± 2.728 ns/op
- i.p.b.CounterBenchmark.prometheusSimpleCounterChildIncBenchmark avgt 5 18.055 ± 1.391 ns/op
- i.p.b.CounterBenchmark.prometheusSimpleCounterIncBenchmark avgt 5 120.543 ± 1.770 ns/op
- i.p.b.CounterBenchmark.prometheusSimpleCounterNoLabelsIncBenchmark avgt 5 19.334 ± 1.471 ns/op
-
-### Gauges
-
-Codahale lacks a metric with a `set` method, so we'll compare to `Counter` which has `inc` and `dec`.
-
- java -jar target/benchmarks.jar GaugeBenchmark -wi 5 -i 5 -f 1 -t 1
- i.p.b.GaugeBenchmark.codahaleCounterDecBenchmark avgt 5 11.620 ± 0.288 ns/op
- i.p.b.GaugeBenchmark.codahaleCounterIncBenchmark avgt 5 11.718 ± 0.333 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeChildDecBenchmark avgt 5 13.358 ± 0.554 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeChildIncBenchmark avgt 5 13.268 ± 0.276 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeChildSetBenchmark avgt 5 11.624 ± 0.210 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeDecBenchmark avgt 5 125.058 ± 2.764 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeIncBenchmark avgt 5 127.814 ± 7.741 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeSetBenchmark avgt 5 127.899 ± 6.690 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeChildDecBenchmark avgt 5 12.961 ± 0.393 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeChildIncBenchmark avgt 5 12.932 ± 0.212 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeChildSetBenchmark avgt 5 36.672 ± 1.112 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeDecBenchmark avgt 5 54.677 ± 3.704 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeIncBenchmark avgt 5 53.278 ± 1.104 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeSetBenchmark avgt 5 79.724 ± 2.723 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeNoLabelsDecBenchmark avgt 5 12.957 ± 0.437 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeNoLabelsIncBenchmark avgt 5 12.932 ± 0.284 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeNoLabelsSetBenchmark avgt 5 40.235 ± 1.735 ns/op
-
- java -jar target/benchmarks.jar GaugeBenchmark -wi 5 -i 5 -f 1 -t 2
- i.p.b.GaugeBenchmark.codahaleCounterDecBenchmark avgt 5 17.443 ± 4.819 ns/op
- i.p.b.GaugeBenchmark.codahaleCounterIncBenchmark avgt 5 14.882 ± 2.875 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeChildDecBenchmark avgt 5 45.206 ± 29.575 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeChildIncBenchmark avgt 5 46.657 ± 33.518 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeChildSetBenchmark avgt 5 21.810 ± 9.370 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeDecBenchmark avgt 5 177.370 ± 2.477 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeIncBenchmark avgt 5 172.136 ± 3.056 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeSetBenchmark avgt 5 186.791 ± 7.996 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeChildDecBenchmark avgt 5 15.978 ± 2.762 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeChildIncBenchmark avgt 5 15.457 ± 1.052 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeChildSetBenchmark avgt 5 156.604 ± 10.953 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeDecBenchmark avgt 5 107.134 ± 33.620 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeIncBenchmark avgt 5 89.362 ± 16.608 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeSetBenchmark avgt 5 163.823 ± 25.270 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeNoLabelsDecBenchmark avgt 5 16.380 ± 1.915 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeNoLabelsIncBenchmark avgt 5 17.042 ± 1.113 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeNoLabelsSetBenchmark avgt 5 164.930 ± 2.565 ns/op
-
- java -jar target/benchmarks.jar GaugeBenchmark -wi 5 -i 5 -f 1 -t 4
- i.p.b.GaugeBenchmark.codahaleCounterDecBenchmark avgt 5 17.291 ± 1.769 ns/op
- i.p.b.GaugeBenchmark.codahaleCounterIncBenchmark avgt 5 17.445 ± 0.709 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeChildDecBenchmark avgt 5 389.411 ± 13.078 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeChildIncBenchmark avgt 5 399.549 ± 29.274 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeChildSetBenchmark avgt 5 123.700 ± 3.894 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeDecBenchmark avgt 5 244.741 ± 22.477 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeIncBenchmark avgt 5 243.525 ± 6.332 ns/op
- i.p.b.GaugeBenchmark.prometheusGaugeSetBenchmark avgt 5 252.363 ± 2.664 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeChildDecBenchmark avgt 5 18.330 ± 2.673 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeChildIncBenchmark avgt 5 20.633 ± 1.219 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeChildSetBenchmark avgt 5 335.455 ± 4.562 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeDecBenchmark avgt 5 116.432 ± 4.793 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeIncBenchmark avgt 5 129.390 ± 2.360 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeSetBenchmark avgt 5 613.186 ± 20.548 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeNoLabelsDecBenchmark avgt 5 19.765 ± 3.189 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeNoLabelsIncBenchmark avgt 5 19.589 ± 1.634 ns/op
- i.p.b.GaugeBenchmark.prometheusSimpleGaugeNoLabelsSetBenchmark avgt 5 307.238 ± 1.918 ns/op
-
-### Summaries
-
-The simpleclient `Summary` doesn't have percentiles, simpleclient's `Histogram`
-offers a way to calculate percentiles on the server side that works with aggregation.
-The closest to the original client's `Summary` is Codahale's
-`Timer`, but that includes timing calls so we compare with `Histogram` instead.
-
- java -jar target/benchmarks.jar SummaryBenchmark -wi 5 -i 5 -f 1 -t 1
- i.p.b.SummaryBenchmark.codahaleHistogramBenchmark avgt 5 186.306 ± 4.958 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleHistogramBenchmark avgt 5 81.595 ± 4.491 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleHistogramChildBenchmark avgt 5 22.143 ± 1.713 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleHistogramNoLabelsBenchmark avgt 5 22.066 ± 0.812 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleSummaryBenchmark avgt 5 59.588 ± 2.087 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleSummaryChildBenchmark avgt 5 15.300 ± 0.659 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleSummaryNoLabelsBenchmark avgt 5 15.608 ± 0.271 ns/op
- i.p.b.SummaryBenchmark.prometheusSummaryBenchmark avgt 5 981.640 ± 315.146 ns/op
- i.p.b.SummaryBenchmark.prometheusSummaryChildBenchmark avgt 5 1155.179 ± 850.237 ns/op
-
- java -jar target/benchmarks.jar SummaryBenchmark -wi 5 -i 5 -f 1 -t 2
- i.p.b.SummaryBenchmark.codahaleHistogramBenchmark avgt 5 289.245 ± 39.721 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleHistogramBenchmark avgt 5 127.014 ± 19.285 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleHistogramChildBenchmark avgt 5 52.597 ± 10.781 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleHistogramNoLabelsBenchmark avgt 5 53.295 ± 9.891 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleSummaryBenchmark avgt 5 117.810 ± 11.694 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleSummaryChildBenchmark avgt 5 31.933 ± 3.439 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleSummaryNoLabelsBenchmark avgt 5 33.918 ± 5.571 ns/op
- i.p.b.SummaryBenchmark.prometheusSummaryBenchmark avgt 5 2059.498 ± 616.954 ns/op
- i.p.b.SummaryBenchmark.prometheusSummaryChildBenchmark avgt 5 2346.163 ± 1503.034 ns/op
-
- java -jar target/benchmarks.jar SummaryBenchmark -wi 5 -i 5 -f 1 -t 4
- i.p.b.SummaryBenchmark.codahaleHistogramBenchmark avgt 5 587.956 ± 2.788 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleHistogramBenchmark avgt 5 163.313 ± 5.163 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleHistogramChildBenchmark avgt 5 66.957 ± 1.746 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleHistogramNoLabelsBenchmark avgt 5 67.064 ± 1.681 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleSummaryBenchmark avgt 5 140.166 ± 4.263 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleSummaryChildBenchmark avgt 5 40.065 ± 0.138 ns/op
- i.p.b.SummaryBenchmark.prometheusSimpleSummaryNoLabelsBenchmark avgt 5 41.331 ± 1.899 ns/op
- i.p.b.SummaryBenchmark.prometheusSummaryBenchmark avgt 5 3950.152 ± 1214.866 ns/op
- i.p.b.SummaryBenchmark.prometheusSummaryChildBenchmark avgt 5 4676.946 ± 3625.977 ns/op
-
-Note the high error bars for the original client, it got slower with each iteration
-so I suspect a flaw in the test setup.
-
-
diff --git a/benchmark/pom.xml b/benchmark/pom.xml
deleted file mode 100644
index 78f2db669..000000000
--- a/benchmark/pom.xml
+++ /dev/null
@@ -1,94 +0,0 @@
-
-
- 4.0.0
-
-
- io.prometheus
- parent
- 0.0.11-SNAPSHOT
-
-
- io.prometheus
- benchmarks
-
- Prometheus Java Client Benchmarks
-
- Benchmarks of client performance, and comparison to other systems.
-
-
-
-
- The Apache Software License, Version 2.0
- http://www.apache.org/licenses/LICENSE-2.0.txt
- repo
-
-
-
-
-
- org.openjdk.jmh
- jmh-core
- 1.3.2
-
-
- org.openjdk.jmh
- jmh-generator-annprocess
- 1.3.2
-
-
-
- io.prometheus
- client
- 0.0.11-SNAPSHOT
-
-
- io.prometheus
- simpleclient
- 0.0.11-SNAPSHOT
-
-
- com.codahale.metrics
- metrics-core
- 3.0.2
-
-
-
-
-
- org.apache.maven.plugins
- maven-shade-plugin
- 2.2
-
-
- package
-
- shade
-
-
- benchmarks
-
-
- org.openjdk.jmh.Main
-
-
-
-
-
- *:*
-
- META-INF/*.SF
- META-INF/*.DSA
- META-INF/*.RSA
-
-
-
-
-
-
-
-
-
-
diff --git a/benchmarks/README.md b/benchmarks/README.md
new file mode 100644
index 000000000..3859eddea
--- /dev/null
+++ b/benchmarks/README.md
@@ -0,0 +1,87 @@
+# Benchmarks
+
+## How to Run
+
+### Running benchmarks
+
+Run benchmarks and update the results in the Javadoc of the benchmark classes:
+
+```shell
+mise run update-benchmarks
+```
+
+### Different benchmark configurations
+
+The full benchmark suite takes approximately 2 hours with JMH defaults.
+For faster iterations, use these preset configurations:
+
+| Command | Duration | Use Case |
+| ----------------------------- | -------- | ---------------------------------------- |
+| `mise run benchmark:quick` | ~10 min | Quick smoke test during development |
+| `mise run benchmark:standard` | ~60 min | CI/nightly runs with good accuracy |
+| `mise run benchmark:full` | ~2 hours | Full JMH defaults for release validation |
+
+### Running benchmarks manually
+
+```shell
+java -jar ./benchmarks/target/benchmarks.jar
+```
+
+Run only one specific benchmark:
+
+```shell
+java -jar ./benchmarks/target/benchmarks.jar CounterBenchmark
+```
+
+### Custom JMH arguments
+
+You can pass custom JMH arguments:
+
+```shell
+# Quick run: 1 fork, 1 warmup iteration, 3 measurement iterations
+mise run update-benchmarks -- --jmh-args "-f 1 -wi 1 -i 3"
+
+# Standard CI: 3 forks, 3 warmup iterations, 5 measurement iterations
+mise run update-benchmarks -- --jmh-args "-f 3 -wi 3 -i 5"
+```
+
+JMH parameter reference:
+
+- `-f N`: Number of forks (JVM restarts)
+- `-wi N`: Number of warmup iterations
+- `-i N`: Number of measurement iterations
+- `-w Ns`: Warmup iteration time (default: 10s)
+- `-r Ns`: Measurement iteration time (default: 10s)
+
+## Results
+
+See Javadoc of the benchmark classes:
+
+- [CounterBenchmark](https://github.com/prometheus/client_java/blob/main/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/CounterBenchmark.java)
+- [HistogramBenchmark](https://github.com/prometheus/client_java/blob/main/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/HistogramBenchmark.java)
+- [TextFormatUtilBenchmark](https://github.com/prometheus/client_java/blob/main/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/TextFormatUtilBenchmark.java)
+
+## What Prometheus Java client optimizes for
+
+concurrent updates of metrics in multi-threaded applications.
+If your application is single-threaded and uses only one processor core, your application isn't
+performance critical anyway.
+If your application is designed to use all available processor cores for maximum performance, then
+you want a metric library that doesn't slow your
+application down.
+Prometheus client Java metrics support concurrent updates and scrapes. This shows in benchmarks with
+multiple threads recording data in shared
+metrics.
+
+## Test the benchmark creation script
+
+To test the benchmark creation script, run:
+
+```shell
+python ./.mise/tasks/test_update-benchmarks.py
+```
+
+## Archive
+
+The `src/main/archive/` directory contains the old benchmarks from 0.16.0 and earlier. It will be
+removed as soon as all benchmarks are ported to the 1.0.0 release.
diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml
new file mode 100644
index 000000000..6d8c9c5c4
--- /dev/null
+++ b/benchmarks/pom.xml
@@ -0,0 +1,122 @@
+
+
+ 4.0.0
+
+
+ io.prometheus
+ client_java
+ 1.8.1-SNAPSHOT
+
+
+ benchmarks
+
+ Prometheus Java Client Benchmarks
+
+ Benchmarks of client performance, and comparison to other systems.
+
+
+
+ 1.37
+ 0.16.0
+ 3.0.2
+ true
+ true
+
+
+
+
+
+ io.opentelemetry.instrumentation
+ opentelemetry-instrumentation-bom-alpha
+ ${otel.instrumentation.version}
+ pom
+ import
+
+
+
+
+
+
+ org.openjdk.jmh
+ jmh-core
+ ${jmh.version}
+
+
+ io.prometheus
+ prometheus-metrics-core
+ ${project.version}
+
+
+ io.prometheus
+ prometheus-metrics-exposition-textformats
+ ${project.version}
+
+
+ io.prometheus
+ simpleclient
+ ${simpleclient.version}
+
+
+ com.codahale.metrics
+ metrics-core
+ ${codahale.version}
+
+
+ io.opentelemetry
+ opentelemetry-api
+
+
+ io.opentelemetry
+ opentelemetry-sdk
+
+
+ io.opentelemetry
+ opentelemetry-sdk-testing
+
+
+
+ ${project.artifactId}
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.8
+ 1.8
+
+
+ -parameters
+
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ ${jmh.version}
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+ package
+
+ shade
+
+
+ benchmarks
+
+
+ io.prometheus.metrics.benchmarks.BenchmarkRunner
+
+
+
+
+
+
+
+
+
+
diff --git a/benchmarks/src/archive/java/io/prometheus/client/CKMSQuantileBenchmark.java b/benchmarks/src/archive/java/io/prometheus/client/CKMSQuantileBenchmark.java
new file mode 100644
index 000000000..ab383d327
--- /dev/null
+++ b/benchmarks/src/archive/java/io/prometheus/client/CKMSQuantileBenchmark.java
@@ -0,0 +1,132 @@
+package io.prometheus.client;
+
+import io.prometheus.client.CKMSQuantiles.Quantile;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.infra.Blackhole;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+public class CKMSQuantileBenchmark {
+
+ @State(Scope.Benchmark)
+ public static class EmptyBenchmarkState {
+ @Param({"10000", "100000", "1000000"})
+ public int value;
+
+ List quantiles;
+ Random rand = new Random(0);
+
+ List shuffle;
+
+ Quantile mean = new Quantile(0.50, 0.050);
+ Quantile q90 = new Quantile(0.90, 0.010);
+ Quantile q95 = new Quantile(0.95, 0.005);
+ Quantile q99 = new Quantile(0.99, 0.001);
+
+ @Setup(Level.Trial)
+ public void setup() {
+ quantiles = new ArrayList();
+ quantiles.add(mean);
+ quantiles.add(q90);
+ quantiles.add(q95);
+ quantiles.add(q99);
+
+ shuffle = new ArrayList(value);
+ for (int i = 0; i < value; i++) {
+ shuffle.add((double) i);
+ }
+ Collections.shuffle(shuffle, rand);
+ }
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.AverageTime})
+ @OutputTimeUnit(TimeUnit.MILLISECONDS)
+ public void ckmsQuantileInsertBenchmark(EmptyBenchmarkState state) {
+ CKMSQuantiles q = new CKMSQuantiles(state.quantiles.toArray(new Quantile[] {}));
+ for (Double l : state.shuffle) {
+ q.insert(l);
+ }
+ }
+
+ /** prefilled benchmark, means that we already have a filled and compressed samples available */
+ @State(Scope.Benchmark)
+ public static class PrefilledBenchmarkState {
+ @Param({"10000", "100000", "1000000"})
+ public int value;
+
+ CKMSQuantiles ckmsQuantiles;
+
+ List quantiles;
+ Random rand = new Random(0);
+
+ Quantile mean = new Quantile(0.50, 0.050);
+ Quantile q90 = new Quantile(0.90, 0.010);
+ Quantile q95 = new Quantile(0.95, 0.005);
+ Quantile q99 = new Quantile(0.99, 0.001);
+ List shuffle;
+
+ int rank = (int) (value * q95.quantile);
+
+ @Setup(Level.Trial)
+ public void setup() {
+ quantiles = new ArrayList();
+ quantiles.add(mean);
+ quantiles.add(q90);
+ quantiles.add(q95);
+ quantiles.add(q99);
+
+ shuffle = new ArrayList(value);
+ for (int i = 0; i < value; i++) {
+ shuffle.add((double) i);
+ }
+ Collections.shuffle(shuffle, rand);
+
+ ckmsQuantiles = new CKMSQuantiles(quantiles.toArray(new Quantile[] {}));
+ for (Double l : shuffle) {
+ ckmsQuantiles.insert(l);
+ }
+ // make sure we inserted all 'hanging' samples (count % 128)
+ ckmsQuantiles.get(0);
+ // compress everything so we have a similar samples size regardless of n.
+ ckmsQuantiles.compress();
+ System.out.println("Sample size is: " + ckmsQuantiles.samples.size());
+ }
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.AverageTime})
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public void ckmsQuantileGetBenchmark(Blackhole blackhole, PrefilledBenchmarkState state) {
+ blackhole.consume(state.ckmsQuantiles.get(state.q90.quantile));
+ }
+
+ /** benchmark for the f method. */
+ @Benchmark
+ @BenchmarkMode({Mode.AverageTime})
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public void ckmsQuantileF(Blackhole blackhole, PrefilledBenchmarkState state) {
+ blackhole.consume(state.ckmsQuantiles.f(state.rank));
+ }
+
+ public static void main(String[] args) throws RunnerException {
+
+ Options opt =
+ new OptionsBuilder()
+ .include(CKMSQuantileBenchmark.class.getSimpleName())
+ .warmupIterations(5)
+ .measurementIterations(4)
+ .threads(1)
+ .forks(1)
+ .build();
+
+ new Runner(opt).run();
+ }
+}
diff --git a/benchmark/src/main/java/io/prometheus/benchmark/CounterBenchmark.java b/benchmarks/src/archive/java/io/prometheus/client/benchmark/CounterBenchmark.java
similarity index 59%
rename from benchmark/src/main/java/io/prometheus/benchmark/CounterBenchmark.java
rename to benchmarks/src/archive/java/io/prometheus/client/benchmark/CounterBenchmark.java
index ca644070c..c37076156 100644
--- a/benchmark/src/main/java/io/prometheus/benchmark/CounterBenchmark.java
+++ b/benchmarks/src/archive/java/io/prometheus/client/benchmark/CounterBenchmark.java
@@ -1,11 +1,10 @@
-package io.prometheus.benchmark;
+package io.prometheus.client.benchmark;
import com.codahale.metrics.MetricRegistry;
-
import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
-import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
@@ -22,69 +21,47 @@ public class CounterBenchmark {
com.codahale.metrics.Counter codahaleCounter;
com.codahale.metrics.Meter codahaleMeter;
- io.prometheus.client.metrics.Counter prometheusCounter;
- io.prometheus.client.metrics.Counter.Child prometheusCounterChild;
io.prometheus.client.Counter prometheusSimpleCounter;
io.prometheus.client.Counter.Child prometheusSimpleCounterChild;
io.prometheus.client.Counter prometheusSimpleCounterNoLabels;
@Setup
public void setup() {
- prometheusCounter = io.prometheus.client.metrics.Counter.newBuilder()
- .name("name")
- .documentation("some description..")
- .build();
- prometheusCounterChild = prometheusCounter.newPartial().apply();
-
- prometheusSimpleCounter = io.prometheus.client.Counter.build()
- .name("name")
- .help("some description..")
- .labelNames("some", "group").create();
+ prometheusSimpleCounter =
+ io.prometheus.client.Counter.build()
+ .name("name")
+ .help("some description..")
+ .labelNames("some", "group")
+ .create();
prometheusSimpleCounterChild = prometheusSimpleCounter.labels("test", "group");
- prometheusSimpleCounterNoLabels = io.prometheus.client.Counter.build()
- .name("name")
- .help("some description..")
- .create();
+ prometheusSimpleCounterNoLabels =
+ io.prometheus.client.Counter.build().name("name").help("some description..").create();
registry = new MetricRegistry();
codahaleCounter = registry.counter("counter");
codahaleMeter = registry.meter("meter");
}
- @Benchmark
- @BenchmarkMode({Mode.AverageTime})
- @OutputTimeUnit(TimeUnit.NANOSECONDS)
- public void prometheusCounterIncBenchmark() {
- prometheusCounter.newPartial().apply().increment();
- }
-
- @Benchmark
- @BenchmarkMode({Mode.AverageTime})
- @OutputTimeUnit(TimeUnit.NANOSECONDS)
- public void prometheusCounterChildIncBenchmark() {
- prometheusCounterChild.increment();
- }
-
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void prometheusSimpleCounterIncBenchmark() {
- prometheusSimpleCounter.labels("test", "group").inc();
+ prometheusSimpleCounter.labels("test", "group").inc();
}
-
+
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void prometheusSimpleCounterChildIncBenchmark() {
- prometheusSimpleCounterChild.inc();
+ prometheusSimpleCounterChild.inc();
}
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void prometheusSimpleCounterNoLabelsIncBenchmark() {
- prometheusSimpleCounterNoLabels.inc();
+ prometheusSimpleCounterNoLabels.inc();
}
@Benchmark
@@ -103,13 +80,14 @@ public void codahaleMeterMarkBenchmark() {
public static void main(String[] args) throws RunnerException {
- Options opt = new OptionsBuilder()
- .include(CounterBenchmark.class.getSimpleName())
- .warmupIterations(5)
- .measurementIterations(4)
- .threads(4)
- .forks(1)
- .build();
+ Options opt =
+ new OptionsBuilder()
+ .include(CounterBenchmark.class.getSimpleName())
+ .warmupIterations(5)
+ .measurementIterations(4)
+ .threads(4)
+ .forks(1)
+ .build();
new Runner(opt).run();
}
diff --git a/benchmarks/src/archive/java/io/prometheus/client/benchmark/ExemplarsBenchmark.java b/benchmarks/src/archive/java/io/prometheus/client/benchmark/ExemplarsBenchmark.java
new file mode 100644
index 000000000..a3fa45ae1
--- /dev/null
+++ b/benchmarks/src/archive/java/io/prometheus/client/benchmark/ExemplarsBenchmark.java
@@ -0,0 +1,87 @@
+package io.prometheus.client.benchmark;
+
+import io.prometheus.client.Counter;
+import io.prometheus.client.exemplars.DefaultExemplarSampler;
+import io.prometheus.client.exemplars.tracer.common.SpanContextSupplier;
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+
+@State(Scope.Benchmark)
+public class ExemplarsBenchmark {
+
+ private Counter counter;
+ private Counter counterWithExemplars;
+ private Counter counterWithoutExemplars;
+
+ @Setup
+ public void setup() {
+
+ counter =
+ Counter.build()
+ .name("counter_total")
+ .help("Total number of requests.")
+ .labelNames("path")
+ .create();
+
+ counterWithExemplars =
+ Counter.build()
+ .name("counter_with_exemplars_total")
+ .help("Total number of requests.")
+ .labelNames("path")
+ .withExemplarSampler(new DefaultExemplarSampler(new MockSpanContextSupplier()))
+ .create();
+
+ counterWithoutExemplars =
+ Counter.build()
+ .name("counter_without_exemplars_total")
+ .help("Total number of requests.")
+ .labelNames("path")
+ .withoutExemplars()
+ .create();
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.AverageTime})
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public void testCounter() {
+ counter.labels("test").inc();
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.AverageTime})
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public void testCounterWithExemplars() {
+ counterWithExemplars.labels("test").inc();
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.AverageTime})
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public void testCounterWithoutExemplars() {
+ counterWithoutExemplars.labels("test").inc();
+ }
+
+ private static class MockSpanContextSupplier implements SpanContextSupplier {
+
+ @Override
+ public String getTraceId() {
+ return "trace-id";
+ }
+
+ @Override
+ public String getSpanId() {
+ return "span-id";
+ }
+
+ @Override
+ public boolean isSampled() {
+ return true;
+ }
+ }
+}
diff --git a/benchmark/src/main/java/io/prometheus/benchmark/GaugeBenchmark.java b/benchmarks/src/archive/java/io/prometheus/client/benchmark/GaugeBenchmark.java
similarity index 55%
rename from benchmark/src/main/java/io/prometheus/benchmark/GaugeBenchmark.java
rename to benchmarks/src/archive/java/io/prometheus/client/benchmark/GaugeBenchmark.java
index d8037723f..a8eb03c83 100644
--- a/benchmark/src/main/java/io/prometheus/benchmark/GaugeBenchmark.java
+++ b/benchmarks/src/archive/java/io/prometheus/client/benchmark/GaugeBenchmark.java
@@ -1,11 +1,10 @@
-package io.prometheus.benchmark;
+package io.prometheus.client.benchmark;
import com.codahale.metrics.MetricRegistry;
-
import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
-import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
@@ -21,69 +20,47 @@ public class GaugeBenchmark {
MetricRegistry registry;
com.codahale.metrics.Counter codahaleCounter;
- io.prometheus.client.metrics.Gauge prometheusGauge;
- io.prometheus.client.metrics.Gauge.Child prometheusGaugeChild;
io.prometheus.client.Gauge prometheusSimpleGauge;
io.prometheus.client.Gauge.Child prometheusSimpleGaugeChild;
io.prometheus.client.Gauge prometheusSimpleGaugeNoLabels;
@Setup
public void setup() {
- prometheusGauge = io.prometheus.client.metrics.Gauge.newBuilder()
- .name("name")
- .documentation("some description..")
- .build();
- prometheusGaugeChild = prometheusGauge.newPartial().apply();
-
- prometheusSimpleGauge = io.prometheus.client.Gauge.build()
- .name("name")
- .help("some description..")
- .labelNames("some", "group").create();
+ prometheusSimpleGauge =
+ io.prometheus.client.Gauge.build()
+ .name("name")
+ .help("some description..")
+ .labelNames("some", "group")
+ .create();
prometheusSimpleGaugeChild = prometheusSimpleGauge.labels("test", "group");
- prometheusSimpleGaugeNoLabels = io.prometheus.client.Gauge.build()
- .name("name")
- .help("some description..")
- .create();
+ prometheusSimpleGaugeNoLabels =
+ io.prometheus.client.Gauge.build().name("name").help("some description..").create();
registry = new MetricRegistry();
codahaleCounter = registry.counter("name");
}
// Increment.
- @Benchmark
- @BenchmarkMode({Mode.AverageTime})
- @OutputTimeUnit(TimeUnit.NANOSECONDS)
- public void prometheusGaugeIncBenchmark() {
- prometheusGauge.newPartial().apply().increment();
- }
-
- @Benchmark
- @BenchmarkMode({Mode.AverageTime})
- @OutputTimeUnit(TimeUnit.NANOSECONDS)
- public void prometheusGaugeChildIncBenchmark() {
- prometheusGaugeChild.increment();
- }
-
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void prometheusSimpleGaugeIncBenchmark() {
- prometheusSimpleGauge.labels("test", "group").inc();
+ prometheusSimpleGauge.labels("test", "group").inc();
}
-
+
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void prometheusSimpleGaugeChildIncBenchmark() {
- prometheusSimpleGaugeChild.inc();
+ prometheusSimpleGaugeChild.inc();
}
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void prometheusSimpleGaugeNoLabelsIncBenchmark() {
- prometheusSimpleGaugeNoLabels.inc();
+ prometheusSimpleGaugeNoLabels.inc();
}
@Benchmark
@@ -93,41 +70,26 @@ public void codahaleCounterIncBenchmark() {
codahaleCounter.inc();
}
-
// Decrement.
- @Benchmark
- @BenchmarkMode({Mode.AverageTime})
- @OutputTimeUnit(TimeUnit.NANOSECONDS)
- public void prometheusGaugeDecBenchmark() {
- prometheusGauge.newPartial().apply().decrement();
- }
-
- @Benchmark
- @BenchmarkMode({Mode.AverageTime})
- @OutputTimeUnit(TimeUnit.NANOSECONDS)
- public void prometheusGaugeChildDecBenchmark() {
- prometheusGaugeChild.decrement();
- }
-
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void prometheusSimpleGaugeDecBenchmark() {
- prometheusSimpleGauge.labels("test", "group").dec();
+ prometheusSimpleGauge.labels("test", "group").dec();
}
-
+
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void prometheusSimpleGaugeChildDecBenchmark() {
- prometheusSimpleGaugeChild.dec();
+ prometheusSimpleGaugeChild.dec();
}
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void prometheusSimpleGaugeNoLabelsDecBenchmark() {
- prometheusSimpleGaugeNoLabels.dec();
+ prometheusSimpleGaugeNoLabels.dec();
}
@Benchmark
@@ -138,27 +100,13 @@ public void codahaleCounterDecBenchmark() {
}
// Set.
- @Benchmark
- @BenchmarkMode({Mode.AverageTime})
- @OutputTimeUnit(TimeUnit.NANOSECONDS)
- public void prometheusGaugeSetBenchmark() {
- prometheusGauge.newPartial().apply().set(42);
- }
-
- @Benchmark
- @BenchmarkMode({Mode.AverageTime})
- @OutputTimeUnit(TimeUnit.NANOSECONDS)
- public void prometheusGaugeChildSetBenchmark() {
- prometheusGaugeChild.set(42);
- }
-
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void prometheusSimpleGaugeSetBenchmark() {
- prometheusSimpleGauge.labels("test", "group").set(42);
+ prometheusSimpleGauge.labels("test", "group").set(42);
}
-
+
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@@ -170,18 +118,19 @@ public void prometheusSimpleGaugeChildSetBenchmark() {
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void prometheusSimpleGaugeNoLabelsSetBenchmark() {
- prometheusSimpleGaugeNoLabels.set(42);
+ prometheusSimpleGaugeNoLabels.set(42);
}
public static void main(String[] args) throws RunnerException {
- Options opt = new OptionsBuilder()
- .include(GaugeBenchmark.class.getSimpleName())
- .warmupIterations(5)
- .measurementIterations(4)
- .threads(4)
- .forks(1)
- .build();
+ Options opt =
+ new OptionsBuilder()
+ .include(GaugeBenchmark.class.getSimpleName())
+ .warmupIterations(5)
+ .measurementIterations(4)
+ .threads(4)
+ .forks(1)
+ .build();
new Runner(opt).run();
}
diff --git a/benchmarks/src/archive/java/io/prometheus/client/benchmark/SanitizeMetricNameBenchmark.java b/benchmarks/src/archive/java/io/prometheus/client/benchmark/SanitizeMetricNameBenchmark.java
new file mode 100644
index 000000000..cb5f300ce
--- /dev/null
+++ b/benchmarks/src/archive/java/io/prometheus/client/benchmark/SanitizeMetricNameBenchmark.java
@@ -0,0 +1,49 @@
+package io.prometheus.client.benchmark;
+
+import io.prometheus.client.Collector;
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+import org.openjdk.jmh.runner.options.TimeValue;
+
+@State(Scope.Benchmark)
+public class SanitizeMetricNameBenchmark {
+
+ @Benchmark
+ @BenchmarkMode({Mode.AverageTime})
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public void sanitizeSanitizedName() {
+ Collector.sanitizeMetricName("good_name");
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.AverageTime})
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public void sanitizeNonSanitizedName() {
+ Collector.sanitizeMetricName("9not_good_name!");
+ }
+
+ public static void main(String[] args) throws RunnerException {
+
+ Options opt =
+ new OptionsBuilder()
+ .include(SanitizeMetricNameBenchmark.class.getSimpleName())
+ .warmupIterations(5)
+ .measurementIterations(4)
+ .measurementTime(TimeValue.seconds(1))
+ .warmupTime(TimeValue.seconds(1))
+ .threads(4)
+ .forks(1)
+ .build();
+
+ new Runner(opt).run();
+ }
+}
diff --git a/benchmark/src/main/java/io/prometheus/benchmark/SummaryBenchmark.java b/benchmarks/src/archive/java/io/prometheus/client/benchmark/SummaryBenchmark.java
similarity index 60%
rename from benchmark/src/main/java/io/prometheus/benchmark/SummaryBenchmark.java
rename to benchmarks/src/archive/java/io/prometheus/client/benchmark/SummaryBenchmark.java
index 3a77dc5ec..2964b8ea8 100644
--- a/benchmark/src/main/java/io/prometheus/benchmark/SummaryBenchmark.java
+++ b/benchmarks/src/archive/java/io/prometheus/client/benchmark/SummaryBenchmark.java
@@ -1,11 +1,10 @@
-package io.prometheus.benchmark;
+package io.prometheus.client.benchmark;
import com.codahale.metrics.MetricRegistry;
-
import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
-import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
@@ -21,8 +20,6 @@ public class SummaryBenchmark {
MetricRegistry registry;
com.codahale.metrics.Histogram codahaleHistogram;
- io.prometheus.client.metrics.Summary prometheusSummary;
- io.prometheus.client.metrics.Summary.Child prometheusSummaryChild;
io.prometheus.client.Summary prometheusSimpleSummary;
io.prometheus.client.Summary.Child prometheusSimpleSummaryChild;
io.prometheus.client.Summary prometheusSimpleSummaryNoLabels;
@@ -32,78 +29,58 @@ public class SummaryBenchmark {
@Setup
public void setup() {
- prometheusSummary = io.prometheus.client.metrics.Summary.newBuilder()
- .name("name")
- .documentation("some description..")
- .build();
- prometheusSummaryChild = prometheusSummary.newPartial().apply();
-
- prometheusSimpleSummary = io.prometheus.client.Summary.build()
- .name("name")
- .help("some description..")
- .labelNames("some", "group").create();
+ prometheusSimpleSummary =
+ io.prometheus.client.Summary.build()
+ .name("name")
+ .help("some description..")
+ .labelNames("some", "group")
+ .create();
prometheusSimpleSummaryChild = prometheusSimpleSummary.labels("test", "group");
- prometheusSimpleSummaryNoLabels = io.prometheus.client.Summary.build()
- .name("name")
- .help("some description..")
- .create();
+ prometheusSimpleSummaryNoLabels =
+ io.prometheus.client.Summary.build().name("name").help("some description..").create();
- prometheusSimpleHistogram = io.prometheus.client.Histogram.build()
- .name("name")
- .help("some description..")
- .labelNames("some", "group").create();
+ prometheusSimpleHistogram =
+ io.prometheus.client.Histogram.build()
+ .name("name")
+ .help("some description..")
+ .labelNames("some", "group")
+ .create();
prometheusSimpleHistogramChild = prometheusSimpleHistogram.labels("test", "group");
- prometheusSimpleHistogramNoLabels = io.prometheus.client.Histogram.build()
- .name("name")
- .help("some description..")
- .create();
+ prometheusSimpleHistogramNoLabels =
+ io.prometheus.client.Histogram.build().name("name").help("some description..").create();
registry = new MetricRegistry();
codahaleHistogram = registry.histogram("name");
}
- @Benchmark
- @BenchmarkMode({Mode.AverageTime})
- @OutputTimeUnit(TimeUnit.NANOSECONDS)
- public void prometheusSummaryBenchmark() {
- prometheusSummary.newPartial().apply().observe(1.0);
- }
-
- @Benchmark
- @BenchmarkMode({Mode.AverageTime})
- @OutputTimeUnit(TimeUnit.NANOSECONDS)
- public void prometheusSummaryChildBenchmark() {
- prometheusSummaryChild.observe(1.0);
- }
-
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void prometheusSimpleSummaryBenchmark() {
- prometheusSimpleSummary.labels("test", "group").observe(1) ;
+ prometheusSimpleSummary.labels("test", "group").observe(1);
}
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void prometheusSimpleSummaryChildBenchmark() {
- prometheusSimpleSummaryChild.observe(1);
+ prometheusSimpleSummaryChild.observe(1);
}
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void prometheusSimpleSummaryNoLabelsBenchmark() {
- prometheusSimpleSummaryNoLabels.observe(1);
+ prometheusSimpleSummaryNoLabels.observe(1);
}
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void prometheusSimpleHistogramBenchmark() {
- prometheusSimpleHistogram.labels("test", "group").observe(1) ;
+ prometheusSimpleHistogram.labels("test", "group").observe(1);
}
@Benchmark
@@ -129,13 +106,14 @@ public void codahaleHistogramBenchmark() {
public static void main(String[] args) throws RunnerException {
- Options opt = new OptionsBuilder()
- .include(SummaryBenchmark.class.getSimpleName())
- .warmupIterations(5)
- .measurementIterations(4)
- .threads(4)
- .forks(1)
- .build();
+ Options opt =
+ new OptionsBuilder()
+ .include(SummaryBenchmark.class.getSimpleName())
+ .warmupIterations(5)
+ .measurementIterations(4)
+ .threads(4)
+ .forks(1)
+ .build();
new Runner(opt).run();
}
diff --git a/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/BenchmarkRunner.java b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/BenchmarkRunner.java
new file mode 100644
index 000000000..9d5d242ae
--- /dev/null
+++ b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/BenchmarkRunner.java
@@ -0,0 +1,7 @@
+package io.prometheus.metrics.benchmarks;
+
+public class BenchmarkRunner {
+ public static void main(String[] args) throws Exception {
+ org.openjdk.jmh.Main.main(args);
+ }
+}
diff --git a/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/CounterBenchmark.java b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/CounterBenchmark.java
new file mode 100644
index 000000000..d8b75e437
--- /dev/null
+++ b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/CounterBenchmark.java
@@ -0,0 +1,206 @@
+package io.prometheus.metrics.benchmarks;
+
+import io.opentelemetry.api.OpenTelemetry;
+import io.opentelemetry.api.common.AttributeKey;
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.metrics.DoubleCounter;
+import io.opentelemetry.api.metrics.LongCounter;
+import io.opentelemetry.api.metrics.Meter;
+import io.opentelemetry.sdk.OpenTelemetrySdk;
+import io.opentelemetry.sdk.metrics.SdkMeterProvider;
+import io.opentelemetry.sdk.resources.Resource;
+import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader;
+import io.prometheus.metrics.core.datapoints.CounterDataPoint;
+import io.prometheus.metrics.core.metrics.Counter;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Threads;
+
+/**
+ * Results on a machine with dedicated Ubuntu 24.04 LTS, AMD Ryzen™ 9 7900 × 24, 96.0 GiB RAM:
+ *
+ *
+ *
+ * The simpleclient (i.e. client_java version 0.16.0 and older) histograms perform about the same as
+ * the classic histogram of the current 1.0.0 version.
+ *
+ *
Compared to OpenTelemetry histograms the Prometheus Java client histograms perform more than 3
+ * times better (OpenTelemetry has 1908 ops / sec for classic histograms, while Prometheus has 6451
+ * ops / sec).
+ */
+public class HistogramBenchmark {
+
+ @State(Scope.Benchmark)
+ public static class PrometheusClassicHistogram {
+
+ final Histogram noLabels;
+
+ public PrometheusClassicHistogram() {
+ noLabels = Histogram.builder().name("test").help("help").classicOnly().build();
+ }
+ }
+
+ @State(Scope.Thread)
+ public static class PrometheusClassicHistogramPerThread {
+
+ final Histogram noLabels;
+
+ public PrometheusClassicHistogramPerThread() {
+ noLabels = Histogram.builder().name("test").help("help").classicOnly().build();
+ }
+ }
+
+ @State(Scope.Benchmark)
+ public static class PrometheusNativeHistogram {
+
+ final Histogram noLabels;
+
+ public PrometheusNativeHistogram() {
+ noLabels =
+ Histogram.builder()
+ .name("test")
+ .help("help")
+ .nativeOnly()
+ .nativeInitialSchema(5)
+ .nativeMaxNumberOfBuckets(0)
+ .build();
+ }
+ }
+
+ @State(Scope.Benchmark)
+ public static class SimpleclientHistogram {
+
+ final io.prometheus.client.Histogram noLabels;
+
+ public SimpleclientHistogram() {
+ noLabels = io.prometheus.client.Histogram.build().name("name").help("help").create();
+ }
+ }
+
+ @State(Scope.Benchmark)
+ public static class OpenTelemetryClassicHistogram {
+
+ final io.opentelemetry.api.metrics.DoubleHistogram histogram;
+
+ public OpenTelemetryClassicHistogram() {
+
+ SdkMeterProvider sdkMeterProvider =
+ SdkMeterProvider.builder()
+ .registerMetricReader(InMemoryMetricReader.create())
+ .setResource(Resource.getDefault())
+ .registerView(
+ InstrumentSelector.builder().setName("test").build(),
+ View.builder()
+ .setAggregation(
+ Aggregation.explicitBucketHistogram(
+ Arrays.asList(
+ .005, .01, .025, .05, .1, .25, .5, 1.0, 2.5, 5.0, 10.0)))
+ .build())
+ .build();
+ OpenTelemetry openTelemetry =
+ OpenTelemetrySdk.builder().setMeterProvider(sdkMeterProvider).build();
+ Meter meter =
+ openTelemetry
+ .meterBuilder("instrumentation-library-name")
+ .setInstrumentationVersion("1.0.0")
+ .build();
+ this.histogram = meter.histogramBuilder("test").setDescription("test").build();
+ }
+ }
+
+ @State(Scope.Benchmark)
+ public static class OpenTelemetryExponentialHistogram {
+
+ final io.opentelemetry.api.metrics.DoubleHistogram histogram;
+
+ public OpenTelemetryExponentialHistogram() {
+
+ SdkMeterProvider sdkMeterProvider =
+ SdkMeterProvider.builder()
+ .registerMetricReader(InMemoryMetricReader.create())
+ .setResource(Resource.getDefault())
+ .registerView(
+ InstrumentSelector.builder().setName("test").build(),
+ View.builder()
+ .setAggregation(Aggregation.base2ExponentialBucketHistogram(10_000, 5))
+ .build())
+ .build();
+ OpenTelemetry openTelemetry =
+ OpenTelemetrySdk.builder().setMeterProvider(sdkMeterProvider).build();
+ Meter meter =
+ openTelemetry
+ .meterBuilder("instrumentation-library-name")
+ .setInstrumentationVersion("1.0.0")
+ .build();
+ this.histogram = meter.histogramBuilder("test").setDescription("test").build();
+ }
+ }
+
+ @Benchmark
+ @Threads(4)
+ public Histogram prometheusClassic(
+ RandomNumbers randomNumbers, PrometheusClassicHistogram histogram) {
+ for (int i = 0; i < randomNumbers.randomNumbers.length; i++) {
+ histogram.noLabels.observe(randomNumbers.randomNumbers[i]);
+ }
+ return histogram.noLabels;
+ }
+
+ @Benchmark
+ @Threads(1)
+ public Histogram prometheusClassicSingleThread(
+ RandomNumbers randomNumbers, PrometheusClassicHistogram histogram) {
+ for (int i = 0; i < randomNumbers.randomNumbers.length; i++) {
+ histogram.noLabels.observe(randomNumbers.randomNumbers[i]);
+ }
+ return histogram.noLabels;
+ }
+
+ @Benchmark
+ @Threads(4)
+ public Histogram prometheusClassicPerThread(
+ RandomNumbers randomNumbers, PrometheusClassicHistogramPerThread histogram) {
+ for (int i = 0; i < randomNumbers.randomNumbers.length; i++) {
+ histogram.noLabels.observe(randomNumbers.randomNumbers[i]);
+ }
+ return histogram.noLabels;
+ }
+
+ @Benchmark
+ @Threads(4)
+ public Histogram prometheusNative(
+ RandomNumbers randomNumbers, PrometheusNativeHistogram histogram) {
+ for (int i = 0; i < randomNumbers.randomNumbers.length; i++) {
+ histogram.noLabels.observe(randomNumbers.randomNumbers[i]);
+ }
+ return histogram.noLabels;
+ }
+
+ @Benchmark
+ @Threads(4)
+ public io.prometheus.client.Histogram simpleclient(
+ RandomNumbers randomNumbers, SimpleclientHistogram histogram) {
+ for (int i = 0; i < randomNumbers.randomNumbers.length; i++) {
+ histogram.noLabels.observe(randomNumbers.randomNumbers[i]);
+ }
+ return histogram.noLabels;
+ }
+
+ @Benchmark
+ @Threads(4)
+ public io.opentelemetry.api.metrics.DoubleHistogram openTelemetryClassic(
+ RandomNumbers randomNumbers, OpenTelemetryClassicHistogram histogram) {
+ for (int i = 0; i < randomNumbers.randomNumbers.length; i++) {
+ histogram.histogram.record(randomNumbers.randomNumbers[i]);
+ }
+ return histogram.histogram;
+ }
+
+ @Benchmark
+ @Threads(4)
+ public io.opentelemetry.api.metrics.DoubleHistogram openTelemetryExponential(
+ RandomNumbers randomNumbers, OpenTelemetryExponentialHistogram histogram) {
+ for (int i = 0; i < randomNumbers.randomNumbers.length; i++) {
+ histogram.histogram.record(randomNumbers.randomNumbers[i]);
+ }
+ return histogram.histogram;
+ }
+}
diff --git a/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/HistogramTextFormatBenchmark.java b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/HistogramTextFormatBenchmark.java
new file mode 100644
index 000000000..47a34ac18
--- /dev/null
+++ b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/HistogramTextFormatBenchmark.java
@@ -0,0 +1,71 @@
+package io.prometheus.metrics.benchmarks;
+
+import io.prometheus.metrics.config.EscapingScheme;
+import io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter;
+import io.prometheus.metrics.expositionformats.PrometheusTextFormatWriter;
+import io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets;
+import io.prometheus.metrics.model.snapshots.HistogramSnapshot;
+import io.prometheus.metrics.model.snapshots.HistogramSnapshot.HistogramDataPointSnapshot;
+import io.prometheus.metrics.model.snapshots.Labels;
+import io.prometheus.metrics.model.snapshots.MetricSnapshots;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Warmup;
+
+/**
+ * Benchmarks for writing a classic histogram (10 label combinations × 12 buckets) to text formats.
+ * Output goes to /dev/null to isolate pure formatting CPU cost with zero IO overhead.
+ */
+@Fork(3)
+@Warmup(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
+@Measurement(iterations = 10, time = 2, timeUnit = TimeUnit.SECONDS)
+public class HistogramTextFormatBenchmark {
+
+ private static final MetricSnapshots SNAPSHOTS;
+
+ static {
+ double[] upperBounds = {
+ .005, .01, .025, .05, .1, .25, .5, 1.0, 2.5, 5.0, 10.0, Double.POSITIVE_INFINITY
+ };
+ Number[] counts = {1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L};
+ ClassicHistogramBuckets buckets = ClassicHistogramBuckets.of(upperBounds, counts);
+
+ HistogramSnapshot.Builder builder =
+ HistogramSnapshot.builder().name("http_request_duration_seconds");
+
+ for (int i = 0; i < 10; i++) {
+ builder.dataPoint(
+ HistogramDataPointSnapshot.builder()
+ .classicHistogramBuckets(buckets)
+ .labels(Labels.of("status", "value_" + i))
+ .sum(123.456)
+ .createdTimestampMillis(1000L)
+ .build());
+ }
+
+ SNAPSHOTS = MetricSnapshots.of(builder.build());
+ }
+
+ private static final OpenMetricsTextFormatWriter OPEN_METRICS_TEXT_FORMAT_WRITER =
+ OpenMetricsTextFormatWriter.create();
+ private static final PrometheusTextFormatWriter PROMETHEUS_TEXT_FORMAT_WRITER =
+ PrometheusTextFormatWriter.create();
+
+ @Benchmark
+ public OutputStream openMetricsWriteToNull() throws IOException {
+ OutputStream nullOutputStream = TextFormatUtilBenchmark.NullOutputStream.INSTANCE;
+ OPEN_METRICS_TEXT_FORMAT_WRITER.write(nullOutputStream, SNAPSHOTS, EscapingScheme.ALLOW_UTF8);
+ return nullOutputStream;
+ }
+
+ @Benchmark
+ public OutputStream prometheusWriteToNull() throws IOException {
+ OutputStream nullOutputStream = TextFormatUtilBenchmark.NullOutputStream.INSTANCE;
+ PROMETHEUS_TEXT_FORMAT_WRITER.write(nullOutputStream, SNAPSHOTS, EscapingScheme.ALLOW_UTF8);
+ return nullOutputStream;
+ }
+}
diff --git a/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/RandomNumbers.java b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/RandomNumbers.java
new file mode 100644
index 000000000..6778c4ea1
--- /dev/null
+++ b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/RandomNumbers.java
@@ -0,0 +1,18 @@
+package io.prometheus.metrics.benchmarks;
+
+import java.util.Random;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+
+@State(Scope.Thread)
+public class RandomNumbers {
+
+ final double[] randomNumbers = new double[10 * 1024];
+
+ public RandomNumbers() {
+ Random rand = new Random(0);
+ for (int i = 0; i < randomNumbers.length; i++) {
+ randomNumbers[i] = Math.abs(rand.nextGaussian());
+ }
+ }
+}
diff --git a/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/TextFormatUtilBenchmark.java b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/TextFormatUtilBenchmark.java
new file mode 100644
index 000000000..19fb60bcb
--- /dev/null
+++ b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/TextFormatUtilBenchmark.java
@@ -0,0 +1,136 @@
+package io.prometheus.metrics.benchmarks;
+
+import io.prometheus.metrics.config.EscapingScheme;
+import io.prometheus.metrics.expositionformats.ExpositionFormatWriter;
+import io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter;
+import io.prometheus.metrics.expositionformats.PrometheusTextFormatWriter;
+import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
+import io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot;
+import io.prometheus.metrics.model.snapshots.Labels;
+import io.prometheus.metrics.model.snapshots.MetricSnapshot;
+import io.prometheus.metrics.model.snapshots.MetricSnapshots;
+import io.prometheus.metrics.model.snapshots.SummarySnapshot;
+import io.prometheus.metrics.model.snapshots.SummarySnapshot.SummaryDataPointSnapshot;
+import io.prometheus.metrics.model.snapshots.Unit;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+
+/**
+ * Results on a machine with dedicated Ubuntu 24.04 LTS, AMD Ryzen™ 9 7900 × 24, 96.0 GiB RAM:
+ *
+ *
- * A {@link JsonSerializer} for converting {@link AtomicDouble} into an
- * acceptable value for {@link com.google.gson.Gson}.
- *
- *
- * @author matt.proud@gmail.com (Matt T. Proud)
- */
-@ThreadSafe
-class AtomicDoubleSerializer implements JsonSerializer {
- @Override
- public JsonElement serialize(final AtomicDouble src, final Type typeOfSrc,
- final JsonSerializationContext context) {
- return new JsonPrimitive(src.doubleValue());
- }
-}
diff --git a/client/src/main/java/io/prometheus/client/Prometheus.java b/client/src/main/java/io/prometheus/client/Prometheus.java
deleted file mode 100644
index e1cf03871..000000000
--- a/client/src/main/java/io/prometheus/client/Prometheus.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright 2013 Prometheus Team Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package io.prometheus.client;
-
-import com.google.common.util.concurrent.AtomicDouble;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonArray;
-import io.prometheus.client.metrics.Counter;
-import io.prometheus.client.metrics.Gauge;
-import io.prometheus.client.metrics.Metric;
-import io.prometheus.client.metrics.Summary;
-import io.prometheus.client.utility.Clock;
-import io.prometheus.client.utility.SystemClock;
-import org.reflections.Reflections;
-import org.reflections.scanners.FieldAnnotationsScanner;
-import org.reflections.util.ClasspathHelper;
-import org.reflections.util.ConfigurationBuilder;
-
-import javax.annotation.concurrent.ThreadSafe;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.Writer;
-import java.lang.reflect.Field;
-import java.util.Collection;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * {@link Prometheus} manages the registration and exposition of
- * {@link io.prometheus.client.metrics.Metric} instances.
- *
- *
- *
- * You can apply the patterns from examples in the following classes' Javadocs:
- *
- *
- * {@link Counter}
- *
- * {@link Gauge}
- *
- * {@link Summary}
- *
- *
- *
- * Important: To initialize the whole stack, call
- * {@link Prometheus#defaultInitialize()} once somewhere in your main
- * function.
- *
- * @see io.prometheus.client.metrics.Metric
- * @author matt.proud@gmail.com (Matt T. Proud)
- */
-@ThreadSafe
-public class Prometheus {
- private static final Logger log = Logger.getLogger(Prometheus.class.getName());
-
- private static final Gson serializer = new GsonBuilder()
- .registerTypeAdapter(AtomicDouble.class, new AtomicDoubleSerializer())
- .registerTypeAdapter(Counter.class, new Counter.Serializer())
- .registerTypeAdapter(Gauge.class, new Gauge.Serializer())
- .registerTypeAdapter(Summary.class, new Summary.Serializer()).create();
-
- private static final Prometheus defaultPrometheus = new Prometheus();
-
- private final Clock clock = new SystemClock();
- private final ConcurrentHashMap metrics = new ConcurrentHashMap();
- private final ConcurrentHashMap preexpositionHooks =
- new ConcurrentHashMap();
-
- private void register(final Metric m) {
- final Metric existing = metrics.putIfAbsent(m, m);
-
- if (existing == null) {
- log.log(Level.FINE, String.format("Registered %s", m));
- } else {
- if (existing != m) {
- log.log(Level.WARNING, String.format(
- "Cannot register %s, because %s is registered in its place.", m, existing));
- }
- }
- }
-
- private void dumpProto(final OutputStream o) throws IOException {
- final long start = clock.nowMs();
-
- runPreexpositionHooks();
-
- final Counter.Partial requests = Telemetry.telemetryRequests.newPartial();
- final Summary.Partial latencies = Telemetry.telemetryGenerationLatencies.newPartial();
- try {
- for (final Metric m : metrics.keySet()) {
- m.dump().writeDelimitedTo(o);
- }
- requests.labelPair("result", "success");
- latencies.labelPair("result", "success");
- } catch (final IOException e) {
- requests.labelPair("result", "failure");
- latencies.labelPair("result", "failure");
- throw e;
- } catch (final RuntimeException e) {
- requests.labelPair("result", "failure");
- latencies.labelPair("result", "failure");
- throw e;
- } finally {
- final double duration = clock.nowMs() - start;
-
- requests.apply().increment();
- latencies.apply().observe(duration);
- }
- }
-
- @Deprecated
- private void dumpJson(final Writer writer) throws IOException {
- final long start = clock.nowMs();
-
- runPreexpositionHooks();
-
- final Counter.Partial requests = Telemetry.telemetryRequests.newPartial();
- final Summary.Partial latencies = Telemetry.telemetryGenerationLatencies.newPartial();
- try {
- final JsonArray array = new JsonArray();
- for (final Metric m : metrics.keySet()) {
- array.add(serializer.toJsonTree(m));
- }
- writer.write(array.toString());
- requests.labelPair("result", "success");
- latencies.labelPair("result", "success");
- } catch (final IOException e) {
- requests.labelPair("result", "failure");
- latencies.labelPair("result", "failure");
- throw e;
- } catch (final RuntimeException e) {
- requests.labelPair("result", "failure");
- latencies.labelPair("result", "failure");
- throw e;
- } finally {
- final double duration = clock.nowMs() - start;
-
- requests.apply().increment();
- latencies.apply().observe(duration);
- }
- }
-
- /**
- *
- * Register a {@link Metric} with Prometheus
- *
- */
- public static void defaultRegister(final Metric m) {
- defaultPrometheus.register(m);
- }
-
- /**
- *
- * Dump all metrics registered via {@link Register} to the provided
- * {@link Writer} in JSON.
- *
- * Dump all metrics registered via {@link Register} to the provided
- * {@link OutputStream} in varint-encoded record-length delimited Protocol
- * Buffer messages of {@link io.prometheus.client.Metrics.MetricFamily}.
- *
- */
- public static void defaultDumpProto(final OutputStream o) throws IOException {
- defaultPrometheus.dumpProto(o);
- }
-
- private Collection collectAnnotatedFields() {
- final Reflections reflections =
- new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forJavaClassPath())
- .setScanners(new FieldAnnotationsScanner()));
-
- return reflections.getFieldsAnnotatedWith(Register.class);
- }
-
- private void initialize() {
- final long start = clock.nowMs();
- final Gauge.Partial duration = Telemetry.initializeTime.newPartial();
-
- try {
- final Collection fields = collectAnnotatedFields();
- for (final Field field : fields) {
- final boolean wasAccessible = field.isAccessible();
- final String candidateName = field.getDeclaringClass().getCanonicalName();
- try {
- // Explicitly load the class to invoke any static blocks and
- // initializers.
- final Class> klass = Class.forName(candidateName);
- if (klass == null) {
- continue;
- }
-
- final Register annotation = field.getAnnotation(Register.class);
- if (annotation == null) {
- continue;
- }
-
- if (!wasAccessible) {
- field.setAccessible(true);
- }
-
- final Metric metric = (Metric) field.get(klass);
- register(metric);
- } catch (final ClassNotFoundException e) {
- System.err.printf("Could not find %s\n", candidateName);
- } catch (final IllegalAccessException e) {
- System.err.printf("Not allowed to access %s\n", field);
- } finally {
- if (!wasAccessible) {
- field.setAccessible(false);
- }
- }
- }
- duration.labelPair("result", "success");
- } catch (final RuntimeException e) {
- duration.labelPair("result", "failure");
- throw e;
- } finally {
- final float elapsed = clock.nowMs() - start;
- duration.apply().set(elapsed);
- }
- }
-
- private void addPreexpositionHook(final ExpositionHook h) {
- preexpositionHooks.putIfAbsent(h, this);
- }
-
- private void runPreexpositionHooks() {
- for (final ExpositionHook hook : preexpositionHooks.keySet()) {
- hook.run();
- }
- }
-
- /**
- *
- * Register all {@link Metric} instances and their derivatives according to
- * the classpath findability discussion in {@link Register}.
- *
- *
- *
- * Important Usage Notes:
- *
- *
- *
Calling this is a prerequisite for successful Prometheus
- * usage, meaning if it is never called, no metrics will be exposed.
- *
It is recommended that it is invoked early in the cycle of the main
- * class' main block.
- * A management hook to be run prior to each metric exposition request.
- *
- */
- public static interface ExpositionHook extends Runnable {
- }
-}
diff --git a/client/src/main/java/io/prometheus/client/Register.java b/client/src/main/java/io/prometheus/client/Register.java
deleted file mode 100644
index 0ec206934..000000000
--- a/client/src/main/java/io/prometheus/client/Register.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2013 Prometheus Team Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package io.prometheus.client;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- *
- * Register {@link io.prometheus.client.metrics.Metric} and their derivatives with the
- * {@link Prometheus} registrar across all runtime libraries and their dependencies and the
- * class path.
- *
- *
- *
- * The purpose of this runtime annotation is to provide a common fragment to search for
- * across an entire server's classpath for metrics to export. Due to nuances in the underlying
- * Java Virtual Machine implementations and behaviors around both class loading and initialization
- * (i.e., behaviors outside of Prometheus' and your direct control), not every class referenced in
- * an application's transitive closure and its classpath will be loaded and initialized, unless it
- * is referenced by a dependent type, which is itself referenced by a root type in the
- * application.
- *
- *
Not using this optional annotation may prevent expected telemetry from being
- * found and registered! This is to say, metric consumers may not find the metrics they
- * want without it. Each {@link io.prometheus.client.metrics.Metric} decorated with
- * {@link Register} will be found and registered for exposition across all libraries your server
- * depends on. This registration property can be beneficial for authors of shared
- * infrastructure libraries that are used by multiple teams!
- *
- *
- * @author matt.proud@gmail.com (Matt T. Proud)
- */
-@Target(value = {ElementType.FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Register {
-}
diff --git a/client/src/main/java/io/prometheus/client/Telemetry.java b/client/src/main/java/io/prometheus/client/Telemetry.java
deleted file mode 100644
index 49e4f2720..000000000
--- a/client/src/main/java/io/prometheus/client/Telemetry.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2013 Prometheus Team Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package io.prometheus.client;
-
-import io.prometheus.client.metrics.Counter;
-import io.prometheus.client.metrics.Gauge;
-import io.prometheus.client.metrics.Summary;
-
-/**
- *
- * Standard telemetry for all Prometheus clients.
- *
- *
- * @author matt.proud@gmail.com (Matt T. Proud)
- */
-class Telemetry {
- @Register
- static final Gauge initializeTime = Gauge.newBuilder()
- .namespace("telemetry")
- .name("initialization_time_ms")
- .documentation("The time it took for the telemetry system to initialize.")
- .build();
-
- @Register
- static final Gauge serverStartTime = Gauge.newBuilder()
- .namespace("telemetry")
- .name("server_start_time_ms")
- .documentation("The time at which the server started.")
- .build();
-
- @Register
- static final Counter telemetryRequests = Counter.newBuilder()
- .namespace("telemetry")
- .name("requests_metrics_total")
- .documentation("A counter of the total requests made against the telemetry system.")
- .build();
-
- @Register
- static final Summary telemetryGenerationLatencies = Summary.newBuilder()
- .namespace("telemetry")
- .name("generation_latency_ms")
- .documentation("A histogram of telemetry generation latencies.")
- .targetQuantile(0.01, 0.05)
- .targetQuantile(0.05, 0.05)
- .targetQuantile(0.5, 0.05)
- .targetQuantile(0.9, 0.01)
- .targetQuantile(0.99, 0.001)
- .build();
-
- static {
- serverStartTime.newPartial().apply().set(System.currentTimeMillis() / 1000);
- }
-}
diff --git a/client/src/main/java/io/prometheus/client/metrics/Counter.java b/client/src/main/java/io/prometheus/client/metrics/Counter.java
deleted file mode 100644
index f462a7fe9..000000000
--- a/client/src/main/java/io/prometheus/client/metrics/Counter.java
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright 2013 Prometheus Team Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package io.prometheus.client.metrics;
-
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.AtomicDouble;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import io.prometheus.client.Metrics;
-import io.prometheus.client.utility.labels.Reserved;
-
-import javax.annotation.concurrent.NotThreadSafe;
-import javax.annotation.concurrent.ThreadSafe;
-import java.lang.reflect.Type;
-import java.util.List;
-import java.util.Map;
-
-/**
- *
- * {@link Counter} is a {@link Metric} that tracks the addition or subtraction
- * of a value from itself.
- *
- *
- *
- * Tallies: Number of people who walked through that door.
- *
- * Running Sums: Amount of money that has been brought through the door.
- *
- *
- *
- *
- * An example follows:
- *
- *
- *
- * {@code
- * package example;
- *
- * import io.prometheus.client.Prometheus;
- * import io.prometheus.client.Register;
- * import io.prometheus.client.metrics.Counter;
- *
- * public class CashRegister {
- * // Annotate this with "Register" if this class is not explicitly loaded
- * // by your project.
- * private static final Counter operations = Counter.newBuilder()
- * .namespace("cash_register")
- * .name("operations")
- * .labelNames("operation", "result")
- * .documentation("Cash register operations partitioned by type and outcome.")
- * .build()
- *
- * public float divide(float dividend, float divisor) {
- * Counter.Partial result = operations.newPartial()
- * .labelPair("operation", "division");
- * try {
- * float f = dividend / divisor;
- * result.labelPair("result", "success");
- * return f;
- * } catch (ArithmeticException e) {
- * result.labelPair("result", "failure");
- * throw e;
- * } finally {
- * result.apply().increment();
- * }
- * }
- * }}
- *
- *
- *
- * Assuming that each code path is executed once, {@code operations} yields the following
- * child metrics:
- *
- * Create a {@link Builder} to configure the {@link Counter}.
- *
- */
- public static Builder newBuilder() {
- return new Builder();
- }
-
- /**
- *
- * Define the characteristics for this {@link Counter}.
- *
- *
- * Implementation-Specific Behaviors:
- *
- *
- * If the metric and its children are reset, a default value of {@code 0} is
- * used.
- *
- *
- *
- * For all other behaviors, see {@link Metric.BaseBuilder}.
- *
- */
- @ThreadSafe
- public static class Builder implements Metric.Builder {
- private static final Double DEFAULT_VALUE = Double.valueOf(0);
-
- private final Metric.BaseBuilder base;
- private final Optional defaultValue;
-
- Builder() {
- base = new Metric.BaseBuilder();
- defaultValue = Optional.absent();
- }
-
- private Builder(final BaseBuilder base, final Optional defaultValue) {
- this.base = base;
- this.defaultValue = defaultValue;
- }
-
- @Override
- public Builder labelNames(String... ds) {
- return new Builder(base.labelNames(ds), defaultValue);
- }
-
- @Override
- public Builder documentation(String d) {
- return new Builder(base.documentation(d), defaultValue);
- }
-
- @Override
- public Builder name(String n) {
- return new Builder(base.name(n), defaultValue);
- }
-
- @Override
- public Builder subsystem(String ss) {
- return new Builder(base.subsystem(ss), defaultValue);
- }
-
- @Override
- public Builder namespace(String ns) {
- return new Builder(base.namespace(ns), defaultValue);
- }
-
- @Override
- public Builder registerStatic(final boolean rs) {
- return new Builder(base.registerStatic(rs), defaultValue);
- }
-
- /**
- *
- * Provide a custom default value for this {@link Counter} when it undergoes
- * a {@link io.prometheus.client.metrics.Counter#resetAll()} or a specific
- * {@link Child} undergoes a {@link Counter.Child#reset()}.
- *
- *
- * @return A copy of the original {@link Builder} with the new
- * target value.
- */
- public Builder defaultValue(final Double v) {
- return new Builder(base, Optional.of(v));
- }
-
- private double getDefaultValue() {
- return defaultValue.or(DEFAULT_VALUE);
- }
-
- /**
- *
- * Generate a concrete {@link Counter} from this {@link Builder}.
- *
- */
- public Counter build() {
- final String name = base.buildName();
- final String docstring = base.buildDocstring();
-
- final Metrics.MetricFamily.Builder builder =
- Metrics.MetricFamily.newBuilder().setName(name).setHelp(docstring)
- .setType(Metrics.MetricType.COUNTER);
-
- return new Counter(name, docstring, base.buildLabelNames(), getDefaultValue(),
- builder.build(), base.getRegisterStatic());
- }
- }
-
- /**
- *
- * A derivative of {@link Counter} that lets you accumulate labels to build a
- * concrete metric via {@link #apply()} for mutation with the methods of
- * {@link Counter.Child}.
- *
- *
- *
- * Warning: All mutations to {@link Partial} are retained. You should not
- * share {@link Partial} between distinct label sets unless you have a parent
- * {@link Partial} that you {@link io.prometheus.client.metrics.Counter.Partial#clone()}.
- *
- *
- *
- * In this example below, we have both a race condition with a nasty outcome that
- * unformedMetric is mutated in both threads and that it is an undefined behavior, which
- * {@code data-type} label pair setting wins.
- *
- * A concrete instance of {@link Counter} for a unique set of label
- * dimensions.
- *
- *
- *
- * Warning: Do not hold onto a reference of a {@link Child} if you
- * ever use the {@link #resetAll()}. If you want to hold onto a concrete
- * instance, please hold onto a {@link io.prometheus.client.metrics.Counter.Partial} and use
- * {@link io.prometheus.client.metrics.Counter.Partial#apply()}.
- *
- *
- * @see Metric.Child
- */
- @ThreadSafe
- public class Child implements Metric.Child {
- final AtomicDouble value = new AtomicDouble();
-
- /**
- *
- * Increment this {@link Counter.Child} by one.
- *
- * Used to serialize {@link Counter} instances for {@link Gson}.
- *
- */
- @Deprecated
- public static class Serializer implements JsonSerializer {
- @Override
- public JsonElement serialize(final Counter src, final Type typeOfSrc,
- final JsonSerializationContext context) {
- final JsonObject container = new JsonObject();
- final JsonObject baseLabels = new JsonObject();
- baseLabels.addProperty(Reserved.NAME.label(), src.name);
-
- container.add(SERIALIZE_BASE_LABELS, baseLabels);
- container.addProperty(SERIALIZE_DOCSTRING, src.docstring);
-
- final JsonObject metric = new JsonObject();
- metric.addProperty("type", "counter");
- final JsonArray values = new JsonArray();
- for (final Map labelSet : src.children.keySet()) {
- final JsonObject element = new JsonObject();
- element.add("labels", context.serialize(labelSet));
- final Child vector = src.children.get(labelSet);
- element.add("value", context.serialize(vector.value.get()));
- values.add(element);
- }
- metric.add("value", values);
-
- container.add(SERIALIZE_METRIC, context.serialize(metric));
-
- return container;
- }
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (!(o instanceof Counter)) return false;
- if (!super.equals(o)) return false;
-
- final Counter counter = (Counter) o;
-
- if (Double.compare(counter.defaultValue, defaultValue) != 0) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = super.hashCode();
- long temp;
- temp = Double.doubleToLongBits(defaultValue);
- result = 31 * result + (int) (temp ^ (temp >>> 32));
- return result;
- }
-}
diff --git a/client/src/main/java/io/prometheus/client/metrics/Gauge.java b/client/src/main/java/io/prometheus/client/metrics/Gauge.java
deleted file mode 100644
index 4cd89643b..000000000
--- a/client/src/main/java/io/prometheus/client/metrics/Gauge.java
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Copyright 2013 Prometheus Team Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package io.prometheus.client.metrics;
-
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.AtomicDouble;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import io.prometheus.client.Metrics;
-import io.prometheus.client.utility.labels.Reserved;
-
-import javax.annotation.concurrent.NotThreadSafe;
-import javax.annotation.concurrent.ThreadSafe;
-import java.lang.reflect.Type;
-import java.util.List;
-import java.util.Map;
-
-/**
- *
- * {@link Gauge} is a {@link Metric} that reports instantaneous values based on
- * external state.
- *
- *
- *
- *
- * Instantaneous value: The amount of money currently in the room. The value
- * comes from a blackbox system that can only return the state result; it does
- * not return how the state was derived.
- *
- *
- *
- * An example follows:
- *
- *
- *
- * {@code
- * package example;
- *
- * import io.prometheus.client.Prometheus;
- * import io.prometheus.client.Register;
- * import io.prometheus.client.metrics.Gauge;
- *
- * public class Aquarium {
- * // Annotate this with "Register" if this class is not explicitly loaded
- * // by your project.
- * private static final Gauge waterTemp = Gauge.newBuilder()
- * .namespace("seaworld")
- * .inSubsystem("aquatic_tanks")
- * .name("water_temperature_c")
- * .labelNames("tank_name")
- * .documentation("The current aquarium tank temperature partitioned by tank name.")
- * .build()
- *
- * public void run() {
- * while (true) {
- * // Busy loop. :sad-trombone:
- * waterTemp.newPartial()
- * .labelPair("tank_name", "shamu")
- * .apply()
- * .set(getShamuTemperature());
- *
- * waterTemp.newPartial()
- * .labelPair("tank_name", "urchin")
- * .apply()
- * .set(getUrchinTemperature());
- * }
- * }
- *
- * private double getShamuTemperature() {
- * // That poor orca's boiling alive!
- * return 42;
- * }
- *
- * private double getUrchinTemperature() {
- * return 9;
- * }
- * }}
- *
- *
- *
- * Assuming that each code path is executed once, {@code waterTemp} yields the following
- * child metrics:
- *
- * Create a {@link Builder} to configure the {@link Gauge}.
- *
- */
- public static Builder newBuilder() {
- return new Builder();
- }
-
- /**
- *
- * Define the characteristics for this {@link Gauge}.
- *
- *
- * Implementation-Specific Behaviors:
- *
- *
- * If the metric and its children are reset, a default value of {@code 0} is
- * used.
- *
- *
- *
- * For all other behaviors, see {@link Metric.BaseBuilder}.
- *
- */
- @ThreadSafe
- public static class Builder implements Metric.Builder {
- private static final Double DEFAULT_VALUE = Double.valueOf(0);
-
- private final BaseBuilder base;
- private final Optional defaultValue;
-
- Builder() {
- base = new BaseBuilder();
- defaultValue = Optional.absent();
- }
-
- private Builder(final BaseBuilder base, final Optional defaultValue) {
- this.base = base;
- this.defaultValue = defaultValue;
- }
-
- @Override
- public Builder labelNames(String... ds) {
- return new Builder(base.labelNames(ds), defaultValue);
- }
-
- @Override
- public Builder documentation(String d) {
- return new Builder(base.documentation(d), defaultValue);
- }
-
- @Override
- public Builder name(String n) {
- return new Builder(base.name(n), defaultValue);
- }
-
- @Override
- public Builder subsystem(String ss) {
- return new Builder(base.subsystem(ss), defaultValue);
- }
-
- @Override
- public Builder namespace(String ns) {
- return new Builder(base.namespace(ns), defaultValue);
- }
-
- @Override
- public Builder registerStatic(final boolean rs) {
- return new Builder(base.registerStatic(rs), defaultValue);
- }
-
- /**
- *
- * Provide a custom default value for this {@link Gauge} when it undergoes a
- * {@link io.prometheus.client.metrics.Gauge#resetAll()} or a specific
- * {@link Child} undergoes a {@link Gauge.Child#reset()}.
- *
- * @return A copy of the original {@link Builder} with the new
- * target value.
- */
- public Builder defaultValue(final Double v) {
- return new Builder(base, Optional.of(v));
- }
-
- private double getDefaultValue() {
- return defaultValue.or(DEFAULT_VALUE);
- }
-
- @Override
- public Gauge build() {
- final String name = base.buildName();
- final String docstring = base.buildDocstring();
-
- final Metrics.MetricFamily.Builder builder =
- Metrics.MetricFamily.newBuilder().setName(name).setHelp(docstring)
- .setType(Metrics.MetricType.GAUGE);
-
- return new Gauge(base.buildName(), base.buildDocstring(), base.buildLabelNames(),
- getDefaultValue(), builder.build(), base.getRegisterStatic());
- }
- }
-
- /**
- *
- * A derivative of {@link Gauge} that lets you accumulate labels to build a
- * concrete metric via {@link #apply()} for mutation with the methods of
- * {@link Gauge.Child}.
- *
- *
- *
- * Warning: All mutations to {@link Partial} are retained. You should not
- * share {@link Partial} between distinct label sets unless you have a parent
- * {@link Partial} that you {@link io.prometheus.client.metrics.Gauge.Partial#clone()}.
- *
- *
- *
- * In this example below, we have both a race condition with a nasty outcome that
- * unformedMetric is mutated in both threads and that it is an undefined behavior, which
- * {@code data-type} label pair setting wins.
- *
- * A concrete instance of {@link Gauge} for a unique set of label dimensions.
- *
- *
- *
- * Warning: Do not hold onto a reference of a {@link Child} if you
- * ever use the {@link #resetAll()}. If you want to hold onto a concrete
- * instance, please hold onto a {@link io.prometheus.client.metrics.Gauge.Partial} and use
- * {@link io.prometheus.client.metrics.Gauge.Partial#apply()}.
- *
- *
- * @see Metric.Child
- */
- @ThreadSafe
- public class Child implements Metric.Child {
- final AtomicDouble value = new AtomicDouble();
-
- /**
- *
- * Set this {@link io.prometheus.client.metrics.Gauge.Child} to an arbitrary
- * value.
- *
- * Used to serialize {@link Gauge} instances for {@link com.google.gson.Gson}.
- *
- */
- @Deprecated
- public static class Serializer implements JsonSerializer {
- @Override
- public JsonElement serialize(final Gauge src, final Type typeOfSrc,
- final JsonSerializationContext context) {
- final JsonObject container = new JsonObject();
- final JsonObject baseLabels = new JsonObject();
- baseLabels.addProperty(Reserved.NAME.label(), src.name);
-
- container.add(SERIALIZE_BASE_LABELS, baseLabels);
- container.addProperty(SERIALIZE_DOCSTRING, src.docstring);
-
- final JsonObject metric = new JsonObject();
- metric.addProperty("type", "gauge");
- final JsonArray values = new JsonArray();
- for (final Map labelSet : src.children.keySet()) {
- final JsonObject element = new JsonObject();
- element.add("labels", context.serialize(labelSet));
- final Child vector = src.children.get(labelSet);
- element.add("value", context.serialize(vector.value.get()));
- values.add(element);
- }
- metric.add("value", values);
-
- container.add(SERIALIZE_METRIC, context.serialize(metric));
-
- return container;
- }
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (!(o instanceof Gauge)) return false;
- if (!super.equals(o)) return false;
-
- final Gauge gauge = (Gauge) o;
-
- if (Double.compare(gauge.defaultValue, defaultValue) != 0) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = super.hashCode();
- long temp;
- temp = Double.doubleToLongBits(defaultValue);
- result = 31 * result + (int) (temp ^ (temp >>> 32));
- return result;
- }
-}
diff --git a/client/src/main/java/io/prometheus/client/metrics/Metric.java b/client/src/main/java/io/prometheus/client/metrics/Metric.java
deleted file mode 100644
index 7760bcaa5..000000000
--- a/client/src/main/java/io/prometheus/client/metrics/Metric.java
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- * Copyright 2013 Prometheus Team Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package io.prometheus.client.metrics;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import io.prometheus.client.Metrics;
-import io.prometheus.client.Prometheus;
-import net.jcip.annotations.Immutable;
-import net.jcip.annotations.NotThreadSafe;
-import net.jcip.annotations.ThreadSafe;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- *
- * A {@link Metric} is the base type of all Prometheus metrics.
- *
- *
- *
- * Note: If you are using Prometheus, you do not need to be familiar with the internals of
- * this class.
- *
- *
- * @param The concrete implementation of {@link Metric}
- * @param The concrete implementation of {@link Metric.Child}
- * @param
- * Per decision
- * on the developer mailinglist, we have declared that no label names shall be allowed that
- * are prefixed with "__" are to be allowed, since they are used internally for private indices.
- *
- */
- private static final String PRIVATE_LABEL_NAMESPACE = "__";
-
- static final String SERIALIZE_BASE_LABELS = "baseLabels";
- static final String SERIALIZE_DOCSTRING = "docstring";
- static final String SERIALIZE_METRIC = "metric";
-
- private final List labelNames;
- private final Metrics.MetricFamily partial;
-
- final String name;
- final String docstring;
- final ConcurrentHashMap
- *
- * @return A copy of the original {@link Builder} with the new
- * target value.
- */
- public B namespace(String namespace);
-
- /**
- *
- * Associate this metric with a subsystem.
- *
- *
- *
- * A subsystem is a collection of systems that perform related units of work
- * that might have multiple aspects against which they are measured.
- *
- *
- *
- * For example, you have provided {@link Metric}'s
- * {@link Metric.BaseBuilder} with the following parameters:
- *
- *
- *
- * {@code namespace = "seaworld"}
- *
- * {@code subsystem = "water_heaters"}
- *
- * {@code name = "efficiency_percentage"}
- *
- *
- * The {@link Metric}'s naming system generates the following composite
- * metric name: {@code seaworld_water_heaters_efficiency_percentage} . The
- * subsystem is water_heaters.
- *
- *
- * @return A copy of the original {@link Builder} with the new
- * target value.
- */
- public B subsystem(String subsystem);
-
- /**
- *
- * Required: Assign this metric a name.
- *
- *
- *
- * A name is a distinct component that is measured, such as temperature.
- *
- *
- *
- * For example, you have provided {@link Metric}'s
- * {@link Metric.BaseBuilder} with the following parameters:
- *
- *
- *
- * {@code namespace = "seaworld"}
- *
- * {@code subsystem = "water_heaters"}
- *
- * {@code name = "efficiency_percentage"}
- *
- *
- * The {@link Metric}'s naming system generates the following composite
- * metric name: {@code seaworld_water_heaters_efficiency_percentage} . The
- * name is efficiency_percentage.
- *
- *
- * @return A copy of the original {@link Builder} with the new
- * target value.
- */
- public B name(String name);
-
- /**
- *
- * Required: Assign a human-readable documentation string to this
- * metric.
- *
- *
- * @return A copy of the original {@link Builder} with the new
- * target value.
- */
- public B documentation(String documentation);
-
- /**
- *
- * Declare this metric's label names.
- *
- *
- *
- * A label is used as a facet for aggregation or pivoting in data. If you
- * were a census technician building a system to show the current number of
- * people in a given postal code at a given time, you could create a label
- * called {@code "postal_code"}.
- *
- *
- *
- * Important: Children of this metric must be instantiated with all
- * of the declared labels. Failure to do so will result in a runtime error
- * due to a programming error.
- *
- *
- * @return A copy of the original {@link Builder} with the new
- * target value.
- */
- public B labelNames(String... labelNames);
-
- /**
- *
- * Instructs Prometheus to register this metric upon its creation.
- *
- *
- *
- * Important: This defaults to true. If more than one metric of the
- * same (full name, docstring) is registered, the first one wins.
- *
- *
- *
- * The following are use cases for setting this to {@code true}:
- *
- *
- * Runtimes where runtime-retained annotations neither respected
- * nor supported, meaning {@link io.prometheus.client.Register} cannot
- * be used and you wish to not explicitly register the metrics yourself.
- *
- *
- *
- * The following are use cases for setting this to {@code false}:
- *
- *
- * Preventing static side-effects from tests.
- *
- * Respecting dependency injection paradigms. Be sure to explicitly use
- * {@link Prometheus#defaultRegister(Metric)}.
- *
- *
- *
- * @return A copy of the original {@link Builder} with the new
- * target value.
- */
- public B registerStatic(boolean registerStatic);
-
- /**
- *
- * Generate a concrete {@link M} from this {@link Builder}.
- *
- */
- M build();
- }
-
- static class BaseBuilder {
- private final boolean DEFAULT_REGISTER_STATIC = true;
-
- protected final Optional namespace;
- protected final Optional subsystem;
- protected final Optional name;
- protected final Optional d;
- protected final Optional registerStatic;
- protected final List labelNames;
-
- BaseBuilder() {
- namespace = Optional.absent();
- subsystem = Optional.absent();
- name = Optional.absent();
- d = Optional.absent();
- registerStatic = Optional.absent();
- labelNames = new ArrayList();
- }
-
- private BaseBuilder(final Optional namespace, final Optional subsystem,
- final Optional name, final Optional d,
- final Optional registerStatic, final List labelNames) {
- this.namespace = namespace;
- this.subsystem = subsystem;
- this.name = name;
- this.d = d;
- this.registerStatic = registerStatic;
- this.labelNames = labelNames;
- }
-
- BaseBuilder namespace(final String ns) {
- return new BaseBuilder(Optional.of(ns), subsystem, name, d, registerStatic, labelNames);
- }
-
- BaseBuilder subsystem(final String ss) {
- return new BaseBuilder(namespace, Optional.of(ss), name, d, registerStatic, labelNames);
- }
-
- BaseBuilder name(final String n) {
- return new BaseBuilder(namespace, subsystem, Optional.of(n), d, registerStatic, labelNames);
- }
-
- BaseBuilder documentation(final String d) {
- return new BaseBuilder(namespace, subsystem, name, Optional.of(d), registerStatic, labelNames);
- }
-
- BaseBuilder labelNames(final String... ds) {
- final List labels = new ArrayList(labelNames);
- labels.addAll(Arrays.asList(ds));
-
- return new BaseBuilder(namespace, subsystem, name, d, registerStatic, labels);
- }
-
- BaseBuilder registerStatic(final boolean rs) {
- return new BaseBuilder(namespace, subsystem, name, d, Optional.of(rs), labelNames);
- }
-
- boolean getRegisterStatic() {
- return registerStatic.or(DEFAULT_REGISTER_STATIC);
- }
-
- String buildName() {
- Preconditions.checkArgument(name.isPresent(), "name may not be empty");
-
- if (!(namespace.isPresent() || subsystem.isPresent())) {
- return name.get();
- } else if (namespace.isPresent() && subsystem.isPresent()) {
- return String.format("%s_%s_%s", namespace.get(), subsystem.get(), name.get());
- }
-
- if (namespace.isPresent()) {
- return String.format("%s_%s", namespace.get(), name.get());
- }
-
- return String.format("%s_%s", subsystem.get(), name.get());
- }
-
- String buildDocstring() {
- Preconditions.checkArgument(d.isPresent(), "docstring may not be empty");
-
- return d.get();
- }
-
- List buildLabelNames() {
- final String metricName = name.or("");
-
- for (final String labelName : labelNames) {
- if (labelName.isEmpty()) {
- throw IllegalLabelDeclarationException.empty(metricName);
- }
- if (labelName.startsWith(PRIVATE_LABEL_NAMESPACE)) {
- throw IllegalLabelDeclarationException.reserved(labelName, metricName);
- }
- }
-
- return labelNames;
- }
- }
-
- /**
- *
- * Create a new {@link P}.
- *
- *
- * @see Metric.Partial
- */
- public abstract P newPartial();
-
- /**
- *
- * {@link Partial} is an incomplete incarnation of a
- * {@link Metric.Child} that you add label value pair to with
- * {@link #labelPair(String, String)}. They are used to provide measurements
- * in a trace-like fashion where the outcomes are not known a priori, and the
- * outcomes affect what label pairs the metric shall have.
- *
- *
- *
- * An example follows:
- *
- *
- *
- *
- * public class InvitationHandler {
- * public static Summary latencies =
- * Summary
- * .newBuilder()
- * .name("request_latency_ms")
- * // There are three distinct labelNames we care about:
- * // - operation: What type of operation are we handling?
- * // - result: What was its outcome?
- * // - shard: What remote storage shard was used in answering this
- * // request?
- * .labelNames("operation", "result", "shard")
- * .documentation(
- * "Latency quantiles for requests partitioned by 'operation' type, 'result' disposition, and storage 'shard' name.")
- * .build();
- *
- * public void handleCreate(CreateReq r) {
- * Summary.Partial op = latencies.newPartial().labelPair("operation", "create");
- * long start = System.currentTimeMillis();
- *
- * try {
- * doCreate(shard, r);
- * op.labelPair("result", "success");
- * } catch (StorageException e) {
- * op.labelPair("result", "storage_failure");
- * } catch (RuntimeException e) {
- * op.labelPair("result", "unknown_error");
- * } finally {
- * op.apply().observe(System.currentTimeMillis() - start);
- * }
- * }
- *
- * private void doCreate(CreateReq r, Summary.Partial t) throws StorageException {
- * String shard = shardMap.getForReq(r);
- * op.labelNames("shard", shard);
- * // Do our work: Create the entity in the remote shard.
- * }
- *
- * public void handleDelete(DeleteReq r) {
- * Summary.Partial op = latencies.newPartial().labelNames("operation", "delete");
- * long start = System.currentTimeMillis();
- *
- * try {
- * doDelete(shard, r);
- * op.labelName("result", "success");
- * } catch (StorageException e) {
- * op.labelNames("result", "storage_failure");
- * } catch (RuntimeException e) {
- * op.labelNames("result", "unknown_error");
- * } finally {
- * op.apply().observe(System.currentTimeMillis() - start);
- * }
- * }
- *
- * private void doDelete(deleteReq r, Summary.Partial t) throws StorageException {
- * String shard = shardMap.getForReq(r);
- * op.labelNames("shard", shard);
- * // Do our work: delete the entity in the remote shard.
- * }
- *
- * public static class CreateReq {}
- *
- * public static class DeleteReq {}
- * }
- *
- *
- *
- *
- * Assuming each code path is hit twice, {@code latencies} could yield the
- * following child metrics:
- *
- * If there is a mismatch between the number of labels that have been
- * accumulated with {@link #labelPair(String, String)} and those defined in
- * the underlying {@code Builder#labelNames}, a runtime exception will
- * occur, signifying illegal use.
- *
- *
- */
- @NotThreadSafe
- public abstract class Partial {
- private final Map dimensions = new HashMap();
-
- protected Partial() {}
-
- /**
- *
- * Attach label-value pairs to this {@link Partial}.
- *
- */
- public abstract P labelPair(final String labelName, final String labelValue);
-
- P baseLabelPair(final String labelName, final String labelValue) {
- dimensions.put(labelName, labelValue);
-
- return (P) this;
- }
-
- /**
- *
- * Duplicate an existing {@link Partial} to create another metric
- * altogether.
- *
- */
- public P clone() {
- final P clone = newPartial();
- for (final String name : dimensions.keySet()) {
- final String value = dimensions.get(name);
- clone.labelPair(name, value);
- }
-
- return clone;
- }
-
- private Map validate() {
- final Map ds = Collections.unmodifiableMap(dimensions);
- final HashSet claimed = new HashSet();
-
- for (final String k : ds.keySet()) {
- Preconditions.checkState(ds.containsKey(k),
- String.format("%s label dimension does not exist", k));
-
- Preconditions.checkState(!claimed.contains(k),
- String.format("%s label dimension is already used", k));
- claimed.add(k);
- }
-
- return ds;
- }
-
- protected abstract C newChild();
-
- /**
- *
- * Instantiates a concrete metric of {@link C} with the attached label-value
- * pairs.
- *
- */
- public abstract C apply();
-
- C baseApply() {
- final TreeMap t = new TreeMap(validate());
- C child = children.get(t);
- if(child == null) {
- child = newChild();
- children.put(t, child);
- }
- return child;
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- try {
- final Partial partial = (Partial) o;
-
- if (!dimensions.equals(partial.dimensions)) return false;
-
- return true;
-
- } catch (final ClassCastException unused) {
- return false;
- }
- }
-
- @Override
- public int hashCode() {
- return dimensions.hashCode();
- }
- }
- /**
- *
- * {@link Child} is a concrete metric, the thing you mutate.
- *
- *
- *
- * Warning: Do not hold onto a reference of a {@link Child} if you
- * ever use the {@link #resetAll()}.
- *
- */
- public static interface Child {
- void reset();
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (!(o instanceof Metric)) return false;
-
- final Metric metric = (Metric) o;
-
- if (!labelNames.equals(metric.labelNames)) return false;
- if (!docstring.equals(metric.docstring)) return false;
- if (!name.equals(metric.name)) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = labelNames.hashCode();
- result = 31 * result + name.hashCode();
- result = 31 * result + docstring.hashCode();
- return result;
- }
-
- @Override
- public String toString() {
- return String.format("Metric{name='%s', labelNames=%s}", name, labelNames);
- }
-
- /**
- *
- * {@link io.prometheus.client.metrics.Metric.IllegalLabelDeclarationException} is used in cases
- * whereby the author of a metric declares an illegal label name.
- *
- */
- public static class IllegalLabelDeclarationException extends IllegalArgumentException {
- private IllegalLabelDeclarationException(final String msg) {
- super(msg);
- }
-
- static IllegalLabelDeclarationException reserved(final String labelName,
- final String metricName) {
- return new IllegalLabelDeclarationException(
- String.format("metric %s's label of %s begins with reserved prefix %s", metricName,
- labelName, PRIVATE_LABEL_NAMESPACE));
- }
-
- static IllegalLabelDeclarationException empty(final String metricName) {
- return new IllegalLabelDeclarationException(
- String.format("metric %s has an empty label name", metricName));
- }
- }
-}
diff --git a/client/src/main/java/io/prometheus/client/metrics/Summary.java b/client/src/main/java/io/prometheus/client/metrics/Summary.java
deleted file mode 100644
index 39f17b156..000000000
--- a/client/src/main/java/io/prometheus/client/metrics/Summary.java
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * Copyright 2013 Prometheus Team Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package io.prometheus.client.metrics;
-
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.NotThreadSafe;
-import javax.annotation.concurrent.ThreadSafe;
-
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.AtomicDouble;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import com.matttproud.quantile.Estimator;
-import com.matttproud.quantile.Quantile;
-
-import io.prometheus.client.Metrics;
-import io.prometheus.client.utility.labels.Reserved;
-import net.jcip.annotations.Immutable;
-
-/**
- *
- * {@link Summary} is a {@link Metric} that samples events over sliding windows
- * of time.
- *
- *
- *
- * Distributions: The spread and depth of observed samples, including quantile
- * ranks.
- *
- *
- *
- *
- * An example follows:
- *
- *
- *
- * {@code
- * package example;
- *
- * import io.prometheus.client.Prometheus;
- * import io.prometheus.client.Register;
- * import io.prometheus.client.metrics.Counter;
- *
- * public class BirdWatcher {
- * // Annotate this with "Register" if this class is not explicitly loaded
- * // by your project.
- * private static final Summary observations = Summary.newBuilder()
- * .namespace("birds")
- * .name("weights")
- * .labelNames("genus")
- * .documentation("Weights of birds partitioned by genus.")
- * .targetQuantile(0.5, 0.05) // Gimme median!
- * .targetQuantile(0.99, 0.001) // Gimme 99th!
- * .build()
- *
- * public float visitForest() {
- * while (true) {
- * // Busy loop. :eat berries, watch birds, and try not to poison yourself:
- * observations.newPartial()
- * .labelPair("genus", "garrulus") // Got a Eurasian Jay.
- * .apply()
- * .observe(175);
- *
- * observations.newPartial()
- * .labelPair("genus", "corvus") // Got a Hooded Crow.
- * .apply()
- * .observe(500);
- * }
- * }
- * }}
- *
- *
- *
- * Assuming that each code path is executed twice, {@code observations} yields the
- * following child metrics:
- *
- *
- * @author Matt T. Proud (matt.proud@gmail.com)
- */
-@ThreadSafe
-public class Summary extends Metric {
- private final long purgeIntervalMs;
- private final long resetIntervalMs;
- private final Map targets;
-
- @GuardedBy("lastPurgeInstantMs") Long lastPurgeInstantMs;
- @GuardedBy("lastResetInstantMs") Long lastResetInstantMs;
-
- private Summary(final String n, final String d, final List ds, final long pi,
- final Map t, final Metrics.MetricFamily p, final boolean rs, final long ri) {
- super(n, d, ds, p, rs);
-
- purgeIntervalMs = pi;
- resetIntervalMs = ri;
-
- targets = t;
-
- lastPurgeInstantMs = System.currentTimeMillis();
- lastResetInstantMs = lastPurgeInstantMs;
- }
-
- void purge() {
- if (purgeIntervalMs == 0) {
- return;
- }
-
- synchronized (lastPurgeInstantMs) {
- final long now = System.currentTimeMillis();
- if (now - lastPurgeInstantMs < purgeIntervalMs) {
- return;
- }
-
- for (final Child c : children.values()) {
- c.reset();
- }
-
- children.clear();
-
- lastPurgeInstantMs = now;
- }
- }
-
- void reset() {
- if (resetIntervalMs == 0) {
- return;
- }
-
- synchronized (lastResetInstantMs) {
- final long now = System.currentTimeMillis();
- if (now - lastResetInstantMs < resetIntervalMs) {
- return;
- }
-
- for (final Child c : children.values()) {
- c.reset();
- }
-
- lastResetInstantMs = now;
- }
- }
-
- @Override
- Metrics.MetricFamily.Builder annotateBuilder(final Metrics.MetricFamily.Builder b) {
- try {
- // TODO(matt): This metric is a prime candidate for extractions.
- // TODO(matt): This could probably use a purge lock.
-
- for (final Map labels : children.keySet()) {
- final Child child = children.get(labels);
- final Metrics.Summary.Builder builder = Metrics.Summary.newBuilder();
-
- if (!child.isEmpty()) {
- // These are the cases whereby a Summary metric's child may be empty:
- // 1. A user has invoked #resetAll on the Summary
- // - The Summary was automatically flushed on a given interval to prevent retention
- // of outliers via Summary.Builder#purgeInterval.
- // - Business logic of the application dictates that all metrics dimensions
- // associated with this name need to be reset.
- // 2. A user has invoked #reset on the single Metric.Child
- // - Business logic of the application dictates that the individual metric needs to
- // be deleted or reset.
-
- for (final double q : child.targets.keySet()) {
- final Double v = child.query(q);
- if (v == null) {
- // This condition should never occur, but we want to be safe.
- continue;
- }
-
- final Metrics.Quantile.Builder qs = builder.addQuantileBuilder();
-
- qs.setQuantile(q);
- qs.setValue(v);
- }
- }
-
- builder.setSampleCount(child.count.get());
- builder.setSampleSum(child.sum.get());
-
- final Metrics.Metric.Builder m = b.addMetricBuilder();
-
- for (final String label : labels.keySet()) {
- final String value = labels.get(label);
- m.addLabelBuilder().setName(label).setValue(value);
- }
-
- m.setSummary(builder);
- }
-
- return b;
- } finally {
- reset();
- purge();
- }
- }
-
- /**
- *
- * Start generating a concrete {@link Child} instance by building a partial
- * and accumulating labels with it.
- *
- *
- * @see io.prometheus.client.metrics.Metric#newPartial()
- */
- @Override
- public Partial newPartial() {
- return new Partial();
- }
-
- public static Builder newBuilder() {
- return new Builder();
- }
-
- @ThreadSafe
- @Immutable
- public static class Builder implements Metric.Builder {
- private static final Long DEFAULT_PURGE_INTERVAL = TimeUnit.MINUTES.toMillis(0);
- private static final Long DEFAULT_RESET_INTERVAL = TimeUnit.MINUTES.toMillis(15);
- private static final ImmutableMap DEFAULT_TARGETS = ImmutableMap.of(0.5, 0.05,
- 0.90, 0.01, 0.99, 0.001);
-
- private final BaseBuilder base;
- private final Map targets;
- private final Optional purgeIntervalMs;
- private final Optional resetIntervalMs;
-
- Builder() {
- base = new BaseBuilder();
- targets = new HashMap();
- purgeIntervalMs = Optional.absent();
- resetIntervalMs = Optional.absent();
- }
-
- private Builder(BaseBuilder base, Map targets, Optional purgeIntervalMs,
- Optional resetIntervalMs) {
- this.base = base;
- this.targets = targets;
- this.purgeIntervalMs = purgeIntervalMs;
- this.resetIntervalMs = resetIntervalMs;
- }
-
- @Override
- public Builder labelNames(String... ds) {
- return new Builder(base.labelNames(ds), targets, purgeIntervalMs, resetIntervalMs);
- }
-
- @Override
- public Builder documentation(String d) {
- return new Builder(base.documentation(d), targets, purgeIntervalMs, resetIntervalMs);
- }
-
- @Override
- public Builder name(String n) {
- return new Builder(base.name(n), targets, purgeIntervalMs, resetIntervalMs);
- }
-
- @Override
- public Builder subsystem(String ss) {
- return new Builder(base.subsystem(ss), targets, purgeIntervalMs, resetIntervalMs);
- }
-
- @Override
- public Builder namespace(String ns) {
- return new Builder(base.namespace(ns), targets, purgeIntervalMs, resetIntervalMs);
- }
-
- @Override
- public Builder registerStatic(final boolean rs) {
- return new Builder(base.registerStatic(rs), targets, purgeIntervalMs, resetIntervalMs);
- }
-
- /**
- *
- * Set the frequency at which the {@link Summary}'s reported quantiles,
- * observation count, and observation sum are reset. This is useful to
- * prevent staleness.
- *
- *
- * @return A copy of the original {@link Builder} with the new
- * target value.
- */
- public Builder resetInterval(final int n, final TimeUnit u) {
- return new Builder(base, targets, purgeIntervalMs, Optional.of(u.toMillis(n)));
- }
-
- /**
- *
- * Set the frequency at which the {@link Summary}'s children are evicted
- * to prevent staleness.
- *
- *
- * @return A copy of the original {@link Builder} with the new
- * target value.
- */
- public Builder purgeInterval(final int n, final TimeUnit u) {
- return new Builder(base, targets, Optional.of(u.toMillis(n)), resetIntervalMs);
- }
-
- /**
- *
- * Important: You may repeat calls to
- * {@link #targetQuantile(Double, Double)} to request additional values in
- * exposition!
- *
- *
- * @param quantile The target quantile expressed over the
- * [0, 1] interval.
- * @param inaccuracy The inaccuracy allowance expressed over the
- * [0, 1] interval.
- * @return A copy of the original {@link Builder} with the new
- * target value.
- */
- public Builder targetQuantile(final Double quantile, final Double inaccuracy) {
- final Map quantiles = new HashMap(targets);
- quantiles.put(quantile, inaccuracy);
- return new Builder(base, quantiles, purgeIntervalMs, resetIntervalMs);
- }
-
-
- private long getPurgeIntervalMs() {
- return purgeIntervalMs.or(DEFAULT_PURGE_INTERVAL);
- }
-
- private long getResetIntervalMs() {
- return purgeIntervalMs.or(DEFAULT_RESET_INTERVAL);
- }
-
- private Map getTargets() {
- if (targets.size() == 0) {
- return DEFAULT_TARGETS;
- }
-
- return targets;
- }
-
- public Summary build() {
- final String name = base.buildName();
- final String docstring = base.buildDocstring();
-
- final Metrics.MetricFamily.Builder builder =
- Metrics.MetricFamily.newBuilder().setName(name).setHelp(docstring)
- .setType(Metrics.MetricType.SUMMARY);
-
- return new Summary(base.buildName(), base.buildDocstring(), base.buildLabelNames(),
- getPurgeIntervalMs(), getTargets(), builder.build(), base.getRegisterStatic(), getResetIntervalMs());
- }
- }
-
- /**
- *
- * A derivative of {@link Summary} that lets you accumulate labels to build a
- * concrete metric via {@link #apply()} for mutation with the methods of
- * {@link Summary.Child}.
- *
- *
- *
- * Warning: All mutations to {@link Partial} are retained. You should not
- * share {@link Partial} between distinct label sets unless you have a parent
- * {@link Partial} that you {@link io.prometheus.client.metrics.Summary.Partial#clone()}.
- *
- *
- *
- * In this example below, we have both a race condition with a nasty outcome that
- * unformedMetric is mutated in both threads and that it is an undefined behavior, which
- * {@code data-type} label pair setting wins.
- *
- * A concrete instance of {@link Summary} for a unique set of label
- * dimensions.
- *
- *
- *
- * Warning: Do not hold onto a reference of a {@link Child} if you
- * ever use the {@link #resetAll()}. If you want to hold onto a concrete
- * instance, please hold onto a {@link io.prometheus.client.metrics.Summary.Partial} and use
- * {@link io.prometheus.client.metrics.Summary.Partial#apply()}.
- *
- */
- @ThreadSafe
- public class Child implements Metric.Child {
- // How large of a buffer to use for internally queued sample observations before passing them
- // to the Estimator. This value is found by performing microbenchmarks against the cross of
- // the following cases
- //
- // - thread count [1, 16]
- // - iteration count [1024, 131072]
- //
- // with a worker threads that #observe a constant value repeatedly in iteration to test
- // overhead of concurrency control. To further minimize noise in the data, the VM was allowed
- // to warm up with three prior runs of the same case in the same process to enable the VM to
- // settle on whatever optimizations it so chooses (running in -server mode for most accurate
- // readout).
- //
- // The value below was reached when performing a binary search of the crosses above against an
- // interval of [128, 8192]. After 2048, diminishing returns were observed. Further costs of
- // memory allocation seem unwarranted. That said, the buffer allocations are single-time and
- // never resize throughout the life of the program once they reach capacity.
- //
- // At a standard metric request interval, which invokes #query, buffers should be compacted
- // rather frequently and probably will rarely reach saturation on their own.
- private static final int BUFFER_SIZE = 2048;
-
- private final AtomicDouble sum = new AtomicDouble();
- private final AtomicLong count = new AtomicLong();
- private final Map targets;
- // Use a low latency buffer to receive incoming sample values. This is done because
- // Estimator is not thread safe and requires coarse locking around it.
- private final ArrayBlockingQueue obsQueue = new ArrayBlockingQueue(BUFFER_SIZE);
- // Upon obsQueue saturation, values are immediately emptied into this pre-allocated buffer to
- // be passed onto the Estimator, which may at its convenience either accept the values as-is
- // for later computation or accept them and precompute the requested quantile values. This
- // latter operation, while fast, should not force sample value producers to block until this
- // operation has been performed.
- private final ArrayList dequeued = new ArrayList(BUFFER_SIZE);
-
- private Estimator estimator;
-
- Child(final Map targets) {
- this.targets = targets;
-
- final Quantile quantiles[] = new Quantile[targets.size()];
- int i = 0;
- for (final Double t : targets.keySet()) {
- final Double a = targets.get(t);
-
- quantiles[i] = new Quantile(t, a);
- i++;
- }
-
- // Default upstream buffer value pinned for predictability.
- estimator = new Estimator(4096, quantiles);
- }
-
- public void observe(final Double v) {
- try {
- if (obsQueue.offer(v)) {
- return;
- }
-
- synchronized (this) {
- if (obsQueue.offer(v)) {
- // Offer the ability to accept the value after potentially waiting without having to
- // force a premature compaction since this current thread may have been blocked with
- // others.
- return;
- }
-
- // Otherwise, this unlucky thread will force a compaction and then accept the value,
- // thereby liberating any waiting parties.
- compact();
- estimator.insert(v);
- }
- } finally {
- sum.getAndAdd(v);
- count.getAndIncrement();
- }
- }
-
- private void compact() {
- obsQueue.drainTo(dequeued);
- estimator.insert(dequeued);
- dequeued.clear();
- }
-
- @Override
- synchronized public void reset() {
- final Quantile quantiles[] = new Quantile[targets.size()];
- int i = 0;
- for (final Double t : targets.keySet()) {
- final Double a = targets.get(t);
-
- quantiles[i] = new Quantile(t, a);
- i++;
- }
-
- estimator = new Estimator(quantiles);
-
- obsQueue.clear();
- dequeued.clear();
- }
-
- synchronized Double query(final Double q) {
- compact(); // Ensure any remaining observations are rendered available.
- return estimator.query(q);
- }
-
- boolean isEmpty() {
- return count.get() == 0;
- }
- }
-
- /**
- *
- * Used to serialize {@link Summary} instances for {@link com.google.gson.Gson}.
- *
- */
- @Deprecated
- public static class Serializer implements JsonSerializer {
- @Override
- public JsonElement serialize(final Summary src, final Type typeOfSrc,
- final JsonSerializationContext context) {
- final JsonObject container = new JsonObject();
- final JsonObject baseLabels = new JsonObject();
- baseLabels.addProperty(Reserved.NAME.label(), src.name);
-
- container.add(SERIALIZE_BASE_LABELS, baseLabels);
- container.addProperty(SERIALIZE_DOCSTRING, src.docstring);
-
- final JsonObject metric = new JsonObject();
- metric.addProperty("type", "histogram");
- final JsonArray values = new JsonArray();
- for (final Map labelSet : src.children.keySet()) {
- final JsonObject element = new JsonObject();
- element.add("labels", context.serialize(labelSet));
- final Child vector = src.children.get(labelSet);
-
- final JsonObject quantiles = new JsonObject();
- for (final Double q : vector.targets.keySet()) {
- final double v = vector.query(q);
- quantiles.addProperty(q.toString(), v);
- }
-
- element.add("value", quantiles);
- values.add(element);
- }
- metric.add("value", values);
-
- container.add(SERIALIZE_METRIC, context.serialize(metric));
-
- return container;
- }
- }
-}
diff --git a/client/src/main/java/io/prometheus/client/utility/Clock.java b/client/src/main/java/io/prometheus/client/utility/Clock.java
deleted file mode 100644
index 993db29e3..000000000
--- a/client/src/main/java/io/prometheus/client/utility/Clock.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2013 Prometheus Team Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package io.prometheus.client.utility;
-
-/**
- *
- * A testable wrapper for getting the current time in milliseconds from the
- * epoch.
- *
- *
- * @author matt.proud@gmail.com (Matt T. Proud)
- */
-public interface Clock {
- public long nowMs();
-}
diff --git a/client/src/main/java/io/prometheus/client/utility/SystemClock.java b/client/src/main/java/io/prometheus/client/utility/SystemClock.java
deleted file mode 100644
index 6d8907699..000000000
--- a/client/src/main/java/io/prometheus/client/utility/SystemClock.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2013 Prometheus Team Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package io.prometheus.client.utility;
-
-/**
- *
- * A {@link Clock} that proxies the system's clock.
- *
- *
- * @see Clock
- * @author matt.proud@gmail.com (Matt T. Proud)
- */
-public class SystemClock implements Clock {
- @Override
- public long nowMs() {
- return System.currentTimeMillis();
- }
-}
diff --git a/client/src/main/java/io/prometheus/client/utility/labels/Outcome.java b/client/src/main/java/io/prometheus/client/utility/labels/Outcome.java
deleted file mode 100644
index 93d7e0172..000000000
--- a/client/src/main/java/io/prometheus/client/utility/labels/Outcome.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2013 Prometheus Team Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package io.prometheus.client.utility.labels;
-
-/**
- *
- * Some prefabricated and optional labels for working with
- * outcome-oriented operations.
- *
- *
- * @author matt.proud@gmail.com (Matt T. Proud)
- */
-public enum Outcome {
- RESULT("result"), SUCCESS("success"), FAILURE("failure");
-
- private final String name;
-
- private Outcome(final String name) {
- this.name = name;
- }
-
- public String label() {
- return name;
- }
-}
diff --git a/client/src/main/java/io/prometheus/client/utility/labels/Reserved.java b/client/src/main/java/io/prometheus/client/utility/labels/Reserved.java
deleted file mode 100644
index 8738a5f78..000000000
--- a/client/src/main/java/io/prometheus/client/utility/labels/Reserved.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2013 Prometheus Team Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package io.prometheus.client.utility.labels;
-
-/**
- *
- * A collection of various reserved label names.
- *
- * {@code name} is a reserved label name key in Prometheus used to indicate
- * the name of the {@link io.prometheus.client.metrics.Metric}.
- *
- */
- NAME("__name__");
-
- private final String name;
-
- private Reserved(final String name) {
- this.name = name;
- }
-
- public String label() {
- return name;
- }
-}
diff --git a/client/src/test/java/io/prometheus/client/metrics/CounterTest.java b/client/src/test/java/io/prometheus/client/metrics/CounterTest.java
deleted file mode 100644
index a8e1c610c..000000000
--- a/client/src/test/java/io/prometheus/client/metrics/CounterTest.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright 2013 Prometheus Team Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package io.prometheus.client.metrics;
-
-import io.prometheus.client.Metrics;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.List;
-
-/**
- *
- * Tests for {@link Counter}.
- *
- */
-public class CounterTest {
- @Test
- public void workflow() {
- Counter.Builder oldBuilder = null;
- Counter.Builder builder = Counter.newBuilder().registerStatic(false);
- Assert.assertNotNull(builder);
-
- oldBuilder = builder;
- builder = builder.namespace("my_namespace");
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
- oldBuilder = builder;
- builder = builder.subsystem("my_subsystem");
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
- oldBuilder = builder;
- builder = builder.name("my_counter");
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
- oldBuilder = builder;
- builder = builder.documentation("my_documentation");
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
- oldBuilder = builder;
- builder = builder.defaultValue(13D);
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
- oldBuilder = builder;
- builder = builder.labelNames("my_label");
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
-
- final Counter Counter = builder.build();
- Assert.assertNotNull(Counter);
-
- Assert.assertEquals("my_documentation", Counter.docstring);
- Assert.assertEquals("my_namespace_my_subsystem_my_counter", Counter.name);
-
- Assert.assertEquals("new metric has no children", 0, Counter.children.size());
-
- final Counter.Partial partial = Counter.newPartial();
- Assert.assertNotNull(partial);
-
- Assert.assertEquals("identical for state transference", partial,
- partial.labelPair("my_label", "my_label_value"));
-
- final Counter.Child child = partial.apply();
- Assert.assertNotNull(child);
-
- child.set(42D);
- Assert.assertEquals("child value is set", 42D, child.value.get(), 0.001);
-
- Assert.assertEquals("only one instantiated child", 1, Counter.children.size());
-
- final Counter.Child newChild = partial.apply();
- Assert.assertEquals("partial's identical label signatures should yield the same child", child,
- newChild);
-
- newChild.increment();
- Assert.assertEquals("original instantiated child incremented", 43, child.value.get(), 0.001);
- newChild.increment(5);
- Assert.assertEquals("original instantiated child incremented by five", 48, child.value.get(),
- 0.001);
-
- Assert.assertEquals("only one child after mutations", 1, Counter.children.size());
-
- final Metrics.MetricFamily metricFamily = Counter.dump();
- Assert.assertNotNull("emitted protocol buffer", metricFamily);
-
- Assert.assertEquals("correct metric type", Metrics.MetricType.COUNTER, metricFamily.getType());
- Assert.assertEquals("passed on docstring", "my_documentation", metricFamily.getHelp());
- Assert.assertEquals("passed on name", "my_namespace_my_subsystem_my_counter",
- metricFamily.getName());
-
- final List metrics = metricFamily.getMetricList();
- Assert.assertEquals("only one metric child", 1, metrics.size());
-
- final Metrics.Metric metric = metrics.get(0);
- Assert.assertNotNull(metric);
-
- final List labels = metric.getLabelList();
- Assert.assertEquals("only one label pair", 1, labels.size());
-
- final Metrics.LabelPair labelPair = labels.get(0);
- Assert.assertEquals("correct label", "my_label", labelPair.getName());
- Assert.assertEquals("correct value", "my_label_value", labelPair.getValue());
-
- final Metrics.Counter nestedCounter = metric.getCounter();
- Assert.assertNotNull("set nested type", nestedCounter);
-
- Assert.assertEquals("transferred last value", 48, nestedCounter.getValue(), 0.001);
-
- Counter.resetAll();
-
- Assert.assertEquals("same children no. after reset", 1, Counter.children.size());
- Assert.assertEquals("got default val. after reset", 13, child.value.get(), 0.001);
- }
-
- @Test
- public void clonePartialSingle() {
- Counter counter = Counter.newBuilder()
- .name("some-name")
- .documentation("some-documentation")
- .labelNames("a-dimension")
- .registerStatic(false)
- .build();
-
- Counter.Partial partial = counter.newPartial();
- partial.labelPair("a-dimension", "preset-value");
- Counter.Partial derivative = partial.clone();
- Assert.assertNotSame("should return a new object", partial, derivative);
- Assert.assertSame(partial.apply(), derivative.apply());
- partial.apply().increment();
- derivative.apply().increment();
-
- Metrics.MetricFamily dump = counter.dump();
- Assert.assertEquals("just one metric", 1, dump.getMetricCount());
- }
-
- @Test
- public void clonePartialDouble() {
- Counter counter = Counter.newBuilder()
- .name("some-name")
- .documentation("some-documentation")
- .labelNames("a-dimension", "another-dimension")
- .registerStatic(false)
- .build();
-
- Counter.Partial partial = counter.newPartial();
- partial.labelPair("a-dimension", "preset-value");
- Counter.Partial derivative = partial.clone();
- Assert.assertNotSame("two different partials", partial, derivative);
- partial.labelPair("another-dimension", "first");
- partial.apply().increment();
- derivative.labelPair("another-dimension", "second");
- derivative.apply().increment();
-
- Metrics.MetricFamily dump = counter.dump();
- Assert.assertEquals("just two metrics", 2, dump.getMetricCount());
-
- Assert.assertEquals("a-dimension", dump.getMetric(0).getLabel(0).getName());
- Assert.assertEquals("preset-value", dump.getMetric(0).getLabel(0).getValue());
- Assert.assertEquals("another-dimension", dump.getMetric(0).getLabel(1).getName());
- Assert.assertEquals("first", dump.getMetric(0).getLabel(1).getValue());
- Assert.assertEquals(1, dump.getMetric(0).getCounter().getValue(), 0);
-
- Assert.assertEquals("a-dimension", dump.getMetric(1).getLabel(0).getName());
- Assert.assertEquals("preset-value", dump.getMetric(1).getLabel(0).getValue());
- Assert.assertEquals("another-dimension", dump.getMetric(1).getLabel(1).getName());
- Assert.assertEquals("second", dump.getMetric(1).getLabel(1).getValue());
- Assert.assertEquals(1, dump.getMetric(1).getCounter().getValue(), 0);
- }
-}
diff --git a/client/src/test/java/io/prometheus/client/metrics/GaugeTest.java b/client/src/test/java/io/prometheus/client/metrics/GaugeTest.java
deleted file mode 100644
index 7b972dc2c..000000000
--- a/client/src/test/java/io/prometheus/client/metrics/GaugeTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright 2013 Prometheus Team Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package io.prometheus.client.metrics;
-
-import io.prometheus.client.Metrics;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.List;
-
-/**
- *
- * Tests for {@link Gauge}.
- *
- */
-public class GaugeTest {
- @Test
- public void workflow() {
- Gauge.Builder oldBuilder = null;
- Gauge.Builder builder = Gauge.newBuilder().registerStatic(false);
- Assert.assertNotNull(builder);
-
- oldBuilder = builder;
- builder = builder.namespace("my_namespace");
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
- oldBuilder = builder;
- builder = builder.subsystem("my_subsystem");
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
- oldBuilder = builder;
- builder = builder.name("my_gauge");
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
- oldBuilder = builder;
- builder = builder.documentation("my_documentation");
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
- oldBuilder = builder;
- builder = builder.defaultValue(5D);
- Assert.assertNotEquals("not identical for state transference", builder);
- oldBuilder = builder;
- builder = builder.labelNames("my_label");
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
-
- final Gauge gauge = builder.build();
- Assert.assertNotNull(gauge);
-
- Assert.assertEquals("my_documentation", gauge.docstring);
- Assert.assertEquals("my_namespace_my_subsystem_my_gauge", gauge.name);
-
- Assert.assertEquals("new metric has no children", 0, gauge.children.size());
-
- final Gauge.Partial partial = gauge.newPartial();
- Assert.assertNotNull(partial);
-
- Assert.assertEquals("identical for state transference", partial,
- partial.labelPair("my_label", "my_label_value"));
-
- final Gauge.Child child = partial.apply();
- Assert.assertNotNull(child);
-
- child.set(42D);
- Assert.assertEquals("child value is set", 42D, child.value.get(), 0.001);
-
- Assert.assertEquals("only one instantiated child", 1, gauge.children.size());
-
- final Gauge.Child newChild = partial.apply();
- Assert.assertEquals("partial's identical label signatures should yield the same child", child,
- newChild);
-
- newChild.set(84D);
- Assert
- .assertEquals("original instantiated child gets new value", 84D, child.value.get(), 0.001);
-
- Assert.assertEquals("only one child after mutations", 1, gauge.children.size());
-
- final Metrics.MetricFamily metricFamily = gauge.dump();
- Assert.assertNotNull("emitted protocol buffer", metricFamily);
-
- Assert.assertEquals("correct metric type", Metrics.MetricType.GAUGE, metricFamily.getType());
- Assert.assertEquals("passed on docstring", "my_documentation", metricFamily.getHelp());
- Assert.assertEquals("passed on name", "my_namespace_my_subsystem_my_gauge",
- metricFamily.getName());
-
- final List metrics = metricFamily.getMetricList();
- Assert.assertEquals("only one metric child", 1, metrics.size());
-
- final Metrics.Metric metric = metrics.get(0);
- Assert.assertNotNull(metric);
-
- final List labels = metric.getLabelList();
- Assert.assertEquals("only one label pair", 1, labels.size());
-
- final Metrics.LabelPair labelPair = labels.get(0);
- Assert.assertEquals("correct label", "my_label", labelPair.getName());
- Assert.assertEquals("correct value", "my_label_value", labelPair.getValue());
-
- final Metrics.Gauge nestedGauge = metric.getGauge();
- Assert.assertNotNull("set nested type", nestedGauge);
-
- Assert.assertEquals("transfered last value", 84, nestedGauge.getValue(), 0.001);
-
- gauge.resetAll();
-
- Assert.assertEquals("same children no. after reset", 1, gauge.children.size());
- Assert.assertEquals("got default val. after reset", 5, child.value.get(), 0.001);
- }
-
- @Test
- public void clonePartialSingle() {
- Gauge gauge = Gauge.newBuilder()
- .name("some-name")
- .documentation("some-documentation")
- .labelNames("a-dimension")
- .registerStatic(false)
- .build();
-
- Gauge.Partial partial = gauge.newPartial();
- partial.labelPair("a-dimension", "preset-value");
- Gauge.Partial derivative = partial.clone();
- Assert.assertNotSame("should return a new object", partial, derivative);
- Assert.assertSame(partial.apply(), derivative.apply());
- partial.apply().set(1);
- derivative.apply().set(1);
-
- Metrics.MetricFamily dump = gauge.dump();
- Assert.assertEquals("just one metric", 1, dump.getMetricCount());
- }
-
- @Test
- public void clonePartialDouble() {
- Gauge gauge = Gauge.newBuilder()
- .name("some-name")
- .documentation("some-documentation")
- .labelNames("a-dimension", "another-dimension")
- .registerStatic(false)
- .build();
-
- Gauge.Partial partial = gauge.newPartial();
- partial.labelPair("a-dimension", "preset-value");
- Gauge.Partial derivative = partial.clone();
- Assert.assertNotSame("two different partials", partial, derivative);
- partial.labelPair("another-dimension", "first");
- partial.apply().set(1);
- derivative.labelPair("another-dimension", "second");
- derivative.apply().set(1);
-
- Metrics.MetricFamily dump = gauge.dump();
- Assert.assertEquals("just two metrics", 2, dump.getMetricCount());
-
- Assert.assertEquals("a-dimension", dump.getMetric(0).getLabel(0).getName());
- Assert.assertEquals("preset-value", dump.getMetric(0).getLabel(0).getValue());
- Assert.assertEquals("another-dimension", dump.getMetric(0).getLabel(1).getName());
- Assert.assertEquals("first", dump.getMetric(0).getLabel(1).getValue());
- Assert.assertEquals(1, dump.getMetric(0).getGauge().getValue(), 0);
-
- Assert.assertEquals("a-dimension", dump.getMetric(1).getLabel(0).getName());
- Assert.assertEquals("preset-value", dump.getMetric(1).getLabel(0).getValue());
- Assert.assertEquals("another-dimension", dump.getMetric(1).getLabel(1).getName());
- Assert.assertEquals("second", dump.getMetric(1).getLabel(1).getValue());
- Assert.assertEquals(1, dump.getMetric(1).getGauge().getValue(), 0);
- }
-
- @Test
- public void incrementDecrement() {
- Gauge gauge = Gauge.newBuilder()
- .name("some-name")
- .documentation("some-documentation")
- .labelNames("a-dimension", "another-dimension")
- .registerStatic(false)
- .build();
- final Gauge.Child child = gauge.newPartial().apply();
- Assert.assertEquals("starts as default", 0, child.value.get(), .001);
-
- child.increment();
- Assert.assertEquals("incremented by one", 1, child.value.get(), .001);
-
- child.increment(10);
- Assert.assertEquals("incremented by many", 11, child.value.get(), .001);
-
- child.decrement();
- Assert.assertEquals("decremented by one", 10, child.value.get(), .001);
-
- child.decrement(5);
- Assert.assertEquals("decremented by many", 5, child.value.get(), .001);
- }
-}
diff --git a/client/src/test/java/io/prometheus/client/metrics/MetricTest.java b/client/src/test/java/io/prometheus/client/metrics/MetricTest.java
deleted file mode 100644
index a7aea3124..000000000
--- a/client/src/test/java/io/prometheus/client/metrics/MetricTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2013 Prometheus Team Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package io.prometheus.client.metrics;
-
-import com.google.common.collect.Lists;
-import io.prometheus.client.Metrics;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.List;
-
-/**
- *
- * Tests for {@link io.prometheus.client.metrics.Metric}.
- *
- */
-public class MetricTest {
- @Test(expected = Metric.IllegalLabelDeclarationException.class)
- public void emptyLabelIllegality() {
- Metric.BaseBuilder builder = new Metric.BaseBuilder();
- builder = builder.labelNames("");
- builder.buildLabelNames();
- }
-
- @Test(expected = Metric.IllegalLabelDeclarationException.class)
- public void reservedLabelIllegality() {
- Metric.BaseBuilder builder = new Metric.BaseBuilder();
- builder = builder.labelNames("__name");
- builder.buildLabelNames();
- }
-
- @Test
- public void allowedLabelName() {
- Metric.BaseBuilder builder = new Metric.BaseBuilder();
- builder = builder.labelNames("name");
- Assert.assertEquals(Lists.newArrayList("name"), builder.buildLabelNames());
- }
-}
diff --git a/client/src/test/java/io/prometheus/client/metrics/SummaryTest.java b/client/src/test/java/io/prometheus/client/metrics/SummaryTest.java
deleted file mode 100644
index f1f75c365..000000000
--- a/client/src/test/java/io/prometheus/client/metrics/SummaryTest.java
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright 2013 Prometheus Team Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package io.prometheus.client.metrics;
-
-import io.prometheus.client.Metrics;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-// TODO(matt): Build fluent matchers to reduce boilerplate.
-
-/**
- *
- * Tests for {@link io.prometheus.client.metrics.Summary}.
- *
- */
-public class SummaryTest {
- @Test
- public void workflow() throws InterruptedException {
- Summary.Builder oldBuilder = null;
- Summary.Builder builder = Summary.newBuilder().registerStatic(false);
- Assert.assertNotNull(builder);
-
- oldBuilder = builder;
- builder = builder.namespace("my_namespace");
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
- oldBuilder = builder;
- builder = builder.subsystem("my_subsystem");
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
- oldBuilder = builder;
- builder = builder.name("my_summary");
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
- oldBuilder = builder;
- builder = builder.documentation("my_documentation");
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
- oldBuilder = builder;
- builder = builder.targetQuantile(0.5, 0.001);
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
- oldBuilder = builder;
- builder = builder.purgeInterval(5, TimeUnit.MINUTES);
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
- oldBuilder = builder;
- builder = builder.labelNames("my_label");
- Assert.assertNotEquals("not identical for state transference", builder, oldBuilder);
-
- final Summary summary = builder.build();
- Assert.assertNotNull(summary);
-
- Assert.assertEquals("my_documentation", summary.docstring);
- Assert.assertEquals("my_namespace_my_subsystem_my_summary", summary.name);
-
- Assert.assertEquals("new metric has no children", 0, summary.children.size());
-
- final Summary.Partial partial = summary.newPartial();
- Assert.assertNotNull(partial);
-
- Assert.assertEquals("identical for state transference", partial,
- partial.labelPair("my_label", "my_label_value"));
-
- final Summary.Child child = partial.apply();
- Assert.assertNotNull(child);
-
- child.observe(50D);
- Assert.assertEquals("child value is set", 50D, child.query(0.5), 0.001);
-
- Assert.assertEquals("only one instantiated child", 1, summary.children.size());
-
- final Summary.Child newChild = partial.apply();
- Assert.assertEquals("partial's identical label signatures should yield the same child", child,
- newChild);
-
- for (int i = 0; i < 99; i++) {
- newChild.observe(50D);
- }
-
- for (int i = 0; i < 100; i++) {
- newChild.observe(100D);
- }
-
- Assert.assertEquals("only one child after mutations", 1, summary.children.size());
-
- final Metrics.MetricFamily metricFamily = summary.dump();
- Assert.assertNotNull("emitted protocol buffer", metricFamily);
-
- Assert.assertEquals("correct metric type", Metrics.MetricType.SUMMARY, metricFamily.getType());
- Assert.assertEquals("passed on docstring", "my_documentation", metricFamily.getHelp());
- Assert.assertEquals("passed on name", "my_namespace_my_subsystem_my_summary",
- metricFamily.getName());
-
- final List metrics = metricFamily.getMetricList();
- Assert.assertEquals("only one metric child", 1, metrics.size());
-
- final Metrics.Metric metric = metrics.get(0);
- Assert.assertNotNull(metric);
-
- final List labels = metric.getLabelList();
- Assert.assertEquals("only one label pair", 1, labels.size());
-
- final Metrics.LabelPair labelPair = labels.get(0);
- Assert.assertEquals("correct label", "my_label", labelPair.getName());
- Assert.assertEquals("correct value", "my_label_value", labelPair.getValue());
-
- final Metrics.Summary nestedSummary = metric.getSummary();
- Assert.assertNotNull("set nested type", nestedSummary);
-
- Assert.assertEquals("observation count", 200, nestedSummary.getSampleCount());
- Assert.assertEquals("observation sum", 15000, nestedSummary.getSampleSum(), 0.001);
-
- final List quantiles = nestedSummary.getQuantileList();
- Assert.assertEquals("quantile count", 1, quantiles.size());
-
- final Metrics.Quantile quantile = quantiles.get(0);
- Assert.assertEquals("quantile rank", 0.5, quantile.getQuantile(), 0.001);
- Assert.assertEquals("quantile value", 50, quantile.getValue(), 0.001);
-
- summary.resetAll();
-
- Assert.assertEquals("same children no. after reset", 1, summary.children.size());
-
- summary.lastPurgeInstantMs = System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1);
- summary.purge();
- Assert.assertEquals("no children after purge", 0, summary.children.size());
- }
-
- @Test
- public void clonePartialSingle() {
- Summary summary = Summary.newBuilder()
- .name("some-name")
- .documentation("some-documentation")
- .labelNames("a-dimension")
- .registerStatic(false)
- .build();
-
- Summary.Partial partial = summary.newPartial();
- partial.labelPair("a-dimension", "preset-value");
- Summary.Partial derivative = partial.clone();
- Assert.assertNotSame("should return a new object", partial, derivative);
- Assert.assertSame(partial.apply(), derivative.apply());
- partial.apply().observe(1D);
- derivative.apply().observe(1D);
-
- Metrics.MetricFamily dump = summary.dump();
- Assert.assertEquals("just one metric", 1, dump.getMetricCount());
- }
-
- @Test
- public void clonePartialDouble() {
- Summary summary = Summary.newBuilder()
- .name("some-name")
- .documentation("some-documentation")
- .labelNames("a-dimension", "another-dimension")
- .registerStatic(false)
- .build();
-
- Summary.Partial partial = summary.newPartial();
- partial.labelPair("a-dimension", "preset-value");
- Summary.Partial derivative = partial.clone();
- Assert.assertNotSame("two different partials", partial, derivative);
- partial.labelPair("another-dimension", "first");
- partial.apply().observe(1D);
- derivative.labelPair("another-dimension", "second");
- derivative.apply().observe(1D);
-
- Metrics.MetricFamily dump = summary.dump();
- Assert.assertEquals("just two metrics", 2, dump.getMetricCount());
-
- Assert.assertEquals("a-dimension", dump.getMetric(0).getLabel(0).getName());
- Assert.assertEquals("preset-value", dump.getMetric(0).getLabel(0).getValue());
- Assert.assertEquals("another-dimension", dump.getMetric(0).getLabel(1).getName());
- Assert.assertEquals("first", dump.getMetric(0).getLabel(1).getValue());
- Assert.assertEquals(1, dump.getMetric(0).getSummary().getQuantile(0).getValue(), 0);
-
- Assert.assertEquals("a-dimension", dump.getMetric(1).getLabel(0).getName());
- Assert.assertEquals("preset-value", dump.getMetric(1).getLabel(0).getValue());
- Assert.assertEquals("another-dimension", dump.getMetric(1).getLabel(1).getName());
- Assert.assertEquals("second", dump.getMetric(1).getLabel(1).getValue());
- Assert.assertEquals(1, dump.getMetric(1).getSummary().getQuantile(0).getValue(), 0);
- }
-
- @Test
- public void emptiedAndSentForExposition() {
- final Summary summary = Summary.newBuilder()
- .name("latencies-by-handler")
- .documentation("some-documentation")
- .labelNames("handler")
- .registerStatic(false)
- .build();
-
- final Summary.Child fooLatencies = summary.newPartial()
- .labelPair("handler", "foo")
- .apply();
-
- fooLatencies.observe(5D);
-
- final Summary.Child barLatencies = summary.newPartial()
- .labelPair("handler", "bar")
- .apply();
-
- barLatencies.observe(1D);
-
- // Explicitly clean the slate of one dimension!
- fooLatencies.reset();
-
- Metrics.MetricFamily out = summary.dump();
-
- Assert.assertEquals("must contain two metrics", 2, out.getMetricCount());
- final Set found = new HashSet();
- for (final Metrics.Metric m : out.getMetricList()) {
- final String dim = m.getLabel(0).getValue();
- final Metrics.Summary sum = m.getSummary();
- found.add(dim);
- if ("foo".equals(dim)) {
- Assert.assertEquals("should lack ranked values after reset", 0, sum.getQuantileCount());
- Assert.assertEquals("should have record of single observation", 1, sum.getSampleCount());
- Assert.assertEquals("should have sum of single observation", 5, sum.getSampleSum(), 0);
- } else if ("bar".equals(dim)) {
- Assert.assertEquals("should have ranked values", 3, sum.getQuantileCount());
- Assert.assertEquals("should have record of single observation", 1, sum.getSampleCount());
- Assert.assertEquals("should have sum of single observation", 1, sum.getSampleSum(), 0);
- } else {
- Assert.fail("illegal condition");
- }
- }
- Assert.assertTrue("must have seen bar", found.contains("bar"));
- Assert.assertTrue("must have seen foo", found.contains("foo"));
- }
-
- @Test
- public void resetBehavior() throws InterruptedException {
- final Summary summary = Summary.newBuilder()
- .name("a-metric")
- .documentation("some-documentation")
- .registerStatic(false)
- .labelNames("dimension_a")
- .resetInterval(1, TimeUnit.MILLISECONDS)
- .build();
-
- summary.newPartial()
- .labelPair("dimension_a", "some_label")
- .apply()
- .observe(100D);
-
- Thread.sleep(100); // WART: Synchronization or injected timing obviates.
-
- summary.reset();
- Metrics.MetricFamily dump = summary.dump();
-
- Assert.assertEquals(1, dump.getMetricCount());
- }
-
- @Test
- public void purgeBehavior() throws InterruptedException {
- final Summary summary = Summary.newBuilder()
- .name("a-metric")
- .documentation("some-documentation")
- .registerStatic(false)
- .labelNames("dimension_a")
- .purgeInterval(1, TimeUnit.MILLISECONDS)
- .build();
-
- summary.newPartial()
- .labelPair("dimension_a", "some_label")
- .apply()
- .observe(100D);
-
- Thread.sleep(100); // WART: Synchronization or injected timing obviates.
-
- summary.purge();
- Metrics.MetricFamily dump = summary.dump();
-
- Assert.assertEquals(0, dump.getMetricCount());
- }
-}
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 000000000..2a8645fe5
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1 @@
+.hugo_build.lock
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 000000000..8ca147236
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,60 @@
+# Docs
+
+This directory contains [hugo](https://gohugo.io) documentation to be published in GitHub pages.
+
+## Run Locally
+
+```shell
+hugo server -D
+```
+
+This will serve the docs on [http://localhost:1313](http://localhost:1313).
+
+## Deploy to GitHub Pages
+
+Changes to the `main` branch will be deployed automatically with GitHub Actions.
+
+## Update Javadoc
+
+Javadoc are not checked-in to the GitHub repository.
+They are generated on the fly by GitHub Actions when the docs are updated.
+To view locally, run the following:
+
+```shell
+# note that the 'compile' in the following command is necessary for
+# Javadoc to detect the module structure
+./mvnw clean compile javadoc:javadoc javadoc:aggregate
+rm -r ./docs/static/api
+mv ./target/site/apidocs ./docs/static/api
+```
+
+GitHub pages are in the `/client_java/` folder, so we link to `/client_java/api` rather than `/api`.
+To make JavaDoc work locally, create a link:
+
+```shell
+mkdir ./docs/static/client_java
+ln -s ../api ./docs/static/client_java/api
+```
+
+## Update Geekdocs
+
+The docs use the [Geekdocs](https://geekdocs.de/) theme. The theme is checked in to GitHub in the
+`./docs/themes/hugo-geekdoc/` folder. To update [Geekdocs](https://geekdocs.de/), remove the current
+folder and create a new one with the
+latest [release](https://github.com/thegeeklab/hugo-geekdoc/releases). There are no local
+modifications in `./docs/themes/hugo-geekdoc/`.
+
+## Notes
+
+Here's how the initial `docs/` folder was set up:
+
+```shell
+hugo new site docs
+cd docs/
+mkdir -p themes/hugo-geekdoc/
+curl -L https://github.com/thegeeklab/hugo-geekdoc/releases/download/v0.41.1/hugo-geekdoc.tar.gz \
+ | tar -xz -C themes/hugo-geekdoc/ --strip-components=1
+```
+
+Create the initial `hugo.toml` file as described
+in [https://geekdocs.de/usage/getting-started/](https://geekdocs.de/usage/getting-started/).
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-annotations.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-annotations.txt
new file mode 100644
index 000000000..b2f6a39d8
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-annotations.txt
@@ -0,0 +1,11 @@
+Comparing source compatibility of prometheus-metrics-annotations-1.6.2-SNAPSHOT.jar against
++++ NEW ANNOTATION: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.annotations.StableApi (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.annotation.Annotation
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW ANNOTATION: java.lang.annotation.Documented
+ +++ NEW ANNOTATION: java.lang.annotation.Target
+ +++ NEW ELEMENT: value=java.lang.annotation.ElementType.TYPE,java.lang.annotation.ElementType.CONSTRUCTOR,java.lang.annotation.ElementType.METHOD,java.lang.annotation.ElementType.FIELD (+)
+ +++ NEW ANNOTATION: java.lang.annotation.Retention
+ +++ NEW ELEMENT: value=java.lang.annotation.RetentionPolicy.CLASS (+)
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-config.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-config.txt
new file mode 100644
index 000000000..dd61db431
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-config.txt
@@ -0,0 +1,263 @@
+Comparing source compatibility of prometheus-metrics-config-1.6.2-SNAPSHOT.jar against prometheus-metrics-config-1.6.1.jar
++++ NEW ENUM: PUBLIC(+) FINAL(+) io.prometheus.metrics.config.EscapingScheme (compatible)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.constant.Constable
+ +++ NEW INTERFACE: java.lang.Comparable
+ +++ NEW INTERFACE: java.io.Serializable
+ +++ NEW SUPERCLASS: java.lang.Enum
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.config.EscapingScheme DOTS_ESCAPING
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.config.EscapingScheme ALLOW_UTF8
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.config.EscapingScheme UNDERSCORE_ESCAPING
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.config.EscapingScheme VALUE_ENCODING_ESCAPING
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.config.EscapingScheme DEFAULT
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.EscapingScheme fromAcceptHeader(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) FINAL(+) java.lang.String getValue()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String toHeaderFormat()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.EscapingScheme valueOf(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.EscapingScheme[] values()
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.config.ExemplarsProperties (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.ExemplarsProperties$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) java.lang.Integer getMaxRetentionPeriodSeconds()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.Integer getMinRetentionPeriodSeconds()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.Integer getSampleIntervalMilliseconds()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.ExemplarsProperties$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExemplarsProperties build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExemplarsProperties$Builder maxRetentionPeriodSeconds(int)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExemplarsProperties$Builder minRetentionPeriodSeconds(int)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExemplarsProperties$Builder sampleIntervalMilliseconds(int)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.config.ExporterFilterProperties (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) java.lang.String METRIC_NAME_MUST_NOT_BE_EQUAL_TO
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) java.lang.String METRIC_NAME_MUST_START_WITH
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) java.lang.String METRIC_NAME_MUST_NOT_START_WITH
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) java.lang.String METRIC_NAME_MUST_BE_EQUAL_TO
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.ExporterFilterProperties$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) java.util.List getAllowedMetricNamePrefixes()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.util.List getAllowedMetricNames()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.util.List getExcludedMetricNamePrefixes()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.util.List getExcludedMetricNames()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.ExporterFilterProperties$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterFilterProperties$Builder allowedNames(java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterFilterProperties$Builder allowedPrefixes(java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterFilterProperties build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterFilterProperties$Builder excludedNames(java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterFilterProperties$Builder excludedPrefixes(java.lang.String[])
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.config.ExporterHttpServerProperties (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.ExporterHttpServerProperties$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) java.lang.Integer getPort()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) boolean isPreferUncompressedResponse()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.ExporterHttpServerProperties$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterHttpServerProperties build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterHttpServerProperties$Builder port(int)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterHttpServerProperties$Builder preferUncompressedResponse(boolean)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getEndpoint()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.util.Map getHeaders()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getInterval()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.Boolean getPreserveNames()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getProtocol()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.util.Map getResourceAttributes()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getServiceInstanceId()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getServiceName()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getServiceNamespace()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getServiceVersion()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getTimeout()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties$Builder endpoint(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties$Builder header(java.lang.String, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties$Builder intervalSeconds(int)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties$Builder preserveNames(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties$Builder protocol(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties$Builder resourceAttribute(java.lang.String, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties$Builder serviceInstanceId(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties$Builder serviceName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties$Builder serviceNamespace(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties$Builder serviceVersion(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties$Builder timeoutSeconds(int)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.config.ExporterProperties (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.ExporterProperties$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) boolean getExemplarsOnAllMetricTypes()
+ +++ NEW METHOD: PUBLIC(+) boolean getIncludeCreatedTimestamps()
+ +++ NEW METHOD: PUBLIC(+) boolean getPrometheusTimestampsInMs()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.ExporterProperties$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterProperties build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterProperties$Builder exemplarsOnAllMetricTypes(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterProperties$Builder includeCreatedTimestamps(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterProperties$Builder prometheusTimestampsInMs(boolean)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.config.ExporterPushgatewayProperties (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.ExporterPushgatewayProperties$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getAddress()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.time.Duration getConnectTimeout()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.EscapingScheme getEscapingScheme()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getJob()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.time.Duration getReadTimeout()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getScheme()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.ExporterPushgatewayProperties$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterPushgatewayProperties$Builder address(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterPushgatewayProperties build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterPushgatewayProperties$Builder connectTimeout(java.time.Duration)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterPushgatewayProperties$Builder escapingScheme(io.prometheus.metrics.config.EscapingScheme)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterPushgatewayProperties$Builder job(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterPushgatewayProperties$Builder readTimeout(java.time.Duration)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterPushgatewayProperties$Builder scheme(java.lang.String)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricsProperties(java.lang.Boolean, java.lang.Boolean, java.lang.Boolean, java.util.List, java.lang.Integer, java.lang.Double, java.lang.Double, java.lang.Integer, java.lang.Long, java.util.List, java.util.List, java.lang.Long, java.lang.Integer)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.MetricsProperties$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) java.lang.Boolean getExemplarsEnabled()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.Boolean getHistogramClassicOnly()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.util.List getHistogramClassicUpperBounds()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.Integer getHistogramNativeInitialSchema()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.Integer getHistogramNativeMaxNumberOfBuckets()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.Double getHistogramNativeMaxZeroThreshold()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.Double getHistogramNativeMinZeroThreshold()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.Boolean getHistogramNativeOnly()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.Long getHistogramNativeResetDurationSeconds()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.Long getSummaryMaxAgeSeconds()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.Integer getSummaryNumberOfAgeBuckets()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.util.List getSummaryQuantileErrors()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.util.List getSummaryQuantiles()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.MetricsProperties$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties$Builder exemplarsEnabled(java.lang.Boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties$Builder histogramClassicOnly(java.lang.Boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties$Builder histogramClassicUpperBounds(double[])
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties$Builder histogramNativeInitialSchema(java.lang.Integer)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties$Builder histogramNativeMaxNumberOfBuckets(java.lang.Integer)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties$Builder histogramNativeMaxZeroThreshold(java.lang.Double)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties$Builder histogramNativeMinZeroThreshold(java.lang.Double)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties$Builder histogramNativeOnly(java.lang.Boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties$Builder histogramNativeResetDurationSeconds(java.lang.Long)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties$Builder summaryMaxAgeSeconds(java.lang.Long)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties$Builder summaryNumberOfAgeBuckets(java.lang.Integer)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties$Builder summaryQuantileErrors(double[])
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties$Builder summaryQuantiles(double[])
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.config.OpenMetrics2Properties (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.OpenMetrics2Properties$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) boolean getCompositeValues()
+ +++ NEW METHOD: PUBLIC(+) boolean getContentNegotiation()
+ +++ NEW METHOD: PUBLIC(+) boolean getEnabled()
+ +++ NEW METHOD: PUBLIC(+) boolean getExemplarCompliance()
+ +++ NEW METHOD: PUBLIC(+) boolean getNativeHistograms()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.OpenMetrics2Properties$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.OpenMetrics2Properties build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.OpenMetrics2Properties$Builder compositeValues(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.OpenMetrics2Properties$Builder contentNegotiation(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.OpenMetrics2Properties$Builder enableAll()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.OpenMetrics2Properties$Builder enabled(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.OpenMetrics2Properties$Builder exemplarCompliance(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.OpenMetrics2Properties$Builder nativeHistograms(boolean)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.config.PrometheusProperties (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.PrometheusProperties$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.PrometheusProperties get()
+ +++ NEW EXCEPTION: io.prometheus.metrics.config.PrometheusPropertiesException
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties getDefaultMetricProperties()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExemplarsProperties getExemplarProperties()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterFilterProperties getExporterFilterProperties()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterHttpServerProperties getExporterHttpServerProperties()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterOpenTelemetryProperties getExporterOpenTelemetryProperties()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterProperties getExporterProperties()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.ExporterPushgatewayProperties getExporterPushgatewayProperties()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties getMetricProperties(java.lang.String)
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.OpenMetrics2Properties getOpenMetrics2Properties()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.PrometheusProperties$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.PrometheusProperties build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.PrometheusProperties$Builder defaultMetricsProperties(io.prometheus.metrics.config.MetricsProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.PrometheusProperties$Builder enableOpenMetrics2(java.util.function.Consumer)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.PrometheusProperties$Builder exemplarProperties(io.prometheus.metrics.config.ExemplarsProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.PrometheusProperties$Builder exporterFilterProperties(io.prometheus.metrics.config.ExporterFilterProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.PrometheusProperties$Builder exporterHttpServerProperties(io.prometheus.metrics.config.ExporterHttpServerProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.PrometheusProperties$Builder exporterOpenTelemetryProperties(io.prometheus.metrics.config.ExporterOpenTelemetryProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.PrometheusProperties$Builder exporterProperties(io.prometheus.metrics.config.ExporterProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.PrometheusProperties$Builder metricProperties(java.util.Map)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.PrometheusProperties$Builder openMetrics2Properties(io.prometheus.metrics.config.OpenMetrics2Properties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.PrometheusProperties$Builder pushgatewayProperties(io.prometheus.metrics.config.ExporterPushgatewayProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.PrometheusProperties$Builder putMetricProperty(java.lang.String, io.prometheus.metrics.config.MetricsProperties)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.config.PrometheusPropertiesException (compatible)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.io.Serializable
+ +++ NEW SUPERCLASS: java.lang.RuntimeException
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusPropertiesException(java.lang.String)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusPropertiesException(java.lang.String, java.lang.Exception)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.config.PrometheusPropertiesLoader (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusPropertiesLoader()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.PrometheusProperties load()
+ +++ NEW EXCEPTION: io.prometheus.metrics.config.PrometheusPropertiesException
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.config.PrometheusProperties load(java.util.Map)
+ +++ NEW EXCEPTION: io.prometheus.metrics.config.PrometheusPropertiesException
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-core.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-core.txt
new file mode 100644
index 000000000..f6b1e9a9c
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-core.txt
@@ -0,0 +1,353 @@
+Comparing source compatibility of prometheus-metrics-core-1.6.2-SNAPSHOT.jar against prometheus-metrics-core-1.6.1.jar
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.core.datapoints.CounterDataPoint (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.DataPoint
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) double get()
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) long getLongValue()
+ +++ NEW METHOD: PUBLIC(+) void inc()
+ +++ NEW METHOD: PUBLIC(+) void inc(long)
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void inc(double)
+ +++ NEW METHOD: PUBLIC(+) void incWithExemplar(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void incWithExemplar(long, io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void incWithExemplar(double, io.prometheus.metrics.model.snapshots.Labels)
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.core.datapoints.DataPoint (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.core.datapoints.DistributionDataPoint (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.DataPoint
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.TimerApi
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) long getCount()
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) double getSum()
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void observe(double)
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void observeWithExemplar(double, io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.datapoints.Timer startTimer()
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.core.datapoints.GaugeDataPoint (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.DataPoint
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.TimerApi
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) void dec()
+ +++ NEW METHOD: PUBLIC(+) void dec(double)
+ +++ NEW METHOD: PUBLIC(+) void decWithExemplar(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void decWithExemplar(double, io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) double get()
+ +++ NEW METHOD: PUBLIC(+) void inc()
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void inc(double)
+ +++ NEW METHOD: PUBLIC(+) void incWithExemplar(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void incWithExemplar(double, io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void set(double)
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void setWithExemplar(double, io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.datapoints.Timer startTimer()
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.core.datapoints.StateSetDataPoint (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.DataPoint
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void setFalse(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) void setFalse(java.lang.Enum>)
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void setTrue(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) void setTrue(java.lang.Enum>)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.datapoints.Timer (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.io.Closeable
+ +++ NEW INTERFACE: java.lang.AutoCloseable
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) void close()
+ +++ NEW METHOD: PUBLIC(+) double observeDuration()
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.core.datapoints.TimerApi (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.core.datapoints.Timer startTimer()
+ +++ NEW METHOD: PUBLIC(+) void time(java.lang.Runnable)
+ +++ NEW METHOD: PUBLIC(+) java.lang.Object time(java.util.function.Supplier)
+ GENERIC TEMPLATES: +++ T:java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) java.lang.Object timeChecked(java.util.concurrent.Callable)
+ +++ NEW EXCEPTION: java.lang.Exception
+ GENERIC TEMPLATES: +++ T:java.lang.Object
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.exemplars.ExemplarSampler (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) ExemplarSampler(io.prometheus.metrics.core.exemplars.ExemplarSamplerConfig, io.prometheus.metrics.tracer.common.SpanContext)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) ExemplarSampler(io.prometheus.metrics.core.exemplars.ExemplarSamplerConfig)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplars collect()
+ +++ NEW METHOD: PUBLIC(+) void observe(double)
+ +++ NEW METHOD: PUBLIC(+) void observeWithExemplar(double, io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void reset()
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.exemplars.ExemplarSamplerConfig (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) int DEFAULT_MIN_RETENTION_PERIOD_SECONDS
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) int DEFAULT_MAX_RETENTION_PERIOD_SECONDS
+ +++ NEW CONSTRUCTOR: PUBLIC(+) ExemplarSamplerConfig(io.prometheus.metrics.config.ExemplarsProperties, int)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) ExemplarSamplerConfig(io.prometheus.metrics.config.ExemplarsProperties, double[])
+ +++ NEW METHOD: PUBLIC(+) double[] getHistogramClassicUpperBounds()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) long getMaxRetentionPeriodMillis()
+ +++ NEW METHOD: PUBLIC(+) long getMinRetentionPeriodMillis()
+ +++ NEW METHOD: PUBLIC(+) int getNumberOfExemplars()
+ +++ NEW METHOD: PUBLIC(+) long getSampleIntervalMillis()
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.metrics.Counter (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.Collector
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.DataPoint
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.CounterDataPoint
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.StatefulMetric
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.Counter$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.Counter$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.CounterSnapshot collect()
+ +++ NEW METHOD: PUBLIC(+) double get()
+ +++ NEW METHOD: PUBLIC(+) long getLongValue()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricType getMetricType()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW METHOD: PUBLIC(+) void inc(long)
+ +++ NEW METHOD: PUBLIC(+) void inc(double)
+ +++ NEW METHOD: PUBLIC(+) void incWithExemplar(long, io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void incWithExemplar(double, io.prometheus.metrics.model.snapshots.Labels)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.Counter$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.StatefulMetric$Builder
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Counter build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Counter$Builder name(java.lang.String)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.metrics.CounterWithCallback (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.Collector
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.CallbackMetric
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.CounterWithCallback$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.CounterWithCallback$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.CounterSnapshot collect()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricType getMetricType()
+ +++ NEW ANNOTATION: java.lang.Deprecated
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.CounterWithCallback$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.CallbackMetric$Builder
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.CounterWithCallback build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.CounterWithCallback$Builder callback(java.util.function.Consumer)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.CounterWithCallback$Builder name(java.lang.String)
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) STATIC(+) io.prometheus.metrics.core.metrics.CounterWithCallback$Callback (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void call(double, java.lang.String[])
+ +++ NEW ANNOTATION: java.lang.FunctionalInterface
++++* NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.metrics.Gauge (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.Collector
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.DataPoint
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.GaugeDataPoint
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.TimerApi
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.StatefulMetric
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.Gauge$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.Gauge$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.GaugeSnapshot collect()
+ +++ NEW METHOD: PUBLIC(+) double get()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricType getMetricType()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW METHOD: PUBLIC(+) void inc(double)
+ +++ NEW METHOD: PUBLIC(+) void incWithExemplar(double, io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void set(double)
+ +++ NEW METHOD: PUBLIC(+) void setWithExemplar(double, io.prometheus.metrics.model.snapshots.Labels)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.Gauge$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.StatefulMetric$Builder
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Gauge build()
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.metrics.GaugeWithCallback (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.Collector
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.CallbackMetric
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.GaugeWithCallback$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.GaugeWithCallback$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.GaugeSnapshot collect()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricType getMetricType()
+ +++ NEW ANNOTATION: java.lang.Deprecated
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.GaugeWithCallback$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.CallbackMetric$Builder
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.GaugeWithCallback build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.GaugeWithCallback$Builder callback(java.util.function.Consumer)
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) STATIC(+) io.prometheus.metrics.core.metrics.GaugeWithCallback$Callback (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void call(double, java.lang.String[])
+ +++ NEW ANNOTATION: java.lang.FunctionalInterface
++++* NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.metrics.Histogram (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.Collector
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.DistributionDataPoint
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.DataPoint
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.TimerApi
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.StatefulMetric
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.Histogram$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.Histogram$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.HistogramSnapshot collect()
+ +++ NEW METHOD: PUBLIC(+) long getCount()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricType getMetricType()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW METHOD: PUBLIC(+) double getSum()
+ +++ NEW METHOD: PUBLIC(+) void observe(double)
+ +++ NEW METHOD: PUBLIC(+) void observeWithExemplar(double, io.prometheus.metrics.model.snapshots.Labels)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.Histogram$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.StatefulMetric$Builder
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) double[] DEFAULT_CLASSIC_UPPER_BOUNDS
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Histogram build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Histogram$Builder classicExponentialUpperBounds(double, double, int)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Histogram$Builder classicLinearUpperBounds(double, double, int)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Histogram$Builder classicOnly()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Histogram$Builder classicUpperBounds(double[])
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties getDefaultProperties()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Histogram$Builder nativeInitialSchema(int)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Histogram$Builder nativeMaxNumberOfBuckets(int)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Histogram$Builder nativeMaxZeroThreshold(double)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Histogram$Builder nativeMinZeroThreshold(double)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Histogram$Builder nativeOnly()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Histogram$Builder nativeResetDuration(long, java.util.concurrent.TimeUnit)
++++* NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.metrics.Histogram$DataPoint (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.DistributionDataPoint
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.DataPoint
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.TimerApi
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) long getCount()
+ +++ NEW METHOD: PUBLIC(+) double getSum()
+ +++ NEW METHOD: PUBLIC(+) void observe(double)
+ +++ NEW METHOD: PUBLIC(+) void observeWithExemplar(double, io.prometheus.metrics.model.snapshots.Labels)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.metrics.Info (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.Collector
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.MetricWithFixedMetadata
+ +++ NEW METHOD: PUBLIC(+) void addLabelValues(java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.Info$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.Info$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.InfoSnapshot collect()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricType getMetricType()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW METHOD: PUBLIC(+) void remove(java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) void setLabelValues(java.lang.String[])
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.Info$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.MetricWithFixedMetadata$Builder
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Info build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Info$Builder name(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Info$Builder unit(io.prometheus.metrics.model.snapshots.Unit)
++++ NEW CLASS: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.core.metrics.Metric (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.Collector
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.model.snapshots.MetricSnapshot collect()
++++ NEW CLASS: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.core.metrics.MetricWithFixedMetadata (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.Collector
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.Metric
+ +++ NEW METHOD: PUBLIC(+) java.util.Set getLabelNames()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricMetadata getMetadata()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor getMetricFamilyDescriptor()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getPrometheusName()
+ +++ NEW ANNOTATION: java.lang.Deprecated
++++ NEW CLASS: PUBLIC(+) ABSTRACT(+) STATIC(+) io.prometheus.metrics.core.metrics.MetricWithFixedMetadata$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ GENERIC TEMPLATES: +++ B:io.prometheus.metrics.core.metrics.MetricWithFixedMetadata$Builder, +++ M:io.prometheus.metrics.core.metrics.MetricWithFixedMetadata
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.Metric$Builder
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.core.metrics.MetricWithFixedMetadata build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.MetricWithFixedMetadata$Builder constLabels(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.MetricWithFixedMetadata$Builder help(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.MetricWithFixedMetadata$Builder labelNames(java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.MetricWithFixedMetadata$Builder name(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.MetricWithFixedMetadata$Builder unit(io.prometheus.metrics.model.snapshots.Unit)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.metrics.SlidingWindow (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ GENERIC TEMPLATES: +++ T:java.lang.Object
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) SlidingWindow(java.lang.Class, java.util.function.Supplier, java.util.function.ObjDoubleConsumer, long, int)
+ +++ NEW METHOD: PUBLIC(+) java.lang.Object current()
+ +++ NEW METHOD: PUBLIC(+) void observe(double)
++++ NEW CLASS: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.core.metrics.StatefulMetric (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ GENERIC TEMPLATES: +++ D:io.prometheus.metrics.core.datapoints.DataPoint, +++ T:D
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.Collector
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.MetricWithFixedMetadata
+ +++ NEW METHOD: PUBLIC(+) void clear()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshot collect()
+ +++ NEW METHOD: PUBLIC(+) void initLabelValues(java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.datapoints.DataPoint labelValues(java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) void remove(java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) void removeIf(java.util.function.Function,java.lang.Boolean>)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.metrics.StateSet (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.Collector
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.DataPoint
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.StateSetDataPoint
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.StatefulMetric
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.StateSet$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.StateSet$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.StateSetSnapshot collect()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricType getMetricType()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW METHOD: PUBLIC(+) void setFalse(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) void setTrue(java.lang.String)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.StateSet$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.StatefulMetric$Builder
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.StateSet build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.StateSet$Builder states(java.lang.Class extends java.lang.Enum extends ?>>)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.StateSet$Builder states(java.lang.String[])
++++* NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.metrics.Summary (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.Collector
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.DistributionDataPoint
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.DataPoint
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.TimerApi
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.StatefulMetric
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.Summary$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.Summary$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.SummarySnapshot collect()
+ +++ NEW METHOD: PUBLIC(+) long getCount()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricType getMetricType()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW METHOD: PUBLIC(+) double getSum()
+ +++ NEW METHOD: PUBLIC(+) void observe(double)
+ +++ NEW METHOD: PUBLIC(+) void observeWithExemplar(double, io.prometheus.metrics.model.snapshots.Labels)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.Summary$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.StatefulMetric$Builder
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) long DEFAULT_MAX_AGE_SECONDS
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) int DEFAULT_NUMBER_OF_AGE_BUCKETS
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Summary build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.MetricsProperties getDefaultProperties()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Summary$Builder maxAgeSeconds(long)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Summary$Builder numberOfAgeBuckets(int)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Summary$Builder quantile(double)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.Summary$Builder quantile(double, double)
++++* NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.metrics.Summary$DataPoint (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.DistributionDataPoint
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.DataPoint
+ +++ NEW INTERFACE: io.prometheus.metrics.core.datapoints.TimerApi
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) long getCount()
+ +++ NEW METHOD: PUBLIC(+) double getSum()
+ +++ NEW METHOD: PUBLIC(+) void observe(double)
+ +++ NEW METHOD: PUBLIC(+) void observeWithExemplar(double, io.prometheus.metrics.model.snapshots.Labels)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.metrics.SummaryWithCallback (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.Collector
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.CallbackMetric
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.SummaryWithCallback$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.SummaryWithCallback$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.SummarySnapshot collect()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricType getMetricType()
+ +++ NEW ANNOTATION: java.lang.Deprecated
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.core.metrics.SummaryWithCallback$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.core.metrics.CallbackMetric$Builder
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.SummaryWithCallback build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.core.metrics.SummaryWithCallback$Builder callback(java.util.function.Consumer)
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) STATIC(+) io.prometheus.metrics.core.metrics.SummaryWithCallback$Callback (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void call(long, double, io.prometheus.metrics.model.snapshots.Quantiles, java.lang.String[])
+ +++ NEW ANNOTATION: java.lang.FunctionalInterface
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-common.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-common.txt
new file mode 100644
index 000000000..d2ba333af
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-common.txt
@@ -0,0 +1,40 @@
+Comparing source compatibility of prometheus-metrics-exporter-common-1.6.2-SNAPSHOT.jar against prometheus-metrics-exporter-common-1.6.1.jar
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.exporter.common.PrometheusHttpExchange (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.AutoCloseable
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void close()
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.exporter.common.PrometheusHttpRequest getRequest()
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.exporter.common.PrometheusHttpResponse getResponse()
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void handleException(java.io.IOException)
+ +++ NEW EXCEPTION: java.io.IOException
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void handleException(java.lang.RuntimeException)
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.exporter.common.PrometheusHttpRequest (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.PrometheusScrapeRequest
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getHeader(java.lang.String)
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.util.Enumeration getHeaders(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.lang.String getMethod()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getParameter(java.lang.String)
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.String[] getParameterValues(java.lang.String)
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.lang.String getQueryString()
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.exporter.common.PrometheusHttpResponse (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.io.OutputStream sendHeadersAndGetBody(int, int)
+ +++ NEW EXCEPTION: java.io.IOException
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void setHeader(java.lang.String, java.lang.String)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.exporter.common.PrometheusScrapeHandler (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusScrapeHandler()
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusScrapeHandler(io.prometheus.metrics.model.registry.PrometheusRegistry)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusScrapeHandler(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusScrapeHandler(io.prometheus.metrics.config.PrometheusProperties, io.prometheus.metrics.model.registry.PrometheusRegistry)
+ +++ NEW METHOD: PUBLIC(+) void handleRequest(io.prometheus.metrics.exporter.common.PrometheusHttpExchange)
+ +++ NEW EXCEPTION: java.io.IOException
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-httpserver.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-httpserver.txt
new file mode 100644
index 000000000..decc352f5
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-httpserver.txt
@@ -0,0 +1,52 @@
+Comparing source compatibility of prometheus-metrics-exporter-httpserver-1.6.2-SNAPSHOT.jar against prometheus-metrics-exporter-httpserver-1.6.1.jar
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.DefaultHandler (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: com.sun.net.httpserver.HttpHandler
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) DefaultHandler(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) void handle(com.sun.net.httpserver.HttpExchange)
+ +++ NEW EXCEPTION: java.io.IOException
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.HealthyHandler (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: com.sun.net.httpserver.HttpHandler
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) HealthyHandler()
+ +++ NEW METHOD: PUBLIC(+) void handle(com.sun.net.httpserver.HttpExchange)
+ +++ NEW EXCEPTION: java.io.IOException
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.io.Closeable
+ +++ NEW INTERFACE: java.lang.AutoCloseable
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW METHOD: PUBLIC(+) void close()
+ +++ NEW METHOD: PUBLIC(+) int getPort()
+ +++ NEW METHOD: PUBLIC(+) void stop()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer$Builder authenticatedSubjectAttributeName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer$Builder authenticator(com.sun.net.httpserver.Authenticator)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer buildAndStart()
+ +++ NEW EXCEPTION: java.io.IOException
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer$Builder defaultHandler(com.sun.net.httpserver.HttpHandler)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer$Builder executorService(java.util.concurrent.ExecutorService)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer$Builder hostname(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer$Builder httpsConfigurator(com.sun.net.httpserver.HttpsConfigurator)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer$Builder inetAddress(java.net.InetAddress)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer$Builder metricsHandlerPath(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer$Builder port(int)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer$Builder registerHealthHandler(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.HTTPServer$Builder registry(io.prometheus.metrics.model.registry.PrometheusRegistry)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.exporter.httpserver.MetricsHandler (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: com.sun.net.httpserver.HttpHandler
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricsHandler(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricsHandler(io.prometheus.metrics.model.registry.PrometheusRegistry)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricsHandler(io.prometheus.metrics.config.PrometheusProperties, io.prometheus.metrics.model.registry.PrometheusRegistry)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricsHandler()
+ +++ NEW METHOD: PUBLIC(+) void handle(com.sun.net.httpserver.HttpExchange)
+ +++ NEW EXCEPTION: java.io.IOException
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-opentelemetry-otel-agent-resources.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-opentelemetry-otel-agent-resources.txt
new file mode 100644
index 000000000..e5d128dd6
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-opentelemetry-otel-agent-resources.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exporter-opentelemetry-otel-agent-resources-1.6.2-SNAPSHOT.jar against prometheus-metrics-exporter-opentelemetry-otel-agent-resources-1.6.1.jar
+No changes.
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-opentelemetry-shaded.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-opentelemetry-shaded.txt
new file mode 100644
index 000000000..8bc4f87f6
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-opentelemetry-shaded.txt
@@ -0,0 +1,26 @@
+Comparing source compatibility of prometheus-metrics-exporter-opentelemetry-1.6.2-SNAPSHOT.jar against prometheus-metrics-exporter-opentelemetry-1.6.1.jar
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.AutoCloseable
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) OpenTelemetryExporter(io.prometheus.metrics.shaded.io_opentelemetry_2_28_1_alpha.sdk.metrics.export.MetricReader)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW METHOD: PUBLIC(+) void close()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter buildAndStart()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder endpoint(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder header(java.lang.String, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder intervalSeconds(int)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder preserveNames(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder protocol(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder registry(io.prometheus.metrics.model.registry.PrometheusRegistry)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder resourceAttribute(java.lang.String, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceInstanceId(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceNamespace(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceVersion(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder timeoutSeconds(int)
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-opentelemetry.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-opentelemetry.txt
new file mode 100644
index 000000000..19d112b08
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-opentelemetry.txt
@@ -0,0 +1,26 @@
+Comparing source compatibility of prometheus-metrics-exporter-opentelemetry-no-otel-1.6.2-SNAPSHOT.jar against prometheus-metrics-exporter-opentelemetry-no-otel-1.6.1.jar
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.AutoCloseable
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) OpenTelemetryExporter(io.opentelemetry.sdk.metrics.export.MetricReader)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW METHOD: PUBLIC(+) void close()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter buildAndStart()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder endpoint(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder header(java.lang.String, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder intervalSeconds(int)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder preserveNames(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder protocol(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder registry(io.prometheus.metrics.model.registry.PrometheusRegistry)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder resourceAttribute(java.lang.String, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceInstanceId(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceNamespace(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceVersion(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder timeoutSeconds(int)
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-pushgateway.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-pushgateway.txt
new file mode 100644
index 000000000..82cd98d0e
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-pushgateway.txt
@@ -0,0 +1,75 @@
+Comparing source compatibility of prometheus-metrics-exporter-pushgateway-1.6.2-SNAPSHOT.jar against prometheus-metrics-exporter-pushgateway-1.6.1.jar
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.DefaultHttpConnectionFactory (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.exporter.pushgateway.HttpConnectionFactory
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) DefaultHttpConnectionFactory()
+ +++ NEW METHOD: PUBLIC(+) java.net.HttpURLConnection create(java.net.URL)
+ +++ NEW EXCEPTION: java.io.IOException
++++ NEW ENUM: PUBLIC(+) FINAL(+) io.prometheus.metrics.exporter.pushgateway.Format (compatible)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.constant.Constable
+ +++ NEW INTERFACE: java.lang.Comparable
+ +++ NEW INTERFACE: java.io.Serializable
+ +++ NEW SUPERCLASS: java.lang.Enum
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.exporter.pushgateway.Format PROMETHEUS_PROTOBUF
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.exporter.pushgateway.Format PROMETHEUS_TEXT
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.pushgateway.Format valueOf(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.pushgateway.Format[] values()
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.exporter.pushgateway.HttpConnectionFactory (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.net.HttpURLConnection create(java.net.URL)
+ +++ NEW EXCEPTION: java.io.IOException
+ +++ NEW ANNOTATION: java.lang.FunctionalInterface
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW METHOD: PUBLIC(+) void delete()
+ +++ NEW EXCEPTION: java.io.IOException
+ +++ NEW METHOD: PUBLIC(+) void push()
+ +++ NEW EXCEPTION: java.io.IOException
+ +++ NEW METHOD: PUBLIC(+) void push(io.prometheus.metrics.model.registry.Collector)
+ +++ NEW EXCEPTION: java.io.IOException
+ +++ NEW METHOD: PUBLIC(+) void push(io.prometheus.metrics.model.registry.MultiCollector)
+ +++ NEW EXCEPTION: java.io.IOException
+ +++ NEW METHOD: PUBLIC(+) void pushAdd()
+ +++ NEW EXCEPTION: java.io.IOException
+ +++ NEW METHOD: PUBLIC(+) void pushAdd(io.prometheus.metrics.model.registry.Collector)
+ +++ NEW EXCEPTION: java.io.IOException
+ +++ NEW METHOD: PUBLIC(+) void pushAdd(io.prometheus.metrics.model.registry.MultiCollector)
+ +++ NEW EXCEPTION: java.io.IOException
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder address(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder basicAuth(java.lang.String, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder bearerToken(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder connectionFactory(io.prometheus.metrics.exporter.pushgateway.HttpConnectionFactory)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder connectionTimeout(java.time.Duration)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder escapingScheme(io.prometheus.metrics.config.EscapingScheme)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder format(io.prometheus.metrics.exporter.pushgateway.Format)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder groupingKey(java.lang.String, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder instanceIpGroupingKey()
+ +++ NEW EXCEPTION: java.net.UnknownHostException
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder job(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder prometheusTimestampsInMs(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder readTimeout(java.time.Duration)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder registry(io.prometheus.metrics.model.registry.PrometheusRegistry)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.pushgateway.PushGateway$Builder scheme(io.prometheus.metrics.exporter.pushgateway.Scheme)
++++ NEW ENUM: PUBLIC(+) FINAL(+) io.prometheus.metrics.exporter.pushgateway.Scheme (compatible)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.constant.Constable
+ +++ NEW INTERFACE: java.lang.Comparable
+ +++ NEW INTERFACE: java.io.Serializable
+ +++ NEW SUPERCLASS: java.lang.Enum
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.exporter.pushgateway.Scheme HTTPS
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.exporter.pushgateway.Scheme HTTP
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.pushgateway.Scheme fromString(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) java.lang.String toString()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.pushgateway.Scheme valueOf(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.exporter.pushgateway.Scheme[] values()
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-servlet-jakarta.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-servlet-jakarta.txt
new file mode 100644
index 000000000..61372aa39
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-servlet-jakarta.txt
@@ -0,0 +1,12 @@
+Comparing source compatibility of prometheus-metrics-exporter-servlet-jakarta-1.6.2-SNAPSHOT.jar against prometheus-metrics-exporter-servlet-jakarta-1.6.1.jar
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.exporter.servlet.jakarta.PrometheusMetricsServlet (compatible)
+ +++ CLASS FILE FORMAT VERSION: 61.0 <- n.a.
+ +++ NEW INTERFACE: jakarta.servlet.ServletConfig
+ +++ NEW INTERFACE: jakarta.servlet.Servlet
+ +++ NEW INTERFACE: java.io.Serializable
+ +++ NEW SUPERCLASS: jakarta.servlet.http.HttpServlet
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusMetricsServlet(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusMetricsServlet(io.prometheus.metrics.config.PrometheusProperties, io.prometheus.metrics.model.registry.PrometheusRegistry)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusMetricsServlet()
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusMetricsServlet(io.prometheus.metrics.model.registry.PrometheusRegistry)
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-servlet-javax.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-servlet-javax.txt
new file mode 100644
index 000000000..434cfaf65
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exporter-servlet-javax.txt
@@ -0,0 +1,12 @@
+Comparing source compatibility of prometheus-metrics-exporter-servlet-javax-1.6.2-SNAPSHOT.jar against prometheus-metrics-exporter-servlet-javax-1.6.1.jar
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.exporter.servlet.javax.PrometheusMetricsServlet (compatible)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: javax.servlet.ServletConfig
+ +++ NEW INTERFACE: javax.servlet.Servlet
+ +++ NEW INTERFACE: java.io.Serializable
+ +++ NEW SUPERCLASS: javax.servlet.http.HttpServlet
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusMetricsServlet(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusMetricsServlet(io.prometheus.metrics.model.registry.PrometheusRegistry)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusMetricsServlet(io.prometheus.metrics.config.PrometheusProperties, io.prometheus.metrics.model.registry.PrometheusRegistry)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusMetricsServlet()
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exposition-formats-shaded.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exposition-formats-shaded.txt
new file mode 100644
index 000000000..2523aafc1
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exposition-formats-shaded.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exposition-formats-1.6.2-SNAPSHOT.jar against prometheus-metrics-exposition-formats-1.6.1.jar
+No changes.
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exposition-formats.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exposition-formats.txt
new file mode 100644
index 000000000..0f04c0d1e
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exposition-formats.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exposition-formats-no-protobuf-1.6.2-SNAPSHOT.jar against prometheus-metrics-exposition-formats-no-protobuf-1.6.1.jar
+No changes.
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exposition-textformats.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exposition-textformats.txt
new file mode 100644
index 000000000..fd61bb649
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-exposition-textformats.txt
@@ -0,0 +1,98 @@
+Comparing source compatibility of prometheus-metrics-exposition-textformats-1.6.2-SNAPSHOT.jar against prometheus-metrics-exposition-textformats-1.6.1.jar
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.expositionformats.ExpositionFormats (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.expositionformats.ExpositionFormatWriter findWriter(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.expositionformats.OpenMetrics2TextFormatWriter getOpenMetrics2TextFormatWriter()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter getOpenMetricsTextFormatWriter()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.expositionformats.PrometheusProtobufWriter getPrometheusProtobufWriter()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.expositionformats.PrometheusTextFormatWriter getPrometheusTextFormatWriter()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.expositionformats.ExpositionFormats init()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.expositionformats.ExpositionFormats init(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.expositionformats.ExpositionFormats init(io.prometheus.metrics.config.ExporterProperties)
+ +++ NEW ANNOTATION: java.lang.Deprecated
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.expositionformats.ExpositionFormatWriter (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) boolean accepts(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.lang.String getContentType()
+ +++ NEW METHOD: PUBLIC(+) boolean isAvailable()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String toDebugString(io.prometheus.metrics.model.snapshots.MetricSnapshots, io.prometheus.metrics.config.EscapingScheme)
+ +++ NEW METHOD: PUBLIC(+) java.lang.String toDebugString(io.prometheus.metrics.model.snapshots.MetricSnapshots)
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void write(java.io.OutputStream, io.prometheus.metrics.model.snapshots.MetricSnapshots, io.prometheus.metrics.config.EscapingScheme)
+ +++ NEW EXCEPTION: java.io.IOException
+ +++ NEW METHOD: PUBLIC(+) void write(java.io.OutputStream, io.prometheus.metrics.model.snapshots.MetricSnapshots)
+ +++ NEW EXCEPTION: java.io.IOException
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.expositionformats.OpenMetrics2TextFormatWriter (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.expositionformats.ExpositionFormatWriter
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) java.lang.String CONTENT_TYPE
+ +++ NEW CONSTRUCTOR: PUBLIC(+) OpenMetrics2TextFormatWriter(io.prometheus.metrics.config.OpenMetrics2Properties, boolean, boolean)
+ +++ NEW METHOD: PUBLIC(+) boolean accepts(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.expositionformats.OpenMetrics2TextFormatWriter$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.expositionformats.OpenMetrics2TextFormatWriter create()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getContentType()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.config.OpenMetrics2Properties getOpenMetrics2Properties()
+ +++ NEW METHOD: PUBLIC(+) void write(java.io.OutputStream, io.prometheus.metrics.model.snapshots.MetricSnapshots, io.prometheus.metrics.config.EscapingScheme)
+ +++ NEW EXCEPTION: java.io.IOException
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.expositionformats.OpenMetrics2TextFormatWriter$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.expositionformats.OpenMetrics2TextFormatWriter build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.expositionformats.OpenMetrics2TextFormatWriter$Builder setCreatedTimestampsEnabled(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.expositionformats.OpenMetrics2TextFormatWriter$Builder setExemplarsOnAllMetricTypesEnabled(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.expositionformats.OpenMetrics2TextFormatWriter$Builder setOpenMetrics2Properties(io.prometheus.metrics.config.OpenMetrics2Properties)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.expositionformats.ExpositionFormatWriter
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) java.lang.String CONTENT_TYPE
+ +++ NEW CONSTRUCTOR: PUBLIC(+) OpenMetricsTextFormatWriter(boolean, boolean)
+ +++ NEW METHOD: PUBLIC(+) boolean accepts(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter create()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getContentType()
+ +++ NEW METHOD: PUBLIC(+) void write(java.io.OutputStream, io.prometheus.metrics.model.snapshots.MetricSnapshots, io.prometheus.metrics.config.EscapingScheme)
+ +++ NEW EXCEPTION: java.io.IOException
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter$Builder setCreatedTimestampsEnabled(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter$Builder setExemplarsOnAllMetricTypesEnabled(boolean)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.expositionformats.PrometheusProtobufWriter (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.expositionformats.ExpositionFormatWriter
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) java.lang.String CONTENT_TYPE
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusProtobufWriter()
+ +++ NEW METHOD: PUBLIC(+) boolean accepts(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getContentType()
+ +++ NEW METHOD: PUBLIC(+) boolean isAvailable()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String toDebugString(io.prometheus.metrics.model.snapshots.MetricSnapshots, io.prometheus.metrics.config.EscapingScheme)
+ +++ NEW METHOD: PUBLIC(+) void write(java.io.OutputStream, io.prometheus.metrics.model.snapshots.MetricSnapshots, io.prometheus.metrics.config.EscapingScheme)
+ +++ NEW EXCEPTION: java.io.IOException
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.expositionformats.PrometheusTextFormatWriter (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.expositionformats.ExpositionFormatWriter
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) java.lang.String CONTENT_TYPE
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusTextFormatWriter(boolean)
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW METHOD: PUBLIC(+) boolean accepts(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.expositionformats.PrometheusTextFormatWriter$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.expositionformats.PrometheusTextFormatWriter create()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getContentType()
+ +++ NEW METHOD: PUBLIC(+) void write(java.io.OutputStream, io.prometheus.metrics.model.snapshots.MetricSnapshots, io.prometheus.metrics.config.EscapingScheme)
+ +++ NEW EXCEPTION: java.io.IOException
+ +++ NEW METHOD: PUBLIC(+) void writeCreated(java.io.Writer, io.prometheus.metrics.model.snapshots.MetricSnapshot, io.prometheus.metrics.config.EscapingScheme)
+ +++ NEW EXCEPTION: java.io.IOException
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.expositionformats.PrometheusTextFormatWriter$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.expositionformats.PrometheusTextFormatWriter build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.expositionformats.PrometheusTextFormatWriter$Builder setIncludeCreatedTimestamps(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.expositionformats.PrometheusTextFormatWriter$Builder setTimestampsInMs(boolean)
+ +++ NEW ANNOTATION: java.lang.Deprecated
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-instrumentation-caffeine.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-instrumentation-caffeine.txt
new file mode 100644
index 000000000..f804dc9ca
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-instrumentation-caffeine.txt
@@ -0,0 +1,23 @@
+Comparing source compatibility of prometheus-metrics-instrumentation-caffeine-1.6.2-SNAPSHOT.jar against prometheus-metrics-instrumentation-caffeine-1.6.1.jar
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.caffeine.CacheMetricsCollector (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.MultiCollector
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) CacheMetricsCollector()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW METHOD: PUBLIC(+) void addCache(java.lang.String, com.github.benmanes.caffeine.cache.Cache,?>)
+ +++ NEW METHOD: PUBLIC(+) void addCache(java.lang.String, com.github.benmanes.caffeine.cache.AsyncCache,?>)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.caffeine.CacheMetricsCollector$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) void clear()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots collect()
+ +++ NEW METHOD: PUBLIC(+) java.util.List getPrometheusNames()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW METHOD: PUBLIC(+) com.github.benmanes.caffeine.cache.Cache,?> removeCache(java.lang.String)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.caffeine.CacheMetricsCollector$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) CacheMetricsCollector$Builder()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.caffeine.CacheMetricsCollector build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.caffeine.CacheMetricsCollector$Builder collectEvictionWeightAsCounter(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.caffeine.CacheMetricsCollector$Builder collectWeightedSize(boolean)
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-instrumentation-dropwizard.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-instrumentation-dropwizard.txt
new file mode 100644
index 000000000..a95df8aae
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-instrumentation-dropwizard.txt
@@ -0,0 +1,19 @@
+Comparing source compatibility of prometheus-metrics-instrumentation-dropwizard-1.6.2-SNAPSHOT.jar against prometheus-metrics-instrumentation-dropwizard-1.6.1.jar
++++* NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.dropwizard.DropwizardExports (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.MultiCollector
+ +++ NEW SUPERCLASS: io.prometheus.metrics.instrumentation.dropwizard5.internal.AbstractDropwizardExports
+ +++ NEW CONSTRUCTOR: PUBLIC(+) DropwizardExports(com.codahale.metrics.MetricRegistry)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) DropwizardExports(com.codahale.metrics.MetricRegistry, com.codahale.metrics.MetricFilter)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) DropwizardExports(com.codahale.metrics.MetricRegistry, com.codahale.metrics.MetricFilter, io.prometheus.metrics.instrumentation.dropwizard5.labels.CustomLabelMapper)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.dropwizard.DropwizardExports$Builder builder()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.dropwizard.DropwizardExports$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.dropwizard.DropwizardExports$Builder customLabelMapper(io.prometheus.metrics.instrumentation.dropwizard5.labels.CustomLabelMapper)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.dropwizard.DropwizardExports$Builder dropwizardRegistry(com.codahale.metrics.MetricRegistry)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.dropwizard.DropwizardExports$Builder invalidMetricHandler(io.prometheus.metrics.instrumentation.dropwizard5.InvalidMetricHandler)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.dropwizard.DropwizardExports$Builder metricFilter(com.codahale.metrics.MetricFilter)
+ +++ NEW METHOD: PUBLIC(+) void register()
+ +++ NEW METHOD: PUBLIC(+) void register(io.prometheus.metrics.model.registry.PrometheusRegistry)
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-instrumentation-dropwizard5.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-instrumentation-dropwizard5.txt
new file mode 100644
index 000000000..e9c13ab17
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-instrumentation-dropwizard5.txt
@@ -0,0 +1,47 @@
+Comparing source compatibility of prometheus-metrics-instrumentation-dropwizard5-1.6.2-SNAPSHOT.jar against prometheus-metrics-instrumentation-dropwizard5-1.6.1.jar
++++* NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.dropwizard5.DropwizardExports (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.MultiCollector
+ +++ NEW SUPERCLASS: io.prometheus.metrics.instrumentation.dropwizard5.internal.AbstractDropwizardExports
+ +++ NEW CONSTRUCTOR: PUBLIC(+) DropwizardExports(io.dropwizard.metrics5.MetricRegistry, io.dropwizard.metrics5.MetricFilter, io.prometheus.metrics.instrumentation.dropwizard5.labels.CustomLabelMapper)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) DropwizardExports(io.dropwizard.metrics5.MetricRegistry)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) DropwizardExports(io.dropwizard.metrics5.MetricRegistry, io.dropwizard.metrics5.MetricFilter)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.dropwizard5.DropwizardExports$Builder builder()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.dropwizard5.DropwizardExports$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.dropwizard5.DropwizardExports$Builder customLabelMapper(io.prometheus.metrics.instrumentation.dropwizard5.labels.CustomLabelMapper)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.dropwizard5.DropwizardExports$Builder dropwizardRegistry(io.dropwizard.metrics5.MetricRegistry)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.dropwizard5.DropwizardExports$Builder invalidMetricHandler(io.prometheus.metrics.instrumentation.dropwizard5.InvalidMetricHandler)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.dropwizard5.DropwizardExports$Builder metricFilter(io.dropwizard.metrics5.MetricFilter)
+ +++ NEW METHOD: PUBLIC(+) void register()
+ +++ NEW METHOD: PUBLIC(+) void register(io.prometheus.metrics.model.registry.PrometheusRegistry)
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.instrumentation.dropwizard5.InvalidMetricHandler (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.instrumentation.dropwizard5.InvalidMetricHandler ALWAYS_THROW
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) boolean suppressException(java.lang.String, java.lang.Exception)
+ +++ NEW ANNOTATION: java.lang.FunctionalInterface
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.dropwizard5.labels.CustomLabelMapper (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) CustomLabelMapper(java.util.List)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Labels getLabels(java.lang.String, java.util.List, java.util.List)
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getName(java.lang.String)
++++ NEW CLASS: PUBLIC(+) FINAL(+) io.prometheus.metrics.instrumentation.dropwizard5.labels.MapperConfig (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MapperConfig()
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MapperConfig(java.lang.String, java.lang.String, java.util.Map)
+ +++ NEW METHOD: PUBLIC(+) boolean equals(java.lang.Object)
+ +++ NEW METHOD: PUBLIC(+) java.util.Map getLabels()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getMatch()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getName()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) int hashCode()
+ +++ NEW METHOD: PUBLIC(+) void setLabels(java.util.Map)
+ +++ NEW METHOD: PUBLIC(+) void setMatch(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) void setName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) java.lang.String toString()
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-instrumentation-guava.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-instrumentation-guava.txt
new file mode 100644
index 000000000..815196d0e
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-instrumentation-guava.txt
@@ -0,0 +1,13 @@
+Comparing source compatibility of prometheus-metrics-instrumentation-guava-1.6.2-SNAPSHOT.jar against prometheus-metrics-instrumentation-guava-1.6.1.jar
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.guava.CacheMetricsCollector (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.MultiCollector
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) CacheMetricsCollector()
+ +++ NEW METHOD: PUBLIC(+) void addCache(java.lang.String, com.google.common.cache.Cache,?>)
+ +++ NEW METHOD: PUBLIC(+) void clear()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots collect()
+ +++ NEW METHOD: PUBLIC(+) java.util.List getPrometheusNames()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW METHOD: PUBLIC(+) com.google.common.cache.Cache,?> removeCache(java.lang.String)
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-instrumentation-jvm.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-instrumentation-jvm.txt
new file mode 100644
index 000000000..391bae997
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-instrumentation-jvm.txt
@@ -0,0 +1,124 @@
+Comparing source compatibility of prometheus-metrics-instrumentation-jvm-1.6.2-SNAPSHOT.jar against prometheus-metrics-instrumentation-jvm-1.6.1.jar
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmBufferPoolMetrics (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmBufferPoolMetrics$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmBufferPoolMetrics$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmBufferPoolMetrics$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmBufferPoolMetrics$Builder constLabels(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void register()
+ +++ NEW METHOD: PUBLIC(+) void register(io.prometheus.metrics.model.registry.PrometheusRegistry)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmClassLoadingMetrics (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmClassLoadingMetrics$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmClassLoadingMetrics$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmClassLoadingMetrics$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmClassLoadingMetrics$Builder constLabels(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void register()
+ +++ NEW METHOD: PUBLIC(+) void register(io.prometheus.metrics.model.registry.PrometheusRegistry)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmCompilationMetrics (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmCompilationMetrics$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmCompilationMetrics$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmCompilationMetrics$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmCompilationMetrics$Builder constLabels(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void register()
+ +++ NEW METHOD: PUBLIC(+) void register(io.prometheus.metrics.model.registry.PrometheusRegistry)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmGarbageCollectorMetrics (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmGarbageCollectorMetrics$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmGarbageCollectorMetrics$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmGarbageCollectorMetrics$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmGarbageCollectorMetrics$Builder constLabels(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void register()
+ +++ NEW METHOD: PUBLIC(+) void register(io.prometheus.metrics.model.registry.PrometheusRegistry)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmMemoryMetrics (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmMemoryMetrics$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmMemoryMetrics$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmMemoryMetrics$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmMemoryMetrics$Builder constLabels(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void register()
+ +++ NEW METHOD: PUBLIC(+) void register(io.prometheus.metrics.model.registry.PrometheusRegistry)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmMemoryPoolAllocationMetrics (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmMemoryPoolAllocationMetrics$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmMemoryPoolAllocationMetrics$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmMemoryPoolAllocationMetrics$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmMemoryPoolAllocationMetrics$Builder constLabels(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void register()
+ +++ NEW METHOD: PUBLIC(+) void register(io.prometheus.metrics.model.registry.PrometheusRegistry)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmMetrics (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) JvmMetrics()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmMetrics$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmMetrics$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmMetrics$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmMetrics$Builder constLabels(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void register()
+ +++ NEW METHOD: PUBLIC(+) void register(io.prometheus.metrics.model.registry.PrometheusRegistry)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmNativeMemoryMetrics (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmNativeMemoryMetrics$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmNativeMemoryMetrics$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmNativeMemoryMetrics$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmNativeMemoryMetrics$Builder constLabels(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void register()
+ +++ NEW METHOD: PUBLIC(+) void register(io.prometheus.metrics.model.registry.PrometheusRegistry)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmRuntimeInfoMetric (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmRuntimeInfoMetric$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmRuntimeInfoMetric$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmRuntimeInfoMetric$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmRuntimeInfoMetric$Builder constLabels(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void register()
+ +++ NEW METHOD: PUBLIC(+) void register(io.prometheus.metrics.model.registry.PrometheusRegistry)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmThreadsMetrics (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmThreadsMetrics$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmThreadsMetrics$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.JvmThreadsMetrics$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.JvmThreadsMetrics$Builder constLabels(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void register()
+ +++ NEW METHOD: PUBLIC(+) void register(io.prometheus.metrics.model.registry.PrometheusRegistry)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.ProcessMetrics (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.ProcessMetrics$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.ProcessMetrics$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.instrumentation.jvm.ProcessMetrics$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.instrumentation.jvm.ProcessMetrics$Builder constLabels(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) void register()
+ +++ NEW METHOD: PUBLIC(+) void register(io.prometheus.metrics.model.registry.PrometheusRegistry)
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-model.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-model.txt
new file mode 100644
index 000000000..98a3e2b0d
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-model.txt
@@ -0,0 +1,600 @@
+Comparing source compatibility of prometheus-metrics-model-1.6.2-SNAPSHOT.jar against prometheus-metrics-model-1.6.1.jar
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.model.registry.Collector (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.model.snapshots.MetricSnapshot collect()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshot collect(io.prometheus.metrics.model.registry.PrometheusScrapeRequest)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshot collect(java.util.function.Predicate)
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshot collect(java.util.function.Predicate, io.prometheus.metrics.model.registry.PrometheusScrapeRequest)
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.util.Set getLabelNames()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricMetadata getMetadata()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor getMetricFamilyDescriptor()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricType getMetricType()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getPrometheusName()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW ANNOTATION: java.lang.FunctionalInterface
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.model.registry.MetricNameFilter (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.util.function.Predicate
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) java.util.function.Predicate ALLOW_ALL
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.registry.MetricNameFilter$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) boolean test(java.lang.String)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.registry.MetricNameFilter$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricNameFilter build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricNameFilter$Builder nameMustBeEqualTo(java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricNameFilter$Builder nameMustBeEqualTo(java.util.Collection)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricNameFilter$Builder nameMustNotBeEqualTo(java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricNameFilter$Builder nameMustNotBeEqualTo(java.util.Collection)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricNameFilter$Builder nameMustNotStartWith(java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricNameFilter$Builder nameMustNotStartWith(java.util.Collection)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricNameFilter$Builder nameMustStartWith(java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricNameFilter$Builder nameMustStartWith(java.util.Collection)
++++ NEW ENUM: PUBLIC(+) FINAL(+) io.prometheus.metrics.model.registry.MetricType (compatible)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.constant.Constable
+ +++ NEW INTERFACE: java.lang.Comparable
+ +++ NEW INTERFACE: java.io.Serializable
+ +++ NEW SUPERCLASS: java.lang.Enum
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.registry.MetricType SUMMARY
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.registry.MetricType HISTOGRAM
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.registry.MetricType STATESET
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.registry.MetricType UNKNOWN
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.registry.MetricType INFO
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.registry.MetricType COUNTER
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.registry.MetricType GAUGE
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.registry.MetricType valueOf(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.registry.MetricType[] values()
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.model.registry.MultiCollector (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.model.snapshots.MetricSnapshots collect()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots collect(io.prometheus.metrics.model.registry.PrometheusScrapeRequest)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots collect(java.util.function.Predicate)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots collect(java.util.function.Predicate, io.prometheus.metrics.model.registry.PrometheusScrapeRequest)
+ +++ NEW METHOD: PUBLIC(+) java.util.Set getLabelNames(java.lang.String)
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricMetadata getMetadata(java.lang.String)
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.util.List getMetricFamilyDescriptors()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricType getMetricType(java.lang.String)
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.util.List getPrometheusNames()
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW ANNOTATION: java.lang.FunctionalInterface
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.model.registry.PrometheusRegistry (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.registry.PrometheusRegistry defaultRegistry
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusRegistry()
+ +++ NEW METHOD: PUBLIC(+) void clear()
+ +++ NEW METHOD: PUBLIC(+) void register(io.prometheus.metrics.model.registry.Collector)
+ +++ NEW METHOD: PUBLIC(+) void register(io.prometheus.metrics.model.registry.MultiCollector)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots scrape()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots scrape(io.prometheus.metrics.model.registry.PrometheusScrapeRequest)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots scrape(java.util.function.Predicate)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots scrape(java.util.function.Predicate, io.prometheus.metrics.model.registry.PrometheusScrapeRequest)
+ +++ NEW METHOD: PUBLIC(+) void unregister(io.prometheus.metrics.model.registry.Collector)
+ +++ NEW METHOD: PUBLIC(+) void unregister(io.prometheus.metrics.model.registry.MultiCollector)
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.model.registry.PrometheusScrapeRequest (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.lang.String[] getParameterValues(java.lang.String)
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.lang.String getRequestPath()
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.model.snapshots.ClassicHistogramBucket (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.Comparable
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) ClassicHistogramBucket(double, long)
+ +++ NEW METHOD: PUBLIC(+) int compareTo(io.prometheus.metrics.model.snapshots.ClassicHistogramBucket)
+ +++ NEW METHOD: PUBLIC(+) long getCount()
+ +++ NEW METHOD: PUBLIC(+) double getUpperBound()
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.Iterable
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets EMPTY
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) long getCount(int)
+ +++ NEW METHOD: PUBLIC(+) double getUpperBound(int)
+ +++ NEW METHOD: PUBLIC(+) boolean isEmpty()
+ +++ NEW METHOD: PUBLIC(+) java.util.Iterator iterator()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets of(java.util.List, java.util.List extends java.lang.Number>)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets of(double[], java.lang.Number[])
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets of(double[], long[])
+ +++ NEW METHOD: PUBLIC(+) int size()
+ +++ NEW METHOD: PUBLIC(+) java.util.stream.Stream stream()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets$Builder bucket(double, long)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets build()
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.model.snapshots.CounterSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricSnapshot
+ +++ NEW CONSTRUCTOR: PUBLIC(+) CounterSnapshot(io.prometheus.metrics.model.snapshots.MetricMetadata, java.util.Collection)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.CounterSnapshot$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) java.util.List getDataPoints()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.CounterSnapshot$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricSnapshot$Builder
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.CounterSnapshot build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.CounterSnapshot$Builder dataPoint(io.prometheus.metrics.model.snapshots.CounterSnapshot$CounterDataPointSnapshot)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.CounterSnapshot$CounterDataPointSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.DataPointSnapshot
+ +++ NEW CONSTRUCTOR: PUBLIC(+) CounterSnapshot$CounterDataPointSnapshot(double, io.prometheus.metrics.model.snapshots.Labels, io.prometheus.metrics.model.snapshots.Exemplar, long)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) CounterSnapshot$CounterDataPointSnapshot(double, io.prometheus.metrics.model.snapshots.Labels, io.prometheus.metrics.model.snapshots.Exemplar, long, long, boolean)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) CounterSnapshot$CounterDataPointSnapshot(double, io.prometheus.metrics.model.snapshots.Labels, io.prometheus.metrics.model.snapshots.Exemplar, long, long)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.CounterSnapshot$CounterDataPointSnapshot$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplar getExemplar()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) double getValue()
++++ NEW CLASS: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.model.snapshots.DataPointSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) long getCreatedTimestampMillis()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Labels getLabels()
+ +++ NEW METHOD: PUBLIC(+) long getScrapeTimestampMillis()
+ +++ NEW METHOD: PUBLIC(+) boolean hasCreatedTimestamp()
+ +++ NEW METHOD: PUBLIC(+) boolean hasScrapeTimestamp()
++++ NEW CLASS: PUBLIC(+) ABSTRACT(+) STATIC(+) io.prometheus.metrics.model.snapshots.DataPointSnapshot$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ GENERIC TEMPLATES: +++ T:io.prometheus.metrics.model.snapshots.DataPointSnapshot$Builder
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) DataPointSnapshot$Builder()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.DataPointSnapshot$Builder labels(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.DataPointSnapshot$Builder scrapeTimestampMillis(long)
++++ NEW CLASS: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.model.snapshots.DistributionDataPointSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.DataPointSnapshot
+ +++ NEW METHOD: PUBLIC(+) long getCount()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplars getExemplars()
+ +++ NEW METHOD: PUBLIC(+) double getSum()
+ +++ NEW METHOD: PUBLIC(+) boolean hasCount()
+ +++ NEW METHOD: PUBLIC(+) boolean hasSum()
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.model.snapshots.DuplicateLabelsException (compatible)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.io.Serializable
+ +++ NEW SUPERCLASS: java.lang.IllegalArgumentException
+ +++ NEW CONSTRUCTOR: PUBLIC(+) DuplicateLabelsException(io.prometheus.metrics.model.snapshots.MetricMetadata, io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Labels getLabels()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricMetadata getMetadata()
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplar (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) java.lang.String SPAN_ID
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) java.lang.String TRACE_ID
+ +++ NEW CONSTRUCTOR: PUBLIC(+) Exemplar(double, io.prometheus.metrics.model.snapshots.Labels, long)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.Exemplar$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Labels getLabels()
+ +++ NEW METHOD: PUBLIC(+) long getTimestampMillis()
+ +++ NEW METHOD: PUBLIC(+) double getValue()
+ +++ NEW METHOD: PUBLIC(+) boolean hasTimestamp()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.Exemplar$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplar build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplar$Builder labels(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplar$Builder spanId(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplar$Builder timestampMillis(long)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplar$Builder traceId(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplar$Builder value(double)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplars (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.Iterable
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.Exemplars EMPTY
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.Exemplars$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplar get(int)
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplar get(double, double)
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplar getLatest()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.util.Iterator iterator()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.Exemplars of(java.util.Collection)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.Exemplars of(io.prometheus.metrics.model.snapshots.Exemplar[])
+ +++ NEW METHOD: PUBLIC(+) int size()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.Exemplars$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplars build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplars$Builder exemplar(io.prometheus.metrics.model.snapshots.Exemplar)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplars$Builder exemplars(java.util.Collection)
++++ NEW CLASS: PUBLIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.GaugeSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricSnapshot
+ +++ NEW CONSTRUCTOR: PUBLIC(+) GaugeSnapshot(io.prometheus.metrics.model.snapshots.MetricMetadata, java.util.Collection)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.GaugeSnapshot$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) java.util.List getDataPoints()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.GaugeSnapshot$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricSnapshot$Builder
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.GaugeSnapshot build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.GaugeSnapshot$Builder dataPoint(io.prometheus.metrics.model.snapshots.GaugeSnapshot$GaugeDataPointSnapshot)
++++ NEW CLASS: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.GaugeSnapshot$GaugeDataPointSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.DataPointSnapshot
+ +++ NEW CONSTRUCTOR: PUBLIC(+) GaugeSnapshot$GaugeDataPointSnapshot(double, io.prometheus.metrics.model.snapshots.Labels, io.prometheus.metrics.model.snapshots.Exemplar, long)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) GaugeSnapshot$GaugeDataPointSnapshot(double, io.prometheus.metrics.model.snapshots.Labels, io.prometheus.metrics.model.snapshots.Exemplar)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.GaugeSnapshot$GaugeDataPointSnapshot$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplar getExemplar()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) double getValue()
++++ NEW CLASS: PUBLIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.HistogramSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricSnapshot
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) int CLASSIC_HISTOGRAM
+ +++ NEW CONSTRUCTOR: PUBLIC(+) HistogramSnapshot(io.prometheus.metrics.model.snapshots.MetricMetadata, java.util.Collection)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) HistogramSnapshot(boolean, io.prometheus.metrics.model.snapshots.MetricMetadata, java.util.Collection)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.HistogramSnapshot$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) java.util.List getDataPoints()
+ +++ NEW METHOD: PUBLIC(+) boolean isGaugeHistogram()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.HistogramSnapshot$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricSnapshot$Builder
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.HistogramSnapshot build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.HistogramSnapshot$Builder dataPoint(io.prometheus.metrics.model.snapshots.HistogramSnapshot$HistogramDataPointSnapshot)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.HistogramSnapshot$Builder gaugeHistogram(boolean)
++++ NEW CLASS: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.HistogramSnapshot$HistogramDataPointSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.DistributionDataPointSnapshot
+ +++ NEW CONSTRUCTOR: PUBLIC(+) HistogramSnapshot$HistogramDataPointSnapshot(int, long, double, io.prometheus.metrics.model.snapshots.NativeHistogramBuckets, io.prometheus.metrics.model.snapshots.NativeHistogramBuckets, double, io.prometheus.metrics.model.snapshots.Labels, io.prometheus.metrics.model.snapshots.Exemplars, long)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) HistogramSnapshot$HistogramDataPointSnapshot(io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets, int, long, double, io.prometheus.metrics.model.snapshots.NativeHistogramBuckets, io.prometheus.metrics.model.snapshots.NativeHistogramBuckets, double, io.prometheus.metrics.model.snapshots.Labels, io.prometheus.metrics.model.snapshots.Exemplars, long)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) HistogramSnapshot$HistogramDataPointSnapshot(io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets, int, long, double, io.prometheus.metrics.model.snapshots.NativeHistogramBuckets, io.prometheus.metrics.model.snapshots.NativeHistogramBuckets, double, io.prometheus.metrics.model.snapshots.Labels, io.prometheus.metrics.model.snapshots.Exemplars, long, long)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) HistogramSnapshot$HistogramDataPointSnapshot(io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets, double, io.prometheus.metrics.model.snapshots.Labels, io.prometheus.metrics.model.snapshots.Exemplars, long)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.HistogramSnapshot$HistogramDataPointSnapshot$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets getClassicBuckets()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.NativeHistogramBuckets getNativeBucketsForNegativeValues()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.NativeHistogramBuckets getNativeBucketsForPositiveValues()
+ +++ NEW METHOD: PUBLIC(+) int getNativeSchema()
+ +++ NEW METHOD: PUBLIC(+) long getNativeZeroCount()
+ +++ NEW METHOD: PUBLIC(+) double getNativeZeroThreshold()
+ +++ NEW METHOD: PUBLIC(+) boolean hasClassicHistogramData()
+ +++ NEW METHOD: PUBLIC(+) boolean hasNativeHistogramData()
++++ NEW CLASS: PUBLIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.InfoSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricSnapshot
+ +++ NEW CONSTRUCTOR: PUBLIC(+) InfoSnapshot(io.prometheus.metrics.model.snapshots.MetricMetadata, java.util.Collection)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.InfoSnapshot$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) java.util.List getDataPoints()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.InfoSnapshot$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricSnapshot$Builder
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.InfoSnapshot build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.InfoSnapshot$Builder dataPoint(io.prometheus.metrics.model.snapshots.InfoSnapshot$InfoDataPointSnapshot)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.InfoSnapshot$Builder unit(io.prometheus.metrics.model.snapshots.Unit)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.InfoSnapshot$InfoDataPointSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.DataPointSnapshot
+ +++ NEW CONSTRUCTOR: PUBLIC(+) InfoSnapshot$InfoDataPointSnapshot(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) InfoSnapshot$InfoDataPointSnapshot(io.prometheus.metrics.model.snapshots.Labels, long)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.InfoSnapshot$InfoDataPointSnapshot$Builder builder()
++++ NEW CLASS: PUBLIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.Label (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.Comparable
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) Label(java.lang.String, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) int compareTo(io.prometheus.metrics.model.snapshots.Label)
+ +++ NEW METHOD: PUBLIC(+) boolean equals(java.lang.Object)
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getName()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getValue()
+ +++ NEW METHOD: PUBLIC(+) int hashCode()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String toString()
++++ NEW CLASS: PUBLIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.Labels (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.Comparable
+ +++ NEW INTERFACE: java.lang.Iterable
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.Labels EMPTY
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Labels add(java.lang.String, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.Labels$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) int compareTo(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) boolean contains(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) boolean equals(java.lang.Object)
+ +++ NEW METHOD: PUBLIC(+) java.lang.String get(java.lang.String)
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getName(int)
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getPrometheusName(int)
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getValue(int)
+ +++ NEW METHOD: PUBLIC(+) int hashCode()
+ +++ NEW METHOD: PUBLIC(+) boolean hasSameNames(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) boolean hasSameValues(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) boolean isEmpty()
+ +++ NEW METHOD: PUBLIC(+) java.util.Iterator iterator()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Labels merge(io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Labels merge(java.lang.String[], java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.Labels of(java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.Labels of(java.util.List, java.util.List)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.Labels of(java.lang.String[], java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) int size()
+ +++ NEW METHOD: PUBLIC(+) java.util.stream.Stream stream()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String toString()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.Labels$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Labels build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Labels$Builder label(java.lang.String, java.lang.String)
++++ NEW CLASS: PUBLIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$CounterBuilder counter(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$GaugeBuilder gauge(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) java.util.Set getLabelNames()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricMetadata getMetadata()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getPrometheusName()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.registry.MetricType getType()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$HistogramBuilder histogram(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$InfoBuilder info(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor of(io.prometheus.metrics.model.registry.MetricType, io.prometheus.metrics.model.snapshots.MetricMetadata)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor of(io.prometheus.metrics.model.registry.MetricType, io.prometheus.metrics.model.snapshots.MetricMetadata, java.util.Collection)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder> of(io.prometheus.metrics.model.registry.MetricType, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$StateSetBuilder stateSet(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$SummaryBuilder summary(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$UnknownBuilder unknown(java.lang.String)
++++ NEW CLASS: PUBLIC(+) ABSTRACT(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ GENERIC TEMPLATES: +++ T:io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricFamilyDescriptor$Builder()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder help(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder labelName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder labelNames(java.lang.String[])
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder labelNames(java.util.Collection)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder name(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder unit(io.prometheus.metrics.model.snapshots.Unit)
++++ NEW CLASS: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$CounterBuilder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricFamilyDescriptor$CounterBuilder()
++++ NEW CLASS: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$GaugeBuilder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricFamilyDescriptor$GaugeBuilder()
++++ NEW CLASS: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$HistogramBuilder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricFamilyDescriptor$HistogramBuilder()
++++ NEW CLASS: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$InfoBuilder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricFamilyDescriptor$InfoBuilder()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$InfoBuilder unit(io.prometheus.metrics.model.snapshots.Unit)
++++ NEW CLASS: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$StateSetBuilder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricFamilyDescriptor$StateSetBuilder()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$StateSetBuilder unit(io.prometheus.metrics.model.snapshots.Unit)
++++ NEW CLASS: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$SummaryBuilder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricFamilyDescriptor$SummaryBuilder()
++++ NEW CLASS: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$UnknownBuilder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor$Builder
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricFamilyDescriptor$UnknownBuilder()
++++ NEW CLASS: PUBLIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.MetricMetadata (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricMetadata(java.lang.String, java.lang.String, java.lang.String, io.prometheus.metrics.model.snapshots.Unit)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricMetadata(java.lang.String)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricMetadata(java.lang.String, java.lang.String, io.prometheus.metrics.model.snapshots.Unit)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricMetadata(java.lang.String, java.lang.String, java.lang.String, java.lang.String, io.prometheus.metrics.model.snapshots.Unit)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricMetadata(java.lang.String, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getExpositionBaseName()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getExpositionBasePrometheusName()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getHelp()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getName()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getOriginalName()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getPrometheusName()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Unit getUnit()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) boolean hasUnit()
++++ NEW CLASS: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.model.snapshots.MetricSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.util.List extends io.prometheus.metrics.model.snapshots.DataPointSnapshot> getDataPoints()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricMetadata getMetadata()
++++ NEW CLASS: PUBLIC(+) ABSTRACT(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshot$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ GENERIC TEMPLATES: +++ T:io.prometheus.metrics.model.snapshots.MetricSnapshot$Builder
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricSnapshot$Builder()
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.model.snapshots.MetricSnapshot build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshot$Builder help(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshot$Builder name(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshot$Builder unit(io.prometheus.metrics.model.snapshots.Unit)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.Iterable
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricSnapshots(java.util.Collection)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) MetricSnapshots(io.prometheus.metrics.model.snapshots.MetricSnapshot[])
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshot get(int)
+ +++ NEW METHOD: PUBLIC(+) java.util.Iterator iterator()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots of(io.prometheus.metrics.model.snapshots.MetricSnapshot[])
+ +++ NEW METHOD: PUBLIC(+) int size()
+ +++ NEW METHOD: PUBLIC(+) java.util.stream.Stream stream()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots build()
+ +++ NEW METHOD: PUBLIC(+) boolean containsMetricName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots$Builder metricSnapshot(io.prometheus.metrics.model.snapshots.MetricSnapshot)
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.model.snapshots.NativeHistogramBucket (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) NativeHistogramBucket(int, long)
+ +++ NEW METHOD: PUBLIC(+) int getBucketIndex()
+ +++ NEW METHOD: PUBLIC(+) long getCount()
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.model.snapshots.NativeHistogramBuckets (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.Iterable
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.NativeHistogramBuckets EMPTY
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.NativeHistogramBuckets$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) int getBucketIndex(int)
+ +++ NEW METHOD: PUBLIC(+) long getCount(int)
+ +++ NEW METHOD: PUBLIC(+) java.util.Iterator iterator()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.NativeHistogramBuckets of(int[], long[])
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.NativeHistogramBuckets of(java.util.List, java.util.List)
+ +++ NEW METHOD: PUBLIC(+) int size()
+ +++ NEW METHOD: PUBLIC(+) java.util.stream.Stream stream()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.NativeHistogramBuckets$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.NativeHistogramBuckets$Builder bucket(int, long)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.NativeHistogramBuckets build()
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.model.snapshots.PrometheusNaming (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) PrometheusNaming()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) java.lang.String escapeName(java.lang.String, io.prometheus.metrics.config.EscapingScheme)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) boolean isValidLabelName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) boolean isValidLegacyLabelName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) boolean isValidLegacyMetricName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) boolean isValidMetricName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) boolean isValidUnitName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) boolean needsEscaping(java.lang.String, io.prometheus.metrics.config.EscapingScheme)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) java.lang.String normalizeMetricName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) java.lang.String normalizeMetricName(java.lang.String, io.prometheus.metrics.model.snapshots.Unit)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) java.lang.String prometheusName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) java.lang.String sanitizeLabelName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) java.lang.String sanitizeMetricName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) java.lang.String sanitizeMetricName(java.lang.String, io.prometheus.metrics.model.snapshots.Unit)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) java.lang.String sanitizeUnitName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) java.lang.String validateMetricName(java.lang.String)
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) java.lang.String validateUnitName(java.lang.String)
+ +++ NEW ANNOTATION: javax.annotation.Nullable
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.model.snapshots.Quantile (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW CONSTRUCTOR: PUBLIC(+) Quantile(double, double)
+ +++ NEW METHOD: PUBLIC(+) double getQuantile()
+ +++ NEW METHOD: PUBLIC(+) double getValue()
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.model.snapshots.Quantiles (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.Iterable
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.Quantiles EMPTY
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.Quantiles$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Quantile get(int)
+ +++ NEW METHOD: PUBLIC(+) java.util.Iterator iterator()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.Quantiles of(java.util.List)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.Quantiles of(io.prometheus.metrics.model.snapshots.Quantile[])
+ +++ NEW METHOD: PUBLIC(+) int size()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.Quantiles$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Quantiles build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Quantiles$Builder quantile(io.prometheus.metrics.model.snapshots.Quantile)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Quantiles$Builder quantile(double, double)
++++ NEW CLASS: PUBLIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.StateSetSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricSnapshot
+ +++ NEW CONSTRUCTOR: PUBLIC(+) StateSetSnapshot(io.prometheus.metrics.model.snapshots.MetricMetadata, java.util.Collection)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.StateSetSnapshot$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) java.util.List getDataPoints()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.StateSetSnapshot$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricSnapshot$Builder
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.StateSetSnapshot build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.StateSetSnapshot$Builder dataPoint(io.prometheus.metrics.model.snapshots.StateSetSnapshot$StateSetDataPointSnapshot)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.StateSetSnapshot$Builder unit(io.prometheus.metrics.model.snapshots.Unit)
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.StateSetSnapshot$State (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getName()
+ +++ NEW METHOD: PUBLIC(+) boolean isTrue()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.StateSetSnapshot$StateSetDataPointSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: java.lang.Iterable
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.DataPointSnapshot
+ +++ NEW CONSTRUCTOR: PUBLIC(+) StateSetSnapshot$StateSetDataPointSnapshot(java.lang.String[], boolean[], io.prometheus.metrics.model.snapshots.Labels, long)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) StateSetSnapshot$StateSetDataPointSnapshot(java.lang.String[], boolean[], io.prometheus.metrics.model.snapshots.Labels)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.StateSetSnapshot$StateSetDataPointSnapshot$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) java.lang.String getName(int)
+ +++ NEW METHOD: PUBLIC(+) boolean isTrue(int)
+ +++ NEW METHOD: PUBLIC(+) java.util.Iterator iterator()
+ +++ NEW METHOD: PUBLIC(+) int size()
+ +++ NEW METHOD: PUBLIC(+) java.util.stream.Stream stream()
++++ NEW CLASS: PUBLIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.SummarySnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricSnapshot
+ +++ NEW CONSTRUCTOR: PUBLIC(+) SummarySnapshot(io.prometheus.metrics.model.snapshots.MetricMetadata, java.util.Collection)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.SummarySnapshot$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) java.util.List getDataPoints()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.SummarySnapshot$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricSnapshot$Builder
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.SummarySnapshot build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.SummarySnapshot$Builder dataPoint(io.prometheus.metrics.model.snapshots.SummarySnapshot$SummaryDataPointSnapshot)
++++ NEW CLASS: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.SummarySnapshot$SummaryDataPointSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.DistributionDataPointSnapshot
+ +++ NEW CONSTRUCTOR: PUBLIC(+) SummarySnapshot$SummaryDataPointSnapshot(long, double, io.prometheus.metrics.model.snapshots.Quantiles, io.prometheus.metrics.model.snapshots.Labels, io.prometheus.metrics.model.snapshots.Exemplars, long, long)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) SummarySnapshot$SummaryDataPointSnapshot(long, double, io.prometheus.metrics.model.snapshots.Quantiles, io.prometheus.metrics.model.snapshots.Labels, io.prometheus.metrics.model.snapshots.Exemplars, long)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.SummarySnapshot$SummaryDataPointSnapshot$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Quantiles getQuantiles()
++++ NEW CLASS: PUBLIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.Unit (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.Unit BYTES
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.Unit GRAMS
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.Unit METERS
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.Unit VOLTS
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.Unit SECONDS
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.Unit RATIO
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.Unit CELSIUS
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.Unit JOULES
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.Unit AMPERES
+ +++ NEW CONSTRUCTOR: PUBLIC(+) Unit(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) boolean equals(java.lang.Object)
+ +++ NEW METHOD: PUBLIC(+) int hashCode()
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) double kiloBytesToBytes(double)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) double millisToSeconds(long)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) double nanosToSeconds(long)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) double secondsToMillis(double)
+ +++ NEW METHOD: PUBLIC(+) java.lang.String toString()
++++ NEW CLASS: PUBLIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.UnknownSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricSnapshot
+ +++ NEW CONSTRUCTOR: PUBLIC(+) UnknownSnapshot(io.prometheus.metrics.model.snapshots.MetricMetadata, java.util.Collection)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.UnknownSnapshot$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) java.util.List getDataPoints()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.UnknownSnapshot$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.MetricSnapshot$Builder
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.UnknownSnapshot build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.UnknownSnapshot$Builder dataPoint(io.prometheus.metrics.model.snapshots.UnknownSnapshot$UnknownDataPointSnapshot)
++++ NEW CLASS: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.UnknownSnapshot$UnknownDataPointSnapshot (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: io.prometheus.metrics.model.snapshots.DataPointSnapshot
+ +++ NEW CONSTRUCTOR: PUBLIC(+) UnknownSnapshot$UnknownDataPointSnapshot(double, io.prometheus.metrics.model.snapshots.Labels, io.prometheus.metrics.model.snapshots.Exemplar, long)
+ +++ NEW CONSTRUCTOR: PUBLIC(+) UnknownSnapshot$UnknownDataPointSnapshot(double, io.prometheus.metrics.model.snapshots.Labels, io.prometheus.metrics.model.snapshots.Exemplar)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.UnknownSnapshot$UnknownDataPointSnapshot$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.Exemplar getExemplar()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) double getValue()
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-simpleclient-bridge.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-simpleclient-bridge.txt
new file mode 100644
index 000000000..bb1fb6594
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-simpleclient-bridge.txt
@@ -0,0 +1,16 @@
+Comparing source compatibility of prometheus-metrics-simpleclient-bridge-1.6.2-SNAPSHOT.jar against prometheus-metrics-simpleclient-bridge-1.6.1.jar
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.simpleclient.bridge.SimpleclientCollector (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW INTERFACE: io.prometheus.metrics.model.registry.MultiCollector
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.simpleclient.bridge.SimpleclientCollector$Builder builder(io.prometheus.metrics.config.PrometheusProperties)
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.simpleclient.bridge.SimpleclientCollector$Builder builder()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricSnapshots collect()
++++ NEW CLASS: PUBLIC(+) STATIC(+) io.prometheus.metrics.simpleclient.bridge.SimpleclientCollector$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.simpleclient.bridge.SimpleclientCollector build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.simpleclient.bridge.SimpleclientCollector$Builder collectorRegistry(io.prometheus.client.CollectorRegistry)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.simpleclient.bridge.SimpleclientCollector register()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.simpleclient.bridge.SimpleclientCollector register(io.prometheus.metrics.model.registry.PrometheusRegistry)
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-tracer-common.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-tracer-common.txt
new file mode 100644
index 000000000..6782f73f2
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-tracer-common.txt
@@ -0,0 +1,13 @@
+Comparing source compatibility of prometheus-metrics-tracer-common-1.6.2-SNAPSHOT.jar against prometheus-metrics-tracer-common-1.6.1.jar
++++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.prometheus.metrics.tracer.common.SpanContext (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) java.lang.String EXEMPLAR_ATTRIBUTE_NAME
+ +++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) java.lang.String EXEMPLAR_ATTRIBUTE_VALUE
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.lang.String getCurrentSpanId()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.lang.String getCurrentTraceId()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) boolean isCurrentSpanSampled()
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void markCurrentSpanAsExemplar()
+
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-tracer-initializer.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-tracer-initializer.txt
new file mode 100644
index 000000000..2d9b9b09d
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-tracer-initializer.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-tracer-initializer-1.6.2-SNAPSHOT.jar against prometheus-metrics-tracer-initializer-1.6.1.jar
+No changes.
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-tracer-otel-agent.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-tracer-otel-agent.txt
new file mode 100644
index 000000000..c44f14c31
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-tracer-otel-agent.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-tracer-otel-agent-1.6.2-SNAPSHOT.jar against prometheus-metrics-tracer-otel-agent-1.6.1.jar
+No changes.
diff --git a/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-tracer-otel.txt b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-tracer-otel.txt
new file mode 100644
index 000000000..b6419eebe
--- /dev/null
+++ b/docs/apidiffs/1.7.0_vs_1.6.1/prometheus-metrics-tracer-otel.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-tracer-otel-1.6.2-SNAPSHOT.jar against prometheus-metrics-tracer-otel-1.6.1.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-annotations.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-annotations.txt
new file mode 100644
index 000000000..36053089a
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-annotations.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-annotations-1.7.1-SNAPSHOT.jar against prometheus-metrics-annotations-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-config.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-config.txt
new file mode 100644
index 000000000..516d53a00
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-config.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-config-1.7.1-SNAPSHOT.jar against prometheus-metrics-config-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-core.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-core.txt
new file mode 100644
index 000000000..fa164a17e
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-core.txt
@@ -0,0 +1,19 @@
+Comparing source compatibility of prometheus-metrics-core-1.7.1-SNAPSHOT.jar against prometheus-metrics-core-1.7.0.jar
++++ NEW CLASS: PUBLIC(+) io.prometheus.metrics.core.exemplars.ExemplarLabelsSupplier (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) java.util.function.Supplier getExemplarLabelsSupplier()
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) void setExemplarLabelsSupplier(java.util.function.Supplier)
+*** MODIFIED CLASS: PUBLIC io.prometheus.metrics.core.exemplars.ExemplarSampler (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ +++ NEW CONSTRUCTOR: PUBLIC(+) ExemplarSampler(io.prometheus.metrics.core.exemplars.ExemplarSamplerConfig, io.prometheus.metrics.tracer.common.SpanContext, java.util.function.Supplier)
+*** MODIFIED CLASS: PUBLIC io.prometheus.metrics.core.metrics.Counter (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+*** MODIFIED CLASS: PUBLIC io.prometheus.metrics.core.metrics.Gauge (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+*** MODIFIED CLASS: PUBLIC io.prometheus.metrics.core.metrics.Histogram (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+*** MODIFIED CLASS: PUBLIC io.prometheus.metrics.core.metrics.Summary (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-common.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-common.txt
new file mode 100644
index 000000000..b88c7d665
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-common.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exporter-common-1.7.1-SNAPSHOT.jar against prometheus-metrics-exporter-common-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-httpserver.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-httpserver.txt
new file mode 100644
index 000000000..805828aef
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-httpserver.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exporter-httpserver-1.7.1-SNAPSHOT.jar against prometheus-metrics-exporter-httpserver-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-opentelemetry-otel-agent-resources.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-opentelemetry-otel-agent-resources.txt
new file mode 100644
index 000000000..7f7163856
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-opentelemetry-otel-agent-resources.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exporter-opentelemetry-otel-agent-resources-1.7.1-SNAPSHOT.jar against prometheus-metrics-exporter-opentelemetry-otel-agent-resources-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-opentelemetry-shaded.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-opentelemetry-shaded.txt
new file mode 100644
index 000000000..543c8e67e
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-opentelemetry-shaded.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exporter-opentelemetry-1.7.1-SNAPSHOT.jar against prometheus-metrics-exporter-opentelemetry-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-opentelemetry.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-opentelemetry.txt
new file mode 100644
index 000000000..764881093
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-opentelemetry.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exporter-opentelemetry-no-otel-1.7.1-SNAPSHOT.jar against prometheus-metrics-exporter-opentelemetry-no-otel-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-pushgateway.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-pushgateway.txt
new file mode 100644
index 000000000..4a4595d9c
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-pushgateway.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exporter-pushgateway-1.7.1-SNAPSHOT.jar against prometheus-metrics-exporter-pushgateway-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-servlet-jakarta.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-servlet-jakarta.txt
new file mode 100644
index 000000000..5c8102616
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-servlet-jakarta.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exporter-servlet-jakarta-1.7.1-SNAPSHOT.jar against prometheus-metrics-exporter-servlet-jakarta-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-servlet-javax.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-servlet-javax.txt
new file mode 100644
index 000000000..397f97388
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exporter-servlet-javax.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exporter-servlet-javax-1.7.1-SNAPSHOT.jar against prometheus-metrics-exporter-servlet-javax-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exposition-formats-shaded.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exposition-formats-shaded.txt
new file mode 100644
index 000000000..379ca0c42
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exposition-formats-shaded.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exposition-formats-1.7.1-SNAPSHOT.jar against prometheus-metrics-exposition-formats-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exposition-formats.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exposition-formats.txt
new file mode 100644
index 000000000..c8a2300d8
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exposition-formats.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exposition-formats-no-protobuf-1.7.1-SNAPSHOT.jar against prometheus-metrics-exposition-formats-no-protobuf-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exposition-textformats.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exposition-textformats.txt
new file mode 100644
index 000000000..df03a5870
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-exposition-textformats.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exposition-textformats-1.7.1-SNAPSHOT.jar against prometheus-metrics-exposition-textformats-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-instrumentation-caffeine.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-instrumentation-caffeine.txt
new file mode 100644
index 000000000..7eb8a50a8
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-instrumentation-caffeine.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-instrumentation-caffeine-1.7.1-SNAPSHOT.jar against prometheus-metrics-instrumentation-caffeine-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-instrumentation-dropwizard.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-instrumentation-dropwizard.txt
new file mode 100644
index 000000000..9c01af3a8
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-instrumentation-dropwizard.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-instrumentation-dropwizard-1.7.1-SNAPSHOT.jar against prometheus-metrics-instrumentation-dropwizard-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-instrumentation-dropwizard5.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-instrumentation-dropwizard5.txt
new file mode 100644
index 000000000..a2b6ad468
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-instrumentation-dropwizard5.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-instrumentation-dropwizard5-1.7.1-SNAPSHOT.jar against prometheus-metrics-instrumentation-dropwizard5-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-instrumentation-guava.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-instrumentation-guava.txt
new file mode 100644
index 000000000..371d0cb3b
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-instrumentation-guava.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-instrumentation-guava-1.7.1-SNAPSHOT.jar against prometheus-metrics-instrumentation-guava-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-instrumentation-jvm.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-instrumentation-jvm.txt
new file mode 100644
index 000000000..bc37dda75
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-instrumentation-jvm.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-instrumentation-jvm-1.7.1-SNAPSHOT.jar against prometheus-metrics-instrumentation-jvm-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-model.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-model.txt
new file mode 100644
index 000000000..f0ba4c4e8
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-model.txt
@@ -0,0 +1,17 @@
+Comparing source compatibility of prometheus-metrics-model-1.7.1-SNAPSHOT.jar against prometheus-metrics-model-1.7.0.jar
+*** MODIFIED CLASS: PUBLIC FINAL io.prometheus.metrics.model.snapshots.MetricMetadata (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ === UNCHANGED CONSTRUCTOR: PUBLIC MetricMetadata(java.lang.String, java.lang.String, java.lang.String, io.prometheus.metrics.model.snapshots.Unit)
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ === UNCHANGED CONSTRUCTOR: PUBLIC MetricMetadata(java.lang.String, java.lang.String, java.lang.String, java.lang.String, io.prometheus.metrics.model.snapshots.Unit)
+ +++ NEW ANNOTATION: java.lang.Deprecated
+ +++ NEW METHOD: PUBLIC(+) STATIC(+) io.prometheus.metrics.model.snapshots.MetricMetadata$Builder builder()
++++ NEW CLASS: PUBLIC(+) STATIC(+) FINAL(+) io.prometheus.metrics.model.snapshots.MetricMetadata$Builder (not serializable)
+ +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+ +++ NEW SUPERCLASS: java.lang.Object
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricMetadata build()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricMetadata$Builder counterSuffix(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricMetadata$Builder help(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricMetadata$Builder name(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.model.snapshots.MetricMetadata$Builder unit(io.prometheus.metrics.model.snapshots.Unit)
+
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-simpleclient-bridge.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-simpleclient-bridge.txt
new file mode 100644
index 000000000..9c2f8993d
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-simpleclient-bridge.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-simpleclient-bridge-1.7.1-SNAPSHOT.jar against prometheus-metrics-simpleclient-bridge-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-tracer-common.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-tracer-common.txt
new file mode 100644
index 000000000..260b1e4fb
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-tracer-common.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-tracer-common-1.7.1-SNAPSHOT.jar against prometheus-metrics-tracer-common-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-tracer-initializer.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-tracer-initializer.txt
new file mode 100644
index 000000000..7ffd7032c
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-tracer-initializer.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-tracer-initializer-1.7.1-SNAPSHOT.jar against prometheus-metrics-tracer-initializer-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-tracer-otel-agent.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-tracer-otel-agent.txt
new file mode 100644
index 000000000..a29c989fb
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-tracer-otel-agent.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-tracer-otel-agent-1.7.1-SNAPSHOT.jar against prometheus-metrics-tracer-otel-agent-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-tracer-otel.txt b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-tracer-otel.txt
new file mode 100644
index 000000000..3e6d87392
--- /dev/null
+++ b/docs/apidiffs/1.8.0_vs_1.7.0/prometheus-metrics-tracer-otel.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-tracer-otel-1.7.1-SNAPSHOT.jar against prometheus-metrics-tracer-otel-1.7.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-annotations.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-annotations.txt
new file mode 100644
index 000000000..a7fe17c13
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-annotations.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-annotations-1.8.1-SNAPSHOT.jar against prometheus-metrics-annotations-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-config.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-config.txt
new file mode 100644
index 000000000..60dad6c1f
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-config.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-config-1.8.1-SNAPSHOT.jar against prometheus-metrics-config-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-core.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-core.txt
new file mode 100644
index 000000000..ffb4a1d52
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-core.txt
@@ -0,0 +1,4 @@
+Comparing source compatibility of prometheus-metrics-core-1.8.1-SNAPSHOT.jar against prometheus-metrics-core-1.8.0.jar
+*** MODIFIED CLASS: PUBLIC io.prometheus.metrics.core.exemplars.ExemplarSampler (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-common.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-common.txt
new file mode 100644
index 000000000..daa5ef822
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-common.txt
@@ -0,0 +1,4 @@
+Comparing source compatibility of prometheus-metrics-exporter-common-1.8.1-SNAPSHOT.jar against prometheus-metrics-exporter-common-1.8.0.jar
+*** MODIFIED CLASS: PUBLIC io.prometheus.metrics.exporter.common.PrometheusScrapeHandler (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-httpserver.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-httpserver.txt
new file mode 100644
index 000000000..17fccaa45
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-httpserver.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exporter-httpserver-1.8.1-SNAPSHOT.jar against prometheus-metrics-exporter-httpserver-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-opentelemetry-otel-agent-resources.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-opentelemetry-otel-agent-resources.txt
new file mode 100644
index 000000000..10f0cbe92
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-opentelemetry-otel-agent-resources.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exporter-opentelemetry-otel-agent-resources-1.8.1-SNAPSHOT.jar against prometheus-metrics-exporter-opentelemetry-otel-agent-resources-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-opentelemetry-shaded.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-opentelemetry-shaded.txt
new file mode 100644
index 000000000..1b6d81f72
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-opentelemetry-shaded.txt
@@ -0,0 +1,20 @@
+Comparing source compatibility of prometheus-metrics-exporter-opentelemetry-1.8.1-SNAPSHOT.jar against prometheus-metrics-exporter-opentelemetry-1.8.0.jar
+***! MODIFIED CLASS: PUBLIC io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ ---! REMOVED CONSTRUCTOR: PUBLIC(-) OpenTelemetryExporter(io.prometheus.metrics.shaded.io_opentelemetry_2_28_1_alpha.sdk.metrics.export.MetricReader)
+*** MODIFIED CLASS: PUBLIC STATIC io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter buildAndStart()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder endpoint(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder header(java.lang.String, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder intervalSeconds(int)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder preserveNames(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder protocol(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder registry(io.prometheus.metrics.model.registry.PrometheusRegistry)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder resourceAttribute(java.lang.String, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceInstanceId(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceNamespace(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceVersion(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder timeoutSeconds(int)
+
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-opentelemetry.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-opentelemetry.txt
new file mode 100644
index 000000000..d0177b813
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-opentelemetry.txt
@@ -0,0 +1,20 @@
+Comparing source compatibility of prometheus-metrics-exporter-opentelemetry-no-otel-1.8.1-SNAPSHOT.jar against prometheus-metrics-exporter-opentelemetry-no-otel-1.8.0.jar
+***! MODIFIED CLASS: PUBLIC io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ ---! REMOVED CONSTRUCTOR: PUBLIC(-) OpenTelemetryExporter(io.opentelemetry.sdk.metrics.export.MetricReader)
+*** MODIFIED CLASS: PUBLIC STATIC io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter buildAndStart()
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder endpoint(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder header(java.lang.String, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder intervalSeconds(int)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder preserveNames(boolean)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder protocol(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder registry(io.prometheus.metrics.model.registry.PrometheusRegistry)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder resourceAttribute(java.lang.String, java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceInstanceId(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceName(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceNamespace(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder serviceVersion(java.lang.String)
+ +++ NEW METHOD: PUBLIC(+) io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter$Builder timeoutSeconds(int)
+
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-pushgateway.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-pushgateway.txt
new file mode 100644
index 000000000..9d500f981
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-pushgateway.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exporter-pushgateway-1.8.1-SNAPSHOT.jar against prometheus-metrics-exporter-pushgateway-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-servlet-jakarta.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-servlet-jakarta.txt
new file mode 100644
index 000000000..324db2bc5
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-servlet-jakarta.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exporter-servlet-jakarta-1.8.1-SNAPSHOT.jar against prometheus-metrics-exporter-servlet-jakarta-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-servlet-javax.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-servlet-javax.txt
new file mode 100644
index 000000000..38e76eeb4
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-exporter-servlet-javax.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exporter-servlet-javax-1.8.1-SNAPSHOT.jar against prometheus-metrics-exporter-servlet-javax-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-exposition-formats-shaded.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-exposition-formats-shaded.txt
new file mode 100644
index 000000000..a2c9bee8f
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-exposition-formats-shaded.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exposition-formats-1.8.1-SNAPSHOT.jar against prometheus-metrics-exposition-formats-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-exposition-formats.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-exposition-formats.txt
new file mode 100644
index 000000000..8dcdc54e9
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-exposition-formats.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exposition-formats-no-protobuf-1.8.1-SNAPSHOT.jar against prometheus-metrics-exposition-formats-no-protobuf-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-exposition-textformats.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-exposition-textformats.txt
new file mode 100644
index 000000000..d3e0a2581
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-exposition-textformats.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-exposition-textformats-1.8.1-SNAPSHOT.jar against prometheus-metrics-exposition-textformats-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-instrumentation-caffeine.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-instrumentation-caffeine.txt
new file mode 100644
index 000000000..2745dbce5
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-instrumentation-caffeine.txt
@@ -0,0 +1,6 @@
+Comparing source compatibility of prometheus-metrics-instrumentation-caffeine-1.8.1-SNAPSHOT.jar against prometheus-metrics-instrumentation-caffeine-1.8.0.jar
+=== UNCHANGED CLASS: PUBLIC io.prometheus.metrics.instrumentation.caffeine.CacheMetricsCollector (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ === UNCHANGED METHOD: PUBLIC com.github.benmanes.caffeine.cache.Cache,?>,?> removeCache(java.lang.String)
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-instrumentation-dropwizard.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-instrumentation-dropwizard.txt
new file mode 100644
index 000000000..f995c7443
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-instrumentation-dropwizard.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-instrumentation-dropwizard-1.8.1-SNAPSHOT.jar against prometheus-metrics-instrumentation-dropwizard-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-instrumentation-dropwizard5.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-instrumentation-dropwizard5.txt
new file mode 100644
index 000000000..ebd5b7f56
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-instrumentation-dropwizard5.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-instrumentation-dropwizard5-1.8.1-SNAPSHOT.jar against prometheus-metrics-instrumentation-dropwizard5-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-instrumentation-guava.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-instrumentation-guava.txt
new file mode 100644
index 000000000..bb87fbec9
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-instrumentation-guava.txt
@@ -0,0 +1,6 @@
+Comparing source compatibility of prometheus-metrics-instrumentation-guava-1.8.1-SNAPSHOT.jar against prometheus-metrics-instrumentation-guava-1.8.0.jar
+=== UNCHANGED CLASS: PUBLIC io.prometheus.metrics.instrumentation.guava.CacheMetricsCollector (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ === UNCHANGED METHOD: PUBLIC com.google.common.cache.Cache,?>,?> removeCache(java.lang.String)
+ +++ NEW ANNOTATION: javax.annotation.Nullable
+
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-instrumentation-jvm.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-instrumentation-jvm.txt
new file mode 100644
index 000000000..9160a6312
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-instrumentation-jvm.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-instrumentation-jvm-1.8.1-SNAPSHOT.jar against prometheus-metrics-instrumentation-jvm-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-model.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-model.txt
new file mode 100644
index 000000000..d298829ca
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-model.txt
@@ -0,0 +1,4 @@
+Comparing source compatibility of prometheus-metrics-model-1.8.1-SNAPSHOT.jar against prometheus-metrics-model-1.8.0.jar
+*** MODIFIED CLASS: PUBLIC FINAL io.prometheus.metrics.model.snapshots.Labels (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-simpleclient-bridge.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-simpleclient-bridge.txt
new file mode 100644
index 000000000..28f5e87ab
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-simpleclient-bridge.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-simpleclient-bridge-1.8.1-SNAPSHOT.jar against prometheus-metrics-simpleclient-bridge-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-tracer-common.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-tracer-common.txt
new file mode 100644
index 000000000..720c4c2c8
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-tracer-common.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-tracer-common-1.8.1-SNAPSHOT.jar against prometheus-metrics-tracer-common-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-tracer-initializer.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-tracer-initializer.txt
new file mode 100644
index 000000000..82cd884d7
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-tracer-initializer.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-tracer-initializer-1.8.1-SNAPSHOT.jar against prometheus-metrics-tracer-initializer-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-tracer-otel-agent.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-tracer-otel-agent.txt
new file mode 100644
index 000000000..c1ac9275d
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-tracer-otel-agent.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-tracer-otel-agent-1.8.1-SNAPSHOT.jar against prometheus-metrics-tracer-otel-agent-1.8.0.jar
+No changes.
diff --git a/docs/apidiffs/current_vs_latest/prometheus-metrics-tracer-otel.txt b/docs/apidiffs/current_vs_latest/prometheus-metrics-tracer-otel.txt
new file mode 100644
index 000000000..a95f29ea4
--- /dev/null
+++ b/docs/apidiffs/current_vs_latest/prometheus-metrics-tracer-otel.txt
@@ -0,0 +1,2 @@
+Comparing source compatibility of prometheus-metrics-tracer-otel-1.8.1-SNAPSHOT.jar against prometheus-metrics-tracer-otel-1.8.0.jar
+No changes.
diff --git a/docs/archetypes/default.md b/docs/archetypes/default.md
new file mode 100644
index 000000000..c6f3fcef6
--- /dev/null
+++ b/docs/archetypes/default.md
@@ -0,0 +1,5 @@
++++
+title = '{{ replace .File.ContentBaseName "-" " " | title }}'
+date = {{ .Date }}
+draft = true
++++
diff --git a/docs/content/_index.md b/docs/content/_index.md
new file mode 100644
index 000000000..c449482f3
--- /dev/null
+++ b/docs/content/_index.md
@@ -0,0 +1,59 @@
+---
+title: "client_java"
+---
+
+This is the documentation for the
+[Prometheus Java client library](https://github.com/prometheus/client_java)
+version 1.0.0 and higher.
+
+The main new features of the 1.0.0 release are:
+
+- **Prometheus native histograms:** Support for the new Prometheus histogram type.
+- **OpenTelemetry Exporter:** Push metrics in OTLP format to an OpenTelemetry endpoint.
+- **Runtime configuration:** Configure metrics, exporters, and more at runtime using a properties
+ file or system properties.
+
+
+
+**Documentation and Examples**
+
+In addition to this documentation page we created an
+[examples/](https://github.com/prometheus/client_java/tree/main/examples) directory with end-to-end
+scenarios (Docker compose) illustrating new features.
+
+**Performance Benchmarks**
+
+Initial performance benchmarks are looking great: All core metric types (including native
+histograms) allow concurrent updates, so if you instrument a performance critical Web service
+that utilizes all processor cores in parallel the metrics library will not introduce additional
+synchronization. See Javadoc comments in
+[benchmarks/](https://github.com/prometheus/client_java/tree/main/benchmarks) for benchmark results.
+
+**More Info**
+
+The Grafana Labs Blog has a post
+[Introducing the Prometheus Java Client 1.0.0](https://grafana.com/blog/2023/09/27/introducing-the-prometheus-java-client-1-0-0/)
+with a good overview of the release.
+
+There will also be a presentation at the [PromCon](https://promcon.io) conference on 29 Sep 2023.
+Tune in to the live stream on [https://promcon.io](https://promcon.io)
+or watch the recording on YouTube.
+
+**For users of the 0.16.0 version and older**
+
+
+
+Updating to the 1.0.0 version is a breaking change. However, there's a
+`prometheus-metrics-simpleclient-bridge` module available that allows you to use your existing
+simpleclient 0.16.0 metrics with the new 1.0.0 `PrometheusRegistry`.
+So you don't need to upgrade your instrumentation code, you can keep using your existing metrics.
+See the
+[compatibility > simpleclient](https://prometheus.github.io/client_java/migration/simpleclient/)
+in the menu on the left.
+
+The pre 1.0.0 code is now maintained on the
+[simpleclient](https://github.com/prometheus/client_java/tree/simpleclient) feature branch.
+
+Not all `simpleclient` modules from 0.16.0 are included in the initial 1.0.0 release.
+Over the next couple of weeks we will work on porting the remaining modules,
+starting with `pushgateway` and the Servlet filter.
diff --git a/docs/content/config/_index.md b/docs/content/config/_index.md
new file mode 100644
index 000000000..dc32223b0
--- /dev/null
+++ b/docs/content/config/_index.md
@@ -0,0 +1,4 @@
+---
+title: Config
+weight: 5
+---
diff --git a/docs/content/config/config.md b/docs/content/config/config.md
new file mode 100644
index 000000000..d3110939f
--- /dev/null
+++ b/docs/content/config/config.md
@@ -0,0 +1,220 @@
+---
+title: Config
+weight: 1
+---
+
+{{< toc >}}
+
+The Prometheus metrics library provides multiple options how to override configuration at runtime:
+
+- Properties file
+- System properties
+- Environment variables
+
+Example:
+
+```properties
+io.prometheus.exporter.http_server.port=9401
+```
+
+The property above changes the port for the
+[HTTPServer exporter]({{< relref "/exporters/httpserver.md" >}}) to _9401_.
+
+- **Properties file**: Add the line above to the properties file.
+- **System properties**: Use the command line parameter
+ `-Dio.prometheus.exporter.http_server.port=9401` when starting your application.
+- **Environment variables**: Set `IO_PROMETHEUS_EXPORTER_HTTP_SERVER_PORT=9401`
+
+## Location of the Properties File
+
+The properties file is searched in the following locations:
+
+- `/prometheus.properties` in the classpath. This is for bundling a properties file
+ with your application.
+- System property `-Dprometheus.config=/path/to/prometheus.properties`.
+- Environment variable `PROMETHEUS_CONFIG=/path/to/prometheus.properties`.
+
+## Property Naming Conventions
+
+Properties use **snake_case** format with underscores separating words
+(e.g., `http_server`, `exemplars_enabled`).
+
+For backward compatibility, camelCase property names are also supported in
+properties files and system properties, but snake_case is the preferred format.
+
+### Environment Variables
+
+Environment variables follow standard conventions:
+
+- All uppercase letters: `IO_PROMETHEUS_EXPORTER_HTTP_SERVER_PORT`
+- Underscores for all separators (both package and word boundaries)
+- Prefix must be `IO_PROMETHEUS`
+
+The library automatically converts environment variables to the correct property format.
+
+**Examples:**
+
+| Environment Variable | Property Equivalent |
+| --------------------------------------------- | --------------------------------------------- |
+| `IO_PROMETHEUS_METRICS_EXEMPLARS_ENABLED` | `io.prometheus.metrics.exemplars_enabled` |
+| `IO_PROMETHEUS_EXPORTER_HTTP_SERVER_PORT` | `io.prometheus.exporter.http_server.port` |
+| `IO_PROMETHEUS_METRICS_HISTOGRAM_NATIVE_ONLY` | `io.prometheus.metrics.histogram_native_only` |
+
+### Property Precedence
+
+When the same property is defined in multiple sources, the following precedence order applies
+(highest to lowest):
+
+1. **External properties** (passed explicitly via API)
+2. **Environment variables**
+3. **System properties** (command line `-D` flags)
+4. **Properties file** (from file or classpath)
+
+## Metrics Properties
+
+| Name | Javadoc | Note |
+| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
+| io.prometheus.metrics.exemplars_enabled | [Counter.Builder.withExemplars()]() | (1) (2) |
+| io.prometheus.metrics.histogram_native_only | [Histogram.Builder.nativeOnly()]() | (2) |
+| io.prometheus.metrics.histogram_classic_only | [Histogram.Builder.classicOnly()]() | (2) |
+| io.prometheus.metrics.histogram_classic_upper_bounds | [Histogram.Builder.classicUpperBounds()]() | (3) |
+| io.prometheus.metrics.histogram_native_initial_schema | [Histogram.Builder.nativeInitialSchema()]() | |
+| io.prometheus.metrics.histogram_native_min_zero_threshold | [Histogram.Builder.nativeMinZeroThreshold()]() | |
+| io.prometheus.metrics.histogram_native_max_zero_threshold | [Histogram.Builder.nativeMaxZeroThreshold()]() | |
+| io.prometheus.metrics.histogram_native_max_number_of_buckets | [Histogram.Builder.nativeMaxNumberOfBuckets()]() | |
+| io.prometheus.metrics.histogram_native_reset_duration_seconds | [Histogram.Builder.nativeResetDuration()]() | |
+| io.prometheus.metrics.summary_quantiles | [Summary.Builder.quantile(double)]() | (4) |
+| io.prometheus.metrics.summary_quantile_errors | [Summary.Builder.quantile(double, double)]() | (5) |
+| io.prometheus.metrics.summary_max_age_seconds | [Summary.Builder.maxAgeSeconds()]() | |
+| io.prometheus.metrics.summary_number_of_age_buckets | [Summary.Builder.numberOfAgeBuckets()]() | |
+
+### Notes
+
+
+
+(1) _withExemplars()_ and _withoutExemplars()_ are available for all metric types,
+not just for counters
+(2) Boolean value. Format: `property=true` or `property=false`.
+(3) Comma-separated list. Example: `.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10`.
+(4) Comma-separated list. Example: `0.5, 0.95, 0.99`.
+(5) Comma-separated list. If specified, the list must have the same length as
+`io.prometheus.metrics.summary_quantiles`. Example: `0.01, 0.005, 0.005`.
+
+
+
+There's one special feature about metric properties: You can set a property for one specific
+metric only by specifying the metric name. Example:
+Let's say you have a histogram named `latency_seconds`.
+
+```properties
+io.prometheus.metrics.histogram_classic_upper_bounds=0.2, 0.4, 0.8, 1.0
+```
+
+The line above sets histogram buckets for all histograms. However:
+
+```properties
+io.prometheus.metrics.latency_seconds.histogram_classic_upper_bounds=0.2, 0.4, 0.8, 1.0
+```
+
+The line above sets histogram buckets only for the histogram named `latency_seconds`.
+
+This works for all Metrics properties.
+
+## Exemplar Properties
+
+| Name | Javadoc | Note |
+| ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
+| io.prometheus.exemplars.min_retention_period_seconds | [ExemplarsProperties.getMinRetentionPeriodSeconds()]() | |
+| io.prometheus.exemplars.max_retention_period_seconds | [ExemplarsProperties.getMaxRetentionPeriodSeconds()]() | |
+| io.prometheus.exemplars.sample_interval_milliseconds | [ExemplarsProperties.getSampleIntervalMilliseconds()]() | |
+
+## Exporter Properties
+
+| Name | Javadoc | Note |
+| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
+| io.prometheus.exporter.include_created_timestamps | [ExporterProperties.getIncludeCreatedTimestamps()]() | (1) |
+| io.prometheus.exporter.exemplars_on_all_metric_types | [ExporterProperties.getExemplarsOnAllMetricTypes()]() | (1) |
+
+(1) Boolean value, `true` or `false`. Default see Javadoc.
+
+## OpenMetrics 2.0 Properties
+
+| Name | Javadoc | Note |
+| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
+| io.prometheus.openmetrics2.enabled | [OpenMetrics2Properties.getEnabled()]() | (1) |
+| io.prometheus.openmetrics2.content_negotiation | [OpenMetrics2Properties.getContentNegotiation()]() | (1) |
+| io.prometheus.openmetrics2.composite_values | [OpenMetrics2Properties.getCompositeValues()]() | (1) |
+| io.prometheus.openmetrics2.exemplar_compliance | [OpenMetrics2Properties.getExemplarCompliance()]() | (1) |
+| io.prometheus.openmetrics2.native_histograms | [OpenMetrics2Properties.getNativeHistograms()]() | (1) |
+
+(1) Boolean value, `true` or `false`. `enabled=true` switches OpenMetrics responses to the OM2
+writer, preserving metric names as written by the application. The other OM2 properties remain
+opt-in. All OpenMetrics 2.0 flags are experimental and default to `false`.
+
+## Exporter Filter Properties
+
+| Name | Javadoc | Note |
+| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
+| io.prometheus.exporter.filter.metric_name_must_be_equal_to | [ExporterFilterProperties.getAllowedMetricNames()]() | (1) |
+| io.prometheus.exporter.filter.metric_name_must_not_be_equal_to | [ExporterFilterProperties.getExcludedMetricNames()]() | (2) |
+| io.prometheus.exporter.filter.metric_name_must_start_with | [ExporterFilterProperties.getAllowedMetricNamePrefixes()]() | (3) |
+| io.prometheus.exporter.filter.metric_name_must_not_start_with | [ExporterFilterProperties.getExcludedMetricNamePrefixes()]() | (4) |
+
+
+
+(1) Comma separated list of allowed metric names. Only these metrics will be exposed.
+(2) Comma separated list of excluded metric names. These metrics will not be exposed.
+(3) Comma separated list of prefixes.
+Only metrics starting with these prefixes will be exposed.
+(4) Comma separated list of prefixes. Metrics starting with these prefixes will not be exposed.
+
+
+
+## Exporter HTTPServer Properties
+
+| Name | Javadoc | Note |
+| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ---- |
+| io.prometheus.exporter.http_server.port | [HTTPServer.Builder.port()]() | |
+
+## Exporter OpenTelemetry Properties
+
+| Name | Javadoc | Note |
+| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
+| io.prometheus.exporter.opentelemetry.protocol | [OpenTelemetryExporter.Builder.protocol()]() | (1) |
+| io.prometheus.exporter.opentelemetry.endpoint | [OpenTelemetryExporter.Builder.endpoint()]() | |
+| io.prometheus.exporter.opentelemetry.headers | [OpenTelemetryExporter.Builder.headers()]() | (2) |
+| io.prometheus.exporter.opentelemetry.interval_seconds | [OpenTelemetryExporter.Builder.intervalSeconds()]() | |
+| io.prometheus.exporter.opentelemetry.timeout_seconds | [OpenTelemetryExporter.Builder.timeoutSeconds()]() | |
+| io.prometheus.exporter.opentelemetry.service_name | [OpenTelemetryExporter.Builder.serviceName()]() | |
+| io.prometheus.exporter.opentelemetry.service_namespace | [OpenTelemetryExporter.Builder.serviceNamespace()]() | |
+| io.prometheus.exporter.opentelemetry.service_instance_id | [OpenTelemetryExporter.Builder.serviceInstanceId()]() | |
+| io.prometheus.exporter.opentelemetry.service_version | [OpenTelemetryExporter.Builder.serviceVersion()]() | |
+| io.prometheus.exporter.opentelemetry.resource_attributes | [OpenTelemetryExporter.Builder.resourceAttributes()]() | (3) |
+| io.prometheus.exporter.opentelemetry.preserve_names | [ExporterOpenTelemetryProperties.getPreserveNames()]() | (4) |
+
+
+
+(1) Protocol can be `grpc` or `http/protobuf`.
+(2) Format: `key1=value1,key2=value2`
+(3) Format: `key1=value1,key2=value2`
+(4) Boolean value, `true` or `false`. Default is `false` for backward compatibility.
+
+
+
+Many of these attributes can alternatively be configured via OpenTelemetry environment variables,
+like `OTEL_EXPORTER_OTLP_ENDPOINT`.
+The Prometheus metrics library has support for OpenTelemetry environment variables.
+See Javadoc for details.
+
+## Exporter PushGateway Properties
+
+| Name | Javadoc | Note |
+| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---- |
+| io.prometheus.exporter.pushgateway.address | [PushGateway.Builder.address()]() | |
+| io.prometheus.exporter.pushgateway.scheme | [PushGateway.Builder.scheme()]() | |
+| io.prometheus.exporter.pushgateway.job | [PushGateway.Builder.job()]() | |
+| io.prometheus.exporter.pushgateway.escaping_scheme | [PushGateway.Builder.escapingScheme()]() | (1) |
+
+(1) Escaping scheme can be `allow-utf-8`, `underscores`, `dots`, or `values` as described in
+[escaping schemes](https://github.com/prometheus/docs/blob/main/docs/instrumenting/escaping_schemes.md#escaping-schemes)
+and in the [Unicode documentation]({{< relref "../exporters/unicode.md" >}}).
diff --git a/docs/content/exporters/_index.md b/docs/content/exporters/_index.md
new file mode 100644
index 000000000..796db3ff3
--- /dev/null
+++ b/docs/content/exporters/_index.md
@@ -0,0 +1,4 @@
+---
+title: Exporters
+weight: 2
+---
diff --git a/docs/content/exporters/filter.md b/docs/content/exporters/filter.md
new file mode 100644
index 000000000..7d3e71d0e
--- /dev/null
+++ b/docs/content/exporters/filter.md
@@ -0,0 +1,30 @@
+---
+title: Filter
+weight: 3
+---
+
+All exporters support a `name[]` URL parameter for querying only specific metric names. Examples:
+
+- `/metrics?name[]=jvm_threads_current` will query the metric named `jvm_threads_current`.
+- `/metrics?name[]=jvm_threads_current&name[]=jvm_threads_daemon` will query two metrics,
+ `jvm_threads_current` and `jvm_threads_daemon`.
+
+Add the following to the scape job configuration in `prometheus.yml`
+to make the Prometheus server send the `name[]` parameter:
+
+```yaml
+params:
+ name[]:
+ - jvm_threads_current
+ - jvm_threads_daemon
+```
+
+## Query parameter limits
+
+For safety, exporters limit the query string to 65,536 characters and accept at most 1,024
+query parameters. The parameter limit counts every `&`-separated pair, including repeated
+parameters and empty pairs. These are fixed implementation limits and cannot be changed through
+runtime configuration.
+
+If a request exceeds either limit or contains invalid percent-encoding, the `/metrics` endpoint
+returns HTTP `400 Bad Request` with the plain-text response `Invalid query parameters`.
diff --git a/docs/content/exporters/formats.md b/docs/content/exporters/formats.md
new file mode 100644
index 000000000..b84222033
--- /dev/null
+++ b/docs/content/exporters/formats.md
@@ -0,0 +1,121 @@
+---
+title: Formats
+weight: 1
+---
+
+All exporters the following exposition formats:
+
+- OpenMetrics text format
+- Prometheus text format
+- Prometheus protobuf format
+
+Moreover, gzip encoding is supported for each of these formats.
+
+## OpenMetrics 2.0 Preview
+
+The library also includes an experimental OpenMetrics 2.0 writer. It is disabled by default and
+must be enabled explicitly. See [OpenMetrics 2.0 Preview]({{< relref "./openmetrics2.md" >}}).
+
+## Scraping with a Prometheus server
+
+The Prometheus server sends an `Accept` header to specify which format is requested. By default, the
+Prometheus server will scrape OpenMetrics text format with gzip encoding. If the Prometheus server
+is started with `--enable-feature=native-histograms`, it will scrape Prometheus protobuf format
+instead.
+
+## Viewing with a Web Browser
+
+If you view the `/metrics` endpoint with your Web browser you will see Prometheus text format. For
+quick debugging of the other formats, exporters provide a `debug` URL parameter:
+
+- `/metrics?debug=openmetrics`: View OpenMetrics text format.
+- `/metrics?debug=text`: View Prometheus text format.
+- `/metrics?debug=prometheus-protobuf`: View a text representation of the Prometheus protobuf
+ format.
+
+## Exclude protobuf exposition format
+
+You can exclude the protobuf exposition format by including the
+`prometheus-metrics-exposition-textformats` module and excluding the
+`prometheus-metrics-exposition-formats` module in your build file.
+
+For example, in Maven:
+
+```xml
+
+
+ io.prometheus
+ prometheus-metrics-exporter-httpserver
+
+
+ io.prometheus
+ prometheus-metrics-exposition-formats
+
+
+
+
+ io.prometheus
+ prometheus-metrics-exposition-textformats
+
+
+```
+
+## Exclude the shaded protobuf classes
+
+You can exclude the shaded protobuf classes including the
+`prometheus-metrics-exposition-formats-no-protobuf` module and excluding the
+`prometheus-metrics-exposition-formats` module in your build file.
+
+If you are using the PushGateway in a shaded jar with `minimizeJar=true`, do not exclude the protobuf classes.
+The PushGateway loads the protobuf writer implementation via reflection, so the full
+`prometheus-metrics-exposition-formats` artifact must stay on the classpath and the relevant
+packages must be preserved during shading. See the [PushGateway docs]({{< relref
+"./pushgateway.md" >}}) for the recommended Maven Shade configuration.
+
+For example, in Maven:
+
+```xml
+
+
+ io.prometheus
+ prometheus-metrics-exporter-httpserver
+
+
+ io.prometheus
+ prometheus-metrics-exposition-formats
+
+
+
+
+ io.prometheus
+ prometheus-metrics-exposition-formats-no-protobuf
+
+
+```
+
+## Exclude the shaded otel classes
+
+You can exclude the shaded otel classes including the
+`prometheus-metrics-exporter-opentelemetry-no-otel` module and excluding the
+`prometheus-metrics-exporter-opentelemetry` module in your build file.
+
+For example, in Maven:
+
+```xml
+
+
+ io.prometheus
+ prometheus-metrics-exporter-opentelemetry
+
+
+ io.prometheus
+ prometheus-metrics-exporter-opentelemetry
+
+
+
+
+ io.prometheus
+ prometheus-metrics-exporter-opentelemetry-no-otel
+
+
+```
diff --git a/docs/content/exporters/httpserver.md b/docs/content/exporters/httpserver.md
new file mode 100644
index 000000000..c0db181c9
--- /dev/null
+++ b/docs/content/exporters/httpserver.md
@@ -0,0 +1,43 @@
+---
+title: HTTPServer
+weight: 4
+---
+
+The `HTTPServer` is a standalone server for exposing a metric endpoint. A minimal example
+application for `HTTPServer` can be found in
+the [examples](https://github.com/prometheus/client_java/tree/1.0.x/examples) directory.
+
+```java
+HTTPServer server = HTTPServer.builder()
+ .port(9400)
+ .buildAndStart();
+```
+
+By default, `HTTPServer` binds to any IP address, you can change this with
+[hostname()]()
+or [inetAddress()]().
+
+`HTTPServer` is configured with three endpoints:
+
+- `/metrics` for Prometheus scraping.
+- `/-/healthy` for simple health checks.
+- `/` the default handler is a static HTML page.
+
+The default handler can be changed
+with [defaultHandler()]().
+
+## Authentication and HTTPS
+
+- [authenticator()]()
+ is for configuring authentication.
+- [httpsConfigurator()]()
+ is for configuring HTTPS.
+
+You can find an example of authentication and SSL in the
+[jmx_exporter](https://github.com/prometheus/jmx_exporter).
+
+## Properties
+
+See _config_ section (_todo_) on runtime configuration options.
+
+- `io.prometheus.exporter.http_server.port`: The port to bind to.
diff --git a/docs/content/exporters/openmetrics2.md b/docs/content/exporters/openmetrics2.md
new file mode 100644
index 000000000..607273881
--- /dev/null
+++ b/docs/content/exporters/openmetrics2.md
@@ -0,0 +1,129 @@
+---
+title: OpenMetrics 2.0 Preview
+weight: 2
+---
+
+The Prometheus Java client library includes experimental support for the OpenMetrics 2.0 text
+format.
+
+{{< hint type=warning >}}
+OpenMetrics 2.0 support is opt-in, experimental, and subject to change while the specification is
+still in draft.
+{{< /hint >}}
+
+{{< toc >}}
+
+## Enable OpenMetrics 2.0
+
+To switch OpenMetrics responses from the legacy OM1 writer to the OM2 writer, set:
+
+```properties
+io.prometheus.openmetrics2.enabled=true
+```
+
+Programmatic configuration:
+
+```java
+PrometheusProperties properties = PrometheusProperties.builder()
+ .enableOpenMetrics2(om2 -> {})
+ .build();
+```
+
+Enabling `enableOpenMetrics2(...)` also enables the top-level `enabled` flag automatically, so you
+only need to configure the sub-flags you want.
+
+With `enabled=true` alone:
+
+- OpenMetrics requests use the OM2 writer.
+- Metric names are preserved as written by the application.
+- Optional OM2 features such as `composite_values`, `exemplar_compliance`, and
+ `native_histograms` remain off.
+
+To enable OM2 only when the scraper explicitly requests `version=2.0.0`, set:
+
+```properties
+io.prometheus.openmetrics2.enabled=true
+io.prometheus.openmetrics2.content_negotiation=true
+```
+
+Programmatic equivalent:
+
+```java
+PrometheusProperties properties = PrometheusProperties.builder()
+ .enableOpenMetrics2(om2 -> om2.contentNegotiation(true))
+ .build();
+```
+
+## Naming Behavior
+
+OpenMetrics 2.0 removes OM1 suffix rewriting.
+
+- Counters do not get `_total` appended automatically.
+- Units do not get appended automatically.
+- Info metrics still end in `_info` because that is required by the spec.
+
+Examples:
+
+| Metric builder input | OM1 output | OM2 output |
+| ---------------------------------- | ----------------- | -------------- |
+| `Counter("events")` | `events_total` | `events` |
+| `Counter("events_total")` | `events_total` | `events_total` |
+| `Counter("req").unit(BYTES)` | `req_bytes_total` | `req` |
+| `Counter("req_bytes").unit(BYTES)` | `req_bytes_total` | `req_bytes` |
+| `Info("target")` | `target_info` | `target_info` |
+
+This means OpenMetrics 2.0 does not apply OM1 suffix behavior such as appending `_total` or unit
+suffixes, while the legacy OpenMetrics 1.0 and Prometheus text formats keep that existing suffix
+behavior.
+
+## Feature Flags
+
+All OpenMetrics 2.0 flags default to `false`.
+
+| Property | Effect |
+| ------------------------------------------------ | -------------------------------------------------------------------------------------- |
+| `io.prometheus.openmetrics2.enabled` | Metric names are preserved as written by the application. |
+| `io.prometheus.openmetrics2.content_negotiation` | Apply OM2 behavior only when the scraper requests `version=2.0.0`. |
+| `io.prometheus.openmetrics2.composite_values` | Emit histograms, summaries, and gauge histograms as single composite lines with `st@`. |
+| `io.prometheus.openmetrics2.exemplar_compliance` | Emit only OM2-compliant exemplars with timestamps. |
+| `io.prometheus.openmetrics2.native_histograms` | Emit OM2 native histogram text fields. |
+
+Enable all flags at once:
+
+```java
+PrometheusProperties properties = PrometheusProperties.builder()
+ .enableOpenMetrics2(om2 -> om2.enableAll())
+ .build();
+```
+
+Equivalent properties:
+
+```properties
+io.prometheus.openmetrics2.enabled=true
+io.prometheus.openmetrics2.content_negotiation=true
+io.prometheus.openmetrics2.composite_values=true
+io.prometheus.openmetrics2.exemplar_compliance=true
+io.prometheus.openmetrics2.native_histograms=true
+```
+
+## Content Negotiation
+
+If `content_negotiation=false`, OpenMetrics 2.0 behavior is applied to OpenMetrics responses even
+if the scraper requested OpenMetrics 1.0.
+
+If `content_negotiation=true`, OpenMetrics 2.0 behavior is only used when the scraper explicitly
+requests `version=2.0.0`. Otherwise the legacy OpenMetrics 1.0 response is returned.
+
+## Native Histograms
+
+With `io.prometheus.openmetrics2.native_histograms=true`, the OpenMetrics 2.0 writer emits native
+histogram fields such as:
+
+- `schema`
+- `zero_threshold`
+- `zero_count`
+- positive and negative spans
+- positive and negative buckets
+
+OM2 native histogram output can coexist with classic histogram buckets. When both are present, the
+native histogram sample is written first.
diff --git a/docs/content/exporters/pushgateway.md b/docs/content/exporters/pushgateway.md
new file mode 100644
index 000000000..755525dd9
--- /dev/null
+++ b/docs/content/exporters/pushgateway.md
@@ -0,0 +1,157 @@
+---
+title: Pushgateway
+weight: 6
+---
+
+The [Prometheus Pushgateway](https://github.com/prometheus/pushgateway) exists to allow ephemeral
+and batch jobs to expose their metrics to Prometheus.
+Since these kinds of jobs may not exist long enough to be scraped, they can instead push their
+metrics to a Pushgateway.
+The Pushgateway then exposes these metrics to Prometheus.
+
+The [PushGateway](/client_java/api/io/prometheus/metrics/exporter/pushgateway/PushGateway.html) Java
+class allows you to push metrics to a Prometheus Pushgateway.
+
+## Example
+
+{{< tabs "uniqueid" >}}
+{{< tab "Gradle" >}}
+
+```groovy
+implementation 'io.prometheus:prometheus-metrics-core:1.3.0'
+implementation 'io.prometheus:prometheus-metrics-exporter-pushgateway:1.3.0'
+```
+
+{{< /tab >}}
+{{< tab "Maven" >}}
+
+```xml
+
+ io.prometheus
+ prometheus-metrics-core
+ 1.3.0
+
+
+ io.prometheus
+ prometheus-metrics-exporter-pushgateway
+ 1.3.0
+
+```
+
+{{< /tab >}}
+{{< /tabs >}}
+
+```java
+public class ExampleBatchJob {
+
+ private static PushGateway pushGateway = PushGateway.builder()
+ .address("localhost:9091") // not needed as localhost:9091 is the default
+ .job("example")
+ .build();
+
+ private static Gauge dataProcessedInBytes = Gauge.builder()
+ .name("data_processed")
+ .help("data processed in the last batch job run")
+ .unit(Unit.BYTES)
+ .register();
+
+ public static void main(String[] args) throws Exception {
+ try {
+ long bytesProcessed = processData();
+ dataProcessedInBytes.set(bytesProcessed);
+ } finally {
+ pushGateway.push();
+ }
+ }
+
+ public static long processData() {
+ // Imagine a batch job here that processes data
+ // and returns the number of Bytes processed.
+ return 42;
+ }
+}
+```
+
+## Basic Auth
+
+The [PushGateway](/client_java/api/io/prometheus/metrics/exporter/pushgateway/PushGateway.html)
+supports basic authentication.
+
+```java
+PushGateway pushGateway = PushGateway.builder()
+ .job("example")
+ .basicAuth("my_user", "my_password")
+ .build();
+```
+
+The `PushGatewayTestApp` in `integration-tests/it-pushgateway` has a complete example of this.
+
+## Bearer token
+
+The [PushGateway](/client_java/api/io/prometheus/metrics/exporter/pushgateway/PushGateway.html)
+supports Bearer token authentication.
+
+```java
+PushGateway pushGateway = PushGateway.builder()
+ .job("example")
+ .bearerToken("my_token")
+ .build();
+```
+
+The `PushGatewayTestApp` in `integration-tests/it-pushgateway` has a complete example of this.
+
+## SSL
+
+The [PushGateway](/client_java/api/io/prometheus/metrics/exporter/pushgateway/PushGateway.html)
+supports SSL.
+
+```java
+PushGateway pushGateway = PushGateway.builder()
+ .job("example")
+ .scheme(Scheme.HTTPS)
+ .build();
+```
+
+However, this requires that the JVM can validate the server certificate.
+
+If you want to skip certificate verification, you need to provide your own
+`HttpConnectionFactory`. See the
+[API docs](/client_java/api/io/prometheus/metrics/exporter/pushgateway/HttpConnectionFactory.html).
+The `PushGatewayTestApp` in `integration-tests/it-pushgateway` has a complete example of this.
+
+## Configuration Properties
+
+The [PushGateway](/client_java/api/io/prometheus/metrics/exporter/pushgateway/PushGateway.html)
+supports a couple of properties that can be configured at runtime.
+See [config]({{< relref "../config/config.md" >}}).
+
+## Troubleshooting shaded jars
+
+If you build a shaded jar with the Maven Shade Plugin and `minimizeJar=true`, the PushGateway may
+fail at runtime with an error like this:
+
+```text
+java.lang.RuntimeException: class
+io.prometheus.metrics.expositionformats.PrometheusProtobufWriter is not available
+```
+
+This happens because the PushGateway loads the protobuf writer implementation via reflection. The
+Maven Shade Plugin does not detect that reflective usage during minimization, so it may strip the
+required classes from the final jar.
+
+To avoid this, keep the `prometheus-metrics-exposition-formats` artifact on the classpath and
+preserve the protobuf-related packages in your shade configuration:
+
+```xml
+
+
+ io.prometheus:prometheus-metrics-exposition-formats
+
+ io/prometheus/metrics/expositionformats/**
+ io/prometheus/metrics/shaded/**
+
+
+
+```
+
+Alternatively, disable jar minimization for the shaded build.
diff --git a/docs/content/exporters/servlet.md b/docs/content/exporters/servlet.md
new file mode 100644
index 000000000..8ddf3c13e
--- /dev/null
+++ b/docs/content/exporters/servlet.md
@@ -0,0 +1,47 @@
+---
+title: Servlet
+weight: 5
+---
+
+The
+[PrometheusMetricsServlet](/client_java/api/io/prometheus/metrics/exporter/servlet/jakarta/PrometheusMetricsServlet.html)
+is a [Jakarta Servlet](https://jakarta.ee/specifications/servlet/) for exposing a metric endpoint.
+
+## web.xml
+
+The old-school way of configuring a servlet is in a `web.xml` file:
+
+```xml
+
+
+
+ prometheus-metrics
+ io.prometheus.metrics.exporter.servlet.jakarta.PrometheusMetricsServlet
+
+
+ prometheus-metrics
+ /metrics
+
+
+```
+
+## Programmatic
+
+Today, most Servlet applications use an embedded Servlet container and configure Servlets
+programmatically rather than via `web.xml`.
+The API for that depends on the Servlet container.
+The [examples](https://github.com/prometheus/client_java/tree/1.0.x/examples) directory has an
+example of an embedded
+[Tomcat](https://tomcat.apache.org/) container with the
+[PrometheusMetricsServlet](/client_java/api/io/prometheus/metrics/exporter/servlet/jakarta/PrometheusMetricsServlet.html)
+configured.
+
+## Spring
+
+You can use
+the [PrometheusMetricsServlet](/client_java/api/io/prometheus/metrics/exporter/servlet/jakarta/PrometheusMetricsServlet.html)
+in Spring applications.
+See [our Spring doc]({{< relref "spring.md" >}}).
diff --git a/docs/content/exporters/spring.md b/docs/content/exporters/spring.md
new file mode 100644
index 000000000..80a7739fa
--- /dev/null
+++ b/docs/content/exporters/spring.md
@@ -0,0 +1,92 @@
+---
+title: Spring
+weight: 7
+---
+
+## Alternative: Use Spring's Built-in Metrics Library
+
+[Spring Boot](https://spring.io/projects/spring-boot) has a built-in metric library named
+[Micrometer](https://micrometer.io/), which supports Prometheus
+exposition format and can be set up in three simple steps:
+
+1. Add the `org.springframework.boot:spring-boot-starter-actuator` dependency.
+2. Add the `io.micrometer:micrometer-registry-prometheus` as a _runtime_ dependency.
+3. Enable the Prometheus endpoint by adding the line
+ `management.endpoints.web.exposure.include=prometheus` to `application.properties`.
+
+Note that Spring's default Prometheus endpoint is `/actuator/prometheus`, not `/metrics`.
+
+In most cases the built-in Spring metrics library will work for you and you don't need the
+Prometheus Java library in Spring applications.
+
+## Use the Prometheus Metrics Library in Spring
+
+However, you may have your reasons why you want to use the Prometheus metrics library in
+Spring anyway. Maybe you want full support for all Prometheus metric types,
+or you want to use the new Prometheus native histograms.
+
+The easiest way to use the Prometheus metrics library in Spring is to configure the
+[PrometheusMetricsServlet](/client_java/api/io/prometheus/metrics/exporter/servlet/jakarta/PrometheusMetricsServlet.html)
+to expose metrics.
+
+Dependencies:
+
+- `prometheus-metrics-core`: The core metrics library.
+- `prometheus-metrics-exporter-servlet-jakarta`: For providing the `/metrics` endpoint.
+- `prometheus-metrics-instrumentation-jvm`: Optional - JVM metrics
+
+The following is the complete source code of a Spring Boot REST service using
+the Prometheus metrics library:
+
+```java
+import io.prometheus.metrics.core.metrics.Counter;
+import io.prometheus.metrics.exporter.servlet.jakarta.PrometheusMetricsServlet;
+import io.prometheus.metrics.instrumentation.jvm.JvmMetrics;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.servlet.ServletRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@SpringBootApplication
+@RestController
+public class DemoApplication {
+
+ private static final Counter requestCount = Counter.builder()
+ .name("requests_total")
+ .register();
+
+ public static void main(String[] args) {
+ SpringApplication.run(DemoApplication.class, args);
+ JvmMetrics.builder().register();
+ }
+
+ @GetMapping("/")
+ public String sayHello() throws InterruptedException {
+ requestCount.inc();
+ return "Hello, World!\n";
+ }
+
+ @Bean
+ public ServletRegistrationBean createPrometheusMetricsEndpoint() {
+ return new ServletRegistrationBean<>(new PrometheusMetricsServlet(), "/metrics/*");
+ }
+}
+```
+
+The important part are the last three lines: They configure the
+[PrometheusMetricsServlet](/client_java/api/io/prometheus/metrics/exporter/servlet/jakarta/PrometheusMetricsServlet.html)
+to expose metrics on `/metrics`:
+
+```java
+
+@Bean
+public ServletRegistrationBean createPrometheusMetricsEndpoint() {
+ return new ServletRegistrationBean<>(new PrometheusMetricsServlet(), "/metrics/*");
+}
+```
+
+The example provides a _Hello, world!_ endpoint on
+[http://localhost:8080](http://localhost:8080), and Prometheus metrics on
+[http://localhost:8080/metrics](http://localhost:8080/metrics).
diff --git a/docs/content/exporters/unicode.md b/docs/content/exporters/unicode.md
new file mode 100644
index 000000000..026292c39
--- /dev/null
+++ b/docs/content/exporters/unicode.md
@@ -0,0 +1,34 @@
+---
+title: Unicode
+weight: 2
+---
+
+{{< hint type=warning >}}
+Unicode support is experimental, because [OpenMetrics specification](https://openmetrics.io/) is not
+updated yet to support Unicode characters in metric and label names.
+{{< /hint >}}
+
+The Prometheus Java client library allows all Unicode characters, that can be encoded as UTF-8.
+
+At scrape time, some characters are replaced based on the `encoding` header according
+to
+the [Escaping scheme](https://github.com/prometheus/docs/blob/main/docs/instrumenting/escaping_schemes.md).
+
+For example, if you use the `underscores` escaping scheme, dots in metric and label names are
+replaced with underscores, so that the metric name `http.server.duration` becomes
+`http_server_duration`.
+
+Prometheus servers that do not support Unicode at all will not pass the `encoding` header, and the
+Prometheus Java client library will replace dots, as well as any character that is not in the legacy
+character set (`a-zA-Z0-9_:`), with underscores by default.
+
+When `escaping=allow-utf-8` is passed, add valid UTF-8 characters to the metric and label names
+without replacing them. This allows you to use dots in metric and label names, as well as
+other UTF-8 characters, without any replacements.
+
+## PushGateway
+
+When using the [Pushgateway]({{< relref "pushgateway.md" >}}), Unicode support has to be enabled
+explicitly by setting `io.prometheus.exporter.pushgateway.escapingScheme` to `allow-utf-8` in the
+Pushgateway configuration file - see
+[Pushgateway configuration]({{< relref "/config/config.md#exporter-pushgateway-properties" >}})
diff --git a/docs/content/getting-started/_index.md b/docs/content/getting-started/_index.md
new file mode 100644
index 000000000..427269117
--- /dev/null
+++ b/docs/content/getting-started/_index.md
@@ -0,0 +1,4 @@
+---
+title: Getting Started
+weight: 1
+---
diff --git a/docs/content/getting-started/callbacks.md b/docs/content/getting-started/callbacks.md
new file mode 100644
index 000000000..514d74c2a
--- /dev/null
+++ b/docs/content/getting-started/callbacks.md
@@ -0,0 +1,62 @@
+---
+title: Callbacks
+weight: 5
+---
+
+The section on [metric types]({{< relref "metric-types.md" >}})
+showed how to use metrics that actively maintain their state.
+
+This section shows how to create callback-based metrics, i.e. metrics that invoke a callback
+at scrape time to get the current values.
+
+For example, let's assume we have two instances of a `Cache`, a `coldCache` and a `hotCache`.
+The following implements a callback-based `cache_size_bytes` metric:
+
+```java
+Cache coldCache = new Cache();
+Cache hotCache = new Cache();
+
+GaugeWithCallback.builder()
+ .name("cache_size_bytes")
+ .help("Size of the cache in Bytes.")
+ .unit(Unit.BYTES)
+ .labelNames("state")
+ .callback(callback -> {
+ callback.call(coldCache.sizeInBytes(), "cold");
+ callback.call(hotCache.sizeInBytes(), "hot");
+ })
+ .register();
+```
+
+The resulting text format looks like this:
+
+```text
+# TYPE cache_size_bytes gauge
+# UNIT cache_size_bytes bytes
+# HELP cache_size_bytes Size of the cache in Bytes.
+cache_size_bytes{state="cold"} 78.0
+cache_size_bytes{state="hot"} 83.0
+```
+
+Better examples of callback metrics can be found in the `prometheus-metrics-instrumentation-jvm`
+module.
+
+The available callback metric types are:
+
+- `GaugeWithCallback` for gauges.
+- `CounterWithCallback` for counters.
+- `SummaryWithCallback` for summaries.
+
+The API for gauges and counters is very similar. For summaries the callback has a few more
+parameters, because it accepts a count, a sum, and quantiles:
+
+```java
+SummaryWithCallback.builder()
+ .name("example_callback_summary")
+ .help("help message.")
+ .labelNames("status")
+ .callback(callback -> {
+ callback.call(cache.getCount(), cache.getSum(), Quantiles.EMPTY, "ok");
+ })
+ .register();
+```
diff --git a/docs/content/getting-started/labels.md b/docs/content/getting-started/labels.md
new file mode 100644
index 000000000..1cbae13d7
--- /dev/null
+++ b/docs/content/getting-started/labels.md
@@ -0,0 +1,153 @@
+---
+title: Labels
+weight: 3
+---
+
+The following shows an example of a Prometheus metric in text format:
+
+```text
+# HELP payments_total total number of payments
+# TYPE payments_total counter
+payments_total{status="error",type="paypal"} 1.0
+payments_total{status="success",type="credit card"} 3.0
+payments_total{status="success",type="paypal"} 2.0
+```
+
+The example shows a counter metric named `payments_total` with two labels: `status` and `type`.
+Each individual data point (each line in text format) is identified by the unique combination of
+its metric name and its label name/value pairs.
+
+## Creating a Metric with Labels
+
+Labels are supported for all metric types. We are using counters in this example, however the
+`labelNames()` and `labelValues()` methods are the same for other metric types.
+
+The following code creates the counter above.
+
+```java
+Counter counter = Counter.builder()
+ .name("payments_total")
+ .help("total number of payments")
+ .labelNames("type", "status")
+ .register();
+
+counter.labelValues("credit card", "success").inc(3.0);
+counter.labelValues("paypal", "success").inc(2.0);
+counter.labelValues("paypal", "error").inc(1.0);
+```
+
+The label names have to be specified when the metric is created and cannot change. The label values
+are created on demand when values are observed.
+
+## Creating a Metric without Labels
+
+Labels are optional. The following example shows a metric without labels:
+
+```java
+Counter counter = Counter.builder()
+ .name("payments_total")
+ .help("total number of payments")
+ .register();
+
+counter.inc(3.0);
+```
+
+## Cardinality Explosion
+
+Each combination of label names and values will result in a new data point, i.e. a new line in text
+format.
+Therefore, a good label should have only a small number of possible values.
+If you select labels with many possible values, like unique IDs or timestamps,
+you may end up with an enormous number of data points.
+This is called cardinality explosion.
+
+Here's a bad example, don't do this:
+
+```java
+Counter loginCount = Counter.builder()
+ .name("logins_total")
+ .help("total number of logins")
+ .labelNames("user_id", "timestamp") // not a good idea, this will result in too many data points
+ .register();
+
+String userId = UUID.randomUUID().toString();
+String timestamp = Long.toString(System.currentTimeMillis());
+
+loginCount.labelValues(userId, timestamp).inc();
+```
+
+## Initializing Label Values
+
+If you register a metric without labels, it will show up immediately with initial value of zero.
+
+However, metrics with labels only show up after the label values are first used. In the example
+above
+
+```java
+counter.labelValues("paypal", "error").inc();
+```
+
+The data point
+
+```text
+payments_total{status="error",type="paypal"} 1.0
+```
+
+will jump from non-existent to value 1.0. You will never see it with value 0.0.
+
+This is usually not an issue. However, if you find this annoying and want to see all possible label
+values from the start, you can initialize label values with `initLabelValues()` like this:
+
+```java
+Counter counter = Counter.builder()
+ .name("payments_total")
+ .help("total number of payments")
+ .labelNames("type", "status")
+ .register();
+
+counter.initLabelValues("credit card", "success");
+counter.initLabelValues("credit card", "error");
+counter.initLabelValues("paypal", "success");
+counter.initLabelValues("paypal", "error");
+```
+
+Now the four combinations will be visible from the start with initial value zero.
+
+```text
+# HELP payments_total total number of payments
+# TYPE payments_total counter
+payments_total{status="error",type="credit card"} 0.0
+payments_total{status="error",type="paypal"} 0.0
+payments_total{status="success",type="credit card"} 0.0
+payments_total{status="success",type="paypal"} 0.0
+```
+
+## Expiring Unused Label Values
+
+There is no automatic expiry of unused label values (yet). Once a set of label values is used, it
+will remain there forever.
+
+However, you can programmatically remove label values like this:
+
+```java
+counter.remove("paypal", "error");
+counter.remove("paypal", "success");
+```
+
+## Const Labels
+
+If you have labels values that never change, you can specify them in the builder as `constLabels()`:
+
+```java
+Counter counter = Counter.builder()
+ .name("payments_total")
+ .help("total number of payments")
+ .constLabels(Labels.of("env", "dev"))
+ .labelNames("type", "status")
+ .register();
+```
+
+However, most use cases for `constLabels()` are better covered by target labels set by the scraping
+Prometheus server,
+or by one specific metric (e.g. a `build_info` or a `machine_role` metric). See also
+[target labels, not static scraped labels](https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels).
diff --git a/docs/content/getting-started/metric-types.md b/docs/content/getting-started/metric-types.md
new file mode 100644
index 000000000..752205107
--- /dev/null
+++ b/docs/content/getting-started/metric-types.md
@@ -0,0 +1,373 @@
+---
+title: "Metric Types"
+weight: 4
+---
+
+The Prometheus Java metrics library implements the metric types defined in
+the [OpenMetrics](https://openmetrics.io) standard:
+
+{{< toc >}}
+
+## Counter
+
+Counter is the most common and useful metric type. Counters can only increase, but never decrease.
+In the Prometheus query language,
+the [rate()](https://prometheus.io/docs/prometheus/latest/querying/functions/#rate) function is
+often used for counters to calculate the average increase per second.
+
+{{< hint type=note >}}
+Counter values do not need to be integers. In many cases counters represent a number of events (like
+the number of requests), and in that case the counter value is an integer. However, counters can
+also be used for something like "total time spent doing something" in which case the counter value
+is a floating point number.
+{{< /hint >}}
+
+Here's an example of a counter:
+
+```java
+Counter serviceTimeSeconds = Counter.builder()
+ .name("service_time_seconds_total")
+ .help("total time spent serving requests")
+ .unit(Unit.SECONDS)
+ .register();
+
+serviceTimeSeconds.inc(Unit.millisToSeconds(200));
+```
+
+The resulting counter has the value `0.2`. As `SECONDS` is the standard time unit in Prometheus, the
+`Unit` utility class has methods to convert other time units to seconds.
+
+For the default OpenMetrics 1.0 and Prometheus text formats, counters are exposed with the
+`_total` suffix. You can name a counter either `service_time_seconds` or
+`service_time_seconds_total`; the exposed name will be `service_time_seconds_total` in both cases.
+
+The experimental OpenMetrics 2.0 writer behaves differently: It preserves metric names instead of
+appending `_total` or unit suffixes automatically. In OpenMetrics 2.0, `_total` is recommended for
+counters, but not enforced by the Java client.
+
+## Gauge
+
+Gauges are current measurements, such as the current temperature in Celsius.
+
+```java
+Gauge temperature = Gauge.builder()
+ .name("temperature_celsius")
+ .help("current temperature")
+ .labelNames("location")
+ .unit(Unit.CELSIUS)
+ .register();
+
+temperature.labelValues("Berlin").set(22.3);
+```
+
+## Histogram
+
+Histograms are for observing distributions, like latency distributions for HTTP services or the
+distribution of request sizes.
+Unlike with counters and gauges, each histogram data point has a complex data structure representing
+different aspects of the distribution:
+
+- Count: The total number of observations.
+- Sum: The sum of all observed values, e.g. the total time spent serving requests.
+- Buckets: The histogram buckets representing the distribution.
+
+Prometheus supports two flavors of histograms:
+
+- Classic histograms: Bucket boundaries are explicitly defined when the histogram is created.
+- Native histograms (exponential histograms): Infinitely many virtual buckets.
+
+By default, histograms maintain both flavors. Which one is used depends on the scrape request from
+the Prometheus server.
+
+- By default, the Prometheus server will scrape metrics in OpenMetrics format and get the classic
+ histogram flavor.
+- If the Prometheus server is started with `--enable-feature=native-histograms`, it will request
+ metrics in Prometheus protobuf format and ingest the native histogram.
+- If the Prometheus server is started with `--enable-feature=native-histogram` and the scrape config
+ has the option `scrape_classic_histograms: true`, it will request metrics in Prometheus protobuf
+ format and ingest both, the classic and the native flavor. This is great for migrating from
+ classic histograms to native histograms.
+
+See [examples/example-native-histogram](https://github.com/prometheus/client_java/tree/1.0.x/examples/example-native-histogram)
+for an example.
+
+```java
+Histogram duration = Histogram.builder()
+ .name("http_request_duration_seconds")
+ .help("HTTP request service time in seconds")
+ .unit(Unit.SECONDS)
+ .labelNames("method", "path", "status_code")
+ .register();
+
+long start = System.nanoTime();
+// do something
+duration.labelValues("GET", "/", "200").observe(Unit.nanosToSeconds(System.nanoTime() - start));
+```
+
+Histograms implement
+the [TimerApi](/client_java/api/io/prometheus/metrics/core/datapoints/TimerApi.html) interface,
+which provides convenience methods for measuring durations.
+
+The histogram builder provides a lot of configuration for fine-tuning the histogram behavior. In
+most cases you don't need them, defaults are good. The following is an incomplete list showing the
+most important options:
+
+- `nativeOnly()` / `classicOnly()`: Create a histogram with one representation only.
+- `classicUpperBounds(...)`: Set the classic bucket upper boundaries. Default bucket upper
+ boundaries are `.005`, `.01`, `.025`, `.05`, `.1`, `.25`, `.5`, `1`, `2.5`, `5`, `and 10`. The
+ default bucket boundaries are designed for measuring request durations in seconds.
+- `nativeMaxNumberOfBuckets()`: Upper limit for the number of native histogram buckets.
+ Default is 160. When the maximum is reached, the native histogram automatically
+ reduces resolution to stay below the limit.
+
+See Javadoc
+for [Histogram.Builder](/client_java/api/io/prometheus/metrics/core/metrics/Histogram.Builder.html)
+for a complete list of options. Some options can be configured at runtime,
+see [config]({{< relref "../config/config.md" >}}).
+
+### Custom Bucket Boundaries
+
+The default bucket boundaries are designed for measuring request durations in seconds. For other
+use cases, you may want to define custom bucket boundaries. The histogram builder provides three
+methods for this:
+
+
+
+**1. Arbitrary Custom Boundaries**
+
+Use `classicUpperBounds(...)` to specify arbitrary bucket boundaries:
+
+```java
+Histogram responseSize = Histogram.builder()
+ .name("http_response_size_bytes")
+ .help("HTTP response size in bytes")
+ .classicUpperBounds(100, 1000, 10000, 100000, 1000000) // bytes
+ .register();
+```
+
+**2. Linear Boundaries**
+
+Use `classicLinearUpperBounds(start, width, count)` for equal-width buckets:
+
+```java
+Histogram queueSize = Histogram.builder()
+ .name("queue_size")
+ .help("Number of items in queue")
+ .classicLinearUpperBounds(10, 10, 10) // 10, 20, 30, ..., 100
+ .register();
+```
+
+**3. Exponential Boundaries**
+
+
+
+Use `classicExponentialUpperBounds(start, factor, count)` for exponential growth:
+
+```java
+Histogram dataSize = Histogram.builder()
+ .name("data_size_bytes")
+ .help("Data size in bytes")
+ .classicExponentialUpperBounds(100, 10, 5) // 100, 1k, 10k, 100k, 1M
+ .register();
+```
+
+### Native Histograms with Custom Buckets (NHCB)
+
+Prometheus supports a special mode called Native Histograms with Custom Buckets (NHCB) that uses
+schema -53. In this mode, custom bucket boundaries from classic histograms are preserved when
+converting to native histograms.
+
+The Java client library automatically supports NHCB:
+
+1. By default, histograms maintain both classic (with custom buckets) and native representations
+2. The classic representation with custom buckets is exposed to Prometheus
+3. Prometheus servers can convert these to NHCB upon ingestion when configured with the
+ `convert_classic_histograms_to_nhcb` scrape option
+
+Example:
+
+```java
+// This histogram will work seamlessly with NHCB
+Histogram apiLatency = Histogram.builder()
+ .name("api_request_duration_seconds")
+ .help("API request duration")
+ .classicUpperBounds(0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0) // custom boundaries
+ .register();
+```
+
+On the Prometheus side, configure the scrape job:
+
+```yaml
+scrape_configs:
+ - job_name: "my-app"
+ scrape_protocols: ["PrometheusProto"]
+ convert_classic_histograms_to_nhcb: true
+ static_configs:
+ - targets: ["localhost:9400"]
+```
+
+{{< hint type=note >}}
+NHCB is useful when:
+
+- You need precise bucket boundaries for your specific use case
+- You're migrating from classic histograms and want to preserve bucket boundaries
+- Exponential bucketing from standard native histograms isn't a good fit for your distribution
+ {{< /hint >}}
+
+See [examples/example-custom-buckets](https://github.com/prometheus/client_java/tree/main/examples/example-custom-buckets)
+for a complete example with Prometheus and Grafana.
+
+Histograms and summaries are both used for observing distributions. Therefore, the both implement
+the `DistributionDataPoint` interface. Using the `DistributionDataPoint` interface directly gives
+you the option to switch between histograms and summaries later with minimal code changes.
+
+Example of using the `DistributionDataPoint` interface for a histogram without labels:
+
+```java
+DistributionDataPoint eventDuration = Histogram.builder()
+ .name("event_duration_seconds")
+ .help("event duration in seconds")
+ .unit(Unit.SECONDS)
+ .register();
+
+// The following still works perfectly fine if eventDuration
+// is backed by a summary rather than a histogram.
+eventDuration.observe(0.2);
+```
+
+Example of using the `DistributionDataPoint` interface for a histogram with labels:
+
+```java
+Histogram eventDuration = Histogram.builder()
+ .name("event_duration_seconds")
+ .help("event duration in seconds")
+ .labelNames("status")
+ .unit(Unit.SECONDS)
+ .register();
+
+DistributionDataPoint successfulEvents = eventDuration.labelValues("ok");
+DistributionDataPoint erroneousEvents = eventDuration.labelValues("error");
+
+// Like in the example above, the following still works perfectly fine
+// if the successfulEvents and erroneousEvents are backed by a summary rather than a histogram.
+successfulEvents.observe(0.7);
+erroneousEvents.observe(0.2);
+```
+
+## Summary
+
+Like histograms, summaries are for observing distributions. Each summary data point has a count and
+a sum like a histogram data point.
+However, rather than histogram buckets summaries maintain quantiles.
+
+```java
+Summary requestLatency = Summary.builder()
+ .name("request_latency_seconds")
+ .help("Request latency in seconds.")
+ .unit(Unit.SECONDS)
+ .quantile(0.5, 0.01)
+ .quantile(0.95, 0.005)
+ .quantile(0.99, 0.005)
+ .labelNames("status")
+ .register();
+
+requestLatency.labelValues("ok").observe(2.7);
+```
+
+The example above creates a summary with the 50th percentile (median), the 95th percentile, and the
+99th percentile. Quantiles are optional, you can create a summary without quantiles if all you need
+is the count and the sum.
+
+{{< hint type=note >}}
+The terms "percentile" and "quantile" mean the same thing. We use percentile when we express it as a
+number in [0, 100], and we use quantile when we express it as a number in [0.0, 1.0].
+{{< /hint >}}
+
+The second parameter to `quantile()` is the maximum acceptable error. The call
+`.quantile(0.5, 0.01)` means that the actual quantile is somewhere in [0.49, 0.51]. Higher precision
+means higher memory usage.
+
+The 0.0 quantile (min value) and the 1.0 quantile (max value) are special cases because you can get
+the precise values (error 0.0) with almost no memory overhead.
+
+Quantile values are calculated based on a 5 minutes moving time window. The default time window can
+be changed with `maxAgeSeconds()` and `numberOfAgeBuckets()`.
+
+Some options can be configured at runtime, see [config]({{< relref "../config/config.md" >}}).
+
+In general you should prefer histograms over summaries. The Prometheus query language has a
+function [histogram_quantile()](https://prometheus.io/docs/prometheus/latest/querying/functions/#histogram_quantile)
+for calculating quantiles from histograms. The advantage of query-time quantile calculation is that
+you can aggregate histograms before calculating the quantile. With summaries you must use the
+quantile with all its labels as it is.
+
+## Info
+
+Info metrics are used to expose textual information which should not change during process lifetime.
+The value of an Info metric is always `1`.
+
+```java
+Info info = Info.builder()
+ .name("jvm_runtime_info")
+ .help("JVM runtime info")
+ .labelNames("version", "vendor", "runtime")
+ .register();
+
+String version = System.getProperty("java.runtime.version", "unknown");
+String vendor = System.getProperty("java.vm.vendor", "unknown");
+String runtime = System.getProperty("java.runtime.name", "unknown");
+
+info.setLabelValues(version, vendor, runtime);
+```
+
+The info above looks as follows in OpenMetrics text format:
+
+```text
+# TYPE jvm_runtime info
+# HELP jvm_runtime JVM runtime info
+jvm_runtime_info{runtime="OpenJDK Runtime Environment",vendor="Oracle Corporation",version="1.8.0_382-b05"} 1
+```
+
+The example is taken from the `prometheus-metrics-instrumentation-jvm` module, so if you have
+`JvmMetrics` registered you should have a `jvm_runtime_info` metric out-of-the-box.
+
+As defined in [OpenMetrics](https://openmetrics.io/), info metric names must have the `_info`
+suffix. If you create a counter without the `_info` suffix the suffix will be appended
+automatically.
+
+## StateSet
+
+StateSet are a niche metric type in the OpenMetrics standard that is rarely used. The main use case
+is to signal which feature flags are enabled.
+
+```java
+StateSet stateSet = StateSet.builder()
+ .name("feature_flags")
+ .help("Feature flags")
+ .labelNames("env")
+ .states("feature1", "feature2")
+ .register();
+
+stateSet.labelValues("dev").setFalse("feature1");
+stateSet.labelValues("dev").setTrue("feature2");
+```
+
+The OpenMetrics text format looks like this:
+
+```text
+# TYPE feature_flags stateset
+# HELP feature_flags Feature flags
+feature_flags{env="dev",feature_flags="feature1"} 0
+feature_flags{env="dev",feature_flags="feature2"} 1
+```
+
+## GaugeHistogram and Unknown
+
+These types are defined in the [OpenMetrics](https://openmetrics.io/) standard but not implemented
+in the `prometheus-metrics-core` API.
+However, `prometheus-metrics-model` implements the underlying data model for these types.
+To use these types, you need to implement your own `Collector` where the `collect()` method returns
+an `UnknownSnapshot` or a `HistogramSnapshot` with `.gaugeHistogram(true)`.
+If your custom collector does not implement `getMetricType()` and `getLabelNames()`, ensure it does
+not produce the same metric name and label set as another collector, or the exposition may contain
+duplicate time series.
diff --git a/docs/content/getting-started/multi-target.md b/docs/content/getting-started/multi-target.md
new file mode 100644
index 000000000..cfa0b841f
--- /dev/null
+++ b/docs/content/getting-started/multi-target.md
@@ -0,0 +1,120 @@
+---
+title: Multi-Target Pattern
+weight: 7
+---
+
+{{< hint type=note >}}
+This is for the upcoming release 1.1.0.
+{{< /hint >}}
+
+To support multi-target pattern you can create a custom collector overriding the purposed internal
+method in ExtendedMultiCollector
+see SampleExtendedMultiCollector in io.prometheus.metrics.examples.httpserver
+
+```java
+public class SampleExtendedMultiCollector extends ExtendedMultiCollector {
+
+ public SampleExtendedMultiCollector() {
+ super();
+ }
+
+ @Override
+ protected MetricSnapshots collectMetricSnapshots(PrometheusScrapeRequest scrapeRequest) {
+
+ GaugeSnapshot.Builder gaugeBuilder = GaugeSnapshot.builder();
+ gaugeBuilder.name("x_load").help("process load");
+
+ CounterSnapshot.Builder counterBuilder = CounterSnapshot.builder();
+ counterBuilder.name(PrometheusNaming.sanitizeMetricName("x_calls_total")).help("invocations");
+
+ String[] targetNames = scrapeRequest.getParameterValues("target");
+ String targetName;
+ String[] procs = scrapeRequest.getParameterValues("proc");
+ if (targetNames == null || targetNames.length == 0) {
+ targetName = "defaultTarget";
+ procs = null; //ignore procs param
+ } else {
+ targetName = targetNames[0];
+ }
+ Builder counterDataPointBuilder = CounterSnapshot.CounterDataPointSnapshot.builder();
+ io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot.Builder gaugeDataPointBuilder = GaugeSnapshot.GaugeDataPointSnapshot.builder();
+ Labels lbls = Labels.of("target", targetName);
+
+ if (procs == null || procs.length == 0) {
+ counterDataPointBuilder.labels(lbls.merge(Labels.of("proc", "defaultProc")));
+ gaugeDataPointBuilder.labels(lbls.merge(Labels.of("proc", "defaultProc")));
+ counterDataPointBuilder.value(70);
+ gaugeDataPointBuilder.value(Math.random());
+
+ counterBuilder.dataPoint(counterDataPointBuilder.build());
+ gaugeBuilder.dataPoint(gaugeDataPointBuilder.build());
+
+ } else {
+ for (int i = 0; i < procs.length; i++) {
+ counterDataPointBuilder.labels(lbls.merge(Labels.of("proc", procs[i])));
+ gaugeDataPointBuilder.labels(lbls.merge(Labels.of("proc", procs[i])));
+ counterDataPointBuilder.value(Math.random());
+ gaugeDataPointBuilder.value(Math.random());
+
+ counterBuilder.dataPoint(counterDataPointBuilder.build());
+ gaugeBuilder.dataPoint(gaugeDataPointBuilder.build());
+ }
+ }
+ Collection snaps = new ArrayList();
+ snaps.add(counterBuilder.build());
+ snaps.add(gaugeBuilder.build());
+ MetricSnapshots msnaps = new MetricSnapshots(snaps);
+ return msnaps;
+ }
+
+ public List getPrometheusNames() {
+ List names = new ArrayList();
+ names.add("x_calls_total");
+ names.add("x_load");
+ return names;
+ }
+
+}
+
+```
+
+`PrometheusScrapeRequest` provides methods to access http-related infos from the request originally
+received by the endpoint
+
+```java
+public interface PrometheusScrapeRequest {
+ String getRequestURI();
+
+ String[] getParameterValues(String name);
+}
+
+```
+
+Sample Prometheus scrape_config
+
+```yaml
+- job_name: "multi-target"
+
+ # metrics_path defaults to '/metrics'
+ # scheme defaults to 'http'.
+ params:
+ proc: [proc1, proc2]
+ relabel_configs:
+ - source_labels: [__address__]
+ target_label: __param_target
+ - source_labels: [__param_target]
+ target_label: instance
+ - target_label: __address__
+ replacement: localhost:9401
+ static_configs:
+ - targets: ["target1", "target2"]
+```
+
+It's up to the specific MultiCollector implementation how to interpret the _target_ parameter.
+It might be an explicit real target (i.e. via host name/ip address) or as an alias in some internal
+configuration.
+The latter is more suitable when the MultiCollector implementation is a proxy (
+see )
+In this case, invoking real target might require extra parameters (e.g. credentials) that might be
+complex to manage in Prometheus configuration
+(not considering the case where the proxy might become an "open relay")
diff --git a/docs/content/getting-started/performance.md b/docs/content/getting-started/performance.md
new file mode 100644
index 000000000..42b2a0a48
--- /dev/null
+++ b/docs/content/getting-started/performance.md
@@ -0,0 +1,88 @@
+---
+title: Performance
+weight: 6
+---
+
+This section has tips on how to use the Prometheus Java client in high performance applications.
+
+## Specify Label Values Only Once
+
+For high performance applications, we recommend to specify label values only once, and then use the
+data point directly.
+
+This applies to all metric types. Let's use a counter as an example here:
+
+```java
+Counter requestCount = Counter.builder()
+ .name("requests_total")
+ .help("total number of requests")
+ .labelNames("path", "status")
+ .register();
+```
+
+You could increment the counter above like this:
+
+```java
+requestCount.labelValue("/", "200").inc();
+```
+
+However, the line above does not only increment the counter, it also looks up the label values to
+find the right data point.
+
+In high performance applications you can optimize this by looking up the data point only once:
+
+```java
+CounterDataPoint successfulCalls = requestCount.labelValues("/", "200");
+```
+
+Now, you can increment the data point directly, which is a highly optimized operation:
+
+```java
+successfulCalls.inc();
+```
+
+## Enable Only One Histogram Representation
+
+By default, histograms maintain two representations under the hood: The classic histogram
+representation with static buckets, and the native histogram representation with dynamic buckets.
+
+While this default provides the flexibility to scrape different representations at runtime, it comes
+at a cost, because maintaining multiple representations causes performance overhead.
+
+In performance critical applications we recommend to use either the classic representation or the
+native representation, but not both.
+
+You can either configure this in code for each histogram by
+calling [classicOnly()]()
+or [nativeOnly()](),
+or you use the corresponding [config options]({{< relref "../config/config.md" >}}).
+
+One way to do this is with system properties in the command line when you start your application
+
+```sh
+java -Dio.prometheus.metrics.histogram_classic_only=true my-app.jar
+```
+
+or
+
+```sh
+java -Dio.prometheus.metrics.histogram_native_only=true my-app.jar
+```
+
+If you don't want to add a command line parameter every time you start your application, you can add
+a `prometheus.properties` file to your classpath (put it in the `src/main/resources/` directory so
+that it gets packed into your JAR file). The `prometheus.properties` file should have the following
+line:
+
+```properties
+io.prometheus.metrics.histogram_classic_only=true
+```
+
+or
+
+```properties
+io.prometheus.metrics.histogram_native_only=true
+```
+
+Future releases will add more configuration options, like support for configuration via environment
+variable`IO_PROMETHEUS_METRICS_HISTOGRAM_NATIVE_ONLY=true`.
diff --git a/docs/content/getting-started/quickstart.md b/docs/content/getting-started/quickstart.md
new file mode 100644
index 000000000..635c63be0
--- /dev/null
+++ b/docs/content/getting-started/quickstart.md
@@ -0,0 +1,213 @@
+---
+title: Quickstart
+weight: 0
+---
+
+This tutorial shows the quickest way to get started with the Prometheus Java metrics library.
+
+{{< toc >}}
+
+## Dependencies
+
+We use the following dependencies:
+
+- `prometheus-metrics-core` is the actual metrics library.
+- `prometheus-metrics-instrumentation-jvm` provides out-of-the-box JVM metrics.
+- `prometheus-metrics-exporter-httpserver` is a standalone HTTP server for exposing Prometheus
+ metrics.
+ {{< tabs "deps" >}}
+ {{< tab "Gradle" >}}
+
+```groovy
+implementation 'io.prometheus:prometheus-metrics-core:$version'
+implementation 'io.prometheus:prometheus-metrics-instrumentation-jvm:$version'
+implementation 'io.prometheus:prometheus-metrics-exporter-httpserver:$version'
+```
+
+{{< /tab >}}
+{{< tab "Maven" >}}
+
+```xml
+
+ io.prometheus
+ prometheus-metrics-core
+ $version
+
+
+ io.prometheus
+ prometheus-metrics-instrumentation-jvm
+ $version
+
+
+ io.prometheus
+ prometheus-metrics-exporter-httpserver
+ $version
+
+```
+
+{{< /tab >}}
+{{< /tabs >}}
+
+There are alternative exporters as well, for example if you are using a Servlet container like
+Tomcat or Undertow you might want to use `prometheus-exporter-servlet-jakarta` rather than a
+standalone HTTP server.
+
+{{< hint type=note >}}
+
+If you do not use the protobuf exposition format, you can
+[exclude]({{< relref "../exporters/formats.md#exclude-protobuf-exposition-format" >}})
+it from the dependencies.
+
+{{< /hint >}}
+
+## Dependency management
+
+A Bill of Material
+([BOM](https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#bill-of-materials-bom-poms))
+ensures that versions of dependencies (including transitive ones) are aligned.
+This is especially important when using Spring Boot, which manages some of the dependencies of the
+project.
+
+You should omit the version number of the dependencies in your build file if you are using a BOM.
+
+{{< tabs "bom" >}}
+{{< tab "Gradle" >}}
+
+You have two ways to import a BOM.
+
+First, you can use the Gradle’s native BOM support by adding `dependencies`:
+
+```kotlin
+import org.springframework.boot.gradle.plugin.SpringBootPlugin
+
+plugins {
+ id("java")
+ id("org.springframework.boot") version "3.2.O" // if you are using Spring Boot
+}
+
+dependencies {
+ implementation(platform(SpringBootPlugin.BOM_COORDINATES)) // if you are using Spring Boot
+ implementation(platform("io.prometheus:prometheus-metrics-bom:$version"))
+}
+```
+
+The other way with Gradle is to use `dependencyManagement`:
+
+```kotlin
+plugins {
+ id("java")
+ id("org.springframework.boot") version "3.2.O" // if you are using Spring Boot
+ id("io.spring.dependency-management") version "1.1.0" // if you are using Spring Boot
+}
+
+dependencyManagement {
+ imports {
+ mavenBom("io.prometheus:prometheus-metrics-bom:$version")
+ }
+}
+```
+
+{{< hint type=note >}}
+
+Be careful not to mix up the different ways of configuring things with Gradle.
+For example, don't use
+`implementation(platform("io.prometheus:prometheus-metrics-bom:$version"))`
+with the `io.spring.dependency-management` plugin.
+
+{{< /hint >}}
+
+{{< /tab >}}
+{{< tab "Maven" >}}
+
+{{< hint type=note >}}
+
+Import the Prometheus Java metrics BOMs before any other BOMs in your
+project. For example, if you import the `spring-boot-dependencies` BOM, you have
+to declare it after the Prometheus Java metrics BOMs.
+
+{{< /hint >}}
+
+The following example shows how to import the Prometheus Java metrics BOMs using Maven:
+
+```xml
+
+
+
+ io.prometheus
+ prometheus-metrics-bom
+ $version
+ pom
+ import
+
+
+
+```
+
+{{< /tab >}}
+{{< /tabs >}}
+
+## Example Application
+
+```java
+import io.prometheus.metrics.core.metrics.Counter;
+import io.prometheus.metrics.exporter.httpserver.HTTPServer;
+import io.prometheus.metrics.instrumentation.jvm.JvmMetrics;
+
+import java.io.IOException;
+
+public class App {
+
+ public static void main(String[] args) throws InterruptedException, IOException {
+
+ JvmMetrics.builder().register(); // initialize the out-of-the-box JVM metrics
+
+ Counter counter = Counter.builder()
+ .name("my_count_total")
+ .help("example counter")
+ .labelNames("status")
+ .register();
+
+ counter.labelValues("ok").inc();
+ counter.labelValues("ok").inc();
+ counter.labelValues("error").inc();
+
+ HTTPServer server = HTTPServer.builder()
+ .port(9400)
+ .buildAndStart();
+
+ System.out.println("HTTPServer listening on port http://localhost:" +
+ server.getPort() + "/metrics");
+
+ Thread.currentThread().join(); // sleep forever
+ }
+}
+```
+
+## Result
+
+Run the application and view [http://localhost:9400/metrics](http://localhost:9400/metrics) with
+your browser to see the raw metrics. You should see the `my_count_total` metric as shown below plus
+the `jvm_` and `process_` metrics coming from `JvmMetrics`.
+
+```text
+# HELP my_count_total example counter
+# TYPE my_count_total counter
+my_count_total{status="error"} 1.0
+my_count_total{status="ok"} 2.0
+```
+
+## Prometheus Configuration
+
+To scrape the metrics with a Prometheus server, download the latest Prometheus
+server [release](https://github.com/prometheus/prometheus/releases), and configure the
+`prometheus.yml` file as follows:
+
+```yaml
+global:
+ scrape_interval: 10s # short interval for manual testing
+
+scrape_configs:
+ - job_name: "java-example"
+ static_configs:
+ - targets: ["localhost:9400"]
+```
diff --git a/docs/content/getting-started/registry.md b/docs/content/getting-started/registry.md
new file mode 100644
index 000000000..de437be23
--- /dev/null
+++ b/docs/content/getting-started/registry.md
@@ -0,0 +1,150 @@
+---
+title: Registry
+weight: 2
+---
+
+In order to expose metrics, you need to register them with a `PrometheusRegistry`. We are using a
+counter as an example here, but the `register()` method is the same for all metric types.
+
+## Registering a Metric with the Default Registry
+
+```java
+Counter eventsTotal = Counter.builder()
+ .name("events_total")
+ .help("Total number of events")
+ .register(); // <-- implicitly uses PrometheusRegistry.defaultRegistry
+```
+
+The `register()` call above builds the counter and registers it with the global static
+`PrometheusRegistry.defaultRegistry`. Using the default registry is recommended.
+
+## Registering a Metric with a Custom Registry
+
+You can also register your metric with a custom registry:
+
+```java
+PrometheusRegistry myRegistry = new PrometheusRegistry();
+
+Counter eventsTotal = Counter.builder()
+ .name("events_total")
+ .help("Total number of events")
+ .register(myRegistry);
+```
+
+## Registering a Metric with Multiple Registries
+
+As an alternative to calling `register()` directly, you can `build()` metrics without registering
+them,
+and register them later:
+
+```java
+
+// create a counter that is not registered with any registry
+
+Counter eventsTotal = Counter.builder()
+ .name("events_total")
+ .help("Total number of events")
+ .build(); // <-- this will create the metric but not register it
+
+// register the counter with the default registry
+
+PrometheusRegistry.defaultRegistry.register(eventsTotal);
+
+// register the counter with a custom registry.
+// This is OK, you can register a metric with multiple registries.
+
+PrometheusRegistry myRegistry = new PrometheusRegistry();
+myRegistry.register(eventsTotal);
+```
+
+Custom registries are useful if you want to maintain different scopes of metrics, like
+a debug registry with a lot of metrics, and a default registry with only a few metrics.
+
+## IllegalArgumentException: Duplicate Metric Name in Registry
+
+While it is OK to register the same metric with multiple registries, it is illegal to register the
+same metric name multiple times with the same registry.
+The following code will throw an `IllegalArgumentException`:
+
+```java
+Counter eventsTotal1 = Counter.builder()
+ .name("events_total")
+ .help("Total number of events")
+ .register();
+
+Counter eventsTotal2 = Counter.builder()
+ .name("events_total")
+ .help("Total number of events")
+ .register(); // IllegalArgumentException, because a metric with that name is already registered
+```
+
+## Suffix-Based Name Validation
+
+Suffix handling happens at scrape time. This makes metric names more flexible while keeping the
+exposed output unambiguous.
+
+The registry now tracks not only the metric names you register, but also the exposition names they
+would claim in OpenMetrics 1.x and Prometheus text format, such as `_total`, `_count`, `_sum`,
+`_bucket`, `_created`, and `_info`.
+
+This means names are accepted when they are safe, and combinations are rejected when they would
+collide at scrape time. The table below also shows the pre-1.6.0 behavior for comparison.
+
+| Example | Before 1.6.0 | Current behavior | Why |
+| --------------------------------------------- | ------------ | ---------------- | ------------------------------------------------------------------------------------------------- |
+| `Gauge("foo_total")` | Rejected | Allowed | Safe because `_total` suffix expansion applies to counters, not gauges. |
+| `Counter("events_total")` | Rejected | Allowed | Safe because the OM1 output is `events_total`; the writer avoids double-appending `_total`. |
+| `Gauge("foo_total")` + `Histogram("foo")` | Rejected | Allowed | Safe because the exposed names do not overlap: `foo_total` vs `foo_bucket`/`foo_count`/`foo_sum`. |
+| `Gauge("events_total")` + `Counter("events")` | Rejected | Rejected | Rejected because both would expose `events_total` in OM1. |
+| `Gauge("foo_count")` + `Histogram("foo")` | Allowed | Rejected | Rejected because both would claim `foo_count` at scrape time. |
+
+## Validation at registration only
+
+Validation of duplicate metric names and label schemas happens at registration time only.
+Built-in metrics (Counter, Gauge, Histogram, etc.) participate in this validation.
+
+Custom collectors that implement the `Collector` or `MultiCollector` interface can optionally
+expose their registration-time metadata so the registry can enforce consistency. The recommended
+way is to override `getMetricFamilyDescriptor()` (or `getMetricFamilyDescriptors()` on
+`MultiCollector`) and return a `MetricFamilyDescriptor` describing the metric name, type, label
+names, and metadata (help, unit) the collector will emit at scrape time.
+
+```java
+@Override
+public MetricFamilyDescriptor getMetricFamilyDescriptor() {
+ return MetricFamilyDescriptor.gauge("my_metric")
+ .help("Example metric")
+ .labelNames("region")
+ .build();
+}
+```
+
+The fragmented `getPrometheusName()`, `getMetricType()`, `getLabelNames()`, and `getMetadata()`
+methods (and their `MultiCollector` per-name variants) are deprecated. They remain bridged by a
+default implementation of `getMetricFamilyDescriptor()` for compatibility, so existing
+collectors keep working unchanged.
+
+**Validation is skipped when registration-time metadata is unavailable:** if
+`getMetricFamilyDescriptor()` returns `null` (the default when name or type is missing), the
+registry does not validate that collector. If two such collectors produce the same metric name and
+same label set at scrape time, the exposition output may contain duplicate time series and be
+invalid for Prometheus.
+
+This is also relevant for downstream adapter libraries that bridge to this registry. If an adapter
+implements `MultiCollector`, its registration-time metadata must match the metric families it will
+actually emit at scrape time. In practice, the `MetricFamilyDescriptor`s returned from
+`getMetricFamilyDescriptors()` need to describe the same names, types, labels, and suffix behavior
+as the eventual `MetricSnapshot` output. Otherwise an adapter may pass or fail collision checks
+differently after upgrading to a newer client_java release, even if its scrape output logic did not
+change.
+
+## Unregistering a Metric
+
+There is no automatic expiry of unused metrics (yet), once a metric is registered it will remain
+registered forever.
+
+However, you can programmatically unregister an obsolete metric like this:
+
+```java
+PrometheusRegistry.defaultRegistry.unregister(eventsTotal);
+```
diff --git a/docs/content/instrumentation/_index.md b/docs/content/instrumentation/_index.md
new file mode 100644
index 000000000..3e255f9fe
--- /dev/null
+++ b/docs/content/instrumentation/_index.md
@@ -0,0 +1,4 @@
+---
+title: Instrumentation
+weight: 3
+---
diff --git a/docs/content/instrumentation/caffeine.md b/docs/content/instrumentation/caffeine.md
new file mode 100644
index 000000000..90a88c05f
--- /dev/null
+++ b/docs/content/instrumentation/caffeine.md
@@ -0,0 +1,128 @@
+---
+title: Caffeine Cache
+weight: 1
+---
+
+The Caffeine instrumentation module, added in version 1.3.2, translates observability data
+provided by caffeine `Cache` objects into prometheus metrics.
+
+{{< tabs "uniqueid" >}}
+{{< tab "Gradle" >}}
+
+```groovy
+implementation 'io.prometheus:prometheus-metrics-instrumentation-caffeine:1.3.2'
+```
+
+{{< /tab >}}
+{{< tab "Maven" >}}
+
+```xml
+
+ io.prometheus
+ prometheus-metrics-instrumentation-caffeine
+ 1.3.2
+
+```
+
+{{< /tab >}}
+{{< /tabs >}}
+
+In order to collect metrics:
+
+- A single `CacheMetricsCollector` instance must be registered with the registry;
+ - Multiple `CacheMetricsCollector` instances cannot be registered with the same registry;
+- The `Cache` object must be instantiated with the `recordStats()` option, and then added to the
+ `CacheMetricsCollector` instance with a unique name, which will be used as the value of the
+ `cache` label on the exported metrics;
+ - If the `recordStats` option is not set, most metrics will only return zero values;
+
+```java
+var cache = Caffeine.newBuilder().recordStats().build();
+var cacheMetrics = CacheMetricsCollector.builder().build();
+PrometheusRegistry.defaultRegistry.register(cacheMetrics);
+cacheMetrics.addCache("mycache", cache);
+```
+
+{{< hint type=note >}}
+
+In version 1.3.5 and older of the caffeine instrumentation library, `CacheMetricsCollector.builder`
+does not exist, i.e. a constructor call `new CacheMetricsCollector()` is the only option.
+
+{{< /hint >}}
+
+All example metrics on this page will use the `mycache` label value.
+
+## Generic Cache Metrics
+
+For all cache instances, the following metrics will be available:
+
+```text
+# TYPE caffeine_cache_hit counter
+# HELP caffeine_cache_hit Cache hit totals
+caffeine_cache_hit_total{cache="mycache"} 10.0
+# TYPE caffeine_cache_miss counter
+# HELP caffeine_cache_miss Cache miss totals
+caffeine_cache_miss_total{cache="mycache"} 3.0
+# TYPE caffeine_cache_requests counter
+# HELP caffeine_cache_requests Cache request totals, hits + misses
+caffeine_cache_requests_total{cache="mycache"} 13.0
+# TYPE caffeine_cache_eviction counter
+# HELP caffeine_cache_eviction Cache eviction totals, doesn't include manually removed entries
+caffeine_cache_eviction_total{cache="mycache"} 1.0
+# TYPE caffeine_cache_estimated_size
+# HELP caffeine_cache_estimated_size Estimated cache size
+caffeine_cache_estimated_size{cache="mycache"} 5.0
+```
+
+## Loading Cache Metrics
+
+If the cache is an instance of `LoadingCache`, i.e. it is built with a `loader` function that is
+managed by the cache library, then metrics for observing load time and load failures become
+available:
+
+```text
+# TYPE caffeine_cache_load_failure counter
+# HELP caffeine_cache_load_failure Cache load failures
+caffeine_cache_load_failure_total{cache="mycache"} 10.0
+# TYPE caffeine_cache_loads counter
+# HELP caffeine_cache_loads Cache loads: both success and failures
+caffeine_cache_loads_total{cache="mycache"} 3.0
+# TYPE caffeine_cache_load_duration_seconds summary
+# HELP caffeine_cache_load_duration_seconds Cache load duration: both success and failures
+caffeine_cache_load_duration_seconds_count{cache="mycache"} 7.0
+caffeine_cache_load_duration_seconds_sum{cache="mycache"} 0.0034
+```
+
+## Weighted Cache Metrics
+
+Two metrics exist for observability specifically of caches that define a `weigher`:
+
+```text
+# TYPE caffeine_cache_eviction_weight counter
+# HELP caffeine_cache_eviction_weight Weight of evicted cache entries, doesn't include manually removed entries
+
+caffeine_cache_eviction_weight_total{cache="mycache"} 5.0
+# TYPE caffeine_cache_weighted_size gauge
+# HELP caffeine_cache_weighted_size Approximate accumulated weight of cache entries
+caffeine_cache_weighted_size{cache="mycache"} 30.0
+```
+
+{{< hint type=note >}}
+
+`caffeine_cache_weighted_size` is available only if the cache instance defines a `maximumWeight`.
+
+{{< /hint >}}
+
+Up to version 1.3.5 and older, the weighted metrics had a different behavior:
+
+- `caffeine_cache_weighted_size` was not implemented;
+- `caffeine_cache_eviction_weight` was exposed as a `gauge`;
+
+It is possible to restore the behavior of version 1.3.5 and older, by either:
+
+- Using the deprecated `new CacheMetricsCollector()` constructor;
+- Using the flags provided on the `CacheMetricsCollector.Builder` object to opt-out of each of the
+ elements of the post-1.3.5 behavior:
+ - `builder.collectWeightedSize(false)` will disable collection of `caffeine_cache_weighted_size`;
+ - `builder.collectEvictionWeightAsCounter(false)` will expose `caffeine_cache_eviction_weight` as
+ a `gauge` metric;
diff --git a/docs/content/instrumentation/guava.md b/docs/content/instrumentation/guava.md
new file mode 100644
index 000000000..ffc8f0ab2
--- /dev/null
+++ b/docs/content/instrumentation/guava.md
@@ -0,0 +1,87 @@
+---
+title: Guava Cache
+weight: 1
+---
+
+The Guava instrumentation module, added in version 1.3.2, translates observability data
+provided by Guava `Cache` objects into prometheus metrics.
+
+{{< tabs "uniqueid" >}}
+{{< tab "Gradle" >}}
+
+```groovy
+implementation 'io.prometheus:prometheus-metrics-instrumentation-guava:1.3.2'
+```
+
+{{< /tab >}}
+{{< tab "Maven" >}}
+
+```xml
+
+ io.prometheus
+ prometheus-metrics-instrumentation-guava
+ 1.3.2
+
+```
+
+{{< /tab >}}
+{{< /tabs >}}
+
+In order to collect metrics:
+
+- A single `CacheMetricsCollector` instance must be registered with the registry;
+ - Multiple `CacheMetricsCollector` instances cannot be registered with the same registry;
+- The `Cache` object must be instantiated with the `recordStats()` option, and then added to the
+ `CacheMetricsCollector` instance with a unique name, which will be used as the value of the
+ `cache` label on the exported metrics;
+ - If the `recordStats` option is not set, most metrics will only return zero values;
+
+```java
+var cache = CacheBuilder.newBuilder().recordStats().build();
+var cacheMetrics = new CacheMetricsCollector();
+PrometheusRegistry.defaultRegistry.register(cacheMetrics);
+cacheMetrics.addCache("mycache", cache);
+```
+
+All example metrics on this page will use the `mycache` label value.
+
+## Generic Cache Metrics
+
+For all cache instances, the following metrics will be available:
+
+```text
+# TYPE guava_cache_hit counter
+# HELP guava_cache_hit Cache hit totals
+guava_cache_hit_total{cache="mycache"} 10.0
+# TYPE guava_cache_miss counter
+# HELP guava_cache_miss Cache miss totals
+guava_cache_miss_total{cache="mycache"} 3.0
+# TYPE guava_cache_requests counter
+# HELP guava_cache_requests Cache request totals
+guava_cache_requests_total{cache="mycache"} 13.0
+# TYPE guava_cache_eviction counter
+# HELP guava_cache_eviction Cache eviction totals, doesn't include manually removed entries
+guava_cache_eviction_total{cache="mycache"} 1.0
+# TYPE guava_cache_size
+# HELP guava_cache_size Cache size
+guava_cache_size{cache="mycache"} 5.0
+```
+
+## Loading Cache Metrics
+
+If the cache is an instance of `LoadingCache`, i.e. it is built with a `loader` function that is
+managed by the cache library, then metrics for observing load time and load failures become
+available:
+
+```text
+# TYPE guava_cache_load_failure counter
+# HELP guava_cache_load_failure Cache load failures
+guava_cache_load_failure_total{cache="mycache"} 10.0
+# TYPE guava_cache_loads counter
+# HELP guava_cache_loads Cache loads: both success and failures
+guava_cache_loads_total{cache="mycache"} 3.0
+# TYPE guava_cache_load_duration_seconds summary
+# HELP guava_cache_load_duration_seconds Cache load duration: both success and failures
+guava_cache_load_duration_seconds_count{cache="mycache"} 7.0
+guava_cache_load_duration_seconds_sum{cache="mycache"} 0.0034
+```
diff --git a/docs/content/instrumentation/jvm.md b/docs/content/instrumentation/jvm.md
new file mode 100644
index 000000000..3a658c05b
--- /dev/null
+++ b/docs/content/instrumentation/jvm.md
@@ -0,0 +1,315 @@
+---
+title: JVM
+weight: 1
+---
+
+{{< hint type=note >}}
+
+Looking for JVM metrics that follow OTel semantic
+conventions? See
+[OTel JVM Runtime Metrics]({{< relref "../otel/jvm-runtime-metrics.md" >}})
+for an alternative based on OpenTelemetry's
+runtime-telemetry module.
+
+{{< /hint >}}
+
+The JVM instrumentation module provides a variety of out-of-the-box JVM and process metrics. To use
+it, add the following dependency:
+
+{{< tabs "uniqueid" >}}
+{{< tab "Gradle" >}}
+
+```groovy
+implementation 'io.prometheus:prometheus-metrics-instrumentation-jvm:1.0.0'
+```
+
+{{< /tab >}}
+{{< tab "Maven" >}}
+
+```xml
+
+ io.prometheus
+ prometheus-metrics-instrumentation-jvm
+ 1.0.0
+
+```
+
+{{< /tab >}}
+{{< /tabs >}}
+
+Now, you can register the JVM metrics as follows:
+
+```java
+JvmMetrics.builder().register();
+```
+
+The line above will initialize all JVM metrics and register them with the default registry. If you
+want to register the metrics with a custom `PrometheusRegistry`, you can pass the registry as
+parameter to the `register()` call.
+
+The sections below describe the individual classes providing JVM metrics. If you don't want to
+register all JVM metrics, you can register each of these classes individually rather than using
+`JvmMetrics`.
+
+## JVM Buffer Pool Metrics
+
+JVM buffer pool metrics are provided by
+the [JvmBufferPoolMetrics](/client_java/api/io/prometheus/metrics/instrumentation/jvm/JvmBufferPoolMetrics.html)
+class. The data is coming from
+the [BufferPoolMXBean](https://docs.oracle.com/en/java/javase/21/docs/api/java.management/java/lang/management/BufferPoolMXBean.html).
+Example metrics:
+
+```text
+# HELP jvm_buffer_pool_capacity_bytes Bytes capacity of a given JVM buffer pool.
+# TYPE jvm_buffer_pool_capacity_bytes gauge
+jvm_buffer_pool_capacity_bytes{pool="direct"} 8192.0
+jvm_buffer_pool_capacity_bytes{pool="mapped"} 0.0
+# HELP jvm_buffer_pool_used_buffers Used buffers of a given JVM buffer pool.
+# TYPE jvm_buffer_pool_used_buffers gauge
+jvm_buffer_pool_used_buffers{pool="direct"} 1.0
+jvm_buffer_pool_used_buffers{pool="mapped"} 0.0
+# HELP jvm_buffer_pool_used_bytes Used bytes of a given JVM buffer pool.
+# TYPE jvm_buffer_pool_used_bytes gauge
+jvm_buffer_pool_used_bytes{pool="direct"} 8192.0
+jvm_buffer_pool_used_bytes{pool="mapped"} 0.0
+```
+
+## JVM Class Loading Metrics
+
+JVM class loading metrics are provided by
+the [JvmClassLoadingMetrics](/client_java/api/io/prometheus/metrics/instrumentation/jvm/JvmClassLoadingMetrics.html)
+class. The data is coming from
+the [ClassLoadingMXBean](https://docs.oracle.com/en/java/javase/21/docs/api/java.management/java/lang/management/ClassLoadingMXBean.html).
+Example metrics:
+
+```text
+# HELP jvm_classes_currently_loaded The number of classes that are currently loaded in the JVM
+# TYPE jvm_classes_currently_loaded gauge
+jvm_classes_currently_loaded 1109.0
+# HELP jvm_classes_loaded_total The total number of classes that have been loaded since the JVM has started execution
+# TYPE jvm_classes_loaded_total counter
+jvm_classes_loaded_total 1109.0
+# HELP jvm_classes_unloaded_total The total number of classes that have been unloaded since the JVM has started execution
+# TYPE jvm_classes_unloaded_total counter
+jvm_classes_unloaded_total 0.0
+```
+
+## JVM Compilation Metrics
+
+JVM compilation metrics are provided by
+the [JvmCompilationMetrics](/client_java/api/io/prometheus/metrics/instrumentation/jvm/JvmCompilationMetrics.html)
+class. The data is coming from
+the [CompilationMXBean](https://docs.oracle.com/en/java/javase/21/docs/api/java.management/java/lang/management/CompilationMXBean.html).
+Example metrics:
+
+```text
+# HELP jvm_compilation_time_seconds_total The total time in seconds taken for HotSpot class compilation
+# TYPE jvm_compilation_time_seconds_total counter
+jvm_compilation_time_seconds_total 0.152
+```
+
+## JVM Garbage Collector Metrics
+
+JVM garbage collector metrics are provided by
+the [JvmGarbageCollectorMetric](/client_java/api/io/prometheus/metrics/instrumentation/jvm/JvmGarbageCollectorMetrics.html)
+class. The data is coming from
+the [GarbageCollectorMXBean](https://docs.oracle.com/en/java/javase/21/docs/api/java.management/java/lang/management/GarbageCollectorMXBean.html).
+Example metrics:
+
+```text
+# HELP jvm_gc_collection_seconds Time spent in a given JVM garbage collector in seconds.
+# TYPE jvm_gc_collection_seconds summary
+jvm_gc_collection_seconds_count{gc="PS MarkSweep"} 0
+jvm_gc_collection_seconds_sum{gc="PS MarkSweep"} 0.0
+jvm_gc_collection_seconds_count{gc="PS Scavenge"} 0
+jvm_gc_collection_seconds_sum{gc="PS Scavenge"} 0.0
+```
+
+## JVM Memory Metrics
+
+JVM memory metrics are provided by
+the [JvmMemoryMetrics](/client_java/api/io/prometheus/metrics/instrumentation/jvm/JvmMemoryMetrics.html)
+class. The data is coming from
+the [MemoryMXBean](https://docs.oracle.com/en/java/javase/21/docs/api/java.management/java/lang/management/MemoryMXBean.html)
+and the [MemoryPoolMXBean](https://docs.oracle.com/en/java/javase/21/docs/api/java.management/java/lang/management/MemoryPoolMXBean.html).
+Example metrics:
+
+```text
+# HELP jvm_memory_committed_bytes Committed (bytes) of a given JVM memory area.
+# TYPE jvm_memory_committed_bytes gauge
+jvm_memory_committed_bytes{area="heap"} 4.98597888E8
+jvm_memory_committed_bytes{area="nonheap"} 1.1993088E7
+# HELP jvm_memory_init_bytes Initial bytes of a given JVM memory area.
+# TYPE jvm_memory_init_bytes gauge
+jvm_memory_init_bytes{area="heap"} 5.20093696E8
+jvm_memory_init_bytes{area="nonheap"} 2555904.0
+# HELP jvm_memory_max_bytes Max (bytes) of a given JVM memory area.
+# TYPE jvm_memory_max_bytes gauge
+jvm_memory_max_bytes{area="heap"} 7.38983936E9
+jvm_memory_max_bytes{area="nonheap"} -1.0
+# HELP jvm_memory_objects_pending_finalization The number of objects waiting in the finalizer queue.
+# TYPE jvm_memory_objects_pending_finalization gauge
+jvm_memory_objects_pending_finalization 0.0
+# HELP jvm_memory_pool_collection_committed_bytes Committed after last collection bytes of a given JVM memory pool.
+# TYPE jvm_memory_pool_collection_committed_bytes gauge
+jvm_memory_pool_collection_committed_bytes{pool="PS Eden Space"} 1.30023424E8
+jvm_memory_pool_collection_committed_bytes{pool="PS Old Gen"} 3.47078656E8
+jvm_memory_pool_collection_committed_bytes{pool="PS Survivor Space"} 2.1495808E7
+# HELP jvm_memory_pool_collection_init_bytes Initial after last collection bytes of a given JVM memory pool.
+# TYPE jvm_memory_pool_collection_init_bytes gauge
+jvm_memory_pool_collection_init_bytes{pool="PS Eden Space"} 1.30023424E8
+jvm_memory_pool_collection_init_bytes{pool="PS Old Gen"} 3.47078656E8
+jvm_memory_pool_collection_init_bytes{pool="PS Survivor Space"} 2.1495808E7
+# HELP jvm_memory_pool_collection_max_bytes Max bytes after last collection of a given JVM memory pool.
+# TYPE jvm_memory_pool_collection_max_bytes gauge
+jvm_memory_pool_collection_max_bytes{pool="PS Eden Space"} 2.727870464E9
+jvm_memory_pool_collection_max_bytes{pool="PS Old Gen"} 5.542248448E9
+jvm_memory_pool_collection_max_bytes{pool="PS Survivor Space"} 2.1495808E7
+# HELP jvm_memory_pool_collection_used_bytes Used bytes after last collection of a given JVM memory pool.
+# TYPE jvm_memory_pool_collection_used_bytes gauge
+jvm_memory_pool_collection_used_bytes{pool="PS Eden Space"} 0.0
+jvm_memory_pool_collection_used_bytes{pool="PS Old Gen"} 1249696.0
+jvm_memory_pool_collection_used_bytes{pool="PS Survivor Space"} 0.0
+# HELP jvm_memory_pool_committed_bytes Committed bytes of a given JVM memory pool.
+# TYPE jvm_memory_pool_committed_bytes gauge
+jvm_memory_pool_committed_bytes{pool="Code Cache"} 4128768.0
+jvm_memory_pool_committed_bytes{pool="Compressed Class Space"} 917504.0
+jvm_memory_pool_committed_bytes{pool="Metaspace"} 6946816.0
+jvm_memory_pool_committed_bytes{pool="PS Eden Space"} 1.30023424E8
+jvm_memory_pool_committed_bytes{pool="PS Old Gen"} 3.47078656E8
+jvm_memory_pool_committed_bytes{pool="PS Survivor Space"} 2.1495808E7
+# HELP jvm_memory_pool_init_bytes Initial bytes of a given JVM memory pool.
+# TYPE jvm_memory_pool_init_bytes gauge
+jvm_memory_pool_init_bytes{pool="Code Cache"} 2555904.0
+jvm_memory_pool_init_bytes{pool="Compressed Class Space"} 0.0
+jvm_memory_pool_init_bytes{pool="Metaspace"} 0.0
+jvm_memory_pool_init_bytes{pool="PS Eden Space"} 1.30023424E8
+jvm_memory_pool_init_bytes{pool="PS Old Gen"} 3.47078656E8
+jvm_memory_pool_init_bytes{pool="PS Survivor Space"} 2.1495808E7
+# HELP jvm_memory_pool_max_bytes Max bytes of a given JVM memory pool.
+# TYPE jvm_memory_pool_max_bytes gauge
+jvm_memory_pool_max_bytes{pool="Code Cache"} 2.5165824E8
+jvm_memory_pool_max_bytes{pool="Compressed Class Space"} 1.073741824E9
+jvm_memory_pool_max_bytes{pool="Metaspace"} -1.0
+jvm_memory_pool_max_bytes{pool="PS Eden Space"} 2.727870464E9
+jvm_memory_pool_max_bytes{pool="PS Old Gen"} 5.542248448E9
+jvm_memory_pool_max_bytes{pool="PS Survivor Space"} 2.1495808E7
+# HELP jvm_memory_pool_used_bytes Used bytes of a given JVM memory pool.
+# TYPE jvm_memory_pool_used_bytes gauge
+jvm_memory_pool_used_bytes{pool="Code Cache"} 4065472.0
+jvm_memory_pool_used_bytes{pool="Compressed Class Space"} 766680.0
+jvm_memory_pool_used_bytes{pool="Metaspace"} 6659432.0
+jvm_memory_pool_used_bytes{pool="PS Eden Space"} 7801536.0
+jvm_memory_pool_used_bytes{pool="PS Old Gen"} 1249696.0
+jvm_memory_pool_used_bytes{pool="PS Survivor Space"} 0.0
+# HELP jvm_memory_used_bytes Used bytes of a given JVM memory area.
+# TYPE jvm_memory_used_bytes gauge
+jvm_memory_used_bytes{area="heap"} 9051232.0
+jvm_memory_used_bytes{area="nonheap"} 1.1490688E7
+```
+
+## JVM Memory Pool Allocation Metrics
+
+JVM memory pool allocation metrics are provided by
+the [JvmMemoryPoolAllocationMetrics](/client_java/api/io/prometheus/metrics/instrumentation/jvm/JvmMemoryPoolAllocationMetrics.html)
+class. The data is obtained by adding
+a [NotificationListener](https://docs.oracle.com/en/java/javase/21/docs/api/java.management/javax/management/NotificationListener.html)
+to the [GarbageCollectorMXBean](https://docs.oracle.com/en/java/javase/21/docs/api/java.management/java/lang/management/GarbageCollectorMXBean.html).
+Example metrics:
+
+```text
+# HELP jvm_memory_pool_allocated_bytes_total Total bytes allocated in a given JVM memory pool. Only updated after GC, not continuously.
+# TYPE jvm_memory_pool_allocated_bytes_total counter
+jvm_memory_pool_allocated_bytes_total{pool="Code Cache"} 4336448.0
+jvm_memory_pool_allocated_bytes_total{pool="Compressed Class Space"} 875016.0
+jvm_memory_pool_allocated_bytes_total{pool="Metaspace"} 7480456.0
+jvm_memory_pool_allocated_bytes_total{pool="PS Eden Space"} 1.79232824E8
+jvm_memory_pool_allocated_bytes_total{pool="PS Old Gen"} 1428888.0
+jvm_memory_pool_allocated_bytes_total{pool="PS Survivor Space"} 4115280.0
+```
+
+## JVM Runtime Info Metric
+
+The JVM runtime info metric is provided by
+the [JvmRuntimeInfoMetric](/client_java/api/io/prometheus/metrics/instrumentation/jvm/JvmRuntimeInfoMetric.html)
+class. The data is obtained via system properties and will not change throughout the lifetime of the
+application. Example metric:
+
+```text
+# TYPE jvm_runtime info
+# HELP jvm_runtime JVM runtime info
+jvm_runtime_info{runtime="OpenJDK Runtime Environment",vendor="Oracle Corporation",version="1.8.0_382-b05"} 1
+```
+
+## JVM Thread Metrics
+
+JVM thread metrics are provided by
+the [JvmThreadsMetrics](/client_java/api/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.html)
+class. The data is coming from
+the [ThreadMXBean](https://docs.oracle.com/en/java/javase/21/docs/api/java.management/java/lang/management/ThreadMXBean.html).
+Example metrics:
+
+```text
+# HELP jvm_threads_current Current thread count of a JVM
+# TYPE jvm_threads_current gauge
+jvm_threads_current 10.0
+# HELP jvm_threads_daemon Daemon thread count of a JVM
+# TYPE jvm_threads_daemon gauge
+jvm_threads_daemon 8.0
+# HELP jvm_threads_deadlocked Cycles of JVM-threads that are in deadlock waiting to acquire object monitors or ownable synchronizers
+# TYPE jvm_threads_deadlocked gauge
+jvm_threads_deadlocked 0.0
+# HELP jvm_threads_deadlocked_monitor Cycles of JVM-threads that are in deadlock waiting to acquire object monitors
+# TYPE jvm_threads_deadlocked_monitor gauge
+jvm_threads_deadlocked_monitor 0.0
+# HELP jvm_threads_peak Peak thread count of a JVM
+# TYPE jvm_threads_peak gauge
+jvm_threads_peak 10.0
+# HELP jvm_threads_started_total Started thread count of a JVM
+# TYPE jvm_threads_started_total counter
+jvm_threads_started_total 10.0
+# HELP jvm_threads_state Current count of threads by state
+# TYPE jvm_threads_state gauge
+jvm_threads_state{state="BLOCKED"} 0.0
+jvm_threads_state{state="NEW"} 0.0
+jvm_threads_state{state="RUNNABLE"} 5.0
+jvm_threads_state{state="TERMINATED"} 0.0
+jvm_threads_state{state="TIMED_WAITING"} 2.0
+jvm_threads_state{state="UNKNOWN"} 0.0
+jvm_threads_state{state="WAITING"} 3.0
+```
+
+## Process Metrics
+
+Process metrics are provided by
+the [ProcessMetrics](/client_java/api/io/prometheus/metrics/instrumentation/jvm/ProcessMetrics.html)
+class. The data is coming from
+the [OperatingSystemMXBean](https://docs.oracle.com/en/java/javase/21/docs/api/java.management/java/lang/management/OperatingSystemMXBean.html),
+the [RuntimeMXBean](https://docs.oracle.com/en/java/javase/21/docs/api/java.management/java/lang/management/RuntimeMXBean.html),
+and from the `/proc/self/status` file on Linux. The metrics with prefix `process_` are not specific
+to Java, but should be provided by every Prometheus client library,
+see [Process Metrics](https://prometheus.io/docs/instrumenting/writing_clientlibs/#process-metrics)
+in the
+Prometheus [writing client libraries](https://prometheus.io/docs/instrumenting/writing_clientlibs/#process-metrics)
+documentation. Example metrics:
+
+```text
+# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
+# TYPE process_cpu_seconds_total counter
+process_cpu_seconds_total 1.63
+# HELP process_max_fds Maximum number of open file descriptors.
+# TYPE process_max_fds gauge
+process_max_fds 524288.0
+# HELP process_open_fds Number of open file descriptors.
+# TYPE process_open_fds gauge
+process_open_fds 28.0
+# HELP process_resident_memory_bytes Resident memory size in bytes.
+# TYPE process_resident_memory_bytes gauge
+process_resident_memory_bytes 7.8577664E7
+# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
+# TYPE process_start_time_seconds gauge
+process_start_time_seconds 1.693829439767E9
+# HELP process_virtual_memory_bytes Virtual memory size in bytes.
+# TYPE process_virtual_memory_bytes gauge
+process_virtual_memory_bytes 1.2683624448E10
+```
diff --git a/docs/content/internals/_index.md b/docs/content/internals/_index.md
new file mode 100644
index 000000000..9cce8243e
--- /dev/null
+++ b/docs/content/internals/_index.md
@@ -0,0 +1,4 @@
+---
+title: Internals
+weight: 7
+---
diff --git a/docs/content/internals/model.md b/docs/content/internals/model.md
new file mode 100644
index 000000000..629e87bf0
--- /dev/null
+++ b/docs/content/internals/model.md
@@ -0,0 +1,47 @@
+---
+title: Model
+weight: 1
+---
+
+The illustration below shows the internal architecture of the Prometheus Java client library.
+
+
+
+## prometheus-metrics-core
+
+This is the user facing metrics library, implementing the core metric types,
+like [Counter](/client_java/api/io/prometheus/metrics/core/metrics/Counter.html),
+[Gauge](/client_java/api/io/prometheus/metrics/core/metrics/Gauge.html)
+[Histogram](/client_java/api/io/prometheus/metrics/core/metrics/Histogram.html),
+and so on.
+
+All metric types implement
+the [Collector](/client_java/api/io/prometheus/metrics/model/registry/Collector.html) interface,
+i.e. they provide
+a [collect()]()
+method to produce snapshots. Implementers expose their registration-time metadata via
+`getMetricFamilyDescriptor()` (or `getMetricFamilyDescriptors()` on `MultiCollector`). When that
+returns `null`, the collector is not validated at registration and must avoid producing the same
+metric name and label schema as another collector, or exposition may be invalid.
+
+## prometheus-metrics-model
+
+The model is an internal library, implementing read-only immutable snapshots. These snapshots are
+returned by
+the [Collector.collect()]()
+method.
+
+There is no need for users to use `prometheus-metrics-model` directly. Users should use the API
+provided by `prometheus-metrics-core`, which includes the core metrics as well as callback metrics.
+
+However, maintainers of third-party metrics libraries might want to use `prometheus-metrics-model`
+if they want to add Prometheus exposition formats to their metrics library.
+
+## Exporters and exposition formats
+
+The `prometheus-metrics-exposition-formats` module converts snapshots to Prometheus exposition
+formats, like text format, OpenMetrics text format, or Prometheus protobuf format.
+
+The exporters like `prometheus-metrics-exporter-httpserver` or
+`prometheus-metrics-exporter-servlet-jakarta` use this to convert snapshots into the right format
+depending on the `Accept` header in the scrape request.
diff --git a/docs/content/internals/stability.md b/docs/content/internals/stability.md
new file mode 100644
index 000000000..d960c7ffa
--- /dev/null
+++ b/docs/content/internals/stability.md
@@ -0,0 +1,33 @@
+---
+title: API stability
+weight: 2
+---
+
+The published Java API surface is marked with the
+[`@StableApi`](/client_java/api/io/prometheus/metrics/annotations/StableApi.html) annotation. The
+annotation is opt-in: only annotated types and members are part of the stable, published API and
+follow semantic versioning — backwards-incompatible changes happen only in a major version bump.
+Unannotated public types are not part of the stability contract and may change in any release.
+
+`@StableApi` can be applied to a type to publish the type and its members, or to individual
+constructors, methods, and fields when only part of a public type is stable.
+
+## API diff check
+
+CI runs [japicmp](https://siom79.github.io/japicmp/) against a pinned baseline release and writes
+the published API diffs under `docs/apidiffs/current_vs_latest/`. Pull requests must keep those
+checked-in diffs up to date. Run it locally with:
+
+```bash
+mise run api-diff
+```
+
+Raw reports are written to `**/target/japicmp/*`.
+
+The baseline version is tracked in `pom.xml` and updated by Renovate; the published baseline diffs
+are stored under `docs/apidiffs/`.
+
+Pull requests that change `docs/apidiffs/current_vs_latest/` are automatically labeled
+`api-change` for additional maintainer review. If the committed API diff contains breaking-change
+markers such as `***!`, `---!`, or `+++!`, the pull request is also labeled
+`breaking-api-change`.
diff --git a/docs/content/migration/_index.md b/docs/content/migration/_index.md
new file mode 100644
index 000000000..7055c0287
--- /dev/null
+++ b/docs/content/migration/_index.md
@@ -0,0 +1,4 @@
+---
+title: Compatibility
+weight: 6
+---
diff --git a/docs/content/migration/simpleclient.md b/docs/content/migration/simpleclient.md
new file mode 100644
index 000000000..6d0580571
--- /dev/null
+++ b/docs/content/migration/simpleclient.md
@@ -0,0 +1,173 @@
+---
+title: Simpleclient
+weight: 1
+---
+
+The Prometheus Java client library 1.0.0 is a complete rewrite of the underlying data model, and is
+not backward
+compatible with releases 0.16.0 and older for a variety of reasons:
+
+- The old data model was based on [OpenMetrics](https://openmetrics.io). Native histograms don't fit
+ with the
+ OpenMetrics model because they don't follow the "every sample has exactly one double value"
+ paradigm. It was a lot
+ cleaner to implement a dedicated `prometheus-metrics-model` than trying to fit native histograms
+ into the existing
+ OpenMetrics-based model.
+- Version 0.16.0 and older has multiple Maven modules sharing the same Java package name. This is
+ not supported by the
+ Java module system. To support users of Java modules, we renamed all packages and made sure no
+ package is reused
+ across multiple Maven modules.
+
+## Migration using the Simpleclient Bridge
+
+Good news: Users of version 0.16.0 and older do not need to refactor all their instrumentation code
+to get started with
+1.0.0.
+
+We provide a migration module for bridging the old simpleclient `CollectorRegistry` to the new
+`PrometheusRegistry`.
+
+To use the bridge, add the following dependency:
+
+{{< tabs "uniqueid" >}}
+{{< tab "Gradle" >}}
+
+```groovy
+implementation 'io.prometheus:prometheus-metrics-simpleclient-bridge:1.0.0'
+```
+
+{{< /tab >}}
+{{< tab "Maven" >}}
+
+```xml
+
+
+ io.prometheus
+ prometheus-metrics-simpleclient-bridge
+ 1.0.0
+
+```
+
+{{< /tab >}}
+{{< /tabs >}}
+
+Then add the following to your code:
+
+```java
+SimpleclientCollector.builder().register();
+```
+
+This will make all metrics registered with simpleclient's `CollectorRegistry.defaultRegistry`
+available in the new
+`PrometheusRegistry.defaultRegistry`.
+
+If you are using custom registries, you can specify them like this:
+
+```java
+CollectorRegistry simpleclientRegistry = ...;
+PrometheusRegistry prometheusRegistry = ...;
+
+SimpleclientCollector.builder()
+ .collectorRegistry(simpleclientRegistry)
+ .register(prometheusRegistry);
+```
+
+## Refactoring the Instrumentation Code
+
+If you decide to get rid of the old 0.16.0 dependencies and use 1.0.0 only, you need to refactor
+your code:
+
+Dependencies:
+
+- `simpleclient` -> `prometheus-metrics-core`
+- `simpleclient_hotspot` -> `prometheus-metrics-instrumentation-jvm`
+- `simpleclient_httpserver` -> `prometheus-metrics-exporter-httpserver`
+- `simpleclient_servlet_jakarta` -> `prometheus-metrics-exporter-servlet-jakarta`
+
+As long as you are using high-level metric API like `Counter`, `Gauge`, `Histogram`, and `Summary`
+converting code to
+the new API is relatively straightforward. You will need to adapt the package name and apply some
+minor changes like
+using `builder()` instead of `build()` or using `labelValues()` instead of `labels()`.
+
+Example of the old 0.16.0 API:
+
+```java
+import io.prometheus.client.Counter;
+
+Counter counter = Counter.build()
+ .name("test")
+ .help("test counter")
+ .labelNames("path")
+ .register();
+
+counter.labels("/hello-world").inc();
+```
+
+Example of the new 1.0.0 API:
+
+```java
+import io.prometheus.metrics.core.metrics.Counter;
+
+Counter counter = Counter.builder()
+ .name("test")
+ .help("test counter")
+ .labelNames("path")
+ .register();
+
+counter.labelValues("/hello-world").inc();
+```
+
+Reasons why we changed the API: Changing the package names was a necessity because the previous
+package names were
+incompatible with the Java module system. However, renaming packages requires changing code anyway,
+so we decided to
+clean up some things. For example, the name `builder()` for a builder method is very common in the
+Java ecosystem, it's
+used in Spring, Lombok, and so on. So naming the method `builder()` makes the Prometheus library
+more aligned with the
+broader Java ecosystem.
+
+If you are using the low level `Collector` API directly, you should have a look at the new callback
+metric types,
+see [/getting-started/callbacks/]({{< relref "../getting-started/callbacks.md" >}}). Chances are
+good that the new callback metrics have
+an easier way to achieve what you need than the old 0.16.0 code.
+
+## JVM Metrics
+
+Version 0.16.0 provided the `simpleclient_hotspot` module for exposing built-in JVM metrics:
+
+```java
+DefaultExports.initialize();
+```
+
+With version 1.0.0 these metrics moved to the `prometheus-metrics-instrumentation-jvm` module and
+are initialized as follows:
+
+```java
+JvmMetrics.builder().register();
+```
+
+A full list of the available JVM metrics can be found
+on [/instrumentation/jvm]({{< relref "../instrumentation/jvm.md" >}}).
+
+Most JVM metric names remained the same, except for a few cases where the old 0.16.0 metric names
+were not compliant with the [OpenMetrics](https://openmetrics.io) specification. OpenMetrics
+requires the unit to be a suffix, so we renamed metrics where the unit was in the middle of the
+metric name and moved the unit to the end of the metric name. The following metric names changed:
+
+- `jvm_memory_bytes_committed` -> `jvm_memory_committed_bytes`
+- `jvm_memory_bytes_init` -> `jvm_memory_init_bytes`
+- `jvm_memory_bytes_max` -> `jvm_memory_max_bytes`
+- `jvm_memory_pool_bytes_committed` -> `jvm_memory_pool_committed_bytes`
+- `jvm_memory_pool_bytes_init` -> `jvm_memory_pool_init_bytes`
+- `jvm_memory_pool_bytes_max` -> `jvm_memory_pool_max_bytes`
+- `jvm_memory_pool_bytes_used` -> `jvm_memory_pool_used_bytes`
+- `jvm_memory_pool_collection_bytes_committed` -> `jvm_memory_pool_collection_committed_bytes`
+- `jvm_memory_pool_collection_bytes_init` -> `jvm_memory_pool_collection_init_bytes`
+- `jvm_memory_pool_collection_bytes_max` -> `jvm_memory_pool_collection_max_bytes`
+- `jvm_memory_pool_collection_bytes_used` -> `jvm_memory_pool_collection_used_bytes`
+- `jvm_info` -> `jvm_runtime_info`
diff --git a/docs/content/otel/_index.md b/docs/content/otel/_index.md
new file mode 100644
index 000000000..79e89d3a5
--- /dev/null
+++ b/docs/content/otel/_index.md
@@ -0,0 +1,4 @@
+---
+title: OpenTelemetry
+weight: 4
+---
diff --git a/docs/content/otel/jvm-runtime-metrics.md b/docs/content/otel/jvm-runtime-metrics.md
new file mode 100644
index 000000000..f8206be15
--- /dev/null
+++ b/docs/content/otel/jvm-runtime-metrics.md
@@ -0,0 +1,241 @@
+---
+title: JVM Runtime Metrics
+weight: 4
+---
+
+OpenTelemetry's
+[runtime-telemetry](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/runtime-telemetry)
+module is an alternative to
+[prometheus-metrics-instrumentation-jvm]({{< relref "../instrumentation/jvm.md" >}})
+for users who want JVM metrics following OTel semantic conventions.
+
+Key advantages:
+
+- Metric names follow
+ [OTel semantic conventions](https://opentelemetry.io/docs/specs/semconv/runtime/jvm-metrics/)
+- Java 17+ JFR support (context switches, network I/O,
+ lock contention, memory allocation)
+- Alignment with the broader OTel ecosystem
+
+Since OpenTelemetry's `opentelemetry-exporter-prometheus`
+already depends on this library's `PrometheusRegistry`,
+no additional code is needed in this library — only the
+OTel SDK wiring shown below.
+
+## Dependencies
+
+Use the [OTel Support]({{< relref "support.md" >}}) module
+to pull in the OTel SDK and Prometheus exporter, then add
+the runtime-telemetry instrumentation:
+
+{{< tabs "jvm-runtime-deps" >}}
+{{< tab "Gradle" >}}
+
+```groovy
+implementation 'io.prometheus:prometheus-metrics-otel-support:$version'
+
+// Use opentelemetry-runtime-telemetry-java8 (Java 8+)
+// or opentelemetry-runtime-telemetry-java17 (Java 17+, JFR-based)
+implementation(
+ 'io.opentelemetry.instrumentation:opentelemetry-runtime-telemetry-java8:$otelVersion-alpha'
+)
+```
+
+{{< /tab >}}
+{{< tab "Maven" >}}
+
+```xml
+
+ io.prometheus
+ prometheus-metrics-otel-support
+ $version
+ pom
+
+
+
+
+
+ io.opentelemetry.instrumentation
+ opentelemetry-runtime-telemetry-java8
+ $otelVersion-alpha
+
+
+
+```
+
+{{< /tab >}}
+{{< /tabs >}}
+
+## Standalone Setup
+
+If you **only** want OTel runtime metrics exposed as
+Prometheus, without any Prometheus Java client metrics:
+
+```java
+import io.opentelemetry.exporter.prometheus.PrometheusHttpServer;
+import io.opentelemetry.instrumentation.runtimemetrics.java8.RuntimeMetrics;
+import io.opentelemetry.sdk.OpenTelemetrySdk;
+import io.opentelemetry.sdk.metrics.SdkMeterProvider;
+
+PrometheusHttpServer prometheusServer =
+ PrometheusHttpServer.builder()
+ .setPort(9464)
+ .build();
+
+OpenTelemetrySdk openTelemetry =
+ OpenTelemetrySdk.builder()
+ .setMeterProvider(
+ SdkMeterProvider.builder()
+ .registerMetricReader(prometheusServer)
+ .build())
+ .build();
+
+RuntimeMetrics runtimeMetrics =
+ RuntimeMetrics.builder(openTelemetry).build();
+
+// Close on shutdown to stop metric collection and server
+Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+ runtimeMetrics.close();
+ prometheusServer.close();
+}));
+
+// Scrape at http://localhost:9464/metrics
+```
+
+## Combined with Prometheus Java Client Metrics
+
+If you already have Prometheus Java client metrics and want to
+add OTel runtime metrics to the **same** `/metrics`
+endpoint, use `PrometheusMetricReader` to bridge OTel
+metrics into a `PrometheusRegistry`:
+
+```java
+import io.prometheus.metrics.core.metrics.Counter;
+import io.prometheus.metrics.exporter.httpserver.HTTPServer;
+import io.prometheus.metrics.model.registry.PrometheusRegistry;
+import io.opentelemetry.exporter.prometheus.PrometheusMetricReader;
+import io.opentelemetry.instrumentation.runtimemetrics.java8.RuntimeMetrics;
+import io.opentelemetry.sdk.OpenTelemetrySdk;
+import io.opentelemetry.sdk.metrics.SdkMeterProvider;
+
+PrometheusRegistry registry =
+ new PrometheusRegistry();
+
+// Register Prometheus metrics as usual
+Counter myCounter = Counter.builder()
+ .name("my_requests_total")
+ .register(registry);
+
+// Bridge OTel metrics into the same registry
+PrometheusMetricReader reader =
+ PrometheusMetricReader.create();
+registry.register(reader);
+
+OpenTelemetrySdk openTelemetry =
+ OpenTelemetrySdk.builder()
+ .setMeterProvider(
+ SdkMeterProvider.builder()
+ .registerMetricReader(reader)
+ .build())
+ .build();
+
+RuntimeMetrics runtimeMetrics =
+ RuntimeMetrics.builder(openTelemetry).build();
+Runtime.getRuntime()
+ .addShutdownHook(new Thread(runtimeMetrics::close));
+
+// Expose everything on one endpoint
+HTTPServer.builder()
+ .port(9400)
+ .registry(registry)
+ .buildAndStart();
+```
+
+The [examples/example-otel-jvm-runtime-metrics](https://github.com/prometheus/client_java/tree/main/examples/example-otel-jvm-runtime-metrics)
+directory has a complete runnable example.
+
+## Configuration
+
+The `RuntimeMetricsBuilder` supports two configuration
+options:
+
+### `captureGcCause()`
+
+Adds a `jvm.gc.cause` attribute to the `jvm.gc.duration`
+metric, indicating why the garbage collection occurred
+(e.g. `G1 Evacuation Pause`, `System.gc()`):
+
+```java
+RuntimeMetrics.builder(openTelemetry)
+ .captureGcCause()
+ .build();
+```
+
+### `emitExperimentalTelemetry()`
+
+Enables additional experimental metrics beyond the stable
+set. These are not yet part of the OTel semantic conventions
+and may change in future releases:
+
+- Buffer pool metrics (direct and mapped byte buffers)
+- Extended CPU metrics
+- Extended memory pool metrics
+- File descriptor metrics
+
+```java
+RuntimeMetrics.builder(openTelemetry)
+ .emitExperimentalTelemetry()
+ .build();
+```
+
+Both options can be combined:
+
+```java
+RuntimeMetrics.builder(openTelemetry)
+ .captureGcCause()
+ .emitExperimentalTelemetry()
+ .build();
+```
+
+Selective per-metric registration is not supported by the
+runtime-telemetry API — it is all-or-nothing with these
+two toggles.
+
+## Java 17 JFR Support
+
+The `opentelemetry-runtime-telemetry-java17` variant adds
+JFR-based metrics. You can selectively enable features:
+
+```java
+import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature;
+import io.opentelemetry.instrumentation.runtimemetrics.java17.RuntimeMetrics;
+
+RuntimeMetrics.builder(openTelemetry)
+ .enableFeature(JfrFeature.BUFFER_METRICS)
+ .enableFeature(JfrFeature.NETWORK_IO_METRICS)
+ .enableFeature(JfrFeature.LOCK_METRICS)
+ .enableFeature(JfrFeature.CONTEXT_SWITCH_METRICS)
+ .build();
+```
+
+## Metric Names
+
+OTel metric names are converted to Prometheus format by
+the exporter. Examples:
+
+| OTel name | Prometheus name |
+| ---------------------------- | ---------------------------------- |
+| `jvm.memory.used` | `jvm_memory_used_bytes` |
+| `jvm.gc.duration` | `jvm_gc_duration_seconds` |
+| `jvm.thread.count` | `jvm_thread_count` |
+| `jvm.class.loaded` | `jvm_class_loaded` |
+| `jvm.cpu.recent_utilization` | `jvm_cpu_recent_utilization_ratio` |
+
+See [Names]({{< relref "names.md" >}}) for full details on
+how OTel names map to Prometheus names.
diff --git a/docs/content/otel/names.md b/docs/content/otel/names.md
new file mode 100644
index 000000000..66e40f7e2
--- /dev/null
+++ b/docs/content/otel/names.md
@@ -0,0 +1,58 @@
+---
+title: Names
+weight: 3
+---
+
+OpenTelemetry naming conventions are different from Prometheus naming conventions. The mapping from
+OpenTelemetry metric names to Prometheus metric names is well defined in
+OpenTelemetry's [Prometheus and OpenMetrics Compatibility](https://opentelemetry.io/docs/specs/otel/compatibility/prometheus_and_openmetrics/)
+spec, and
+the [OpenTelemetryExporter](/client_java/api/io/prometheus/metrics/exporter/opentelemetry/OpenTelemetryExporter.html)
+implements that specification.
+
+The goal is, if you set up a pipeline as illustrated below, you will see the same
+metric names in the Prometheus server as if you had exposed Prometheus metrics
+directly.
+
+![Image of a with the Prometheus client library pushing metrics to an OpenTelemetry collector][otel-pipeline]
+
+The main steps when converting OpenTelemetry metric names to Prometheus metric names are:
+
+- Escape illegal characters as described in [Unicode support]
+- If the metric has a unit, append the unit to the metric name, like `_seconds`.
+- If the metric type has a suffix, append it, like `_total` for counters.
+
+## `preserve_names`
+
+The Prometheus Java client library can also export its own metrics to OpenTelemetry using the
+[OpenTelemetryExporter](/client_java/api/io/prometheus/metrics/exporter/opentelemetry/OpenTelemetryExporter.html).
+
+For that exporter, `io.prometheus.exporter.opentelemetry.preserve_names=true` preserves metric
+names exactly as they were written in the Prometheus Java client.
+
+Examples:
+
+| Prometheus Java metric | Default OTel export | With `preserve_names=true` |
+| ---------------------------------- | --------------------- | --------------------------- |
+| `Counter("events")` | `events` | `events` |
+| `Counter("events_total")` | `events` | `events_total` |
+| `Counter("req").unit(BYTES)` | name `req`, unit `By` | name `req`, unit `By` |
+| `Counter("req_bytes").unit(BYTES)` | name `req`, unit `By` | name `req_bytes`, unit `By` |
+
+Today the default is `false` for backward compatibility. It is planned to change to `true` in the
+next major release.
+
+## Dots in Metric and Label Names
+
+OpenTelemetry defines not only a line protocol, but also _semantic conventions_, i.e. standardized
+metric and label names. For example,
+OpenTelemetry's [Semantic Conventions for HTTP Metrics](https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/http-metrics/)
+say that if you instrument an HTTP server with OpenTelemetry, you must have a histogram named
+`http.server.duration`.
+
+Most names defined in semantic conventions use dots.
+Dots in metric and label names are now supported in the Prometheus Java client library as
+described in [Unicode support].
+
+[Unicode support]: {{< relref "../exporters/unicode.md" >}}
+[otel-pipeline]: /client_java/images/otel-pipeline.png
diff --git a/docs/content/otel/otlp.md b/docs/content/otel/otlp.md
new file mode 100644
index 000000000..e2ea987dd
--- /dev/null
+++ b/docs/content/otel/otlp.md
@@ -0,0 +1,69 @@
+---
+title: OTLP
+weight: 1
+---
+
+The Prometheus Java client library allows you to push metrics to an
+OpenTelemetry endpoint using the OTLP protocol.
+
+![Image of a with the Prometheus client library pushing metrics to an OpenTelemetry collector][otel-pipeline]
+
+To implement this, you need to include `prometheus-metrics-exporter` as a dependency
+
+{{< tabs "uniqueid" >}}
+{{< tab "Gradle" >}}
+
+```groovy
+implementation 'io.prometheus:prometheus-metrics-exporter-opentelemetry:1.0.0'
+```
+
+{{< /tab >}}
+{{< tab "Maven" >}}
+
+```xml
+
+ io.prometheus
+ prometheus-metrics-exporter-opentelemetry
+ 1.0.0
+
+```
+
+{{< /tab >}}
+{{< /tabs >}}
+
+Initialize the `OpenTelemetryExporter` in your Java code:
+
+```java
+OpenTelemetryExporter.builder()
+ // optional: call configuration methods here
+ .buildAndStart();
+```
+
+By default, the `OpenTelemetryExporter` will push metrics every 60 seconds to
+`localhost:4317` using `grpc` protocol. You can configure this in code using
+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)
+environment variable to configure the endpoint. The Javadoc
+for [OpenTelemetryExporter.Builder](/client_java/api/io/prometheus/metrics/exporter/opentelemetry/OpenTelemetryExporter.Builder.html)
+shows which settings have corresponding OTel configuration. The intended use case is that if you
+attach the
+[OpenTelemetry Java agent](https://github.com/open-telemetry/opentelemetry-java-instrumentation/)
+for tracing, and use the Prometheus Java client for metrics, it is sufficient to configure the OTel
+agent because the Prometheus library will pick up the same configuration.
+
+The [examples/example-exporter-opentelemetry][opentelemetry-example] folder has
+a Docker compose with a complete end-to-end example, including a Java app, the
+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/docs/content/otel/support.md b/docs/content/otel/support.md
new file mode 100644
index 000000000..e3b8cbe3a
--- /dev/null
+++ b/docs/content/otel/support.md
@@ -0,0 +1,47 @@
+---
+title: OTel Support
+weight: 2
+---
+
+The `prometheus-metrics-otel-support` module bundles the
+OpenTelemetry SDK and the Prometheus exporter into a single
+POM dependency.
+
+Use this module when you want to combine OpenTelemetry
+instrumentations (e.g. JVM runtime metrics) with the
+Prometheus Java client on one `/metrics` endpoint.
+
+## Dependencies
+
+{{< tabs "otel-support-deps" >}}
+{{< tab "Gradle" >}}
+
+```groovy
+implementation 'io.prometheus:prometheus-metrics-otel-support:$version'
+```
+
+{{< /tab >}}
+{{< tab "Maven" >}}
+
+```xml
+
+ io.prometheus
+ prometheus-metrics-otel-support
+ $version
+ pom
+
+```
+
+{{< /tab >}}
+{{< /tabs >}}
+
+This single dependency replaces:
+
+- `io.opentelemetry:opentelemetry-sdk`
+- `io.opentelemetry:opentelemetry-exporter-prometheus`
+
+## Use Cases
+
+See [JVM Runtime Metrics]({{< relref "jvm-runtime-metrics.md" >}})
+for a concrete example of combining OTel JVM metrics with
+the Prometheus Java client.
diff --git a/docs/content/otel/tracing.md b/docs/content/otel/tracing.md
new file mode 100644
index 000000000..9d598c6f4
--- /dev/null
+++ b/docs/content/otel/tracing.md
@@ -0,0 +1,117 @@
+---
+title: Tracing
+weight: 2
+---
+
+OpenTelemetry’s
+[vision statement](https://github.com/open-telemetry/community/blob/main/mission-vision-values.md)
+says that
+[telemetry should be loosely coupled](https://github.com/open-telemetry/community/blob/main/mission-vision-values.md#telemetry-should-be-loosely-coupled),
+allowing end users to pick and choose from the pieces they want without having to bring in the rest
+of the project, too. In that spirit, you might choose to instrument your Java application with the
+Prometheus Java client library for metrics, and attach the
+[OpenTelemetry Java agent](https://github.com/open-telemetry/opentelemetry-java-instrumentation/)
+to get distributed tracing.
+
+First, if you attach the
+[OpenTelemetry Java agent](https://github.com/open-telemetry/opentelemetry-java-instrumentation/)
+you might want to turn off OTel's built-in metrics, because otherwise you get metrics from both the
+Prometheus Java client library and the OpenTelemetry agent (technically it's no problem to get both
+metrics, it's just not a common use case).
+
+```bash
+# This will tell the OpenTelemetry agent not to send metrics, just traces and logs.
+export OTEL_METRICS_EXPORTER=none
+```
+
+Now, start your application with the OpenTelemetry Java agent attached for traces and logs.
+
+```bash
+java -javaagent:path/to/opentelemetry-javaagent.jar -jar myapp.jar
+```
+
+With the OpenTelemetry Java agent attached, the Prometheus client library will do a lot of magic
+under the hood.
+
+- `service.name` and `service.instance.id` are used in OpenTelemetry to uniquely identify a service
+ instance. The Prometheus client library will automatically use the same `service.name` and
+ `service.instance.id` as the agent when pushing metrics in OpenTelemetry format. That way the
+ monitoring backend will see that the metrics and the traces are coming from the same instance.
+- Exemplars are added automatically if a Prometheus metric is updated in the context of a
+ distributed OpenTelemetry trace.
+- If a Span is used as an Exemplar, the Span is marked with the Span attribute `exemplar="true"`.
+ This can be used in the OpenTelemetry's sampling policy to make sure Exemplars are always sampled.
+
+Here's more context on the `exemplar="true"` Span attribute: Many users of tracing libraries don't
+keep 100% of their trace data, because traces are very repetitive. It is very common to sample only
+10% of traces and discard 90%. However, this can be an issue with Exemplars: In 90% of the cases
+Exemplars would point to a trace that has been thrown away.
+
+To solve this, the Prometheus Java client library annotates each Span that has been used as an
+Exemplar with the `exemplar="true"` Span attribute.
+
+The sampling policy in the OpenTelemetry collector can be configured to keep traces with this
+attribute. There's no risk that this results in a significant increase in trace data, because new
+Exemplars are only selected every
+[`minRetentionPeriodSeconds`]({{< relref "../config/config.md#exemplar-properties" >}}) seconds.
+
+Here's an example of how to configure OpenTelemetry's
+[tail sampling processor](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/tailsamplingprocessor/)
+to sample all Spans marked with `exemplar="true"`, and then discard 90% of the traces:
+
+```yaml
+policies:
+ [
+ {
+ name: keep-exemplars,
+ type: string_attribute,
+ string_attribute: { key: "exemplar", values: ["true"] },
+ },
+ { name: keep-10-percent, type: probabilistic, probabilistic: { sampling_percentage: 10 } },
+ ]
+```
+
+The [examples/example-exemplar-tail-sampling/](https://github.com/prometheus/client_java/tree/main/examples/example-exemplars-tail-sampling)
+directory has a complete end-to-end example, with a distributed Java application with two services,
+an OpenTelemetry collector, Prometheus, Tempo as a trace database, and Grafana dashboards. Use
+docker-compose as described in the example's readme to run the example and explore the results.
+
+## Adding custom labels to exemplars
+
+Automatically-sampled exemplars carry the `trace_id` and `span_id` labels. You can attach
+additional, custom labels (for example an internal identifier) to every automatically-sampled
+exemplar. There are two options.
+
+### Global (all metrics)
+
+Register a global supplier to add custom labels to the exemplars of _all_ metrics, including
+metrics registered by third-party libraries that you do not control. This is the right option when
+you cannot modify the code that creates the metric:
+
+```java
+ExemplarLabelsSupplier.setExemplarLabelsSupplier(
+ () -> Labels.of("management_id", currentManagementId()));
+```
+
+### Per metric
+
+If you only want the extra labels on a specific metric you define yourself, use the builder:
+
+```java
+Counter counter =
+ Counter.builder()
+ .name("requests_total")
+ .exemplarLabelsSupplier(() -> Labels.of("management_id", currentManagementId()))
+ .build();
+```
+
+### Notes
+
+- The supplier is invoked on the (rate-limited) hot path each time an exemplar is sampled, so it
+ should be cheap. It may return dynamic, request-scoped values (e.g. read from a thread-local).
+- Custom labels are only added when a valid, sampled span context is present; the supplier never
+ causes an exemplar to be created on its own.
+- Precedence on a label-name collision: the reserved `trace_id`/`span_id` labels always win, then
+ the per-metric supplier, then the global supplier. Colliding labels are silently dropped.
+- If the supplier throws, the exception is swallowed and the exemplar is created without the
+ additional labels, so a misbehaving supplier never breaks metric collection.
diff --git a/docs/data/menu/extra.yaml b/docs/data/menu/extra.yaml
new file mode 100644
index 000000000..ff5756bf8
--- /dev/null
+++ b/docs/data/menu/extra.yaml
@@ -0,0 +1,6 @@
+---
+header:
+ - name: GitHub
+ ref: https://github.com/prometheus/client_java
+ icon: gdoc_github
+ external: true
diff --git a/docs/data/menu/more.yaml b/docs/data/menu/more.yaml
new file mode 100644
index 000000000..ee55dc634
--- /dev/null
+++ b/docs/data/menu/more.yaml
@@ -0,0 +1,14 @@
+---
+more:
+ - name: JavaDoc
+ ref: "/client_java/api"
+ external: true
+ icon: "gdoc_bookmark"
+ - name: Releases
+ ref: "https://github.com/prometheus/client_java/releases"
+ external: true
+ icon: "gdoc_download"
+ - name: Github
+ ref: "https://github.com/prometheus/client_java"
+ external: true
+ icon: "gdoc_github"
diff --git a/docs/hugo.toml b/docs/hugo.toml
new file mode 100644
index 000000000..9223f49ef
--- /dev/null
+++ b/docs/hugo.toml
@@ -0,0 +1,34 @@
+baseURL = "http://localhost"
+languageCode = 'en-us'
+title = "client_java"
+theme = "hugo-geekdoc"
+
+pluralizeListTitles = false
+
+# Geekdoc required configuration
+#pygmentsUseClasses = true
+pygmentsUseClasses = false
+pygmentsCodeFences = true
+disablePathToLower = true
+# geekdocFileTreeSortBy = "linkTitle"
+
+# Required if you want to render robots.txt template
+enableRobotsTXT = true
+
+# Needed for mermaid shortcodes
+[markup]
+[markup.goldmark.renderer]
+# Needed for mermaid shortcode
+unsafe = true
+[markup.tableOfContents]
+startLevel = 1
+endLevel = 9
+[markup.highlight]
+style = 'solarized-dark'
+
+[taxonomies]
+tag = "tags"
+
+[caches]
+[caches.images]
+dir = ':cacheDir/images'
diff --git a/docs/static/.gitignore b/docs/static/.gitignore
new file mode 100644
index 000000000..eedd89b45
--- /dev/null
+++ b/docs/static/.gitignore
@@ -0,0 +1 @@
+api
diff --git a/docs/static/brand.svg b/docs/static/brand.svg
new file mode 100644
index 000000000..5c51f66d9
--- /dev/null
+++ b/docs/static/brand.svg
@@ -0,0 +1,50 @@
+
+
+
+
\ No newline at end of file
diff --git a/docs/static/custom.css b/docs/static/custom.css
new file mode 100644
index 000000000..ed919a35d
--- /dev/null
+++ b/docs/static/custom.css
@@ -0,0 +1,43 @@
+/*
+ * Didn't find much time to create a theme yet,
+ * so there are just a few non-default settings for now.
+ */
+:root,
+:root[color-theme="light"] {
+ --header-background: #222222;
+ --footer-background: #e6522c;
+ --footer-link-color: #ffffff;
+ --footer-link-color-visited: #ffffff;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ --header-background: #222222;
+ --footer-background: #e6522c;
+ --footer-link-color: #ffffff;
+ --footer-link-color-visited: #ffffff;
+ }
+}
+
+:root[color-theme="dark"]
+{
+ --header-background: #111c24;
+ --body-background: #1f1f21;
+ --footer-background: #e6522c;
+ --footer-link-color: #ffffff;
+ --footer-link-color-visited: #ffffff;
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --header-background: #111c24;
+ --body-background: #1f1f21;
+ --footer-background: #e6522c;
+ --footer-link-color: #ffffff;
+ --footer-link-color-visited: #ffffff;
+ }
+}
+
+.gdoc-markdown pre,.gdoc-markdown code {
+ overflow: auto;
+}
\ No newline at end of file
diff --git a/docs/static/favicon/favicon-16x16.png b/docs/static/favicon/favicon-16x16.png
new file mode 100644
index 000000000..7a8cc5816
Binary files /dev/null and b/docs/static/favicon/favicon-16x16.png differ
diff --git a/docs/static/favicon/favicon-32x32.png b/docs/static/favicon/favicon-32x32.png
new file mode 100644
index 000000000..7d5a3ae3c
Binary files /dev/null and b/docs/static/favicon/favicon-32x32.png differ
diff --git a/docs/static/favicon/favicon.ico b/docs/static/favicon/favicon.ico
new file mode 100644
index 000000000..34bd1fbf0
Binary files /dev/null and b/docs/static/favicon/favicon.ico differ
diff --git a/docs/static/favicon/favicon.svg b/docs/static/favicon/favicon.svg
new file mode 100644
index 000000000..5c51f66d9
--- /dev/null
+++ b/docs/static/favicon/favicon.svg
@@ -0,0 +1,50 @@
+
+
+
+
\ No newline at end of file
diff --git a/docs/static/images/model.png b/docs/static/images/model.png
new file mode 100644
index 000000000..ee5094596
Binary files /dev/null and b/docs/static/images/model.png differ
diff --git a/docs/static/images/otel-pipeline.png b/docs/static/images/otel-pipeline.png
new file mode 100644
index 000000000..5cf8eda3d
Binary files /dev/null and b/docs/static/images/otel-pipeline.png differ
diff --git a/docs/themes/hugo-geekdoc/LICENSE b/docs/themes/hugo-geekdoc/LICENSE
new file mode 100644
index 000000000..3812eb46b
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2022 Robert Kaussow
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/docs/themes/hugo-geekdoc/README.md b/docs/themes/hugo-geekdoc/README.md
new file mode 100644
index 000000000..99358d83c
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/README.md
@@ -0,0 +1,46 @@
+# Geekdoc
+
+[](https://ci.thegeeklab.de/repos/thegeeklab/hugo-geekdoc)
+[](https://gohugo.io)
+[](https://github.com/thegeeklab/hugo-geekdoc/releases/latest)
+[](https://github.com/thegeeklab/hugo-geekdoc/graphs/contributors)
+[](https://github.com/thegeeklab/hugo-geekdoc/blob/main/LICENSE)
+
+Geekdoc is a simple Hugo theme for documentations. It is intentionally designed as a fast and lean theme and may not fit the requirements of complex projects. If a more feature-complete theme is required there are a lot of good alternatives out there. You can find a demo and the full documentation at [https://geekdocs.de](https://geekdocs.de).
+
+
+
+## Build and release process
+
+This theme is subject to a CI driven build and release process common for software development. During the release build, all necessary assets are automatically built by [webpack](https://webpack.js.org/) and bundled in a release tarball. You can download the latest release from the GitHub [release page](https://github.com/thegeeklab/hugo-geekdoc/releases).
+
+Due to the fact that `webpack` and `npm scripts` are used as pre-processors, the theme cannot be used from the main branch by default. If you want to use the theme from a cloned branch instead of a release tarball you'll need to install `webpack` locally and run the build script once to create all required assets.
+
+```shell
+# install required packages from package.json
+npm install
+
+# run the build script to build required assets
+npm run build
+
+# build release tarball
+npm run pack
+```
+
+See the [Getting Started Guide](https://geekdocs.de/usage/getting-started/) for details about the different setup options.
+
+## Contributors
+
+Special thanks to all [contributors](https://github.com/thegeeklab/hugo-geekdoc/graphs/contributors). If you would like to contribute, please see the [instructions](https://github.com/thegeeklab/hugo-geekdoc/blob/main/CONTRIBUTING.md).
+
+Geekdoc is inspired and partially based on the [hugo-book](https://github.com/alex-shpak/hugo-book) theme, thanks [Alex Shpak](https://github.com/alex-shpak/) for your work.
+
+## License
+
+This project is licensed under the MIT License - see the [LICENSE](https://github.com/thegeeklab/hugo-geekdoc/blob/main/LICENSE) file for details.
+
+The used SVG icons and generated icon fonts are licensed under the license of the respective icon pack:
+
+- Font Awesome: [CC BY 4.0 License](https://github.com/FortAwesome/Font-Awesome#license)
+- IcoMoon Free Pack: [GPL/CC BY 4.0](https://icomoon.io/#icons-icomoon)
+- Material Icons: [Apache License 2.0](https://github.com/google/material-design-icons/blob/main/LICENSE)
diff --git a/docs/themes/hugo-geekdoc/VERSION b/docs/themes/hugo-geekdoc/VERSION
new file mode 100644
index 000000000..d0cca40aa
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/VERSION
@@ -0,0 +1 @@
+v0.41.1
diff --git a/docs/themes/hugo-geekdoc/archetypes/docs.md b/docs/themes/hugo-geekdoc/archetypes/docs.md
new file mode 100644
index 000000000..aa0d88f7b
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/archetypes/docs.md
@@ -0,0 +1,7 @@
+---
+title: "{{ .Name | humanize | title }}"
+weight: 1
+# geekdocFlatSection: false
+# geekdocToc: 6
+# geekdocHidden: false
+---
diff --git a/docs/themes/hugo-geekdoc/archetypes/posts.md b/docs/themes/hugo-geekdoc/archetypes/posts.md
new file mode 100644
index 000000000..fdccff8ae
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/archetypes/posts.md
@@ -0,0 +1,4 @@
+---
+title: "{{ replace .Name "-" " " | title }}"
+date: {{ .Date }}
+---
diff --git a/docs/themes/hugo-geekdoc/assets/search/config.json b/docs/themes/hugo-geekdoc/assets/search/config.json
new file mode 100644
index 000000000..1a5582a2e
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/assets/search/config.json
@@ -0,0 +1,8 @@
+{{- $searchDataFile := printf "search/%s.data.json" .Language.Lang -}}
+{{- $searchData := resources.Get "search/data.json" | resources.ExecuteAsTemplate $searchDataFile . | resources.Minify -}}
+{
+ "dataFile": {{ $searchData.RelPermalink | jsonify }},
+ "indexConfig": {{ .Site.Params.geekdocSearchConfig | jsonify }},
+ "showParent": {{ if .Site.Params.geekdocSearchShowParent }}true{{ else }}false{{ end }},
+ "showDescription": {{ if .Site.Params.geekdocSearchshowDescription }}true{{ else }}false{{ end }}
+}
diff --git a/docs/themes/hugo-geekdoc/assets/search/data.json b/docs/themes/hugo-geekdoc/assets/search/data.json
new file mode 100644
index 000000000..f1c0e804e
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/assets/search/data.json
@@ -0,0 +1,13 @@
+[
+ {{ range $index, $page := (where .Site.Pages "Params.geekdocProtected" "ne" true) }}
+ {{ if ne $index 0 }},{{ end }}
+ {
+ "id": {{ $index }},
+ "href": "{{ $page.RelPermalink }}",
+ "title": {{ (partial "utils/title" $page) | jsonify }},
+ "parent": {{ with $page.Parent }}{{ (partial "utils/title" .) | jsonify }}{{ else }}""{{ end }},
+ "content": {{ $page.Plain | jsonify }},
+ "description": {{ $page.Summary | plainify | jsonify }}
+ }
+ {{ end }}
+]
diff --git a/docs/themes/hugo-geekdoc/assets/sprites/geekdoc.svg b/docs/themes/hugo-geekdoc/assets/sprites/geekdoc.svg
new file mode 100644
index 000000000..4f3cfd291
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/assets/sprites/geekdoc.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/themes/hugo-geekdoc/data/assets.json b/docs/themes/hugo-geekdoc/data/assets.json
new file mode 100644
index 000000000..81541fbbc
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/data/assets.json
@@ -0,0 +1,158 @@
+{
+ "main.js": {
+ "src": "js/main-924a1933.bundle.min.js",
+ "integrity": "sha512-0QF6awwW0WbBo491yytmULiHrc9gx94bloJ9MSXIvdJh3YHWw7CWyeX2YXu0rzOQefJp4jW/I6ZjUDYpNVFhdA=="
+ },
+ "colortheme.js": {
+ "src": "js/colortheme-d3e4d351.bundle.min.js",
+ "integrity": "sha512-HpQogL/VeKqG/v1qYOfJOgFUzBnQvW4yO4tAJO+54IiwbLbB9feROdeaYf7dpO6o5tSHsSZhaYLhtLMRlEgpJQ=="
+ },
+ "mermaid.js": {
+ "src": "js/mermaid-d305d450.bundle.min.js",
+ "integrity": "sha512-TASG03QptoVv1mkfOL47vm5A5kvmyOrnsi8PXhc82j1+FuHZuMOHXc2x5/jGEkOxbKi7mum0h/W7qYhrV29raw=="
+ },
+ "katex.js": {
+ "src": "js/katex-d4d5881d.bundle.min.js",
+ "integrity": "sha512-M8CLtMTu/HVXo11Et+lv3OqPanLf5Bl+GljNAn2yQuLclg/ZpZK1KUpHDRsZJhmkhCcCH90+bVj5CW3lLlmBgg=="
+ },
+ "search.js": {
+ "src": "js/search-9719be99.bundle.min.js",
+ "integrity": "sha512-/7NZxFUEbalC/8RKDgfAsHFDI42/Ydp33uJmCLckZgnO+kuz9LrTfmPFfVJxPJ31StMxa3MTQ5Jq049CmNK4pw=="
+ },
+ "js/637-86fbbecd.chunk.min.js": {
+ "src": "js/637-86fbbecd.chunk.min.js",
+ "integrity": "sha512-vD1y0C4MPPV/JhEKmNVAye9SQg7mB5v87nLf63keSALdnM7P+L0ybjEn2MzYzVTzs6JnOCryM7A6/t0TkYucDA=="
+ },
+ "js/116-341f79d9.chunk.min.js": {
+ "src": "js/116-341f79d9.chunk.min.js",
+ "integrity": "sha512-F7tq1KsF5mnJl0AAA6x2jZcx8x69kEZrUIZJJM4RZ1KlEO79yrrFHf4CZRvhNrYOxmkBpkQ84U9J0vFtRPKjTw=="
+ },
+ "js/545-8e970b03.chunk.min.js": {
+ "src": "js/545-8e970b03.chunk.min.js",
+ "integrity": "sha512-vDOXX1FstnT8UMkRIAMn6z4ucL8LVqI5kZw+T7LrD8pGC9xtKwwhWcmNeqnngc7FHc5Ogt7ppXBNp+uFPUgrJg=="
+ },
+ "js/728-5df4a5e5.chunk.min.js": {
+ "src": "js/728-5df4a5e5.chunk.min.js",
+ "integrity": "sha512-vX2dPV1VjOgv8DP4XbZ9xk9ZzHS9hPAUwPfHM8UG42efxXxH/qCqTpyavqob98onxR2FuiF+j1Vn56d3wqsgaw=="
+ },
+ "js/81-4e653aac.chunk.min.js": {
+ "src": "js/81-4e653aac.chunk.min.js",
+ "integrity": "sha512-a80h3DpDlMG6HhYXv9n9Q7r1M+rQX5kfJ7sFhfmPHlDRVimult9nn7vvTHFzTzmMFM+tLcfg4pZGd+AkxPcjEw=="
+ },
+ "js/430-cc171d93.chunk.min.js": {
+ "src": "js/430-cc171d93.chunk.min.js",
+ "integrity": "sha512-cqQyiIE22ZPo2PIPR4eb0DPSu1TWjxgJUKrIIyfVF48gc2vdLKnbHzWBZg6MpiOWYmUvJb5Ki+n5U6qEvNp2KQ=="
+ },
+ "js/729-32b017b3.chunk.min.js": {
+ "src": "js/729-32b017b3.chunk.min.js",
+ "integrity": "sha512-KAW7lnN0NHmIzfD6aIwVaU3TcpUkO8ladLrbOE83zq80NOJH/MGS4Ep+2rIfQZTvZP+a7nqZLHkmezfs27c2pw=="
+ },
+ "js/773-8f0c4fb8.chunk.min.js": {
+ "src": "js/773-8f0c4fb8.chunk.min.js",
+ "integrity": "sha512-HxtbZvs0J28pB9fImN8n82aprG/GW0QenIBzC7BHWhEUX6IhmxTeBqG4IZFbbAURG17VegOr2UlJg6w0qaX9gw=="
+ },
+ "js/433-f2655a46.chunk.min.js": {
+ "src": "js/433-f2655a46.chunk.min.js",
+ "integrity": "sha512-/yMUz6rxhVpvCPpQG+f28jFgdJK+X/5/3XWVsrAE2FHC57jxnHaL7SxZluZ4klUl0YsRCrhxAQj8maNspwwH1Q=="
+ },
+ "js/546-560b35c2.chunk.min.js": {
+ "src": "js/546-560b35c2.chunk.min.js",
+ "integrity": "sha512-am1/hYno7/cFQ8reHZqnbsth2KcphvKqLfkueVIm8I/i/6f9u+bbc0Z6zpYTLysl3oWddYXqyeO58zXoJoDVIA=="
+ },
+ "js/118-f1de6a20.chunk.min.js": {
+ "src": "js/118-f1de6a20.chunk.min.js",
+ "integrity": "sha512-tikydCOmBT1keN0AlCqvkpvbV1gB9U8lVXX8wmrS6fQ2faNc8DnH1QV9dzAlLtGeA1p8HAXnh+AevnVKxhXVbg=="
+ },
+ "js/19-86f47ecd.chunk.min.js": {
+ "src": "js/19-86f47ecd.chunk.min.js",
+ "integrity": "sha512-qRG0UrV25Kr/36tJTPZ49QobR6a/zv2BRAMDzSZwjlPgqSwse1HtgP9EEZtn59b1Vq7ayB1LoWfB9MZ9Gcm7Gw=="
+ },
+ "js/361-f7cd601a.chunk.min.js": {
+ "src": "js/361-f7cd601a.chunk.min.js",
+ "integrity": "sha512-7kwaFQhXUyiM/v2v0n6vI9wz6nSAu7sz2236r+MbwT0r4aBxYqeOxij+PkGnTUqR2n1UExnbWKjuruDi9V/H5g=="
+ },
+ "js/519-8d0cec7f.chunk.min.js": {
+ "src": "js/519-8d0cec7f.chunk.min.js",
+ "integrity": "sha512-tFsZN3iyUMIMeB/b4E1PZNOFDKqMM4Fes63RGNkHNhtRTL/AIUpqPcTKZ+Fi2ZTdyYvPSTtjc5urnzLUi196Wg=="
+ },
+ "js/747-b55f0f97.chunk.min.js": {
+ "src": "js/747-b55f0f97.chunk.min.js",
+ "integrity": "sha512-hoyvC5SSJcX9NGij9J9l4Ov1JAFNBX0UxlFXyiB5TC7TGW3lgIvm41zyfKhLyJudVGftY/qKxIO2EYtYD2pqOQ=="
+ },
+ "js/642-12e7dea2.chunk.min.js": {
+ "src": "js/642-12e7dea2.chunk.min.js",
+ "integrity": "sha512-ZVUj7NYSa8mMHdWaztAf3DCg7qznXTbMWWwqJaS2nfaqh0lVDOf5kVExPy6SGkXCeNu/B9gGbWLtDUa7kHFF6A=="
+ },
+ "js/626-1706197a.chunk.min.js": {
+ "src": "js/626-1706197a.chunk.min.js",
+ "integrity": "sha512-OlpbPXiGmQJR/ISfBSsHU2UGATggZDuHbopvAhhfVpw7ObMZgc/UvE6pK1FmGCjgI9iS+qmPhQyvf9SIbLFyxQ=="
+ },
+ "js/438-760c9ed3.chunk.min.js": {
+ "src": "js/438-760c9ed3.chunk.min.js",
+ "integrity": "sha512-Wo2DxS59Y8DVBTWNWDUmg6V+UCyLoiDd4sPs2xc7TkflQy7reGWPt/oHZCANXeGjZPpqcR3qfKYidNofUyIWEA=="
+ },
+ "js/639-88c6538a.chunk.min.js": {
+ "src": "js/639-88c6538a.chunk.min.js",
+ "integrity": "sha512-KbTKHxx+/Xwv+GH8jQsIJ9X1CFaGSsqgeSXnR8pW27YZpFz4ly8R6K7h+yq6P2b2AzQdW7krradZzyNo7Vz26w=="
+ },
+ "js/940-25dfc794.chunk.min.js": {
+ "src": "js/940-25dfc794.chunk.min.js",
+ "integrity": "sha512-qst5aejItmhzMvZ3CsAXyJe2F3FtLkyZwBqj422/8ViyQptcQFgP3x8bPsLwJEfiWFJVrLJkk4VhwflQuIyDtw=="
+ },
+ "js/662-17acb8f4.chunk.min.js": {
+ "src": "js/662-17acb8f4.chunk.min.js",
+ "integrity": "sha512-S/UlqDqwt++RzVZMVqjsdCNyhe1xNQ9/Qm38yIphmXfn9VBHzGqobIQTuhloYZVfTE4/GezrH+1T7mdrUqpAKQ=="
+ },
+ "js/579-9222afff.chunk.min.js": {
+ "src": "js/579-9222afff.chunk.min.js",
+ "integrity": "sha512-rl3bxxl/uhUFYlIuoHfVQE+VkmxfJr7TAuC/fxOBJXBCCMpdxP0XCPzms1zjEjOVjIs4bi4SUwn8r4STSl09Lg=="
+ },
+ "js/771-942a62df.chunk.min.js": {
+ "src": "js/771-942a62df.chunk.min.js",
+ "integrity": "sha512-8WfA8U1Udlfa6uWAYbdNKJzjlJ91qZ0ZhC+ldKdhghUgilxqA6UmZxHFKGRDQydjOFDk828O28XVmZU2IEvckA=="
+ },
+ "js/506-6950d52c.chunk.min.js": {
+ "src": "js/506-6950d52c.chunk.min.js",
+ "integrity": "sha512-h2po0SsM4N3IXiBbNWlIbasxX7zSm5XVDpgYfmsEmcfQkMcFwJtTJGppek085Mxi1XZmrhjfxq2AUtnUs03LJg=="
+ },
+ "js/76-732e78f1.chunk.min.js": {
+ "src": "js/76-732e78f1.chunk.min.js",
+ "integrity": "sha512-ZjF2oB76jiCtdQNJZ9v1MUJSPaBcZCXmTA2T3qDBuU260uVA99wGeprrNQ3WdHQeK+VYXCq26dOE9w+I3b6Q4w=="
+ },
+ "js/476-86e5cf96.chunk.min.js": {
+ "src": "js/476-86e5cf96.chunk.min.js",
+ "integrity": "sha512-siq24cNKFc1tXGACAQlpbXOb2gRKDnncf39INGAPlnJSiAsYewhNusq1UxhMDFA836eucVq7NzE1TqEYskI0ug=="
+ },
+ "js/813-0d3c16f5.chunk.min.js": {
+ "src": "js/813-0d3c16f5.chunk.min.js",
+ "integrity": "sha512-gDVyQtM781xlTfyZzuEJ1tnQWyasbFKLRPwgGUF5lpdS3QpW6KTIwCnMuVn2b5XF2qKSxpei9YNIushpBI4ILA=="
+ },
+ "js/423-897d7f17.chunk.min.js": {
+ "src": "js/423-897d7f17.chunk.min.js",
+ "integrity": "sha512-ERAmXYsLT59PDGFPLTHNgaNw5CsaTOK88orlaXr+7SOxf+Yjf5fvDmpXCNJe1odvU6OF4cajtlVM1qO9hzOqWw=="
+ },
+ "js/535-dcead599.chunk.min.js": {
+ "src": "js/535-dcead599.chunk.min.js",
+ "integrity": "sha512-3gB2l6iJbt94EMd1Xh6udlMXjdHlAbuRKkyl87X/LSuG1fGbfTe11O5ma+un13BBX1wZ1xnHtUv6Fyc3pgbgDg=="
+ },
+ "main.scss": {
+ "src": "main-252d384c.min.css",
+ "integrity": "sha512-WiV7BVk76Yp0EACJrwdWDk7+WNa+Jyiupi9aCKFrzZyiKkXk7BH+PL2IJcuDQpCMtMBFJEgen2fpKu9ExjjrUQ=="
+ },
+ "katex.css": {
+ "src": "katex-66092164.min.css",
+ "integrity": "sha512-ng+uY3bZP0IENn+fO0T+jdk1v1r7HQJjsVRJgzU+UiJJadAevmo0gVNrpVxrBFGpRQqSz42q20uTre1C1Qrnow=="
+ },
+ "mobile.scss": {
+ "src": "mobile-79ddc617.min.css",
+ "integrity": "sha512-dzw2wMOouDwhSgstQKLbXD/vIqS48Ttc2IV6DeG7yam9yvKUuChJVaworzL8s2UoGMX4x2jEm50PjFJE4R4QWw=="
+ },
+ "print.scss": {
+ "src": "print-735ccc12.min.css",
+ "integrity": "sha512-c28KLNtBnKDW1+/bNWFhwuGBLw9octTXA2wnuaS2qlvpNFL0DytCapui9VM4YYkZg6e9TVp5LyuRQc2lTougDw=="
+ },
+ "custom.css": {
+ "src": "custom.css",
+ "integrity": "sha512-1kALo+zc1L2u1rvyxPIew+ZDPWhnIA1Ei2rib3eHHbskQW+EMxfI9Ayyva4aV+YRrHvH0zFxvPSFIuZ3mfsbRA=="
+ }
+}
diff --git a/docs/themes/hugo-geekdoc/i18n/cs.yaml b/docs/themes/hugo-geekdoc/i18n/cs.yaml
new file mode 100644
index 000000000..71dd8ed30
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/i18n/cs.yaml
@@ -0,0 +1,53 @@
+---
+edit_page: Upravit stránku
+
+nav_navigation: Navigace
+nav_tags: Tagy
+nav_more: Více
+nav_top: Zpět nahoru
+
+form_placeholder_search: Vyhledat
+
+error_page_title: Ztracen? Nic se neděje
+error_message_title: Ztracen?
+error_message_code: Error 404
+error_message_text: >
+ Vypadá to že stránka, kterou hledáte, neexistuje. Nemějte obavy, můžete
+ se vrátit zpět na domovskou stránku.
+
+button_toggle_dark: Přepnout tmavý/světlý/automatický režim
+button_nav_open: Otevřít navigaci
+button_nav_close: Zavřít navigaci
+button_menu_open: Otevřít lištu nabídky
+button_menu_close: Zavřít lištu nabídky
+button_homepage: Zpět na domovskou stránku
+
+title_anchor_prefix: "Odkaz na:"
+
+posts_read_more: Přečíst celý příspěvek
+posts_read_time:
+ one: "Doba čtení: 1 minuta"
+ other: "Doba čtení: {{ . }} minut(y)"
+posts_update_prefix: Naposledy upraveno
+posts_count:
+ one: "Jeden příspěvek"
+ other: "Příspěvků: {{ . }}"
+posts_tagged_with: Všechny příspěvky označeny '{{ . }}'
+
+footer_build_with: >
+ Vytvořeno za pomocí Hugo a
+
+footer_legal_notice: Právní upozornění
+footer_privacy_policy: Zásady ochrany soukromí
+footer_content_license_prefix: >
+ Obsah licencovaný pod
+
+language_switch_no_tranlation_prefix: "Stránka není přeložena:"
+
+propertylist_required: povinné
+propertylist_optional: volitené
+propertylist_default: výchozí
+
+pagination_page_prev: předchozí
+pagination_page_next: další
+pagination_page_state: "{{ .PageNumber }}/{{ .TotalPages }}"
diff --git a/docs/themes/hugo-geekdoc/i18n/de.yaml b/docs/themes/hugo-geekdoc/i18n/de.yaml
new file mode 100644
index 000000000..ae3dc99fc
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/i18n/de.yaml
@@ -0,0 +1,53 @@
+---
+edit_page: Seite bearbeiten
+
+nav_navigation: Navigation
+nav_tags: Tags
+nav_more: Weitere
+nav_top: Nach oben
+
+form_placeholder_search: Suchen
+
+error_page_title: Verlaufen? Keine Sorge
+error_message_title: Verlaufen?
+error_message_code: Fehler 404
+error_message_text: >
+ Wir können die Seite nach der Du gesucht hast leider nicht finden. Keine Sorge,
+ wir bringen Dich zurück zur Startseite.
+
+button_toggle_dark: Wechsel zwischen Dunkel/Hell/Auto Modus
+button_nav_open: Navigation öffnen
+button_nav_close: Navigation schließen
+button_menu_open: Menüband öffnen
+button_menu_close: Menüband schließen
+button_homepage: Zurück zur Startseite
+
+title_anchor_prefix: "Link zu:"
+
+posts_read_more: Ganzen Artikel lesen
+posts_read_time:
+ one: "Eine Minute Lesedauer"
+ other: "{{ . }} Minuten Lesedauer"
+posts_update_prefix: Aktualisiert am
+posts_count:
+ one: "Ein Artikel"
+ other: "{{ . }} Artikel"
+posts_tagged_with: Alle Artikel mit dem Tag '{{ . }}'
+
+footer_build_with: >
+ Entwickelt mit Hugo und
+
+footer_legal_notice: Impressum
+footer_privacy_policy: Datenschutzerklärung
+footer_content_license_prefix: >
+ Inhalt lizensiert unter
+
+language_switch_no_tranlation_prefix: "Seite nicht übersetzt:"
+
+propertylist_required: erforderlich
+propertylist_optional: optional
+propertylist_default: Standardwert
+
+pagination_page_prev: vorher
+pagination_page_next: weiter
+pagination_page_state: "{{ .PageNumber }}/{{ .TotalPages }}"
diff --git a/docs/themes/hugo-geekdoc/i18n/en.yaml b/docs/themes/hugo-geekdoc/i18n/en.yaml
new file mode 100644
index 000000000..ff19ea4e8
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/i18n/en.yaml
@@ -0,0 +1,53 @@
+---
+edit_page: Edit page
+
+nav_navigation: Navigation
+nav_tags: Tags
+nav_more: More
+nav_top: Back to top
+
+form_placeholder_search: Search
+
+error_page_title: Lost? Don't worry
+error_message_title: Lost?
+error_message_code: Error 404
+error_message_text: >
+ Seems like what you are looking for can't be found. Don't worry, we can
+ bring you back to the homepage.
+
+button_toggle_dark: Toggle Dark/Light/Auto mode
+button_nav_open: Open Navigation
+button_nav_close: Close Navigation
+button_menu_open: Open Menu Bar
+button_menu_close: Close Menu Bar
+button_homepage: Back to homepage
+
+title_anchor_prefix: "Anchor to:"
+
+posts_read_more: Read full post
+posts_read_time:
+ one: "One minute to read"
+ other: "{{ . }} minutes to read"
+posts_update_prefix: Updated on
+posts_count:
+ one: "One post"
+ other: "{{ . }} posts"
+posts_tagged_with: All posts tagged with '{{ . }}'
+
+footer_build_with: >
+ Built with Hugo and
+
+footer_legal_notice: Legal Notice
+footer_privacy_policy: Privacy Policy
+footer_content_license_prefix: >
+ Content licensed under
+
+language_switch_no_tranlation_prefix: "Page not translated:"
+
+propertylist_required: required
+propertylist_optional: optional
+propertylist_default: default
+
+pagination_page_prev: prev
+pagination_page_next: next
+pagination_page_state: "{{ .PageNumber }}/{{ .TotalPages }}"
diff --git a/docs/themes/hugo-geekdoc/i18n/es.yaml b/docs/themes/hugo-geekdoc/i18n/es.yaml
new file mode 100644
index 000000000..8e65cec7b
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/i18n/es.yaml
@@ -0,0 +1,53 @@
+---
+edit_page: Editar página
+
+nav_navigation: Navegación
+nav_tags: Etiquetas
+nav_more: Más
+nav_top: Inicio de la página
+
+form_placeholder_search: Buscar
+
+error_page_title: Perdido? No te preocupes
+error_message_title: Perdido?
+error_message_code: Error 404
+error_message_text: >
+ Al parecer, lo que estás buscando no pudo ser encontrado. No te preocupes, podemos
+ llevarte de vuelta al inicio.
+
+button_toggle_dark: Cambiar el modo Oscuro/Claro/Auto
+button_nav_open: Abrir la Navegación
+button_nav_close: Cerrar la Navegación
+button_menu_open: Abrir el Menú Bar
+button_menu_close: Cerrar el Menú Bar
+button_homepage: Volver al Inicio
+
+title_anchor_prefix: "Anclado a:"
+
+posts_read_more: Lee la publicación completa
+posts_read_time:
+ one: "Un minuto para leer"
+ other: "{{ . }} minutos para leer"
+posts_update_prefix: Actualizado en
+posts_count:
+ one: "Una publicación"
+ other: "{{ . }} publicaciones"
+posts_tagged_with: Todas las publicaciones etiquetadas con '{{ . }}'
+
+footer_build_with: >
+ Creado con Hugo y
+
+footer_legal_notice: Aviso Legal
+footer_privacy_policy: Política de Privacidad
+footer_content_license_prefix: >
+ Contenido licenciado con
+
+language_switch_no_tranlation_prefix: "Página no traducida:"
+
+propertylist_required: requerido
+propertylist_optional: opcional
+propertylist_default: estándar
+
+pagination_page_prev: previo
+pagination_page_next: siguiente
+pagination_page_state: "{{ .PageNumber }}/{{ .TotalPages }}"
diff --git a/docs/themes/hugo-geekdoc/i18n/it.yaml b/docs/themes/hugo-geekdoc/i18n/it.yaml
new file mode 100644
index 000000000..ce7c40b4e
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/i18n/it.yaml
@@ -0,0 +1,53 @@
+---
+edit_page: Modifica la pagina
+
+nav_navigation: Navigazione
+nav_tags: Etichette
+nav_more: Altro
+nav_top: Torna su
+
+form_placeholder_search: Cerca
+
+error_page_title: Perso? Non ti preoccupare
+error_message_title: Perso?
+error_message_code: Errore 404
+error_message_text: >
+ Sembra che non sia possibile trovare quello che stavi cercando. Non ti preoccupare,
+ possiamo riportarti alla pagina iniziale.
+
+button_toggle_dark: Seleziona il tema Chiaro/Scuro/Automatico
+button_nav_open: Apri la Navigazione
+button_nav_close: Chiudi la Navigazione
+button_menu_open: Apri la Barra del Menu
+button_menu_close: Chiudi la Barra del Menu
+button_homepage: Torna alla pagina iniziale
+
+title_anchor_prefix: "Ancora a:"
+
+posts_read_more: Leggi tutto il post
+posts_read_time:
+ one: "Tempo di lettura: un minuto"
+ other: "Tempo di lettura: {{ . }} minuti"
+posts_update_prefix: Aggiornato il
+posts_count:
+ one: "Un post"
+ other: "{{ . }} post"
+posts_tagged_with: Tutti i post etichettati con '{{ . }}'
+
+footer_build_with: >
+ Realizzato con Hugo e
+
+footer_legal_notice: Avviso Legale
+footer_privacy_policy: Politica sulla Privacy
+footer_content_license_prefix: >
+ Contenuto sotto licenza
+
+language_switch_no_tranlation_prefix: "Pagina non tradotta:"
+
+propertylist_required: richiesto
+propertylist_optional: opzionale
+propertylist_default: valore predefinito
+
+pagination_page_prev: precedente
+pagination_page_next: prossimo
+pagination_page_state: "{{ .PageNumber }}/{{ .TotalPages }}"
diff --git a/docs/themes/hugo-geekdoc/i18n/ja.yaml b/docs/themes/hugo-geekdoc/i18n/ja.yaml
new file mode 100644
index 000000000..506e7b4e1
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/i18n/ja.yaml
@@ -0,0 +1,53 @@
+---
+edit_page: ページの編集
+
+nav_navigation: ナビゲーション
+nav_tags: タグ
+nav_more: さらに
+nav_top: トップへ戻る
+
+form_placeholder_search: 検索
+
+error_page_title: お困りですか?ご心配なく
+error_message_title: お困りですか?
+error_message_code: 404 エラー
+error_message_text: >
+ お探しのものが見つからないようです。トップページ
+ へ戻ることができるので、ご安心ください。
+
+button_toggle_dark: モードの切替 ダーク/ライト/自動
+button_nav_open: ナビゲーションを開く
+button_nav_close: ナビゲーションを閉じる
+button_menu_open: メニューバーを開く
+button_menu_close: メニューバーを閉じる
+button_homepage: トップページへ戻る
+
+title_anchor_prefix: "アンカー先:"
+
+posts_read_more: 全投稿を閲覧
+posts_read_time:
+ one: "読むのに 1 分かかります"
+ other: "読むのに要する時間 {{ . }} (分)"
+posts_update_prefix: 更新時刻
+posts_count:
+ one: "一件の投稿"
+ other: "{{ . }} 件の投稿"
+posts_tagged_with: "'{{ . }}'のタグが付いた記事全部"
+
+footer_build_with: >
+ Hugo でビルドしています。
+
+footer_legal_notice: 法的な告知事項
+footer_privacy_policy: プライバシーポリシー
+footer_content_license_prefix: >
+ 提供するコンテンツのライセンス
+
+language_switch_no_tranlation_prefix: "未翻訳のページ:"
+
+propertylist_required: 必須
+propertylist_optional: 任意
+propertylist_default: 既定値
+
+pagination_page_prev: 前
+pagination_page_next: 次
+pagination_page_state: "{{ .PageNumber }}/{{ .TotalPages }}"
diff --git a/docs/themes/hugo-geekdoc/i18n/nl.yaml b/docs/themes/hugo-geekdoc/i18n/nl.yaml
new file mode 100644
index 000000000..240bcea5a
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/i18n/nl.yaml
@@ -0,0 +1,53 @@
+---
+edit_page: Wijzig pagina
+
+nav_navigation: Navigatie
+nav_tags: Markering
+nav_more: Meer
+nav_top: Terug naar boven
+
+form_placeholder_search: Zoek
+
+error_page_title: Verdwaald? Geen probleem
+error_message_title: Verdwaald?
+error_message_code: Error 404
+error_message_text: >
+ Het lijkt er op dat wat je zoekt niet gevonden kan worden. Geen probleem,
+ we kunnen je terug naar de startpagina brengen.
+
+button_toggle_dark: Wijzig Donker/Licht/Auto weergave
+button_nav_open: Open navigatie
+button_nav_close: Sluit navigatie
+button_menu_open: Open menubalk
+button_menu_close: Sluit menubalk
+button_homepage: Terug naar startpagina
+
+title_anchor_prefix: "Link naar:"
+
+posts_read_more: Lees volledige bericht
+posts_read_time:
+ one: "Een minuut leestijd"
+ other: "{{ . }} minuten leestijd"
+posts_update_prefix: Bijgewerkt op
+posts_count:
+ one: "Een bericht"
+ other: "{{ . }} berichten"
+posts_tagged_with: Alle berichten gemarkeerd met '{{ . }}'
+
+footer_build_with: >
+ Gebouwd met Hugo en
+
+footer_legal_notice: Juridische mededeling
+footer_privacy_policy: Privacybeleid
+footer_content_license_prefix: >
+ Inhoud gelicenseerd onder
+
+language_switch_no_tranlation_prefix: "Pagina niet vertaald:"
+
+propertylist_required: verplicht
+propertylist_optional: optioneel
+propertylist_default: standaard
+
+pagination_page_prev: vorige
+pagination_page_next: volgende
+pagination_page_state: "{{ .PageNumber }}/{{ .TotalPages }}"
diff --git a/docs/themes/hugo-geekdoc/i18n/zh-cn.yaml b/docs/themes/hugo-geekdoc/i18n/zh-cn.yaml
new file mode 100644
index 000000000..e6403acd1
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/i18n/zh-cn.yaml
@@ -0,0 +1,53 @@
+---
+edit_page: 编辑页面
+
+nav_navigation: 导航
+nav_tags: 标签
+nav_more: 更多
+nav_top: 回到顶部
+
+form_placeholder_search: 搜索
+
+error_page_title: 迷路了? 不用担心
+error_message_title: 迷路了?
+error_message_code: 错误 404
+error_message_text: >
+ 好像找不到你要找的东西。 别担心,我们可以
+ 带您回到主页。
+
+button_toggle_dark: 切换暗/亮/自动模式
+button_nav_open: 打开导航
+button_nav_close: 关闭导航
+button_menu_open: 打开菜单栏
+button_menu_close: 关闭菜单栏
+button_homepage: 返回首页
+
+title_anchor_prefix: "锚定到:"
+
+posts_read_more: 阅读全文
+posts_read_time:
+ one: "一分钟阅读时间"
+ other: "{{ . }} 分钟阅读时间"
+posts_update_prefix: 更新时间
+posts_count:
+ one: 一篇文章
+ other: "{{ . }} 个帖子"
+posts_tagged_with: 所有带有“{{ . }}”标签的帖子。
+
+footer_build_with: >
+ 基于 Hugo
+ 制作
+footer_legal_notice: "法律声明"
+footer_privacy_policy: "隐私政策"
+footer_content_license_prefix: >
+ 内容许可证
+
+language_switch_no_tranlation_prefix: "页面未翻译:"
+
+propertylist_required: 需要
+propertylist_optional: 可选
+propertylist_default: 默认值
+
+pagination_page_prev: 以前
+pagination_page_next: 下一个
+pagination_page_state: "{{ .PageNumber }}/{{ .TotalPages }}"
diff --git a/docs/themes/hugo-geekdoc/images/readme.png b/docs/themes/hugo-geekdoc/images/readme.png
new file mode 100644
index 000000000..10c8ff157
Binary files /dev/null and b/docs/themes/hugo-geekdoc/images/readme.png differ
diff --git a/docs/themes/hugo-geekdoc/images/screenshot.png b/docs/themes/hugo-geekdoc/images/screenshot.png
new file mode 100644
index 000000000..af243606d
Binary files /dev/null and b/docs/themes/hugo-geekdoc/images/screenshot.png differ
diff --git a/docs/themes/hugo-geekdoc/images/tn.png b/docs/themes/hugo-geekdoc/images/tn.png
new file mode 100644
index 000000000..ee6e42ed0
Binary files /dev/null and b/docs/themes/hugo-geekdoc/images/tn.png differ
diff --git a/docs/themes/hugo-geekdoc/layouts/404.html b/docs/themes/hugo-geekdoc/layouts/404.html
new file mode 100644
index 000000000..f8a61bb53
--- /dev/null
+++ b/docs/themes/hugo-geekdoc/layouts/404.html
@@ -0,0 +1,40 @@
+
+
+
+ {{ partial "head/meta" . }}
+ {{ i18n "error_page_title" }}
+
+ {{ partial "head/favicons" . }}
+ {{ partial "head/others" . }}
+
+
+
+ {{ partial "svg-icon-symbols" . }}
+
+
+