diff --git a/.codespellrc b/.codespellrc new file mode 100644 index 000000000..e4dbb3a7f --- /dev/null +++ b/.codespellrc @@ -0,0 +1,5 @@ +[codespell] +# Ignore words that are valid technical terms: +# - vertx: Vert.x reactive framework +# - errorprone: Error Prone static analysis tool +ignore-words-list = vertx,errorprone diff --git a/.editorconfig b/.editorconfig index 8628b45bd..80219f95e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,16 +4,19 @@ root = true max_line_length = 100 indent_size = 2 -[{version-rules.xml,maven-wrapper.properties,checkstyle.xml,docker-compose.yaml,docker-compose.yml,Dockerfile,example_target_info.json,mise.toml,mvnm,mvnw.cmd,generate-protobuf.sh,super-linter.env,.gitleaksignore,*.json5}] +[{version-rules.xml,maven-wrapper.properties,checkstyle.xml,docker-compose.yaml,docker-compose.yml,Dockerfile,example_target_info.json,mise.toml,mvnm,mvnw.cmd,generate-protobuf.sh,.gitleaksignore,prometheus.properties}] max_line_length = 200 -[{grafana-dashboard-*.json,.editorconfig}] +[{grafana-dashboard-*.json,.editorconfig,super-linter.env,lychee.toml,renovate.json5}] max_line_length = 300 [pom.xml] -max_line_length = 110 +max_line_length = 120 [*.py] # checked by black indent_size = 4 max_line_length = 120 + +[{.mise/tasks/build-release.sh,.github/workflows/multi-version-test.yml}] +max_line_length = 200 diff --git a/.github/config/.release-please-manifest.json b/.github/config/.release-please-manifest.json new file mode 100644 index 000000000..dd8fde779 --- /dev/null +++ b/.github/config/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "1.5.0" +} diff --git a/.github/config/lychee.toml b/.github/config/lychee.toml new file mode 100644 index 000000000..864350fb5 --- /dev/null +++ b/.github/config/lychee.toml @@ -0,0 +1,30 @@ +# Lychee configuration file +# See https://lychee.cli.rs/config/ + +timeout = 30 +retry_wait_time = 5 +max_retries = 6 +max_concurrency = 4 + +# Check link anchors +include_fragments = true + +base_url = "https://prometheus.github.io" +exclude_path = ["docs/themes"] + +exclude = [ + # excluding links to pull requests and issues is done for performance + "^https://github.com/prometheus/client_java/(issues|pull)/\\d+$", + + # exclude localhost URLs as they require running services + "^http://localhost", + "^https://localhost", + + '#', + 'CONTRIBUTING.md', + 'LICENSE', + 'MAINTAINERS.md', + + # exclude private GitHub settings pages + "^https://github.com/prometheus/client_java/settings/", +] diff --git a/.github/config/release-please-config.json b/.github/config/release-please-config.json new file mode 100644 index 000000000..0182b5204 --- /dev/null +++ b/.github/config/release-please-config.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "pull-request-footer": "> [!IMPORTANT]\n> Close and reopen this PR to trigger CI checks.", + "packages": { + ".": { + "release-type": "java", + "versioning": "always-bump-patch", + "extra-files": [ + "prometheus-metrics-parent/pom.xml", + "integration-tests/it-spring-boot-smoke-test/pom.xml" + ] + } + } +} diff --git a/.github/super-linter.env b/.github/config/super-linter.env similarity index 93% rename from .github/super-linter.env rename to .github/config/super-linter.env index 62850b064..566f1bfb3 100644 --- a/.github/super-linter.env +++ b/.github/config/super-linter.env @@ -1,6 +1,7 @@ -FILTER_REGEX_EXCLUDE=mvnw|src/main/generated/.*|docs/themes/.*|keystore.pkcs12|.*.java|prometheus-metrics-exporter-opentelemetry-shaded/pom.xml|CODE_OF_CONDUCT.md +FILTER_REGEX_EXCLUDE=mvnw|src/main/generated/.*|docs/themes/.*|keystore.pkcs12|.*.java|prometheus-metrics-exporter-opentelemetry-shaded/pom.xml|CODE_OF_CONDUCT.md|CLAUDE.md IGNORE_GITIGNORED_FILES=true JAVA_FILE_NAME=google_checks.xml +LOG_LEVEL=ERROR # conflicts with prettier VALIDATE_BIOME_FORMAT=false # conflicts with prettier @@ -38,4 +39,5 @@ FIX_MARKDOWN=true FIX_MARKDOWN_PRETTIER=true FIX_PYTHON_BLACK=true FIX_SHELL_SHFMT=true +FIX_SPELL_CODESPELL=true FIX_YAML_PRETTIER=true diff --git a/.github/renovate-tracked-deps.json b/.github/renovate-tracked-deps.json new file mode 100644 index 000000000..d3089ecb7 --- /dev/null +++ b/.github/renovate-tracked-deps.json @@ -0,0 +1,560 @@ +{ + ".github/renovate.json5": { + "renovate-config-presets": ["grafana/flint"] + }, + ".mise/envs/native/mise.toml": { + "mise": ["java"] + }, + ".mvn/wrapper/maven-wrapper.properties": { + "maven-wrapper": ["maven"] + }, + "benchmarks/pom.xml": { + "maven": [ + "com.codahale.metrics:metrics-core", + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exposition-textformats", + "io.prometheus:simpleclient", + "org.openjdk.jmh:jmh-core", + "org.openjdk.jmh:jmh-generator-annprocess" + ] + }, + "integration-tests/it-common/pom.xml": { + "maven": [ + "io.prometheus:integration-tests", + "io.prometheus:prometheus-metrics-exposition-formats" + ] + }, + "integration-tests/it-exporter/it-exporter-duplicate-metrics-sample/pom.xml": { + "maven": [ + "io.prometheus:it-exporter", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exporter-httpserver" + ] + }, + "integration-tests/it-exporter/it-exporter-httpserver-sample/pom.xml": { + "maven": [ + "io.prometheus:it-exporter", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exporter-httpserver" + ] + }, + "integration-tests/it-exporter/it-exporter-no-protobuf/pom.xml": { + "maven": [ + "io.prometheus:it-exporter", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exporter-httpserver" + ] + }, + "integration-tests/it-exporter/it-exporter-servlet-jetty-sample/pom.xml": { + "maven": [ + "io.prometheus:it-exporter", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exporter-servlet-jakarta", + "org.eclipse.jetty.ee10:jetty-ee10-servlet", + "org.eclipse.jetty:jetty-server" + ] + }, + "integration-tests/it-exporter/it-exporter-servlet-tomcat-sample/pom.xml": { + "maven": [ + "io.prometheus:it-exporter", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exporter-servlet-jakarta", + "org.apache.tomcat.embed:tomcat-embed-core" + ] + }, + "integration-tests/it-exporter/it-exporter-test/pom.xml": { + "maven": ["io.prometheus:it-common", "io.prometheus:it-exporter"] + }, + "integration-tests/it-exporter/it-no-protobuf-test/pom.xml": { + "maven": ["io.prometheus:it-common", "io.prometheus:it-exporter"] + }, + "integration-tests/it-exporter/pom.xml": { + "maven": ["io.prometheus:integration-tests"] + }, + "integration-tests/it-pushgateway/pom.xml": { + "maven": [ + "com.jayway.jsonpath:json-path", + "com.squareup.okhttp:okhttp", + "io.prometheus:integration-tests", + "io.prometheus:it-common", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exporter-pushgateway" + ] + }, + "integration-tests/it-spring-boot-smoke-test/pom.xml": { + "maven": [ + "com.diffplug.spotless:spotless-maven-plugin", + "io.prometheus:it-common", + "io.prometheus:prometheus-metrics-bom", + "org.junit:junit-bom", + "org.springframework.boot:spring-boot-starter-parent" + ] + }, + "integration-tests/pom.xml": { + "maven": [ + "commons-io:commons-io", + "io.prometheus:client_java", + "org.testcontainers:junit-jupiter" + ] + }, + "mise.toml": { + "mise": [ + "go:github.com/gohugoio/hugo", + "go:github.com/grafana/oats", + "java", + "lychee", + "node", + "npm:renovate", + "protoc" + ], + "regex": ["ghcr.io/super-linter/super-linter", "grafana/flint"] + }, + "mvnw": { + "maven-wrapper": ["maven-wrapper"] + }, + "mvnw.cmd": { + "maven-wrapper": ["maven-wrapper"] + }, + "pom.xml": { + "maven": [ + "com.google.code.findbugs:jsr305", + "com.google.errorprone:error_prone_core", + "com.google.guava:guava", + "com.google.protobuf:protobuf-java", + "com.uber.nullaway:nullaway", + "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha", + "io.opentelemetry:opentelemetry-proto", + "io.prometheus:client_java_parent", + "org.apache.felix:maven-bundle-plugin", + "org.apache.maven.plugins:maven-checkstyle-plugin", + "org.apache.maven.plugins:maven-clean-plugin", + "org.apache.maven.plugins:maven-compiler-plugin", + "org.apache.maven.plugins:maven-dependency-plugin", + "org.apache.maven.plugins:maven-deploy-plugin", + "org.apache.maven.plugins:maven-enforcer-plugin", + "org.apache.maven.plugins:maven-failsafe-plugin", + "org.apache.maven.plugins:maven-install-plugin", + "org.apache.maven.plugins:maven-jar-plugin", + "org.apache.maven.plugins:maven-javadoc-plugin", + "org.apache.maven.plugins:maven-resources-plugin", + "org.apache.maven.plugins:maven-shade-plugin", + "org.apache.maven.plugins:maven-site-plugin", + "org.apache.maven.plugins:maven-surefire-plugin", + "org.assertj:assertj-core", + "org.awaitility:awaitility", + "org.codehaus.mojo:build-helper-maven-plugin", + "org.codehaus.mojo:exec-maven-plugin", + "org.codehaus.mojo:versions-maven-plugin", + "org.jacoco:jacoco-maven-plugin", + "org.junit-pioneer:junit-pioneer", + "org.junit.jupiter:junit-jupiter", + "org.junit.jupiter:junit-jupiter-params", + "org.junit:junit-bom", + "org.mockito:mockito-core", + "org.slf4j:slf4j-simple", + "org.wiremock:wiremock" + ] + }, + "prometheus-metrics-bom/pom.xml": { + "maven": [ + "io.prometheus:client_java_parent", + "io.prometheus:prometheus-metrics-config", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exporter-common", + "io.prometheus:prometheus-metrics-exporter-httpserver", + "io.prometheus:prometheus-metrics-exporter-opentelemetry", + "io.prometheus:prometheus-metrics-exporter-opentelemetry-no-otel", + "io.prometheus:prometheus-metrics-exporter-opentelemetry-otel-agent-resources", + "io.prometheus:prometheus-metrics-exporter-pushgateway", + "io.prometheus:prometheus-metrics-exporter-servlet-jakarta", + "io.prometheus:prometheus-metrics-exporter-servlet-javax", + "io.prometheus:prometheus-metrics-exposition-formats", + "io.prometheus:prometheus-metrics-exposition-formats-no-protobuf", + "io.prometheus:prometheus-metrics-exposition-textformats", + "io.prometheus:prometheus-metrics-instrumentation-caffeine", + "io.prometheus:prometheus-metrics-instrumentation-dropwizard", + "io.prometheus:prometheus-metrics-instrumentation-dropwizard5", + "io.prometheus:prometheus-metrics-instrumentation-guava", + "io.prometheus:prometheus-metrics-instrumentation-jvm", + "io.prometheus:prometheus-metrics-model", + "io.prometheus:prometheus-metrics-otel-support", + "io.prometheus:prometheus-metrics-simpleclient-bridge", + "io.prometheus:prometheus-metrics-tracer", + "io.prometheus:prometheus-metrics-tracer-common", + "io.prometheus:prometheus-metrics-tracer-initializer", + "io.prometheus:prometheus-metrics-tracer-otel", + "io.prometheus:prometheus-metrics-tracer-otel-agent" + ] + }, + "prometheus-metrics-config/pom.xml": { + "maven": ["io.prometheus:client_java"] + }, + "prometheus-metrics-core/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-config", + "io.prometheus:prometheus-metrics-exposition-formats-no-protobuf", + "io.prometheus:prometheus-metrics-model", + "io.prometheus:prometheus-metrics-tracer-initializer", + "org.apache.commons:commons-math3" + ] + }, + "prometheus-metrics-exporter-common/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exposition-formats", + "io.prometheus:prometheus-metrics-exposition-textformats", + "io.prometheus:prometheus-metrics-model" + ] + }, + "prometheus-metrics-exporter-httpserver/pom.xml": { + "maven": ["io.prometheus:client_java", "io.prometheus:prometheus-metrics-exporter-common"] + }, + "prometheus-metrics-exporter-opentelemetry-otel-agent-resources/pom.xml": { + "maven": [ + "io.opentelemetry:opentelemetry-api", + "io.opentelemetry:opentelemetry-context", + "io.prometheus:client_java" + ] + }, + "prometheus-metrics-exporter-opentelemetry-shaded/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exporter-opentelemetry-otel-agent-resources" + ] + }, + "prometheus-metrics-exporter-opentelemetry/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exporter-opentelemetry-otel-agent-resources" + ] + }, + "prometheus-metrics-exporter-pushgateway/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exporter-common", + "org.mock-server:mockserver-netty-no-dependencies" + ] + }, + "prometheus-metrics-exporter-servlet-jakarta/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exporter-common", + "jakarta.servlet:jakarta.servlet-api" + ] + }, + "prometheus-metrics-exporter-servlet-javax/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exporter-common", + "javax.servlet:javax.servlet-api" + ] + }, + "prometheus-metrics-exposition-formats-shaded/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-exposition-textformats" + ] + }, + "prometheus-metrics-exposition-formats/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-exposition-textformats" + ] + }, + "prometheus-metrics-exposition-textformats/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-config", + "io.prometheus:prometheus-metrics-model" + ] + }, + "prometheus-metrics-instrumentation-caffeine/pom.xml": { + "maven": [ + "com.github.ben-manes.caffeine:caffeine", + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exposition-textformats" + ] + }, + "prometheus-metrics-instrumentation-dropwizard/pom.xml": { + "maven": [ + "io.dropwizard.metrics:metrics-core", + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exporter-httpserver", + "io.prometheus:prometheus-metrics-exposition-textformats", + "io.prometheus:prometheus-metrics-instrumentation-dropwizard5" + ] + }, + "prometheus-metrics-instrumentation-dropwizard5/pom.xml": { + "maven": [ + "io.dropwizard.metrics5:metrics-core", + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exporter-httpserver", + "io.prometheus:prometheus-metrics-exposition-textformats" + ] + }, + "prometheus-metrics-instrumentation-guava/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exposition-textformats" + ] + }, + "prometheus-metrics-instrumentation-jvm/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-core", + "io.prometheus:prometheus-metrics-exporter-httpserver", + "io.prometheus:prometheus-metrics-exposition-textformats" + ] + }, + "prometheus-metrics-model/pom.xml": { + "maven": ["io.prometheus:client_java", "io.prometheus:prometheus-metrics-config"] + }, + "prometheus-metrics-otel-support/pom.xml": { + "maven": ["io.prometheus:client_java"] + }, + "prometheus-metrics-parent/pom.xml": { + "maven": [ + "com.diffplug.spotless:spotless-maven-plugin", + "org.apache.maven.plugins:maven-gpg-plugin", + "org.apache.maven.plugins:maven-source-plugin", + "org.sonatype.central:central-publishing-maven-plugin" + ] + }, + "prometheus-metrics-simpleclient-bridge/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:prometheus-metrics-config", + "io.prometheus:prometheus-metrics-exposition-textformats", + "io.prometheus:prometheus-metrics-model", + "io.prometheus:simpleclient", + "io.prometheus:simpleclient_common" + ] + }, + "prometheus-metrics-tracer/pom.xml": { + "maven": ["io.prometheus:client_java"] + }, + "prometheus-metrics-tracer/prometheus-metrics-tracer-common/pom.xml": { + "maven": ["io.prometheus:prometheus-metrics-tracer"] + }, + "prometheus-metrics-tracer/prometheus-metrics-tracer-initializer/pom.xml": { + "maven": [ + "io.prometheus:prometheus-metrics-tracer", + "io.prometheus:prometheus-metrics-tracer-common", + "io.prometheus:prometheus-metrics-tracer-otel", + "io.prometheus:prometheus-metrics-tracer-otel-agent" + ] + }, + "prometheus-metrics-tracer/prometheus-metrics-tracer-otel-agent/pom.xml": { + "maven": [ + "io.prometheus:prometheus-metrics-tracer", + "io.prometheus:prometheus-metrics-tracer-common" + ] + }, + "prometheus-metrics-tracer/prometheus-metrics-tracer-otel/pom.xml": { + "maven": [ + "io.prometheus:prometheus-metrics-tracer", + "io.prometheus:prometheus-metrics-tracer-common" + ] + }, + "simpleclient-archive/integration_tests/it_common/pom.xml": { + "maven": ["io.prometheus:integration_tests"] + }, + "simpleclient-archive/integration_tests/it_exemplars_otel_agent/pom.xml": { + "maven": [ + "ch.qos.logback:logback-classic", + "io.prometheus:integration_tests", + "io.prometheus:it_common", + "io.prometheus:simpleclient_bom", + "io.prometheus:simpleclient_hotspot", + "io.prometheus:simpleclient_servlet", + "org.springframework.boot:spring-boot-dependencies", + "org.springframework.boot:spring-boot-maven-plugin" + ] + }, + "simpleclient-archive/integration_tests/it_exemplars_otel_sdk/pom.xml": { + "maven": [ + "io.opentelemetry:opentelemetry-api", + "io.opentelemetry:opentelemetry-sdk", + "io.prometheus:integration_tests", + "io.prometheus:it_common", + "io.prometheus:simpleclient", + "io.prometheus:simpleclient_httpserver" + ] + }, + "simpleclient-archive/integration_tests/it_java_versions/pom.xml": { + "maven": [ + "io.prometheus:integration_tests", + "io.prometheus:it_common", + "io.prometheus:simpleclient", + "io.prometheus:simpleclient_hotspot", + "io.prometheus:simpleclient_httpserver" + ] + }, + "simpleclient-archive/integration_tests/it_log4j2/pom.xml": { + "maven": [ + "io.prometheus:integration_tests", + "io.prometheus:it_common", + "io.prometheus:simpleclient", + "io.prometheus:simpleclient_httpserver", + "io.prometheus:simpleclient_log4j2", + "org.apache.logging.log4j:log4j-api", + "org.apache.logging.log4j:log4j-core" + ] + }, + "simpleclient-archive/integration_tests/it_pushgateway/pom.xml": { + "maven": [ + "ch.qos.logback:logback-classic", + "com.squareup.okhttp3:okhttp", + "io.prometheus:integration_tests", + "io.prometheus:it_common", + "io.prometheus:simpleclient", + "io.prometheus:simpleclient_pushgateway" + ] + }, + "simpleclient-archive/integration_tests/it_servlet_jakarta_exporter_webxml/pom.xml": { + "maven": [ + "ch.qos.logback:logback-classic", + "com.squareup.okhttp3:okhttp", + "io.prometheus:integration_tests", + "io.prometheus:simpleclient", + "io.prometheus:simpleclient_hotspot", + "io.prometheus:simpleclient_servlet_jakarta", + "jakarta.servlet:jakarta.servlet-api", + "org.apache.maven.plugins:maven-war-plugin" + ] + }, + "simpleclient-archive/integration_tests/pom.xml": { + "maven": [ + "ch.qos.logback:logback-classic", + "com.squareup.okhttp3:okhttp", + "io.prometheus:client_java", + "org.testcontainers:testcontainers" + ] + }, + "simpleclient-archive/simpleclient_graphite_bridge/pom.xml": { + "maven": ["io.prometheus:client_java", "io.prometheus:simpleclient"] + }, + "simpleclient-archive/simpleclient_hibernate/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:simpleclient", + "org.hibernate:hibernate-core" + ] + }, + "simpleclient-archive/simpleclient_httpserver/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:simpleclient", + "io.prometheus:simpleclient_common", + "javax.xml.bind:jaxb-api" + ] + }, + "simpleclient-archive/simpleclient_jetty/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:simpleclient", + "org.eclipse.jetty:jetty-server", + "org.eclipse.jetty:jetty-servlet", + "org.hamcrest:hamcrest-all" + ] + }, + "simpleclient-archive/simpleclient_jetty_jdk8/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:simpleclient", + "org.eclipse.jetty:jetty-server", + "org.eclipse.jetty:jetty-servlet", + "org.hamcrest:hamcrest-all" + ] + }, + "simpleclient-archive/simpleclient_log4j/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:simpleclient", + "org.apache.logging.log4j:log4j-1.2-api", + "org.apache.logging.log4j:log4j-core" + ] + }, + "simpleclient-archive/simpleclient_log4j2/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:simpleclient", + "org.apache.logging.log4j:log4j-core" + ] + }, + "simpleclient-archive/simpleclient_logback/pom.xml": { + "maven": [ + "ch.qos.logback:logback-classic", + "io.prometheus:client_java", + "io.prometheus:simpleclient" + ] + }, + "simpleclient-archive/simpleclient_servlet/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:simpleclient", + "io.prometheus:simpleclient_common", + "io.prometheus:simpleclient_servlet_common", + "javax.servlet:javax.servlet-api", + "org.eclipse.jetty:jetty-servlet" + ] + }, + "simpleclient-archive/simpleclient_servlet_common/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:simpleclient", + "io.prometheus:simpleclient_common" + ] + }, + "simpleclient-archive/simpleclient_servlet_jakarta/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:simpleclient", + "io.prometheus:simpleclient_common", + "io.prometheus:simpleclient_servlet_common", + "jakarta.servlet:jakarta.servlet-api", + "org.eclipse.jetty:jetty-servlet" + ] + }, + "simpleclient-archive/simpleclient_spring_web/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:simpleclient", + "io.prometheus:simpleclient_common", + "org.apache.commons:commons-lang3", + "org.aspectj:aspectjweaver", + "org.springframework:spring-aop", + "org.springframework:spring-context", + "org.springframework:spring-test", + "org.springframework:spring-web" + ] + }, + "simpleclient-archive/simpleclient_vertx/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:simpleclient", + "io.prometheus:simpleclient_common", + "io.vertx:vertx-web" + ] + }, + "simpleclient-archive/simpleclient_vertx4/pom.xml": { + "maven": [ + "io.prometheus:client_java", + "io.prometheus:simpleclient", + "io.prometheus:simpleclient_common", + "io.vertx:vertx-web" + ] + } +} diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 67c8c137f..ff4363ba5 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -1,6 +1,6 @@ { $schema: "https://docs.renovatebot.com/renovate-schema.json", - extends: ["config:best-practices", "config:recommended"], + extends: ["config:best-practices", "config:recommended", "github>grafana/flint"], platformCommit: "enabled", automerge: true, ignorePaths: [ @@ -12,20 +12,26 @@ labels: ["dependencies"], packageRules: [ { - matchPackageNames: ["jdx/mise"], - groupName: "mise", - schedule: ["before 4am on monday"], + matchFileNames: ["mise.toml"], + matchDepNames: ["java"], + groupName: "java temurin", + additionalBranchPrefix: "temurin-", + }, + { + matchFileNames: [".mise/envs/native/mise.toml"], + matchDepNames: ["java"], + groupName: "java graalvm", + additionalBranchPrefix: "graalvm-", + }, + { + matchPackageNames: ["io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha"], + ignoreUnstable: false, }, - ], - customManagers: [ { - customType: "regex", - description: "update mise", - managerFilePatterns: ["/(^|/)(workflow-templates|\\.(?:github|gitea|forgejo)/(?:workflows|actions))/.+\\.ya?ml$/", "/(^|/)action\\.ya?ml$/"], - datasourceTemplate: "github-release-attachments", - packageNameTemplate: "jdx/mise", - depNameTemplate: "mise", - matchStrings: ["jdx/mise-action.*\\n\\s*with:\\s*\\n\\s*version: [\"']?(?v[.\\d]+)[\"']?\\s*\\n\\s*sha256: [\"']?(?\\w+)[\"']?"], + enabled: false, + description: "Ignore internal project modules", + matchPackageNames: ["/^io\\.prometheus:(examples|example-.+|integration-tests|it-.+)$/"], }, ], + customManagers: [], } diff --git a/.github/workflows/acceptance-tests.yml b/.github/workflows/acceptance-tests.yml index c810d0667..977973f3b 100644 --- a/.github/workflows/acceptance-tests.yml +++ b/.github/workflows/acceptance-tests.yml @@ -12,10 +12,7 @@ jobs: - name: Check out with: persist-credentials: false - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - - uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3.5.1 - with: - version: v2025.12.13 - sha256: 2134c55725d08547cddc921f84ddac05c9de1700115c32817563435072cae5ed + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8 # v3.6.1 - name: Run acceptance tests run: mise run acceptance-test diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bda2f62af..e5b1980e8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,15 +9,12 @@ jobs: build: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: persist-credentials: false - - uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3.5.1 - with: - version: v2025.12.13 - sha256: 2134c55725d08547cddc921f84ddac05c9de1700115c32817563435072cae5ed + - uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8 # v3.6.1 - name: Cache local Maven repository - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5 + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/github-pages.yaml b/.github/workflows/github-pages.yaml index d10ccf942..37cc39f37 100644 --- a/.github/workflows/github-pages.yaml +++ b/.github/workflows/github-pages.yaml @@ -32,15 +32,13 @@ jobs: if: github.repository == 'prometheus/client_java' runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: persist-credentials: false fetch-tags: "true" fetch-depth: 0 - - uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3.5.1 + - uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8 # v3.6.1 with: - version: v2025.12.13 - sha256: 2134c55725d08547cddc921f84ddac05c9de1700115c32817563435072cae5ed cache: "false" - name: Setup Pages id: pages diff --git a/.github/workflows/java-version-matrix-tests.yml b/.github/workflows/java-version-matrix-tests.yml new file mode 100644 index 000000000..d476e7bb7 --- /dev/null +++ b/.github/workflows/java-version-matrix-tests.yml @@ -0,0 +1,81 @@ +--- +name: Integration Tests - Java Version Compatibility Matrix + +on: + pull_request: + paths: + - 'integration-tests/**' + - 'prometheus-metrics-core/**' + - 'prometheus-metrics-exporter-*/**' + - 'prometheus-metrics-exposition-*/**' + - '.github/workflows/java-version-matrix-tests.yml' + push: + branches: + - main + workflow_dispatch: + +permissions: {} + +jobs: + integration-tests: + name: Java ${{ matrix.java-version }} + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + # Note: Java 8 runtime testing is skipped due to Spotless incompatibility + java-version: [11, 17, 21, 25] + steps: + - name: Check out + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Set up mise + uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8 # v3.6.1 + + - name: Cache local Maven repository + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + + - name: Build core library artifacts + run: mise exec -- ./mvnw install -DskipTests -Dspotless.check.skip=true -Dcoverage.skip=true -Dcheckstyle.skip=true -Dwarnings=-nowarn -pl '!integration-tests' + + - name: Install parent POMs + run: | + cd integration-tests + mise exec -- ../mvnw clean install -N -Dspotless.skip=true + cd it-exporter + mise exec -- ../../mvnw install -N -Dspotless.skip=true + + - name: Rebuild sample apps targeting Java ${{ matrix.java-version }} + run: | + cd integration-tests + # Note: Jetty 12 and Tomcat 11 require Java 17+, so servlet samples are skipped for Java 11 + if [ "${{ matrix.java-version }}" = "11" ]; then + MODULES="it-common,it-exporter/it-exporter-httpserver-sample,it-exporter/it-exporter-no-protobuf,it-pushgateway" + else + MODULES="it-common,it-exporter/it-exporter-httpserver-sample,it-exporter/it-exporter-servlet-tomcat-sample,it-exporter/it-exporter-servlet-jetty-sample,it-exporter/it-exporter-no-protobuf,it-pushgateway" + fi + mise exec -- ../mvnw clean install -DskipTests -Dspotless.skip=true -Dcoverage.skip=true -Dcheckstyle.skip=true -Dwarnings=-nowarn \ + -Djava.version=${{ matrix.java-version }} \ + -Dmaven.compiler.release=${{ matrix.java-version }} \ + -pl $MODULES + + - name: Run integration tests + env: + TEST_JAVA_VERSION: ${{ matrix.java-version }} + run: | + cd integration-tests + # Note: Servlet tests require Java 17+ (due to Jetty 12 and Tomcat 11) + if [ "${{ matrix.java-version }}" = "11" ]; then + TEST_MODULES="it-exporter/it-no-protobuf-test,it-pushgateway" + else + TEST_MODULES="it-exporter/it-exporter-test,it-exporter/it-no-protobuf-test,it-pushgateway" + fi + mise exec -- ../mvnw verify -T 2C -Dspotless.skip=true -Dcoverage.skip=true -Dcheckstyle.skip=true -Dwarnings=-nowarn \ + -pl $TEST_MODULES diff --git a/.github/workflows/lint-rest.yml b/.github/workflows/lint-rest.yml deleted file mode 100644 index 80afb4d1e..000000000 --- a/.github/workflows/lint-rest.yml +++ /dev/null @@ -1,21 +0,0 @@ ---- -name: Lint What Super Linter Can't - -on: [pull_request] - -permissions: {} - -jobs: - lint: - runs-on: ubuntu-24.04 - steps: - - name: Check out - with: - persist-credentials: false - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3.5.1 - with: - version: v2025.12.13 - sha256: 2134c55725d08547cddc921f84ddac05c9de1700115c32817563435072cae5ed - - name: Lint - run: mise run lint:rest diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 000000000..c6a2575c1 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,31 @@ +--- +name: Lint + +on: + pull_request: + +permissions: {} + +jobs: + lint: + runs-on: ubuntu-24.04 + + permissions: + contents: read + + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + fetch-depth: 0 # needed for git diff --merge-base in lint:links + + - name: Setup mise + uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8 # v3.6.1 + + - name: Lint + env: + GITHUB_TOKEN: ${{ github.token }} + GITHUB_HEAD_SHA: ${{ github.event.pull_request.head.sha }} + PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} + run: mise run lint diff --git a/.github/workflows/multi-version-test.yml b/.github/workflows/multi-version-test.yml new file mode 100644 index 000000000..92318c1aa --- /dev/null +++ b/.github/workflows/multi-version-test.yml @@ -0,0 +1,39 @@ +--- +name: Java-Version Compatibility Tests + +on: [pull_request] + +permissions: {} + +jobs: + compatibility-test: + name: Test on Java ${{ matrix.java }} + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + java: [17, 21, 25] + steps: + - name: Check out + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + + - name: Set up Java ${{ matrix.java }} + id: setup-java + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + distribution: "temurin" + java-version: ${{ matrix.java }} + + - name: Cache local Maven repository + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-java${{ matrix.java }}-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven-java${{ matrix.java }}- + ${{ runner.os }}-maven- + + - name: Build and test on Java ${{ matrix.java }} + run: ./mvnw clean install -Dtest.java.version=${{ matrix.java }} -Dspotless.skip=true -Dcheckstyle.skip=true -Dwarnings=-nowarn -Dcoverage.skip=true diff --git a/.github/workflows/native-tests.yml b/.github/workflows/native-tests.yml index 4c41dba19..b93edab06 100644 --- a/.github/workflows/native-tests.yml +++ b/.github/workflows/native-tests.yml @@ -12,11 +12,9 @@ jobs: - name: Check out with: persist-credentials: false - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - - uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3.5.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8 # v3.6.1 with: - version: v2025.12.13 - sha256: 2134c55725d08547cddc921f84ddac05c9de1700115c32817563435072cae5ed working_directory: .mise/envs/native - name: Run native tests working-directory: .mise/envs/native diff --git a/.github/workflows/nightly-benchmarks.yml b/.github/workflows/nightly-benchmarks.yml new file mode 100644 index 000000000..4ee4adbc5 --- /dev/null +++ b/.github/workflows/nightly-benchmarks.yml @@ -0,0 +1,99 @@ +--- +name: Nightly Benchmarks + +on: + schedule: + # Run at 2 AM UTC every day + - cron: "0 2 * * *" + workflow_dispatch: + inputs: + jmh_args: + description: "Additional JMH arguments (e.g., '-f 1 -wi 1 -i 3' for quick run)" + required: false + default: "" + +permissions: {} + +concurrency: + group: "benchmarks" + +defaults: + run: + shell: bash + +jobs: + benchmark: + runs-on: ubuntu-24.04 + permissions: + contents: write + steps: + - name: Checkout main branch + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: true + fetch-depth: 0 + + - name: Setup mise + uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8 # v3.6.1 + + - name: Cache local Maven repository + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + + - name: Run JMH benchmarks + run: mise run benchmark:ci-json + env: + JMH_ARGS: ${{ github.event.inputs.jmh_args }} + + - name: Generate benchmark summary + run: | + mise run benchmark:generate-summary \ + --input benchmark-results.json \ + --output-dir benchmark-results \ + --commit-sha "${{ github.sha }}" + env: + GITHUB_REPOSITORY: ${{ github.repository }} + + - name: Commit and push results to benchmarks branch + run: | + # Save results to a temp location + mkdir -p /tmp/benchmark-output + cp -r benchmark-results/* /tmp/benchmark-output/ + + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + # Checkout or create benchmarks branch (use -- to disambiguate from benchmarks/ directory) + if git ls-remote --heads origin benchmarks | grep -q benchmarks; then + git fetch origin benchmarks + git switch benchmarks + # Preserve existing history + if [ -d history ]; then + cp -r history /tmp/benchmark-output/ + fi + else + git switch --orphan benchmarks + fi + + # Clean working directory + git rm -rf . 2>/dev/null || true + find . -mindepth 1 -maxdepth 1 ! -name '.git' -exec rm -rf {} + + + # Copy only the benchmark results + cp -r /tmp/benchmark-output/* . + + git add README.md results.json history/ + + DATE=$(date -u +"%Y-%m-%d") + COMMIT_SHORT=$(echo "${{ github.sha }}" | cut -c1-7) + + git commit \ + -m "Benchmark results for ${DATE} (${COMMIT_SHORT})" \ + -m "From commit ${{ github.sha }}" \ + || echo "No changes to commit" + + git push origin benchmarks --force-with-lease || git push origin benchmarks diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml new file mode 100644 index 000000000..76a13e3df --- /dev/null +++ b/.github/workflows/pr-title.yml @@ -0,0 +1,18 @@ +--- +name: PR Title + +on: + pull_request: + types: + - opened + - edited +permissions: + pull-requests: read + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1 + env: + GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 000000000..75cf34f16 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,23 @@ +--- +name: Release Please + +on: + push: + branches: + - main + +permissions: + contents: write + pull-requests: write + +jobs: + release-please: + if: ${{ github.repository == 'prometheus/client_java' }} + runs-on: ubuntu-24.04 + steps: + - uses: googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38 # v4.4.0 + id: release-please + with: + token: ${{ secrets.GITHUB_TOKEN }} + config-file: .github/config/release-please-config.json + manifest-file: .github/config/.release-please-manifest.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6aaf1c05b..93d32c188 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,23 +20,19 @@ jobs: echo "${#GPG_SIGNING_KEY}" echo "${GPG_SIGNING_KEY}" | gpg --batch --import-options import-show --import - name: Checkout Plugin Repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: persist-credentials: false - - uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3.5.1 + - uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8 # v3.6.1 with: - version: v2025.12.13 - sha256: 2134c55725d08547cddc921f84ddac05c9de1700115c32817563435072cae5ed cache: false - name: Build release version run: mise run build-release - env: - TAG: ${{ github.ref_name }} - name: Set up Apache Maven Central - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: distribution: "temurin" java-version: "21" diff --git a/.github/workflows/super-linter.yml b/.github/workflows/super-linter.yml deleted file mode 100644 index eba4d3890..000000000 --- a/.github/workflows/super-linter.yml +++ /dev/null @@ -1,30 +0,0 @@ ---- -name: Lint - -on: [pull_request] - -jobs: - lint: - runs-on: ubuntu-24.04 - - permissions: - contents: read - packages: read - # To report GitHub Actions status checks - statuses: write - - steps: - - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - persist-credentials: false - fetch-depth: 0 - - - name: Load super-linter configuration - run: grep -v '^#' .github/super-linter.env | grep -v 'FIX_' >> "$GITHUB_ENV" - - - name: Super-linter - uses: super-linter/super-linter@d5b0a2ab116623730dd094f15ddc1b6b25bf7b99 # v8.3.2 - env: - # To report GitHub Actions status checks - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test-release-build.yml b/.github/workflows/test-release-build.yml index 17e27f116..f8de00d8c 100644 --- a/.github/workflows/test-release-build.yml +++ b/.github/workflows/test-release-build.yml @@ -13,22 +13,22 @@ jobs: build: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: persist-credentials: false - - uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3.5.1 - with: - version: v2025.12.13 - sha256: 2134c55725d08547cddc921f84ddac05c9de1700115c32817563435072cae5ed + fetch-tags: "true" + fetch-depth: 0 + - uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8 # v3.6.1 - name: Cache local Maven repository - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5 + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- + - name: Build GitHub Pages + run: mise run build-gh-pages + env: + BASE_URL: "/client_java" - name: Build release version run: mise run build-release - env: - # don't use the current snapshot version, to test a more realistic release - TAG: ${{ github.run_number }} diff --git a/.gitignore b/.gitignore index b727017a9..b98fa5703 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,9 @@ dependency-reduced-pom.xml **/.settings/ docs/public .lycheecache + +benchmark-results/ +benchmark-results.json +benchmark-output.log + +*.DS_Store \ No newline at end of file diff --git a/.mise/tasks/build-release.sh b/.mise/tasks/build-release.sh index a29b0d22f..620dca77a 100755 --- a/.mise/tasks/build-release.sh +++ b/.mise/tasks/build-release.sh @@ -1,12 +1,8 @@ #!/usr/bin/env bash #MISE description="Build release package" -#USAGE arg "" env="TAG" default="1.5.0-SNAPSHOT" set -euo pipefail -# shellcheck disable=SC2154 # is set by mise -VERSION=${usage_tag#v} - -mise run set-version "$VERSION" -mvn -B package -P 'release,!default' -Dmaven.test.skip=true +mvn -B package -P 'release,!default,!examples-and-integration-tests' \ + -Dmaven.test.skip=true -Dgpg.skip=true diff --git a/.mise/tasks/generate_benchmark_summary.py b/.mise/tasks/generate_benchmark_summary.py new file mode 100644 index 000000000..0b0c4fb01 --- /dev/null +++ b/.mise/tasks/generate_benchmark_summary.py @@ -0,0 +1,378 @@ +#!/usr/bin/env python3 + +# [MISE] description="Generate markdown summary from JMH benchmark JSON results" +# [MISE] alias="generate-benchmark-summary" + +""" +Generate a markdown summary from JMH benchmark JSON results. + +Usage: + python3 .mise/tasks/generate_benchmark_summary.py [--input results.json] [--output-dir ./benchmark-results] + +This script: +1. Reads JMH JSON output +2. Generates a README.md with formatted tables +3. Copies results to the output directory with historical naming +""" + +import argparse +import json +import os +import shutil +import sys +from datetime import datetime, timezone +from pathlib import Path +from typing import Dict, List, Optional + + +def parse_args(): + parser = argparse.ArgumentParser( + description="Generate benchmark summary from JMH JSON" + ) + parser.add_argument( + "--input", + default="benchmark-results.json", + help="Path to JMH JSON results file (default: benchmark-results.json)", + ) + parser.add_argument( + "--output-dir", + default="benchmark-results", + help="Output directory for results (default: benchmark-results)", + ) + parser.add_argument( + "--commit-sha", + default=None, + help="Git commit SHA (default: read from git or 'local')", + ) + return parser.parse_args() + + +def get_system_info() -> Dict[str, str]: + """Capture system hardware information.""" + import multiprocessing + import platform + + info = {} + + try: + info["cpu_cores"] = str(multiprocessing.cpu_count()) + except Exception: + pass + + try: + with open("/proc/cpuinfo", "r") as f: + for line in f: + if line.startswith("model name"): + info["cpu_model"] = line.split(":")[1].strip() + break + except FileNotFoundError: + # macOS + try: + import subprocess + + result = subprocess.run( + ["sysctl", "-n", "machdep.cpu.brand_string"], + capture_output=True, + text=True, + timeout=5, + ) + if result.returncode == 0: + info["cpu_model"] = result.stdout.strip() + except Exception: + pass + + try: + with open("/proc/meminfo", "r") as f: + for line in f: + if line.startswith("MemTotal"): + kb = int(line.split()[1]) + info["memory_gb"] = str(round(kb / 1024 / 1024)) + break + except FileNotFoundError: + # macOS + try: + import subprocess + + result = subprocess.run( + ["sysctl", "-n", "hw.memsize"], + capture_output=True, + text=True, + timeout=5, + ) + if result.returncode == 0: + bytes_mem = int(result.stdout.strip()) + info["memory_gb"] = str(round(bytes_mem / 1024 / 1024 / 1024)) + except Exception: + pass + + info["os"] = f"{platform.system()} {platform.release()}" + + return info + + +def get_commit_sha(provided_sha: Optional[str]) -> str: + """Get commit SHA from argument, git, or return 'local'.""" + if provided_sha: + return provided_sha + + try: + import subprocess + + result = subprocess.run( + ["git", "rev-parse", "HEAD"], + capture_output=True, + text=True, + timeout=5, + ) + if result.returncode == 0: + return result.stdout.strip() + except Exception: + pass + + return "local" + + +def format_score(score) -> str: + """Format score with appropriate precision.""" + try: + val = float(score) + if val >= 1_000_000: + return f"{val / 1_000_000:.2f}M" + elif val >= 1_000: + return f"{val / 1_000:.2f}K" + else: + return f"{val:.2f}" + except (ValueError, TypeError): + return str(score) + + +def format_error(error) -> str: + """Format error value, handling NaN.""" + try: + error_val = float(error) + if error_val != error_val: # NaN check + return "" + elif error_val >= 1_000: + return f"± {error_val / 1_000:.2f}K" + else: + return f"± {error_val:.2f}" + except (ValueError, TypeError): + return "" + + +def generate_markdown(results: List, commit_sha: str, repo: str) -> str: + """Generate markdown summary from JMH results.""" + commit_short = commit_sha[:7] + datetime_str = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") + + # Extract metadata from first result + first = results[0] if results else {} + jdk_version = first.get("jdkVersion", "unknown") + vm_name = first.get("vmName", "unknown") + threads = first.get("threads", "?") + forks = first.get("forks", "?") + warmup_iters = first.get("warmupIterations", "?") + measure_iters = first.get("measurementIterations", "?") + + sysinfo = get_system_info() + + md = [] + md.append("# Prometheus Java Client Benchmarks") + md.append("") + + md.append("## Run Information") + md.append("") + md.append(f"- **Date:** {datetime_str}") + if commit_sha != "local": + md.append( + f"- **Commit:** [`{commit_short}`](https://github.com/{repo}/commit/{commit_sha})" + ) + else: + md.append(f"- **Commit:** `{commit_short}` (local run)") + md.append(f"- **JDK:** {jdk_version} ({vm_name})") + bench_cfg = f"{forks} fork(s), {warmup_iters} warmup, {measure_iters} measurement, {threads} threads" + md.append(f"- **Benchmark config:** {bench_cfg}") + + hw_parts = [] + if sysinfo.get("cpu_model"): + hw_parts.append(sysinfo["cpu_model"]) + if sysinfo.get("cpu_cores"): + hw_parts.append(f"{sysinfo['cpu_cores']} cores") + if sysinfo.get("memory_gb"): + hw_parts.append(f"{sysinfo['memory_gb']} GB RAM") + if hw_parts: + md.append(f"- **Hardware:** {', '.join(hw_parts)}") + if sysinfo.get("os"): + md.append(f"- **OS:** {sysinfo['os']}") + + md.append("") + + # Group by benchmark class + benchmarks_by_class: Dict[str, List] = {} + for b in results: + name = b.get("benchmark", "") + parts = name.rsplit(".", 1) + if len(parts) == 2: + class_name, method = parts + class_short = class_name.split(".")[-1] + else: + class_short = "Other" + benchmarks_by_class.setdefault(class_short, []).append(b) + + md.append("## Results") + md.append("") + + # Generate table for each class + for class_name in sorted(benchmarks_by_class.keys()): + benchmarks = benchmarks_by_class[class_name] + md.append(f"### {class_name}") + md.append("") + + # Sort by score descending + sorted_benchmarks = sorted( + benchmarks, + key=lambda x: x.get("primaryMetric", {}).get("score", 0), + reverse=True, + ) + + md.append("| Benchmark | Score | Error | Units | |") + md.append("|:----------|------:|------:|:------|:---|") + + best_score = ( + sorted_benchmarks[0].get("primaryMetric", {}).get("score", 1) + if sorted_benchmarks + else 1 + ) + + for i, b in enumerate(sorted_benchmarks): + name = b.get("benchmark", "").split(".")[-1] + score = b.get("primaryMetric", {}).get("score", 0) + error = b.get("primaryMetric", {}).get("scoreError", 0) + unit = b.get("primaryMetric", {}).get("scoreUnit", "ops/s") + + score_fmt = format_score(score) + error_fmt = format_error(error) + + # Calculate relative performance as multiplier + try: + if i == 0: + relative_fmt = "**fastest**" + else: + multiplier = float(best_score) / float(score) + if multiplier >= 10: + relative_fmt = f"{multiplier:.0f}x slower" + else: + relative_fmt = f"{multiplier:.1f}x slower" + except (ValueError, TypeError, ZeroDivisionError): + relative_fmt = "" + + md.append( + f"| {name} | {score_fmt} | {error_fmt} | {unit} | {relative_fmt} |" + ) + + md.append("") + + md.append("### Raw Results") + md.append("") + md.append("```") + md.append( + f"{'Benchmark':<50} {'Mode':>6} {'Cnt':>4} {'Score':>14} {'Error':>12} Units" + ) + + for b in sorted(results, key=lambda x: x.get("benchmark", "")): + name = b.get("benchmark", "").replace("io.prometheus.metrics.benchmarks.", "") + mode = b.get("mode", "thrpt") + cnt = b.get("measurementIterations", 0) * b.get("forks", 1) + score = b.get("primaryMetric", {}).get("score", 0) + error = b.get("primaryMetric", {}).get("scoreError", 0) + unit = b.get("primaryMetric", {}).get("scoreUnit", "ops/s") + + try: + score_str = f"{float(score):.3f}" + except (ValueError, TypeError): + score_str = str(score) + + try: + error_val = float(error) + if error_val != error_val: # NaN + error_str = "" + else: + error_str = f"± {error_val:.3f}" + except (ValueError, TypeError): + error_str = "" + + md.append( + f"{name:<50} {mode:>6} {cnt:>4} {score_str:>14} {error_str:>12} {unit}" + ) + + md.append("```") + md.append("") + + md.append("## Notes") + md.append("") + md.append("- **Score** = Throughput in operations per second (higher is better)") + md.append("- **Error** = 99.9% confidence interval") + md.append("") + + md.append("## Benchmark Descriptions") + md.append("") + md.append("| Benchmark | Description |") + md.append("|:----------|:------------|") + md.append( + "| **CounterBenchmark** | Counter increment performance: " + "Prometheus, OpenTelemetry, simpleclient, Codahale |" + ) + md.append( + "| **HistogramBenchmark** | Histogram observation performance " + "(classic vs native/exponential) |" + ) + md.append( + "| **TextFormatUtilBenchmark** | Metric exposition format writing speed |" + ) + md.append("") + return "\n".join(md) + + +def main(): + args = parse_args() + + input_path = Path(args.input) + if not input_path.exists(): + print(f"Error: Input file not found: {input_path}") + sys.exit(1) + + print(f"Reading results from: {input_path}") + with open(input_path, "r") as f: + results = json.load(f) + + print(f"Found {len(results)} benchmark results") + + commit_sha = get_commit_sha(args.commit_sha) + commit_short = commit_sha[:7] + repo = os.environ.get("GITHUB_REPOSITORY", "prometheus/client_java") + + output_dir = Path(args.output_dir) + output_dir.mkdir(parents=True, exist_ok=True) + history_dir = output_dir / "history" + history_dir.mkdir(parents=True, exist_ok=True) + + results_json_path = output_dir / "results.json" + shutil.copy(input_path, results_json_path) + print(f"Copied results to: {results_json_path}") + + date_str = datetime.now(timezone.utc).strftime("%Y-%m-%d") + history_path = history_dir / f"{date_str}-{commit_short}.json" + shutil.copy(input_path, history_path) + print(f"Saved historical entry: {history_path}") + + markdown = generate_markdown(results, commit_sha, repo) + readme_path = output_dir / "README.md" + with open(readme_path, "w") as f: + f.write(markdown) + print(f"Generated summary: {readme_path}") + + print(f"\nDone! Results are in: {output_dir}/") + + +if __name__ == "__main__": + main() diff --git a/.mise/tasks/lint/bom.py b/.mise/tasks/lint/bom.py index bada5bc9f..d77b88e23 100755 --- a/.mise/tasks/lint/bom.py +++ b/.mise/tasks/lint/bom.py @@ -36,7 +36,6 @@ def add_dir(dir_path: Path, want: List[str]): raise FileNotFoundError(f"Directory {dir_path} does not exist.") if any(dir_path.name == ig for ig in IGNORE_DIRS): - print(f"Skipping {dir_path}") return pom = dir_path / "pom.xml" @@ -47,7 +46,6 @@ def add_dir(dir_path: Path, want: List[str]): if not artifact_id: raise RuntimeError(f"No artifactId found in {pom}") - print(f"Found artifactId '{artifact_id}' in {pom}") want.append(artifact_id) @@ -108,7 +106,6 @@ def main() -> int: sys.stdout.writelines(diff) return 1 else: - print("BOM file is up to date.") return 0 except Exception as e: diff --git a/.mise/tasks/lint/super-linter.sh b/.mise/tasks/lint/super-linter.sh deleted file mode 100755 index 54c2b434e..000000000 --- a/.mise/tasks/lint/super-linter.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash - -#MISE description="Run GitHub Super Linter on the repository" - -set -euo pipefail - -docker pull ghcr.io/super-linter/super-linter:latest - -docker run --rm \ - -e RUN_LOCAL=true \ - -e DEFAULT_BRANCH=main \ - --env-file ".github/super-linter.env" \ - -v "$(pwd)":/tmp/lint \ - ghcr.io/super-linter/super-linter:latest diff --git a/.mise/tasks/set-release-version-github-pages.sh b/.mise/tasks/set-release-version-github-pages.sh index 142d0eb82..2016373c8 100755 --- a/.mise/tasks/set-release-version-github-pages.sh +++ b/.mise/tasks/set-release-version-github-pages.sh @@ -1,9 +1,12 @@ #!/usr/bin/env bash -#MISE description="Set release version in GitHub Pages quickstart.md" +#MISE description="Set release version in all GitHub Pages docs" set -euox pipefail version=$(git tag -l | grep 'v' | sort | tail -1 | sed 's/v//') -marker="\$version" -sed -i "s/$marker/$version/g" docs/content/getting-started/quickstart.md +otelVersion=$(grep -oP '\K[^<]+' pom.xml | sed 's/-alpha$//') + +find ./docs/content -name '*.md' \ + -exec sed -i "s/\$version/$version/g" {} + \ + -exec sed -i "s/\$otelVersion/$otelVersion/g" {} + diff --git a/.mise/tasks/set-version.sh b/.mise/tasks/set-version.sh deleted file mode 100755 index 2309976ce..000000000 --- a/.mise/tasks/set-version.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash - -#MISE description="Update version in all pom.xml files" -#USAGE arg "" help="new version" - -set -euo pipefail - -# replace all occurrences '1.5.0-SNAPSHOT' with -# '$usage_version' in all pom.xml files in the current directory and -# subdirectories - -# shellcheck disable=SC2154 # is set by mise -find . -name 'pom.xml' -exec \ - sed -i "s/1.5.0-SNAPSHOT<\/version>/$usage_version<\/version>/g" {} + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..3e5ed1592 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,133 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) 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 for development) +mise run compile + +# Run unit tests only (skips formatting/coverage/checkstyle checks) +mise run test + +# Run all tests including integration tests +mise run test-all + +# Format code with Google Java Format +mise run format +# or directly: ./mvnw spotless:apply + +# Run a single test class +./mvnw test -Dtest=CounterTest -Dspotless.check.skip=true -Dcoverage.skip=true -Dcheckstyle.skip=true + +# Run a single test method +./mvnw test -Dtest=CounterTest#testIncrement -Dspotless.check.skip=true -Dcoverage.skip=true -Dcheckstyle.skip=true + +# Run tests in a specific module +./mvnw test -pl prometheus-metrics-core -Dspotless.check.skip=true -Dcoverage.skip=true -Dcheckstyle.skip=true + +# Regenerate protobuf classes (after protobuf dependency update) +mise run generate +``` + +## Architecture + +The library follows a layered architecture where metrics flow from core types through a registry to exporters: + +``` +prometheus-metrics-core (user-facing API) + │ + ▼ collect() +prometheus-metrics-model (immutable snapshots) + │ + ▼ +prometheus-metrics-exposition-formats (text/protobuf/OpenMetrics) + │ + ▼ +Exporters (httpserver, servlet, pushgateway, opentelemetry) +``` + +### Key Modules + +- **prometheus-metrics-core**: User-facing metric types (Counter, Gauge, Histogram, Summary, Info, StateSet). All metrics implement the `Collector` interface with a `collect()` method. +- **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 Spotless) +- **Line length**: 100 characters (enforced for ALL files including Markdown, Java, YAML, etc.) +- **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 org.assertj.core.api.Assertions.assertThat`) +- **Empty catch blocks**: Use `ignored` as the exception variable name +- **Markdown code blocks**: Always specify language (e.g., ` ```java`, ` ```bash`, ` ```text`) + +## Linting and Validation + +**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 (Spotless with Google Java Format) + - Static analysis (Error Prone with NullAway) + - Checkstyle validation + - Build succeeds (tests are skipped; run `mise run test` or `mise run test-all` to execute tests) + +### Non-Java Files (Markdown, YAML, JSON, shell scripts, etc.) + +- **ALWAYS** run `mise run lint` after modifying non-Java files + (runs super-linter + link checking + BOM check) +- `mise run fix` auto-fixes lint issues +- Super-linter will **auto-fix** many issues (formatting, trailing whitespace, etc.) +- It only reports ERROR-level issues (configured via `LOG_LEVEL=ERROR` in `.github/super-linter.env`) +- Common issues caught: + - Lines exceeding 100 characters in Markdown files + - Missing language tags in fenced code blocks + - Table formatting issues + - YAML/JSON syntax errors + +### Running Linters + +```bash +# After modifying Java files (run BEFORE committing) +mise run build + +# After modifying non-Java files (run BEFORE committing) +mise run lint +# or to auto-fix: mise run fix +``` + +## 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/CONTRIBUTING.md b/CONTRIBUTING.md index 5be7b073d..2abbd91e2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,6 +19,14 @@ the code. Run `./mvnw spotless:apply` to format the code (only changed files) before committing. +Or run all the linters: + +`mise run lint` + +To autofix linting issues: + +`mise run fix` + ## Running Tests If you're getting errors when running tests: @@ -52,12 +60,34 @@ or simply 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 ``` -Add the new `Metrics.java` to Git and commit it. +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/RELEASING.md b/RELEASING.md index 601034d01..25f2d59a5 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,39 +1,58 @@ # Releasing Instructions for Prometheus Java Client -## Before the Release +Releases are automated via +[release-please](https://github.com/googleapis/release-please). -If there have been significant changes since the last release, update the -benchmarks before creating a new release: +## How It Works -```shell -mise run update-benchmarks -``` +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 -## Create a Release +Add a `release-as: X.Y.0` footer to any commit on `main`: -1. Go to -2. Click on "Choose a tag", enter the tag name (e.g. `v0.1.0`), and click "Create a new tag". -3. Click on "Generate release notes" to auto-generate the release notes based on the commits since - the last release. -4. Click on "Publish release". +```text +feat: add new feature -## Major or minor release +release-as: 1.6.0 +``` + +Alternatively, edit the release PR title to +`chore(main): release 1.6.0`. + +## Before the Release -After the release is created, do a text replace everywhere in the repository to update the -snapshot version in the `pom.xml` files (and some other files) to the next version. -For example, if the last release was `1.4.0`, the next snapshot version should be `1.5.0-SNAPSHOT`. +If there have been significant changes since the last release, update +the benchmarks before merging the release PR: -Replace `1.4.0-SNAPSHOT` with `1.5.0-SNAPSHOT` in all following files. +```shell +mise run update-benchmarks +``` -## If the GPG key expired +## 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: +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/benchmarks/README.md b/benchmarks/README.md index 3bba56422..b4c824d85 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -10,6 +10,17 @@ Run benchmarks and update the results in the Javadoc of the benchmark classes: 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 @@ -22,6 +33,26 @@ Run only one specific benchmark: 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: diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml index b2fad5766..7c211006b 100644 --- a/benchmarks/pom.xml +++ b/benchmarks/pom.xml @@ -8,7 +8,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT benchmarks @@ -23,6 +23,7 @@ 0.16.0 3.0.2 true + true @@ -85,8 +86,8 @@ 1.8 1.8 - - + + -parameters diff --git a/checkstyle-suppressions.xml b/checkstyle-suppressions.xml index 5f632c578..82e964658 100644 --- a/checkstyle-suppressions.xml +++ b/checkstyle-suppressions.xml @@ -5,5 +5,20 @@ "https://checkstyle.org/dtds/suppressions_1_2.dtd"> - + + + + + + + + + + + + + + diff --git a/docs/content/_index.md b/docs/content/_index.md index 3b8966cf3..28e5165cd 100644 --- a/docs/content/_index.md +++ b/docs/content/_index.md @@ -30,7 +30,7 @@ synchronization. See Javadoc comments in **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/) +[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. diff --git a/docs/content/config/config.md b/docs/content/config/config.md index deceae000..cd7f7af7b 100644 --- a/docs/content/config/config.md +++ b/docs/content/config/config.md @@ -9,21 +9,21 @@ The Prometheus metrics library provides multiple options how to override configu - Properties file - System properties - -Future releases will add more options, like configuration via environment variables. +- Environment variables Example: ```properties -io.prometheus.exporter.httpServer.port=9401 +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.httpServer.port=9401` -- when starting your application. +- **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 @@ -34,25 +34,61 @@ The properties file is searched in the following locations: - 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.exemplarsEnabled | [Counter.Builder.withExemplars()]() | (1) (2) | -| io.prometheus.metrics.histogramNativeOnly | [Histogram.Builder.nativeOnly()]() | (2) | -| io.prometheus.metrics.histogramClassicOnly | [Histogram.Builder.classicOnly()]() | (2) | -| io.prometheus.metrics.histogramClassicUpperBounds | [Histogram.Builder.classicUpperBounds()]() | (3) | -| io.prometheus.metrics.histogramNativeInitialSchema | [Histogram.Builder.nativeInitialSchema()]() | | -| io.prometheus.metrics.histogramNativeMinZeroThreshold | [Histogram.Builder.nativeMinZeroThreshold()]() | | -| io.prometheus.metrics.histogramNativeMaxZeroThreshold | [Histogram.Builder.nativeMaxZeroThreshold()]() | | -| io.prometheus.metrics.histogramNativeMaxNumberOfBuckets | [Histogram.Builder.nativeMaxNumberOfBuckets()]() | | -| io.prometheus.metrics.histogramNativeResetDurationSeconds | [Histogram.Builder.nativeResetDuration()]() | | -| io.prometheus.metrics.summaryQuantiles | [Summary.Builder.quantile(double)]() | (4) | -| io.prometheus.metrics.summaryQuantileErrors | [Summary.Builder.quantile(double, double)]() | (5) | -| io.prometheus.metrics.summaryMaxAgeSeconds | [Summary.Builder.maxAgeSeconds()]() | | -| io.prometheus.metrics.summaryNumberOfAgeBuckets | [Summary.Builder.numberOfAgeBuckets()]() | | +| 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()]() | | @@ -64,20 +100,20 @@ not just for counters
(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.summaryQuantiles`. Example: `0.01, 0.005, 0.005`. +`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.histogramClassicUpperBounds=0.2, 0.4, 0.8, 1.0 +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.histogramClassicUpperBounds=0.2, 0.4, 0.8, 1.0 +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`. @@ -88,11 +124,11 @@ This works for all Metrics properties. -| Name | Javadoc | Note | -| -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | -| io.prometheus.exemplars.minRetentionPeriodSeconds | [ExemplarsProperties.getMinRetentionPeriodSeconds()]() | | -| io.prometheus.exemplars.maxRetentionPeriodSeconds | [ExemplarsProperties.getMaxRetentionPeriodSeconds()]() | | -| io.prometheus.exemplars.sampleIntervalMilliseconds | [ExemplarsProperties.getSampleIntervalMilliseconds()]() | | +| 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()]() | | @@ -100,10 +136,10 @@ This works for all Metrics properties. -| Name | Javadoc | Note | -| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | -| io.prometheus.exporter.includeCreatedTimestamps | [ExporterProperties.getIncludeCreatedTimestamps()]() | (1) | -| io.prometheus.exporter.exemplarsOnAllMetricTypes | [ExporterProperties.getExemplarsOnAllMetricTypes()]() | (1) | +| Name | Javadoc | Note | +| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | +| io.prometheus.exporter.include_created_timestamps | [ExporterProperties.getIncludeCreatedTimestamps()]() | (1) | +| io.prometheus.exporter.exemplars_on_all_metric_types | [ExporterProperties.getExemplarsOnAllMetricTypes()]() | (1) | @@ -113,12 +149,12 @@ This works for all Metrics properties. -| Name | Javadoc | Note | -| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | -| io.prometheus.exporter.filter.metricNameMustBeEqualTo | [ExporterFilterProperties.getAllowedMetricNames()]() | (1) | -| io.prometheus.exporter.filter.metricNameMustNotBeEqualTo | [ExporterFilterProperties.getExcludedMetricNames()]() | (2) | -| io.prometheus.exporter.filter.metricNameMustStartWith | [ExporterFilterProperties.getAllowedMetricNamePrefixes()]() | (3) | -| io.prometheus.exporter.filter.metricNameMustNotStartWith | [ExporterFilterProperties.getExcludedMetricNamePrefixes()]() | (4) | +| 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) | @@ -132,9 +168,9 @@ Only metrics starting with these prefixes will be exposed.
-| Name | Javadoc | Note | -| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ---- | -| io.prometheus.exporter.httpServer.port | [HTTPServer.Builder.port()]() | | +| Name | Javadoc | Note | +| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ---- | +| io.prometheus.exporter.http_server.port | [HTTPServer.Builder.port()]() | | @@ -142,18 +178,18 @@ Only metrics starting with these prefixes will be exposed.
-| 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.intervalSeconds | [OpenTelemetryExporter.Builder.intervalSeconds()]() | | -| io.prometheus.exporter.opentelemetry.timeoutSeconds | [OpenTelemetryExporter.Builder.timeoutSeconds()]() | | -| io.prometheus.exporter.opentelemetry.serviceName | [OpenTelemetryExporter.Builder.serviceName()]() | | -| io.prometheus.exporter.opentelemetry.serviceNamespace | [OpenTelemetryExporter.Builder.serviceNamespace()]() | | -| io.prometheus.exporter.opentelemetry.serviceInstanceId | [OpenTelemetryExporter.Builder.serviceInstanceId()]() | | -| io.prometheus.exporter.opentelemetry.serviceVersion | [OpenTelemetryExporter.Builder.serviceVersion()]() | | -| io.prometheus.exporter.opentelemetry.resourceAttributes | [OpenTelemetryExporter.Builder.resourceAttributes()]() | (3) | +| 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) | @@ -170,12 +206,12 @@ See Javadoc for details. -| 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.escapingScheme | [PushGateway.Builder.escapingScheme()]() | (1) | +| 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) | diff --git a/docs/content/exporters/httpserver.md b/docs/content/exporters/httpserver.md index 801ad60eb..a9017b0de 100644 --- a/docs/content/exporters/httpserver.md +++ b/docs/content/exporters/httpserver.md @@ -40,4 +40,4 @@ You can find an example of authentication and SSL in the See _config_ section (_todo_) on runtime configuration options. -- `io.prometheus.exporter.httpServer.port`: The port to bind to. +- `io.prometheus.exporter.http_server.port`: The port to bind to. diff --git a/docs/content/getting-started/metric-types.md b/docs/content/getting-started/metric-types.md index 46d53ece1..97424ef5c 100644 --- a/docs/content/getting-started/metric-types.md +++ b/docs/content/getting-started/metric-types.md @@ -121,6 +121,94 @@ for [Histogram.Builder](/client_java/api/io/prometheus/metrics/core/metrics/Hist 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. @@ -276,3 +364,6 @@ 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/performance.md b/docs/content/getting-started/performance.md index 31b8de162..435f0d18a 100644 --- a/docs/content/getting-started/performance.md +++ b/docs/content/getting-started/performance.md @@ -60,13 +60,13 @@ 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.histogramClassicOnly=true my-app.jar +java -Dio.prometheus.metrics.histogram_classic_only=true my-app.jar ``` or ```sh -java -Dio.prometheus.metrics.histogramNativeOnly=true my-app.jar +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 @@ -75,13 +75,13 @@ that it gets packed into your JAR file). The `prometheus.properties` file should line: ```properties -io.prometheus.metrics.histogramClassicOnly=true +io.prometheus.metrics.histogram_classic_only=true ``` or ```properties -io.prometheus.metrics.histogramNativeOnly=true +io.prometheus.metrics.histogram_native_only=true ``` Future releases will add more configuration options, like support for configuration via environment diff --git a/docs/content/getting-started/registry.md b/docs/content/getting-started/registry.md index afebbb304..7f561ecef 100644 --- a/docs/content/getting-started/registry.md +++ b/docs/content/getting-started/registry.md @@ -6,7 +6,7 @@ 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 Metrics with the Default Registry +## Registering a Metric with the Default Registry ```java Counter eventsTotal = Counter.builder() @@ -18,7 +18,7 @@ Counter eventsTotal = Counter.builder() The `register()` call above builds the counter and registers it with the global static `PrometheusRegistry.defaultRegistry`. Using the default registry is recommended. -## Registering a Metrics with a Custom Registry +## Registering a Metric with a Custom Registry You can also register your metric with a custom registry: @@ -78,12 +78,30 @@ Counter eventsTotal2 = Counter.builder() .register(); // IllegalArgumentException, because a metric with that name is already registered ``` +## 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 +implement `getPrometheusName()` and `getMetricType()` (and the MultiCollector per-name variants) so +the registry can enforce consistency. **Validation is skipped when metric name or type is +unavailable:** if `getPrometheusName()` or `getMetricType()` returns `null`, 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. + +When validation _is_ performed (name and type are non-null), **null label names are treated as an +empty label schema:** `getLabelNames()` returning `null` is normalized to `Collections.emptySet()` +and full label-schema validation and duplicate detection still apply. A collector that returns a +non-null type but leaves `getLabelNames()` as `null` is still validated, with its labels treated as +empty. + ## 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 unregistered an obsolete metric like this: +However, you can programmatically unregister an obsolete metric like this: ```java PrometheusRegistry.defaultRegistry.unregister(eventsTotal); diff --git a/docs/content/instrumentation/jvm.md b/docs/content/instrumentation/jvm.md index 804c1b09b..a9a15341f 100644 --- a/docs/content/instrumentation/jvm.md +++ b/docs/content/instrumentation/jvm.md @@ -3,6 +3,16 @@ 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: diff --git a/docs/content/internals/model.md b/docs/content/internals/model.md index c54e79ee3..e1b2af644 100644 --- a/docs/content/internals/model.md +++ b/docs/content/internals/model.md @@ -19,7 +19,10 @@ 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. +method to produce snapshots. Implementers that do not provide metric type or label names (returning +null from `getMetricType()` and `getLabelNames()`) are not validated at registration; they must +avoid producing the same metric name and label schema as another collector, or exposition may be +invalid. ## prometheus-metrics-model diff --git a/docs/content/otel/jvm-runtime-metrics.md b/docs/content/otel/jvm-runtime-metrics.md new file mode 100644 index 000000000..d61da1861 --- /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/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/themes/hugo-geekdoc/layouts/partials/microformats/schema.html b/docs/themes/hugo-geekdoc/layouts/partials/microformats/schema.html index e4a71eb4e..7e49ef8c7 100644 --- a/docs/themes/hugo-geekdoc/layouts/partials/microformats/schema.html +++ b/docs/themes/hugo-geekdoc/layouts/partials/microformats/schema.html @@ -1,70 +1,58 @@ {{ $isPage := or (and (ne .Type "posts") (in "section page" .Kind )) (and (eq .Type "posts") (eq .Kind "page")) }} {{- if eq .Kind "home" }} + {{- $schema := dict "@context" "http://schema.org" "@type" "WebSite" "name" .Site.Title "url" .Site.BaseURL "inLanguage" .Lang }} + {{- with partial "utils/description" . }} + {{- $schema = merge $schema (dict "description" (. | plainify | htmlUnescape | chomp)) }} + {{- end }} + {{- with partial "utils/featured" . }} + {{- $schema = merge $schema (dict "thumbnailUrl" .) }} + {{- end }} + {{- with .Site.Params.geekdocContentLicense }} + {{- $schema = merge $schema (dict "license" .name) }} + {{- end }} {{- else if $isPage }} + {{- $title := partial "utils/title" . }} + {{- $schema := dict + "@context" "http://schema.org" + "@type" "TechArticle" + "articleSection" (.Section | humanize | title) + "name" $title + "url" .Permalink + "headline" $title + "wordCount" (string .WordCount) + "inLanguage" .Lang + "isFamilyFriendly" "true" + "copyrightHolder" .Site.Title + "copyrightYear" (.Date.Format "2006") + "dateCreated" (.Date.Format "2006-01-02T15:04:05.00Z") + "datePublished" (.PublishDate.Format "2006-01-02T15:04:05.00Z") + "dateModified" (.Lastmod.Format "2006-01-02T15:04:05.00Z") + }} + {{- with .Params.lead }} + {{- $schema = merge $schema (dict "alternativeHeadline" .) }} + {{- end }} + {{- with partial "utils/description" . }} + {{- $schema = merge $schema (dict "description" (. | plainify | htmlUnescape | chomp)) }} + {{- end }} + {{- with partial "utils/featured" . }} + {{- $schema = merge $schema (dict "thumbnailUrl" .) }} + {{- end }} + {{- with .Site.Params.geekdocContentLicense }} + {{- $schema = merge $schema (dict "license" .name) }} + {{- end }} + {{- $mainEntity := dict "@type" "WebPage" "@id" .Permalink }} + {{- $schema = merge $schema (dict "mainEntityOfPage" $mainEntity) }} + {{- with $tags := .Params.tags }} + {{- $schema = merge $schema (dict "keywords" $tags) }} + {{- end }} + {{- $logoUrl := default "brand.svg" .Site.Params.logo | absURL }} + {{- $logo := dict "@type" "ImageObject" "url" $logoUrl "width" "32" "height" "32" }} + {{- $publisher := dict "@type" "Organization" "name" .Site.Title "url" .Site.BaseURL "logo" $logo }} + {{- $schema = merge $schema (dict "publisher" $publisher) }} {{- end }} diff --git a/examples/example-custom-buckets/README.md b/examples/example-custom-buckets/README.md new file mode 100644 index 000000000..a7a6a8564 --- /dev/null +++ b/examples/example-custom-buckets/README.md @@ -0,0 +1,170 @@ +# Native Histograms with Custom Buckets (NHCB) Example + +This example demonstrates how to use native histograms with custom bucket boundaries (NHCB) in +Prometheus Java client. It shows three different types of custom bucket configurations and how +Prometheus converts them to native histograms with schema -53. + +## What are Native Histograms with Custom Buckets? + +Native Histograms with Custom Buckets (NHCB) is a Prometheus feature that combines the benefits of: + +- **Custom bucket boundaries**: Precisely defined buckets optimized for your specific use case +- **Native histograms**: Efficient storage and querying capabilities of native histograms + +When you configure Prometheus with `convert_classic_histograms_to_nhcb: true`, it converts classic +histograms with custom buckets into native histograms using schema -53, preserving the custom +bucket boundaries. + +## Example Metrics + +This example application generates three different histogram metrics demonstrating different +bucket configuration strategies: + +### 1. API Latency - Arbitrary Custom Boundaries + +```java +Histogram apiLatency = Histogram.builder() + .name("api_request_duration_seconds") + .classicUpperBounds(0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0) + .register(); +``` + +**Use case**: Optimized for typical API response times in seconds. + +### 2. Queue Size - Linear Boundaries + +```java +Histogram queueSize = Histogram.builder() + .name("message_queue_size") + .classicLinearUpperBounds(10, 10, 10) // 10, 20, 30, ..., 100 + .register(); +``` + +**Use case**: Equal-width buckets for monitoring queue depth or other discrete values. + +### 3. Response Size - Exponential Boundaries + +```java +Histogram responseSize = Histogram.builder() + .name("http_response_size_bytes") + .classicExponentialUpperBounds(100, 10, 6) // 100, 1k, 10k, 100k, 1M, 10M + .register(); +``` + +**Use case**: Data spanning multiple orders of magnitude (bytes, milliseconds, etc). + +## Build + +This example is built as part of the `client_java` project: + +```shell +./mvnw package +``` + +This creates `./examples/example-custom-buckets/target/example-custom-buckets.jar`. + +## Run + +With the JAR file present, run: + +```shell +cd ./examples/example-custom-buckets/ +docker-compose up +``` + +This starts three Docker containers: + +- **[http://localhost:9400/metrics](http://localhost:9400/metrics)** - Example application +- **[http://localhost:9090](http://localhost:9090)** - Prometheus server (with NHCB enabled) +- **[http://localhost:3000](http://localhost:3000)** - Grafana (user: _admin_, password: _admin_) + +You might need to replace `localhost` with `host.docker.internal` on macOS or Windows. + +## Verify NHCB Conversion + +### 1. Check Prometheus Configuration + +The Prometheus configuration enables NHCB conversion: + +```yaml +scrape_configs: + - job_name: "custom-buckets-demo" + scrape_protocols: ["PrometheusProto"] + convert_classic_histograms_to_nhcb: true + scrape_classic_histograms: true +``` + +### 2. Verify in Prometheus + +Visit [http://localhost:9090](http://localhost:9090) and run queries: + +```promql +# View histogram metadata (should show schema -53 for NHCB) +prometheus_tsdb_head_series + +# Calculate quantiles from custom buckets +histogram_quantile(0.95, rate(api_request_duration_seconds[1m])) + +# View raw histogram structure +api_request_duration_seconds +``` + +### 3. View in Grafana + +The Grafana dashboard at [http://localhost:3000](http://localhost:3000) shows: + +- p95 and p50 latencies for API endpoints (arbitrary custom buckets) +- Queue size distribution (linear buckets) +- Response size distribution (exponential buckets) + +## Key Observations + +1. **Custom Buckets Preserved**: The custom bucket boundaries you define are preserved when + converted to NHCB (schema -53). + +2. **Dual Representation**: By default, histograms maintain both classic and native + representations, allowing gradual migration. + +3. **Efficient Storage**: Native histograms provide more efficient storage than classic histograms + while preserving your custom bucket boundaries. + +4. **Flexible Bucket Strategies**: You can choose arbitrary, linear, or exponential buckets based + on your specific monitoring needs. + +## When to Use Custom Buckets + +Consider using custom buckets (and NHCB) when: + +- **Precise boundaries needed**: You know the expected distribution and want specific bucket edges +- **Migrating from classic histograms**: You want to preserve existing bucket boundaries +- **Specific use cases**: Default exponential bucketing doesn't fit your distribution well + - Temperature ranges (might include negative values) + - Queue depths (discrete values with linear growth) + - File sizes (exponential growth but with specific thresholds) + - API latencies (specific SLA boundaries) + +## Differences from Standard Native Histograms + +| Feature | Standard Native Histograms | NHCB (Schema -53) | +| ----------------- | ------------------------------- | --------------------------------- | +| Bucket boundaries | Exponential (base 2^(2^-scale)) | Custom boundaries | +| Use case | General-purpose | Specific distributions | +| Mergeability | Can merge with same schema | Cannot merge different boundaries | +| Configuration | Schema level (0-8) | Explicit boundary list | + +## Cleanup + +Stop the containers: + +```shell +docker-compose down +``` + +## Further Reading + + + + +- [Prometheus Native Histograms Specification](https://prometheus.io/docs/specs/native_histograms/) +- [Prometheus Java Client Documentation](https://prometheus.github.io/client_java/) +- [OpenTelemetry Exponential Histograms](https://opentelemetry.io/docs/specs/otel/metrics/data-model/#exponentialhistogram) diff --git a/examples/example-custom-buckets/docker-compose.yaml b/examples/example-custom-buckets/docker-compose.yaml new file mode 100644 index 000000000..b024481af --- /dev/null +++ b/examples/example-custom-buckets/docker-compose.yaml @@ -0,0 +1,26 @@ +version: "3" +services: + example-application: + image: eclipse-temurin:25.0.2_10-jre@sha256:0a9c973778b03b88f39ccae4f8cc26022d84a3237a818cb98770369eb6c5daf9 + network_mode: host + volumes: + - ./target/example-custom-buckets.jar:/example-custom-buckets.jar + command: + - /opt/java/openjdk/bin/java + - -jar + - /example-custom-buckets.jar + prometheus: + image: prom/prometheus:v3.9.1@sha256:1f0f50f06acaceb0f5670d2c8a658a599affe7b0d8e78b898c1035653849a702 + network_mode: host + volumes: + - ./docker-compose/prometheus.yml:/prometheus.yml + command: + - --enable-feature=native-histograms + - --config.file=/prometheus.yml + grafana: + image: grafana/grafana:12.3.3@sha256:9e1e77ade304069aee3196e9a4f210830e96e80ce9a2640891eccc324b152faf + network_mode: host + volumes: + - ./docker-compose/grafana-datasources.yaml:/etc/grafana/provisioning/datasources/grafana-datasources.yaml + - ./docker-compose/grafana-dashboards.yaml:/etc/grafana/provisioning/dashboards/grafana-dashboards.yaml + - ./docker-compose/grafana-dashboard-custom-buckets.json:/etc/grafana/grafana-dashboard-custom-buckets.json diff --git a/examples/example-custom-buckets/docker-compose/grafana-dashboard-custom-buckets.json b/examples/example-custom-buckets/docker-compose/grafana-dashboard-custom-buckets.json new file mode 100644 index 000000000..11ae25775 --- /dev/null +++ b/examples/example-custom-buckets/docker-compose/grafana-dashboard-custom-buckets.json @@ -0,0 +1,349 @@ +{ + "annotations": { + "list": [] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "description": "API request duration with custom bucket boundaries (0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0 seconds). Shows how custom buckets are preserved in NHCB (schema -53).", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "tooltip": false, + "viz": false, + "legend": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": ["mean", "max"], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.95, rate(api_request_duration_seconds[1m]))", + "instant": false, + "legendFormat": "{{endpoint}} {{status}} (p95)", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.5, rate(api_request_duration_seconds[1m]))", + "hide": false, + "instant": false, + "legendFormat": "{{endpoint}} {{status}} (p50)", + "range": true, + "refId": "B" + } + ], + "title": "API Latency - Custom Buckets (Arbitrary Boundaries)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "description": "Queue size with linear bucket boundaries (10, 20, 30, ..., 100). Demonstrates equal-width buckets for discrete values.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "tooltip": false, + "viz": false, + "legend": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": ["mean", "max"], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.95, rate(message_queue_size[1m]))", + "instant": false, + "legendFormat": "{{queue_name}} (p95)", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.5, rate(message_queue_size[1m]))", + "hide": false, + "instant": false, + "legendFormat": "{{queue_name}} (p50)", + "range": true, + "refId": "B" + } + ], + "title": "Queue Size - Linear Buckets", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "description": "HTTP response size with exponential bucket boundaries (100, 1k, 10k, 100k, 1M, 10M bytes). Shows exponential growth for data spanning multiple orders of magnitude.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "tooltip": false, + "viz": false, + "legend": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 3, + "options": { + "legend": { + "calcs": ["mean", "max"], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.95, rate(http_response_size_bytes[1m]))", + "instant": false, + "legendFormat": "{{endpoint}} (p95)", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.5, rate(http_response_size_bytes[1m]))", + "hide": false, + "instant": false, + "legendFormat": "{{endpoint}} (p50)", + "range": true, + "refId": "B" + } + ], + "title": "Response Size - Exponential Buckets", + "type": "timeseries" + } + ], + "refresh": "5s", + "schemaVersion": 39, + "tags": ["custom-buckets", "nhcb", "native-histogram"], + "templating": { + "list": [] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Native Histograms with Custom Buckets (NHCB)", + "uid": "custom-buckets-nhcb", + "version": 1, + "weekStart": "" +} diff --git a/examples/example-custom-buckets/docker-compose/grafana-dashboards.yaml b/examples/example-custom-buckets/docker-compose/grafana-dashboards.yaml new file mode 100644 index 000000000..3225b88ae --- /dev/null +++ b/examples/example-custom-buckets/docker-compose/grafana-dashboards.yaml @@ -0,0 +1,8 @@ +apiVersion: 1 + +providers: + - name: "Custom Buckets (NHCB) Example" + type: file + options: + path: /etc/grafana/grafana-dashboard-custom-buckets.json + foldersFromFilesStructure: false diff --git a/examples/example-custom-buckets/docker-compose/grafana-datasources.yaml b/examples/example-custom-buckets/docker-compose/grafana-datasources.yaml new file mode 100644 index 000000000..d442d28d2 --- /dev/null +++ b/examples/example-custom-buckets/docker-compose/grafana-datasources.yaml @@ -0,0 +1,7 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + type: prometheus + uid: prometheus + url: http://localhost:9090 diff --git a/examples/example-custom-buckets/docker-compose/prometheus.yml b/examples/example-custom-buckets/docker-compose/prometheus.yml new file mode 100644 index 000000000..5c5782023 --- /dev/null +++ b/examples/example-custom-buckets/docker-compose/prometheus.yml @@ -0,0 +1,14 @@ +--- +global: + scrape_interval: 5s # very short interval for demo purposes + +scrape_configs: + - job_name: "custom-buckets-demo" + # Use protobuf format to receive native histogram data + scrape_protocols: ["PrometheusProto"] + # Convert classic histograms with custom buckets to NHCB (schema -53) + convert_classic_histograms_to_nhcb: true + # Also scrape classic histograms for comparison + scrape_classic_histograms: true + static_configs: + - targets: ["localhost:9400"] diff --git a/examples/example-custom-buckets/pom.xml b/examples/example-custom-buckets/pom.xml new file mode 100644 index 000000000..ca4c52843 --- /dev/null +++ b/examples/example-custom-buckets/pom.xml @@ -0,0 +1,72 @@ + + + 4.0.0 + + io.prometheus + example-custom-buckets + 1.0-SNAPSHOT + + + 8 + UTF-8 + + + Example - Custom Buckets + + End-to-End example of Native Histograms with Custom Buckets (NHCB): Java app -> Prometheus -> Grafana + + + + + + io.prometheus + prometheus-metrics-bom + 1.5.0 + pom + import + + + + + + + io.prometheus + prometheus-metrics-core + + + io.prometheus + prometheus-metrics-instrumentation-jvm + + + io.prometheus + prometheus-metrics-exporter-httpserver + + + + + ${project.artifactId} + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + + + io.prometheus.metrics.examples.custombuckets.Main + + + + + + + + + diff --git a/examples/example-custom-buckets/src/main/java/io/prometheus/metrics/examples/custombuckets/Main.java b/examples/example-custom-buckets/src/main/java/io/prometheus/metrics/examples/custombuckets/Main.java new file mode 100644 index 000000000..3d286fdf0 --- /dev/null +++ b/examples/example-custom-buckets/src/main/java/io/prometheus/metrics/examples/custombuckets/Main.java @@ -0,0 +1,108 @@ +package io.prometheus.metrics.examples.custombuckets; + +import io.prometheus.metrics.core.metrics.Histogram; +import io.prometheus.metrics.exporter.httpserver.HTTPServer; +import io.prometheus.metrics.instrumentation.jvm.JvmMetrics; +import io.prometheus.metrics.model.snapshots.Unit; +import java.io.IOException; +import java.util.Random; + +/** + * Example demonstrating native histograms with custom buckets (NHCB). + * + *

This example shows three different types of custom bucket configurations: + * + *

    + *
  • API latency with arbitrary custom boundaries optimized for typical response times + *
  • Queue size with linear boundaries for equal-width buckets + *
  • Response size with exponential boundaries for data spanning multiple orders of magnitude + *
+ * + *

These histograms maintain both classic (with custom buckets) and native representations. When + * Prometheus is configured with {@code convert_classic_histograms_to_nhcb: true}, the custom bucket + * boundaries are preserved in the native histogram format (schema -53). + */ +public class Main { + + public static void main(String[] args) throws IOException, InterruptedException { + + JvmMetrics.builder().register(); + + // Example 1: API latency with arbitrary custom boundaries + // Optimized for typical API response times in seconds + Histogram apiLatency = + Histogram.builder() + .name("api_request_duration_seconds") + .help("API request duration with custom buckets") + .unit(Unit.SECONDS) + .classicUpperBounds(0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0) + .labelNames("endpoint", "status") + .register(); + + // Example 2: Queue size with linear boundaries + // Equal-width buckets for monitoring queue depth + Histogram queueSize = + Histogram.builder() + .name("message_queue_size") + .help("Number of messages in queue with linear buckets") + .classicLinearUpperBounds(10, 10, 10) // 10, 20, 30, ..., 100 + .labelNames("queue_name") + .register(); + + // Example 3: Response size with exponential boundaries + // Exponential growth for data spanning multiple orders of magnitude + Histogram responseSize = + Histogram.builder() + .name("http_response_size_bytes") + .help("HTTP response size in bytes with exponential buckets") + .classicExponentialUpperBounds(100, 10, 6) // 100, 1k, 10k, 100k, 1M, 10M + .labelNames("endpoint") + .register(); + + HTTPServer server = HTTPServer.builder().port(9400).buildAndStart(); + + System.out.println( + "HTTPServer listening on port http://localhost:" + server.getPort() + "/metrics"); + System.out.println("\nGenerating metrics with custom bucket configurations:"); + System.out.println("1. API latency: custom boundaries optimized for response times"); + System.out.println("2. Queue size: linear boundaries (10, 20, 30, ..., 100)"); + System.out.println("3. Response size: exponential boundaries (100, 1k, 10k, ..., 10M)"); + System.out.println("\nPrometheus will convert these to NHCB (schema -53) when configured.\n"); + + Random random = new Random(0); + + while (true) { + // Simulate API latency observations + // Fast endpoint: mostly < 100ms, occasionally slow + double fastLatency = Math.abs(random.nextGaussian() * 0.03 + 0.05); + String status = random.nextInt(100) < 95 ? "200" : "500"; + apiLatency.labelValues("/api/fast", status).observe(fastLatency); + + // Slow endpoint: typically 1-3 seconds + double slowLatency = Math.abs(random.nextGaussian() * 0.5 + 2.0); + apiLatency.labelValues("/api/slow", status).observe(slowLatency); + + // Simulate queue size observations + // Queue oscillates between 20-80 items + int queueDepth = 50 + (int) (random.nextGaussian() * 15); + queueDepth = Math.max(0, Math.min(100, queueDepth)); + queueSize.labelValues("default").observe(queueDepth); + + // Priority queue: usually smaller + int priorityQueueDepth = 10 + (int) (random.nextGaussian() * 5); + priorityQueueDepth = Math.max(0, Math.min(50, priorityQueueDepth)); + queueSize.labelValues("priority").observe(priorityQueueDepth); + + // Simulate response size observations + // Small responses: mostly < 10KB + double smallResponse = Math.abs(random.nextGaussian() * 2000 + 5000); + responseSize.labelValues("/api/summary").observe(smallResponse); + + // Large responses: can be up to several MB + double largeResponse = Math.abs(random.nextGaussian() * 200000 + 500000); + responseSize.labelValues("/api/download").observe(largeResponse); + + Thread.sleep(1000); + } + } +} diff --git a/examples/example-exemplars-tail-sampling/docker-compose.yaml b/examples/example-exemplars-tail-sampling/docker-compose.yaml index 6b3f50b32..dee885885 100644 --- a/examples/example-exemplars-tail-sampling/docker-compose.yaml +++ b/examples/example-exemplars-tail-sampling/docker-compose.yaml @@ -36,7 +36,7 @@ services: - -jar - /example-greeting-service.jar collector: - image: otel/opentelemetry-collector-contrib:0.143.1@sha256:f051aff195ad50ed5ad9d95bcdd51d7258200c937def3797cf830366ed62e034 + image: otel/opentelemetry-collector-contrib:0.146.1@sha256:f6e429c1052ab50f85a7afa5f7e32f25931697751622b0e1f453d10f79a1df3c network_mode: host volumes: - ./config/otelcol-config.yaml:/config.yaml @@ -52,14 +52,14 @@ services: - --enable-feature=native-histograms - --config.file=/prometheus.yaml tempo: - image: grafana/tempo:2.9.0@sha256:65a5789759435f1ef696f1953258b9bbdb18eb571d5ce711ff812d2e128288a4 + image: grafana/tempo:2.10.1@sha256:9371af1b75b4e057eb77f22dc4dd4d9176cd6985e29f181527be6723b7f29c41 network_mode: host volumes: - ./config/tempo-config.yaml:/config.yaml command: - --config.file=/config.yaml grafana: - image: grafana/grafana:12.3.1@sha256:2175aaa91c96733d86d31cf270d5310b278654b03f5718c59de12a865380a31f + image: grafana/grafana:12.3.3@sha256:9e1e77ade304069aee3196e9a4f210830e96e80ce9a2640891eccc324b152faf network_mode: host ports: - "3000:3000" @@ -68,7 +68,7 @@ services: - ./config/grafana-dashboards.yaml:/etc/grafana/provisioning/dashboards/grafana-dashboards.yaml - ./config/grafana-example-dashboard.json:/etc/grafana/example-dashboard.json k6: - image: grafana/k6@sha256:a7c79af2b374c9a3afa8b0fae9ec2899277d066612029b7b0fcd2fcb724ba86f + image: grafana/k6@sha256:5e937f439684142ba7803722b42e3c9ac9233cfa01d561de0596c1c2794fd680 network_mode: host volumes: - ./config/k6-script.js:/k6-script.js diff --git a/examples/example-exemplars-tail-sampling/example-greeting-service/pom.xml b/examples/example-exemplars-tail-sampling/example-greeting-service/pom.xml index ca96b3723..8621a7e19 100644 --- a/examples/example-exemplars-tail-sampling/example-greeting-service/pom.xml +++ b/examples/example-exemplars-tail-sampling/example-greeting-service/pom.xml @@ -4,13 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - io.prometheus - example-exemplars-tail-sampling - 1.5.0-SNAPSHOT - - + io.prometheus example-greeting-service + 1.0-SNAPSHOT + + + 17 + UTF-8 + Example - OpenTelemetry Exemplars - Greeting Service @@ -18,30 +19,35 @@ tracing - - 25 - + + + + io.prometheus + prometheus-metrics-bom + 1.5.0 + pom + import + + + io.prometheus prometheus-metrics-core - ${project.version} io.prometheus prometheus-metrics-instrumentation-jvm - ${project.version} io.prometheus prometheus-metrics-exporter-servlet-jakarta - ${project.version} org.apache.tomcat.embed tomcat-embed-core - 11.0.15 + 11.0.18 diff --git a/examples/example-exemplars-tail-sampling/example-hello-world-app/pom.xml b/examples/example-exemplars-tail-sampling/example-hello-world-app/pom.xml index f3664d80b..df861667f 100644 --- a/examples/example-exemplars-tail-sampling/example-hello-world-app/pom.xml +++ b/examples/example-exemplars-tail-sampling/example-hello-world-app/pom.xml @@ -4,13 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - io.prometheus - example-exemplars-tail-sampling - 1.5.0-SNAPSHOT - - + io.prometheus example-hello-world-app + 1.0-SNAPSHOT + + + 17 + UTF-8 + Example - OpenTelemetry Exemplars - Hello World App @@ -18,30 +19,35 @@ tracing - - 25 - + + + + io.prometheus + prometheus-metrics-bom + 1.5.0 + pom + import + + + io.prometheus prometheus-metrics-core - ${project.version} io.prometheus prometheus-metrics-instrumentation-jvm - ${project.version} io.prometheus prometheus-metrics-exporter-servlet-jakarta - ${project.version} org.apache.tomcat.embed tomcat-embed-core - 11.0.15 + 11.0.18 diff --git a/examples/example-exemplars-tail-sampling/pom.xml b/examples/example-exemplars-tail-sampling/pom.xml index 8a739e939..ac4c6ccf5 100644 --- a/examples/example-exemplars-tail-sampling/pom.xml +++ b/examples/example-exemplars-tail-sampling/pom.xml @@ -4,24 +4,16 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - io.prometheus - examples - 1.5.0-SNAPSHOT - - + io.prometheus example-exemplars-tail-sampling + 1.0-SNAPSHOT pom Example - Exemplars with OpenTelemetry's Tail Sampling - Example project showing Examplars with OpenTelemetry's Tail Sampling. + Example project showing Exemplars with OpenTelemetry's Tail Sampling. - - 11 - - example-greeting-service example-hello-world-app diff --git a/examples/example-exporter-httpserver/pom.xml b/examples/example-exporter-httpserver/pom.xml index f9ee206f0..7160339ad 100644 --- a/examples/example-exporter-httpserver/pom.xml +++ b/examples/example-exporter-httpserver/pom.xml @@ -4,34 +4,44 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - io.prometheus - examples - 1.5.0-SNAPSHOT - - + io.prometheus example-exporter-httpserver + 1.0-SNAPSHOT + + + 8 + UTF-8 + Example - HTTPServer Exporter Prometheus Metrics Example using the HTTPServer for exposing the metrics endpoint + + + + io.prometheus + prometheus-metrics-bom + 1.5.0 + pom + import + + + + io.prometheus prometheus-metrics-core - ${project.version} io.prometheus prometheus-metrics-instrumentation-jvm - ${project.version} io.prometheus prometheus-metrics-exporter-httpserver - ${project.version} diff --git a/examples/example-exporter-multi-target/pom.xml b/examples/example-exporter-multi-target/pom.xml index ac13ff2a1..e5ee1bf83 100644 --- a/examples/example-exporter-multi-target/pom.xml +++ b/examples/example-exporter-multi-target/pom.xml @@ -4,34 +4,44 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - io.prometheus - examples - 1.5.0-SNAPSHOT - - + io.prometheus example-exporter-multi-target + 1.0-SNAPSHOT + + + 8 + UTF-8 + Example - HTTPServer Exporter Multi Target Prometheus Metrics Example for multi-target pattern implementation + + + + io.prometheus + prometheus-metrics-bom + 1.5.0 + pom + import + + + + io.prometheus prometheus-metrics-core - ${project.version} io.prometheus prometheus-metrics-instrumentation-jvm - ${project.version} io.prometheus prometheus-metrics-exporter-httpserver - ${project.version} diff --git a/examples/example-exporter-opentelemetry/docker-compose.yaml b/examples/example-exporter-opentelemetry/docker-compose.yaml index 9d9b8fda9..97bc9ab9b 100644 --- a/examples/example-exporter-opentelemetry/docker-compose.yaml +++ b/examples/example-exporter-opentelemetry/docker-compose.yaml @@ -13,7 +13,7 @@ services: #- -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005 - /example-exporter-opentelemetry.jar collector: - image: otel/opentelemetry-collector-contrib:0.143.1@sha256:f051aff195ad50ed5ad9d95bcdd51d7258200c937def3797cf830366ed62e034 + image: otel/opentelemetry-collector-contrib:0.146.1@sha256:f6e429c1052ab50f85a7afa5f7e32f25931697751622b0e1f453d10f79a1df3c network_mode: host volumes: - ./config/otelcol-config.yaml:/config.yaml diff --git a/examples/example-exporter-opentelemetry/oats-tests/agent/Dockerfile b/examples/example-exporter-opentelemetry/oats-tests/agent/Dockerfile index 861890709..bc1adac60 100644 --- a/examples/example-exporter-opentelemetry/oats-tests/agent/Dockerfile +++ b/examples/example-exporter-opentelemetry/oats-tests/agent/Dockerfile @@ -1,4 +1,4 @@ -FROM eclipse-temurin:25.0.1_8-jre@sha256:f6b092537e68d9836e86f676344e94102f2be325bbc652133cd9ef85b27d3ea9 +FROM eclipse-temurin:25.0.2_10-jre@sha256:0a9c973778b03b88f39ccae4f8cc26022d84a3237a818cb98770369eb6c5daf9 COPY target/example-exporter-opentelemetry.jar ./app.jar # check that the resource attributes from the agent are used, epsecially the service.instance.id should be the same diff --git a/examples/example-exporter-opentelemetry/oats-tests/agent/service_instance_id_check.py b/examples/example-exporter-opentelemetry/oats-tests/agent/service_instance_id_check.py index 6bb8291f7..35ff88b8d 100755 --- a/examples/example-exporter-opentelemetry/oats-tests/agent/service_instance_id_check.py +++ b/examples/example-exporter-opentelemetry/oats-tests/agent/service_instance_id_check.py @@ -3,6 +3,7 @@ Check if the service instance id is present in the exported data. Returns 0 if the service instance id is present in the exported data. """ + import json import urllib.parse from urllib.request import urlopen diff --git a/examples/example-exporter-opentelemetry/oats-tests/http/Dockerfile b/examples/example-exporter-opentelemetry/oats-tests/http/Dockerfile index ea011f6c3..763ba191f 100644 --- a/examples/example-exporter-opentelemetry/oats-tests/http/Dockerfile +++ b/examples/example-exporter-opentelemetry/oats-tests/http/Dockerfile @@ -1,4 +1,4 @@ -FROM eclipse-temurin:25.0.1_8-jre@sha256:f6b092537e68d9836e86f676344e94102f2be325bbc652133cd9ef85b27d3ea9 +FROM eclipse-temurin:25.0.2_10-jre@sha256:0a9c973778b03b88f39ccae4f8cc26022d84a3237a818cb98770369eb6c5daf9 COPY target/example-exporter-opentelemetry.jar ./app.jar diff --git a/examples/example-exporter-opentelemetry/pom.xml b/examples/example-exporter-opentelemetry/pom.xml index 8e8fa6891..7c7501a57 100644 --- a/examples/example-exporter-opentelemetry/pom.xml +++ b/examples/example-exporter-opentelemetry/pom.xml @@ -4,34 +4,44 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - io.prometheus - examples - 1.5.0-SNAPSHOT - - + io.prometheus example-exporter-opentelemetry + 1.0-SNAPSHOT + + + 8 + UTF-8 + Example - OpenTelemetry Metrics Exporter Example of exposing metrics in OpenTelemetry format and pushing them to an OpenTelemetry collector + + + + io.prometheus + prometheus-metrics-bom + 1.5.0 + pom + import + + + + io.prometheus prometheus-metrics-core - ${project.version} io.prometheus prometheus-metrics-instrumentation-jvm - ${project.version} io.prometheus prometheus-metrics-exporter-opentelemetry - ${project.version} diff --git a/examples/example-exporter-servlet-tomcat/README.md b/examples/example-exporter-servlet-tomcat/README.md index 05ac894e3..01e76832d 100644 --- a/examples/example-exporter-servlet-tomcat/README.md +++ b/examples/example-exporter-servlet-tomcat/README.md @@ -71,7 +71,7 @@ browser: static_configs: - targets: ["localhost:8080"] ``` -4. Run with native histograms and examplars enabled: +4. Run with native histograms and exemplars enabled: ```shell ./prometheus --enable-feature=native-histograms --enable-feature=exemplar-storage ``` diff --git a/examples/example-exporter-servlet-tomcat/pom.xml b/examples/example-exporter-servlet-tomcat/pom.xml index b5f0d1e60..ab5ba0198 100644 --- a/examples/example-exporter-servlet-tomcat/pom.xml +++ b/examples/example-exporter-servlet-tomcat/pom.xml @@ -3,43 +3,49 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - io.prometheus - examples - 1.5.0-SNAPSHOT - - + io.prometheus example-exporter-servlet-tomcat + 1.0-SNAPSHOT + + + 17 + UTF-8 + Example - Servlet Exporter with Tomcat Prometheus Metrics Example using Embedded Tomcat and the Exporter Servlet - - 25 - + + + + io.prometheus + prometheus-metrics-bom + 1.5.0 + pom + import + + + io.prometheus prometheus-metrics-core - ${project.version} io.prometheus prometheus-metrics-instrumentation-jvm - ${project.version} io.prometheus prometheus-metrics-exporter-servlet-jakarta - ${project.version} org.apache.tomcat.embed tomcat-embed-core - 11.0.15 + 11.0.18 diff --git a/examples/example-native-histogram/docker-compose.yaml b/examples/example-native-histogram/docker-compose.yaml index 30b33e2d1..492ce015f 100644 --- a/examples/example-native-histogram/docker-compose.yaml +++ b/examples/example-native-histogram/docker-compose.yaml @@ -1,7 +1,7 @@ version: "3" services: example-application: - image: eclipse-temurin:25.0.1_8-jre@sha256:f6b092537e68d9836e86f676344e94102f2be325bbc652133cd9ef85b27d3ea9 + image: eclipse-temurin:25.0.2_10-jre@sha256:0a9c973778b03b88f39ccae4f8cc26022d84a3237a818cb98770369eb6c5daf9 network_mode: host volumes: - ./target/example-native-histogram.jar:/example-native-histogram.jar @@ -18,7 +18,7 @@ services: - --enable-feature=native-histograms - --config.file=/prometheus.yml grafana: - image: grafana/grafana:12.3.1@sha256:2175aaa91c96733d86d31cf270d5310b278654b03f5718c59de12a865380a31f + image: grafana/grafana:12.3.3@sha256:9e1e77ade304069aee3196e9a4f210830e96e80ce9a2640891eccc324b152faf network_mode: host volumes: - ./docker-compose/grafana-datasources.yaml:/etc/grafana/provisioning/datasources/grafana-datasources.yaml diff --git a/examples/example-native-histogram/pom.xml b/examples/example-native-histogram/pom.xml index 5324ffb91..7d799cc52 100644 --- a/examples/example-native-histogram/pom.xml +++ b/examples/example-native-histogram/pom.xml @@ -3,34 +3,44 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - io.prometheus - examples - 1.5.0-SNAPSHOT - - + io.prometheus example-native-histogram + 1.0-SNAPSHOT + + + 8 + UTF-8 + Example - Native Histogram End-to-End example of a Native histogram: Java app -> Prometheus -> Grafana + + + + io.prometheus + prometheus-metrics-bom + 1.5.0 + pom + import + + + + io.prometheus prometheus-metrics-core - ${project.version} io.prometheus prometheus-metrics-instrumentation-jvm - ${project.version} io.prometheus prometheus-metrics-exporter-httpserver - ${project.version} diff --git a/examples/example-otel-jvm-runtime-metrics/README.md b/examples/example-otel-jvm-runtime-metrics/README.md new file mode 100644 index 000000000..a58584694 --- /dev/null +++ b/examples/example-otel-jvm-runtime-metrics/README.md @@ -0,0 +1,41 @@ +# OTel JVM Runtime Metrics with Prometheus HTTPServer + +## Build + +This example is built as part of the `client_java` project. + +```shell +./mvnw package +``` + +## Run + +The build creates a JAR file with the example application in +`./examples/example-otel-jvm-runtime-metrics/target/`. + +```shell +java -jar ./examples/example-otel-jvm-runtime-metrics/target/example-otel-jvm-runtime-metrics.jar +``` + +## Manually Testing the Metrics Endpoint + +Accessing +[http://localhost:9400/metrics](http://localhost:9400/metrics) +with a Web browser should yield both a Prometheus counter metric +and OTel JVM runtime metrics on the same endpoint. + +Prometheus counter: + +```text +# HELP uptime_seconds_total total number of seconds since this application was started +# TYPE uptime_seconds_total counter +uptime_seconds_total 42.0 +``` + +OTel JVM runtime metrics (excerpt): + +```text +# HELP jvm_memory_used_bytes Measure of memory used. +# TYPE jvm_memory_used_bytes gauge +jvm_memory_used_bytes{jvm_memory_pool_name="G1 Eden Space",jvm_memory_type="heap"} 4194304.0 +``` diff --git a/examples/example-otel-jvm-runtime-metrics/pom.xml b/examples/example-otel-jvm-runtime-metrics/pom.xml new file mode 100644 index 000000000..58869bfd7 --- /dev/null +++ b/examples/example-otel-jvm-runtime-metrics/pom.xml @@ -0,0 +1,85 @@ + + + 4.0.0 + + io.prometheus + example-otel-jvm-runtime-metrics + 1.0-SNAPSHOT + + + 8 + UTF-8 + + + Example - OTel JVM Runtime Metrics + + Example of combining Prometheus metrics with OpenTelemetry JVM runtime metrics on one endpoint + + + + + + io.prometheus + prometheus-metrics-bom + 1.5.0 + pom + import + + + io.opentelemetry.instrumentation + opentelemetry-instrumentation-bom-alpha + 2.25.0-alpha + pom + import + + + + + + + io.prometheus + prometheus-metrics-core + + + io.prometheus + prometheus-metrics-exporter-httpserver + + + io.prometheus + prometheus-metrics-otel-support + pom + + + io.opentelemetry.instrumentation + opentelemetry-runtime-telemetry-java8 + + + + + ${project.artifactId} + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + + + io.prometheus.metrics.examples.otelruntimemetrics.Main + + + + + + + + + diff --git a/examples/example-otel-jvm-runtime-metrics/src/main/java/io/prometheus/metrics/examples/otelruntimemetrics/Main.java b/examples/example-otel-jvm-runtime-metrics/src/main/java/io/prometheus/metrics/examples/otelruntimemetrics/Main.java new file mode 100644 index 000000000..49a608651 --- /dev/null +++ b/examples/example-otel-jvm-runtime-metrics/src/main/java/io/prometheus/metrics/examples/otelruntimemetrics/Main.java @@ -0,0 +1,76 @@ +package io.prometheus.metrics.examples.otelruntimemetrics; + +import io.opentelemetry.exporter.prometheus.PrometheusMetricReader; +import io.opentelemetry.instrumentation.runtimemetrics.java8.RuntimeMetrics; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.metrics.SdkMeterProvider; +import io.prometheus.metrics.core.metrics.Counter; +import io.prometheus.metrics.exporter.httpserver.HTTPServer; +import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.Unit; +import java.io.IOException; + +/** + * Example combining Prometheus metrics with OpenTelemetry JVM runtime metrics on a single endpoint. + * + *

This demonstrates: + * + *

    + *
  • Registering a Prometheus counter metric + *
  • Bridging OTel runtime metrics into the same PrometheusRegistry + *
  • Exposing everything via the built-in HTTPServer on /metrics + *
+ */ +public class Main { + + public static void main(String[] args) throws IOException, InterruptedException { + + PrometheusRegistry registry = new PrometheusRegistry(); + + // 1. Register a Prometheus counter metric + Counter counter = + Counter.builder() + .name("uptime_seconds_total") + .help("total number of seconds since this application was started") + .unit(Unit.SECONDS) + .register(registry); + + // 2. Create a PrometheusMetricReader and register it with the same registry. + // This bridges OTel metrics into the Prometheus registry. + PrometheusMetricReader reader = PrometheusMetricReader.create(); + registry.register(reader); + + // 3. Build the OTel SDK with the reader. + OpenTelemetrySdk openTelemetry = + OpenTelemetrySdk.builder() + .setMeterProvider(SdkMeterProvider.builder().registerMetricReader(reader).build()) + .build(); + + // 4. Start OTel JVM runtime metrics collection. + // - captureGcCause() adds a jvm.gc.cause attribute to jvm.gc.duration + // - emitExperimentalTelemetry() enables buffer pools, extended CPU, + // extended memory pools, and file descriptor metrics + RuntimeMetrics runtimeMetrics = + RuntimeMetrics.builder(openTelemetry).captureGcCause().emitExperimentalTelemetry().build(); + + // 5. Expose both Prometheus and OTel metrics on a single endpoint. + HTTPServer server = HTTPServer.builder().port(9400).registry(registry).buildAndStart(); + + // 6. Close RuntimeMetrics and server on shutdown to stop JMX metric collection. + Runtime.getRuntime() + .addShutdownHook( + new Thread( + () -> { + runtimeMetrics.close(); + server.close(); + })); + + System.out.println( + "HTTPServer listening on port http://localhost:" + server.getPort() + "/metrics"); + + while (true) { + Thread.sleep(1000); + counter.inc(); + } + } +} diff --git a/examples/example-prometheus-properties/pom.xml b/examples/example-prometheus-properties/pom.xml index b02b8fa03..bedd517f7 100644 --- a/examples/example-prometheus-properties/pom.xml +++ b/examples/example-prometheus-properties/pom.xml @@ -3,34 +3,44 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - io.prometheus - examples - 1.5.0-SNAPSHOT - - + io.prometheus example-prometheus-properties + 1.0-SNAPSHOT + + + 8 + UTF-8 + Example - prometheus.properties Example of runtime configuration with prometheus.properties + + + + io.prometheus + prometheus-metrics-bom + 1.5.0 + pom + import + + + + io.prometheus prometheus-metrics-core - ${project.version} io.prometheus prometheus-metrics-instrumentation-jvm - ${project.version} io.prometheus prometheus-metrics-exporter-httpserver - ${project.version} diff --git a/examples/example-prometheus-properties/src/main/resources/prometheus.properties b/examples/example-prometheus-properties/src/main/resources/prometheus.properties index a786fd370..be895f2fe 100644 --- a/examples/example-prometheus-properties/src/main/resources/prometheus.properties +++ b/examples/example-prometheus-properties/src/main/resources/prometheus.properties @@ -1,8 +1,8 @@ -io.prometheus.exporter.httpServer.port = 9401 -io.prometheus.exporter.includeCreatedTimestamps = true +io.prometheus.exporter.http_server.port = 9401 +io.prometheus.exporter.include_created_timestamps = true # Set a new default for all histograms -io.prometheus.metrics.histogramClassicUpperBounds = .2, .4, .8, .1 +io.prometheus.metrics.histogram_classic_upper_bounds = .2, .4, .8, .1 # Override the default for one specific histogram -io.prometheus.metrics.request_size_bytes.histogramClassicUpperBounds = 256, 512, 768, 1024 +io.prometheus.metrics.request_size_bytes.histogram_classic_upper_bounds = 256, 512, 768, 1024 diff --git a/examples/example-simpleclient-bridge/pom.xml b/examples/example-simpleclient-bridge/pom.xml index f6d2c4207..d0edb60cf 100644 --- a/examples/example-simpleclient-bridge/pom.xml +++ b/examples/example-simpleclient-bridge/pom.xml @@ -3,19 +3,32 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - io.prometheus - examples - 1.5.0-SNAPSHOT - - + io.prometheus example-simpleclient-bridge + 1.0-SNAPSHOT + + + 8 + UTF-8 + Example - Simpleclient Bridge Prometheus Metrics Example of the Simpleclient Backwards Compatibility module + + + + io.prometheus + prometheus-metrics-bom + 1.5.0 + pom + import + + + + io.prometheus @@ -25,12 +38,10 @@ io.prometheus prometheus-metrics-simpleclient-bridge - ${project.version} io.prometheus prometheus-metrics-exporter-httpserver - ${project.version} diff --git a/examples/pom.xml b/examples/pom.xml index f88b313a2..e033a3d1e 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT examples @@ -19,6 +19,7 @@ true + true @@ -29,7 +30,9 @@ example-exporter-opentelemetry example-simpleclient-bridge example-native-histogram + example-custom-buckets example-prometheus-properties + example-otel-jvm-runtime-metrics diff --git a/integration-tests/it-common/pom.xml b/integration-tests/it-common/pom.xml index 2faac1769..9ae86303c 100644 --- a/integration-tests/it-common/pom.xml +++ b/integration-tests/it-common/pom.xml @@ -6,7 +6,7 @@ io.prometheus integration-tests - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT it-common diff --git a/integration-tests/it-common/src/test/java/io/prometheus/client/it/common/ExporterTest.java b/integration-tests/it-common/src/test/java/io/prometheus/client/it/common/ExporterTest.java index 9de8b8be8..91a7ed712 100644 --- a/integration-tests/it-common/src/test/java/io/prometheus/client/it/common/ExporterTest.java +++ b/integration-tests/it-common/src/test/java/io/prometheus/client/it/common/ExporterTest.java @@ -4,7 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; -import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics; +import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -24,7 +24,7 @@ import org.testcontainers.containers.GenericContainer; public abstract class ExporterTest { - private final GenericContainer sampleAppContainer; + protected final GenericContainer sampleAppContainer; private final Volume sampleAppVolume; protected final String sampleApp; @@ -33,8 +33,12 @@ public ExporterTest(String sampleApp) throws IOException, URISyntaxException { this.sampleAppVolume = Volume.create("it-exporter") .copy("../../it-" + sampleApp + "/target/" + sampleApp + ".jar"); + String javaVersion = System.getenv("TEST_JAVA_VERSION"); + if (javaVersion == null || javaVersion.isEmpty()) { + javaVersion = "25"; + } this.sampleAppContainer = - new GenericContainer<>("eclipse-temurin:25") + new GenericContainer<>("eclipse-temurin:" + javaVersion) .withFileSystemBind(sampleAppVolume.getHostPath(), "/app", BindMode.READ_ONLY) .withWorkingDirectory("/app") .withLogConsumer(LogConsumer.withPrefix(sampleApp)) @@ -53,7 +57,7 @@ protected void start(String outcome) { } @AfterEach - public void tearDown() throws IOException { + void tearDown() throws IOException { sampleAppContainer.stop(); sampleAppVolume.remove(); } diff --git a/integration-tests/it-exporter/it-exporter-duplicate-metrics-sample/pom.xml b/integration-tests/it-exporter/it-exporter-duplicate-metrics-sample/pom.xml new file mode 100644 index 000000000..13364ec5d --- /dev/null +++ b/integration-tests/it-exporter/it-exporter-duplicate-metrics-sample/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + + io.prometheus + it-exporter + 1.6.0-SNAPSHOT + + + it-exporter-duplicate-metrics-sample + + Integration Tests - Duplicate Metrics Sample + + HTTPServer Sample demonstrating duplicate metric names with different label sets + + + + + io.prometheus + prometheus-metrics-exporter-httpserver + ${project.version} + + + io.prometheus + prometheus-metrics-core + ${project.version} + + + + + exporter-duplicate-metrics-sample + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + + + + io.prometheus.metrics.it.exporter.duplicatemetrics.DuplicateMetricsSample + + + + + + + + + + \ No newline at end of file diff --git a/integration-tests/it-exporter/it-exporter-duplicate-metrics-sample/src/main/java/io/prometheus/metrics/it/exporter/duplicatemetrics/DuplicateMetricsSample.java b/integration-tests/it-exporter/it-exporter-duplicate-metrics-sample/src/main/java/io/prometheus/metrics/it/exporter/duplicatemetrics/DuplicateMetricsSample.java new file mode 100644 index 000000000..c6005674a --- /dev/null +++ b/integration-tests/it-exporter/it-exporter-duplicate-metrics-sample/src/main/java/io/prometheus/metrics/it/exporter/duplicatemetrics/DuplicateMetricsSample.java @@ -0,0 +1,91 @@ +package io.prometheus.metrics.it.exporter.duplicatemetrics; + +import io.prometheus.metrics.core.metrics.Counter; +import io.prometheus.metrics.core.metrics.Gauge; +import io.prometheus.metrics.exporter.httpserver.HTTPServer; +import io.prometheus.metrics.model.snapshots.Unit; +import java.io.IOException; + +/** Integration test sample demonstrating metrics with duplicate names but different label sets. */ +public class DuplicateMetricsSample { + + public static void main(String[] args) throws IOException, InterruptedException { + if (args.length != 2) { + System.err.println("Usage: java -jar duplicate-metrics-sample.jar "); + System.err.println("Where outcome is \"success\" or \"error\"."); + System.exit(1); + } + + int port = parsePortOrExit(args[0]); + String outcome = args[1]; + run(port, outcome); + } + + private static void run(int port, String outcome) throws IOException, InterruptedException { + // Register multiple counters with the same Prometheus name "http_requests_total" + // but different label sets + Counter requestsSuccess = + Counter.builder() + .name("http_requests_total") + .help("Total HTTP requests by status") + .labelNames("status", "method") + .register(); + requestsSuccess.labelValues("success", "GET").inc(150); + requestsSuccess.labelValues("success", "POST").inc(45); + + Counter requestsError = + Counter.builder() + .name("http_requests_total") + .help("Total HTTP requests by status") + .labelNames("status", "endpoint") + .register(); + requestsError.labelValues("error", "/api").inc(5); + requestsError.labelValues("error", "/health").inc(2); + + // Register multiple gauges with the same Prometheus name "active_connections" + // but different label sets + Gauge connectionsByRegion = + Gauge.builder() + .name("active_connections") + .help("Active connections") + .labelNames("region", "protocol") + .register(); + connectionsByRegion.labelValues("us-east", "http").set(42); + connectionsByRegion.labelValues("us-west", "http").set(38); + connectionsByRegion.labelValues("eu-west", "https").set(55); + + Gauge connectionsByPool = + Gauge.builder() + .name("active_connections") + .help("Active connections") + .labelNames("pool", "type") + .register(); + connectionsByPool.labelValues("primary", "read").set(30); + connectionsByPool.labelValues("replica", "write").set(10); + + // Also add a regular metric without duplicates for reference + Counter uniqueMetric = + Counter.builder() + .name("unique_metric_total") + .help("A unique metric for reference") + .unit(Unit.BYTES) + .register(); + uniqueMetric.inc(1024); + + HTTPServer server = HTTPServer.builder().port(port).buildAndStart(); + + System.out.println( + "DuplicateMetricsSample listening on http://localhost:" + server.getPort() + "/metrics"); + Thread.currentThread().join(); // wait forever + } + + private static int parsePortOrExit(String port) { + try { + return Integer.parseInt(port); + } catch (NumberFormatException e) { + System.err.println("\"" + port + "\": Invalid port number."); + System.exit(1); + } + return 0; // this won't happen + } +} diff --git a/integration-tests/it-exporter/it-exporter-httpserver-sample/pom.xml b/integration-tests/it-exporter/it-exporter-httpserver-sample/pom.xml index f52c8434e..3dfa05f07 100644 --- a/integration-tests/it-exporter/it-exporter-httpserver-sample/pom.xml +++ b/integration-tests/it-exporter/it-exporter-httpserver-sample/pom.xml @@ -6,7 +6,7 @@ io.prometheus it-exporter - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT it-exporter-httpserver-sample diff --git a/integration-tests/it-exporter/it-exporter-no-protobuf/pom.xml b/integration-tests/it-exporter/it-exporter-no-protobuf/pom.xml index f75c398a5..6bfd7c5cb 100644 --- a/integration-tests/it-exporter/it-exporter-no-protobuf/pom.xml +++ b/integration-tests/it-exporter/it-exporter-no-protobuf/pom.xml @@ -6,7 +6,7 @@ io.prometheus it-exporter - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT it-exporter-no-protobuf diff --git a/integration-tests/it-exporter/it-exporter-servlet-jetty-sample/pom.xml b/integration-tests/it-exporter/it-exporter-servlet-jetty-sample/pom.xml index 4d679b572..ed5285769 100644 --- a/integration-tests/it-exporter/it-exporter-servlet-jetty-sample/pom.xml +++ b/integration-tests/it-exporter/it-exporter-servlet-jetty-sample/pom.xml @@ -6,7 +6,7 @@ io.prometheus it-exporter - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT it-exporter-servlet-jetty-sample @@ -16,7 +16,7 @@ Jetty Sample for the Exporter Integration Test - 12.1.5 + 12.1.6 25 diff --git a/integration-tests/it-exporter/it-exporter-servlet-tomcat-sample/pom.xml b/integration-tests/it-exporter/it-exporter-servlet-tomcat-sample/pom.xml index 2d5c34202..be9c7704d 100644 --- a/integration-tests/it-exporter/it-exporter-servlet-tomcat-sample/pom.xml +++ b/integration-tests/it-exporter/it-exporter-servlet-tomcat-sample/pom.xml @@ -6,7 +6,7 @@ io.prometheus it-exporter - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT it-exporter-servlet-tomcat-sample @@ -34,7 +34,7 @@ org.apache.tomcat.embed tomcat-embed-core - 11.0.15 + 11.0.18 diff --git a/integration-tests/it-exporter/it-exporter-test/pom.xml b/integration-tests/it-exporter/it-exporter-test/pom.xml index 1929a9c6d..027631fbd 100644 --- a/integration-tests/it-exporter/it-exporter-test/pom.xml +++ b/integration-tests/it-exporter/it-exporter-test/pom.xml @@ -6,7 +6,7 @@ io.prometheus it-exporter - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT it-exporter-test diff --git a/integration-tests/it-exporter/it-exporter-test/src/test/java/io/prometheus/metrics/it/exporter/test/DuplicateMetricsIT.java b/integration-tests/it-exporter/it-exporter-test/src/test/java/io/prometheus/metrics/it/exporter/test/DuplicateMetricsIT.java new file mode 100644 index 000000000..7530070ac --- /dev/null +++ b/integration-tests/it-exporter/it-exporter-test/src/test/java/io/prometheus/metrics/it/exporter/test/DuplicateMetricsIT.java @@ -0,0 +1,181 @@ +package io.prometheus.metrics.it.exporter.test; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.prometheus.client.it.common.ExporterTest; +import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.List; +import org.junit.jupiter.api.Test; + +class DuplicateMetricsIT extends ExporterTest { + + public DuplicateMetricsIT() throws IOException, URISyntaxException { + super("exporter-duplicate-metrics-sample"); + } + + @Test + void testDuplicateMetricsInPrometheusTextFormat() throws IOException { + start(); + Response response = scrape("GET", ""); + assertThat(response.status).isEqualTo(200); + assertContentType( + "text/plain; version=0.0.4; charset=utf-8", response.getHeader("Content-Type")); + + String expected = + """ + # HELP active_connections Active connections + # TYPE active_connections gauge + active_connections{pool="primary",type="read"} 30.0 + active_connections{pool="replica",type="write"} 10.0 + active_connections{protocol="http",region="us-east"} 42.0 + active_connections{protocol="http",region="us-west"} 38.0 + active_connections{protocol="https",region="eu-west"} 55.0 + # HELP http_requests_total Total HTTP requests by status + # TYPE http_requests_total counter + http_requests_total{endpoint="/api",status="error"} 5.0 + http_requests_total{endpoint="/health",status="error"} 2.0 + http_requests_total{method="GET",status="success"} 150.0 + http_requests_total{method="POST",status="success"} 45.0 + # HELP unique_metric_bytes_total A unique metric for reference + # TYPE unique_metric_bytes_total counter + unique_metric_bytes_total 1024.0 + """; + + assertThat(response.stringBody()).isEqualTo(expected); + } + + @Test + void testDuplicateMetricsInOpenMetricsTextFormat() throws IOException { + start(); + Response response = + scrape("GET", "", "Accept", "application/openmetrics-text; version=1.0.0; charset=utf-8"); + assertThat(response.status).isEqualTo(200); + assertContentType( + "application/openmetrics-text; version=1.0.0; charset=utf-8", + response.getHeader("Content-Type")); + + // OpenMetrics format should have UNIT for unique_metric_bytes (base name without _total) + String expected = + """ + # TYPE active_connections gauge + # HELP active_connections Active connections + active_connections{pool="primary",type="read"} 30.0 + active_connections{pool="replica",type="write"} 10.0 + active_connections{protocol="http",region="us-east"} 42.0 + active_connections{protocol="http",region="us-west"} 38.0 + active_connections{protocol="https",region="eu-west"} 55.0 + # TYPE http_requests counter + # HELP http_requests Total HTTP requests by status + http_requests_total{endpoint="/api",status="error"} 5.0 + http_requests_total{endpoint="/health",status="error"} 2.0 + http_requests_total{method="GET",status="success"} 150.0 + http_requests_total{method="POST",status="success"} 45.0 + # TYPE unique_metric_bytes counter + # UNIT unique_metric_bytes bytes + # HELP unique_metric_bytes A unique metric for reference + unique_metric_bytes_total 1024.0 + # EOF + """; + + assertThat(response.stringBody()).isEqualTo(expected); + } + + @Test + void testDuplicateMetricsInPrometheusProtobufFormat() throws IOException { + start(); + Response response = + scrape( + "GET", + "", + "Accept", + "application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily;" + + " encoding=delimited"); + assertThat(response.status).isEqualTo(200); + assertContentType( + "application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily;" + + " encoding=delimited", + response.getHeader("Content-Type")); + + List metrics = response.protoBody(); + + assertThat(metrics).hasSize(3); + + // Metrics are sorted by name + assertThat(metrics.get(0).getName()).isEqualTo("active_connections"); + assertThat(metrics.get(1).getName()).isEqualTo("http_requests_total"); + assertThat(metrics.get(2).getName()).isEqualTo("unique_metric_bytes_total"); + + // Verify active_connections has all 5 data points merged + Metrics.MetricFamily activeConnections = metrics.get(0); + assertThat(activeConnections.getType()).isEqualTo(Metrics.MetricType.GAUGE); + assertThat(activeConnections.getHelp()).isEqualTo("Active connections"); + assertThat(activeConnections.getMetricList()).hasSize(5); + + // Verify http_requests_total has all 4 data points merged + Metrics.MetricFamily httpRequests = metrics.get(1); + assertThat(httpRequests.getType()).isEqualTo(Metrics.MetricType.COUNTER); + assertThat(httpRequests.getHelp()).isEqualTo("Total HTTP requests by status"); + assertThat(httpRequests.getMetricList()).hasSize(4); + + // Verify each data point has the expected labels + boolean foundSuccessGet = false; + boolean foundSuccessPost = false; + boolean foundErrorApi = false; + boolean foundErrorHealth = false; + + for (Metrics.Metric metric : httpRequests.getMetricList()) { + List labels = metric.getLabelList(); + if (hasLabel(labels, "status", "success") && hasLabel(labels, "method", "GET")) { + assertThat(metric.getCounter().getValue()).isEqualTo(150.0); + foundSuccessGet = true; + } else if (hasLabel(labels, "status", "success") && hasLabel(labels, "method", "POST")) { + assertThat(metric.getCounter().getValue()).isEqualTo(45.0); + foundSuccessPost = true; + } else if (hasLabel(labels, "status", "error") && hasLabel(labels, "endpoint", "/api")) { + assertThat(metric.getCounter().getValue()).isEqualTo(5.0); + foundErrorApi = true; + } else if (hasLabel(labels, "status", "error") && hasLabel(labels, "endpoint", "/health")) { + assertThat(metric.getCounter().getValue()).isEqualTo(2.0); + foundErrorHealth = true; + } + } + + assertThat(foundSuccessGet).isTrue(); + assertThat(foundSuccessPost).isTrue(); + assertThat(foundErrorApi).isTrue(); + assertThat(foundErrorHealth).isTrue(); + + Metrics.MetricFamily uniqueMetric = metrics.get(2); + assertThat(uniqueMetric.getType()).isEqualTo(Metrics.MetricType.COUNTER); + assertThat(uniqueMetric.getMetricList()).hasSize(1); + assertThat(uniqueMetric.getMetric(0).getCounter().getValue()).isEqualTo(1024.0); + } + + @Test + void testDuplicateMetricsWithNameFilter() throws IOException { + start(); + // Only scrape http_requests_total + Response response = scrape("GET", nameParam()); + assertThat(response.status).isEqualTo(200); + + String body = response.stringBody(); + + assertThat(body) + .contains("http_requests_total{method=\"GET\",status=\"success\"} 150.0") + .contains("http_requests_total{endpoint=\"/api\",status=\"error\"} 5.0"); + + // Should NOT contain active_connections or unique_metric_total + assertThat(body).doesNotContain("active_connections").doesNotContain("unique_metric_total"); + } + + private boolean hasLabel(List labels, String name, String value) { + return labels.stream() + .anyMatch(label -> label.getName().equals(name) && label.getValue().equals(value)); + } + + private String nameParam() { + return "name[]=" + "http_requests_total"; + } +} diff --git a/integration-tests/it-exporter/it-exporter-test/src/test/java/io/prometheus/metrics/it/exporter/test/ExporterIT.java b/integration-tests/it-exporter/it-exporter-test/src/test/java/io/prometheus/metrics/it/exporter/test/ExporterIT.java index e7b4550ed..e9bcc2ee7 100644 --- a/integration-tests/it-exporter/it-exporter-test/src/test/java/io/prometheus/metrics/it/exporter/test/ExporterIT.java +++ b/integration-tests/it-exporter/it-exporter-test/src/test/java/io/prometheus/metrics/it/exporter/test/ExporterIT.java @@ -5,7 +5,7 @@ import com.google.common.io.Resources; import io.prometheus.client.it.common.ExporterTest; -import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics; +import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics; import java.io.IOException; import java.net.URISyntaxException; import java.net.URLEncoder; @@ -22,7 +22,7 @@ public ExporterIT(String sampleApp) throws IOException, URISyntaxException { } @Test - public void testOpenMetricsTextFormat() throws IOException { + void testOpenMetricsTextFormat() throws IOException { start(); Response response = scrape("GET", "", "Accept", "application/openmetrics-text; version=1.0.0; charset=utf-8"); @@ -44,7 +44,7 @@ public void testOpenMetricsTextFormat() throws IOException { } @Test - public void testPrometheusTextFormat() throws IOException { + void testPrometheusTextFormat() throws IOException { start(); Response response = scrape("GET", ""); assertThat(response.status).isEqualTo(200); @@ -64,7 +64,7 @@ public void testPrometheusTextFormat() throws IOException { } @Test - public void testPrometheusProtobufFormat() throws IOException { + void testPrometheusProtobufFormat() throws IOException { start(); Response response = scrape( @@ -121,7 +121,7 @@ public void testPrometheusProtobufDebugFormat(String format, String expected) th } @Test - public void testCompression() throws IOException { + void testCompression() throws IOException { start(); Response response = scrape( @@ -149,7 +149,7 @@ public void testCompression() throws IOException { } @Test - public void testErrorHandling() throws IOException { + void testErrorHandling() throws IOException { start("error"); Response response = scrape("GET", ""); assertThat(response.status).isEqualTo(500); @@ -157,7 +157,7 @@ public void testErrorHandling() throws IOException { } @Test - public void testHeadRequest() throws IOException { + void testHeadRequest() throws IOException { start(); Response fullResponse = scrape("GET", ""); int size = fullResponse.body.length; @@ -169,7 +169,7 @@ public void testHeadRequest() throws IOException { } @Test - public void testDebug() throws IOException { + void testDebug() throws IOException { start(); Response response = scrape("GET", "debug=openmetrics"); assertThat(response.status).isEqualTo(200); @@ -180,7 +180,7 @@ public void testDebug() throws IOException { } @Test - public void testNameFilter() throws IOException { + void testNameFilter() throws IOException { start(); Response response = scrape( @@ -199,7 +199,7 @@ public void testNameFilter() throws IOException { } @Test - public void testEmptyResponseOpenMetrics() throws IOException { + void testEmptyResponseOpenMetrics() throws IOException { start(); Response response = scrape( @@ -217,7 +217,7 @@ public void testEmptyResponseOpenMetrics() throws IOException { } @Test - public void testEmptyResponseText() throws IOException { + void testEmptyResponseText() throws IOException { start(); Response response = scrape("GET", nameParam("none_existing")); assertThat(response.status).isEqualTo(200); @@ -231,7 +231,7 @@ public void testEmptyResponseText() throws IOException { } @Test - public void testEmptyResponseProtobuf() throws IOException { + void testEmptyResponseProtobuf() throws IOException { start(); Response response = scrape( @@ -249,7 +249,7 @@ public void testEmptyResponseProtobuf() throws IOException { } @Test - public void testEmptyResponseGzipOpenMetrics() throws IOException { + void testEmptyResponseGzipOpenMetrics() throws IOException { start(); Response response = scrape( @@ -265,7 +265,7 @@ public void testEmptyResponseGzipOpenMetrics() throws IOException { } @Test - public void testEmptyResponseGzipText() throws IOException { + void testEmptyResponseGzipText() throws IOException { start(); Response response = scrape("GET", nameParam("none_existing"), "Accept-Encoding", "gzip"); assertThat(response.status).isEqualTo(200); @@ -278,7 +278,7 @@ private String nameParam(String name) { } @Test - public void testDebugUnknown() throws IOException { + void testDebugUnknown() throws IOException { start(); Response response = scrape("GET", "debug=unknown"); assertThat(response.status).isEqualTo(500); diff --git a/integration-tests/it-exporter/it-no-protobuf-test/pom.xml b/integration-tests/it-exporter/it-no-protobuf-test/pom.xml index 6321799db..1a17b83dc 100644 --- a/integration-tests/it-exporter/it-no-protobuf-test/pom.xml +++ b/integration-tests/it-exporter/it-no-protobuf-test/pom.xml @@ -6,7 +6,7 @@ io.prometheus it-exporter - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT it-no-protobuf-test diff --git a/integration-tests/it-exporter/it-no-protobuf-test/src/test/java/io/prometheus/metrics/it/noprotobuf/NoProtobufIT.java b/integration-tests/it-exporter/it-no-protobuf-test/src/test/java/io/prometheus/metrics/it/noprotobuf/NoProtobufIT.java index cd534dcb9..9b041795e 100644 --- a/integration-tests/it-exporter/it-no-protobuf-test/src/test/java/io/prometheus/metrics/it/noprotobuf/NoProtobufIT.java +++ b/integration-tests/it-exporter/it-no-protobuf-test/src/test/java/io/prometheus/metrics/it/noprotobuf/NoProtobufIT.java @@ -14,7 +14,7 @@ public NoProtobufIT() throws IOException, URISyntaxException { } @Test - public void testPrometheusProtobufDebugFormat() throws IOException { + void testPrometheusProtobufDebugFormat() throws IOException { start(); assertThat(scrape("GET", "debug=text").status).isEqualTo(200); // protobuf is not supported diff --git a/integration-tests/it-exporter/pom.xml b/integration-tests/it-exporter/pom.xml index a442b9086..08386d8b0 100644 --- a/integration-tests/it-exporter/pom.xml +++ b/integration-tests/it-exporter/pom.xml @@ -6,7 +6,7 @@ io.prometheus integration-tests - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT it-exporter @@ -21,6 +21,7 @@ it-exporter-servlet-tomcat-sample it-exporter-servlet-jetty-sample it-exporter-httpserver-sample + it-exporter-duplicate-metrics-sample it-exporter-no-protobuf it-exporter-test it-no-protobuf-test diff --git a/integration-tests/it-pushgateway/pom.xml b/integration-tests/it-pushgateway/pom.xml index cf3e68169..a70ea5458 100644 --- a/integration-tests/it-pushgateway/pom.xml +++ b/integration-tests/it-pushgateway/pom.xml @@ -6,7 +6,7 @@ io.prometheus integration-tests - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT it-pushgateway diff --git a/integration-tests/it-pushgateway/src/test/java/io/prometheus/metrics/it/pushgateway/PushGatewayIT.java b/integration-tests/it-pushgateway/src/test/java/io/prometheus/metrics/it/pushgateway/PushGatewayIT.java index 29a8fad72..3d31129f1 100644 --- a/integration-tests/it-pushgateway/src/test/java/io/prometheus/metrics/it/pushgateway/PushGatewayIT.java +++ b/integration-tests/it-pushgateway/src/test/java/io/prometheus/metrics/it/pushgateway/PushGatewayIT.java @@ -22,7 +22,7 @@ import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.MountableFile; -public class PushGatewayIT { +class PushGatewayIT { private GenericContainer sampleAppContainer; private GenericContainer pushGatewayContainer; @@ -30,9 +30,13 @@ public class PushGatewayIT { private Volume sampleAppVolume; @BeforeEach - public void setUp() throws IOException, URISyntaxException { + void setUp() throws IOException, URISyntaxException { Network network = Network.newNetwork(); sampleAppVolume = Volume.create("it-pushgateway").copy("pushgateway-test-app.jar"); + String javaVersion = System.getenv("TEST_JAVA_VERSION"); + if (javaVersion == null || javaVersion.isEmpty()) { + javaVersion = "25"; + } pushGatewayContainer = new GenericContainer<>("prom/pushgateway:v1.8.0") .withExposedPorts(9091) @@ -41,7 +45,7 @@ public void setUp() throws IOException, URISyntaxException { .withLogConsumer(LogConsumer.withPrefix("pushgateway")) .waitingFor(Wait.forListeningPort()); sampleAppContainer = - new GenericContainer<>("eclipse-temurin:25") + new GenericContainer<>("eclipse-temurin:" + javaVersion) .withFileSystemBind(sampleAppVolume.getHostPath(), "/app", BindMode.READ_ONLY) .withNetwork(network) .withWorkingDirectory("/app") @@ -56,7 +60,7 @@ public void setUp() throws IOException, URISyntaxException { } @AfterEach - public void tearDown() throws IOException { + void tearDown() throws IOException { prometheusContainer.stop(); pushGatewayContainer.stop(); sampleAppContainer.stop(); @@ -66,7 +70,7 @@ public void tearDown() throws IOException { final OkHttpClient client = new OkHttpClient(); @Test - public void testSimple() throws IOException, InterruptedException { + void testSimple() throws IOException, InterruptedException { pushGatewayContainer.start(); sampleAppContainer .withCommand( @@ -86,7 +90,7 @@ public void testSimple() throws IOException, InterruptedException { } @Test - public void testTextFormat() throws IOException, InterruptedException { + void testTextFormat() throws IOException, InterruptedException { pushGatewayContainer.start(); sampleAppContainer .withCommand( @@ -106,7 +110,7 @@ public void testTextFormat() throws IOException, InterruptedException { } @Test - public void testBasicAuth() throws IOException, InterruptedException { + void testBasicAuth() throws IOException, InterruptedException { pushGatewayContainer .withCopyFileToContainer( MountableFile.forClasspathResource("/pushgateway-basicauth.yaml"), @@ -131,7 +135,7 @@ public void testBasicAuth() throws IOException, InterruptedException { } @Test - public void testSsl() throws InterruptedException, IOException { + void testSsl() throws InterruptedException, IOException { pushGatewayContainer .withCopyFileToContainer( MountableFile.forClasspathResource("/pushgateway-ssl.yaml"), @@ -156,7 +160,7 @@ public void testSsl() throws InterruptedException, IOException { } @Test - public void testProtobuf() throws IOException, InterruptedException { + void testProtobuf() throws IOException, InterruptedException { pushGatewayContainer.start(); sampleAppContainer .withCommand( diff --git a/integration-tests/it-spring-boot-smoke-test/pom.xml b/integration-tests/it-spring-boot-smoke-test/pom.xml index 35663055f..ee653fbb4 100644 --- a/integration-tests/it-spring-boot-smoke-test/pom.xml +++ b/integration-tests/it-spring-boot-smoke-test/pom.xml @@ -8,13 +8,13 @@ org.springframework.boot spring-boot-starter-parent - 4.0.1 + 4.0.3 io.prometheus it-spring-boot-smoke-test - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT Integration Test - Spring Smoke Tests @@ -22,7 +22,7 @@ 25 - 6.0.2 + 6.0.3 @@ -89,95 +89,108 @@ - - org.graalvm.buildtools - native-maven-plugin - - - - - --initialize-at-build-time=org.junit.jupiter.api.DisplayNameGenerator$IndicativeSentences - - - --initialize-at-build-time=org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$ClassInfo - - - --initialize-at-build-time=org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$LifecycleMethods - - - --initialize-at-build-time=org.junit.jupiter.engine.descriptor.ClassTemplateInvocationTestDescriptor - - - --initialize-at-build-time=org.junit.jupiter.engine.descriptor.ClassTemplateTestDescriptor - - - --initialize-at-build-time=org.junit.jupiter.engine.descriptor.DynamicDescendantFilter$Mode - - - --initialize-at-build-time=org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector$1 - - - --initialize-at-build-time=org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$MethodInfo - - - --initialize-at-build-time=org.junit.jupiter.engine.discovery.ClassSelectorResolver$DummyClassTemplateInvocationContext - - - --initialize-at-build-time=org.junit.platform.engine.support.store.NamespacedHierarchicalStore$EvaluatedValue - - --initialize-at-build-time=org.junit.platform.launcher.core.DiscoveryIssueNotifier - - - --initialize-at-build-time=org.junit.platform.launcher.core.HierarchicalOutputDirectoryProvider - - - --initialize-at-build-time=org.junit.platform.launcher.core.LauncherDiscoveryResult$EngineResultInfo - - - --initialize-at-build-time=org.junit.platform.suite.engine.SuiteTestDescriptor$LifecycleMethods - - - --initialize-at-build-time=org.junit.platform.commons.logging.LoggerFactory$DelegatingLogger - - - --initialize-at-build-time=org.junit.jupiter.engine.execution.ConditionEvaluator - - - --initialize-at-build-time=org.junit.jupiter.engine.execution.InterceptingExecutableInvoker - - - --initialize-at-build-time=org.junit.jupiter.api.extension.ConditionEvaluationResult - - - --initialize-at-build-time=org.junit.jupiter.engine.execution.InvocationInterceptorChain - - - - - org.springframework.boot spring-boot-maven-plugin - - com.diffplug.spotless - spotless-maven-plugin - 3.1.0 - - - - - - - - verify - - check - - - - + + + java17-plus + + [17,) + + + + + org.graalvm.buildtools + native-maven-plugin + + + + + --initialize-at-build-time=org.junit.jupiter.api.DisplayNameGenerator$IndicativeSentences + + + --initialize-at-build-time=org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$ClassInfo + + + --initialize-at-build-time=org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$LifecycleMethods + + + --initialize-at-build-time=org.junit.jupiter.engine.descriptor.ClassTemplateInvocationTestDescriptor + + + --initialize-at-build-time=org.junit.jupiter.engine.descriptor.ClassTemplateTestDescriptor + + + --initialize-at-build-time=org.junit.jupiter.engine.descriptor.DynamicDescendantFilter$Mode + + + --initialize-at-build-time=org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector$1 + + + --initialize-at-build-time=org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$MethodInfo + + + --initialize-at-build-time=org.junit.jupiter.engine.discovery.ClassSelectorResolver$DummyClassTemplateInvocationContext + + + --initialize-at-build-time=org.junit.platform.engine.support.store.NamespacedHierarchicalStore$EvaluatedValue + + --initialize-at-build-time=org.junit.platform.launcher.core.DiscoveryIssueNotifier + + + --initialize-at-build-time=org.junit.platform.launcher.core.HierarchicalOutputDirectoryProvider + + + --initialize-at-build-time=org.junit.platform.launcher.core.LauncherDiscoveryResult$EngineResultInfo + + + --initialize-at-build-time=org.junit.platform.suite.engine.SuiteTestDescriptor$LifecycleMethods + + + --initialize-at-build-time=org.junit.platform.commons.logging.LoggerFactory$DelegatingLogger + + + --initialize-at-build-time=org.junit.jupiter.engine.execution.ConditionEvaluator + + + --initialize-at-build-time=org.junit.jupiter.engine.execution.InterceptingExecutableInvoker + + + --initialize-at-build-time=org.junit.jupiter.api.extension.ConditionEvaluationResult + + + --initialize-at-build-time=org.junit.jupiter.engine.execution.InvocationInterceptorChain + + + + + + + com.diffplug.spotless + spotless-maven-plugin + 3.2.1 + + + + + + + + verify + + check + + + + + + + + + diff --git a/integration-tests/it-spring-boot-smoke-test/src/test/java/io/prometheus/metrics/it/springboot/ApplicationTest.java b/integration-tests/it-spring-boot-smoke-test/src/test/java/io/prometheus/metrics/it/springboot/ApplicationTest.java index 864cd68dc..fed9fba6d 100644 --- a/integration-tests/it-spring-boot-smoke-test/src/test/java/io/prometheus/metrics/it/springboot/ApplicationTest.java +++ b/integration-tests/it-spring-boot-smoke-test/src/test/java/io/prometheus/metrics/it/springboot/ApplicationTest.java @@ -3,7 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import io.prometheus.client.it.common.ExporterTest; -import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics; +import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics; import java.io.IOException; import java.net.URI; import java.util.List; @@ -14,7 +14,7 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) class ApplicationTest { @Test - public void testPrometheusProtobufFormat() throws IOException { + void testPrometheusProtobufFormat() throws IOException { ExporterTest.Response response = ExporterTest.scrape( "GET", diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index b932c5799..f0ab29299 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT integration-tests @@ -19,6 +19,7 @@ true + true diff --git a/lychee.toml b/lychee.toml deleted file mode 100644 index d67acf825..000000000 --- a/lychee.toml +++ /dev/null @@ -1,15 +0,0 @@ -max_retries = 6 -exclude_loopback = true -cache = true - -base_url = "https://prometheus.github.io" -exclude_path = ["docs/themes"] -exclude = [ - '^https://github\.com/prometheus/client_java/settings', - '#', - 'CONTRIBUTING.md', - 'LICENSE', - 'MAINTAINERS.md' -] - - diff --git a/mise.toml b/mise.toml index f9819b481..ebf962bc4 100644 --- a/mise.toml +++ b/mise.toml @@ -1,9 +1,16 @@ [tools] -"go:github.com/gohugoio/hugo" = "v0.154.3" -"go:github.com/grafana/oats" = "0.6.0" -java = "temurin-25.0.1+8.0.LTS" -lychee = "0.22.0" -protoc = "33.2" +"go:github.com/gohugoio/hugo" = "v0.156.0" +"go:github.com/grafana/oats" = "0.6.1" +java = "temurin-25.0.2+10.0.LTS" +lychee = "0.23.0" +node = "24.13.1" +"npm:renovate" = "43.8.5" +protoc = "33.5" + +[env] +RENOVATE_TRACKED_DEPS_EXCLUDE="github-actions,github-runners" +# renovate: datasource=docker depName=ghcr.io/super-linter/super-linter +SUPER_LINTER_VERSION="slim-v8.5.0@sha256:857dcc3f0bf5dd065fdeed1ace63394bb2004238a5ef02910ea23d9bcd8fd2b8" [tasks.ci] description = "CI Build" @@ -43,17 +50,26 @@ run = "./mvnw verify" description = "build all modules without tests" run = "./mvnw install -DskipTests -Dcoverage.skip=true" +# Shared lint tasks from flint (https://github.com/grafana/flint) +[tasks."lint:super-linter"] +description = "Run Super-Linter on the repository" +file = "https://raw.githubusercontent.com/grafana/flint/5bb3726cfe3305072457c0c4fa85dce5ca154680/tasks/lint/super-linter.sh" # v0.6.0 + [tasks."lint:links"] -description = "Lint markdown links" -run = "lychee --include-fragments ." +description = "Lint links" +file = "https://raw.githubusercontent.com/grafana/flint/5bb3726cfe3305072457c0c4fa85dce5ca154680/tasks/lint/links.sh" # v0.6.0 -[tasks."lint:rest"] -description = "All lints not covered by super linter" -depends = ["lint:links", "lint:bom"] +[tasks."lint:renovate-deps"] +description = "Verify renovate-tracked-deps.json is up to date" +file = "https://raw.githubusercontent.com/grafana/flint/5bb3726cfe3305072457c0c4fa85dce5ca154680/tasks/lint/renovate-deps.py" # v0.6.0 -[tasks."lint:all"] -description = "All lints" -depends = ["lint:rest", "lint:super-linter"] +[tasks."lint"] +description = "Run all lints" +depends = ["lint:super-linter", "lint:links", "lint:bom", "lint:renovate-deps"] + +[tasks.fix] +description = "Auto-fix lint issues" +run = "AUTOFIX=true mise run lint" [tasks.acceptance-test] description = "Run OATs acceptance tests" @@ -83,3 +99,24 @@ run = [ "hugo --gc --minify --baseURL ${BASE_URL}/", "echo 'ls ./public/api' && ls ./public/api" ] + +[tasks."benchmark:quick"] +description = "Run benchmarks with reduced iterations (quick smoke test, ~10 min)" +run = "python3 ./.mise/tasks/update_benchmarks.py --jmh-args '-f 1 -wi 1 -i 3'" + +[tasks."benchmark:ci"] +description = "Run benchmarks with CI configuration (3 forks, 3 warmup, 5 measurement iterations (~60 min total)" +run = "python3 ./.mise/tasks/update_benchmarks.py --jmh-args '-f 3 -wi 3 -i 5'" + +[tasks."benchmark:ci-json"] +description = "Run benchmarks with CI configuration and JSON output (for workflow/testing)" +run = """ +./mvnw -pl benchmarks -am -DskipTests clean package +JMH_ARGS="${JMH_ARGS:--f 3 -wi 3 -i 5}" +echo "Running benchmarks with args: $JMH_ARGS" +java -jar ./benchmarks/target/benchmarks.jar -rf json -rff benchmark-results.json $JMH_ARGS +""" + +[tasks."benchmark:generate-summary"] +description = "Generate summary from existing benchmark-results.json" +run = "python3 ./.mise/tasks/generate_benchmark_summary.py" diff --git a/pom.xml b/pom.xml index e9a06374a..c166f0648 100644 --- a/pom.xml +++ b/pom.xml @@ -8,11 +8,10 @@ io.prometheus client_java_parent - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-parent/pom.xml - 1.5.0-SNAPSHOT client_java Prometheus Metrics Library @@ -23,11 +22,12 @@ UTF-8 --module-name-need-to-be-overridden-- - 4.33.2 + 4.33.5 33.5.0-jre - 6.0.2 - 2.16.0-alpha + 6.0.3 + 2.25.0-alpha 8 + 25 0.70 false false @@ -60,6 +60,7 @@ prometheus-metrics-instrumentation-dropwizard prometheus-metrics-instrumentation-guava prometheus-metrics-simpleclient-bridge + prometheus-metrics-otel-support @@ -69,6 +70,67 @@ 3.0.2 provided + + + org.junit.jupiter + junit-jupiter + ${junit-jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-params + ${junit-jupiter.version} + test + + + org.mockito + mockito-core + 5.21.0 + test + + + org.assertj + assertj-core + 3.27.7 + test + + + com.google.guava + guava + ${guava.version} + test + + + org.slf4j + slf4j-simple + 2.0.17 + test + + + org.junit-pioneer + junit-pioneer + 2.3.0 + test + + + org.awaitility + awaitility + 4.3.0 + test + + + org.wiremock + wiremock + 3.13.2 + test + + + org.hamcrest + hamcrest-core + + + @@ -86,7 +148,7 @@ maven-compiler-plugin - 3.14.1 + 3.15.0 maven-surefire-plugin @@ -119,7 +181,7 @@ maven-dependency-plugin - 3.9.0 + 3.10.0 maven-javadoc-plugin @@ -173,6 +235,8 @@ **/generated/** **/*BlockingRejectedExecutionHandler* + **/*AllocationCountingNotificationListener* + **/*MapperConfig*
@@ -203,6 +267,11 @@ COVEREDRATIO ${jacoco.line-coverage} + + BRANCH + COVEREDRATIO + 0.50 + @@ -252,62 +321,62 @@ ${java.version} ${java.version} ${java.version} - 25 - 25 - 25 + ${test.java.version} + ${test.java.version} + ${test.java.version} true -Xlint:all,-serial,-processing,-options ${warnings} --should-stop=ifError=FLOW -XDcompilePolicy=simple - - -Xplugin:ErrorProne - -Xep:AlmostJavadoc:OFF - -Xep:MissingSummary:OFF - -Xep:LongDoubleConversion:OFF - -Xep:StringSplitter:OFF - -XepExcludedPaths:(.*/generated/.*|.*/src/test/java/.*|.*/examples/.*|.*/integration-tests/.*) - -XepOpt:NullAway:AnnotatedPackages=io.prometheus.metrics - - - - com.google.errorprone - error_prone_core - 2.45.0 - - - com.uber.nullaway - nullaway - 0.12.15 - - - org.codehaus.mojo versions-maven-plugin - 2.20.1 + 2.21.0 file://${project.basedir}/version-rules.xml + + maven-javadoc-plugin + + ${javadoc.skip} + + + + + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + + + io.opentelemetry.instrumentation + opentelemetry-instrumentation-bom-alpha + ${otel.instrumentation.version} + pom + import + + + io.opentelemetry + opentelemetry-proto + 1.7.1-alpha + test + + + + - - - maven-project-info-reports-plugin - 3.9.0 - maven-javadoc-plugin @@ -331,102 +400,15 @@ - default + examples-and-integration-tests - true + [25,) examples benchmarks integration-tests - - - - org.junit - junit-bom - ${junit-jupiter.version} - pom - import - - - io.opentelemetry.instrumentation - opentelemetry-instrumentation-bom-alpha - ${otel.instrumentation.version} - pom - import - - - io.opentelemetry - opentelemetry-proto - 1.7.1-alpha - test - - - - - - - org.junit.jupiter - junit-jupiter - ${junit-jupiter.version} - test - - - org.junit.jupiter - junit-jupiter-params - ${junit-jupiter.version} - test - - - org.mockito - mockito-core - 5.21.0 - test - - - org.assertj - assertj-core - 3.27.6 - test - - - com.google.guava - guava - ${guava.version} - test - - - org.slf4j - slf4j-simple - 2.0.17 - test - - - org.junit-pioneer - junit-pioneer - 2.3.0 - test - - - org.awaitility - awaitility - 4.3.0 - test - - - org.wiremock - wiremock - 3.13.2 - test - - - org.hamcrest - hamcrest-core - - - - javadoc @@ -435,6 +417,7 @@ maven-javadoc-plugin + ${javadoc.skip} UTF-8 UTF-8 true @@ -448,6 +431,45 @@ + + errorprone + + [21,) + + + + + maven-compiler-plugin + + + -XDaddTypeAnnotationsToSymbol=true + + -Xplugin:ErrorProne + -Xep:AlmostJavadoc:OFF + -Xep:MissingSummary:OFF + -Xep:LongDoubleConversion:OFF + -Xep:StringSplitter:OFF + -XepExcludedPaths:(.*/generated/.*|.*/src/test/java/.*|.*/examples/.*|.*/integration-tests/.*) + -XepOpt:NullAway:AnnotatedPackages=io.prometheus.metrics + + + + + com.google.errorprone + error_prone_core + 2.47.0 + + + com.uber.nullaway + nullaway + 0.13.1 + + + + + + + release diff --git a/prometheus-metrics-bom/pom.xml b/prometheus-metrics-bom/pom.xml index a13398228..167ea522e 100644 --- a/prometheus-metrics-bom/pom.xml +++ b/prometheus-metrics-bom/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java_parent - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT ../prometheus-metrics-parent/pom.xml @@ -119,6 +119,12 @@ prometheus-metrics-model ${project.version} + + io.prometheus + prometheus-metrics-otel-support + ${project.version} + pom + io.prometheus prometheus-metrics-simpleclient-bridge diff --git a/prometheus-metrics-config/pom.xml b/prometheus-metrics-config/pom.xml index a07c83f0b..494282cc7 100644 --- a/prometheus-metrics-config/pom.xml +++ b/prometheus-metrics-config/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-config diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExemplarsProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExemplarsProperties.java index 20933bfdc..765d33ac5 100644 --- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExemplarsProperties.java +++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExemplarsProperties.java @@ -1,15 +1,14 @@ package io.prometheus.metrics.config; -import java.util.Map; import javax.annotation.Nullable; /** Properties starting with io.prometheus.exemplars */ public class ExemplarsProperties { private static final String PREFIX = "io.prometheus.exemplars"; - private static final String MIN_RETENTION_PERIOD_SECONDS = "minRetentionPeriodSeconds"; - private static final String MAX_RETENTION_PERIOD_SECONDS = "maxRetentionPeriodSeconds"; - private static final String SAMPLE_INTERVAL_MILLISECONDS = "sampleIntervalMilliseconds"; + private static final String MIN_RETENTION_PERIOD_SECONDS = "min_retention_period_seconds"; + private static final String MAX_RETENTION_PERIOD_SECONDS = "max_retention_period_seconds"; + private static final String SAMPLE_INTERVAL_MILLISECONDS = "sample_interval_milliseconds"; @Nullable private final Integer minRetentionPeriodSeconds; @Nullable private final Integer maxRetentionPeriodSeconds; @@ -57,17 +56,17 @@ public Integer getSampleIntervalMilliseconds() { } /** - * Note that this will remove entries from {@code properties}. This is because we want to know if - * there are unused properties remaining after all properties have been loaded. + * Note that this will remove entries from {@code propertySource}. This is because we want to know + * if there are unused properties remaining after all properties have been loaded. */ - static ExemplarsProperties load(Map properties) + static ExemplarsProperties load(PropertySource propertySource) throws PrometheusPropertiesException { Integer minRetentionPeriodSeconds = - Util.loadInteger(PREFIX + "." + MIN_RETENTION_PERIOD_SECONDS, properties); + Util.loadInteger(PREFIX, MIN_RETENTION_PERIOD_SECONDS, propertySource); Integer maxRetentionPeriodSeconds = - Util.loadInteger(PREFIX + "." + MAX_RETENTION_PERIOD_SECONDS, properties); + Util.loadInteger(PREFIX, MAX_RETENTION_PERIOD_SECONDS, propertySource); Integer sampleIntervalMilliseconds = - Util.loadInteger(PREFIX + "." + SAMPLE_INTERVAL_MILLISECONDS, properties); + Util.loadInteger(PREFIX, SAMPLE_INTERVAL_MILLISECONDS, propertySource); Util.assertValue( minRetentionPeriodSeconds, diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterFilterProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterFilterProperties.java index 7f3b46842..d59330cb9 100644 --- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterFilterProperties.java +++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterFilterProperties.java @@ -4,16 +4,15 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Map; import javax.annotation.Nullable; /** Properties starting with io.prometheus.exporter.filter */ public class ExporterFilterProperties { - public static final String METRIC_NAME_MUST_BE_EQUAL_TO = "metricNameMustBeEqualTo"; - public static final String METRIC_NAME_MUST_NOT_BE_EQUAL_TO = "metricNameMustNotBeEqualTo"; - public static final String METRIC_NAME_MUST_START_WITH = "metricNameMustStartWith"; - public static final String METRIC_NAME_MUST_NOT_START_WITH = "metricNameMustNotStartWith"; + public static final String METRIC_NAME_MUST_BE_EQUAL_TO = "metric_name_must_be_equal_to"; + public static final String METRIC_NAME_MUST_NOT_BE_EQUAL_TO = "metric_name_must_not_be_equal_to"; + public static final String METRIC_NAME_MUST_START_WITH = "metric_name_must_start_with"; + public static final String METRIC_NAME_MUST_NOT_START_WITH = "metric_name_must_not_start_with"; private static final String PREFIX = "io.prometheus.exporter.filter"; @Nullable private final List allowedNames; @@ -61,19 +60,19 @@ public List getExcludedMetricNamePrefixes() { } /** - * Note that this will remove entries from {@code properties}. This is because we want to know if - * there are unused properties remaining after all properties have been loaded. + * Note that this will remove entries from {@code propertySource}. This is because we want to know + * if there are unused properties remaining after all properties have been loaded. */ - static ExporterFilterProperties load(Map properties) + static ExporterFilterProperties load(PropertySource propertySource) throws PrometheusPropertiesException { List allowedNames = - Util.loadStringList(PREFIX + "." + METRIC_NAME_MUST_BE_EQUAL_TO, properties); + Util.loadStringList(PREFIX, METRIC_NAME_MUST_BE_EQUAL_TO, propertySource); List excludedNames = - Util.loadStringList(PREFIX + "." + METRIC_NAME_MUST_NOT_BE_EQUAL_TO, properties); + Util.loadStringList(PREFIX, METRIC_NAME_MUST_NOT_BE_EQUAL_TO, propertySource); List allowedPrefixes = - Util.loadStringList(PREFIX + "." + METRIC_NAME_MUST_START_WITH, properties); + Util.loadStringList(PREFIX, METRIC_NAME_MUST_START_WITH, propertySource); List excludedPrefixes = - Util.loadStringList(PREFIX + "." + METRIC_NAME_MUST_NOT_START_WITH, properties); + Util.loadStringList(PREFIX, METRIC_NAME_MUST_NOT_START_WITH, propertySource); return new ExporterFilterProperties( allowedNames, excludedNames, allowedPrefixes, excludedPrefixes); } diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterHttpServerProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterHttpServerProperties.java index 01849f55a..0623f78e1 100644 --- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterHttpServerProperties.java +++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterHttpServerProperties.java @@ -1,14 +1,13 @@ package io.prometheus.metrics.config; -import java.util.Map; import javax.annotation.Nullable; -/** Properties starting with io.prometheus.exporter.httpServer */ +/** Properties starting with io.prometheus.exporter.http_server */ public class ExporterHttpServerProperties { private static final String PORT = "port"; - private static final String PREFER_UNCOMPRESSED_RESPONSE = "preferUncompressedResponse"; - private static final String PREFIX = "io.prometheus.exporter.httpServer"; + private static final String PREFER_UNCOMPRESSED_RESPONSE = "prefer_uncompressed_response"; + private static final String PREFIX = "io.prometheus.exporter.http_server"; @Nullable private final Integer port; private final boolean preferUncompressedResponse; @@ -27,16 +26,16 @@ public boolean isPreferUncompressedResponse() { } /** - * Note that this will remove entries from {@code properties}. This is because we want to know if - * there are unused properties remaining after all properties have been loaded. + * Note that this will remove entries from {@code propertySource}. This is because we want to know + * if there are unused properties remaining after all properties have been loaded. */ - static ExporterHttpServerProperties load(Map properties) + static ExporterHttpServerProperties load(PropertySource propertySource) throws PrometheusPropertiesException { - Integer port = Util.loadInteger(PREFIX + "." + PORT, properties); + Integer port = Util.loadInteger(PREFIX, PORT, propertySource); Util.assertValue(port, t -> t > 0, "Expecting value > 0.", PREFIX, PORT); Boolean preferUncompressedResponse = - Util.loadBoolean(PREFIX + "." + PREFER_UNCOMPRESSED_RESPONSE, properties); + Util.loadBoolean(PREFIX, PREFER_UNCOMPRESSED_RESPONSE, propertySource); return new ExporterHttpServerProperties( port, preferUncompressedResponse != null && preferUncompressedResponse); diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterOpenTelemetryProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterOpenTelemetryProperties.java index be09b5a63..bd1dcdaf2 100644 --- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterOpenTelemetryProperties.java +++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterOpenTelemetryProperties.java @@ -4,7 +4,33 @@ import java.util.Map; import javax.annotation.Nullable; -// TODO: JavaDoc is currently only in OpenTelemetryExporter.Builder. Look there for reference. +/** + * Properties for configuring the OpenTelemetry exporter. + * + *

These properties can be configured via {@code prometheus.properties}, system properties, or + * programmatically. + * + *

All properties are prefixed with {@code io.prometheus.exporter.opentelemetry}. + * + *

Available properties: + * + *

    + *
  • {@code protocol} - OTLP protocol: {@code "grpc"} or {@code "http/protobuf"} + *
  • {@code endpoint} - OTLP endpoint URL + *
  • {@code headers} - HTTP headers for outgoing requests + *
  • {@code intervalSeconds} - Export interval in seconds + *
  • {@code timeoutSeconds} - Request timeout in seconds + *
  • {@code serviceName} - Service name resource attribute + *
  • {@code serviceNamespace} - Service namespace resource attribute + *
  • {@code serviceInstanceId} - Service instance ID resource attribute + *
  • {@code serviceVersion} - Service version resource attribute + *
  • {@code resourceAttributes} - Additional resource attributes + *
+ * + * @see OpenTelemetry + * SDK Environment Variables + */ public class ExporterOpenTelemetryProperties { // See @@ -12,14 +38,14 @@ public class ExporterOpenTelemetryProperties { private static final String PROTOCOL = "protocol"; // otel.exporter.otlp.protocol private static final String ENDPOINT = "endpoint"; // otel.exporter.otlp.endpoint private static final String HEADERS = "headers"; // otel.exporter.otlp.headers - private static final String INTERVAL_SECONDS = "intervalSeconds"; // otel.metric.export.interval - private static final String TIMEOUT_SECONDS = "timeoutSeconds"; // otel.exporter.otlp.timeout - private static final String SERVICE_NAME = "serviceName"; // otel.service.name - private static final String SERVICE_NAMESPACE = "serviceNamespace"; - private static final String SERVICE_INSTANCE_ID = "serviceInstanceId"; - private static final String SERVICE_VERSION = "serviceVersion"; + private static final String INTERVAL_SECONDS = "interval_seconds"; // otel.metric.export.interval + private static final String TIMEOUT_SECONDS = "timeout_seconds"; // otel.exporter.otlp.timeout + private static final String SERVICE_NAME = "service_name"; // otel.service.name + private static final String SERVICE_NAMESPACE = "service_namespace"; + private static final String SERVICE_INSTANCE_ID = "service_instance_id"; + private static final String SERVICE_VERSION = "service_version"; private static final String RESOURCE_ATTRIBUTES = - "resourceAttributes"; // otel.resource.attributes + "resource_attributes"; // otel.resource.attributes private static final String PREFIX = "io.prometheus.exporter.opentelemetry"; @Nullable private final String endpoint; @@ -105,22 +131,22 @@ public Map getResourceAttributes() { } /** - * Note that this will remove entries from {@code properties}. This is because we want to know if - * there are unused properties remaining after all properties have been loaded. + * Note that this will remove entries from {@code propertySource}. This is because we want to know + * if there are unused properties remaining after all properties have been loaded. */ - static ExporterOpenTelemetryProperties load(Map properties) + static ExporterOpenTelemetryProperties load(PropertySource propertySource) throws PrometheusPropertiesException { - String protocol = Util.loadString(PREFIX + "." + PROTOCOL, properties); - String endpoint = Util.loadString(PREFIX + "." + ENDPOINT, properties); - Map headers = Util.loadMap(PREFIX + "." + HEADERS, properties); - String interval = Util.loadStringAddSuffix(PREFIX + "." + INTERVAL_SECONDS, properties, "s"); - String timeout = Util.loadStringAddSuffix(PREFIX + "." + TIMEOUT_SECONDS, properties, "s"); - String serviceName = Util.loadString(PREFIX + "." + SERVICE_NAME, properties); - String serviceNamespace = Util.loadString(PREFIX + "." + SERVICE_NAMESPACE, properties); - String serviceInstanceId = Util.loadString(PREFIX + "." + SERVICE_INSTANCE_ID, properties); - String serviceVersion = Util.loadString(PREFIX + "." + SERVICE_VERSION, properties); + String protocol = Util.loadString(PREFIX, PROTOCOL, propertySource); + String endpoint = Util.loadString(PREFIX, ENDPOINT, propertySource); + Map headers = Util.loadMap(PREFIX, HEADERS, propertySource); + String interval = Util.loadStringAddSuffix(PREFIX, INTERVAL_SECONDS, propertySource, "s"); + String timeout = Util.loadStringAddSuffix(PREFIX, TIMEOUT_SECONDS, propertySource, "s"); + String serviceName = Util.loadString(PREFIX, SERVICE_NAME, propertySource); + String serviceNamespace = Util.loadString(PREFIX, SERVICE_NAMESPACE, propertySource); + String serviceInstanceId = Util.loadString(PREFIX, SERVICE_INSTANCE_ID, propertySource); + String serviceVersion = Util.loadString(PREFIX, SERVICE_VERSION, propertySource); Map resourceAttributes = - Util.loadMap(PREFIX + "." + RESOURCE_ATTRIBUTES, properties); + Util.loadMap(PREFIX, RESOURCE_ATTRIBUTES, propertySource); return new ExporterOpenTelemetryProperties( protocol, endpoint, @@ -153,6 +179,14 @@ public static class Builder { private Builder() {} + /** + * The OTLP protocol to use. + * + *

Supported values: {@code "grpc"} or {@code "http/protobuf"}. + * + *

See OpenTelemetry's OTEL_EXPORTER_OTLP_PROTOCOL. + */ public Builder protocol(String protocol) { if (!protocol.equals("grpc") && !protocol.equals("http/protobuf")) { throw new IllegalArgumentException( @@ -162,17 +196,43 @@ public Builder protocol(String protocol) { return this; } + /** + * The OTLP endpoint to send metric data to. + * + *

The default depends on the protocol: + * + *

    + *
  • {@code "grpc"}: {@code "http://localhost:4317"} + *
  • {@code "http/protobuf"}: {@code "http://localhost:4318/v1/metrics"} + *
+ * + *

See OpenTelemetry's OTEL_EXPORTER_OTLP_METRICS_ENDPOINT. + */ public Builder endpoint(String endpoint) { this.endpoint = endpoint; return this; } - /** Add a request header. Call multiple times to add multiple headers. */ + /** + * Add an HTTP header to be applied to outgoing requests. Call multiple times to add multiple + * headers. + * + *

See OpenTelemetry's OTEL_EXPORTER_OTLP_HEADERS. + */ public Builder header(String name, String value) { this.headers.put(name, value); return this; } + /** + * The interval between the start of two export attempts. Default is 60 seconds. + * + *

Like OpenTelemetry's OTEL_METRIC_EXPORT_INTERVAL + * (which defaults to 60000 milliseconds), but specified in seconds rather than milliseconds. + */ public Builder intervalSeconds(int intervalSeconds) { if (intervalSeconds <= 0) { throw new IllegalArgumentException(intervalSeconds + ": Expecting intervalSeconds > 0"); @@ -181,6 +241,13 @@ public Builder intervalSeconds(int intervalSeconds) { return this; } + /** + * The timeout for outgoing requests. Default is 10. + * + *

Like OpenTelemetry's OTEL_EXPORTER_OTLP_METRICS_TIMEOUT, + * but in seconds rather than milliseconds. + */ public Builder timeoutSeconds(int timeoutSeconds) { if (timeoutSeconds <= 0) { throw new IllegalArgumentException(timeoutSeconds + ": Expecting timeoutSeconds > 0"); @@ -189,26 +256,63 @@ public Builder timeoutSeconds(int timeoutSeconds) { return this; } + /** + * The {@code service.name} resource attribute. + * + *

If not explicitly specified, {@code client_java} will try to initialize it with a + * reasonable default, like the JAR file name. + * + *

See {@code service.name} in OpenTelemetry's Resource + * Semantic Conventions. + */ public Builder serviceName(String serviceName) { this.serviceName = serviceName; return this; } + /** + * The {@code service.namespace} resource attribute. + * + *

See {@code service.namespace} in OpenTelemetry's Resource + * Semantic Conventions. + */ public Builder serviceNamespace(String serviceNamespace) { this.serviceNamespace = serviceNamespace; return this; } + /** + * The {@code service.instance.id} resource attribute. + * + *

See {@code service.instance.id} in OpenTelemetry's Resource + * Semantic Conventions. + */ public Builder serviceInstanceId(String serviceInstanceId) { this.serviceInstanceId = serviceInstanceId; return this; } + /** + * The {@code service.version} resource attribute. + * + *

See {@code service.version} in OpenTelemetry's Resource + * Semantic Conventions. + */ public Builder serviceVersion(String serviceVersion) { this.serviceVersion = serviceVersion; return this; } + /** + * Add a resource attribute. Call multiple times to add multiple resource attributes. + * + *

See OpenTelemetry's OTEL_RESOURCE_ATTRIBUTES. + */ public Builder resourceAttribute(String name, String value) { this.resourceAttributes.put(name, value); return this; diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterProperties.java index 6b081816d..460a5cae2 100644 --- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterProperties.java +++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterProperties.java @@ -1,15 +1,14 @@ package io.prometheus.metrics.config; -import java.util.Map; import javax.annotation.Nullable; /** Properties starting with io.prometheus.exporter */ public class ExporterProperties { - private static final String INCLUDE_CREATED_TIMESTAMPS = "includeCreatedTimestamps"; + private static final String INCLUDE_CREATED_TIMESTAMPS = "include_created_timestamps"; // milliseconds is the default - we only provide a boolean flag to avoid a breaking change - private static final String PROMETHEUS_TIMESTAMPS_IN_MS = "prometheusTimestampsInMs"; - private static final String EXEMPLARS_ON_ALL_METRIC_TYPES = "exemplarsOnAllMetricTypes"; + private static final String PROMETHEUS_TIMESTAMPS_IN_MS = "prometheus_timestamps_in_ms"; + private static final String EXEMPLARS_ON_ALL_METRIC_TYPES = "exemplars_on_all_metric_types"; private static final String PREFIX = "io.prometheus.exporter"; @Nullable private final Boolean includeCreatedTimestamps; @@ -44,17 +43,16 @@ public boolean getExemplarsOnAllMetricTypes() { } /** - * Note that this will remove entries from {@code properties}. This is because we want to know if - * there are unused properties remaining after all properties have been loaded. + * Note that this will remove entries from {@code propertySource}. This is because we want to know + * if there are unused properties remaining after all properties have been loaded. */ - static ExporterProperties load(Map properties) + static ExporterProperties load(PropertySource propertySource) throws PrometheusPropertiesException { Boolean includeCreatedTimestamps = - Util.loadBoolean(PREFIX + "." + INCLUDE_CREATED_TIMESTAMPS, properties); - Boolean timestampsInMs = - Util.loadBoolean(PREFIX + "." + PROMETHEUS_TIMESTAMPS_IN_MS, properties); + Util.loadBoolean(PREFIX, INCLUDE_CREATED_TIMESTAMPS, propertySource); + Boolean timestampsInMs = Util.loadBoolean(PREFIX, PROMETHEUS_TIMESTAMPS_IN_MS, propertySource); Boolean exemplarsOnAllMetricTypes = - Util.loadBoolean(PREFIX + "." + EXEMPLARS_ON_ALL_METRIC_TYPES, properties); + Util.loadBoolean(PREFIX, EXEMPLARS_ON_ALL_METRIC_TYPES, propertySource); return new ExporterProperties( includeCreatedTimestamps, timestampsInMs, exemplarsOnAllMetricTypes); } diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java index bd53f8b76..aea4b2d8f 100644 --- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java +++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java @@ -1,7 +1,6 @@ package io.prometheus.metrics.config; import java.time.Duration; -import java.util.Map; import javax.annotation.Nullable; public class ExporterPushgatewayProperties { @@ -9,9 +8,9 @@ public class ExporterPushgatewayProperties { private static final String ADDRESS = "address"; private static final String JOB = "job"; private static final String SCHEME = "scheme"; - private static final String ESCAPING_SCHEME = "escapingScheme"; - private static final String READ_TIMEOUT = "readTimeoutSeconds"; - private static final String CONNECT_TIMEOUT = "connectTimeoutSeconds"; + private static final String ESCAPING_SCHEME = "escaping_scheme"; + private static final String READ_TIMEOUT = "read_timeout_seconds"; + private static final String CONNECT_TIMEOUT = "connect_timeout_seconds"; private static final String PREFIX = "io.prometheus.exporter.pushgateway"; @Nullable private final String scheme; @Nullable private final String address; @@ -78,17 +77,17 @@ public Duration getReadTimeout() { } /** - * Note that this will remove entries from {@code properties}. This is because we want to know if - * there are unused properties remaining after all properties have been loaded. + * Note that this will remove entries from {@code propertySource}. This is because we want to know + * if there are unused properties remaining after all properties have been loaded. */ - static ExporterPushgatewayProperties load(Map properties) + static ExporterPushgatewayProperties load(PropertySource propertySource) throws PrometheusPropertiesException { - String address = Util.loadString(PREFIX + "." + ADDRESS, properties); - String job = Util.loadString(PREFIX + "." + JOB, properties); - String scheme = Util.loadString(PREFIX + "." + SCHEME, properties); - String escapingScheme = Util.loadString(PREFIX + "." + ESCAPING_SCHEME, properties); - Duration connectTimeout = Util.loadOptionalDuration(PREFIX + "." + CONNECT_TIMEOUT, properties); - Duration readTimeout = Util.loadOptionalDuration(PREFIX + "." + READ_TIMEOUT, properties); + String address = Util.loadString(PREFIX, ADDRESS, propertySource); + String job = Util.loadString(PREFIX, JOB, propertySource); + String scheme = Util.loadString(PREFIX, SCHEME, propertySource); + String escapingScheme = Util.loadString(PREFIX, ESCAPING_SCHEME, propertySource); + Duration connectTimeout = Util.loadOptionalDuration(PREFIX, CONNECT_TIMEOUT, propertySource); + Duration readTimeout = Util.loadOptionalDuration(PREFIX, READ_TIMEOUT, propertySource); if (scheme != null) { if (!scheme.equals("http") && !scheme.equals("https")) { diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/MetricsProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/MetricsProperties.java index 6c8942713..a530f35e1 100644 --- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/MetricsProperties.java +++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/MetricsProperties.java @@ -5,29 +5,49 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import javax.annotation.Nullable; /** Properties starting with io.prometheus.metrics */ public class MetricsProperties { - private static final String EXEMPLARS_ENABLED = "exemplarsEnabled"; - private static final String HISTOGRAM_NATIVE_ONLY = "histogramNativeOnly"; - private static final String HISTOGRAM_CLASSIC_ONLY = "histogramClassicOnly"; - private static final String HISTOGRAM_CLASSIC_UPPER_BOUNDS = "histogramClassicUpperBounds"; - private static final String HISTOGRAM_NATIVE_INITIAL_SCHEMA = "histogramNativeInitialSchema"; + private static final String EXEMPLARS_ENABLED = "exemplars_enabled"; + private static final String HISTOGRAM_NATIVE_ONLY = "histogram_native_only"; + private static final String HISTOGRAM_CLASSIC_ONLY = "histogram_classic_only"; + private static final String HISTOGRAM_CLASSIC_UPPER_BOUNDS = "histogram_classic_upper_bounds"; + private static final String HISTOGRAM_NATIVE_INITIAL_SCHEMA = "histogram_native_initial_schema"; private static final String HISTOGRAM_NATIVE_MIN_ZERO_THRESHOLD = - "histogramNativeMinZeroThreshold"; + "histogram_native_min_zero_threshold"; private static final String HISTOGRAM_NATIVE_MAX_ZERO_THRESHOLD = - "histogramNativeMaxZeroThreshold"; + "histogram_native_max_zero_threshold"; private static final String HISTOGRAM_NATIVE_MAX_NUMBER_OF_BUCKETS = - "histogramNativeMaxNumberOfBuckets"; // 0 means unlimited number of buckets + "histogram_native_max_number_of_buckets"; // 0 means unlimited number of buckets private static final String HISTOGRAM_NATIVE_RESET_DURATION_SECONDS = - "histogramNativeResetDurationSeconds"; // 0 means no reset - private static final String SUMMARY_QUANTILES = "summaryQuantiles"; - private static final String SUMMARY_QUANTILE_ERRORS = "summaryQuantileErrors"; - private static final String SUMMARY_MAX_AGE_SECONDS = "summaryMaxAgeSeconds"; - private static final String SUMMARY_NUMBER_OF_AGE_BUCKETS = "summaryNumberOfAgeBuckets"; + "histogram_native_reset_duration_seconds"; // 0 means no reset + private static final String SUMMARY_QUANTILES = "summary_quantiles"; + private static final String SUMMARY_QUANTILE_ERRORS = "summary_quantile_errors"; + private static final String SUMMARY_MAX_AGE_SECONDS = "summary_max_age_seconds"; + private static final String SUMMARY_NUMBER_OF_AGE_BUCKETS = "summary_number_of_age_buckets"; + + /** + * All known property suffixes that can be configured for metrics. + * + *

This list is used to parse metric-specific configuration keys from environment variables. + */ + static final String[] PROPERTY_SUFFIXES = { + EXEMPLARS_ENABLED, + HISTOGRAM_NATIVE_ONLY, + HISTOGRAM_CLASSIC_ONLY, + HISTOGRAM_CLASSIC_UPPER_BOUNDS, + HISTOGRAM_NATIVE_INITIAL_SCHEMA, + HISTOGRAM_NATIVE_MIN_ZERO_THRESHOLD, + HISTOGRAM_NATIVE_MAX_ZERO_THRESHOLD, + HISTOGRAM_NATIVE_MAX_NUMBER_OF_BUCKETS, + HISTOGRAM_NATIVE_RESET_DURATION_SECONDS, + SUMMARY_QUANTILES, + SUMMARY_QUANTILE_ERRORS, + SUMMARY_MAX_AGE_SECONDS, + SUMMARY_NUMBER_OF_AGE_BUCKETS + }; @Nullable private final Boolean exemplarsEnabled; @Nullable private final Boolean histogramNativeOnly; @@ -226,17 +246,16 @@ private void validate(String prefix) throws PrometheusPropertiesException { + SUMMARY_QUANTILES); } if (summaryQuantileErrors.size() != summaryQuantiles.size()) { + String fullKey = + prefix.isEmpty() ? SUMMARY_QUANTILE_ERRORS : prefix + "." + SUMMARY_QUANTILE_ERRORS; throw new PrometheusPropertiesException( - prefix - + "." - + SUMMARY_QUANTILE_ERRORS - + ": must have the same length as " - + SUMMARY_QUANTILES); + fullKey + ": must have the same length as " + SUMMARY_QUANTILES); } for (double error : summaryQuantileErrors) { if (error < 0 || error > 1) { - throw new PrometheusPropertiesException( - prefix + "." + SUMMARY_QUANTILE_ERRORS + ": Expecting 0.0 <= error <= 1.0"); + String fullKey = + prefix.isEmpty() ? SUMMARY_QUANTILE_ERRORS : prefix + "." + SUMMARY_QUANTILE_ERRORS; + throw new PrometheusPropertiesException(fullKey + ": Expecting 0.0 <= error <= 1.0"); } } } @@ -335,25 +354,25 @@ public Integer getSummaryNumberOfAgeBuckets() { } /** - * Note that this will remove entries from {@code properties}. This is because we want to know if - * there are unused properties remaining after all properties have been loaded. + * Note that this will remove entries from {@code propertySource}. This is because we want to know + * if there are unused properties remaining after all properties have been loaded. */ - static MetricsProperties load(String prefix, Map properties) + static MetricsProperties load(String prefix, PropertySource propertySource) throws PrometheusPropertiesException { return new MetricsProperties( - Util.loadBoolean(prefix + "." + EXEMPLARS_ENABLED, properties), - Util.loadBoolean(prefix + "." + HISTOGRAM_NATIVE_ONLY, properties), - Util.loadBoolean(prefix + "." + HISTOGRAM_CLASSIC_ONLY, properties), - Util.loadDoubleList(prefix + "." + HISTOGRAM_CLASSIC_UPPER_BOUNDS, properties), - Util.loadInteger(prefix + "." + HISTOGRAM_NATIVE_INITIAL_SCHEMA, properties), - Util.loadDouble(prefix + "." + HISTOGRAM_NATIVE_MIN_ZERO_THRESHOLD, properties), - Util.loadDouble(prefix + "." + HISTOGRAM_NATIVE_MAX_ZERO_THRESHOLD, properties), - Util.loadInteger(prefix + "." + HISTOGRAM_NATIVE_MAX_NUMBER_OF_BUCKETS, properties), - Util.loadLong(prefix + "." + HISTOGRAM_NATIVE_RESET_DURATION_SECONDS, properties), - Util.loadDoubleList(prefix + "." + SUMMARY_QUANTILES, properties), - Util.loadDoubleList(prefix + "." + SUMMARY_QUANTILE_ERRORS, properties), - Util.loadLong(prefix + "." + SUMMARY_MAX_AGE_SECONDS, properties), - Util.loadInteger(prefix + "." + SUMMARY_NUMBER_OF_AGE_BUCKETS, properties), + Util.loadBoolean(prefix, EXEMPLARS_ENABLED, propertySource), + Util.loadBoolean(prefix, HISTOGRAM_NATIVE_ONLY, propertySource), + Util.loadBoolean(prefix, HISTOGRAM_CLASSIC_ONLY, propertySource), + Util.loadDoubleList(prefix, HISTOGRAM_CLASSIC_UPPER_BOUNDS, propertySource), + Util.loadInteger(prefix, HISTOGRAM_NATIVE_INITIAL_SCHEMA, propertySource), + Util.loadDouble(prefix, HISTOGRAM_NATIVE_MIN_ZERO_THRESHOLD, propertySource), + Util.loadDouble(prefix, HISTOGRAM_NATIVE_MAX_ZERO_THRESHOLD, propertySource), + Util.loadInteger(prefix, HISTOGRAM_NATIVE_MAX_NUMBER_OF_BUCKETS, propertySource), + Util.loadLong(prefix, HISTOGRAM_NATIVE_RESET_DURATION_SECONDS, propertySource), + Util.loadDoubleList(prefix, SUMMARY_QUANTILES, propertySource), + Util.loadDoubleList(prefix, SUMMARY_QUANTILE_ERRORS, propertySource), + Util.loadLong(prefix, SUMMARY_MAX_AGE_SECONDS, propertySource), + Util.loadInteger(prefix, SUMMARY_NUMBER_OF_AGE_BUCKETS, propertySource), prefix); } diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusProperties.java index ab78b48e3..055fe4aa3 100644 --- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusProperties.java +++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusProperties.java @@ -14,7 +14,7 @@ public class PrometheusProperties { private static final PrometheusProperties instance = PrometheusPropertiesLoader.load(); private final MetricsProperties defaultMetricsProperties; - private final Map metricProperties = new HashMap<>(); + private final MetricPropertiesMap metricProperties; private final ExemplarsProperties exemplarProperties; private final ExporterProperties exporterProperties; private final ExporterFilterProperties exporterFilterProperties; @@ -22,6 +22,67 @@ public class PrometheusProperties { private final ExporterOpenTelemetryProperties exporterOpenTelemetryProperties; private final ExporterPushgatewayProperties exporterPushgatewayProperties; + /** + * Map that stores metric-specific properties keyed by metric name in exposition format + * (underscores instead of dots). + * + *

This wrapper makes it explicit that metric names are normalized to underscore format for + * storage, so that environment variables and properties with dots in metric names can be + * correctly looked up using normalized names. + */ + static class MetricPropertiesMap { + private final Map map = new HashMap<>(); + + void set(Map properties) { + map.clear(); + properties.forEach(this::put); + } + + void put(String metricName, MetricsProperties properties) { + map.put(normalize(metricName), properties); + } + + /** + * Get metric properties by metric name. + * + *

Accepts metric names in any format (with dots or underscores) and automatically converts + * them to the normalized underscore format used for storage. + * + * @param metricName the metric name (dots will be converted to underscores) + * @return the metric properties, or null if not configured + */ + @Nullable + MetricsProperties get(String metricName) { + return map.get(normalize(metricName)); + } + + // copied from PrometheusNaming - but we can't reuse that class here because it's in a module + // that + // depends on PrometheusProperties, which would create a circular dependency. + private static String normalize(String name) { + StringBuilder escaped = new StringBuilder(); + + for (int i = 0; i < name.length(); ) { + int c = name.codePointAt(i); + if (isValidLegacyChar(c, i)) { + escaped.appendCodePoint(c); + } else { + escaped.append('_'); + } + i += Character.charCount(c); + } + return escaped.toString(); + } + } + + private static boolean isValidLegacyChar(int c, int i) { + return (c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || c == '_' + || c == ':' + || (c >= '0' && c <= '9' && i > 0); + } + /** * Get the properties instance. When called for the first time, {@code get()} loads the properties * from the following locations: @@ -41,9 +102,10 @@ public static Builder builder() { return new Builder(); } - public PrometheusProperties( + // Package-private constructor for PrometheusPropertiesLoader and Builder + PrometheusProperties( MetricsProperties defaultMetricsProperties, - Map metricProperties, + MetricPropertiesMap metricProperties, ExemplarsProperties exemplarProperties, ExporterProperties exporterProperties, ExporterFilterProperties exporterFilterProperties, @@ -51,7 +113,7 @@ public PrometheusProperties( ExporterPushgatewayProperties pushgatewayProperties, ExporterOpenTelemetryProperties otelConfig) { this.defaultMetricsProperties = defaultMetricsProperties; - this.metricProperties.putAll(metricProperties); + this.metricProperties = metricProperties; this.exemplarProperties = exemplarProperties; this.exporterProperties = exporterProperties; this.exporterFilterProperties = exporterFilterProperties; @@ -72,10 +134,13 @@ public MetricsProperties getDefaultMetricProperties() { * Properties specific for one metric. Should be merged with {@link * #getDefaultMetricProperties()}. May return {@code null} if no metric-specific properties are * configured for a metric name. + * + * @param metricName the metric name (dots will be automatically converted to underscores to match + * exposition format) */ @Nullable public MetricsProperties getMetricProperties(String metricName) { - return metricProperties.get(metricName.replace(".", "_")); + return metricProperties.get(metricName); } public ExemplarsProperties getExemplarProperties() { @@ -104,7 +169,7 @@ public ExporterOpenTelemetryProperties getExporterOpenTelemetryProperties() { public static class Builder { private MetricsProperties defaultMetricsProperties = MetricsProperties.builder().build(); - private Map metricProperties = new HashMap<>(); + private final MetricPropertiesMap metricProperties = new MetricPropertiesMap(); private ExemplarsProperties exemplarProperties = ExemplarsProperties.builder().build(); private ExporterProperties exporterProperties = ExporterProperties.builder().build(); private ExporterFilterProperties exporterFilterProperties = @@ -124,7 +189,7 @@ public Builder defaultMetricsProperties(MetricsProperties defaultMetricsProperti } public Builder metricProperties(Map metricProperties) { - this.metricProperties = metricProperties; + this.metricProperties.set(metricProperties); return this; } diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesLoader.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesLoader.java index a847a8dba..9119c2f65 100644 --- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesLoader.java +++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesLoader.java @@ -5,12 +5,9 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Properties; import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * The Properties Loader is early stages. @@ -29,20 +26,21 @@ public static PrometheusProperties load() throws PrometheusPropertiesException { public static PrometheusProperties load(Map externalProperties) throws PrometheusPropertiesException { - Map properties = loadProperties(externalProperties); - Map metricsConfigs = loadMetricsConfigs(properties); + PropertySource propertySource = loadProperties(externalProperties); + PrometheusProperties.MetricPropertiesMap metricsConfigs = loadMetricsConfigs(propertySource); MetricsProperties defaultMetricsProperties = - MetricsProperties.load("io.prometheus.metrics", properties); - ExemplarsProperties exemplarConfig = ExemplarsProperties.load(properties); - ExporterProperties exporterProperties = ExporterProperties.load(properties); - ExporterFilterProperties exporterFilterProperties = ExporterFilterProperties.load(properties); + MetricsProperties.load("io.prometheus.metrics", propertySource); + ExemplarsProperties exemplarConfig = ExemplarsProperties.load(propertySource); + ExporterProperties exporterProperties = ExporterProperties.load(propertySource); + ExporterFilterProperties exporterFilterProperties = + ExporterFilterProperties.load(propertySource); ExporterHttpServerProperties exporterHttpServerProperties = - ExporterHttpServerProperties.load(properties); + ExporterHttpServerProperties.load(propertySource); ExporterPushgatewayProperties exporterPushgatewayProperties = - ExporterPushgatewayProperties.load(properties); + ExporterPushgatewayProperties.load(propertySource); ExporterOpenTelemetryProperties exporterOpenTelemetryProperties = - ExporterOpenTelemetryProperties.load(properties); - validateAllPropertiesProcessed(properties); + ExporterOpenTelemetryProperties.load(propertySource); + validateAllPropertiesProcessed(propertySource); return new PrometheusProperties( defaultMetricsProperties, metricsConfigs, @@ -54,28 +52,49 @@ public static PrometheusProperties load(Map externalProperties) exporterOpenTelemetryProperties); } - // This will remove entries from properties when they are processed. - private static Map loadMetricsConfigs(Map properties) { - Map result = new HashMap<>(); + // This will remove entries from propertySource when they are processed. + static PrometheusProperties.MetricPropertiesMap loadMetricsConfigs( + PropertySource propertySource) { + PrometheusProperties.MetricPropertiesMap result = + new PrometheusProperties.MetricPropertiesMap(); // Note that the metric name in the properties file must be as exposed in the Prometheus // exposition formats, // i.e. all dots replaced with underscores. - Pattern pattern = Pattern.compile("io\\.prometheus\\.metrics\\.([^.]+)\\."); - // Create a copy of the keySet() for iterating. We cannot iterate directly over keySet() - // because entries are removed when MetricsConfig.load(...) is called. - Set propertyNames = new HashSet<>(); - for (Object key : properties.keySet()) { - propertyNames.add(key.toString()); - } + + // Get a snapshot of all keys for pattern matching. Entries will be removed + // when MetricsProperties.load(...) is called. + Set propertyNames = propertySource.getAllKeys(); for (String propertyName : propertyNames) { - Matcher matcher = pattern.matcher(propertyName); - if (matcher.find()) { - String metricName = matcher.group(1).replace(".", "_"); - if (!result.containsKey(metricName)) { - result.put( - metricName, - MetricsProperties.load("io.prometheus.metrics." + metricName, properties)); + String metricName = null; + + if (propertyName.startsWith("io.prometheus.metrics.")) { + // Dot-separated format (from regular properties, system properties, or files) + String remainder = propertyName.substring("io.prometheus.metrics.".length()); + // Try to match against known property suffixes + for (String suffix : MetricsProperties.PROPERTY_SUFFIXES) { + if (remainder.endsWith("." + suffix)) { + // Metric name in dot format, convert dots to underscores for exposition format + metricName = + remainder.substring(0, remainder.length() - suffix.length() - 1).replace(".", "_"); + break; + } } + } else if (propertyName.startsWith("io_prometheus_metrics_")) { + // Underscore-separated format (from environment variables) + String remainder = propertyName.substring("io_prometheus_metrics_".length()); + // Try to match against known property suffixes + for (String suffix : MetricsProperties.PROPERTY_SUFFIXES) { + if (remainder.endsWith("_" + suffix)) { + metricName = remainder.substring(0, remainder.length() - suffix.length() - 1); + break; + } + } + } + + if (metricName != null && result.get(metricName) == null) { + result.put( + metricName, + MetricsProperties.load("io.prometheus.metrics." + metricName, propertySource)); } } return result; @@ -84,26 +103,43 @@ private static Map loadMetricsConfigs(Map properties) { - for (Object key : properties.keySet()) { - if (key.toString().startsWith("io.prometheus")) { + private static void validateAllPropertiesProcessed(PropertySource propertySource) { + for (String key : propertySource.getRemainingKeys()) { + if (key.startsWith("io.prometheus") || key.startsWith("io_prometheus")) { throw new PrometheusPropertiesException(key + ": Unknown property"); } } } - private static Map loadProperties(Map externalProperties) { - Map properties = new HashMap<>(); - properties.putAll(loadPropertiesFromClasspath()); - properties.putAll(loadPropertiesFromFile()); // overriding the entries from the classpath file + private static PropertySource loadProperties(Map externalProperties) { + // Regular properties (lowest priority): classpath, file, system properties + Map regularProperties = new HashMap<>(); + // Normalize all properties at load time to handle camelCase in files for backward compatibility + normalizeAndPutAll(regularProperties, loadPropertiesFromClasspath()); + normalizeAndPutAll( + regularProperties, + loadPropertiesFromFile()); // overriding the entries from the classpath file // overriding the entries from the properties file // copy System properties to avoid ConcurrentModificationException + // normalize camelCase system properties to snake_case for backward compatibility System.getProperties().stringPropertyNames().stream() .filter(key -> key.startsWith("io.prometheus")) - .forEach(key -> properties.put(key, System.getProperty(key))); - properties.putAll(externalProperties); // overriding all the entries above - // TODO: Add environment variables like EXEMPLARS_ENABLED. - return properties; + .forEach(key -> regularProperties.put(normalizePropertyKey(key), System.getProperty(key))); + + // Environment variables (second priority): just lowercase, keep underscores + Map envVarProperties = loadPropertiesFromEnvironment(); + + // External properties (highest priority): normalize camelCase for backward compatibility + Map normalizedExternalProperties = new HashMap<>(); + externalProperties.forEach( + (key, value) -> + normalizedExternalProperties.put(normalizePropertyKey(key.toString()), value)); + + return new PropertySource(normalizedExternalProperties, envVarProperties, regularProperties); + } + + private static void normalizeAndPutAll(Map target, Map source) { + source.forEach((key, value) -> target.put(normalizePropertyKey(key.toString()), value)); } private static Properties loadPropertiesFromClasspath() { @@ -135,4 +171,48 @@ private static Properties loadPropertiesFromFile() throws PrometheusPropertiesEx } return properties; } + + /** + * Load properties from environment variables. + * + *

Environment variables are converted to lowercase but keep underscores as-is. For example, + * the environment variable IO_PROMETHEUS_METRICS_EXEMPLARS_ENABLED becomes + * io_prometheus_metrics_exemplars_enabled. + * + *

The transformation to dot notation happens at access time in PropertySource. + * + *

Only environment variables starting with IO_PROMETHEUS are considered. + * + * @return properties loaded from environment variables (with lowercase keys and underscores) + */ + private static Map loadPropertiesFromEnvironment() { + Map properties = new HashMap<>(); + System.getenv() + .forEach( + (key, value) -> { + if (key.startsWith("IO_PROMETHEUS")) { + String normalizedKey = key.toLowerCase(java.util.Locale.ROOT); + properties.put(normalizedKey, value); + } + }); + return properties; + } + + /** + * Normalize a property key for consistent lookup. + * + *

Converts camelCase property keys to snake_case. This allows both snake_case (preferred) and + * camelCase (deprecated) property names to be used. + * + *

For example: exemplarsEnabled → exemplars_enabled exemplars_enabled → exemplars_enabled + * (unchanged) + * + * @param key the property key + * @return the normalized property key + */ + static String normalizePropertyKey(String key) { + // Insert underscores before uppercase letters to convert camelCase to snake_case + String withUnderscores = key.replaceAll("([a-z])([A-Z])", "$1_$2"); + return withUnderscores.toLowerCase(java.util.Locale.ROOT); + } } diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PropertySource.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PropertySource.java new file mode 100644 index 000000000..a85212469 --- /dev/null +++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PropertySource.java @@ -0,0 +1,165 @@ +package io.prometheus.metrics.config; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +/** + * PropertySource encapsulates three separate property maps with different priorities and + * transformation rules. + * + *

Properties are checked in the following order: + * + *

    + *
  1. External properties (highest priority) - exact key match + *
  2. Environment variables (second priority) - with dot-to-underscore transformation + *
  3. Regular properties (lowest priority) - from system properties, files, and classpath + *
+ * + *

Property lookups remove entries from the maps. This allows detecting unused properties at the + * end of configuration loading. + */ +class PropertySource { + + private final Map externalProperties; // Highest priority + private final Map envVarProperties; // Second priority + private final Map regularProperties; // Lowest priority + + /** + * Creates a PropertySource with three separate property maps. + * + * @param externalProperties properties passed explicitly (e.g., from application code) + * @param envVarProperties properties from environment variables (keys in env var format with + * underscores, lowercase) + * @param regularProperties properties from system properties, files, and classpath (keys + * normalized to snake_case) + */ + PropertySource( + Map externalProperties, + Map envVarProperties, + Map regularProperties) { + this.externalProperties = externalProperties; + this.envVarProperties = envVarProperties; + this.regularProperties = regularProperties; + } + + /** + * Creates a PropertySource with only regular properties (for testing). + * + *

Creates empty maps for external and environment variable properties. + * + * @param regularProperties properties from system properties, files, and classpath (keys + * normalized to snake_case) + */ + PropertySource(Map regularProperties) { + this(new HashMap<>(), new HashMap<>(), regularProperties); + } + + /** + * Gets a property value by key, checking all three sources in priority order. + * + *

For external and regular properties, performs exact key match. For environment variables, + * transforms dots to underscores before lookup (e.g., "io.prometheus.metrics.exemplars_enabled" + * becomes "io_prometheus_metrics_exemplars_enabled"). + * + *

Removes the property from ALL source maps to prevent duplicate detection during validation. + * + * @param key the property key to look up + * @return the property value, or null if not found + */ + @Nullable + String getProperty(String key) { + String result = null; + + // Check external properties first (highest priority) + Object value = externalProperties.remove(key); + if (value != null) { + result = value.toString(); + } + + // Check env vars with transformation (second priority) + // Transform dots to underscores: io.prometheus.metrics.exemplars_enabled + // -> io_prometheus_metrics_exemplars_enabled + String envKey = key.replace(".", "_"); + Object envValue = envVarProperties.remove(envKey); + if (result == null && envValue != null) { + result = envValue.toString(); + } + + // Check regular properties last (lowest priority) + Object regularValue = regularProperties.remove(key); + if (result == null && regularValue != null) { + result = regularValue.toString(); + } + + return result; + } + + /** + * Gets a property value by prefix and property name. + * + *

This is a convenience method that concatenates the prefix and property name with a dot and + * calls {@link #getProperty(String)}. + * + * @param prefix the property prefix (e.g., "io.prometheus.metrics"), or empty string for no + * prefix + * @param propertyName the property name (e.g., "exemplars_enabled") + * @return the property value, or null if not found + */ + @Nullable + String getProperty(String prefix, String propertyName) { + String fullKey = prefix.isEmpty() ? propertyName : prefix + "." + propertyName; + return getProperty(fullKey); + } + + /** + * Returns all keys from all three property sources. + * + *

Keys are returned in the format they are stored in each source: external and regular + * properties typically use dot-separated keys, while environment variables are exposed in their + * underscore form (e.g., "io_prometheus_metrics_exemplars_enabled"). + * + *

This is used for pattern matching to find metric-specific configurations. + * + * @return a set of all property keys + */ + Set getAllKeys() { + Set allKeys = new HashSet<>(); + for (Object key : externalProperties.keySet()) { + allKeys.add(key.toString()); + } + // Include env var keys as stored (underscore-separated, lowercase) + for (Object key : envVarProperties.keySet()) { + String envKey = key.toString(); + allKeys.add(envKey); + } + for (Object key : regularProperties.keySet()) { + allKeys.add(key.toString()); + } + return allKeys; + } + + /** + * Returns all remaining keys from all three property sources. + * + *

This is used for validation to detect unused properties that might indicate configuration + * errors. + * + * @return a set of all remaining property keys + */ + Set getRemainingKeys() { + Set remainingKeys = new HashSet<>(); + for (Object key : externalProperties.keySet()) { + remainingKeys.add(key.toString()); + } + for (Object key : envVarProperties.keySet()) { + remainingKeys.add(key.toString()); + } + for (Object key : regularProperties.keySet()) { + remainingKeys.add(key.toString()); + } + return remainingKeys; + } +} diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/Util.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/Util.java index 04eb78a19..20bd75699 100644 --- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/Util.java +++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/Util.java @@ -12,22 +12,19 @@ class Util { @Nullable - static String getProperty(String name, Map properties) { - Object object = properties.remove(name); - if (object != null) { - return object.toString(); - } - return null; + static String getProperty(String prefix, String propertyName, PropertySource propertySource) { + return propertySource.getProperty(prefix, propertyName); } @Nullable - static Boolean loadBoolean(String name, Map properties) + static Boolean loadBoolean(String prefix, String propertyName, PropertySource propertySource) throws PrometheusPropertiesException { - String property = getProperty(name, properties); + String property = getProperty(prefix, propertyName, propertySource); if (property != null) { + String fullKey = prefix.isEmpty() ? propertyName : prefix + "." + propertyName; if (!"true".equalsIgnoreCase(property) && !"false".equalsIgnoreCase(property)) { throw new PrometheusPropertiesException( - String.format("%s: Expecting 'true' or 'false'. Found: %s", name, property)); + String.format("%s: Expecting 'true' or 'false'. Found: %s", fullKey, property)); } return Boolean.parseBoolean(property); } @@ -47,24 +44,26 @@ static List toList(@Nullable double... values) { } @Nullable - static String loadString(String name, Map properties) + static String loadString(String prefix, String propertyName, PropertySource propertySource) throws PrometheusPropertiesException { - return getProperty(name, properties); + return getProperty(prefix, propertyName, propertySource); } @Nullable - static String loadStringAddSuffix(String name, Map properties, String suffix) { - Object object = properties.remove(name); - if (object != null) { - return object + suffix; + static String loadStringAddSuffix( + String prefix, String propertyName, PropertySource propertySource, String suffix) { + String value = propertySource.getProperty(prefix, propertyName); + if (value != null) { + return value + suffix; } return null; } @Nullable - static List loadStringList(String name, Map properties) + static List loadStringList( + String prefix, String propertyName, PropertySource propertySource) throws PrometheusPropertiesException { - String property = getProperty(name, properties); + String property = getProperty(prefix, propertyName, propertySource); if (property != null) { return Arrays.asList(property.split("\\s*,\\s*")); } @@ -72,10 +71,12 @@ static List loadStringList(String name, Map properties) } @Nullable - static List loadDoubleList(String name, Map properties) + static List loadDoubleList( + String prefix, String propertyName, PropertySource propertySource) throws PrometheusPropertiesException { - String property = getProperty(name, properties); + String property = getProperty(prefix, propertyName, propertySource); if (property != null) { + String fullKey = prefix.isEmpty() ? propertyName : prefix + "." + propertyName; String[] numbers = property.split("\\s*,\\s*"); Double[] result = new Double[numbers.length]; for (int i = 0; i < numbers.length; i++) { @@ -87,7 +88,7 @@ static List loadDoubleList(String name, Map properties) } } catch (NumberFormatException e) { throw new PrometheusPropertiesException( - name + "=" + property + ": Expecting comma separated list of double values"); + fullKey + "=" + property + ": Expecting comma separated list of double values"); } } return Arrays.asList(result); @@ -96,10 +97,11 @@ static List loadDoubleList(String name, Map properties) } // Map is represented as "key1=value1,key2=value2" - static Map loadMap(String name, Map properties) + static Map loadMap( + String prefix, String propertyName, PropertySource propertySource) throws PrometheusPropertiesException { Map result = new HashMap<>(); - String property = getProperty(name, properties); + String property = getProperty(prefix, propertyName, propertySource); if (property != null) { String[] pairs = property.split(","); for (String pair : pairs) { @@ -119,55 +121,61 @@ static Map loadMap(String name, Map properties) } @Nullable - static Integer loadInteger(String name, Map properties) + static Integer loadInteger(String prefix, String propertyName, PropertySource propertySource) throws PrometheusPropertiesException { - String property = getProperty(name, properties); + String property = getProperty(prefix, propertyName, propertySource); if (property != null) { + String fullKey = prefix.isEmpty() ? propertyName : prefix + "." + propertyName; try { return Integer.parseInt(property); } catch (NumberFormatException e) { throw new PrometheusPropertiesException( - name + "=" + property + ": Expecting integer value"); + fullKey + "=" + property + ": Expecting integer value"); } } return null; } @Nullable - static Double loadDouble(String name, Map properties) + static Double loadDouble(String prefix, String propertyName, PropertySource propertySource) throws PrometheusPropertiesException { - String property = getProperty(name, properties); + String property = getProperty(prefix, propertyName, propertySource); if (property != null) { + String fullKey = prefix.isEmpty() ? propertyName : prefix + "." + propertyName; try { return Double.parseDouble(property); } catch (NumberFormatException e) { - throw new PrometheusPropertiesException(name + "=" + property + ": Expecting double value"); + throw new PrometheusPropertiesException( + fullKey + "=" + property + ": Expecting double value"); } } return null; } @Nullable - static Long loadLong(String name, Map properties) + static Long loadLong(String prefix, String propertyName, PropertySource propertySource) throws PrometheusPropertiesException { - String property = getProperty(name, properties); + String property = getProperty(prefix, propertyName, propertySource); if (property != null) { + String fullKey = prefix.isEmpty() ? propertyName : prefix + "." + propertyName; try { return Long.parseLong(property); } catch (NumberFormatException e) { - throw new PrometheusPropertiesException(name + "=" + property + ": Expecting long value"); + throw new PrometheusPropertiesException( + fullKey + "=" + property + ": Expecting long value"); } } return null; } @Nullable - static Duration loadOptionalDuration(String name, Map properties) + static Duration loadOptionalDuration( + String prefix, String propertyName, PropertySource propertySource) throws PrometheusPropertiesException { - Long value = loadLong(name, properties); + Long value = loadLong(prefix, propertyName, propertySource); - assertValue(value, t -> t >= 0, "Expecting value >= 0.", null, name); + assertValue(value, t -> t >= 0, "Expecting value >= 0.", prefix, propertyName); if (value == null || value == 0) { return null; @@ -180,10 +188,11 @@ static void assertValue( Predicate predicate, String message, @Nullable String prefix, - String name) + String propertyName) throws PrometheusPropertiesException { if (number != null && !predicate.test(number)) { - String fullKey = prefix == null ? name : prefix + "." + name; + String fullKey = + (prefix == null || prefix.isEmpty()) ? propertyName : prefix + "." + propertyName; String fullMessage = String.format("%s: %s Found: %s", fullKey, message, number); throw new PrometheusPropertiesException(fullMessage); } diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExemplarsPropertiesTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExemplarsPropertiesTest.java index 53f7ae072..aa87ed105 100644 --- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExemplarsPropertiesTest.java +++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExemplarsPropertiesTest.java @@ -14,31 +14,35 @@ void load() { ExemplarsProperties properties = load( Map.of( - "io.prometheus.exemplars.minRetentionPeriodSeconds", "1", - "io.prometheus.exemplars.maxRetentionPeriodSeconds", "2", - "io.prometheus.exemplars.sampleIntervalMilliseconds", "3")); + "io.prometheus.exemplars.min_retention_period_seconds", "1", + "io.prometheus.exemplars.max_retention_period_seconds", "2", + "io.prometheus.exemplars.sample_interval_milliseconds", "3")); assertThat(properties.getMinRetentionPeriodSeconds()).isOne(); assertThat(properties.getMaxRetentionPeriodSeconds()).isEqualTo(2); assertThat(properties.getSampleIntervalMilliseconds()).isEqualTo(3); assertThatExceptionOfType(PrometheusPropertiesException.class) - .isThrownBy(() -> load(Map.of("io.prometheus.exemplars.minRetentionPeriodSeconds", "-1"))) + .isThrownBy( + () -> load(Map.of("io.prometheus.exemplars.min_retention_period_seconds", "-1"))) .withMessage( - "io.prometheus.exemplars.minRetentionPeriodSeconds: Expecting value > 0. Found: -1"); + "io.prometheus.exemplars.min_retention_period_seconds: Expecting value > 0. Found: -1"); assertThatExceptionOfType(PrometheusPropertiesException.class) - .isThrownBy(() -> load(Map.of("io.prometheus.exemplars.maxRetentionPeriodSeconds", "0"))) + .isThrownBy(() -> load(Map.of("io.prometheus.exemplars.max_retention_period_seconds", "0"))) .withMessage( - "io.prometheus.exemplars.maxRetentionPeriodSeconds: Expecting value > 0. Found: 0"); + "io.prometheus.exemplars.max_retention_period_seconds: Expecting value > 0. Found: 0"); assertThatExceptionOfType(PrometheusPropertiesException.class) - .isThrownBy(() -> load(Map.of("io.prometheus.exemplars.sampleIntervalMilliseconds", "-1"))) + .isThrownBy( + () -> load(Map.of("io.prometheus.exemplars.sample_interval_milliseconds", "-1"))) .withMessage( - "io.prometheus.exemplars.sampleIntervalMilliseconds: Expecting value > 0. Found: -1"); + "io.prometheus.exemplars.sample_interval_milliseconds: Expecting value > 0. Found: -1"); } private static ExemplarsProperties load(Map map) { - return ExemplarsProperties.load(new HashMap<>(map)); + Map regularProperties = new HashMap<>(map); + PropertySource propertySource = new PropertySource(regularProperties); + return ExemplarsProperties.load(propertySource); } @Test diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterFilterPropertiesTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterFilterPropertiesTest.java index 0b30fbd43..c7b9124af 100644 --- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterFilterPropertiesTest.java +++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterFilterPropertiesTest.java @@ -13,10 +13,10 @@ void load() { ExporterFilterProperties properties = load( Map.of( - "io.prometheus.exporter.filter.metricNameMustBeEqualTo", "a,b,c", - "io.prometheus.exporter.filter.metricNameMustNotBeEqualTo", "d,e,f", - "io.prometheus.exporter.filter.metricNameMustStartWith", "g,h,i", - "io.prometheus.exporter.filter.metricNameMustNotStartWith", "j,k,l")); + "io.prometheus.exporter.filter.metric_name_must_be_equal_to", "a,b,c", + "io.prometheus.exporter.filter.metric_name_must_not_be_equal_to", "d,e,f", + "io.prometheus.exporter.filter.metric_name_must_start_with", "g,h,i", + "io.prometheus.exporter.filter.metric_name_must_not_start_with", "j,k,l")); assertThat(properties.getAllowedMetricNames()).containsExactly("a", "b", "c"); assertThat(properties.getExcludedMetricNames()).containsExactly("d", "e", "f"); assertThat(properties.getAllowedMetricNamePrefixes()).containsExactly("g", "h", "i"); @@ -24,7 +24,9 @@ void load() { } private static ExporterFilterProperties load(Map map) { - return ExporterFilterProperties.load(new HashMap<>(map)); + Map regularProperties = new HashMap<>(map); + PropertySource propertySource = new PropertySource(regularProperties); + return ExporterFilterProperties.load(propertySource); } @Test diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterHttpServerPropertiesTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterHttpServerPropertiesTest.java index ae83c305e..fc4faf141 100644 --- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterHttpServerPropertiesTest.java +++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterHttpServerPropertiesTest.java @@ -12,13 +12,13 @@ class ExporterHttpServerPropertiesTest { @Test void load() { ExporterHttpServerProperties properties = - load(Map.of("io.prometheus.exporter.httpServer.port", "1")); + load(Map.of("io.prometheus.exporter.http_server.port", "1")); assertThat(properties.getPort()).isOne(); assertThat(properties.isPreferUncompressedResponse()).isFalse(); assertThatExceptionOfType(PrometheusPropertiesException.class) - .isThrownBy(() -> load(Map.of("io.prometheus.exporter.httpServer.port", "0"))) - .withMessage("io.prometheus.exporter.httpServer.port: Expecting value > 0. Found: 0"); + .isThrownBy(() -> load(Map.of("io.prometheus.exporter.http_server.port", "0"))) + .withMessage("io.prometheus.exporter.http_server.port: Expecting value > 0. Found: 0"); } @Test @@ -34,6 +34,8 @@ void builder() { } private static ExporterHttpServerProperties load(Map map) { - return ExporterHttpServerProperties.load(new HashMap<>(map)); + Map regularProperties = new HashMap<>(map); + PropertySource propertySource = new PropertySource(regularProperties); + return ExporterHttpServerProperties.load(propertySource); } } diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterOpenTelemetryPropertiesTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterOpenTelemetryPropertiesTest.java index 7ba275570..003fba0e6 100644 --- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterOpenTelemetryPropertiesTest.java +++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterOpenTelemetryPropertiesTest.java @@ -1,6 +1,7 @@ package io.prometheus.metrics.config; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import java.util.HashMap; import java.util.Map; @@ -16,13 +17,13 @@ void load() { "io.prometheus.exporter.opentelemetry.protocol", "grpc", "io.prometheus.exporter.opentelemetry.endpoint", "http://localhost:8080", "io.prometheus.exporter.opentelemetry.headers", "key1=value1,key2=value2", - "io.prometheus.exporter.opentelemetry.intervalSeconds", "10", - "io.prometheus.exporter.opentelemetry.timeoutSeconds", "5", - "io.prometheus.exporter.opentelemetry.serviceName", "serviceName", - "io.prometheus.exporter.opentelemetry.serviceNamespace", "serviceNamespace", - "io.prometheus.exporter.opentelemetry.serviceInstanceId", "serviceInstanceId", - "io.prometheus.exporter.opentelemetry.serviceVersion", "serviceVersion", - "io.prometheus.exporter.opentelemetry.resourceAttributes", + "io.prometheus.exporter.opentelemetry.interval_seconds", "10", + "io.prometheus.exporter.opentelemetry.timeout_seconds", "5", + "io.prometheus.exporter.opentelemetry.service_name", "serviceName", + "io.prometheus.exporter.opentelemetry.service_namespace", "serviceNamespace", + "io.prometheus.exporter.opentelemetry.service_instance_id", "serviceInstanceId", + "io.prometheus.exporter.opentelemetry.service_version", "serviceVersion", + "io.prometheus.exporter.opentelemetry.resource_attributes", "key1=value1,key2=value2")); assertValues(properties); @@ -44,7 +45,9 @@ private static void assertValues(ExporterOpenTelemetryProperties properties) { } private static ExporterOpenTelemetryProperties load(Map map) { - return ExporterOpenTelemetryProperties.load(new HashMap<>(map)); + Map regularProperties = new HashMap<>(map); + PropertySource propertySource = new PropertySource(regularProperties); + return ExporterOpenTelemetryProperties.load(propertySource); } @Test @@ -66,4 +69,40 @@ void builder() { .build(); assertValues(properties); } + + @Test + void builderWithHttpProtobuf() { + ExporterOpenTelemetryProperties properties = + ExporterOpenTelemetryProperties.builder().protocol("http/protobuf").build(); + assertThat(properties.getProtocol()).isEqualTo("http/protobuf"); + } + + @Test + void builderWithInvalidProtocol() { + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> ExporterOpenTelemetryProperties.builder().protocol("invalid")) + .withMessage("invalid: Unsupported protocol. Expecting grpc or http/protobuf"); + } + + @Test + void builderWithInvalidIntervalSeconds() { + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> ExporterOpenTelemetryProperties.builder().intervalSeconds(0)) + .withMessage("0: Expecting intervalSeconds > 0"); + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> ExporterOpenTelemetryProperties.builder().intervalSeconds(-1)) + .withMessage("-1: Expecting intervalSeconds > 0"); + } + + @Test + void builderWithInvalidTimeoutSeconds() { + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> ExporterOpenTelemetryProperties.builder().timeoutSeconds(0)) + .withMessage("0: Expecting timeoutSeconds > 0"); + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> ExporterOpenTelemetryProperties.builder().timeoutSeconds(-1)) + .withMessage("-1: Expecting timeoutSeconds > 0"); + } } diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPropertiesTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPropertiesTest.java index dec9e03a5..6cde17648 100644 --- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPropertiesTest.java +++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPropertiesTest.java @@ -15,8 +15,8 @@ void load() { load( new HashMap<>( Map.of( - "io.prometheus.exporter.includeCreatedTimestamps", "true", - "io.prometheus.exporter.exemplarsOnAllMetricTypes", "true"))); + "io.prometheus.exporter.include_created_timestamps", "true", + "io.prometheus.exporter.exemplars_on_all_metric_types", "true"))); assertThat(properties.getIncludeCreatedTimestamps()).isTrue(); assertThat(properties.getExemplarsOnAllMetricTypes()).isTrue(); @@ -25,23 +25,25 @@ void load() { () -> load( new HashMap<>( - Map.of("io.prometheus.exporter.includeCreatedTimestamps", "invalid")))) + Map.of("io.prometheus.exporter.include_created_timestamps", "invalid")))) .withMessage( - "io.prometheus.exporter.includeCreatedTimestamps: Expecting 'true' or 'false'. Found:" + "io.prometheus.exporter.include_created_timestamps: Expecting 'true' or 'false'. Found:" + " invalid"); assertThatExceptionOfType(PrometheusPropertiesException.class) .isThrownBy( () -> load( new HashMap<>( - Map.of("io.prometheus.exporter.exemplarsOnAllMetricTypes", "invalid")))) + Map.of("io.prometheus.exporter.exemplars_on_all_metric_types", "invalid")))) .withMessage( - "io.prometheus.exporter.exemplarsOnAllMetricTypes: Expecting 'true' or 'false'. Found:" + "io.prometheus.exporter.exemplars_on_all_metric_types: Expecting 'true' or 'false'. Found:" + " invalid"); } private static ExporterProperties load(Map map) { - return ExporterProperties.load(new HashMap<>(map)); + Map regularProperties = new HashMap<>(map); + PropertySource propertySource = new PropertySource(regularProperties); + return ExporterProperties.load(propertySource); } @Test @@ -54,5 +56,35 @@ void builder() { .build(); assertThat(properties.getIncludeCreatedTimestamps()).isTrue(); assertThat(properties.getExemplarsOnAllMetricTypes()).isTrue(); + assertThat(properties.getPrometheusTimestampsInMs()).isFalse(); + } + + @Test + void defaultValues() { + ExporterProperties properties = ExporterProperties.builder().build(); + assertThat(properties.getIncludeCreatedTimestamps()).isFalse(); + assertThat(properties.getExemplarsOnAllMetricTypes()).isFalse(); + assertThat(properties.getPrometheusTimestampsInMs()).isFalse(); + } + + @Test + void prometheusTimestampsInMs() { + ExporterProperties properties = + ExporterProperties.builder().prometheusTimestampsInMs(true).build(); + assertThat(properties.getPrometheusTimestampsInMs()).isTrue(); + + properties = + load(new HashMap<>(Map.of("io.prometheus.exporter.prometheus_timestamps_in_ms", "true"))); + assertThat(properties.getPrometheusTimestampsInMs()).isTrue(); + + assertThatExceptionOfType(PrometheusPropertiesException.class) + .isThrownBy( + () -> + load( + new HashMap<>( + Map.of("io.prometheus.exporter.prometheus_timestamps_in_ms", "invalid")))) + .withMessage( + "io.prometheus.exporter.prometheus_timestamps_in_ms: Expecting 'true' or 'false'. Found:" + + " invalid"); } } diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPushgatewayPropertiesTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPushgatewayPropertiesTest.java index e1e06348a..c92e6f2f9 100644 --- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPushgatewayPropertiesTest.java +++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPushgatewayPropertiesTest.java @@ -30,8 +30,54 @@ void load() { + " Found: foo"); } + @Test + void loadWithHttps() { + ExporterPushgatewayProperties properties = + load(Map.of("io.prometheus.exporter.pushgateway.scheme", "https")); + assertThat(properties.getScheme()).isEqualTo("https"); + } + + @Test + void loadWithEscapingSchemes() { + ExporterPushgatewayProperties properties = + load(Map.of("io.prometheus.exporter.pushgateway.escaping_scheme", "allow-utf-8")); + assertThat(properties.getEscapingScheme()).isEqualTo(EscapingScheme.ALLOW_UTF8); + + properties = load(Map.of("io.prometheus.exporter.pushgateway.escaping_scheme", "values")); + assertThat(properties.getEscapingScheme()).isEqualTo(EscapingScheme.VALUE_ENCODING_ESCAPING); + + properties = load(Map.of("io.prometheus.exporter.pushgateway.escaping_scheme", "underscores")); + assertThat(properties.getEscapingScheme()).isEqualTo(EscapingScheme.UNDERSCORE_ESCAPING); + + properties = load(Map.of("io.prometheus.exporter.pushgateway.escaping_scheme", "dots")); + assertThat(properties.getEscapingScheme()).isEqualTo(EscapingScheme.DOTS_ESCAPING); + } + + @Test + void loadWithInvalidEscapingScheme() { + assertThatExceptionOfType(PrometheusPropertiesException.class) + .isThrownBy( + () -> load(Map.of("io.prometheus.exporter.pushgateway.escaping_scheme", "invalid"))) + .withMessage( + "io.prometheus.exporter.pushgateway.escaping_scheme: Illegal value. Expecting" + + " 'allow-utf-8', 'values', 'underscores', or 'dots'. Found: invalid"); + } + + @Test + void loadWithTimeouts() { + ExporterPushgatewayProperties properties = + load( + Map.of( + "io.prometheus.exporter.pushgateway.connect_timeout_seconds", "5", + "io.prometheus.exporter.pushgateway.read_timeout_seconds", "10")); + assertThat(properties.getConnectTimeout()).isEqualTo(Duration.ofSeconds(5)); + assertThat(properties.getReadTimeout()).isEqualTo(Duration.ofSeconds(10)); + } + private static ExporterPushgatewayProperties load(Map map) { - return ExporterPushgatewayProperties.load(new HashMap<>(map)); + Map regularProperties = new HashMap<>(map); + PropertySource propertySource = new PropertySource(regularProperties); + return ExporterPushgatewayProperties.load(propertySource); } @Test diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/MetricsPropertiesTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/MetricsPropertiesTest.java index 4f4c56755..9f7684a8d 100644 --- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/MetricsPropertiesTest.java +++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/MetricsPropertiesTest.java @@ -47,17 +47,17 @@ void builder() { assertThatExceptionOfType(PrometheusPropertiesException.class) .isThrownBy(() -> MetricsProperties.builder().summaryNumberOfAgeBuckets(0).build()) - .withMessage(".summaryNumberOfAgeBuckets: Expecting value > 0. Found: 0"); + .withMessage("summary_number_of_age_buckets: Expecting value > 0. Found: 0"); assertThatExceptionOfType(PrometheusPropertiesException.class) .isThrownBy(() -> MetricsProperties.builder().summaryQuantiles(2L).build()) - .withMessage(".summaryQuantiles: Expecting 0.0 <= quantile <= 1.0. Found: 2.0"); + .withMessage(".summary_quantiles: Expecting 0.0 <= quantile <= 1.0. Found: 2.0"); assertThatExceptionOfType(PrometheusPropertiesException.class) .isThrownBy(() -> MetricsProperties.builder().summaryQuantileErrors(0.9).build()) .withMessage( - ".summaryQuantileErrors: Can't configure summaryQuantileErrors without configuring" - + " summaryQuantiles"); + ".summary_quantile_errors: Can't configure summary_quantile_errors without configuring" + + " summary_quantiles"); assertThatExceptionOfType(PrometheusPropertiesException.class) .isThrownBy( @@ -66,7 +66,7 @@ void builder() { .summaryQuantiles(0.1) .summaryQuantileErrors(0.1, 0.9) .build()) - .withMessage(".summaryQuantileErrors: must have the same length as summaryQuantiles"); + .withMessage("summary_quantile_errors: must have the same length as summary_quantiles"); assertThatExceptionOfType(PrometheusPropertiesException.class) .isThrownBy( @@ -75,7 +75,7 @@ void builder() { .summaryQuantiles(0.1) .summaryQuantileErrors(-0.9) .build()) - .withMessage(".summaryQuantileErrors: Expecting 0.0 <= error <= 1.0"); + .withMessage("summary_quantile_errors: Expecting 0.0 <= error <= 1.0"); } @Test @@ -114,24 +114,24 @@ void nativeBuilder() { assertThatExceptionOfType(PrometheusPropertiesException.class) .isThrownBy(() -> MetricsProperties.builder().histogramNativeInitialSchema(10).build()) .withMessage( - ".histogramNativeInitialSchema: Expecting number between -4 and +8. Found: 10"); + "histogram_native_initial_schema: Expecting number between -4 and +8. Found: 10"); assertThatExceptionOfType(PrometheusPropertiesException.class) .isThrownBy(() -> MetricsProperties.builder().histogramNativeMinZeroThreshold(-1.0).build()) - .withMessage(".histogramNativeMinZeroThreshold: Expecting value >= 0. Found: -1.0"); + .withMessage("histogram_native_min_zero_threshold: Expecting value >= 0. Found: -1.0"); assertThatExceptionOfType(PrometheusPropertiesException.class) .isThrownBy(() -> MetricsProperties.builder().histogramNativeMaxZeroThreshold(-1.0).build()) - .withMessage(".histogramNativeMaxZeroThreshold: Expecting value >= 0. Found: -1.0"); + .withMessage("histogram_native_max_zero_threshold: Expecting value >= 0. Found: -1.0"); assertThatExceptionOfType(PrometheusPropertiesException.class) .isThrownBy(() -> MetricsProperties.builder().histogramNativeMaxNumberOfBuckets(-1).build()) - .withMessage(".histogramNativeMaxNumberOfBuckets: Expecting value >= 0. Found: -1"); + .withMessage("histogram_native_max_number_of_buckets: Expecting value >= 0. Found: -1"); assertThatExceptionOfType(PrometheusPropertiesException.class) .isThrownBy( () -> MetricsProperties.builder().histogramNativeResetDurationSeconds(-1L).build()) - .withMessage(".histogramNativeResetDurationSeconds: Expecting value >= 0. Found: -1"); + .withMessage("histogram_native_reset_duration_seconds: Expecting value >= 0. Found: -1"); assertThatExceptionOfType(PrometheusPropertiesException.class) .isThrownBy( @@ -140,7 +140,7 @@ void nativeBuilder() { .histogramNativeOnly(true) .histogramClassicOnly(true) .build()) - .withMessage(".histogramNativeOnly and .histogramClassicOnly cannot both be true"); + .withMessage(".histogram_native_only and .histogram_classic_only cannot both be true"); assertThatExceptionOfType(PrometheusPropertiesException.class) .isThrownBy( @@ -150,7 +150,7 @@ void nativeBuilder() { .histogramNativeMaxZeroThreshold(0.01) .build()) .withMessage( - ".histogramNativeMinZeroThreshold cannot be greater than" - + " .histogramNativeMaxZeroThreshold"); + ".histogram_native_min_zero_threshold cannot be greater than" + + " .histogram_native_max_zero_threshold"); } } diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/PrometheusPropertiesLoaderTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/PrometheusPropertiesLoaderTest.java index cf4933acf..532b00295 100644 --- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/PrometheusPropertiesLoaderTest.java +++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/PrometheusPropertiesLoaderTest.java @@ -3,6 +3,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import java.util.HashMap; +import java.util.Map; import java.util.Properties; import org.junit.jupiter.api.Test; import org.junitpioneer.jupiter.SetSystemProperty; @@ -11,7 +13,7 @@ class PrometheusPropertiesLoaderTest { @Test - public void propertiesShouldBeLoadedFromPropertiesFile() { + void propertiesShouldBeLoadedFromPropertiesFile() { PrometheusProperties prometheusProperties = PrometheusPropertiesLoader.load(); assertThat(prometheusProperties.getDefaultMetricProperties().getHistogramClassicUpperBounds()) .hasSize(11); @@ -28,23 +30,20 @@ public void propertiesShouldBeLoadedFromPropertiesFile() { @SetSystemProperty(key = "prometheus.config", value = "nonexistent.properties") void cantLoadPropertiesFile() { assertThatExceptionOfType(PrometheusPropertiesException.class) - .isThrownBy( - () -> { - PrometheusPropertiesLoader.load(new Properties()); - }) + .isThrownBy(() -> PrometheusPropertiesLoader.load(new Properties())) .withMessage( "Failed to read Prometheus properties from nonexistent.properties:" + " nonexistent.properties"); } @Test - public void externalPropertiesShouldOverridePropertiesFile() { + void externalPropertiesShouldOverridePropertiesFile() { Properties properties = new Properties(); - properties.setProperty("io.prometheus.metrics.histogramClassicUpperBounds", ".005, .01"); + properties.setProperty("io.prometheus.metrics.histogram_classic_upper_bounds", ".005, .01"); properties.setProperty( - "io.prometheus.metrics.http_duration_seconds.histogramClassicUpperBounds", + "io.prometheus.metrics.http_duration_seconds.histogram_classic_upper_bounds", ".005, .01, .015"); - properties.setProperty("io.prometheus.exporter.exemplarsOnAllMetricTypes", "false"); + properties.setProperty("io.prometheus.exporter.exemplars_on_all_metric_types", "false"); PrometheusProperties prometheusProperties = PrometheusPropertiesLoader.load(properties); assertThat(prometheusProperties.getDefaultMetricProperties().getHistogramClassicUpperBounds()) @@ -57,4 +56,148 @@ public void externalPropertiesShouldOverridePropertiesFile() { assertThat(prometheusProperties.getExporterProperties().getExemplarsOnAllMetricTypes()) .isFalse(); } + + @Test + void environmentVariablesShouldConfigureMetrics() { + // Simulate environment variables as they would be loaded + Map envVarProperties = new HashMap<>(); + envVarProperties.put( + "io_prometheus_metrics_http_duration_seconds_histogram_classic_upper_bounds", + ".001, .005, .01"); + envVarProperties.put("io_prometheus_metrics_exemplars_enabled", "false"); + + PropertySource propertySource = + new PropertySource(new HashMap<>(), envVarProperties, new HashMap<>()); + PrometheusProperties.MetricPropertiesMap metricsConfigs = + PrometheusPropertiesLoader.loadMetricsConfigs(propertySource); + + assertThat(metricsConfigs.get("http_duration_seconds").getHistogramClassicUpperBounds()) + .hasSize(3) + .containsExactly(0.001, 0.005, 0.01); + + MetricsProperties defaultMetrics = + MetricsProperties.load("io.prometheus.metrics", propertySource); + assertThat(defaultMetrics.getExemplarsEnabled()).isFalse(); + } + + @Test + void environmentVariablesShouldHandleSnakeCaseMetricNames() { + // Simulate environment variable for metric with snake_case name + Map envVarProperties = new HashMap<>(); + envVarProperties.put("io_prometheus_metrics_http_server_histogram_native_only", "true"); + + PropertySource propertySource = + new PropertySource(new HashMap<>(), envVarProperties, new HashMap<>()); + PrometheusProperties.MetricPropertiesMap metricsConfigs = + PrometheusPropertiesLoader.loadMetricsConfigs(propertySource); + + assertThat(metricsConfigs.get("http_server").getHistogramNativeOnly()).isTrue(); + } + + @Test + void environmentVariablesShouldHandleMultipleSnakeCaseSegments() { + // Simulate environment variable for metric with multiple snake_case segments + Map envVarProperties = new HashMap<>(); + envVarProperties.put("io_prometheus_metrics_my_custom_metric_histogram_native_only", "true"); + + PropertySource propertySource = + new PropertySource(new HashMap<>(), envVarProperties, new HashMap<>()); + PrometheusProperties.MetricPropertiesMap metricsConfigs = + PrometheusPropertiesLoader.loadMetricsConfigs(propertySource); + + assertThat(metricsConfigs.get("my_custom_metric").getHistogramNativeOnly()).isTrue(); + } + + @Test + void environmentVariablesShouldHandleMetricNamesContainingPropertyKeywords() { + // Metric names can contain words like "summary" or "histogram" + // This should not confuse the parser + Map envVarProperties = new HashMap<>(); + envVarProperties.put("io_prometheus_metrics_my_summary_metric_histogram_native_only", "true"); + envVarProperties.put( + "io_prometheus_metrics_histogram_processor_summary_quantiles", "0.5, 0.95"); + + PropertySource propertySource = + new PropertySource(new HashMap<>(), envVarProperties, new HashMap<>()); + PrometheusProperties.MetricPropertiesMap metricsConfigs = + PrometheusPropertiesLoader.loadMetricsConfigs(propertySource); + + assertThat(metricsConfigs.get("my_summary_metric").getHistogramNativeOnly()).isTrue(); + assertThat(metricsConfigs.get("histogram_processor").getSummaryQuantiles()) + .containsExactly(0.5, 0.95); + } + + @Test + void regularPropertiesShouldHandleComplexMetricNames() { + // Test that suffix-based matching works correctly for regular properties + // Metric names already use underscores (exposition format) + Properties properties = new Properties(); + properties.setProperty( + "io.prometheus.metrics.http_server_requests_total.histogram_native_only", "true"); + properties.setProperty( + "io.prometheus.metrics.my_app_custom_metric.summary_quantiles", "0.5, 0.99"); + + PropertySource propertySource = new PropertySource(properties); + PrometheusProperties.MetricPropertiesMap metricsConfigs = + PrometheusPropertiesLoader.loadMetricsConfigs(propertySource); + + assertThat(metricsConfigs.get("http_server_requests_total").getHistogramNativeOnly()).isTrue(); + assertThat(metricsConfigs.get("my_app_custom_metric").getSummaryQuantiles()) + .containsExactly(0.5, 0.99); + } + + @Test + void normalizePropertyKeyShouldConvertCamelCaseToSnakeCase() { + // Test that camelCase keys are correctly converted to snake_case for backward compatibility + assertThat( + PrometheusPropertiesLoader.normalizePropertyKey( + "io.prometheus.exporter.httpServer.port")) + .isEqualTo("io.prometheus.exporter.http_server.port"); + assertThat( + PrometheusPropertiesLoader.normalizePropertyKey( + "io.prometheus.metrics.exemplarsEnabled")) + .isEqualTo("io.prometheus.metrics.exemplars_enabled"); + assertThat( + PrometheusPropertiesLoader.normalizePropertyKey( + "io.prometheus.exporter.openTelemetry.serviceName")) + .isEqualTo("io.prometheus.exporter.open_telemetry.service_name"); + + // Test that snake_case keys remain unchanged + assertThat( + PrometheusPropertiesLoader.normalizePropertyKey( + "io.prometheus.exporter.http_server.port")) + .isEqualTo("io.prometheus.exporter.http_server.port"); + assertThat( + PrometheusPropertiesLoader.normalizePropertyKey( + "io.prometheus.metrics.exemplars_enabled")) + .isEqualTo("io.prometheus.metrics.exemplars_enabled"); + } + + @Test + void environmentVariablesShouldHaveCorrectPrecedence() { + // Test that environment variables override system properties and files, + // but are overridden by external properties + Properties fileProperties = new Properties(); + fileProperties.setProperty("io.prometheus.metrics.histogram_native_only", "false"); + + Map envVarProperties = new HashMap<>(); + envVarProperties.put("io_prometheus_metrics_histogram_native_only", "true"); + + Map externalProperties = new HashMap<>(); + externalProperties.put("io.prometheus.metrics.histogram_native_only", "false"); + + // Test that env vars override file properties + PropertySource propertySourceWithEnv = + new PropertySource(new HashMap<>(), envVarProperties, fileProperties); + MetricsProperties metricsWithEnv = + MetricsProperties.load("io.prometheus.metrics", propertySourceWithEnv); + assertThat(metricsWithEnv.getHistogramNativeOnly()).isTrue(); + + // Test that external properties override env vars + PropertySource propertySourceWithExternal = + new PropertySource(externalProperties, envVarProperties, fileProperties); + MetricsProperties metricsWithExternal = + MetricsProperties.load("io.prometheus.metrics", propertySourceWithExternal); + assertThat(metricsWithExternal.getHistogramNativeOnly()).isFalse(); + } } diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/PrometheusPropertiesTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/PrometheusPropertiesTest.java index d0205b28e..3e891202a 100644 --- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/PrometheusPropertiesTest.java +++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/PrometheusPropertiesTest.java @@ -6,13 +6,14 @@ import java.io.InputStream; import java.util.Collections; import java.util.HashMap; +import java.util.Map; import java.util.Properties; import org.junit.jupiter.api.Test; class PrometheusPropertiesTest { @Test - public void testPrometheusConfig() { + void testPrometheusConfig() { PrometheusProperties result = PrometheusProperties.get(); assertThat(result.getDefaultMetricProperties().getHistogramClassicUpperBounds()).hasSize(11); assertThat(result.getMetricProperties("http_duration_seconds").getHistogramClassicUpperBounds()) @@ -20,7 +21,7 @@ public void testPrometheusConfig() { } @Test - public void testEmptyUpperBounds() throws IOException { + void testEmptyUpperBounds() throws IOException { Properties properties = new Properties(); try (InputStream stream = Thread.currentThread() @@ -29,12 +30,14 @@ public void testEmptyUpperBounds() throws IOException { properties.load(stream); } assertThat(properties).hasSize(1); - MetricsProperties.load("io.prometheus.metrics", properties); - assertThat(properties).isEmpty(); + Map regularProperties = new HashMap<>(properties); + PropertySource propertySource = new PropertySource(regularProperties); + MetricsProperties.load("io.prometheus.metrics", propertySource); + assertThat(regularProperties).isEmpty(); } @Test - public void testBuilder() { + void testBuilder() { PrometheusProperties defaults = PrometheusPropertiesLoader.load(new HashMap<>()); PrometheusProperties.Builder builder = PrometheusProperties.builder(); builder.defaultMetricsProperties(defaults.getDefaultMetricProperties()); @@ -67,4 +70,62 @@ public void testBuilder() { assertThat(result.getMetricProperties("unknown_metric")).isNull(); assertThat(result.getExporterProperties()).isSameAs(defaults.getExporterProperties()); } + + @Test + void testMetricNameNormalization() { + PrometheusProperties.Builder builder = PrometheusProperties.builder(); + MetricsProperties customProps = + MetricsProperties.builder().histogramClassicUpperBounds(0.1, 0.5).build(); + + // Test that metric names with dots are normalized to underscores + builder.putMetricProperty("my.metric.name", customProps); + PrometheusProperties result = builder.build(); + + // Should be able to retrieve with dots + assertThat(result.getMetricProperties("my.metric.name")).isSameAs(customProps); + // Should also be able to retrieve with underscores + assertThat(result.getMetricProperties("my_metric_name")).isSameAs(customProps); + } + + @Test + void testMetricNameWithInvalidCharacters() { + PrometheusProperties.Builder builder = PrometheusProperties.builder(); + MetricsProperties customProps = + MetricsProperties.builder().histogramClassicUpperBounds(0.1, 0.5).build(); + + // Test that invalid characters are converted to underscores + builder.putMetricProperty("metric-name@with#invalid$chars", customProps); + PrometheusProperties result = builder.build(); + + // Should normalize invalid characters to underscores + assertThat(result.getMetricProperties("metric-name@with#invalid$chars")).isSameAs(customProps); + assertThat(result.getMetricProperties("metric_name_with_invalid_chars")).isSameAs(customProps); + } + + @Test + void testMetricNameWithValidCharacters() { + PrometheusProperties.Builder builder = PrometheusProperties.builder(); + MetricsProperties customProps = + MetricsProperties.builder().histogramClassicUpperBounds(0.1, 0.5).build(); + + // Test valid characters: letters, numbers (not at start), underscore, colon + builder.putMetricProperty("my_metric:name123", customProps); + PrometheusProperties result = builder.build(); + + assertThat(result.getMetricProperties("my_metric:name123")).isSameAs(customProps); + } + + @Test + void testMetricNameStartingWithNumber() { + PrometheusProperties.Builder builder = PrometheusProperties.builder(); + MetricsProperties customProps = + MetricsProperties.builder().histogramClassicUpperBounds(0.1, 0.5).build(); + + // First digit is invalid (i=0), but subsequent digits are valid (i>0) + builder.putMetricProperty("123metric", customProps); + PrometheusProperties result = builder.build(); + + assertThat(result.getMetricProperties("123metric")).isSameAs(customProps); + assertThat(result.getMetricProperties("_23metric")).isSameAs(customProps); + } } diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/UtilTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/UtilTest.java index 23ffbd33b..e4d7fa829 100644 --- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/UtilTest.java +++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/UtilTest.java @@ -11,40 +11,46 @@ class UtilTest { @Test void loadOptionalDuration_positive() { - Map properties = new HashMap<>(Map.of("foo", "5")); + Map regularProperties = new HashMap<>(Map.of("foo", "5")); + PropertySource propertySource = new PropertySource(regularProperties); - assertThat(Util.loadOptionalDuration("foo", properties)).isEqualTo(Duration.ofSeconds(5)); + assertThat(Util.loadOptionalDuration("", "foo", propertySource)) + .isEqualTo(Duration.ofSeconds(5)); } @Test void loadOptionalDuration_zero() { - Map properties = new HashMap<>(Map.of("foo", "0")); + Map regularProperties = new HashMap<>(Map.of("foo", "0")); + PropertySource propertySource = new PropertySource(regularProperties); - assertThat(Util.loadOptionalDuration("foo", properties)).isNull(); + assertThat(Util.loadOptionalDuration("", "foo", propertySource)).isNull(); } @Test void loadOptionalDuration_missing() { - Map properties = new HashMap<>(); + Map regularProperties = new HashMap<>(); + PropertySource propertySource = new PropertySource(regularProperties); - assertThat(Util.loadOptionalDuration("foo", properties)).isNull(); + assertThat(Util.loadOptionalDuration("", "foo", propertySource)).isNull(); } @Test void loadOptionalDuration_negative_throws() { - Map properties = new HashMap<>(Map.of("foo", "-1")); + Map regularProperties = new HashMap<>(Map.of("foo", "-1")); + PropertySource propertySource = new PropertySource(regularProperties); assertThatExceptionOfType(PrometheusPropertiesException.class) - .isThrownBy(() -> Util.loadOptionalDuration("foo", properties)) + .isThrownBy(() -> Util.loadOptionalDuration("", "foo", propertySource)) .withMessage("foo: Expecting value >= 0. Found: -1"); } @Test void loadOptionalDuration_invalidNumber_throws() { - Map properties = new HashMap<>(Map.of("foo", "abc")); + Map regularProperties = new HashMap<>(Map.of("foo", "abc")); + PropertySource propertySource = new PropertySource(regularProperties); assertThatExceptionOfType(PrometheusPropertiesException.class) - .isThrownBy(() -> Util.loadOptionalDuration("foo", properties)) + .isThrownBy(() -> Util.loadOptionalDuration("", "foo", propertySource)) .withMessage("foo=abc: Expecting long value"); } } diff --git a/prometheus-metrics-config/src/test/resources/emptyUpperBounds.properties b/prometheus-metrics-config/src/test/resources/emptyUpperBounds.properties index c019761ca..d8c1a3515 100644 --- a/prometheus-metrics-config/src/test/resources/emptyUpperBounds.properties +++ b/prometheus-metrics-config/src/test/resources/emptyUpperBounds.properties @@ -1 +1 @@ -io.prometheus.metrics.histogramClassicUpperBounds =, +io.prometheus.metrics.histogram_classic_upper_bounds =, diff --git a/prometheus-metrics-config/src/test/resources/prometheus.properties b/prometheus-metrics-config/src/test/resources/prometheus.properties index 13a5d9e39..e5469803f 100644 --- a/prometheus-metrics-config/src/test/resources/prometheus.properties +++ b/prometheus-metrics-config/src/test/resources/prometheus.properties @@ -1,26 +1,26 @@ -io.prometheus.metrics.histogramClassicUpperBounds = .005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10 -io.prometheus.metrics.http_duration_seconds.histogramClassicUpperBounds = .005, .01, .015, .02 -io.prometheus.metrics.summaryQuantiles = 0.5, 0.95, 0.99 -io.prometheus.metrics.summaryQuantileErrors = 0.01, 0.01, 0.001 +io.prometheus.metrics.histogram_classic_upper_bounds = .005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10 +io.prometheus.metrics.http_duration_seconds.histogram_classic_upper_bounds = .005, .01, .015, .02 +io.prometheus.metrics.summary_quantiles = 0.5, 0.95, 0.99 +io.prometheus.metrics.summary_quantile_errors = 0.01, 0.01, 0.001 -io.prometheus.metrics.exemplarsEnabled = true -io.prometheus.metrics.http_duration_seconds.exemplarsEnabled = true +io.prometheus.metrics.exemplars_enabled = true +io.prometheus.metrics.http_duration_seconds.exemplars_enabled = true -io.prometheus.exporter.includeCreatedTimestamps = false -io.prometheus.exporter.exemplarsOnAllMetricTypes = true -io.prometheus.exporter.filter.metricNameMustBeEqualTo = a, b, c +io.prometheus.exporter.include_created_timestamps = false +io.prometheus.exporter.exemplars_on_all_metric_types = true +io.prometheus.exporter.filter.metric_name_must_be_equal_to = a, b, c -io.prometheus.exemplars.minRetentionPeriodSeconds = 30 -io.prometheus.exemplars.maxRetentionPeriodSeconds = 30 -io.prometheus.exemplars.sampleIntervalMilliseconds = 30 +io.prometheus.exemplars.min_retention_period_seconds = 30 +io.prometheus.exemplars.max_retention_period_seconds = 30 +io.prometheus.exemplars.sample_interval_milliseconds = 30 -io.prometheus.exporter.httpServer.port = 9000 +io.prometheus.exporter.http_server.port = 9000 io.prometheus.exporter.opentelemetry.endpoint=http://localhost:4318 -io.prometheus.exporter.opentelemetry.intervalSeconds=30 -io.prometheus.exporter.opentelemetry.serviceName=hello-world-app -io.prometheus.exporter.opentelemetry.serviceNamespace=prod -io.prometheus.exporter.opentelemetry.serviceInstanceId=localhost:8081 +io.prometheus.exporter.opentelemetry.interval_seconds=30 +io.prometheus.exporter.opentelemetry.service_name=hello-world-app +io.prometheus.exporter.opentelemetry.service_namespace=prod +io.prometheus.exporter.opentelemetry.service_instance_id=localhost:8081 -# io.prometheus.metrics.unusedLabelsRetentionTimeSeconds = 0 +# io.prometheus.metrics.unused_labels_retention_time_seconds = 0 diff --git a/prometheus-metrics-core/pom.xml b/prometheus-metrics-core/pom.xml index 3a61050de..b64c5db54 100644 --- a/prometheus-metrics-core/pom.xml +++ b/prometheus-metrics-core/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-core @@ -38,10 +38,10 @@ ${project.version} - + io.prometheus - prometheus-metrics-exposition-formats + prometheus-metrics-exposition-formats-no-protobuf ${project.version} test diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Buffer.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Buffer.java index d4ff33a37..1c47f867c 100644 --- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Buffer.java +++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Buffer.java @@ -18,7 +18,15 @@ class Buffer { private static final long bufferActiveBit = 1L << 63; - private final AtomicLong observationCount = new AtomicLong(0); + // Tracking observation counts requires an AtomicLong for coordination between recording and + // collecting. AtomicLong does much worse under contention than the LongAdder instances used + // elsewhere to hold aggregated state. To improve, we stripe the AtomicLong into N instances, + // where N is the number of available processors. Each record operation chooses the appropriate + // instance to use based on the modulo of its thread id and N. This is a more naive / simple + // implementation compared to the striping used under the hood in java.util.concurrent classes + // like LongAdder - contention and hot spots can still occur if recording thread ids happen to + // resolve to the same index. Further improvement is possible. + private final AtomicLong[] stripedObservationCounts; private double[] observationBuffer = new double[0]; private int bufferPos = 0; private boolean reset = false; @@ -27,8 +35,17 @@ class Buffer { ReentrantLock runLock = new ReentrantLock(); Condition bufferFilled = appendLock.newCondition(); + Buffer() { + stripedObservationCounts = new AtomicLong[Runtime.getRuntime().availableProcessors()]; + for (int i = 0; i < stripedObservationCounts.length; i++) { + stripedObservationCounts[i] = new AtomicLong(0); + } + } + boolean append(double value) { - long count = observationCount.incrementAndGet(); + int index = Math.abs((int) Thread.currentThread().getId()) % stripedObservationCounts.length; + AtomicLong observationCountForThread = stripedObservationCounts[index]; + long count = observationCountForThread.incrementAndGet(); if ((count & bufferActiveBit) == 0) { return false; // sign bit not set -> buffer not active. } else { @@ -69,7 +86,10 @@ T run( runLock.lock(); try { // Signal that the buffer is active. - Long expectedCount = observationCount.getAndAdd(bufferActiveBit); + long expectedCount = 0L; + for (AtomicLong observationCount : stripedObservationCounts) { + expectedCount += observationCount.getAndAdd(bufferActiveBit); + } while (!complete.apply(expectedCount)) { // Wait until all in-flight threads have added their observations to the histogram / @@ -81,14 +101,18 @@ T run( result = createResult.get(); // Signal that the buffer is inactive. - int expectedBufferSize; + long expectedBufferSize = 0; if (reset) { - expectedBufferSize = - (int) ((observationCount.getAndSet(0) & ~bufferActiveBit) - expectedCount); + for (AtomicLong observationCount : stripedObservationCounts) { + expectedBufferSize += observationCount.getAndSet(0) & ~bufferActiveBit; + } reset = false; } else { - expectedBufferSize = (int) (observationCount.addAndGet(bufferActiveBit) - expectedCount); + for (AtomicLong observationCount : stripedObservationCounts) { + expectedBufferSize += observationCount.addAndGet(bufferActiveBit); + } } + expectedBufferSize -= expectedCount; appendLock.lock(); try { diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Counter.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Counter.java index a2bac20d2..c5f2f1cff 100644 --- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Counter.java +++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Counter.java @@ -5,6 +5,7 @@ import io.prometheus.metrics.core.datapoints.CounterDataPoint; import io.prometheus.metrics.core.exemplars.ExemplarSampler; import io.prometheus.metrics.core.exemplars.ExemplarSamplerConfig; +import io.prometheus.metrics.model.registry.MetricType; import io.prometheus.metrics.model.snapshots.CounterSnapshot; import io.prometheus.metrics.model.snapshots.Exemplar; import io.prometheus.metrics.model.snapshots.Labels; @@ -92,6 +93,11 @@ protected CounterSnapshot collect(List labels, List metricDat return new CounterSnapshot(getMetadata(), data); } + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + @Override protected DataPoint newDataPoint() { if (exemplarSamplerConfig != null) { diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/CounterWithCallback.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/CounterWithCallback.java index 044644ec5..3a818c004 100644 --- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/CounterWithCallback.java +++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/CounterWithCallback.java @@ -1,6 +1,7 @@ package io.prometheus.metrics.core.metrics; import io.prometheus.metrics.config.PrometheusProperties; +import io.prometheus.metrics.model.registry.MetricType; import io.prometheus.metrics.model.snapshots.CounterSnapshot; import java.util.ArrayList; import java.util.Collections; @@ -50,6 +51,11 @@ public CounterSnapshot collect() { return new CounterSnapshot(getMetadata(), dataPoints); } + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + public static Builder builder() { return new Builder(PrometheusProperties.get()); } diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Gauge.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Gauge.java index 5850a1cfe..8b1f31409 100644 --- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Gauge.java +++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Gauge.java @@ -5,6 +5,7 @@ import io.prometheus.metrics.core.datapoints.GaugeDataPoint; import io.prometheus.metrics.core.exemplars.ExemplarSampler; import io.prometheus.metrics.core.exemplars.ExemplarSamplerConfig; +import io.prometheus.metrics.model.registry.MetricType; import io.prometheus.metrics.model.snapshots.Exemplar; import io.prometheus.metrics.model.snapshots.GaugeSnapshot; import io.prometheus.metrics.model.snapshots.Labels; @@ -94,6 +95,11 @@ protected GaugeSnapshot collect(List labels, List metricData) return new GaugeSnapshot(getMetadata(), dataPointSnapshots); } + @Override + public MetricType getMetricType() { + return MetricType.GAUGE; + } + @Override protected DataPoint newDataPoint() { if (exemplarSamplerConfig != null) { diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/GaugeWithCallback.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/GaugeWithCallback.java index 82f26afe1..88aee225f 100644 --- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/GaugeWithCallback.java +++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/GaugeWithCallback.java @@ -1,6 +1,7 @@ package io.prometheus.metrics.core.metrics; import io.prometheus.metrics.config.PrometheusProperties; +import io.prometheus.metrics.model.registry.MetricType; import io.prometheus.metrics.model.snapshots.GaugeSnapshot; import java.util.ArrayList; import java.util.Collections; @@ -54,6 +55,11 @@ public GaugeSnapshot collect() { return new GaugeSnapshot(getMetadata(), dataPoints); } + @Override + public MetricType getMetricType() { + return MetricType.GAUGE; + } + public static Builder builder() { return new Builder(PrometheusProperties.get()); } diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Histogram.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Histogram.java index 85f6225d3..930d9e67e 100644 --- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Histogram.java +++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Histogram.java @@ -7,6 +7,7 @@ import io.prometheus.metrics.core.exemplars.ExemplarSampler; import io.prometheus.metrics.core.exemplars.ExemplarSamplerConfig; import io.prometheus.metrics.core.util.Scheduler; +import io.prometheus.metrics.model.registry.MetricType; import io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets; import io.prometheus.metrics.model.snapshots.Exemplars; import io.prometheus.metrics.model.snapshots.HistogramSnapshot; @@ -649,6 +650,11 @@ protected HistogramSnapshot collect(List labels, List metricD return new HistogramSnapshot(getMetadata(), data); } + @Override + public MetricType getMetricType() { + return MetricType.HISTOGRAM; + } + @Override protected DataPoint newDataPoint() { return new DataPoint(); @@ -962,11 +968,18 @@ public Builder nativeMaxNumberOfBuckets(int nativeMaxBuckets) { *

Default is no reset. */ public Builder nativeResetDuration(long duration, TimeUnit unit) { - // TODO: reset interval isn't tested yet if (duration <= 0) { throw new IllegalArgumentException(duration + ": value > 0 expected"); } - nativeResetDurationSeconds = unit.toSeconds(duration); + long seconds = unit.toSeconds(duration); + if (seconds == 0) { + throw new IllegalArgumentException( + duration + + " " + + unit + + ": duration must be at least 1 second. Sub-second durations are not supported."); + } + nativeResetDurationSeconds = seconds; return this; } diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Info.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Info.java index d7aa6be70..011f0bb73 100644 --- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Info.java +++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Info.java @@ -1,6 +1,7 @@ package io.prometheus.metrics.core.metrics; import io.prometheus.metrics.config.PrometheusProperties; +import io.prometheus.metrics.model.registry.MetricType; import io.prometheus.metrics.model.snapshots.InfoSnapshot; import io.prometheus.metrics.model.snapshots.Labels; import io.prometheus.metrics.model.snapshots.Unit; @@ -105,6 +106,11 @@ public InfoSnapshot collect() { return new InfoSnapshot(getMetadata(), data); } + @Override + public MetricType getMetricType() { + return MetricType.INFO; + } + public static Builder builder() { return new Builder(PrometheusProperties.get()); } diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/MetricWithFixedMetadata.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/MetricWithFixedMetadata.java index 6f6afa482..12c48c51d 100644 --- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/MetricWithFixedMetadata.java +++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/MetricWithFixedMetadata.java @@ -1,12 +1,15 @@ package io.prometheus.metrics.core.metrics; import io.prometheus.metrics.config.PrometheusProperties; +import io.prometheus.metrics.model.snapshots.Label; import io.prometheus.metrics.model.snapshots.Labels; import io.prometheus.metrics.model.snapshots.MetricMetadata; import io.prometheus.metrics.model.snapshots.PrometheusNaming; import io.prometheus.metrics.model.snapshots.Unit; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import javax.annotation.Nullable; /** @@ -27,7 +30,8 @@ protected MetricWithFixedMetadata(Builder builder) { this.labelNames = Arrays.copyOf(builder.labelNames, builder.labelNames.length); } - protected MetricMetadata getMetadata() { + @Override + public MetricMetadata getMetadata() { return metadata; } @@ -48,6 +52,18 @@ public String getPrometheusName() { return metadata.getPrometheusName(); } + @Override + public Set getLabelNames() { + Set names = new HashSet<>(); + for (String labelName : labelNames) { + names.add(PrometheusNaming.prometheusName(labelName)); + } + for (Label label : constLabels) { + names.add(PrometheusNaming.prometheusName(label.getName())); + } + return names; + } + public abstract static class Builder, M extends MetricWithFixedMetadata> extends Metric.Builder { diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/SlidingWindow.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/SlidingWindow.java index 5360e3349..e56134d5d 100644 --- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/SlidingWindow.java +++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/SlidingWindow.java @@ -15,8 +15,16 @@ *

It is implemented in a generic way so that 3rd party libraries can use it for implementing * sliding windows. * - *

TODO: The current implementation is {@code synchronized}. There is likely room for - * optimization. + *

Thread Safety: This class uses coarse-grained {@code synchronized} methods for + * simplicity and correctness. All public methods ({@link #current()} and {@link #observe(double)}) + * are synchronized, which ensures thread-safe access to the ring buffer and rotation logic. + * + *

Performance Note: The synchronized approach may cause contention under high-frequency + * observations. + * + *

However, given that Summary metrics are less commonly used (Histogram is generally preferred), + * and the observation frequency is typically lower than Counter increments, the current + * implementation provides an acceptable trade-off between simplicity and performance. */ public class SlidingWindow { diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/StateSet.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/StateSet.java index 4dbaf8ad5..740183f31 100644 --- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/StateSet.java +++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/StateSet.java @@ -4,6 +4,7 @@ import io.prometheus.metrics.config.PrometheusProperties; import io.prometheus.metrics.core.datapoints.StateSetDataPoint; +import io.prometheus.metrics.model.registry.MetricType; import io.prometheus.metrics.model.snapshots.Labels; import io.prometheus.metrics.model.snapshots.StateSetSnapshot; import java.util.ArrayList; @@ -84,6 +85,11 @@ protected StateSetSnapshot collect(List labels, List metricDa return new StateSetSnapshot(getMetadata(), data); } + @Override + public MetricType getMetricType() { + return MetricType.STATESET; + } + @Override public void setTrue(String state) { getNoLabels().setTrue(state); diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Summary.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Summary.java index 7d964dbb6..47b6e2a9c 100644 --- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Summary.java +++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Summary.java @@ -7,6 +7,7 @@ import io.prometheus.metrics.core.datapoints.DistributionDataPoint; import io.prometheus.metrics.core.exemplars.ExemplarSampler; import io.prometheus.metrics.core.exemplars.ExemplarSamplerConfig; +import io.prometheus.metrics.model.registry.MetricType; import io.prometheus.metrics.model.snapshots.Exemplars; import io.prometheus.metrics.model.snapshots.Labels; import io.prometheus.metrics.model.snapshots.Quantile; @@ -118,6 +119,11 @@ protected SummarySnapshot collect(List labels, List metricDat return new SummarySnapshot(getMetadata(), data); } + @Override + public MetricType getMetricType() { + return MetricType.SUMMARY; + } + @Override protected DataPoint newDataPoint() { return new DataPoint(); @@ -202,7 +208,13 @@ private void doObserve(double amount) { private SummarySnapshot.SummaryDataPointSnapshot collect(Labels labels) { return buffer.run( expectedCount -> count.sum() == expectedCount, - // TODO Exemplars (are hard-coded as empty in the line below) + // Note: Exemplars are currently hard-coded as empty for Summary metrics. + // While exemplars are sampled during observe() and observeWithExemplar() calls + // via the exemplarSampler field, they are not included in the snapshot to maintain + // consistency with the buffering mechanism. The buffer.run() ensures atomic + // collection of count, sum, and quantiles. Adding exemplars would require + // coordination between the buffer and exemplarSampler, which could impact + // performance. Consider using Histogram instead if exemplars are needed. () -> new SummarySnapshot.SummaryDataPointSnapshot( count.sum(), diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/SummaryWithCallback.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/SummaryWithCallback.java index 3c4a910ea..fa823e68e 100644 --- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/SummaryWithCallback.java +++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/SummaryWithCallback.java @@ -1,6 +1,7 @@ package io.prometheus.metrics.core.metrics; import io.prometheus.metrics.config.PrometheusProperties; +import io.prometheus.metrics.model.registry.MetricType; import io.prometheus.metrics.model.snapshots.Exemplars; import io.prometheus.metrics.model.snapshots.Quantiles; import io.prometheus.metrics.model.snapshots.SummarySnapshot; @@ -63,6 +64,11 @@ public SummarySnapshot collect() { return new SummarySnapshot(getMetadata(), dataPoints); } + @Override + public MetricType getMetricType() { + return MetricType.SUMMARY; + } + public static Builder builder() { return new Builder(PrometheusProperties.get()); } diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/exemplars/ExemplarSamplerTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/exemplars/ExemplarSamplerTest.java index 059929c22..8ba1370da 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/exemplars/ExemplarSamplerTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/exemplars/ExemplarSamplerTest.java @@ -52,24 +52,24 @@ public void markCurrentSpanAsExemplar() {} } @Test - public void testCustomExemplarsBuckets() throws Exception { + void testCustomExemplarsBuckets() throws Exception { // TODO } private io.prometheus.metrics.tracer.common.SpanContext origContext; @BeforeEach - public void setUp() { + void setUp() { origContext = SpanContextSupplier.getSpanContext(); } @AfterEach - public void tearDown() { + void tearDown() { SpanContextSupplier.setSpanContext(origContext); } @Test - public void testIsSampled() throws Exception { + void testIsSampled() throws Exception { SpanContext context = new SpanContext(); context.isSampled = false; ExemplarSampler sampler = new ExemplarSampler(makeConfig(), context); @@ -79,7 +79,7 @@ public void testIsSampled() throws Exception { } @Test - public void testDefaultConfigHasFourExemplars() throws Exception { + void testDefaultConfigHasFourExemplars() throws Exception { ExemplarSampler sampler = new ExemplarSampler(makeConfig(), new SpanContext()); Thread.sleep(tick); // t = 1 tick sampler.observe(0.3); @@ -96,7 +96,7 @@ public void testDefaultConfigHasFourExemplars() throws Exception { } @Test - public void testEmptyBuckets() throws Exception { + void testEmptyBuckets() throws Exception { ExemplarSampler sampler = new ExemplarSampler(makeConfig(Double.POSITIVE_INFINITY), new SpanContext()); Thread.sleep(tick); // t = 1 tick @@ -108,7 +108,7 @@ public void testEmptyBuckets() throws Exception { } @Test - public void testDefaultExemplarsBuckets() throws Exception { + void testDefaultExemplarsBuckets() throws Exception { ExemplarSampler sampler = new ExemplarSampler( makeConfig(0.2, 0.4, 0.6, 0.8, 1.0, Double.POSITIVE_INFINITY), new SpanContext()); @@ -136,12 +136,12 @@ public void testDefaultExemplarsBuckets() throws Exception { } @Test - public void testCustomExemplarsNoBuckets() throws Exception { + void testCustomExemplarsNoBuckets() throws Exception { // TODO } @Test - public void testDefaultExemplarsNoBuckets() throws Exception { + void testDefaultExemplarsNoBuckets() throws Exception { ExemplarSampler sampler = new ExemplarSampler(makeConfig(), new SpanContext()); Scheduler.awaitInitialization(); Thread.sleep(tick); // t = 1 tick diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/exemplars/SpanContextSupplierTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/exemplars/SpanContextSupplierTest.java index 6c89b48a5..5ddfb2ad5 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/exemplars/SpanContextSupplierTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/exemplars/SpanContextSupplierTest.java @@ -51,12 +51,12 @@ public void markCurrentSpanAsExemplar() {} ); @BeforeEach - public void setUp() { + void setUp() { origSpanContext = SpanContextSupplier.getSpanContext(); } @AfterEach - public void tearDown() { + void tearDown() { SpanContextSupplier.setSpanContext(origSpanContext); } @@ -66,7 +66,7 @@ public void tearDown() { * SpanContextSupplier}. */ @Test - public void testConstructorInjection() { + void testConstructorInjection() { ExemplarsProperties properties = ExemplarsProperties.builder().build(); ExemplarSamplerConfig config = new ExemplarSamplerConfig(properties, 1); ExemplarSampler exemplarSampler = new ExemplarSampler(config, spanContextA); @@ -86,7 +86,7 @@ public void testConstructorInjection() { * ExemplarSampler}). */ @Test - public void testUpdateSpanContext() throws InterruptedException { + void testUpdateSpanContext() throws InterruptedException { ExemplarSampler exemplarSampler = new ExemplarSampler(config); SpanContextSupplier.setSpanContext(spanContextB); diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CKMSQuantilesTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CKMSQuantilesTest.java index bd6b177a4..5a7fd7f48 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CKMSQuantilesTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CKMSQuantilesTest.java @@ -20,13 +20,13 @@ class CKMSQuantilesTest { private final Quantile qMax = new Quantile(1.0, 0.00); @Test - public void testGetOnEmptyValues() { + void testGetOnEmptyValues() { CKMSQuantiles ckms = new CKMSQuantiles(q50, q95, q99); assertThat(Double.isNaN(ckms.get(q95.quantile))).isTrue(); } @Test - public void testGet() { + void testGet() { Random random = new Random(0); CKMSQuantiles ckms = new CKMSQuantiles(q50, q95, q99); List input = shuffledValues(100, random); @@ -37,7 +37,7 @@ public void testGet() { } @Test - public void testBatchInsert() { + void testBatchInsert() { Random random = new Random(1); testInsertBatch(1, 1, 100, random); testInsertBatch(1, 10, 100, random); @@ -87,7 +87,7 @@ private void testInsertBatch( } @Test - public void testGetWithAMillionElements() { + void testGetWithAMillionElements() { Random random = new Random(2); List input = shuffledValues(1000 * 1000, random); CKMSQuantiles ckms = new CKMSQuantiles(q50, q95, q99); @@ -99,7 +99,7 @@ public void testGetWithAMillionElements() { } @Test - public void testMin() { + void testMin() { Random random = new Random(3); List input = shuffledValues(1000, random); CKMSQuantiles ckms = new CKMSQuantiles(qMin); @@ -112,7 +112,7 @@ public void testMin() { } @Test - public void testMax() { + void testMax() { Random random = new Random(4); List input = shuffledValues(1000, random); CKMSQuantiles ckms = new CKMSQuantiles(qMax); @@ -125,7 +125,7 @@ public void testMax() { } @Test - public void testMinMax() { + void testMinMax() { Random random = new Random(5); List input = shuffledValues(1000, random); CKMSQuantiles ckms = new CKMSQuantiles(qMin, qMax); @@ -138,7 +138,7 @@ public void testMinMax() { } @Test - public void testMinAndOthers() { + void testMinAndOthers() { Random random = new Random(6); List input = shuffledValues(1000, random); CKMSQuantiles ckms = new CKMSQuantiles(q95, qMin); @@ -150,7 +150,7 @@ public void testMinAndOthers() { } @Test - public void testMaxAndOthers() { + void testMaxAndOthers() { Random random = new Random(7); List input = shuffledValues(10000, random); CKMSQuantiles ckms = new CKMSQuantiles(q50, q95, qMax); @@ -162,7 +162,7 @@ public void testMaxAndOthers() { } @Test - public void testMinMaxAndOthers() { + void testMinMaxAndOthers() { Random random = new Random(8); List input = shuffledValues(10000, random); CKMSQuantiles ckms = new CKMSQuantiles(qMin, q50, q95, q99, qMax); @@ -174,7 +174,7 @@ public void testMinMaxAndOthers() { } @Test - public void testExactQuantile() { + void testExactQuantile() { Random random = new Random(9); List input = shuffledValues(10000, random); CKMSQuantiles ckms = new CKMSQuantiles(new Quantile(0.95, 0)); @@ -187,7 +187,7 @@ public void testExactQuantile() { } @Test - public void testExactAndOthers() { + void testExactAndOthers() { Random random = new Random(10); List input = shuffledValues(10000, random); CKMSQuantiles ckms = new CKMSQuantiles(q50, new Quantile(0.95, 0), q99); @@ -200,7 +200,7 @@ public void testExactAndOthers() { } @Test - public void testExactAndMin() { + void testExactAndMin() { Random random = new Random(11); List input = shuffledValues(10000, random); CKMSQuantiles ckms = new CKMSQuantiles(qMin, q50, new Quantile(0.95, 0)); @@ -213,7 +213,7 @@ public void testExactAndMin() { } @Test - public void testMaxEpsilon() { + void testMaxEpsilon() { Random random = new Random(12); List input = shuffledValues(10000, random); // epsilon == 1 basically gives you random results, but it should still not throw an exception. @@ -225,7 +225,7 @@ public void testMaxEpsilon() { } @Test - public void testGetGaussian() { + void testGetGaussian() { RandomGenerator rand = new JDKRandomGenerator(); rand.setSeed(0); @@ -284,7 +284,7 @@ public void testGetGaussian() { } @Test - public void testIllegalArgumentException() { + void testIllegalArgumentException() { try { new Quantile(-1, 0); } catch (IllegalArgumentException e) { diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CounterTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CounterTest.java index 8532ebcb8..b6d6779d7 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CounterTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CounterTest.java @@ -9,9 +9,10 @@ import io.prometheus.metrics.config.MetricsProperties; import io.prometheus.metrics.config.PrometheusProperties; import io.prometheus.metrics.core.exemplars.ExemplarSamplerConfigTestUtil; -import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics; +import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics; import io.prometheus.metrics.expositionformats.internal.PrometheusProtobufWriterImpl; import io.prometheus.metrics.expositionformats.internal.ProtobufUtil; +import io.prometheus.metrics.model.registry.PrometheusRegistry; import io.prometheus.metrics.model.snapshots.CounterSnapshot; import io.prometheus.metrics.model.snapshots.Exemplar; import io.prometheus.metrics.model.snapshots.Label; @@ -36,7 +37,7 @@ class CounterTest { private SpanContext origSpanContext; @BeforeEach - public void setUp() throws NoSuchFieldException, IllegalAccessException { + void setUp() throws NoSuchFieldException, IllegalAccessException { noLabels = Counter.builder().name("nolabels").build(); labels = Counter.builder().name("labels").help("help").unit(Unit.SECONDS).labelNames("l").build(); @@ -48,7 +49,7 @@ public void setUp() throws NoSuchFieldException, IllegalAccessException { } @AfterEach - public void tearDown() { + void tearDown() { SpanContextSupplier.setSpanContext(origSpanContext); } @@ -71,7 +72,7 @@ private int getNumberOfLabels(Counter counter) { } @Test - public void testIncrement() { + void testIncrement() { noLabels.inc(); assertThat(getValue(noLabels)).isCloseTo(1.0, offset(.001)); noLabels.inc(2); @@ -83,20 +84,20 @@ public void testIncrement() { } @Test - public void testNegativeIncrementFails() { + void testNegativeIncrementFails() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> noLabels.inc(-1)) .withMessage("Negative increment -1 is illegal for Counter metrics."); } @Test - public void testEmptyCountersHaveNoLabels() { + void testEmptyCountersHaveNoLabels() { assertThat(getNumberOfLabels(noLabels)).isOne(); assertThat(getNumberOfLabels(labels)).isZero(); } @Test - public void testLabels() { + void testLabels() { assertThat(getNumberOfLabels(labels)).isZero(); labels.labelValues("a").inc(); assertThat(getNumberOfLabels(labels)).isOne(); @@ -115,7 +116,7 @@ public void testLabels() { "my_counter", "my_counter_seconds", }) - public void testTotalStrippedFromName(String name) { + void testTotalStrippedFromName(String name) { Counter counter = Counter.builder().name(name).unit(Unit.SECONDS).build(); Metrics.MetricFamily protobufData = new PrometheusProtobufWriterImpl().convert(counter.collect(), EscapingScheme.ALLOW_UTF8); @@ -125,7 +126,7 @@ public void testTotalStrippedFromName(String name) { } @Test - public void testSnapshotComplete() { + void testSnapshotComplete() { long before = System.currentTimeMillis(); Counter counter = Counter.builder() @@ -180,7 +181,7 @@ public void testSnapshotComplete() { } @Test - public void testIncWithExemplar() throws Exception { + void testIncWithExemplar() throws Exception { noLabels.incWithExemplar(Labels.of("key", "value")); assertExemplar(noLabels, 1.0, "key", "value"); @@ -202,7 +203,7 @@ private void assertExemplar(Counter counter, double value, String... labels) { } @Test - public void testExemplarSampler() throws Exception { + void testExemplarSampler() throws Exception { Exemplar exemplar1 = Exemplar.builder().value(2.0).traceId("abc").spanId("123").build(); Exemplar exemplar2 = Exemplar.builder().value(1.0).traceId("def").spanId("456").build(); Exemplar exemplar3 = Exemplar.builder().value(1.0).traceId("123").spanId("abc").build(); @@ -320,7 +321,7 @@ void incWithExemplar2() { } @Test - public void testExemplarSamplerDisabled() { + void testExemplarSamplerDisabled() { Counter counter = Counter.builder().name("count_total").withoutExemplars().build(); counter.incWithExemplar(3.0, Labels.of("a", "b")); assertThat(getData(counter).getExemplar()).isNull(); @@ -329,7 +330,7 @@ public void testExemplarSamplerDisabled() { } @Test - public void testExemplarSamplerDisabled_enabledByDefault() { + void testExemplarSamplerDisabled_enabledByDefault() { PrometheusProperties properties = PrometheusProperties.builder() .defaultMetricsProperties(MetricsProperties.builder().exemplarsEnabled(true).build()) @@ -342,7 +343,7 @@ public void testExemplarSamplerDisabled_enabledByDefault() { } @Test - public void testExemplarSamplerDisabledInBuilder_enabledByPropertiesOnMetric() { + void testExemplarSamplerDisabledInBuilder_enabledByPropertiesOnMetric() { PrometheusProperties properties = PrometheusProperties.builder() .putMetricProperty("count", MetricsProperties.builder().exemplarsEnabled(true).build()) @@ -355,7 +356,7 @@ public void testExemplarSamplerDisabledInBuilder_enabledByPropertiesOnMetric() { } @Test - public void testConstLabelsFirst() { + void testConstLabelsFirst() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> @@ -367,7 +368,7 @@ public void testConstLabelsFirst() { } @Test - public void testConstLabelsSecond() { + void testConstLabelsSecond() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> @@ -377,4 +378,17 @@ public void testConstLabelsSecond() { .constLabels(Labels.of("const_a", "const_b")) .build()); } + + @Test + void testLabelNormalizationInRegistration() { + PrometheusRegistry registry = new PrometheusRegistry(); + + Counter.builder().name("requests").labelNames("request.count").register(registry); + + // request.count and request_count normalize to the same name + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy( + () -> Counter.builder().name("requests").labelNames("request_count").register(registry)) + .withMessageContaining("duplicate metric name with identical label schema"); + } } diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CounterWithCallbackTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CounterWithCallbackTest.java index 47c5f5c57..2907a8a02 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CounterWithCallbackTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CounterWithCallbackTest.java @@ -13,7 +13,7 @@ class CounterWithCallbackTest { @Test - public void testCounter() { + void testCounter() { final AtomicInteger value = new AtomicInteger(1); List labelValues = Arrays.asList("v1", "v2"); CounterWithCallback counter = @@ -38,7 +38,7 @@ public void testCounter() { } @Test - public void testCounterNoCallback() { + void testCounterNoCallback() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> CounterWithCallback.builder().name("counter").labelNames("l1", "l2").build()); diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CustomBucketsHistogramTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CustomBucketsHistogramTest.java new file mode 100644 index 000000000..347f775cf --- /dev/null +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CustomBucketsHistogramTest.java @@ -0,0 +1,470 @@ +package io.prometheus.metrics.core.metrics; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.data.Offset.offset; + +import io.prometheus.metrics.config.EscapingScheme; +import io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter; +import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics; +import io.prometheus.metrics.expositionformats.internal.PrometheusProtobufWriterImpl; +import io.prometheus.metrics.model.snapshots.ClassicHistogramBucket; +import io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets; +import io.prometheus.metrics.model.snapshots.HistogramSnapshot; +import io.prometheus.metrics.model.snapshots.Labels; +import io.prometheus.metrics.model.snapshots.MetricSnapshots; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.stream.Collectors; +import org.junit.jupiter.api.Test; + +/** + * Comprehensive tests to verify that client_java supports native histograms with custom buckets + * (NHCB). + * + *

According to the Prometheus specification + * (https://prometheus.io/docs/specs/native_histograms/), native histograms with custom buckets + * (schema -53) are exposed as classic histograms with custom bucket boundaries. Prometheus servers + * can then convert these to NHCB upon ingestion when configured with + * convert_classic_histograms_to_nhcb. + * + *

These tests verify that: + * + *

    + *
  • Histograms with custom bucket boundaries can be created + *
  • Custom buckets are properly exposed in both text and protobuf formats + *
  • Both classic-only and dual (classic+native) histograms work with custom buckets + *
  • Various custom bucket configurations (linear, exponential, arbitrary) work correctly + *
+ * + *

See issue #1838 for more context. + */ +class CustomBucketsHistogramTest { + + @Test + void testCustomBucketsWithArbitraryBoundaries() { + // Create a histogram with arbitrary custom bucket boundaries + Histogram histogram = + Histogram.builder() + .name("http_request_duration_seconds") + .help("HTTP request duration with custom buckets") + .classicUpperBounds(0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0) + .build(); + + // Observe some values + histogram.observe(0.008); + histogram.observe(0.045); + histogram.observe(0.3); + histogram.observe(2.5); + histogram.observe(7.8); + + HistogramSnapshot snapshot = histogram.collect(); + HistogramSnapshot.HistogramDataPointSnapshot data = snapshot.getDataPoints().get(0); + + // Verify custom bucket boundaries are set correctly + List upperBounds = + data.getClassicBuckets().stream() + .map(ClassicHistogramBucket::getUpperBound) + .collect(Collectors.toList()); + + assertThat(upperBounds) + .containsExactly(0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, Double.POSITIVE_INFINITY); + + // Verify observations are distributed correctly across buckets + // Note: counts are non-cumulative (count for that specific bucket only) + ClassicHistogramBuckets buckets = data.getClassicBuckets(); + assertThat(buckets.getCount(0)).isEqualTo(1); // <= 0.01: (0.008) + assertThat(buckets.getCount(1)).isEqualTo(1); // (0.01, 0.05]: (0.045) + assertThat(buckets.getCount(2)).isEqualTo(0); // (0.05, 0.1]: none + assertThat(buckets.getCount(3)).isEqualTo(1); // (0.1, 0.5]: (0.3) + assertThat(buckets.getCount(4)).isEqualTo(0); // (0.5, 1.0]: none + assertThat(buckets.getCount(5)).isEqualTo(1); // (1.0, 5.0]: (2.5) + assertThat(buckets.getCount(6)).isEqualTo(1); // (5.0, 10.0]: (7.8) + assertThat(buckets.getCount(7)).isEqualTo(0); // (10.0, +Inf]: none + + // Verify count and sum + assertThat(data.getCount()).isEqualTo(5); + assertThat(data.getSum()).isCloseTo(10.653, offset(0.01)); + } + + @Test + void testCustomBucketsWithLinearBoundaries() { + // Create a histogram with linear custom bucket boundaries + // This represents a use case where equal-width buckets are needed + Histogram histogram = + Histogram.builder() + .name("queue_size") + .help("Queue size with linear buckets") + .classicLinearUpperBounds(10.0, 10.0, 10) // start=10, width=10, count=10 + .build(); + + // Observe some values + for (int i = 5; i <= 95; i += 10) { + histogram.observe(i); + } + + HistogramSnapshot snapshot = histogram.collect(); + HistogramSnapshot.HistogramDataPointSnapshot data = snapshot.getDataPoints().get(0); + + // Verify linear bucket boundaries + List upperBounds = + data.getClassicBuckets().stream() + .map(ClassicHistogramBucket::getUpperBound) + .collect(Collectors.toList()); + + assertThat(upperBounds) + .containsExactly( + 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, Double.POSITIVE_INFINITY); + + // Verify observations + assertThat(data.getCount()).isEqualTo(10); + } + + @Test + void testCustomBucketsWithExponentialBoundaries() { + // Create a histogram with exponential custom bucket boundaries + // This is useful for metrics that span multiple orders of magnitude + Histogram histogram = + Histogram.builder() + .name("response_size_bytes") + .help("Response size with exponential buckets") + .classicExponentialUpperBounds(100.0, 10.0, 5) // start=100, factor=10, count=5 + .build(); + + // Observe some values across different magnitudes + histogram.observe(50); + histogram.observe(500); + histogram.observe(5000); + histogram.observe(50000); + histogram.observe(500000); + + HistogramSnapshot snapshot = histogram.collect(); + HistogramSnapshot.HistogramDataPointSnapshot data = snapshot.getDataPoints().get(0); + + // Verify exponential bucket boundaries + List upperBounds = + data.getClassicBuckets().stream() + .map(ClassicHistogramBucket::getUpperBound) + .collect(Collectors.toList()); + + assertThat(upperBounds) + .containsExactly(100.0, 1000.0, 10000.0, 100000.0, 1000000.0, Double.POSITIVE_INFINITY); + + // Verify observations + assertThat(data.getCount()).isEqualTo(5); + } + + @Test + void testCustomBucketsClassicOnlyHistogram() { + // Verify that custom buckets work with classic-only histograms + Histogram histogram = + Histogram.builder() + .name("test_classic_only") + .help("Classic-only histogram with custom buckets") + .classicOnly() + .classicUpperBounds(1.0, 5.0, 10.0) + .build(); + + histogram.observe(2.0); + histogram.observe(7.0); + + HistogramSnapshot snapshot = histogram.collect(); + HistogramSnapshot.HistogramDataPointSnapshot data = snapshot.getDataPoints().get(0); + + // Verify it's a classic-only histogram + assertThat(data.getNativeSchema()).isEqualTo(HistogramSnapshot.CLASSIC_HISTOGRAM); + + // Verify custom buckets + List upperBounds = + data.getClassicBuckets().stream() + .map(ClassicHistogramBucket::getUpperBound) + .collect(Collectors.toList()); + + assertThat(upperBounds).containsExactly(1.0, 5.0, 10.0, Double.POSITIVE_INFINITY); + } + + @Test + void testCustomBucketsDualModeHistogram() { + // Verify that custom buckets work with dual-mode (classic+native) histograms + // This is the default mode and most relevant for NHCB support + Histogram histogram = + Histogram.builder() + .name("test_dual_mode") + .help("Dual-mode histogram with custom buckets") + .classicUpperBounds(0.1, 1.0, 10.0) + .build(); + + histogram.observe(0.5); + histogram.observe(5.0); + + HistogramSnapshot snapshot = histogram.collect(); + HistogramSnapshot.HistogramDataPointSnapshot data = snapshot.getDataPoints().get(0); + + // Verify it has both classic and native representations + assertThat(data.getClassicBuckets().size()).isGreaterThan(0); + assertThat(data.getNativeSchema()).isNotEqualTo(HistogramSnapshot.CLASSIC_HISTOGRAM); + + // Verify custom classic buckets + List upperBounds = + data.getClassicBuckets().stream() + .map(ClassicHistogramBucket::getUpperBound) + .collect(Collectors.toList()); + + assertThat(upperBounds).containsExactly(0.1, 1.0, 10.0, Double.POSITIVE_INFINITY); + + // Verify native histogram is also populated + long nativeTotalCount = + data.getNativeBucketsForPositiveValues().stream() + .mapToLong(bucket -> bucket.getCount()) + .sum(); + assertThat(nativeTotalCount).isEqualTo(2); + } + + @Test + void testCustomBucketsTextFormatOutput() throws IOException { + // Verify that custom buckets are correctly serialized in text format + Histogram histogram = + Histogram.builder() + .name("test_custom_buckets") + .help("Test histogram with custom buckets") + .classicUpperBounds(0.5, 1.0, 2.0) + .build(); + + histogram.observe(0.3); + histogram.observe(0.7); + histogram.observe(1.5); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter(false, true); + writer.write(out, MetricSnapshots.of(histogram.collect()), EscapingScheme.ALLOW_UTF8); + + String output = out.toString(StandardCharsets.UTF_8); + + // Verify the output contains the custom bucket boundaries + assertThat(output).contains("le=\"0.5\""); + assertThat(output).contains("le=\"1.0\""); + assertThat(output).contains("le=\"2.0\""); + assertThat(output).contains("le=\"+Inf\""); + + // Verify bucket counts + assertThat(output).containsPattern("le=\"0.5\".*1"); // 1 observation <= 0.5 + assertThat(output).containsPattern("le=\"1.0\".*2"); // 2 observations <= 1.0 + assertThat(output).containsPattern("le=\"2.0\".*3"); // 3 observations <= 2.0 + assertThat(output).containsPattern("le=\"\\+Inf\".*3"); // 3 observations total + } + + @Test + void testCustomBucketsProtobufFormatOutput() { + // Verify that custom buckets are correctly serialized in Prometheus protobuf format + Histogram histogram = + Histogram.builder() + .name("test_custom_buckets_protobuf") + .help("Test histogram with custom buckets for protobuf") + .classicUpperBounds(1.0, 5.0, 10.0) + .build(); + + histogram.observe(0.5); + histogram.observe(3.0); + histogram.observe(7.0); + + HistogramSnapshot snapshot = histogram.collect(); + Metrics.MetricFamily metricFamily = + new PrometheusProtobufWriterImpl().convert(snapshot, EscapingScheme.ALLOW_UTF8); + + assertThat(metricFamily).isNotNull(); + assertThat(metricFamily.getName()).isEqualTo("test_custom_buckets_protobuf"); + assertThat(metricFamily.getType()).isEqualTo(Metrics.MetricType.HISTOGRAM); + + Metrics.Histogram protoHistogram = metricFamily.getMetric(0).getHistogram(); + + // Verify classic buckets in protobuf + assertThat(protoHistogram.getBucketCount()).isEqualTo(4); // 3 custom + +Inf + + // Verify bucket upper bounds + assertThat(protoHistogram.getBucket(0).getUpperBound()).isEqualTo(1.0); + assertThat(protoHistogram.getBucket(1).getUpperBound()).isEqualTo(5.0); + assertThat(protoHistogram.getBucket(2).getUpperBound()).isEqualTo(10.0); + assertThat(protoHistogram.getBucket(3).getUpperBound()).isEqualTo(Double.POSITIVE_INFINITY); + + // Verify bucket counts (cumulative) + assertThat(protoHistogram.getBucket(0).getCumulativeCount()).isEqualTo(1); // <= 1.0 + assertThat(protoHistogram.getBucket(1).getCumulativeCount()).isEqualTo(2); // <= 5.0 + assertThat(protoHistogram.getBucket(2).getCumulativeCount()).isEqualTo(3); // <= 10.0 + assertThat(protoHistogram.getBucket(3).getCumulativeCount()).isEqualTo(3); // +Inf + + // Verify native histogram fields are also present (for dual-mode) + assertThat(protoHistogram.hasSchema()).isTrue(); + assertThat(protoHistogram.getSchema()).isNotEqualTo(HistogramSnapshot.CLASSIC_HISTOGRAM); + } + + @Test + void testCustomBucketsWithNegativeValues() { + // Verify that custom buckets work correctly with negative values + Histogram histogram = + Histogram.builder() + .name("temperature_celsius") + .help("Temperature readings with custom buckets") + .classicUpperBounds(-20.0, -10.0, 0.0, 10.0, 20.0, 30.0) + .build(); + + histogram.observe(-15.0); + histogram.observe(-5.0); + histogram.observe(5.0); + histogram.observe(15.0); + histogram.observe(25.0); + + HistogramSnapshot snapshot = histogram.collect(); + HistogramSnapshot.HistogramDataPointSnapshot data = snapshot.getDataPoints().get(0); + + // Verify bucket boundaries + List upperBounds = + data.getClassicBuckets().stream() + .map(ClassicHistogramBucket::getUpperBound) + .collect(Collectors.toList()); + + assertThat(upperBounds) + .containsExactly(-20.0, -10.0, 0.0, 10.0, 20.0, 30.0, Double.POSITIVE_INFINITY); + + // Verify observations are distributed correctly + // Note: counts are non-cumulative + ClassicHistogramBuckets buckets = data.getClassicBuckets(); + assertThat(buckets.getCount(0)).isEqualTo(0); // <= -20: none + assertThat(buckets.getCount(1)).isEqualTo(1); // (-20, -10]: (-15.0) + assertThat(buckets.getCount(2)).isEqualTo(1); // (-10, 0]: (-5.0) + assertThat(buckets.getCount(3)).isEqualTo(1); // (0, 10]: (5.0) + assertThat(buckets.getCount(4)).isEqualTo(1); // (10, 20]: (15.0) + assertThat(buckets.getCount(5)).isEqualTo(1); // (20, 30]: (25.0) + + assertThat(data.getCount()).isEqualTo(5); + } + + @Test + void testCustomBucketsWithLabels() { + // Verify that custom buckets work correctly with labeled histograms + Histogram histogram = + Histogram.builder() + .name("api_request_duration_seconds") + .help("API request duration with custom buckets") + .classicUpperBounds(0.01, 0.1, 1.0, 10.0) + .labelNames("method", "endpoint") + .build(); + + histogram.labelValues("GET", "/users").observe(0.05); + histogram.labelValues("GET", "/users").observe(0.5); + histogram.labelValues("POST", "/users").observe(2.0); + + HistogramSnapshot snapshot = histogram.collect(); + + // Verify we have 2 data points (one for each unique label combination) + assertThat(snapshot.getDataPoints()).hasSize(2); + + // Verify both data points have the correct custom buckets + for (HistogramSnapshot.HistogramDataPointSnapshot data : snapshot.getDataPoints()) { + List upperBounds = + data.getClassicBuckets().stream() + .map(ClassicHistogramBucket::getUpperBound) + .collect(Collectors.toList()); + + assertThat(upperBounds).containsExactly(0.01, 0.1, 1.0, 10.0, Double.POSITIVE_INFINITY); + } + + // Verify GET /users data point + HistogramSnapshot.HistogramDataPointSnapshot getData = + getData(histogram, "method", "GET", "endpoint", "/users"); + + assertThat(getData.getCount()).isEqualTo(2); + + // Verify POST /users data point + HistogramSnapshot.HistogramDataPointSnapshot postData = + getData(histogram, "method", "POST", "endpoint", "/users"); + + assertThat(postData.getCount()).isEqualTo(1); + } + + private HistogramSnapshot.HistogramDataPointSnapshot getData( + Histogram histogram, String... labels) { + return histogram.collect().getDataPoints().stream() + .filter(d -> d.getLabels().equals(Labels.of(labels))) + .findAny() + .orElseThrow(() -> new RuntimeException("histogram with labels not found")); + } + + @Test + void testCustomBucketsBoundaryEdgeCases() { + // Test edge cases: observations exactly on bucket boundaries + Histogram histogram = + Histogram.builder() + .name("test_boundaries") + .help("Test bucket boundary edge cases") + .classicUpperBounds(1.0, 5.0, 10.0) + .build(); + + // Observe values exactly on the boundaries + histogram.observe(1.0); + histogram.observe(5.0); + histogram.observe(10.0); + + HistogramSnapshot snapshot = histogram.collect(); + HistogramSnapshot.HistogramDataPointSnapshot data = snapshot.getDataPoints().get(0); + + // Values on boundaries should be included in their respective buckets + // Buckets are inclusive of upper bound + // Note: counts are non-cumulative + ClassicHistogramBuckets buckets = data.getClassicBuckets(); + assertThat(buckets.getCount(0)).isEqualTo(1); // <= 1.0: (1.0) + assertThat(buckets.getCount(1)).isEqualTo(1); // (1.0, 5.0]: (5.0) + assertThat(buckets.getCount(2)).isEqualTo(1); // (5.0, 10.0]: (10.0) + + assertThat(data.getCount()).isEqualTo(3); + } + + @Test + void testCustomBucketsFineBoundaries() { + // Test with very fine-grained custom bucket boundaries + // This simulates a use case where precise bucket boundaries are needed + Histogram histogram = + Histogram.builder() + .name("precise_measurement") + .help("Histogram with fine-grained custom buckets") + .classicUpperBounds(0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.01) + .build(); + + histogram.observe(0.0015); + histogram.observe(0.0045); + histogram.observe(0.0075); + + HistogramSnapshot snapshot = histogram.collect(); + HistogramSnapshot.HistogramDataPointSnapshot data = snapshot.getDataPoints().get(0); + + // Verify fine-grained buckets are set correctly + List upperBounds = + data.getClassicBuckets().stream() + .map(ClassicHistogramBucket::getUpperBound) + .collect(Collectors.toList()); + + assertThat(upperBounds) + .containsExactly( + 0.001, + 0.002, + 0.003, + 0.004, + 0.005, + 0.006, + 0.007, + 0.008, + 0.009, + 0.01, + Double.POSITIVE_INFINITY); + + // Verify observations are in correct buckets + // Note: counts are non-cumulative + ClassicHistogramBuckets buckets = data.getClassicBuckets(); + assertThat(buckets.getCount(0)).isEqualTo(0); // <= 0.001: none + assertThat(buckets.getCount(1)).isEqualTo(1); // (0.001, 0.002]: (0.0015) + assertThat(buckets.getCount(4)).isEqualTo(1); // (0.004, 0.005]: (0.0045) + assertThat(buckets.getCount(7)).isEqualTo(1); // (0.007, 0.008]: (0.0075) + + assertThat(data.getCount()).isEqualTo(3); + } +} diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/GaugeTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/GaugeTest.java index 108fc05ce..be25711c7 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/GaugeTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/GaugeTest.java @@ -27,14 +27,14 @@ class GaugeTest { private SpanContext origSpanContext; @BeforeEach - public void setUp() { + void setUp() { noLabels = Gauge.builder().name("nolabels").build(); labels = Gauge.builder().name("labels").labelNames("l").build(); origSpanContext = SpanContextSupplier.getSpanContext(); } @AfterEach - public void tearDown() { + void tearDown() { SpanContextSupplier.setSpanContext(origSpanContext); } @@ -50,7 +50,7 @@ private double getValue(Gauge gauge, String... labels) { } @Test - public void testIncrement() { + void testIncrement() { noLabels.inc(); assertThat(getValue(noLabels)).isCloseTo(1.0, offset(.001)); noLabels.inc(2); @@ -62,7 +62,7 @@ public void testIncrement() { } @Test - public void testDecrement() { + void testDecrement() { noLabels.dec(); assertThat(getValue(noLabels)).isCloseTo(-1.0, offset(.001)); noLabels.dec(2); @@ -74,7 +74,7 @@ public void testDecrement() { } @Test - public void testSet() { + void testSet() { noLabels.set(42); assertThat(getValue(noLabels)).isCloseTo(42, offset(.001)); noLabels.set(7); @@ -92,12 +92,12 @@ public void testTimer() throws InterruptedException { } @Test - public void noLabelsDefaultZeroValue() { + void noLabelsDefaultZeroValue() { assertThat(getValue(noLabels)).isCloseTo(0.0, offset(.001)); } @Test - public void testLabels() { + void testLabels() { labels.labelValues("a").inc(); labels.labelValues("b").inc(3); assertThat(getValue(labels, "l", "a")).isCloseTo(1.0, offset(.001)); @@ -105,7 +105,7 @@ public void testLabels() { } @Test - public void testExemplarSampler() throws Exception { + void testExemplarSampler() throws Exception { Exemplar exemplar1 = Exemplar.builder().value(2.0).traceId("abc").spanId("123").build(); Exemplar exemplar2 = Exemplar.builder().value(6.5).traceId("def").spanId("456").build(); Exemplar exemplar3 = Exemplar.builder().value(7.0).traceId("123").spanId("abc").build(); @@ -222,7 +222,7 @@ void decWithExemplar() { } @Test - public void testExemplarSamplerDisabled() { + void testExemplarSamplerDisabled() { Gauge gauge = Gauge.builder().name("test").withoutExemplars().build(); gauge.setWithExemplar(3.0, Labels.of("a", "b")); assertThat(getData(gauge).getExemplar()).isNull(); @@ -231,7 +231,7 @@ public void testExemplarSamplerDisabled() { } @Test - public void testExemplarSamplerDisabledByBuilder_enabledByPropertiesOnMetric() { + void testExemplarSamplerDisabledByBuilder_enabledByPropertiesOnMetric() { PrometheusProperties properties = PrometheusProperties.builder() .putMetricProperty("test", MetricsProperties.builder().exemplarsEnabled(true).build()) diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/GaugeWithCallbackTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/GaugeWithCallbackTest.java index 92a2d605e..f89fd70d2 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/GaugeWithCallbackTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/GaugeWithCallbackTest.java @@ -13,7 +13,7 @@ class GaugeWithCallbackTest { @Test - public void testGauge() { + void testGauge() { final AtomicInteger value = new AtomicInteger(1); List labelValues = Arrays.asList("v1", "v2"); GaugeWithCallback gauge = @@ -38,7 +38,7 @@ public void testGauge() { } @Test - public void testGaugeNoCallback() { + void testGaugeNoCallback() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> GaugeWithCallback.builder().name("gauge").labelNames("l1", "l2").build()); } diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/HistogramTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/HistogramTest.java index 62fe246e9..c67c9dd42 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/HistogramTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/HistogramTest.java @@ -1,9 +1,11 @@ package io.prometheus.metrics.core.metrics; import static io.prometheus.metrics.core.metrics.TestUtil.assertExemplarEquals; +import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.data.Offset.offset; +import static org.awaitility.Awaitility.await; import io.prometheus.metrics.config.EscapingScheme; import io.prometheus.metrics.config.MetricsProperties; @@ -11,7 +13,7 @@ import io.prometheus.metrics.core.datapoints.DistributionDataPoint; import io.prometheus.metrics.core.exemplars.ExemplarSamplerConfigTestUtil; import io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter; -import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics; +import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics; import io.prometheus.metrics.expositionformats.internal.PrometheusProtobufWriterImpl; import io.prometheus.metrics.expositionformats.internal.ProtobufUtil; import io.prometheus.metrics.model.snapshots.*; @@ -51,12 +53,12 @@ class HistogramTest { private SpanContext origSpanContext; @BeforeEach - public void setUp() { + void setUp() { origSpanContext = SpanContextSupplier.getSpanContext(); } @AfterEach - public void tearDown() { + void tearDown() { SpanContextSupplier.setSpanContext(origSpanContext); } @@ -99,7 +101,7 @@ private void run() throws NoSuchFieldException, IllegalAccessException { /** Test cases copied from histogram_test.go in client_golang. */ @Test - public void testGolangTests() throws NoSuchFieldException, IllegalAccessException { + void testGolangTests() throws NoSuchFieldException, IllegalAccessException { GolangTestCase[] testCases = new GolangTestCase[] { new GolangTestCase( @@ -763,7 +765,7 @@ public void testGolangTests() throws NoSuchFieldException, IllegalAccessExceptio /** Additional tests that are not part of client_golang's test suite. */ @Test - public void testAdditional() throws NoSuchFieldException, IllegalAccessException { + void testAdditional() throws NoSuchFieldException, IllegalAccessException { GolangTestCase[] testCases = new GolangTestCase[] { new GolangTestCase( @@ -797,7 +799,7 @@ public void testAdditional() throws NoSuchFieldException, IllegalAccessException *

This test is ported from client_golang's TestGetLe(). */ @Test - public void testNativeBucketIndexToUpperBound() + void testNativeBucketIndexToUpperBound() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { int[] indexes = new int[] {-1, 0, 1, 512, 513, -1, 0, 1, 1024, 1025, -1, 0, 1, 4096, 4097}; int[] schemas = new int[] {-1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2}; @@ -839,7 +841,7 @@ public void testNativeBucketIndexToUpperBound() * findBucketIndex() */ @Test - public void testFindBucketIndex() + void testFindBucketIndex() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Random rand = new Random(); Method findBucketIndex = @@ -884,7 +886,7 @@ public void testFindBucketIndex() } @Test - public void testDefaults() throws IOException { + void testDefaults() throws IOException { Histogram histogram = Histogram.builder().name("test").build(); histogram.observe(0.5); HistogramSnapshot snapshot = histogram.collect(); @@ -955,7 +957,7 @@ public void testDefaults() throws IOException { } @Test - public void testExemplarsClassicHistogram() throws Exception { + void testExemplarsClassicHistogram() throws Exception { SpanContext spanContext = new SpanContext() { int callCount = 0; @@ -1020,10 +1022,18 @@ public void markCurrentSpanAsExemplar() {} assertThat(getExemplar(snapshot, Double.POSITIVE_INFINITY, "path", "/hello")).isNull(); assertThat(getExemplar(snapshot, Double.POSITIVE_INFINITY, "path", "/world")).isNull(); - Thread.sleep(sampleIntervalMillis + 1); + waitForSampleInterval(sampleIntervalMillis); histogram.labelValues("/hello").observe(4.5); histogram.labelValues("/world").observe(4.5); + await() + .atMost(2, SECONDS) + .until( + () -> { + HistogramSnapshot s = histogram.collect(); + return getExemplar(s, Double.POSITIVE_INFINITY, "path", "/hello") != null + && getExemplar(s, Double.POSITIVE_INFINITY, "path", "/world") != null; + }); snapshot = histogram.collect(); assertExemplarEquals(ex1a, getExemplar(snapshot, 1.0, "path", "/hello")); assertExemplarEquals(ex1b, getExemplar(snapshot, 1.0, "path", "/world")); @@ -1036,16 +1046,28 @@ public void markCurrentSpanAsExemplar() {} assertExemplarEquals(ex2a, getExemplar(snapshot, Double.POSITIVE_INFINITY, "path", "/hello")); assertExemplarEquals(ex2b, getExemplar(snapshot, Double.POSITIVE_INFINITY, "path", "/world")); - Thread.sleep(sampleIntervalMillis + 1); + waitForSampleInterval(sampleIntervalMillis); histogram.labelValues("/hello").observe(1.5); histogram.labelValues("/world").observe(1.5); - Thread.sleep(sampleIntervalMillis + 1); + waitForSampleInterval(sampleIntervalMillis); histogram.labelValues("/hello").observe(2.5); histogram.labelValues("/world").observe(2.5); - Thread.sleep(sampleIntervalMillis + 1); + waitForSampleInterval(sampleIntervalMillis); histogram.labelValues("/hello").observe(3.5); histogram.labelValues("/world").observe(3.5); + await() + .atMost(2, SECONDS) + .until( + () -> { + HistogramSnapshot s = histogram.collect(); + return getExemplar(s, 2.0, "path", "/hello") != null + && getExemplar(s, 2.0, "path", "/world") != null + && getExemplar(s, 3.0, "path", "/hello") != null + && getExemplar(s, 3.0, "path", "/world") != null + && getExemplar(s, 4.0, "path", "/hello") != null + && getExemplar(s, 4.0, "path", "/world") != null; + }); snapshot = histogram.collect(); assertExemplarEquals(ex1a, getExemplar(snapshot, 1.0, "path", "/hello")); assertExemplarEquals(ex1b, getExemplar(snapshot, 1.0, "path", "/world")); @@ -1072,15 +1094,32 @@ public void markCurrentSpanAsExemplar() {} "span_id", "spanId-11")) .build(); - Thread.sleep(sampleIntervalMillis + 1); + waitForSampleInterval(sampleIntervalMillis); histogram .labelValues("/hello") .observeWithExemplar(3.4, Labels.of("key1", "value1", "key2", "value2")); + await() + .atMost(2, SECONDS) + .until( + () -> { + Exemplar actual = getExemplar(histogram.collect(), 4.0, "path", "/hello"); + return actual != null && Math.abs(actual.getValue() - 3.4) < 0.00001; + }); snapshot = histogram.collect(); // custom exemplars have preference, so the automatic exemplar is replaced assertExemplarEquals(custom, getExemplar(snapshot, 4.0, "path", "/hello")); } + /** Waits for the exemplar sampler's rate limit window so the next observation is accepted. */ + private static void waitForSampleInterval(long sampleIntervalMillis) { + try { + Thread.sleep(2 * sampleIntervalMillis); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new AssertionError("Interrupted while waiting for sample interval", e); + } + } + private Exemplar getExemplar(HistogramSnapshot snapshot, double le, String... labels) { HistogramSnapshot.HistogramDataPointSnapshot data = snapshot.getDataPoints().stream() @@ -1099,7 +1138,7 @@ private Exemplar getExemplar(HistogramSnapshot snapshot, double le, String... la } @Test - public void testCustomExemplarsClassicHistogram() + void testCustomExemplarsClassicHistogram() throws InterruptedException, NoSuchFieldException, IllegalAccessException { // TODO: This was copied from the old simpleclient, can probably be refactored. @@ -1167,7 +1206,7 @@ private void assertExemplar(Histogram histogram, double value, String... labels) } @Test - public void testExemplarsNativeHistogram() throws NoSuchFieldException, IllegalAccessException { + void testExemplarsNativeHistogram() throws NoSuchFieldException, IllegalAccessException { SpanContext spanContext = new SpanContext() { @@ -1236,13 +1275,13 @@ public void markCurrentSpanAsExemplar() {} } @Test - public void testIllegalLabelName() { + void testIllegalLabelName() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> Histogram.builder().name("test").labelNames("label", "le")); } @Test - public void testIllegalLabelNameConstLabels() { + void testIllegalLabelNameConstLabels() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> @@ -1252,25 +1291,25 @@ public void testIllegalLabelNameConstLabels() { } @Test - public void testIllegalLabelNamePrefix() { + void testIllegalLabelNamePrefix() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> Histogram.builder().name("test").labelNames("__hello")); } @Test - public void testNoName() { + void testNoName() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> Histogram.builder().build()); } @Test - public void testNullName() { + void testNullName() { assertThatExceptionOfType(NullPointerException.class) .isThrownBy(() -> Histogram.builder().name(null)); } @Test - public void testDuplicateClassicBuckets() { + void testDuplicateClassicBuckets() { Histogram histogram = Histogram.builder().name("test").classicUpperBounds(0, 3, 17, 3, 21).build(); List upperBounds = @@ -1282,7 +1321,7 @@ public void testDuplicateClassicBuckets() { } @Test - public void testUnsortedBuckets() { + void testUnsortedBuckets() { Histogram histogram = Histogram.builder().name("test").classicUpperBounds(0.2, 0.1).build(); List upperBounds = getData(histogram).getClassicBuckets().stream() @@ -1292,7 +1331,7 @@ public void testUnsortedBuckets() { } @Test - public void testEmptyBuckets() { + void testEmptyBuckets() { Histogram histogram = Histogram.builder().name("test").classicUpperBounds().build(); List upperBounds = getData(histogram).getClassicBuckets().stream() @@ -1302,7 +1341,7 @@ public void testEmptyBuckets() { } @Test - public void testBucketsIncludePositiveInfinity() { + void testBucketsIncludePositiveInfinity() { Histogram histogram = Histogram.builder() .name("test") @@ -1316,7 +1355,7 @@ public void testBucketsIncludePositiveInfinity() { } @Test - public void testLinearBuckets() { + void testLinearBuckets() { Histogram histogram = Histogram.builder().name("test").classicLinearUpperBounds(0.1, 0.1, 10).build(); List upperBounds = @@ -1330,7 +1369,7 @@ public void testLinearBuckets() { } @Test - public void testExponentialBuckets() { + void testExponentialBuckets() { Histogram histogram = Histogram.builder().classicExponentialUpperBounds(2, 2.5, 3).name("test").build(); List upperBounds = @@ -1341,14 +1380,14 @@ public void testExponentialBuckets() { } @Test - public void testBucketsIncludeNaN() { + void testBucketsIncludeNaN() { assertThatExceptionOfType(RuntimeException.class) .isThrownBy( () -> Histogram.builder().name("test").classicUpperBounds(0.01, 0.1, 1.0, Double.NaN)); } @Test - public void testNoLabelsDefaultZeroValue() { + void testNoLabelsDefaultZeroValue() { Histogram noLabels = Histogram.builder().name("test").build(); assertThat(getBucket(noLabels, 0.005).getCount()).isZero(); assertThat(getData(noLabels).getCount()).isZero(); @@ -1363,7 +1402,7 @@ private ClassicHistogramBucket getBucket(Histogram histogram, double le, String. } @Test - public void testObserve() { + void testObserve() { Histogram noLabels = Histogram.builder().name("test").build(); noLabels.observe(2); assertThat(noLabels.getCount()).isOne(); @@ -1384,7 +1423,7 @@ public void testObserve() { @Test // See https://github.com/prometheus/client_java/issues/646 - public void testNegativeAmount() { + void testNegativeAmount() { Histogram histogram = Histogram.builder() .name("histogram") @@ -1410,7 +1449,7 @@ public void testNegativeAmount() { } @Test - public void testBoundaryConditions() { + void testBoundaryConditions() { Histogram histogram = Histogram.builder().name("test").build(); histogram.observe(2.5); assertThat(getBucket(histogram, 1).getCount()).isZero(); @@ -1425,14 +1464,14 @@ public void testBoundaryConditions() { } @Test - public void testExemplarsDisabledInBuilder() { + void testExemplarsDisabledInBuilder() { Histogram histogram = Histogram.builder().withoutExemplars().name("test").build(); histogram.observeWithExemplar(2.5, Labels.EMPTY); assertThat(getData(histogram).getExemplars().size()).isZero(); } @Test - public void testExemplarsDisabledInBuilder_enabledByPropertiesOnMetric() { + void testExemplarsDisabledInBuilder_enabledByPropertiesOnMetric() { PrometheusProperties properties = PrometheusProperties.builder() .putMetricProperty("test", MetricsProperties.builder().exemplarsEnabled(true).build()) @@ -1444,7 +1483,7 @@ public void testExemplarsDisabledInBuilder_enabledByPropertiesOnMetric() { } @Test - public void testObserveWithLabels() { + void testObserveWithLabels() { Histogram histogram = Histogram.builder() .name("test") @@ -1475,7 +1514,7 @@ public void testObserveWithLabels() { } @Test - public void testObserveMultithreaded() + void testObserveMultithreaded() throws InterruptedException, ExecutionException, TimeoutException { // Hard to test concurrency, but let's run a couple of observations in parallel and assert none // gets lost. @@ -1526,6 +1565,70 @@ public void testObserveMultithreaded() assertThat(executor.awaitTermination(5, TimeUnit.SECONDS)).isTrue(); } + @Test + void testNativeResetDuration() { + // Test that nativeResetDuration can be configured without error and the histogram + // functions correctly. The reset duration schedules internal reset behavior but + // is not directly observable in the snapshot. + Histogram histogram = + Histogram.builder() + .name("test_histogram_with_reset") + .nativeOnly() + .nativeResetDuration(24, TimeUnit.HOURS) + .build(); + + histogram.observe(1.0); + histogram.observe(2.0); + histogram.observe(3.0); + + HistogramSnapshot snapshot = histogram.collect(); + assertThat(snapshot.getDataPoints()).hasSize(1); + HistogramSnapshot.HistogramDataPointSnapshot dataPoint = snapshot.getDataPoints().get(0); + assertThat(dataPoint.hasNativeHistogramData()).isTrue(); + assertThat(dataPoint.getCount()).isEqualTo(3); + assertThat(dataPoint.getSum()).isEqualTo(6.0); + } + + @Test + void testNativeResetDurationNegativeValue() { + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy( + () -> + Histogram.builder() + .name("test_histogram") + .nativeOnly() + .nativeResetDuration(-1, TimeUnit.HOURS) + .build()) + .withMessageContaining("value > 0 expected"); + } + + @Test + void testNativeResetDurationZeroValue() { + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy( + () -> + Histogram.builder() + .name("test_histogram") + .nativeOnly() + .nativeResetDuration(0, TimeUnit.HOURS) + .build()) + .withMessageContaining("value > 0 expected"); + } + + @Test + void testNativeResetDurationSubSecond() { + // Sub-second durations should be rejected as they truncate to 0 seconds + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy( + () -> + Histogram.builder() + .name("test_histogram") + .nativeOnly() + .nativeResetDuration(500, TimeUnit.MILLISECONDS) + .build()) + .withMessageContaining("duration must be at least 1 second"); + } + private HistogramSnapshot.HistogramDataPointSnapshot getData( Histogram histogram, String... labels) { return histogram.collect().getDataPoints().stream() diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/InfoTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/InfoTest.java index 138fa6ff0..0681f73e1 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/InfoTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/InfoTest.java @@ -5,7 +5,7 @@ import io.prometheus.metrics.config.EscapingScheme; import io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter; -import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics; +import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics; import io.prometheus.metrics.expositionformats.internal.PrometheusProtobufWriterImpl; import io.prometheus.metrics.expositionformats.internal.ProtobufUtil; import io.prometheus.metrics.model.snapshots.Labels; @@ -34,7 +34,7 @@ public void testInfoStrippedFromName(String name) { } @Test - public void testAddAndRemove() { + void testAddAndRemove() { Info info = Info.builder().name("test_info").labelNames("a", "b").build(); assertThat(info.collect().getDataPoints()).isEmpty(); info.addLabelValues("val1", "val2"); @@ -58,7 +58,7 @@ public void testAddAndRemove() { } @Test - public void testSet() throws IOException { + void testSet() throws IOException { Info info = Info.builder() .name("target_info") @@ -88,7 +88,7 @@ public void testSet() throws IOException { } @Test - public void testConstLabelsOnly() throws IOException { + void testConstLabelsOnly() throws IOException { Info info = Info.builder() .name("target_info") @@ -106,14 +106,14 @@ void unit() { } @Test - public void testConstLabelsDuplicate1() { + void testConstLabelsDuplicate1() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> Info.builder().constLabels(Labels.of("a_1", "val1")).labelNames("a.1").build()); } @Test - public void testConstLabelsDuplicate2() { + void testConstLabelsDuplicate2() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> Info.builder().labelNames("a_1").constLabels(Labels.of("a.1", "val1")).build()); diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/SlidingWindowTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/SlidingWindowTest.java index d85e5637c..dea8fdfbd 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/SlidingWindowTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/SlidingWindowTest.java @@ -43,7 +43,7 @@ void assertValues(double... expectedValues) { private final long timeBetweenRotateMillis = maxAgeSeconds * 1000 / ageBuckets + 2; @BeforeEach - public void setUp() { + void setUp() { startTime = System.currentTimeMillis(); currentTimeMillis.set(startTime); ringBuffer = @@ -57,7 +57,7 @@ public void setUp() { } @Test - public void testRotate() { + void testRotate() { for (int i = 0; i < ageBuckets; i++) { currentTimeMillis.addAndGet(timeBetweenRotateMillis); ringBuffer.observe(1.0); @@ -76,7 +76,7 @@ public void testRotate() { } @Test - public void testMultiRotate() { + void testMultiRotate() { ringBuffer.observe(1.0); currentTimeMillis.addAndGet(2 * timeBetweenRotateMillis); // 2/5 of max aqe ringBuffer.observe(2.0); diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/StateSetTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/StateSetTest.java index 7d466335b..318013edf 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/StateSetTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/StateSetTest.java @@ -27,7 +27,7 @@ public String toString() { } @Test - public void testEnumStateSet() { + void testEnumStateSet() { StateSet stateSet = StateSet.builder() .name("feature_flags") @@ -51,7 +51,7 @@ public void testEnumStateSet() { } @Test - public void testDefaultFalse() { + void testDefaultFalse() { StateSet stateSet = StateSet.builder().name("test").states("state1", "state2", "state3").build(); assertThat(getData(stateSet).size()).isEqualTo(3); @@ -83,7 +83,7 @@ private StateSetSnapshot.StateSetDataPointSnapshot getData(StateSet stateSet, St } @Test - public void testStatesCannotBeEmpty() { + void testStatesCannotBeEmpty() { assertThatExceptionOfType(IllegalStateException.class) .isThrownBy(() -> StateSet.builder().name("invalid").build()); } diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/StatefulMetricTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/StatefulMetricTest.java index 00aa53bbd..f940d505d 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/StatefulMetricTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/StatefulMetricTest.java @@ -12,7 +12,7 @@ class StatefulMetricTest { @Test - public void testLabelRemoveWhileCollecting() throws Exception { + void testLabelRemoveWhileCollecting() throws Exception { Counter counter = Counter.builder().name("test").labelNames("label1", "label2").build(); Field data = counter.getClass().getSuperclass().getDeclaredField("data"); data.setAccessible(true); @@ -61,7 +61,7 @@ public void testLabelRemoveIf() throws Exception { } @Test - public void testClear() { + void testClear() { Counter counter = Counter.builder().name("test").labelNames("label1", "label2").build(); counter.labelValues("a", "b").inc(3.0); counter.labelValues("c", "d").inc(3.0); @@ -76,7 +76,7 @@ public void testClear() { } @Test - public void testClearNoLabels() { + void testClearNoLabels() { Counter counter = Counter.builder().name("test").build(); counter.inc(); assertThat(counter.collect().getDataPoints()).hasSize(1); @@ -95,7 +95,7 @@ public void testClearNoLabels() { } @Test - public void testNullLabel() { + void testNullLabel() { Counter counter = Counter.builder().name("test").labelNames("l1", "l2").build(); assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> counter.labelValues("l1", null)) diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/SummaryTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/SummaryTest.java index cdfffe5f0..b6c045229 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/SummaryTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/SummaryTest.java @@ -30,7 +30,7 @@ class SummaryTest { private Summary noLabelsAndQuantiles; @BeforeEach - public void setUp() { + void setUp() { registry = new PrometheusRegistry(); noLabels = Summary.builder().name("nolabels").unit(Unit.SECONDS).help("help").register(registry); @@ -63,7 +63,7 @@ public void setUp() { } @Test - public void testObserve() { + void testObserve() { noLabels.observe(2); assertThat(noLabels.getCount()).isOne(); assertThat(noLabels.getSum()).isCloseTo(2.0, offset(.0)); @@ -86,7 +86,7 @@ public void testObserve() { } @Test - public void testNegativeAmount() { + void testNegativeAmount() { noLabels.observe(-1); noLabels.observe(-3); assertThat(getCount(noLabels, Labels.EMPTY)).isEqualTo(2); @@ -94,7 +94,7 @@ public void testNegativeAmount() { } @Test - public void testQuantiles() { + void testQuantiles() { int nSamples = 1000000; // simulate one million samples for (int i = 1; i <= nSamples; i++) { @@ -119,7 +119,7 @@ public void testQuantiles() { } @Test - public void testMaxAge() throws InterruptedException { + void testMaxAge() throws InterruptedException { Summary summary = Summary.builder() .quantile(0.99, 0.001) @@ -138,7 +138,7 @@ public void testMaxAge() throws InterruptedException { } @Test - public void testTimer() { + void testTimer() { int result = noLabels.time(() -> 123); assertThat(result).isEqualTo(123); assertThat(getCount(noLabels, Labels.EMPTY)).isOne(); @@ -150,31 +150,31 @@ public void testTimer() { } @Test - public void noLabelsDefaultZeroValue() { + void noLabelsDefaultZeroValue() { assertThat(getCount(noLabels, Labels.EMPTY)).isZero(); assertThat(getSum(noLabels, Labels.EMPTY)).isCloseTo(0.0, offset(.001)); } @Test - public void testBuilderInvalidNumberOfAgeBuckets() { + void testBuilderInvalidNumberOfAgeBuckets() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> Summary.builder().name("name").numberOfAgeBuckets(-1).build()); } @Test - public void testBuilderInvalidMaxAge() { + void testBuilderInvalidMaxAge() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> Summary.builder().name("name").maxAgeSeconds(-1).build()); } @Test - public void testBuilderInvalidQuantile() { + void testBuilderInvalidQuantile() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> Summary.builder().name("name").quantile(42).build()); } @Test - public void testBuilderInvalidQuantileError() { + void testBuilderInvalidQuantileError() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> Summary.builder().name("name").quantile(0.5, 20).build()); } diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/SummaryWithCallbackTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/SummaryWithCallbackTest.java index 929efc597..aacb83193 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/SummaryWithCallbackTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/SummaryWithCallbackTest.java @@ -15,7 +15,7 @@ class SummaryWithCallbackTest { @Test - public void testGauge() { + void testGauge() { final AtomicInteger count = new AtomicInteger(1); final AtomicInteger sum = new AtomicInteger(1); final Quantiles quantiles = Quantiles.of(new Quantile(0.5, 10)); @@ -49,7 +49,7 @@ public void testGauge() { } @Test - public void testSummaryNoCallback() { + void testSummaryNoCallback() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> SummaryWithCallback.builder().name("summary").labelNames("l1", "l2").build()); diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/TestUtil.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/TestUtil.java index 8d9a5bd0f..10ce1db94 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/TestUtil.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/TestUtil.java @@ -6,7 +6,7 @@ import io.prometheus.metrics.model.snapshots.Exemplar; import io.prometheus.metrics.model.snapshots.Label; -class TestUtil { +public class TestUtil { public static void assertExemplarEquals(Exemplar expected, Exemplar actual) { // ignore timestamp diff --git a/prometheus-metrics-exporter-common/pom.xml b/prometheus-metrics-exporter-common/pom.xml index 73eed61cb..a471c0b9b 100644 --- a/prometheus-metrics-exporter-common/pom.xml +++ b/prometheus-metrics-exporter-common/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-exporter-common @@ -38,6 +38,14 @@ ${project.version} runtime + + + + io.prometheus + prometheus-metrics-core + ${project.version} + test + diff --git a/prometheus-metrics-exporter-common/src/main/java/io/prometheus/metrics/exporter/common/PrometheusHttpRequest.java b/prometheus-metrics-exporter-common/src/main/java/io/prometheus/metrics/exporter/common/PrometheusHttpRequest.java index 3af9996e3..4483fc83f 100644 --- a/prometheus-metrics-exporter-common/src/main/java/io/prometheus/metrics/exporter/common/PrometheusHttpRequest.java +++ b/prometheus-metrics-exporter-common/src/main/java/io/prometheus/metrics/exporter/common/PrometheusHttpRequest.java @@ -43,6 +43,8 @@ default String getParameter(String name) { /** See {@code jakarta.servlet.ServletRequest.getParameterValues(String)} */ @Override @Nullable + // decode with Charset is only available in Java 10+, but we want to support Java 8 + @SuppressWarnings("JdkObsolete") default String[] getParameterValues(String name) { try { ArrayList result = new ArrayList<>(); diff --git a/prometheus-metrics-exporter-common/src/test/java/io/prometheus/metrics/exporter/common/PrometheusHttpRequestTest.java b/prometheus-metrics-exporter-common/src/test/java/io/prometheus/metrics/exporter/common/PrometheusHttpRequestTest.java new file mode 100644 index 000000000..a2b630ecd --- /dev/null +++ b/prometheus-metrics-exporter-common/src/test/java/io/prometheus/metrics/exporter/common/PrometheusHttpRequestTest.java @@ -0,0 +1,120 @@ +package io.prometheus.metrics.exporter.common; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Collections; +import java.util.Enumeration; +import org.junit.jupiter.api.Test; + +class PrometheusHttpRequestTest { + + @Test + void testGetHeaderReturnsFirstValue() { + PrometheusHttpRequest request = + new TestPrometheusHttpRequest("name[]=metric1&name[]=metric2", "gzip"); + assertThat(request.getHeader("Accept-Encoding")).isEqualTo("gzip"); + } + + @Test + void testGetHeaderReturnsNullWhenNoHeaders() { + PrometheusHttpRequest request = new TestPrometheusHttpRequest("", null); + assertThat(request.getHeader("Accept-Encoding")).isNull(); + } + + @Test + void testGetParameterReturnsFirstValue() { + PrometheusHttpRequest request = new TestPrometheusHttpRequest("name[]=metric1&name[]=metric2"); + assertThat(request.getParameter("name[]")).isEqualTo("metric1"); + } + + @Test + void testGetParameterReturnsNullWhenNotPresent() { + PrometheusHttpRequest request = new TestPrometheusHttpRequest("other=value"); + assertThat(request.getParameter("name[]")).isNull(); + } + + @Test + void testGetParameterValuesReturnsMultipleValues() { + PrometheusHttpRequest request = new TestPrometheusHttpRequest("name[]=metric1&name[]=metric2"); + String[] values = request.getParameterValues("name[]"); + assertThat(values).containsExactly("metric1", "metric2"); + } + + @Test + void testGetParameterValuesReturnsNullWhenNotPresent() { + PrometheusHttpRequest request = new TestPrometheusHttpRequest("other=value"); + assertThat(request.getParameterValues("name[]")).isNull(); + } + + @Test + void testGetParameterValuesWithEmptyQueryString() { + PrometheusHttpRequest request = new TestPrometheusHttpRequest(""); + assertThat(request.getParameterValues("name[]")).isNull(); + } + + @Test + void testGetParameterValuesWithNullQueryString() { + PrometheusHttpRequest request = new TestPrometheusHttpRequest(null); + assertThat(request.getParameterValues("name[]")).isNull(); + } + + @Test + void testGetParameterValuesWithUrlEncodedValues() { + PrometheusHttpRequest request = new TestPrometheusHttpRequest("name=hello%20world"); + String[] values = request.getParameterValues("name"); + assertThat(values).containsExactly("hello world"); + } + + @Test + void testGetParameterValuesWithSpecialCharacters() { + PrometheusHttpRequest request = new TestPrometheusHttpRequest("name=%2Ffoo%2Fbar"); + String[] values = request.getParameterValues("name"); + assertThat(values).containsExactly("/foo/bar"); + } + + @Test + void testGetParameterValuesIgnoresParametersWithoutEquals() { + PrometheusHttpRequest request = + new TestPrometheusHttpRequest("name[]=value1&invalid&name[]=value2"); + String[] values = request.getParameterValues("name[]"); + assertThat(values).containsExactly("value1", "value2"); + } + + /** Test implementation of PrometheusHttpRequest for testing default methods. */ + private static class TestPrometheusHttpRequest implements PrometheusHttpRequest { + private final String queryString; + private final String acceptEncoding; + + TestPrometheusHttpRequest(String queryString) { + this(queryString, null); + } + + TestPrometheusHttpRequest(String queryString, String acceptEncoding) { + this.queryString = queryString; + this.acceptEncoding = acceptEncoding; + } + + @Override + public String getQueryString() { + return queryString; + } + + @Override + public Enumeration getHeaders(String name) { + if (acceptEncoding != null && name.equals("Accept-Encoding")) { + return Collections.enumeration(Collections.singletonList(acceptEncoding)); + } + return null; + } + + @Override + public String getMethod() { + return "GET"; + } + + @Override + public String getRequestPath() { + return "/metrics"; + } + } +} diff --git a/prometheus-metrics-exporter-common/src/test/java/io/prometheus/metrics/exporter/common/PrometheusScrapeHandlerTest.java b/prometheus-metrics-exporter-common/src/test/java/io/prometheus/metrics/exporter/common/PrometheusScrapeHandlerTest.java new file mode 100644 index 000000000..07ea8ac52 --- /dev/null +++ b/prometheus-metrics-exporter-common/src/test/java/io/prometheus/metrics/exporter/common/PrometheusScrapeHandlerTest.java @@ -0,0 +1,303 @@ +package io.prometheus.metrics.exporter.common; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.prometheus.metrics.core.metrics.Counter; +import io.prometheus.metrics.model.registry.PrometheusRegistry; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.zip.GZIPInputStream; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class PrometheusScrapeHandlerTest { + + private PrometheusRegistry registry; + private PrometheusScrapeHandler handler; + private Counter testCounter; + + @BeforeEach + void setUp() { + registry = new PrometheusRegistry(); + handler = new PrometheusScrapeHandler(registry); + testCounter = Counter.builder().name("test_counter").help("Test counter").register(registry); + testCounter.inc(5); + } + + @Test + void testBasicScrape() throws IOException { + TestHttpExchange exchange = new TestHttpExchange("GET", null); + handler.handleRequest(exchange); + + assertThat(exchange.getResponseCode()).isEqualTo(200); + assertThat(exchange.getResponseBody()).contains("test_counter"); + assertThat(exchange.getResponseBody()).contains("5.0"); + } + + @Test + void testOpenMetricsFormat() throws IOException { + TestHttpExchange exchange = + new TestHttpExchange("GET", null).withHeader("Accept", "application/openmetrics-text"); + handler.handleRequest(exchange); + + assertThat(exchange.getResponseCode()).isEqualTo(200); + assertThat(exchange.getResponseHeaders().get("Content-Type")) + .contains("application/openmetrics-text"); + assertThat(exchange.getResponseBody()).contains("test_counter"); + } + + @Test + void testPrometheusTextFormat() throws IOException { + TestHttpExchange exchange = + new TestHttpExchange("GET", null).withHeader("Accept", "text/plain"); + handler.handleRequest(exchange); + + assertThat(exchange.getResponseCode()).isEqualTo(200); + assertThat(exchange.getResponseHeaders().get("Content-Type")).contains("text/plain"); + assertThat(exchange.getResponseBody()).contains("test_counter"); + } + + @Test + void testGzipCompression() throws IOException { + TestHttpExchange exchange = + new TestHttpExchange("GET", null).withHeader("Accept-Encoding", "gzip"); + handler.handleRequest(exchange); + + assertThat(exchange.getResponseCode()).isEqualTo(200); + assertThat(exchange.getResponseHeaders().get("Content-Encoding")).isEqualTo("gzip"); + assertThat(exchange.isGzipCompressed()).isTrue(); + + // Decompress and verify content + String decompressed = exchange.getDecompressedBody(); + assertThat(decompressed).contains("test_counter"); + } + + @Test + void testMultipleAcceptEncodingHeaders() throws IOException { + TestHttpExchange exchange = + new TestHttpExchange("GET", null) + .withHeader("Accept-Encoding", "deflate") + .withHeader("Accept-Encoding", "gzip, br"); + handler.handleRequest(exchange); + + assertThat(exchange.getResponseCode()).isEqualTo(200); + assertThat(exchange.getResponseHeaders().get("Content-Encoding")).isEqualTo("gzip"); + } + + @Test + void testHeadRequest() throws IOException { + TestHttpExchange exchange = new TestHttpExchange("HEAD", null); + handler.handleRequest(exchange); + + assertThat(exchange.getResponseCode()).isEqualTo(200); + assertThat(exchange.getResponseHeaders().get("Content-Length")).isNotNull(); + // For HEAD requests, body should be empty even though Content-Length is set + assertThat(exchange.rawResponseBody.size()).isEqualTo(0); + } + + @Test + void testDebugOpenMetrics() throws IOException { + TestHttpExchange exchange = new TestHttpExchange("GET", "debug=openmetrics"); + handler.handleRequest(exchange); + + assertThat(exchange.getResponseCode()).isEqualTo(200); + assertThat(exchange.getResponseHeaders().get("Content-Type")) + .isEqualTo("text/plain; charset=utf-8"); + assertThat(exchange.getResponseBody()).contains("test_counter"); + } + + @Test + void testDebugText() throws IOException { + TestHttpExchange exchange = new TestHttpExchange("GET", "debug=text"); + handler.handleRequest(exchange); + + assertThat(exchange.getResponseCode()).isEqualTo(200); + assertThat(exchange.getResponseBody()).contains("test_counter"); + } + + @Test + void testDebugInvalidParameter() throws IOException { + TestHttpExchange exchange = new TestHttpExchange("GET", "debug=invalid"); + handler.handleRequest(exchange); + + assertThat(exchange.getResponseCode()).isEqualTo(500); + assertThat(exchange.getResponseBody()).contains("debug=invalid: Unsupported query parameter"); + } + + @Test + void testMetricNameFilter() throws IOException { + Counter anotherCounter = + Counter.builder().name("another_counter").help("Another counter").register(registry); + anotherCounter.inc(10); + + TestHttpExchange exchange = new TestHttpExchange("GET", "name[]=test_counter"); + handler.handleRequest(exchange); + + assertThat(exchange.getResponseCode()).isEqualTo(200); + assertThat(exchange.getResponseBody()).contains("test_counter"); + assertThat(exchange.getResponseBody()).doesNotContain("another_counter"); + } + + @Test + void testMultipleMetricNameFilters() throws IOException { + Counter counter1 = Counter.builder().name("metric_one").help("Metric one").register(registry); + Counter counter2 = Counter.builder().name("metric_two").help("Metric two").register(registry); + Counter counter3 = + Counter.builder().name("metric_three").help("Metric three").register(registry); + counter1.inc(); + counter2.inc(); + counter3.inc(); + + TestHttpExchange exchange = new TestHttpExchange("GET", "name[]=metric_one&name[]=metric_two"); + handler.handleRequest(exchange); + + assertThat(exchange.getResponseCode()).isEqualTo(200); + String body = exchange.getResponseBody(); + assertThat(body).contains("metric_one"); + assertThat(body).contains("metric_two"); + assertThat(body).doesNotContain("metric_three"); + } + + /** Test implementation of PrometheusHttpExchange for testing. */ + private static class TestHttpExchange implements PrometheusHttpExchange { + private final TestHttpRequest request; + private final TestHttpResponse response; + private boolean closed = false; + + ByteArrayOutputStream rawResponseBody = new ByteArrayOutputStream(); + + TestHttpExchange(String method, String queryString) { + this.request = new TestHttpRequest(method, queryString); + this.response = new TestHttpResponse(rawResponseBody); + } + + TestHttpExchange withHeader(String name, String value) { + request.addHeader(name, value); + return this; + } + + @Override + public PrometheusHttpRequest getRequest() { + return request; + } + + @Override + public PrometheusHttpResponse getResponse() { + return response; + } + + @Override + public void handleException(IOException e) throws IOException { + throw e; + } + + @Override + public void handleException(RuntimeException e) { + throw e; + } + + @Override + public void close() { + closed = true; + } + + public int getResponseCode() { + return response.statusCode; + } + + public Map getResponseHeaders() { + return response.headers; + } + + public String getResponseBody() { + return rawResponseBody.toString(StandardCharsets.UTF_8); + } + + public boolean isGzipCompressed() { + return "gzip".equals(response.headers.get("Content-Encoding")); + } + + public String getDecompressedBody() throws IOException { + if (!isGzipCompressed()) { + return getResponseBody(); + } + byte[] compressed = rawResponseBody.toByteArray(); + try (GZIPInputStream gzipInputStream = + new GZIPInputStream(new java.io.ByteArrayInputStream(compressed))) { + ByteArrayOutputStream decompressed = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len; + while ((len = gzipInputStream.read(buffer)) > 0) { + decompressed.write(buffer, 0, len); + } + return decompressed.toString(StandardCharsets.UTF_8.name()); + } + } + } + + /** Test implementation of PrometheusHttpRequest. */ + private static class TestHttpRequest implements PrometheusHttpRequest { + private final String method; + private final String queryString; + private final Map> headers = new HashMap<>(); + + TestHttpRequest(String method, String queryString) { + this.method = method; + this.queryString = queryString; + } + + void addHeader(String name, String value) { + headers.computeIfAbsent(name, k -> new java.util.ArrayList<>()).add(value); + } + + @Override + public String getQueryString() { + return queryString; + } + + @Override + public Enumeration getHeaders(String name) { + java.util.List values = headers.get(name); + return values == null ? null : Collections.enumeration(values); + } + + @Override + public String getMethod() { + return method; + } + + @Override + public String getRequestPath() { + return "/metrics"; + } + } + + /** Test implementation of PrometheusHttpResponse. */ + private static class TestHttpResponse implements PrometheusHttpResponse { + private final Map headers = new HashMap<>(); + private final ByteArrayOutputStream outputStream; + private int statusCode; + + TestHttpResponse(ByteArrayOutputStream outputStream) { + this.outputStream = outputStream; + } + + @Override + public void setHeader(String name, String value) { + headers.put(name, value); + } + + @Override + public OutputStream sendHeadersAndGetBody(int statusCode, int contentLength) + throws IOException { + this.statusCode = statusCode; + return outputStream; + } + } +} diff --git a/prometheus-metrics-exporter-httpserver/pom.xml b/prometheus-metrics-exporter-httpserver/pom.xml index 07c2abd71..d2843b51a 100644 --- a/prometheus-metrics-exporter-httpserver/pom.xml +++ b/prometheus-metrics-exporter-httpserver/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-exporter-httpserver @@ -19,7 +19,7 @@ io.prometheus.metrics.exporter.httpserver - 0.45 + 0.60 diff --git a/prometheus-metrics-exporter-httpserver/src/main/java/io/prometheus/metrics/exporter/httpserver/HTTPServer.java b/prometheus-metrics-exporter-httpserver/src/main/java/io/prometheus/metrics/exporter/httpserver/HTTPServer.java index 41fdec76d..55ed6c67e 100644 --- a/prometheus-metrics-exporter-httpserver/src/main/java/io/prometheus/metrics/exporter/httpserver/HTTPServer.java +++ b/prometheus-metrics-exporter-httpserver/src/main/java/io/prometheus/metrics/exporter/httpserver/HTTPServer.java @@ -66,11 +66,21 @@ private HTTPServer( this.server = httpServer; this.executorService = executorService; String metricsPath = getMetricsPath(metricsHandlerPath); + try { + server.removeContext("/"); + } catch (IllegalArgumentException e) { + // context "/" not registered yet, ignore + } registerHandler( "/", defaultHandler == null ? new DefaultHandler(metricsPath) : defaultHandler, authenticator, authenticatedSubjectAttributeName); + try { + server.removeContext(metricsPath); + } catch (IllegalArgumentException e) { + // context metricsPath not registered yet, ignore + } registerHandler( metricsPath, new MetricsHandler(config, registry), diff --git a/prometheus-metrics-exporter-httpserver/src/main/java/io/prometheus/metrics/exporter/httpserver/HttpExchangeAdapter.java b/prometheus-metrics-exporter-httpserver/src/main/java/io/prometheus/metrics/exporter/httpserver/HttpExchangeAdapter.java index 3e0322309..df99837cb 100644 --- a/prometheus-metrics-exporter-httpserver/src/main/java/io/prometheus/metrics/exporter/httpserver/HttpExchangeAdapter.java +++ b/prometheus-metrics-exporter-httpserver/src/main/java/io/prometheus/metrics/exporter/httpserver/HttpExchangeAdapter.java @@ -112,7 +112,7 @@ private void sendErrorResponseWithStackTrace(Exception requestHandlerException) httpExchange.getResponseHeaders().set("Content-Type", "text/plain; charset=utf-8"); httpExchange.sendResponseHeaders(500, stackTrace.length); httpExchange.getResponseBody().write(stackTrace); - } catch (Exception errorWriterException) { + } catch (IOException errorWriterException) { // We want to avoid logging so that we don't mess with application logs when the HTTPServer // is used in a Java agent. // However, if we can't even send an error response to the client there's nothing we can do diff --git a/prometheus-metrics-exporter-httpserver/src/test/java/io/prometheus/metrics/exporter/httpserver/HTTPServerTest.java b/prometheus-metrics-exporter-httpserver/src/test/java/io/prometheus/metrics/exporter/httpserver/HTTPServerTest.java index 9b7f658de..ff2d55048 100644 --- a/prometheus-metrics-exporter-httpserver/src/test/java/io/prometheus/metrics/exporter/httpserver/HTTPServerTest.java +++ b/prometheus-metrics-exporter-httpserver/src/test/java/io/prometheus/metrics/exporter/httpserver/HTTPServerTest.java @@ -10,25 +10,42 @@ import com.sun.net.httpserver.HttpsConfigurator; import io.prometheus.metrics.model.registry.PrometheusRegistry; import io.prometheus.metrics.model.registry.PrometheusScrapeRequest; +import io.prometheus.metrics.model.snapshots.CounterSnapshot; +import io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot; +import io.prometheus.metrics.model.snapshots.Labels; +import io.prometheus.metrics.model.snapshots.MetricMetadata; import io.prometheus.metrics.model.snapshots.MetricSnapshots; import java.io.IOException; +import java.lang.reflect.Method; import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.nio.charset.StandardCharsets; -import java.security.NoSuchAlgorithmException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; import java.security.Principal; +import java.util.List; import java.util.concurrent.Executors; import javax.net.ssl.SSLContext; import javax.security.auth.Subject; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class HTTPServerTest { +class HTTPServerTest { + + private PrometheusRegistry registry; + + @BeforeEach + void setUp() { + final MetricMetadata metadata = new MetricMetadata("my-counter"); + final CounterDataPointSnapshot dataPointSnapshot = + new CounterDataPointSnapshot(1.0, Labels.EMPTY, null, System.currentTimeMillis()); + + registry = new PrometheusRegistry(); + registry.register(() -> new CounterSnapshot(metadata, List.of(dataPointSnapshot))); + } @Test - @SuppressWarnings({"removal"}) public void testSubjectDoAs() throws Exception { - final String user = "joe"; final Subject subject = new Subject(); subject.getPrincipals().add(() -> user); @@ -45,7 +62,7 @@ public Result authenticate(HttpExchange exchange) { HttpHandler handler = exchange -> { boolean found = false; - Subject current = Subject.current(); + Subject current = getCurrentSubject(); for (Principal p : current.getPrincipals()) { if (user.equals(p.getName())) { found = true; @@ -65,61 +82,84 @@ public Result authenticate(HttpExchange exchange) { .authenticatedSubjectAttributeName("aa") .buildAndStart(); - run(server, "204", "/"); + run(server, "/", 204, ""); } - private static void run(HTTPServer server, String expected, String path) throws IOException { - try (Socket socket = new Socket()) { - socket.connect(new InetSocketAddress("localhost", server.getPort())); - - socket - .getOutputStream() - .write(("GET " + path + " HTTP/1.1 \r\n").getBytes(StandardCharsets.UTF_8)); - socket.getOutputStream().write("HOST: localhost \r\n\r\n".getBytes(StandardCharsets.UTF_8)); - socket.getOutputStream().flush(); - - String actualResponse = ""; - byte[] resp = new byte[500]; - int read = socket.getInputStream().read(resp, 0, resp.length); - if (read > 0) { - actualResponse = new String(resp, 0, read, StandardCharsets.UTF_8); - } - assertThat(actualResponse).contains(expected); - } + @Test + void testSubjectDoAsWithInvalidSubject() throws Exception { + Authenticator authenticator = + new Authenticator() { + @Override + public Result authenticate(HttpExchange exchange) { + exchange.setAttribute("aa", "not-a-subject"); + return new Success(new HttpPrincipal("user", "/")); + } + }; + + HttpHandler handler = exchange -> exchange.sendResponseHeaders(204, -1); + HTTPServer server = + HTTPServer.builder() + .port(0) + .authenticator(authenticator) + .defaultHandler(handler) + .authenticatedSubjectAttributeName("aa") + .buildAndStart(); + + run(server, "/", 403, ""); } @Test - void defaultHandler() throws IOException { - run(HTTPServer.builder().port(0).buildAndStart(), "200", "/"); + void defaultHandler() throws Exception { + run( + HTTPServer.builder().port(0).buildAndStart(), + "/", + 200, + "Prometheus Java Client"); } @Test - void metrics() throws IOException { + void metrics() throws Exception { run( HTTPServer.builder() .port(0) - .registry(new PrometheusRegistry()) + .registry(registry) .executorService(Executors.newFixedThreadPool(1)) .buildAndStart(), - "200", - "/metrics"); + "/metrics", + 200, + "my_counter_total 1.0"); } @Test - void metricsCustomPath() throws IOException { + void metricsCustomPath() throws Exception { run( HTTPServer.builder() .port(0) - .registry(new PrometheusRegistry()) + .registry(registry) .metricsHandlerPath("/my-metrics") .executorService(Executors.newFixedThreadPool(1)) .buildAndStart(), - "200", - "/my-metrics"); + "/my-metrics", + 200, + "my_counter_total 1.0"); + } + + @Test + void metricsCustomRootPath() throws Exception { + run( + HTTPServer.builder() + .port(0) + .registry(registry) + .metricsHandlerPath("/") + .executorService(Executors.newFixedThreadPool(1)) + .buildAndStart(), + "/", + 200, + "my_counter_total 1.0"); } @Test - void registryThrows() throws IOException { + void registryThrows() throws Exception { HTTPServer server = HTTPServer.builder() .port(0) @@ -131,11 +171,12 @@ public MetricSnapshots scrape(PrometheusScrapeRequest scrapeRequest) { } }) .buildAndStart(); - run(server, "500", "/metrics"); + run(server, "/metrics", 500, "An Exception occurred while scraping metrics"); } @Test - void config() throws NoSuchAlgorithmException, IOException { + @SuppressWarnings("resource") + void config() { assertThatExceptionOfType(IllegalStateException.class) .isThrownBy( () -> @@ -146,23 +187,27 @@ void config() throws NoSuchAlgorithmException, IOException { .buildAndStart()) .withMessage("cannot configure 'inetAddress' and 'hostname' at the same time"); - // ssl doesn't work without in tests - run( - HTTPServer.builder() - .port(0) - .httpsConfigurator(new HttpsConfigurator(SSLContext.getDefault())) - .buildAndStart(), - "", - "/"); + // SSL doesn't work in this simple test configuration + assertThatExceptionOfType(IOException.class) + .isThrownBy( + () -> + run( + HTTPServer.builder() + .port(0) + .httpsConfigurator(new HttpsConfigurator(SSLContext.getDefault())) + .buildAndStart(), + "/", + 0, + "ignored")); } @Test - void health() throws IOException { - run(HTTPServer.builder().port(0).buildAndStart(), "200", "/-/healthy"); + void health() throws Exception { + run(HTTPServer.builder().port(0).buildAndStart(), "/-/healthy", 200, "Exporter is healthy."); } @Test - void healthEnabled() throws IOException { + void healthEnabled() throws Exception { HttpHandler handler = exchange -> exchange.sendResponseHeaders(204, -1); run( HTTPServer.builder() @@ -170,12 +215,13 @@ void healthEnabled() throws IOException { .defaultHandler(handler) .registerHealthHandler(true) .buildAndStart(), - "200", - "/-/healthy"); + "/-/healthy", + 200, + "Exporter is healthy."); } @Test - void healthDisabled() throws IOException { + void healthDisabled() throws Exception { HttpHandler handler = exchange -> exchange.sendResponseHeaders(204, -1); run( HTTPServer.builder() @@ -183,7 +229,50 @@ void healthDisabled() throws IOException { .defaultHandler(handler) .registerHealthHandler(false) .buildAndStart(), - "204", - "/-/healthy"); + "/-/healthy", + 204, + ""); + } + + private static void run( + HTTPServer server, String path, int expectedStatusCode, String expectedBody) + throws Exception { + // we cannot use try-with-resources or even client.close(), or the test will fail with Java 17 + @SuppressWarnings("resource") + final HttpClient client = HttpClient.newBuilder().build(); + try { + final URI uri = URI.create("http://localhost:%s%s".formatted(server.getPort(), path)); + final HttpRequest request = HttpRequest.newBuilder().uri(uri).GET().build(); + + final HttpResponse response = + client.send(request, HttpResponse.BodyHandlers.ofString()); + assertThat(response.statusCode()).isEqualTo(expectedStatusCode); + assertThat(response.body()).contains(expectedBody); + } finally { + server.stop(); + } + } + + /** + * Get current Subject using reflection to support both Java 17 and Java 18+. + * + *

Java 18+ has Subject.current(), but Java 17 and earlier require + * Subject.getSubject(AccessController.getContext()). + */ + @SuppressWarnings({"removal"}) + private static Subject getCurrentSubject() { + try { + Method currentMethod = Subject.class.getMethod("current"); + return (Subject) currentMethod.invoke(null); + } catch (NoSuchMethodException e) { + // Fall back to pre-Java 18 API + try { + return Subject.getSubject(java.security.AccessController.getContext()); + } catch (Exception ex) { + throw new RuntimeException("Failed to get current Subject", ex); + } + } catch (Exception e) { + throw new RuntimeException("Failed to invoke Subject.current()", e); + } } } diff --git a/prometheus-metrics-exporter-httpserver/src/test/java/io/prometheus/metrics/exporter/httpserver/HttpExchangeAdapterTest.java b/prometheus-metrics-exporter-httpserver/src/test/java/io/prometheus/metrics/exporter/httpserver/HttpExchangeAdapterTest.java new file mode 100644 index 000000000..19bc0d66e --- /dev/null +++ b/prometheus-metrics-exporter-httpserver/src/test/java/io/prometheus/metrics/exporter/httpserver/HttpExchangeAdapterTest.java @@ -0,0 +1,49 @@ +package io.prometheus.metrics.exporter.httpserver; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpExchange; +import java.net.URI; +import java.util.List; +import org.junit.jupiter.api.Test; + +class HttpExchangeAdapterTest { + + @Test + void getRequestPath() { + HttpExchange httpExchange = mock(HttpExchange.class); + when(httpExchange.getRequestURI()).thenReturn(URI.create("/metrics?name=test")); + HttpExchangeAdapter adapter = new HttpExchangeAdapter(httpExchange); + assertThat(adapter.getRequest().getRequestPath()).isEqualTo("/metrics"); + } + + @Test + void getRequestPathWithoutQueryString() { + HttpExchange httpExchange = mock(HttpExchange.class); + when(httpExchange.getRequestURI()).thenReturn(URI.create("/metrics")); + HttpExchangeAdapter adapter = new HttpExchangeAdapter(httpExchange); + assertThat(adapter.getRequest().getRequestPath()).isEqualTo("/metrics"); + } + + @Test + void getHeadersWhenPresent() { + HttpExchange httpExchange = mock(HttpExchange.class); + Headers headers = new Headers(); + headers.put("Accept", List.of("text/plain")); + when(httpExchange.getRequestHeaders()).thenReturn(headers); + HttpExchangeAdapter adapter = new HttpExchangeAdapter(httpExchange); + assertThat(adapter.getRequest().getHeaders("Accept").nextElement()).isEqualTo("text/plain"); + } + + @Test + void getHeadersWhenNotPresent() { + HttpExchange httpExchange = mock(HttpExchange.class); + Headers headers = new Headers(); + when(httpExchange.getRequestHeaders()).thenReturn(headers); + HttpExchangeAdapter adapter = new HttpExchangeAdapter(httpExchange); + assertThat(adapter.getRequest().getHeaders("Accept").hasMoreElements()).isFalse(); + } +} diff --git a/prometheus-metrics-exporter-opentelemetry-otel-agent-resources/pom.xml b/prometheus-metrics-exporter-opentelemetry-otel-agent-resources/pom.xml index b87712160..40ce26a57 100644 --- a/prometheus-metrics-exporter-opentelemetry-otel-agent-resources/pom.xml +++ b/prometheus-metrics-exporter-opentelemetry-otel-agent-resources/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-exporter-opentelemetry-otel-agent-resources @@ -21,6 +21,8 @@ io.prometheus.otel.resource.attributes 1.29.0 + + 0.50 @@ -59,6 +61,40 @@ + + org.jacoco + jacoco-maven-plugin + + + **/io/opentelemetry/** + + + + + check + + check + + + + + CLASS + + + LINE + COVEREDRATIO + ${jacoco.line-coverage} + + + + io.opentelemetry.** + + + + + + + diff --git a/prometheus-metrics-exporter-opentelemetry-otel-agent-resources/src/test/java/io/prometheus/otelagent/ResourceAttributesFromOtelAgentTest.java b/prometheus-metrics-exporter-opentelemetry-otel-agent-resources/src/test/java/io/prometheus/otelagent/ResourceAttributesFromOtelAgentTest.java new file mode 100644 index 000000000..9f0165b45 --- /dev/null +++ b/prometheus-metrics-exporter-opentelemetry-otel-agent-resources/src/test/java/io/prometheus/otelagent/ResourceAttributesFromOtelAgentTest.java @@ -0,0 +1,67 @@ +package io.prometheus.otelagent; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Map; +import org.junit.jupiter.api.Test; + +class ResourceAttributesFromOtelAgentTest { + + @Test + void testGetResourceAttributesWithoutOtelAgent() { + // When OTel agent is not attached, should return empty map + Map attributes = + ResourceAttributesFromOtelAgent.getResourceAttributes("test-scope"); + assertThat(attributes).isEmpty(); + } + + @Test + void testGetResourceAttributesWithDifferentInstrumentationScopes() { + // Test with different scope names to ensure temp directory creation works + Map attributes1 = + ResourceAttributesFromOtelAgent.getResourceAttributes("scope-one"); + Map attributes2 = + ResourceAttributesFromOtelAgent.getResourceAttributes("scope-two"); + + assertThat(attributes1).isEmpty(); + assertThat(attributes2).isEmpty(); + } + + @Test + void testGetResourceAttributesHandlesExceptions() { + // Test with special characters that might cause issues in temp directory names + Map attributes = + ResourceAttributesFromOtelAgent.getResourceAttributes("test/scope"); + // Should not throw, should return empty map + assertThat(attributes).isEmpty(); + } + + @Test + void testGetResourceAttributesReturnsImmutableMap() { + Map attributes = + ResourceAttributesFromOtelAgent.getResourceAttributes("test-scope"); + + // Verify the returned map is not null + assertThat(attributes).isNotNull(); + + // The returned map should be unmodifiable (per implementation) + try { + attributes.put("test.key", "test.value"); + // If we get here without exception, it's not truly immutable, + // but we still verify it returned empty + assertThat(attributes).isEmpty(); + } catch (UnsupportedOperationException e) { + // This is the expected behavior for an immutable map + assertThat(attributes).isEmpty(); + } + } + + @Test + void testGetResourceAttributesWithNullKey() { + // Test the null handling in the attribute map processing + // Without OTel agent, this returns empty map, but tests the null check logic + Map attributes = + ResourceAttributesFromOtelAgent.getResourceAttributes("test-scope"); + assertThat(attributes).isEmpty(); + } +} diff --git a/prometheus-metrics-exporter-opentelemetry-shaded/pom.xml b/prometheus-metrics-exporter-opentelemetry-shaded/pom.xml index c08919d13..a30a16847 100644 --- a/prometheus-metrics-exporter-opentelemetry-shaded/pom.xml +++ b/prometheus-metrics-exporter-opentelemetry-shaded/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-exporter-opentelemetry diff --git a/prometheus-metrics-exporter-opentelemetry/pom.xml b/prometheus-metrics-exporter-opentelemetry/pom.xml index acae00e0a..7d427d96b 100644 --- a/prometheus-metrics-exporter-opentelemetry/pom.xml +++ b/prometheus-metrics-exporter-opentelemetry/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-exporter-opentelemetry-no-otel diff --git a/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/OtelAutoConfig.java b/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/OtelAutoConfig.java index 4a16ee07e..e0c6a0fa9 100644 --- a/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/OtelAutoConfig.java +++ b/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/OtelAutoConfig.java @@ -112,7 +112,7 @@ static Resource getResourceField(AutoConfiguredOpenTelemetrySdk sdk) { Method method = AutoConfiguredOpenTelemetrySdk.class.getDeclaredMethod("getResource"); method.setAccessible(true); return (Resource) method.invoke(sdk); - } catch (Exception e) { + } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } } diff --git a/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusInstrumentationScope.java b/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusInstrumentationScope.java index 5f02d38cc..91241295a 100644 --- a/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusInstrumentationScope.java +++ b/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusInstrumentationScope.java @@ -1,6 +1,8 @@ package io.prometheus.metrics.exporter.opentelemetry; import io.opentelemetry.sdk.common.InstrumentationScopeInfo; +import java.io.IOException; +import java.io.InputStream; import java.util.Properties; class PrometheusInstrumentationScope { @@ -21,8 +23,15 @@ static InstrumentationScopeInfo loadInstrumentationScopeInfo( String path, String nameKey, String versionKey) { try { Properties properties = new Properties(); - properties.load( - PrometheusInstrumentationScope.class.getClassLoader().getResourceAsStream(path)); + InputStream stream = + PrometheusInstrumentationScope.class.getClassLoader().getResourceAsStream(path); + if (stream == null) { + throw new IllegalStateException( + "Prometheus metrics library initialization error: Failed to read " + + path + + " from classpath."); + } + properties.load(stream); String instrumentationScopeName = properties.getProperty(nameKey); if (instrumentationScopeName == null) { throw new IllegalStateException( @@ -44,7 +53,7 @@ static InstrumentationScopeInfo loadInstrumentationScopeInfo( return InstrumentationScopeInfo.builder(instrumentationScopeName) .setVersion(instrumentationScopeVersion) .build(); - } catch (Exception e) { + } catch (IOException e) { throw new IllegalStateException( "Prometheus metrics library initialization error: Failed to read " + path diff --git a/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusMetricProducer.java b/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusMetricProducer.java index 54aa5135a..9344fc4db 100644 --- a/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusMetricProducer.java +++ b/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusMetricProducer.java @@ -41,8 +41,14 @@ public PrometheusMetricProducer( @Override public Collection collectAllMetrics() { - // TODO: We could add a filter configuration for the OpenTelemetry exporter and call - // registry.scrape(filter) if a filter is configured, like in the Servlet exporter. + // Note: Currently all metrics from the registry are exported. To add metric filtering + // similar to the Servlet exporter, one could: + // 1. Add filter properties to ExporterOpenTelemetryProperties (allowedNames, excludedNames, + // etc.) + // 2. Convert these properties to a Predicate using MetricNameFilter.builder() + // 3. Call registry.scrape(filter) instead of registry.scrape() + // OpenTelemetry also provides its own Views API for filtering and aggregation, which may be + // preferred for OpenTelemetry-specific deployments. MetricSnapshots snapshots = registry.scrape(); Resource resourceWithTargetInfo = resource.merge(resourceFromTargetInfo(snapshots)); InstrumentationScopeInfo scopeFromInfo = instrumentationScopeFromOtelScopeInfo(snapshots); diff --git a/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/ExemplarTest.java b/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/ExemplarTest.java index 48054b192..c21f1ead4 100644 --- a/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/ExemplarTest.java +++ b/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/ExemplarTest.java @@ -45,7 +45,7 @@ class ExemplarTest { private OpenTelemetryExporter openTelemetryExporter; @BeforeEach - public void setUp() { + void setUp() { openTelemetryExporter = OpenTelemetryExporter.builder() .endpoint("http://localhost:4317") @@ -64,7 +64,7 @@ public void setUp() { } @AfterEach - public void tearDown() { + void tearDown() { PrometheusRegistry.defaultRegistry.unregister(testCounter); openTelemetryExporter.close(); } diff --git a/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/ExportTest.java b/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/ExportTest.java index 55589ce84..5ec213563 100644 --- a/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/ExportTest.java +++ b/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/ExportTest.java @@ -29,7 +29,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -public class ExportTest { +class ExportTest { private static final Attributes ATTRIBUTES = Attributes.of(AttributeKey.stringKey("label"), "val", AttributeKey.stringKey("key"), "value"); diff --git a/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusInstrumentationScopeTest.java b/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusInstrumentationScopeTest.java index c50354b24..948dfc498 100644 --- a/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusInstrumentationScopeTest.java +++ b/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/PrometheusInstrumentationScopeTest.java @@ -22,7 +22,6 @@ void loadInstrumentationScopeInfo() { () -> PrometheusInstrumentationScope.loadInstrumentationScopeInfo( "instrumentationScope.properties", "name", "version")) - .havingRootCause() .withMessage( "Prometheus metrics library initialization error: name not found in" + " instrumentationScope.properties in classpath."); @@ -32,7 +31,6 @@ void loadInstrumentationScopeInfo() { () -> PrometheusInstrumentationScope.loadInstrumentationScopeInfo( "instrumentationScope.properties", "instrumentationScope.name", "version")) - .havingRootCause() .withMessage( "Prometheus metrics library initialization error: version not found in" + " instrumentationScope.properties in classpath."); diff --git a/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/otelmodel/ExponentialHistogramPointDataImplTest.java b/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/otelmodel/ExponentialHistogramPointDataImplTest.java new file mode 100644 index 000000000..066913420 --- /dev/null +++ b/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/otelmodel/ExponentialHistogramPointDataImplTest.java @@ -0,0 +1,92 @@ +package io.prometheus.metrics.exporter.opentelemetry.otelmodel; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.sdk.metrics.data.ExponentialHistogramBuckets; +import java.util.List; +import org.junit.jupiter.api.Test; + +class ExponentialHistogramPointDataImplTest { + + private static final ExponentialHistogramBuckets EMPTY_BUCKETS = + ExponentialHistogramBuckets.create(0, 0, List.of()); + + @Test + void hasMinReturnsTrueWhenMinIsNotNaN() { + ExponentialHistogramPointDataImpl histogramPoint = + new ExponentialHistogramPointDataImpl( + 0, + 10.0, + 5, + 0, + 1.0, + 5.0, + EMPTY_BUCKETS, + EMPTY_BUCKETS, + 0L, + 1L, + Attributes.empty(), + List.of()); + assertThat(histogramPoint.hasMin()).isTrue(); + assertThat(histogramPoint.getMin()).isEqualTo(1.0); + } + + @Test + void hasMinReturnsFalseWhenMinIsNaN() { + ExponentialHistogramPointDataImpl histogramPoint = + new ExponentialHistogramPointDataImpl( + 0, + 10.0, + 5, + 0, + Double.NaN, + 5.0, + EMPTY_BUCKETS, + EMPTY_BUCKETS, + 0L, + 1L, + Attributes.empty(), + List.of()); + assertThat(histogramPoint.hasMin()).isFalse(); + } + + @Test + void hasMaxReturnsTrueWhenMaxIsNotNaN() { + ExponentialHistogramPointDataImpl histogramPoint = + new ExponentialHistogramPointDataImpl( + 0, + 10.0, + 5, + 0, + 1.0, + 5.0, + EMPTY_BUCKETS, + EMPTY_BUCKETS, + 0L, + 1L, + Attributes.empty(), + List.of()); + assertThat(histogramPoint.hasMax()).isTrue(); + assertThat(histogramPoint.getMax()).isEqualTo(5.0); + } + + @Test + void hasMaxReturnsFalseWhenMaxIsNaN() { + ExponentialHistogramPointDataImpl histogramPoint = + new ExponentialHistogramPointDataImpl( + 0, + 10.0, + 5, + 0, + 1.0, + Double.NaN, + EMPTY_BUCKETS, + EMPTY_BUCKETS, + 0L, + 1L, + Attributes.empty(), + List.of()); + assertThat(histogramPoint.hasMax()).isFalse(); + } +} diff --git a/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/otelmodel/HistogramPointDataImplTest.java b/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/otelmodel/HistogramPointDataImplTest.java new file mode 100644 index 000000000..b5c4e9373 --- /dev/null +++ b/prometheus-metrics-exporter-opentelemetry/src/test/java/io/prometheus/metrics/exporter/opentelemetry/otelmodel/HistogramPointDataImplTest.java @@ -0,0 +1,80 @@ +package io.prometheus.metrics.exporter.opentelemetry.otelmodel; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import java.util.List; +import org.junit.jupiter.api.Test; + +class HistogramPointDataImplTest { + + @Test + void hasMinReturnsTrueWhenMinIsNotNaN() { + HistogramPointDataImpl histogramPoint = + new HistogramPointDataImpl( + 10.0, + 5, + 1.0, + 5.0, + List.of(1.0, 2.0), + List.of(2L, 3L), + 0L, + 1L, + Attributes.empty(), + List.of()); + assertThat(histogramPoint.hasMin()).isTrue(); + assertThat(histogramPoint.getMin()).isEqualTo(1.0); + } + + @Test + void hasMinReturnsFalseWhenMinIsNaN() { + HistogramPointDataImpl histogramPoint = + new HistogramPointDataImpl( + 10.0, + 5, + Double.NaN, + 5.0, + List.of(1.0, 2.0), + List.of(2L, 3L), + 0L, + 1L, + Attributes.empty(), + List.of()); + assertThat(histogramPoint.hasMin()).isFalse(); + } + + @Test + void hasMaxReturnsTrueWhenMaxIsNotNaN() { + HistogramPointDataImpl histogramPoint = + new HistogramPointDataImpl( + 10.0, + 5, + 1.0, + 5.0, + List.of(1.0, 2.0), + List.of(2L, 3L), + 0L, + 1L, + Attributes.empty(), + List.of()); + assertThat(histogramPoint.hasMax()).isTrue(); + assertThat(histogramPoint.getMax()).isEqualTo(5.0); + } + + @Test + void hasMaxReturnsFalseWhenMaxIsNaN() { + HistogramPointDataImpl histogramPoint = + new HistogramPointDataImpl( + 10.0, + 5, + 1.0, + Double.NaN, + List.of(1.0, 2.0), + List.of(2L, 3L), + 0L, + 1L, + Attributes.empty(), + List.of()); + assertThat(histogramPoint.hasMax()).isFalse(); + } +} diff --git a/prometheus-metrics-exporter-pushgateway/pom.xml b/prometheus-metrics-exporter-pushgateway/pom.xml index 6d59b2b4d..c466c8552 100644 --- a/prometheus-metrics-exporter-pushgateway/pom.xml +++ b/prometheus-metrics-exporter-pushgateway/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-exporter-pushgateway diff --git a/prometheus-metrics-exporter-pushgateway/src/main/java/io/prometheus/metrics/exporter/pushgateway/PushGateway.java b/prometheus-metrics-exporter-pushgateway/src/main/java/io/prometheus/metrics/exporter/pushgateway/PushGateway.java index 72e0561c1..594132cf2 100644 --- a/prometheus-metrics-exporter-pushgateway/src/main/java/io/prometheus/metrics/exporter/pushgateway/PushGateway.java +++ b/prometheus-metrics-exporter-pushgateway/src/main/java/io/prometheus/metrics/exporter/pushgateway/PushGateway.java @@ -253,6 +253,8 @@ private void doRequest(@Nullable PrometheusRegistry registry, String method) thr } } + // toString with Charset is only available in Java 10+, but we want to support Java 8 + @SuppressWarnings("JdkObsolete") private static String readFromStream(InputStream is) throws IOException { ByteArrayOutputStream result = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; @@ -394,7 +396,7 @@ public Builder escapingScheme(EscapingScheme escapingScheme) { /** * Use milliseconds for timestamps in text format? Default is {@code false}. Can be overwritten - * at runtime with the {@code io.prometheus.exporter.timestampsInMs} property. + * at runtime with the {@code io.prometheus.exporter.timestamps_in_ms} property. */ public Builder prometheusTimestampsInMs(boolean prometheusTimestampsInMs) { this.prometheusTimestampsInMs = prometheusTimestampsInMs; @@ -497,6 +499,8 @@ private Format getFormat() { return Format.PROMETHEUS_PROTOBUF; } + // encode with Charset is only available in Java 10+, but we want to support Java 8 + @SuppressWarnings("JdkObsolete") private URL makeUrl(@Nullable ExporterPushgatewayProperties properties) throws UnsupportedEncodingException, MalformedURLException { StringBuilder url = diff --git a/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/BasicAuthPushGatewayTest.java b/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/BasicAuthPushGatewayTest.java index e2f052d6b..137686d32 100644 --- a/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/BasicAuthPushGatewayTest.java +++ b/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/BasicAuthPushGatewayTest.java @@ -21,7 +21,7 @@ class BasicAuthPushGatewayTest { PushGateway pushGateway; @BeforeEach - public void setUp() { + void setUp() { mockServerClient = ClientAndServer.startClientAndServer(0); registry = new PrometheusRegistry(); gauge = Gauge.builder().name("g").help("help").build(); @@ -42,7 +42,7 @@ void tearDown() { } @Test - public void testAuthorizedPush() throws IOException { + void testAuthorizedPush() throws IOException { mockServerClient .when( request() diff --git a/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/BearerTokenPushGatewayTest.java b/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/BearerTokenPushGatewayTest.java index 09e6ff5e9..996442e5a 100644 --- a/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/BearerTokenPushGatewayTest.java +++ b/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/BearerTokenPushGatewayTest.java @@ -21,7 +21,7 @@ class BearerTokenPushGatewayTest { PushGateway pushGateway; @BeforeEach - public void setUp() { + void setUp() { mockServerClient = ClientAndServer.startClientAndServer(0); registry = new PrometheusRegistry(); gauge = Gauge.builder().name("g").help("help").build(); @@ -40,7 +40,7 @@ void tearDown() { } @Test - public void testAuthorizedPush() throws IOException { + void testAuthorizedPush() throws IOException { mockServerClient .when( request() diff --git a/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTest.java b/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTest.java index 4eba4cb17..bae8fdd91 100644 --- a/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTest.java +++ b/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTest.java @@ -26,7 +26,7 @@ class PushGatewayTest { Gauge gauge; @BeforeEach - public void setUp() { + void setUp() { mockServerClient = ClientAndServer.startClientAndServer(0); registry = new PrometheusRegistry(); gauge = Gauge.builder().name("g").help("help").build(); @@ -38,7 +38,7 @@ void tearDown() { } @Test - public void testInvalidURLThrowsRuntimeException() { + void testInvalidURLThrowsRuntimeException() { assertThatExceptionOfType(RuntimeException.class) .isThrownBy( () -> { @@ -49,8 +49,7 @@ public void testInvalidURLThrowsRuntimeException() { } @Test - public void testMultipleSlashesAreStrippedFromURL() - throws NoSuchFieldException, IllegalAccessException { + void testMultipleSlashesAreStrippedFromURL() throws NoSuchFieldException, IllegalAccessException { final PushGateway pushGateway = PushGateway.builder().address("example.com:1234/context///path//").job("test").build(); assertThat(getUrl(pushGateway)) @@ -64,7 +63,7 @@ private URL getUrl(PushGateway pushGateway) throws IllegalAccessException, NoSuc } @Test - public void testPush() throws IOException { + void testPush() throws IOException { mockServerClient .when(request().withMethod("PUT").withPath("/metrics/job/j")) .respond(response().withStatusCode(202)); @@ -78,7 +77,7 @@ public void testPush() throws IOException { } @Test - public void testPush200Response() throws IOException { + void testPush200Response() throws IOException { mockServerClient .when(request().withMethod("PUT").withPath("/metrics/job/j")) .respond(response().withStatusCode(200)); @@ -92,7 +91,7 @@ public void testPush200Response() throws IOException { } @Test - public void testNon202ResponseThrows() { + void testNon202ResponseThrows() { mockServerClient .when(request().withMethod("PUT").withPath("/metrics/job/j")) .respond(response().withStatusCode(500)); @@ -114,7 +113,7 @@ public void testNon202ResponseThrows() { } @Test - public void testPushCollector() throws IOException { + void testPushCollector() throws IOException { mockServerClient .when(request().withMethod("PUT").withPath("/metrics/job/j")) .respond(response().withStatusCode(202)); @@ -128,7 +127,7 @@ public void testPushCollector() throws IOException { } @Test - public void testPushWithGroupingKey() throws IOException { + void testPushWithGroupingKey() throws IOException { mockServerClient .when(request().withMethod("PUT").withPath("/metrics/job/j/l/v")) .respond(response().withStatusCode(202)); @@ -143,7 +142,7 @@ public void testPushWithGroupingKey() throws IOException { } @Test - public void testPushWithEscapedGroupingKey() throws IOException { + void testPushWithEscapedGroupingKey() throws IOException { mockServerClient .when(request().withMethod("PUT").withPath("/metrics/job/j/U__l_2e_1/v1")) .respond(response().withStatusCode(202)); @@ -158,7 +157,7 @@ public void testPushWithEscapedGroupingKey() throws IOException { } @Test - public void testPushWithMultiGroupingKey() throws IOException { + void testPushWithMultiGroupingKey() throws IOException { mockServerClient .when(request().withMethod("PUT").withPath("/metrics/job/j/l/v/l2/v2")) .respond(response().withStatusCode(202)); @@ -174,7 +173,7 @@ public void testPushWithMultiGroupingKey() throws IOException { } @Test - public void testPushWithMultiEscapedGroupingKey() throws IOException { + void testPushWithMultiEscapedGroupingKey() throws IOException { mockServerClient .when(request().withMethod("PUT").withPath("/metrics/job/j/U__l_2e_1/v1/U__l_2e_2/v2")) @@ -191,7 +190,7 @@ public void testPushWithMultiEscapedGroupingKey() throws IOException { } @Test - public void testPushWithEmptyLabelGroupingKey() throws IOException { + void testPushWithEmptyLabelGroupingKey() throws IOException { mockServerClient .when(request().withMethod("PUT").withPath("/metrics/job/j/l/v/l2@base64/=")) .respond(response().withStatusCode(202)); @@ -207,7 +206,7 @@ public void testPushWithEmptyLabelGroupingKey() throws IOException { } @Test - public void testPushWithGroupingKeyWithSlashes() throws IOException { + void testPushWithGroupingKeyWithSlashes() throws IOException { mockServerClient .when( request().withMethod("PUT").withPath("/metrics/job@base64/YS9i/l/v/l2@base64/75-_Lw==")) @@ -224,7 +223,7 @@ public void testPushWithGroupingKeyWithSlashes() throws IOException { } @Test - public void testPushCollectorWithGroupingKey() throws IOException { + void testPushCollectorWithGroupingKey() throws IOException { mockServerClient .when(request().withMethod("PUT").withPath("/metrics/job/j/l/v")) .respond(response().withStatusCode(202)); @@ -239,7 +238,7 @@ public void testPushCollectorWithGroupingKey() throws IOException { } @Test - public void testPushCollectorWithEscapedGroupingKey() throws IOException { + void testPushCollectorWithEscapedGroupingKey() throws IOException { mockServerClient .when(request().withMethod("PUT").withPath("/metrics/job/j/U__l_2e_1/v1")) .respond(response().withStatusCode(202)); @@ -254,7 +253,7 @@ public void testPushCollectorWithEscapedGroupingKey() throws IOException { } @Test - public void testPushAdd() throws IOException { + void testPushAdd() throws IOException { mockServerClient .when(request().withMethod("POST").withPath("/metrics/job/j")) .respond(response().withStatusCode(202)); @@ -268,7 +267,7 @@ public void testPushAdd() throws IOException { } @Test - public void testPushAddCollector() throws IOException { + void testPushAddCollector() throws IOException { mockServerClient .when(request().withMethod("POST").withPath("/metrics/job/j")) .respond(response().withStatusCode(202)); @@ -278,7 +277,7 @@ public void testPushAddCollector() throws IOException { } @Test - public void testPushAddWithGroupingKey() throws IOException { + void testPushAddWithGroupingKey() throws IOException { mockServerClient .when(request().withMethod("POST").withPath("/metrics/job/j/l/v")) .respond(response().withStatusCode(202)); @@ -293,7 +292,7 @@ public void testPushAddWithGroupingKey() throws IOException { } @Test - public void testPushAddWithEscapedGroupingKey() throws IOException { + void testPushAddWithEscapedGroupingKey() throws IOException { mockServerClient .when(request().withMethod("POST").withPath("/metrics/job/j/U__l_2e_1/v1")) .respond(response().withStatusCode(202)); @@ -308,7 +307,7 @@ public void testPushAddWithEscapedGroupingKey() throws IOException { } @Test - public void testPushAddCollectorWithGroupingKey() throws IOException { + void testPushAddCollectorWithGroupingKey() throws IOException { mockServerClient .when(request().withMethod("POST").withPath("/metrics/job/j/l/v")) .respond(response().withStatusCode(202)); @@ -323,7 +322,7 @@ public void testPushAddCollectorWithGroupingKey() throws IOException { } @Test - public void testPushAddCollectorWithEscapedGroupingKey() throws IOException { + void testPushAddCollectorWithEscapedGroupingKey() throws IOException { mockServerClient .when(request().withMethod("POST").withPath("/metrics/job/j/U__l_2e_1/v1")) @@ -339,7 +338,7 @@ public void testPushAddCollectorWithEscapedGroupingKey() throws IOException { } @Test - public void testDelete() throws IOException { + void testDelete() throws IOException { mockServerClient .when(request().withMethod("DELETE").withPath("/metrics/job/j")) .respond(response().withStatusCode(202)); @@ -349,7 +348,7 @@ public void testDelete() throws IOException { } @Test - public void testDeleteWithGroupingKey() throws IOException { + void testDeleteWithGroupingKey() throws IOException { mockServerClient .when(request().withMethod("DELETE").withPath("/metrics/job/j/l/v")) .respond(response().withStatusCode(202)); @@ -363,7 +362,7 @@ public void testDeleteWithGroupingKey() throws IOException { } @Test - public void testDeleteWithEscapedGroupingKey() throws IOException { + void testDeleteWithEscapedGroupingKey() throws IOException { mockServerClient .when(request().withMethod("DELETE").withPath("/metrics/job/j/U__l_2e_1/v1")) @@ -378,7 +377,7 @@ public void testDeleteWithEscapedGroupingKey() throws IOException { } @Test - public void testInstanceIpGroupingKey() throws IOException { + void testInstanceIpGroupingKey() throws IOException { String ip = InetAddress.getLocalHost().getHostAddress(); assertThat(ip).isNotEmpty(); mockServerClient @@ -395,7 +394,7 @@ public void testInstanceIpGroupingKey() throws IOException { } @Test - public void testInstanceIpEscapedGroupingKey() throws IOException { + void testInstanceIpEscapedGroupingKey() throws IOException { String ip = InetAddress.getLocalHost().getHostAddress(); assertThat(ip).isNotEmpty(); @@ -416,7 +415,7 @@ public void testInstanceIpEscapedGroupingKey() throws IOException { } @Test - public void testEscapingSchemeDefaultValue() throws IllegalAccessException, NoSuchFieldException { + void testEscapingSchemeDefaultValue() throws IllegalAccessException, NoSuchFieldException { PushGateway pg = PushGateway.builder() .address("localhost:" + mockServerClient.getPort()) diff --git a/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/SchemeTest.java b/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/SchemeTest.java index 6695a2911..0f6bf61d9 100644 --- a/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/SchemeTest.java +++ b/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/SchemeTest.java @@ -9,6 +9,8 @@ class SchemeTest { @Test void fromString() { + assertThat(Scheme.fromString("http")).isEqualTo(Scheme.HTTP); + assertThat(Scheme.fromString("https")).isEqualTo(Scheme.HTTPS); assertThat(Scheme.HTTP).hasToString("http"); assertThat(Scheme.HTTPS).hasToString("https"); assertThatExceptionOfType(IllegalArgumentException.class) diff --git a/prometheus-metrics-exporter-servlet-jakarta/pom.xml b/prometheus-metrics-exporter-servlet-jakarta/pom.xml index 263428a20..6dd93f190 100644 --- a/prometheus-metrics-exporter-servlet-jakarta/pom.xml +++ b/prometheus-metrics-exporter-servlet-jakarta/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-exporter-servlet-jakarta @@ -34,5 +34,13 @@ 6.1.0 provided + + + + io.prometheus + prometheus-metrics-core + ${project.version} + test + diff --git a/prometheus-metrics-exporter-servlet-jakarta/src/test/java/io/prometheus/metrics/exporter/servlet/jakarta/HttpExchangeAdapterTest.java b/prometheus-metrics-exporter-servlet-jakarta/src/test/java/io/prometheus/metrics/exporter/servlet/jakarta/HttpExchangeAdapterTest.java new file mode 100644 index 000000000..7a795cc04 --- /dev/null +++ b/prometheus-metrics-exporter-servlet-jakarta/src/test/java/io/prometheus/metrics/exporter/servlet/jakarta/HttpExchangeAdapterTest.java @@ -0,0 +1,165 @@ +package io.prometheus.metrics.exporter.servlet.jakarta; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.prometheus.metrics.exporter.common.PrometheusHttpRequest; +import io.prometheus.metrics.exporter.common.PrometheusHttpResponse; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Collections; +import org.junit.jupiter.api.Test; + +class HttpExchangeAdapterTest { + + @Test + void testRequestGetQueryString() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + when(servletRequest.getQueryString()).thenReturn("name[]=test"); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpRequest request = adapter.getRequest(); + + assertThat(request.getQueryString()).isEqualTo("name[]=test"); + } + + @Test + void testRequestGetHeaders() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + when(servletRequest.getHeaders("Accept")) + .thenReturn(Collections.enumeration(Collections.singletonList("text/plain"))); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpRequest request = adapter.getRequest(); + + assertThat(request.getHeaders("Accept").nextElement()).isEqualTo("text/plain"); + } + + @Test + void testRequestGetMethod() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + when(servletRequest.getMethod()).thenReturn("GET"); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpRequest request = adapter.getRequest(); + + assertThat(request.getMethod()).isEqualTo("GET"); + } + + @Test + void testRequestGetRequestPath() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + when(servletRequest.getContextPath()).thenReturn("/app"); + when(servletRequest.getServletPath()).thenReturn("/metrics"); + when(servletRequest.getPathInfo()).thenReturn(null); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpRequest request = adapter.getRequest(); + + assertThat(request.getRequestPath()).isEqualTo("/app/metrics"); + } + + @Test + void testRequestGetRequestPathWithPathInfo() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + when(servletRequest.getContextPath()).thenReturn("/app"); + when(servletRequest.getServletPath()).thenReturn("/metrics"); + when(servletRequest.getPathInfo()).thenReturn("/extra"); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpRequest request = adapter.getRequest(); + + assertThat(request.getRequestPath()).isEqualTo("/app/metrics/extra"); + } + + @Test + void testResponseSetHeader() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpResponse response = adapter.getResponse(); + + response.setHeader("Content-Type", "text/plain"); + verify(servletResponse).setHeader("Content-Type", "text/plain"); + } + + @Test + void testResponseSendHeadersAndGetBody() throws IOException { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + ServletOutputStream outputStream = mock(ServletOutputStream.class); + when(servletResponse.getOutputStream()).thenReturn(outputStream); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpResponse response = adapter.getResponse(); + + response.sendHeadersAndGetBody(200, 100); + + verify(servletResponse).setContentLength(100); + verify(servletResponse).setStatus(200); + verify(servletResponse).getOutputStream(); + } + + @Test + void testResponseSendHeadersWithContentLengthAlreadySet() throws IOException { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + ServletOutputStream outputStream = mock(ServletOutputStream.class); + when(servletResponse.getHeader("Content-Length")).thenReturn("50"); + when(servletResponse.getOutputStream()).thenReturn(outputStream); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpResponse response = adapter.getResponse(); + + response.sendHeadersAndGetBody(200, 100); + + verify(servletResponse).setStatus(200); + verify(servletResponse).getOutputStream(); + } + + @Test + void testHandleIOException() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + IOException exception = new IOException("Test exception"); + + assertThatExceptionOfType(IOException.class) + .isThrownBy(() -> adapter.handleException(exception)) + .withMessage("Test exception"); + } + + @Test + void testHandleRuntimeException() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + RuntimeException exception = new RuntimeException("Test exception"); + + assertThatExceptionOfType(RuntimeException.class) + .isThrownBy(() -> adapter.handleException(exception)) + .withMessage("Test exception"); + } + + @Test + void testClose() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + adapter.close(); // Should not throw + } +} diff --git a/prometheus-metrics-exporter-servlet-jakarta/src/test/java/io/prometheus/metrics/exporter/servlet/jakarta/PrometheusMetricsServletTest.java b/prometheus-metrics-exporter-servlet-jakarta/src/test/java/io/prometheus/metrics/exporter/servlet/jakarta/PrometheusMetricsServletTest.java new file mode 100644 index 000000000..5d0d66bfd --- /dev/null +++ b/prometheus-metrics-exporter-servlet-jakarta/src/test/java/io/prometheus/metrics/exporter/servlet/jakarta/PrometheusMetricsServletTest.java @@ -0,0 +1,82 @@ +package io.prometheus.metrics.exporter.servlet.jakarta; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import io.prometheus.metrics.core.metrics.Counter; +import io.prometheus.metrics.model.registry.PrometheusRegistry; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.WriteListener; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class PrometheusMetricsServletTest { + + private PrometheusRegistry registry; + private Counter testCounter; + + @BeforeEach + void setUp() { + registry = new PrometheusRegistry(); + testCounter = Counter.builder().name("test_counter").help("Test counter").register(registry); + testCounter.inc(42); + } + + @Test + void testDoGetWritesMetrics() throws IOException { + HttpServletRequest request = mock(HttpServletRequest.class); + HttpServletResponse response = mock(HttpServletResponse.class); + + when(request.getQueryString()).thenReturn(null); + when(request.getMethod()).thenReturn("GET"); + when(request.getHeaders("Accept-Encoding")).thenReturn(Collections.emptyEnumeration()); + when(request.getHeaders("Accept")).thenReturn(Collections.emptyEnumeration()); + when(request.getContextPath()).thenReturn(""); + when(request.getServletPath()).thenReturn("/metrics"); + when(request.getPathInfo()).thenReturn(null); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + when(response.getOutputStream()) + .thenReturn( + new ServletOutputStream() { + @Override + public void write(int b) throws IOException { + outputStream.write(b); + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setWriteListener(WriteListener writeListener) {} + }); + + PrometheusMetricsServlet servlet = new PrometheusMetricsServlet(registry); + servlet.doGet(request, response); + + String output = outputStream.toString(StandardCharsets.UTF_8.name()); + assertThat(output).contains("test_counter"); + assertThat(output).contains("42.0"); + } + + @Test + void testServletUsesDefaultRegistry() { + PrometheusMetricsServlet servlet = new PrometheusMetricsServlet(); + assertThat(servlet).isNotNull(); + } + + @Test + void testServletWithCustomRegistry() { + PrometheusMetricsServlet servlet = new PrometheusMetricsServlet(registry); + assertThat(servlet).isNotNull(); + } +} diff --git a/prometheus-metrics-exporter-servlet-javax/pom.xml b/prometheus-metrics-exporter-servlet-javax/pom.xml index 30cd52539..9d78816f0 100644 --- a/prometheus-metrics-exporter-servlet-javax/pom.xml +++ b/prometheus-metrics-exporter-servlet-javax/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-exporter-servlet-javax @@ -41,6 +41,14 @@ 4.0.1 provided + + + + io.prometheus + prometheus-metrics-core + ${project.version} + test + diff --git a/prometheus-metrics-exporter-servlet-javax/src/test/java/io/prometheus/metrics/exporter/servlet/javax/HttpExchangeAdapterTest.java b/prometheus-metrics-exporter-servlet-javax/src/test/java/io/prometheus/metrics/exporter/servlet/javax/HttpExchangeAdapterTest.java new file mode 100644 index 000000000..f4f1f0f3f --- /dev/null +++ b/prometheus-metrics-exporter-servlet-javax/src/test/java/io/prometheus/metrics/exporter/servlet/javax/HttpExchangeAdapterTest.java @@ -0,0 +1,190 @@ +package io.prometheus.metrics.exporter.servlet.javax; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.prometheus.metrics.exporter.common.PrometheusHttpRequest; +import io.prometheus.metrics.exporter.common.PrometheusHttpResponse; +import java.io.IOException; +import java.util.Collections; +import javax.servlet.ServletOutputStream; +import javax.servlet.WriteListener; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.junit.jupiter.api.Test; + +class HttpExchangeAdapterTest { + + @Test + void testRequestGetQueryString() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + when(servletRequest.getQueryString()).thenReturn("name[]=test"); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpRequest request = adapter.getRequest(); + + assertThat(request.getQueryString()).isEqualTo("name[]=test"); + } + + @Test + void testRequestGetHeaders() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + when(servletRequest.getHeaders("Accept")) + .thenReturn(Collections.enumeration(Collections.singletonList("text/plain"))); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpRequest request = adapter.getRequest(); + + assertThat(request.getHeaders("Accept").nextElement()).isEqualTo("text/plain"); + } + + @Test + void testRequestGetMethod() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + when(servletRequest.getMethod()).thenReturn("GET"); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpRequest request = adapter.getRequest(); + + assertThat(request.getMethod()).isEqualTo("GET"); + } + + @Test + void testRequestGetRequestPath() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + when(servletRequest.getContextPath()).thenReturn("/app"); + when(servletRequest.getServletPath()).thenReturn("/metrics"); + when(servletRequest.getPathInfo()).thenReturn(null); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpRequest request = adapter.getRequest(); + + assertThat(request.getRequestPath()).isEqualTo("/app/metrics"); + } + + @Test + void testRequestGetRequestPathWithPathInfo() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + when(servletRequest.getContextPath()).thenReturn("/app"); + when(servletRequest.getServletPath()).thenReturn("/metrics"); + when(servletRequest.getPathInfo()).thenReturn("/extra"); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpRequest request = adapter.getRequest(); + + assertThat(request.getRequestPath()).isEqualTo("/app/metrics/extra"); + } + + @Test + void testResponseSetHeader() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpResponse response = adapter.getResponse(); + + response.setHeader("Content-Type", "text/plain"); + verify(servletResponse).setHeader("Content-Type", "text/plain"); + } + + @Test + void testResponseSendHeadersAndGetBody() throws IOException { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + ServletOutputStream outputStream = + new ServletOutputStream() { + @Override + public void write(int b) throws IOException {} + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setWriteListener(WriteListener writeListener) {} + }; + when(servletResponse.getOutputStream()).thenReturn(outputStream); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpResponse response = adapter.getResponse(); + + response.sendHeadersAndGetBody(200, 100); + + verify(servletResponse).setContentLength(100); + verify(servletResponse).setStatus(200); + verify(servletResponse).getOutputStream(); + } + + @Test + void testResponseSendHeadersWithContentLengthAlreadySet() throws IOException { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + ServletOutputStream outputStream = + new ServletOutputStream() { + @Override + public void write(int b) throws IOException {} + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setWriteListener(WriteListener writeListener) {} + }; + when(servletResponse.getHeader("Content-Length")).thenReturn("50"); + when(servletResponse.getOutputStream()).thenReturn(outputStream); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + PrometheusHttpResponse response = adapter.getResponse(); + + response.sendHeadersAndGetBody(200, 100); + + verify(servletResponse).setStatus(200); + verify(servletResponse).getOutputStream(); + } + + @Test + void testHandleIOException() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + IOException exception = new IOException("Test exception"); + + assertThatExceptionOfType(IOException.class) + .isThrownBy(() -> adapter.handleException(exception)) + .withMessage("Test exception"); + } + + @Test + void testHandleRuntimeException() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + RuntimeException exception = new RuntimeException("Test exception"); + + assertThatExceptionOfType(RuntimeException.class) + .isThrownBy(() -> adapter.handleException(exception)) + .withMessage("Test exception"); + } + + @Test + void testClose() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + HttpExchangeAdapter adapter = new HttpExchangeAdapter(servletRequest, servletResponse); + adapter.close(); // Should not throw + } +} diff --git a/prometheus-metrics-exporter-servlet-javax/src/test/java/io/prometheus/metrics/exporter/servlet/javax/PrometheusMetricsServletTest.java b/prometheus-metrics-exporter-servlet-javax/src/test/java/io/prometheus/metrics/exporter/servlet/javax/PrometheusMetricsServletTest.java new file mode 100644 index 000000000..0b3c5e5f6 --- /dev/null +++ b/prometheus-metrics-exporter-servlet-javax/src/test/java/io/prometheus/metrics/exporter/servlet/javax/PrometheusMetricsServletTest.java @@ -0,0 +1,82 @@ +package io.prometheus.metrics.exporter.servlet.javax; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import io.prometheus.metrics.core.metrics.Counter; +import io.prometheus.metrics.model.registry.PrometheusRegistry; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import javax.servlet.ServletOutputStream; +import javax.servlet.WriteListener; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class PrometheusMetricsServletTest { + + private PrometheusRegistry registry; + private Counter testCounter; + + @BeforeEach + void setUp() { + registry = new PrometheusRegistry(); + testCounter = Counter.builder().name("test_counter").help("Test counter").register(registry); + testCounter.inc(42); + } + + @Test + void testDoGetWritesMetrics() throws IOException { + HttpServletRequest request = mock(HttpServletRequest.class); + HttpServletResponse response = mock(HttpServletResponse.class); + + when(request.getQueryString()).thenReturn(null); + when(request.getMethod()).thenReturn("GET"); + when(request.getHeaders("Accept-Encoding")).thenReturn(Collections.emptyEnumeration()); + when(request.getHeaders("Accept")).thenReturn(Collections.emptyEnumeration()); + when(request.getContextPath()).thenReturn(""); + when(request.getServletPath()).thenReturn("/metrics"); + when(request.getPathInfo()).thenReturn(null); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + when(response.getOutputStream()) + .thenReturn( + new ServletOutputStream() { + @Override + public void write(int b) throws IOException { + outputStream.write(b); + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setWriteListener(WriteListener writeListener) {} + }); + + PrometheusMetricsServlet servlet = new PrometheusMetricsServlet(registry); + servlet.doGet(request, response); + + String output = outputStream.toString(StandardCharsets.UTF_8.name()); + assertThat(output).contains("test_counter"); + assertThat(output).contains("42.0"); + } + + @Test + void testServletUsesDefaultRegistry() { + PrometheusMetricsServlet servlet = new PrometheusMetricsServlet(); + assertThat(servlet).isNotNull(); + } + + @Test + void testServletWithCustomRegistry() { + PrometheusMetricsServlet servlet = new PrometheusMetricsServlet(registry); + assertThat(servlet).isNotNull(); + } +} diff --git a/prometheus-metrics-exposition-formats-shaded/pom.xml b/prometheus-metrics-exposition-formats-shaded/pom.xml index 64e033366..d3e02eb2b 100644 --- a/prometheus-metrics-exposition-formats-shaded/pom.xml +++ b/prometheus-metrics-exposition-formats-shaded/pom.xml @@ -7,7 +7,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-exposition-formats diff --git a/prometheus-metrics-exposition-formats/generate-protobuf.sh b/prometheus-metrics-exposition-formats/generate-protobuf.sh index 9bd222241..323cf033c 100755 --- a/prometheus-metrics-exposition-formats/generate-protobuf.sh +++ b/prometheus-metrics-exposition-formats/generate-protobuf.sh @@ -18,7 +18,7 @@ mkdir -p "$TARGET_DIR" rm -rf $PROTO_DIR || true mkdir -p $PROTO_DIR -OLD_PACKAGE=$(sed -nE 's/import (io.prometheus.metrics.expositionformats.generated.*).Metrics;/\1/p' src/main/java/io/prometheus/metrics/expositionformats/internal/PrometheusProtobufWriterImpl.java) +OLD_PACKAGE=$(sed -nE 's/.*extends (io\.prometheus\.metrics\.expositionformats\.generated\.[^ ]*?)\.Metrics.*/\1/p' src/main/java/io/prometheus/metrics/expositionformats/generated/Metrics.java) PACKAGE="io.prometheus.metrics.expositionformats.generated.com_google_protobuf_${PROTOBUF_VERSION_STRING}" if [[ $OLD_PACKAGE != "$PACKAGE" ]]; then @@ -33,6 +33,10 @@ protoc --java_out "$TARGET_DIR" $PROTO_DIR/metrics.proto sed -i '1 i\//CHECKSTYLE:OFF: checkstyle' "$(find src/main/generated/io -type f)" sed -i -e $'$a\\\n//CHECKSTYLE:ON: checkstyle' "$(find src/main/generated/io -type f)" +GENERATED_FILE="$TARGET_DIR/${PACKAGE//\.//}/Metrics.java" +sed -i 's/public final class Metrics/public class Metrics/' "$GENERATED_FILE" +sed -i 's/private Metrics() {}/protected Metrics() {}/' "$GENERATED_FILE" + GENERATED_WITH=$(grep -oP '\/\/ Protobuf Java Version: \K.*' "$TARGET_DIR/${PACKAGE//\.//}"/Metrics.java) function help() { diff --git a/prometheus-metrics-exposition-formats/pom.xml b/prometheus-metrics-exposition-formats/pom.xml index bb780f0c2..5cb35db2e 100644 --- a/prometheus-metrics-exposition-formats/pom.xml +++ b/prometheus-metrics-exposition-formats/pom.xml @@ -7,7 +7,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-exposition-formats-no-protobuf diff --git a/prometheus-metrics-exposition-formats/src/main/generated/io/prometheus/metrics/expositionformats/generated/com_google_protobuf_4_33_2/Metrics.java b/prometheus-metrics-exposition-formats/src/main/generated/io/prometheus/metrics/expositionformats/generated/com_google_protobuf_4_33_5/Metrics.java similarity index 89% rename from prometheus-metrics-exposition-formats/src/main/generated/io/prometheus/metrics/expositionformats/generated/com_google_protobuf_4_33_2/Metrics.java rename to prometheus-metrics-exposition-formats/src/main/generated/io/prometheus/metrics/expositionformats/generated/com_google_protobuf_4_33_5/Metrics.java index 2adba900d..5f4788c14 100644 --- a/prometheus-metrics-exposition-formats/src/main/generated/io/prometheus/metrics/expositionformats/generated/com_google_protobuf_4_33_2/Metrics.java +++ b/prometheus-metrics-exposition-formats/src/main/generated/io/prometheus/metrics/expositionformats/generated/com_google_protobuf_4_33_5/Metrics.java @@ -2,19 +2,19 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: src/main/protobuf/metrics.proto -// Protobuf Java Version: 4.33.2 +// Protobuf Java Version: 4.33.5 -package io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2; +package io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5; @com.google.protobuf.Generated -public final class Metrics extends com.google.protobuf.GeneratedFile { - private Metrics() {} +public class Metrics extends com.google.protobuf.GeneratedFile { + protected Metrics() {} static { com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 33, - /* patch= */ 2, + /* patch= */ 5, /* suffix= */ "", "Metrics"); } @@ -87,7 +87,7 @@ public enum MetricType com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 33, - /* patch= */ 2, + /* patch= */ 5, /* suffix= */ "", "MetricType"); } @@ -193,7 +193,7 @@ public MetricType findValueByNumber(int number) { } public static com.google.protobuf.Descriptors.EnumDescriptor getDescriptor() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.getDescriptor().getEnumTypes().get(0); + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.getDescriptor().getEnumTypes().get(0); } private static final MetricType[] VALUES = values(); @@ -267,7 +267,7 @@ public static final class LabelPair extends com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 33, - /* patch= */ 2, + /* patch= */ 5, /* suffix= */ "", "LabelPair"); } @@ -282,15 +282,15 @@ private LabelPair() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_LabelPair_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_LabelPair_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_LabelPair_fieldAccessorTable + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_LabelPair_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder.class); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder.class); } private int bitField0_; @@ -437,10 +437,10 @@ public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair)) { + if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair)) { return super.equals(obj); } - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair) obj; + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair) obj; if (hasName() != other.hasName()) return false; if (hasName()) { @@ -476,44 +476,44 @@ public int hashCode() { return hash; } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair parseFrom( java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair parseFrom(byte[] data) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair parseFrom(java.io.InputStream input) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -521,26 +521,26 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto .parseWithIOException(PARSER, input, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair parseDelimitedFrom(java.io.InputStream input) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair parseDelimitedFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -553,7 +553,7 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair prototype) { + public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } @java.lang.Override @@ -574,21 +574,21 @@ protected Builder newBuilderForType( public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements // @@protoc_insertion_point(builder_implements:io.prometheus.client.LabelPair) - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPairOrBuilder { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPairOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_LabelPair_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_LabelPair_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_LabelPair_fieldAccessorTable + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_LabelPair_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder.class); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder.class); } - // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.newBuilder() + // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.newBuilder() private Builder() { } @@ -610,17 +610,17 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_LabelPair_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_LabelPair_descriptor; } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair getDefaultInstanceForType() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.getDefaultInstance(); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair getDefaultInstanceForType() { + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.getDefaultInstance(); } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair build() { - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair result = buildPartial(); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair build() { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } @@ -628,14 +628,14 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3 } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair buildPartial() { - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair(this); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair buildPartial() { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair(this); if (bitField0_ != 0) { buildPartial0(result); } onBuilt(); return result; } - private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair result) { + private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair result) { int from_bitField0_ = bitField0_; int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000001) != 0)) { @@ -651,16 +651,16 @@ private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair) { - return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair)other); + if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair) { + return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair other) { - if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.getDefaultInstance()) return this; + public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair other) { + if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.getDefaultInstance()) return this; if (other.hasName()) { name_ = other.name_; bitField0_ |= 0x00000001; @@ -888,12 +888,12 @@ public Builder setValueBytes( } // @@protoc_insertion_point(class_scope:io.prometheus.client.LabelPair) - private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair DEFAULT_INSTANCE; + private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair(); + DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair(); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair getDefaultInstance() { + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair getDefaultInstance() { return DEFAULT_INSTANCE; } @@ -929,7 +929,7 @@ public com.google.protobuf.Parser getParserForType() { } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair getDefaultInstanceForType() { + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair getDefaultInstanceForType() { return DEFAULT_INSTANCE; } @@ -963,7 +963,7 @@ public static final class Gauge extends com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 33, - /* patch= */ 2, + /* patch= */ 5, /* suffix= */ "", "Gauge"); } @@ -976,15 +976,15 @@ private Gauge() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Gauge_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Gauge_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Gauge_fieldAccessorTable + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Gauge_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.Builder.class); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.Builder.class); } private int bitField0_; @@ -1047,10 +1047,10 @@ public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge)) { + if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge)) { return super.equals(obj); } - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge) obj; + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge) obj; if (hasValue() != other.hasValue()) return false; if (hasValue()) { @@ -1079,44 +1079,44 @@ public int hashCode() { return hash; } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge parseFrom( java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge parseFrom(byte[] data) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge parseFrom(java.io.InputStream input) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -1124,26 +1124,26 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto .parseWithIOException(PARSER, input, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge parseDelimitedFrom(java.io.InputStream input) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge parseDelimitedFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -1156,7 +1156,7 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge prototype) { + public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } @java.lang.Override @@ -1177,21 +1177,21 @@ protected Builder newBuilderForType( public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements // @@protoc_insertion_point(builder_implements:io.prometheus.client.Gauge) - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.GaugeOrBuilder { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.GaugeOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Gauge_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Gauge_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Gauge_fieldAccessorTable + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Gauge_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.Builder.class); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.Builder.class); } - // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.newBuilder() + // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.newBuilder() private Builder() { } @@ -1212,17 +1212,17 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Gauge_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Gauge_descriptor; } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge getDefaultInstanceForType() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.getDefaultInstance(); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge getDefaultInstanceForType() { + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.getDefaultInstance(); } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge build() { - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge result = buildPartial(); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge build() { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } @@ -1230,14 +1230,14 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3 } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge buildPartial() { - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge(this); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge buildPartial() { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge(this); if (bitField0_ != 0) { buildPartial0(result); } onBuilt(); return result; } - private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge result) { + private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge result) { int from_bitField0_ = bitField0_; int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000001) != 0)) { @@ -1249,16 +1249,16 @@ private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge) { - return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge)other); + if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge) { + return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge other) { - if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.getDefaultInstance()) return this; + public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge other) { + if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.getDefaultInstance()) return this; if (other.hasValue()) { setValue(other.getValue()); } @@ -1354,12 +1354,12 @@ public Builder clearValue() { } // @@protoc_insertion_point(class_scope:io.prometheus.client.Gauge) - private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge DEFAULT_INSTANCE; + private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge(); + DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge(); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge getDefaultInstance() { + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge getDefaultInstance() { return DEFAULT_INSTANCE; } @@ -1395,7 +1395,7 @@ public com.google.protobuf.Parser getParserForType() { } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge getDefaultInstanceForType() { + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge getDefaultInstanceForType() { return DEFAULT_INSTANCE; } @@ -1425,11 +1425,11 @@ public interface CounterOrBuilder extends * optional .io.prometheus.client.Exemplar exemplar = 2; * @return The exemplar. */ - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar getExemplar(); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar getExemplar(); /** * optional .io.prometheus.client.Exemplar exemplar = 2; */ - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder getExemplarOrBuilder(); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder getExemplarOrBuilder(); /** * optional .google.protobuf.Timestamp created_timestamp = 3; @@ -1459,7 +1459,7 @@ public static final class Counter extends com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 33, - /* patch= */ 2, + /* patch= */ 5, /* suffix= */ "", "Counter"); } @@ -1472,15 +1472,15 @@ private Counter() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Counter_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Counter_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Counter_fieldAccessorTable + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Counter_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.Builder.class); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.Builder.class); } private int bitField0_; @@ -1504,7 +1504,7 @@ public double getValue() { } public static final int EXEMPLAR_FIELD_NUMBER = 2; - private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar exemplar_; + private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar exemplar_; /** * optional .io.prometheus.client.Exemplar exemplar = 2; * @return Whether the exemplar field is set. @@ -1518,15 +1518,15 @@ public boolean hasExemplar() { * @return The exemplar. */ @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar getExemplar() { - return exemplar_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.getDefaultInstance() : exemplar_; + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar getExemplar() { + return exemplar_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.getDefaultInstance() : exemplar_; } /** * optional .io.prometheus.client.Exemplar exemplar = 2; */ @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder getExemplarOrBuilder() { - return exemplar_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.getDefaultInstance() : exemplar_; + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder getExemplarOrBuilder() { + return exemplar_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.getDefaultInstance() : exemplar_; } public static final int CREATED_TIMESTAMP_FIELD_NUMBER = 3; @@ -1609,10 +1609,10 @@ public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter)) { + if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter)) { return super.equals(obj); } - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter) obj; + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter) obj; if (hasValue() != other.hasValue()) return false; if (hasValue()) { @@ -1659,44 +1659,44 @@ public int hashCode() { return hash; } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter parseFrom( java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter parseFrom(byte[] data) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter parseFrom(java.io.InputStream input) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -1704,26 +1704,26 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto .parseWithIOException(PARSER, input, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter parseDelimitedFrom(java.io.InputStream input) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter parseDelimitedFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -1736,7 +1736,7 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter prototype) { + public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } @java.lang.Override @@ -1757,21 +1757,21 @@ protected Builder newBuilderForType( public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements // @@protoc_insertion_point(builder_implements:io.prometheus.client.Counter) - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.CounterOrBuilder { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.CounterOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Counter_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Counter_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Counter_fieldAccessorTable + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Counter_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.Builder.class); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.Builder.class); } - // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.newBuilder() + // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.newBuilder() private Builder() { maybeForceBuilderInitialization(); } @@ -1809,17 +1809,17 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Counter_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Counter_descriptor; } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter getDefaultInstanceForType() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.getDefaultInstance(); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter getDefaultInstanceForType() { + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.getDefaultInstance(); } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter build() { - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter result = buildPartial(); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter build() { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } @@ -1827,14 +1827,14 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3 } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter buildPartial() { - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter(this); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter buildPartial() { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter(this); if (bitField0_ != 0) { buildPartial0(result); } onBuilt(); return result; } - private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter result) { + private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter result) { int from_bitField0_ = bitField0_; int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000001) != 0)) { @@ -1858,16 +1858,16 @@ private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter) { - return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter)other); + if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter) { + return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter other) { - if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.getDefaultInstance()) return this; + public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter other) { + if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.getDefaultInstance()) return this; if (other.hasValue()) { setValue(other.getValue()); } @@ -1979,9 +1979,9 @@ public Builder clearValue() { return this; } - private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar exemplar_; + private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar exemplar_; private com.google.protobuf.SingleFieldBuilder< - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder> exemplarBuilder_; + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder> exemplarBuilder_; /** * optional .io.prometheus.client.Exemplar exemplar = 2; * @return Whether the exemplar field is set. @@ -1993,9 +1993,9 @@ public boolean hasExemplar() { * optional .io.prometheus.client.Exemplar exemplar = 2; * @return The exemplar. */ - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar getExemplar() { + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar getExemplar() { if (exemplarBuilder_ == null) { - return exemplar_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.getDefaultInstance() : exemplar_; + return exemplar_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.getDefaultInstance() : exemplar_; } else { return exemplarBuilder_.getMessage(); } @@ -2003,7 +2003,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3 /** * optional .io.prometheus.client.Exemplar exemplar = 2; */ - public Builder setExemplar(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar value) { + public Builder setExemplar(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar value) { if (exemplarBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -2020,7 +2020,7 @@ public Builder setExemplar(io.prometheus.metrics.expositionformats.generated.com * optional .io.prometheus.client.Exemplar exemplar = 2; */ public Builder setExemplar( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder builderForValue) { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder builderForValue) { if (exemplarBuilder_ == null) { exemplar_ = builderForValue.build(); } else { @@ -2033,11 +2033,11 @@ public Builder setExemplar( /** * optional .io.prometheus.client.Exemplar exemplar = 2; */ - public Builder mergeExemplar(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar value) { + public Builder mergeExemplar(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar value) { if (exemplarBuilder_ == null) { if (((bitField0_ & 0x00000002) != 0) && exemplar_ != null && - exemplar_ != io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.getDefaultInstance()) { + exemplar_ != io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.getDefaultInstance()) { getExemplarBuilder().mergeFrom(value); } else { exemplar_ = value; @@ -2067,7 +2067,7 @@ public Builder clearExemplar() { /** * optional .io.prometheus.client.Exemplar exemplar = 2; */ - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder getExemplarBuilder() { + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder getExemplarBuilder() { bitField0_ |= 0x00000002; onChanged(); return internalGetExemplarFieldBuilder().getBuilder(); @@ -2075,23 +2075,23 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3 /** * optional .io.prometheus.client.Exemplar exemplar = 2; */ - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder getExemplarOrBuilder() { + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder getExemplarOrBuilder() { if (exemplarBuilder_ != null) { return exemplarBuilder_.getMessageOrBuilder(); } else { return exemplar_ == null ? - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.getDefaultInstance() : exemplar_; + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.getDefaultInstance() : exemplar_; } } /** * optional .io.prometheus.client.Exemplar exemplar = 2; */ private com.google.protobuf.SingleFieldBuilder< - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder> + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder> internalGetExemplarFieldBuilder() { if (exemplarBuilder_ == null) { exemplarBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder>( + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder>( getExemplar(), getParentForChildren(), isClean()); @@ -2225,12 +2225,12 @@ public com.google.protobuf.TimestampOrBuilder getCreatedTimestampOrBuilder() { } // @@protoc_insertion_point(class_scope:io.prometheus.client.Counter) - private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter DEFAULT_INSTANCE; + private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter(); + DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter(); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter getDefaultInstance() { + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter getDefaultInstance() { return DEFAULT_INSTANCE; } @@ -2266,7 +2266,7 @@ public com.google.protobuf.Parser getParserForType() { } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter getDefaultInstanceForType() { + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter getDefaultInstanceForType() { return DEFAULT_INSTANCE; } @@ -2311,7 +2311,7 @@ public static final class Quantile extends com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 33, - /* patch= */ 2, + /* patch= */ 5, /* suffix= */ "", "Quantile"); } @@ -2324,15 +2324,15 @@ private Quantile() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Quantile_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Quantile_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Quantile_fieldAccessorTable + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Quantile_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.Builder.class); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.Builder.class); } private int bitField0_; @@ -2421,10 +2421,10 @@ public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile)) { + if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile)) { return super.equals(obj); } - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile) obj; + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile) obj; if (hasQuantile() != other.hasQuantile()) return false; if (hasQuantile()) { @@ -2464,44 +2464,44 @@ public int hashCode() { return hash; } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile parseFrom( java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile parseFrom(byte[] data) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile parseFrom(java.io.InputStream input) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -2509,26 +2509,26 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto .parseWithIOException(PARSER, input, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile parseDelimitedFrom(java.io.InputStream input) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile parseDelimitedFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -2541,7 +2541,7 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile prototype) { + public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } @java.lang.Override @@ -2562,21 +2562,21 @@ protected Builder newBuilderForType( public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements // @@protoc_insertion_point(builder_implements:io.prometheus.client.Quantile) - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.QuantileOrBuilder { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.QuantileOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Quantile_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Quantile_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Quantile_fieldAccessorTable + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Quantile_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.Builder.class); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.Builder.class); } - // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.newBuilder() + // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.newBuilder() private Builder() { } @@ -2598,17 +2598,17 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Quantile_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Quantile_descriptor; } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile getDefaultInstanceForType() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.getDefaultInstance(); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile getDefaultInstanceForType() { + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.getDefaultInstance(); } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile build() { - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile result = buildPartial(); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile build() { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } @@ -2616,14 +2616,14 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3 } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile buildPartial() { - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile(this); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile buildPartial() { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile(this); if (bitField0_ != 0) { buildPartial0(result); } onBuilt(); return result; } - private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile result) { + private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile result) { int from_bitField0_ = bitField0_; int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000001) != 0)) { @@ -2639,16 +2639,16 @@ private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile) { - return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile)other); + if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile) { + return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile other) { - if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.getDefaultInstance()) return this; + public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile other) { + if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.getDefaultInstance()) return this; if (other.hasQuantile()) { setQuantile(other.getQuantile()); } @@ -2792,12 +2792,12 @@ public Builder clearValue() { } // @@protoc_insertion_point(class_scope:io.prometheus.client.Quantile) - private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile DEFAULT_INSTANCE; + private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile(); + DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile(); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile getDefaultInstance() { + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile getDefaultInstance() { return DEFAULT_INSTANCE; } @@ -2833,7 +2833,7 @@ public com.google.protobuf.Parser getParserForType() { } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile getDefaultInstanceForType() { + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile getDefaultInstanceForType() { return DEFAULT_INSTANCE; } @@ -2868,12 +2868,12 @@ public interface SummaryOrBuilder extends /** * repeated .io.prometheus.client.Quantile quantile = 3; */ - java.util.List + java.util.List getQuantileList(); /** * repeated .io.prometheus.client.Quantile quantile = 3; */ - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile getQuantile(int index); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile getQuantile(int index); /** * repeated .io.prometheus.client.Quantile quantile = 3; */ @@ -2881,12 +2881,12 @@ public interface SummaryOrBuilder extends /** * repeated .io.prometheus.client.Quantile quantile = 3; */ - java.util.List + java.util.List getQuantileOrBuilderList(); /** * repeated .io.prometheus.client.Quantile quantile = 3; */ - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.QuantileOrBuilder getQuantileOrBuilder( + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.QuantileOrBuilder getQuantileOrBuilder( int index); /** @@ -2917,7 +2917,7 @@ public static final class Summary extends com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 33, - /* patch= */ 2, + /* patch= */ 5, /* suffix= */ "", "Summary"); } @@ -2931,15 +2931,15 @@ private Summary() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Summary_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Summary_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Summary_fieldAccessorTable + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Summary_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.Builder.class); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.Builder.class); } private int bitField0_; @@ -2983,19 +2983,19 @@ public double getSampleSum() { public static final int QUANTILE_FIELD_NUMBER = 3; @SuppressWarnings("serial") - private java.util.List quantile_; + private java.util.List quantile_; /** * repeated .io.prometheus.client.Quantile quantile = 3; */ @java.lang.Override - public java.util.List getQuantileList() { + public java.util.List getQuantileList() { return quantile_; } /** * repeated .io.prometheus.client.Quantile quantile = 3; */ @java.lang.Override - public java.util.List + public java.util.List getQuantileOrBuilderList() { return quantile_; } @@ -3010,14 +3010,14 @@ public int getQuantileCount() { * repeated .io.prometheus.client.Quantile quantile = 3; */ @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile getQuantile(int index) { + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile getQuantile(int index) { return quantile_.get(index); } /** * repeated .io.prometheus.client.Quantile quantile = 3; */ @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.QuantileOrBuilder getQuantileOrBuilder( + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.QuantileOrBuilder getQuantileOrBuilder( int index) { return quantile_.get(index); } @@ -3109,10 +3109,10 @@ public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary)) { + if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary)) { return super.equals(obj); } - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary) obj; + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary) obj; if (hasSampleCount() != other.hasSampleCount()) return false; if (hasSampleCount()) { @@ -3166,44 +3166,44 @@ public int hashCode() { return hash; } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary parseFrom( java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary parseFrom(byte[] data) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary parseFrom(java.io.InputStream input) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -3211,26 +3211,26 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto .parseWithIOException(PARSER, input, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary parseDelimitedFrom(java.io.InputStream input) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary parseDelimitedFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -3243,7 +3243,7 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary prototype) { + public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } @java.lang.Override @@ -3264,21 +3264,21 @@ protected Builder newBuilderForType( public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements // @@protoc_insertion_point(builder_implements:io.prometheus.client.Summary) - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.SummaryOrBuilder { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.SummaryOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Summary_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Summary_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Summary_fieldAccessorTable + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Summary_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.Builder.class); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.Builder.class); } - // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.newBuilder() + // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.newBuilder() private Builder() { maybeForceBuilderInitialization(); } @@ -3319,17 +3319,17 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Summary_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Summary_descriptor; } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary getDefaultInstanceForType() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.getDefaultInstance(); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary getDefaultInstanceForType() { + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.getDefaultInstance(); } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary build() { - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary result = buildPartial(); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary build() { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } @@ -3337,15 +3337,15 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3 } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary buildPartial() { - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary(this); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary buildPartial() { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary(this); buildPartialRepeatedFields(result); if (bitField0_ != 0) { buildPartial0(result); } onBuilt(); return result; } - private void buildPartialRepeatedFields(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary result) { + private void buildPartialRepeatedFields(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary result) { if (quantileBuilder_ == null) { if (((bitField0_ & 0x00000004) != 0)) { quantile_ = java.util.Collections.unmodifiableList(quantile_); @@ -3357,7 +3357,7 @@ private void buildPartialRepeatedFields(io.prometheus.metrics.expositionformats. } } - private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary result) { + private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary result) { int from_bitField0_ = bitField0_; int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000001) != 0)) { @@ -3379,16 +3379,16 @@ private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary) { - return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary)other); + if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary) { + return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary other) { - if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.getDefaultInstance()) return this; + public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary other) { + if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.getDefaultInstance()) return this; if (other.hasSampleCount()) { setSampleCount(other.getSampleCount()); } @@ -3461,9 +3461,9 @@ public Builder mergeFrom( break; } // case 17 case 26: { - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile m = + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile m = input.readMessage( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.parser(), + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.parser(), extensionRegistry); if (quantileBuilder_ == null) { ensureQuantileIsMutable(); @@ -3577,22 +3577,22 @@ public Builder clearSampleSum() { return this; } - private java.util.List quantile_ = + private java.util.List quantile_ = java.util.Collections.emptyList(); private void ensureQuantileIsMutable() { if (!((bitField0_ & 0x00000004) != 0)) { - quantile_ = new java.util.ArrayList(quantile_); + quantile_ = new java.util.ArrayList(quantile_); bitField0_ |= 0x00000004; } } private com.google.protobuf.RepeatedFieldBuilder< - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.QuantileOrBuilder> quantileBuilder_; + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.QuantileOrBuilder> quantileBuilder_; /** * repeated .io.prometheus.client.Quantile quantile = 3; */ - public java.util.List getQuantileList() { + public java.util.List getQuantileList() { if (quantileBuilder_ == null) { return java.util.Collections.unmodifiableList(quantile_); } else { @@ -3612,7 +3612,7 @@ public int getQuantileCount() { /** * repeated .io.prometheus.client.Quantile quantile = 3; */ - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile getQuantile(int index) { + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile getQuantile(int index) { if (quantileBuilder_ == null) { return quantile_.get(index); } else { @@ -3623,7 +3623,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3 * repeated .io.prometheus.client.Quantile quantile = 3; */ public Builder setQuantile( - int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile value) { + int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile value) { if (quantileBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -3640,7 +3640,7 @@ public Builder setQuantile( * repeated .io.prometheus.client.Quantile quantile = 3; */ public Builder setQuantile( - int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.Builder builderForValue) { + int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.Builder builderForValue) { if (quantileBuilder_ == null) { ensureQuantileIsMutable(); quantile_.set(index, builderForValue.build()); @@ -3653,7 +3653,7 @@ public Builder setQuantile( /** * repeated .io.prometheus.client.Quantile quantile = 3; */ - public Builder addQuantile(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile value) { + public Builder addQuantile(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile value) { if (quantileBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -3670,7 +3670,7 @@ public Builder addQuantile(io.prometheus.metrics.expositionformats.generated.com * repeated .io.prometheus.client.Quantile quantile = 3; */ public Builder addQuantile( - int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile value) { + int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile value) { if (quantileBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -3687,7 +3687,7 @@ public Builder addQuantile( * repeated .io.prometheus.client.Quantile quantile = 3; */ public Builder addQuantile( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.Builder builderForValue) { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.Builder builderForValue) { if (quantileBuilder_ == null) { ensureQuantileIsMutable(); quantile_.add(builderForValue.build()); @@ -3701,7 +3701,7 @@ public Builder addQuantile( * repeated .io.prometheus.client.Quantile quantile = 3; */ public Builder addQuantile( - int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.Builder builderForValue) { + int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.Builder builderForValue) { if (quantileBuilder_ == null) { ensureQuantileIsMutable(); quantile_.add(index, builderForValue.build()); @@ -3715,7 +3715,7 @@ public Builder addQuantile( * repeated .io.prometheus.client.Quantile quantile = 3; */ public Builder addAllQuantile( - java.lang.Iterable values) { + java.lang.Iterable values) { if (quantileBuilder_ == null) { ensureQuantileIsMutable(); com.google.protobuf.AbstractMessageLite.Builder.addAll( @@ -3755,14 +3755,14 @@ public Builder removeQuantile(int index) { /** * repeated .io.prometheus.client.Quantile quantile = 3; */ - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.Builder getQuantileBuilder( + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.Builder getQuantileBuilder( int index) { return internalGetQuantileFieldBuilder().getBuilder(index); } /** * repeated .io.prometheus.client.Quantile quantile = 3; */ - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.QuantileOrBuilder getQuantileOrBuilder( + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.QuantileOrBuilder getQuantileOrBuilder( int index) { if (quantileBuilder_ == null) { return quantile_.get(index); } else { @@ -3772,7 +3772,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3 /** * repeated .io.prometheus.client.Quantile quantile = 3; */ - public java.util.List + public java.util.List getQuantileOrBuilderList() { if (quantileBuilder_ != null) { return quantileBuilder_.getMessageOrBuilderList(); @@ -3783,31 +3783,31 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3 /** * repeated .io.prometheus.client.Quantile quantile = 3; */ - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.Builder addQuantileBuilder() { + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.Builder addQuantileBuilder() { return internalGetQuantileFieldBuilder().addBuilder( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.getDefaultInstance()); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.getDefaultInstance()); } /** * repeated .io.prometheus.client.Quantile quantile = 3; */ - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.Builder addQuantileBuilder( + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.Builder addQuantileBuilder( int index) { return internalGetQuantileFieldBuilder().addBuilder( - index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.getDefaultInstance()); + index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.getDefaultInstance()); } /** * repeated .io.prometheus.client.Quantile quantile = 3; */ - public java.util.List + public java.util.List getQuantileBuilderList() { return internalGetQuantileFieldBuilder().getBuilderList(); } private com.google.protobuf.RepeatedFieldBuilder< - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.QuantileOrBuilder> + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.QuantileOrBuilder> internalGetQuantileFieldBuilder() { if (quantileBuilder_ == null) { quantileBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Quantile.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.QuantileOrBuilder>( + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Quantile.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.QuantileOrBuilder>( quantile_, ((bitField0_ & 0x00000004) != 0), getParentForChildren(), @@ -3942,12 +3942,12 @@ public com.google.protobuf.TimestampOrBuilder getCreatedTimestampOrBuilder() { } // @@protoc_insertion_point(class_scope:io.prometheus.client.Summary) - private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary DEFAULT_INSTANCE; + private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary(); + DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary(); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary getDefaultInstance() { + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary getDefaultInstance() { return DEFAULT_INSTANCE; } @@ -3983,7 +3983,7 @@ public com.google.protobuf.Parser

getParserForType() { } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary getDefaultInstanceForType() { + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary getDefaultInstanceForType() { return DEFAULT_INSTANCE; } @@ -4017,7 +4017,7 @@ public static final class Untyped extends com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 33, - /* patch= */ 2, + /* patch= */ 5, /* suffix= */ "", "Untyped"); } @@ -4030,15 +4030,15 @@ private Untyped() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Untyped_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Untyped_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Untyped_fieldAccessorTable + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Untyped_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.Builder.class); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.Builder.class); } private int bitField0_; @@ -4101,10 +4101,10 @@ public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped)) { + if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped)) { return super.equals(obj); } - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped) obj; + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped) obj; if (hasValue() != other.hasValue()) return false; if (hasValue()) { @@ -4133,44 +4133,44 @@ public int hashCode() { return hash; } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped parseFrom( java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped parseFrom(byte[] data) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped parseFrom(java.io.InputStream input) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -4178,26 +4178,26 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto .parseWithIOException(PARSER, input, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped parseDelimitedFrom(java.io.InputStream input) + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped parseDelimitedFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped parseFrom( + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -4210,7 +4210,7 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped prototype) { + public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } @java.lang.Override @@ -4231,21 +4231,21 @@ protected Builder newBuilderForType( public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements // @@protoc_insertion_point(builder_implements:io.prometheus.client.Untyped) - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.UntypedOrBuilder { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.UntypedOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Untyped_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Untyped_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Untyped_fieldAccessorTable + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Untyped_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.Builder.class); + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.Builder.class); } - // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.newBuilder() + // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.newBuilder() private Builder() { } @@ -4266,17 +4266,17 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Untyped_descriptor; + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Untyped_descriptor; } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped getDefaultInstanceForType() { - return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.getDefaultInstance(); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped getDefaultInstanceForType() { + return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.getDefaultInstance(); } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped build() { - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped result = buildPartial(); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped build() { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } @@ -4284,14 +4284,14 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3 } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped buildPartial() { - io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped(this); + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped buildPartial() { + io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped(this); if (bitField0_ != 0) { buildPartial0(result); } onBuilt(); return result; } - private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped result) { + private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped result) { int from_bitField0_ = bitField0_; int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000001) != 0)) { @@ -4303,16 +4303,16 @@ private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped) { - return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped)other); + if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped) { + return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped other) { - if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.getDefaultInstance()) return this; + public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped other) { + if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.getDefaultInstance()) return this; if (other.hasValue()) { setValue(other.getValue()); } @@ -4408,12 +4408,12 @@ public Builder clearValue() { } // @@protoc_insertion_point(class_scope:io.prometheus.client.Untyped) - private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped DEFAULT_INSTANCE; + private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped(); + DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped(); } - public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped getDefaultInstance() { + public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped getDefaultInstance() { return DEFAULT_INSTANCE; } @@ -4449,7 +4449,7 @@ public com.google.protobuf.Parser getParserForType() { } @java.lang.Override - public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped getDefaultInstanceForType() { + public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped getDefaultInstanceForType() { return DEFAULT_INSTANCE; } @@ -4507,7 +4507,7 @@ public interface HistogramOrBuilder extends * * repeated .io.prometheus.client.Bucket bucket = 3; */ - java.util.List + java.util.List getBucketList(); /** *
@@ -4516,7 +4516,7 @@ public interface HistogramOrBuilder extends
      *
      * repeated .io.prometheus.client.Bucket bucket = 3;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket getBucket(int index);
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket getBucket(int index);
     /**
      * 
      * Buckets for the conventional histogram.
@@ -4532,7 +4532,7 @@ public interface HistogramOrBuilder extends
      *
      * repeated .io.prometheus.client.Bucket bucket = 3;
      */
-    java.util.List 
+    java.util.List 
         getBucketOrBuilderList();
     /**
      * 
@@ -4541,7 +4541,7 @@ public interface HistogramOrBuilder extends
      *
      * repeated .io.prometheus.client.Bucket bucket = 3;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketOrBuilder getBucketOrBuilder(
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketOrBuilder getBucketOrBuilder(
         int index);
 
     /**
@@ -4650,7 +4650,7 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      *
      * repeated .io.prometheus.client.BucketSpan negative_span = 9;
      */
-    java.util.List 
+    java.util.List 
         getNegativeSpanList();
     /**
      * 
@@ -4659,7 +4659,7 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      *
      * repeated .io.prometheus.client.BucketSpan negative_span = 9;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan getNegativeSpan(int index);
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan getNegativeSpan(int index);
     /**
      * 
      * Negative buckets for the native histogram.
@@ -4675,7 +4675,7 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      *
      * repeated .io.prometheus.client.BucketSpan negative_span = 9;
      */
-    java.util.List 
+    java.util.List 
         getNegativeSpanOrBuilderList();
     /**
      * 
@@ -4684,7 +4684,7 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      *
      * repeated .io.prometheus.client.BucketSpan negative_span = 9;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpanOrBuilder getNegativeSpanOrBuilder(
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpanOrBuilder getNegativeSpanOrBuilder(
         int index);
 
     /**
@@ -4761,7 +4761,7 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      *
      * repeated .io.prometheus.client.BucketSpan positive_span = 12;
      */
-    java.util.List 
+    java.util.List 
         getPositiveSpanList();
     /**
      * 
@@ -4773,7 +4773,7 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      *
      * repeated .io.prometheus.client.BucketSpan positive_span = 12;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan getPositiveSpan(int index);
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan getPositiveSpan(int index);
     /**
      * 
      * Positive buckets for the native histogram.
@@ -4795,7 +4795,7 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      *
      * repeated .io.prometheus.client.BucketSpan positive_span = 12;
      */
-    java.util.List 
+    java.util.List 
         getPositiveSpanOrBuilderList();
     /**
      * 
@@ -4807,7 +4807,7 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      *
      * repeated .io.prometheus.client.BucketSpan positive_span = 12;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpanOrBuilder getPositiveSpanOrBuilder(
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpanOrBuilder getPositiveSpanOrBuilder(
         int index);
 
     /**
@@ -4881,7 +4881,7 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      *
      * repeated .io.prometheus.client.Exemplar exemplars = 16;
      */
-    java.util.List 
+    java.util.List 
         getExemplarsList();
     /**
      * 
@@ -4890,7 +4890,7 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      *
      * repeated .io.prometheus.client.Exemplar exemplars = 16;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar getExemplars(int index);
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar getExemplars(int index);
     /**
      * 
      * Only used for native histograms. These exemplars MUST have a timestamp.
@@ -4906,7 +4906,7 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      *
      * repeated .io.prometheus.client.Exemplar exemplars = 16;
      */
-    java.util.List 
+    java.util.List 
         getExemplarsOrBuilderList();
     /**
      * 
@@ -4915,7 +4915,7 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      *
      * repeated .io.prometheus.client.Exemplar exemplars = 16;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder getExemplarsOrBuilder(
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder getExemplarsOrBuilder(
         int index);
   }
   /**
@@ -4931,7 +4931,7 @@ public static final class Histogram extends
         com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
         /* major= */ 4,
         /* minor= */ 33,
-        /* patch= */ 2,
+        /* patch= */ 5,
         /* suffix= */ "",
         "Histogram");
     }
@@ -4952,15 +4952,15 @@ private Histogram() {
 
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Histogram_descriptor;
+      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Histogram_descriptor;
     }
 
     @java.lang.Override
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Histogram_fieldAccessorTable
+      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Histogram_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.Builder.class);
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.Builder.class);
     }
 
     private int bitField0_;
@@ -5031,7 +5031,7 @@ public double getSampleSum() {
 
     public static final int BUCKET_FIELD_NUMBER = 3;
     @SuppressWarnings("serial")
-    private java.util.List bucket_;
+    private java.util.List bucket_;
     /**
      * 
      * Buckets for the conventional histogram.
@@ -5040,7 +5040,7 @@ public double getSampleSum() {
      * repeated .io.prometheus.client.Bucket bucket = 3;
      */
     @java.lang.Override
-    public java.util.List getBucketList() {
+    public java.util.List getBucketList() {
       return bucket_;
     }
     /**
@@ -5051,7 +5051,7 @@ public java.util.Listrepeated .io.prometheus.client.Bucket bucket = 3;
      */
     @java.lang.Override
-    public java.util.List 
+    public java.util.List 
         getBucketOrBuilderList() {
       return bucket_;
     }
@@ -5074,7 +5074,7 @@ public int getBucketCount() {
      * repeated .io.prometheus.client.Bucket bucket = 3;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket getBucket(int index) {
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket getBucket(int index) {
       return bucket_.get(index);
     }
     /**
@@ -5085,7 +5085,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
      * repeated .io.prometheus.client.Bucket bucket = 3;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketOrBuilder getBucketOrBuilder(
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketOrBuilder getBucketOrBuilder(
         int index) {
       return bucket_.get(index);
     }
@@ -5234,7 +5234,7 @@ public double getZeroCountFloat() {
 
     public static final int NEGATIVE_SPAN_FIELD_NUMBER = 9;
     @SuppressWarnings("serial")
-    private java.util.List negativeSpan_;
+    private java.util.List negativeSpan_;
     /**
      * 
      * Negative buckets for the native histogram.
@@ -5243,7 +5243,7 @@ public double getZeroCountFloat() {
      * repeated .io.prometheus.client.BucketSpan negative_span = 9;
      */
     @java.lang.Override
-    public java.util.List getNegativeSpanList() {
+    public java.util.List getNegativeSpanList() {
       return negativeSpan_;
     }
     /**
@@ -5254,7 +5254,7 @@ public java.util.Listrepeated .io.prometheus.client.BucketSpan negative_span = 9;
      */
     @java.lang.Override
-    public java.util.List 
+    public java.util.List 
         getNegativeSpanOrBuilderList() {
       return negativeSpan_;
     }
@@ -5277,7 +5277,7 @@ public int getNegativeSpanCount() {
      * repeated .io.prometheus.client.BucketSpan negative_span = 9;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan getNegativeSpan(int index) {
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan getNegativeSpan(int index) {
       return negativeSpan_.get(index);
     }
     /**
@@ -5288,7 +5288,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
      * repeated .io.prometheus.client.BucketSpan negative_span = 9;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpanOrBuilder getNegativeSpanOrBuilder(
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpanOrBuilder getNegativeSpanOrBuilder(
         int index) {
       return negativeSpan_.get(index);
     }
@@ -5383,7 +5383,7 @@ public double getNegativeCount(int index) {
 
     public static final int POSITIVE_SPAN_FIELD_NUMBER = 12;
     @SuppressWarnings("serial")
-    private java.util.List positiveSpan_;
+    private java.util.List positiveSpan_;
     /**
      * 
      * Positive buckets for the native histogram.
@@ -5395,7 +5395,7 @@ public double getNegativeCount(int index) {
      * repeated .io.prometheus.client.BucketSpan positive_span = 12;
      */
     @java.lang.Override
-    public java.util.List getPositiveSpanList() {
+    public java.util.List getPositiveSpanList() {
       return positiveSpan_;
     }
     /**
@@ -5409,7 +5409,7 @@ public java.util.Listrepeated .io.prometheus.client.BucketSpan positive_span = 12;
      */
     @java.lang.Override
-    public java.util.List 
+    public java.util.List 
         getPositiveSpanOrBuilderList() {
       return positiveSpan_;
     }
@@ -5438,7 +5438,7 @@ public int getPositiveSpanCount() {
      * repeated .io.prometheus.client.BucketSpan positive_span = 12;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan getPositiveSpan(int index) {
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan getPositiveSpan(int index) {
       return positiveSpan_.get(index);
     }
     /**
@@ -5452,7 +5452,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
      * repeated .io.prometheus.client.BucketSpan positive_span = 12;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpanOrBuilder getPositiveSpanOrBuilder(
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpanOrBuilder getPositiveSpanOrBuilder(
         int index) {
       return positiveSpan_.get(index);
     }
@@ -5547,7 +5547,7 @@ public double getPositiveCount(int index) {
 
     public static final int EXEMPLARS_FIELD_NUMBER = 16;
     @SuppressWarnings("serial")
-    private java.util.List exemplars_;
+    private java.util.List exemplars_;
     /**
      * 
      * Only used for native histograms. These exemplars MUST have a timestamp.
@@ -5556,7 +5556,7 @@ public double getPositiveCount(int index) {
      * repeated .io.prometheus.client.Exemplar exemplars = 16;
      */
     @java.lang.Override
-    public java.util.List getExemplarsList() {
+    public java.util.List getExemplarsList() {
       return exemplars_;
     }
     /**
@@ -5567,7 +5567,7 @@ public java.util.Listrepeated .io.prometheus.client.Exemplar exemplars = 16;
      */
     @java.lang.Override
-    public java.util.List 
+    public java.util.List 
         getExemplarsOrBuilderList() {
       return exemplars_;
     }
@@ -5590,7 +5590,7 @@ public int getExemplarsCount() {
      * repeated .io.prometheus.client.Exemplar exemplars = 16;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar getExemplars(int index) {
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar getExemplars(int index) {
       return exemplars_.get(index);
     }
     /**
@@ -5601,7 +5601,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
      * repeated .io.prometheus.client.Exemplar exemplars = 16;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder getExemplarsOrBuilder(
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder getExemplarsOrBuilder(
         int index) {
       return exemplars_.get(index);
     }
@@ -5765,10 +5765,10 @@ public boolean equals(final java.lang.Object obj) {
       if (obj == this) {
        return true;
       }
-      if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram)) {
+      if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram)) {
         return super.equals(obj);
       }
-      io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram) obj;
+      io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram) obj;
 
       if (hasSampleCount() != other.hasSampleCount()) return false;
       if (hasSampleCount()) {
@@ -5916,44 +5916,44 @@ public int hashCode() {
       return hash;
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram parseFrom(
         java.nio.ByteBuffer data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram parseFrom(
         java.nio.ByteBuffer data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram parseFrom(byte[] data)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram parseFrom(java.io.InputStream input)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseWithIOException(PARSER, input);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -5961,26 +5961,26 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto
           .parseWithIOException(PARSER, input, extensionRegistry);
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram parseDelimitedFrom(java.io.InputStream input)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseDelimitedWithIOException(PARSER, input);
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram parseDelimitedFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseWithIOException(PARSER, input);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -5993,7 +5993,7 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto
     public static Builder newBuilder() {
       return DEFAULT_INSTANCE.toBuilder();
     }
-    public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram prototype) {
+    public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram prototype) {
       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
     }
     @java.lang.Override
@@ -6014,21 +6014,21 @@ protected Builder newBuilderForType(
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder implements
         // @@protoc_insertion_point(builder_implements:io.prometheus.client.Histogram)
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.HistogramOrBuilder {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.HistogramOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Histogram_descriptor;
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Histogram_descriptor;
       }
 
       @java.lang.Override
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Histogram_fieldAccessorTable
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Histogram_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.Builder.class);
+                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.Builder.class);
       }
 
-      // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.newBuilder()
+      // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -6102,17 +6102,17 @@ public Builder clear() {
       @java.lang.Override
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Histogram_descriptor;
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Histogram_descriptor;
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram getDefaultInstanceForType() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.getDefaultInstance();
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram getDefaultInstanceForType() {
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.getDefaultInstance();
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram build() {
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram result = buildPartial();
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram build() {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
@@ -6120,15 +6120,15 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram buildPartial() {
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram(this);
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram buildPartial() {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram(this);
         buildPartialRepeatedFields(result);
         if (bitField0_ != 0) { buildPartial0(result); }
         onBuilt();
         return result;
       }
 
-      private void buildPartialRepeatedFields(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram result) {
+      private void buildPartialRepeatedFields(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram result) {
         if (bucketBuilder_ == null) {
           if (((bitField0_ & 0x00000008) != 0)) {
             bucket_ = java.util.Collections.unmodifiableList(bucket_);
@@ -6167,7 +6167,7 @@ private void buildPartialRepeatedFields(io.prometheus.metrics.expositionformats.
         }
       }
 
-      private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram result) {
+      private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram result) {
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000001) != 0)) {
@@ -6225,16 +6225,16 @@ private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com
 
       @java.lang.Override
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram) {
-          return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram)other);
+        if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram) {
+          return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram other) {
-        if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.getDefaultInstance()) return this;
+      public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram other) {
+        if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.getDefaultInstance()) return this;
         if (other.hasSampleCount()) {
           setSampleCount(other.getSampleCount());
         }
@@ -6444,9 +6444,9 @@ public Builder mergeFrom(
                 break;
               } // case 17
               case 26: {
-                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket m =
+                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket m =
                     input.readMessage(
-                        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.parser(),
+                        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.parser(),
                         extensionRegistry);
                 if (bucketBuilder_ == null) {
                   ensureBucketIsMutable();
@@ -6482,9 +6482,9 @@ public Builder mergeFrom(
                 break;
               } // case 65
               case 74: {
-                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan m =
+                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan m =
                     input.readMessage(
-                        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.parser(),
+                        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.parser(),
                         extensionRegistry);
                 if (negativeSpanBuilder_ == null) {
                   ensureNegativeSpanIsMutable();
@@ -6528,9 +6528,9 @@ public Builder mergeFrom(
                 break;
               } // case 90
               case 98: {
-                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan m =
+                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan m =
                     input.readMessage(
-                        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.parser(),
+                        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.parser(),
                         extensionRegistry);
                 if (positiveSpanBuilder_ == null) {
                   ensurePositiveSpanIsMutable();
@@ -6581,9 +6581,9 @@ public Builder mergeFrom(
                 break;
               } // case 122
               case 130: {
-                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar m =
+                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar m =
                     input.readMessage(
-                        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.parser(),
+                        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.parser(),
                         extensionRegistry);
                 if (exemplarsBuilder_ == null) {
                   ensureExemplarsIsMutable();
@@ -6746,17 +6746,17 @@ public Builder clearSampleSum() {
         return this;
       }
 
-      private java.util.List bucket_ =
+      private java.util.List bucket_ =
         java.util.Collections.emptyList();
       private void ensureBucketIsMutable() {
         if (!((bitField0_ & 0x00000008) != 0)) {
-          bucket_ = new java.util.ArrayList(bucket_);
+          bucket_ = new java.util.ArrayList(bucket_);
           bitField0_ |= 0x00000008;
          }
       }
 
       private com.google.protobuf.RepeatedFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketOrBuilder> bucketBuilder_;
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketOrBuilder> bucketBuilder_;
 
       /**
        * 
@@ -6765,7 +6765,7 @@ private void ensureBucketIsMutable() {
        *
        * repeated .io.prometheus.client.Bucket bucket = 3;
        */
-      public java.util.List getBucketList() {
+      public java.util.List getBucketList() {
         if (bucketBuilder_ == null) {
           return java.util.Collections.unmodifiableList(bucket_);
         } else {
@@ -6793,7 +6793,7 @@ public int getBucketCount() {
        *
        * repeated .io.prometheus.client.Bucket bucket = 3;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket getBucket(int index) {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket getBucket(int index) {
         if (bucketBuilder_ == null) {
           return bucket_.get(index);
         } else {
@@ -6808,7 +6808,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        * repeated .io.prometheus.client.Bucket bucket = 3;
        */
       public Builder setBucket(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket value) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket value) {
         if (bucketBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -6829,7 +6829,7 @@ public Builder setBucket(
        * repeated .io.prometheus.client.Bucket bucket = 3;
        */
       public Builder setBucket(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.Builder builderForValue) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.Builder builderForValue) {
         if (bucketBuilder_ == null) {
           ensureBucketIsMutable();
           bucket_.set(index, builderForValue.build());
@@ -6846,7 +6846,7 @@ public Builder setBucket(
        *
        * repeated .io.prometheus.client.Bucket bucket = 3;
        */
-      public Builder addBucket(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket value) {
+      public Builder addBucket(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket value) {
         if (bucketBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -6867,7 +6867,7 @@ public Builder addBucket(io.prometheus.metrics.expositionformats.generated.com_g
        * repeated .io.prometheus.client.Bucket bucket = 3;
        */
       public Builder addBucket(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket value) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket value) {
         if (bucketBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -6888,7 +6888,7 @@ public Builder addBucket(
        * repeated .io.prometheus.client.Bucket bucket = 3;
        */
       public Builder addBucket(
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.Builder builderForValue) {
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.Builder builderForValue) {
         if (bucketBuilder_ == null) {
           ensureBucketIsMutable();
           bucket_.add(builderForValue.build());
@@ -6906,7 +6906,7 @@ public Builder addBucket(
        * repeated .io.prometheus.client.Bucket bucket = 3;
        */
       public Builder addBucket(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.Builder builderForValue) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.Builder builderForValue) {
         if (bucketBuilder_ == null) {
           ensureBucketIsMutable();
           bucket_.add(index, builderForValue.build());
@@ -6924,7 +6924,7 @@ public Builder addBucket(
        * repeated .io.prometheus.client.Bucket bucket = 3;
        */
       public Builder addAllBucket(
-          java.lang.Iterable values) {
+          java.lang.Iterable values) {
         if (bucketBuilder_ == null) {
           ensureBucketIsMutable();
           com.google.protobuf.AbstractMessageLite.Builder.addAll(
@@ -6976,7 +6976,7 @@ public Builder removeBucket(int index) {
        *
        * repeated .io.prometheus.client.Bucket bucket = 3;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.Builder getBucketBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.Builder getBucketBuilder(
           int index) {
         return internalGetBucketFieldBuilder().getBuilder(index);
       }
@@ -6987,7 +6987,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.Bucket bucket = 3;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketOrBuilder getBucketOrBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketOrBuilder getBucketOrBuilder(
           int index) {
         if (bucketBuilder_ == null) {
           return bucket_.get(index);  } else {
@@ -7001,7 +7001,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.Bucket bucket = 3;
        */
-      public java.util.List 
+      public java.util.List 
            getBucketOrBuilderList() {
         if (bucketBuilder_ != null) {
           return bucketBuilder_.getMessageOrBuilderList();
@@ -7016,9 +7016,9 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.Bucket bucket = 3;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.Builder addBucketBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.Builder addBucketBuilder() {
         return internalGetBucketFieldBuilder().addBuilder(
-            io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.getDefaultInstance());
+            io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.getDefaultInstance());
       }
       /**
        * 
@@ -7027,10 +7027,10 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.Bucket bucket = 3;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.Builder addBucketBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.Builder addBucketBuilder(
           int index) {
         return internalGetBucketFieldBuilder().addBuilder(
-            index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.getDefaultInstance());
+            index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.getDefaultInstance());
       }
       /**
        * 
@@ -7039,16 +7039,16 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.Bucket bucket = 3;
        */
-      public java.util.List 
+      public java.util.List 
            getBucketBuilderList() {
         return internalGetBucketFieldBuilder().getBuilderList();
       }
       private com.google.protobuf.RepeatedFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketOrBuilder> 
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketOrBuilder> 
           internalGetBucketFieldBuilder() {
         if (bucketBuilder_ == null) {
           bucketBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketOrBuilder>(
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketOrBuilder>(
                   bucket_,
                   ((bitField0_ & 0x00000008) != 0),
                   getParentForChildren(),
@@ -7419,17 +7419,17 @@ public Builder clearZeroCountFloat() {
         return this;
       }
 
-      private java.util.List negativeSpan_ =
+      private java.util.List negativeSpan_ =
         java.util.Collections.emptyList();
       private void ensureNegativeSpanIsMutable() {
         if (!((bitField0_ & 0x00000200) != 0)) {
-          negativeSpan_ = new java.util.ArrayList(negativeSpan_);
+          negativeSpan_ = new java.util.ArrayList(negativeSpan_);
           bitField0_ |= 0x00000200;
          }
       }
 
       private com.google.protobuf.RepeatedFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpanOrBuilder> negativeSpanBuilder_;
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpanOrBuilder> negativeSpanBuilder_;
 
       /**
        * 
@@ -7438,7 +7438,7 @@ private void ensureNegativeSpanIsMutable() {
        *
        * repeated .io.prometheus.client.BucketSpan negative_span = 9;
        */
-      public java.util.List getNegativeSpanList() {
+      public java.util.List getNegativeSpanList() {
         if (negativeSpanBuilder_ == null) {
           return java.util.Collections.unmodifiableList(negativeSpan_);
         } else {
@@ -7466,7 +7466,7 @@ public int getNegativeSpanCount() {
        *
        * repeated .io.prometheus.client.BucketSpan negative_span = 9;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan getNegativeSpan(int index) {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan getNegativeSpan(int index) {
         if (negativeSpanBuilder_ == null) {
           return negativeSpan_.get(index);
         } else {
@@ -7481,7 +7481,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        * repeated .io.prometheus.client.BucketSpan negative_span = 9;
        */
       public Builder setNegativeSpan(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan value) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan value) {
         if (negativeSpanBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -7502,7 +7502,7 @@ public Builder setNegativeSpan(
        * repeated .io.prometheus.client.BucketSpan negative_span = 9;
        */
       public Builder setNegativeSpan(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder builderForValue) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder builderForValue) {
         if (negativeSpanBuilder_ == null) {
           ensureNegativeSpanIsMutable();
           negativeSpan_.set(index, builderForValue.build());
@@ -7519,7 +7519,7 @@ public Builder setNegativeSpan(
        *
        * repeated .io.prometheus.client.BucketSpan negative_span = 9;
        */
-      public Builder addNegativeSpan(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan value) {
+      public Builder addNegativeSpan(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan value) {
         if (negativeSpanBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -7540,7 +7540,7 @@ public Builder addNegativeSpan(io.prometheus.metrics.expositionformats.generated
        * repeated .io.prometheus.client.BucketSpan negative_span = 9;
        */
       public Builder addNegativeSpan(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan value) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan value) {
         if (negativeSpanBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -7561,7 +7561,7 @@ public Builder addNegativeSpan(
        * repeated .io.prometheus.client.BucketSpan negative_span = 9;
        */
       public Builder addNegativeSpan(
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder builderForValue) {
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder builderForValue) {
         if (negativeSpanBuilder_ == null) {
           ensureNegativeSpanIsMutable();
           negativeSpan_.add(builderForValue.build());
@@ -7579,7 +7579,7 @@ public Builder addNegativeSpan(
        * repeated .io.prometheus.client.BucketSpan negative_span = 9;
        */
       public Builder addNegativeSpan(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder builderForValue) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder builderForValue) {
         if (negativeSpanBuilder_ == null) {
           ensureNegativeSpanIsMutable();
           negativeSpan_.add(index, builderForValue.build());
@@ -7597,7 +7597,7 @@ public Builder addNegativeSpan(
        * repeated .io.prometheus.client.BucketSpan negative_span = 9;
        */
       public Builder addAllNegativeSpan(
-          java.lang.Iterable values) {
+          java.lang.Iterable values) {
         if (negativeSpanBuilder_ == null) {
           ensureNegativeSpanIsMutable();
           com.google.protobuf.AbstractMessageLite.Builder.addAll(
@@ -7649,7 +7649,7 @@ public Builder removeNegativeSpan(int index) {
        *
        * repeated .io.prometheus.client.BucketSpan negative_span = 9;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder getNegativeSpanBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder getNegativeSpanBuilder(
           int index) {
         return internalGetNegativeSpanFieldBuilder().getBuilder(index);
       }
@@ -7660,7 +7660,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.BucketSpan negative_span = 9;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpanOrBuilder getNegativeSpanOrBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpanOrBuilder getNegativeSpanOrBuilder(
           int index) {
         if (negativeSpanBuilder_ == null) {
           return negativeSpan_.get(index);  } else {
@@ -7674,7 +7674,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.BucketSpan negative_span = 9;
        */
-      public java.util.List 
+      public java.util.List 
            getNegativeSpanOrBuilderList() {
         if (negativeSpanBuilder_ != null) {
           return negativeSpanBuilder_.getMessageOrBuilderList();
@@ -7689,9 +7689,9 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.BucketSpan negative_span = 9;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder addNegativeSpanBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder addNegativeSpanBuilder() {
         return internalGetNegativeSpanFieldBuilder().addBuilder(
-            io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.getDefaultInstance());
+            io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.getDefaultInstance());
       }
       /**
        * 
@@ -7700,10 +7700,10 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.BucketSpan negative_span = 9;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder addNegativeSpanBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder addNegativeSpanBuilder(
           int index) {
         return internalGetNegativeSpanFieldBuilder().addBuilder(
-            index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.getDefaultInstance());
+            index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.getDefaultInstance());
       }
       /**
        * 
@@ -7712,16 +7712,16 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.BucketSpan negative_span = 9;
        */
-      public java.util.List 
+      public java.util.List 
            getNegativeSpanBuilderList() {
         return internalGetNegativeSpanFieldBuilder().getBuilderList();
       }
       private com.google.protobuf.RepeatedFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpanOrBuilder> 
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpanOrBuilder> 
           internalGetNegativeSpanFieldBuilder() {
         if (negativeSpanBuilder_ == null) {
           negativeSpanBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpanOrBuilder>(
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpanOrBuilder>(
                   negativeSpan_,
                   ((bitField0_ & 0x00000200) != 0),
                   getParentForChildren(),
@@ -7975,17 +7975,17 @@ public Builder clearNegativeCount() {
         return this;
       }
 
-      private java.util.List positiveSpan_ =
+      private java.util.List positiveSpan_ =
         java.util.Collections.emptyList();
       private void ensurePositiveSpanIsMutable() {
         if (!((bitField0_ & 0x00001000) != 0)) {
-          positiveSpan_ = new java.util.ArrayList(positiveSpan_);
+          positiveSpan_ = new java.util.ArrayList(positiveSpan_);
           bitField0_ |= 0x00001000;
          }
       }
 
       private com.google.protobuf.RepeatedFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpanOrBuilder> positiveSpanBuilder_;
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpanOrBuilder> positiveSpanBuilder_;
 
       /**
        * 
@@ -7997,7 +7997,7 @@ private void ensurePositiveSpanIsMutable() {
        *
        * repeated .io.prometheus.client.BucketSpan positive_span = 12;
        */
-      public java.util.List getPositiveSpanList() {
+      public java.util.List getPositiveSpanList() {
         if (positiveSpanBuilder_ == null) {
           return java.util.Collections.unmodifiableList(positiveSpan_);
         } else {
@@ -8031,7 +8031,7 @@ public int getPositiveSpanCount() {
        *
        * repeated .io.prometheus.client.BucketSpan positive_span = 12;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan getPositiveSpan(int index) {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan getPositiveSpan(int index) {
         if (positiveSpanBuilder_ == null) {
           return positiveSpan_.get(index);
         } else {
@@ -8049,7 +8049,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        * repeated .io.prometheus.client.BucketSpan positive_span = 12;
        */
       public Builder setPositiveSpan(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan value) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan value) {
         if (positiveSpanBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -8073,7 +8073,7 @@ public Builder setPositiveSpan(
        * repeated .io.prometheus.client.BucketSpan positive_span = 12;
        */
       public Builder setPositiveSpan(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder builderForValue) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder builderForValue) {
         if (positiveSpanBuilder_ == null) {
           ensurePositiveSpanIsMutable();
           positiveSpan_.set(index, builderForValue.build());
@@ -8093,7 +8093,7 @@ public Builder setPositiveSpan(
        *
        * repeated .io.prometheus.client.BucketSpan positive_span = 12;
        */
-      public Builder addPositiveSpan(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan value) {
+      public Builder addPositiveSpan(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan value) {
         if (positiveSpanBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -8117,7 +8117,7 @@ public Builder addPositiveSpan(io.prometheus.metrics.expositionformats.generated
        * repeated .io.prometheus.client.BucketSpan positive_span = 12;
        */
       public Builder addPositiveSpan(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan value) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan value) {
         if (positiveSpanBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -8141,7 +8141,7 @@ public Builder addPositiveSpan(
        * repeated .io.prometheus.client.BucketSpan positive_span = 12;
        */
       public Builder addPositiveSpan(
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder builderForValue) {
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder builderForValue) {
         if (positiveSpanBuilder_ == null) {
           ensurePositiveSpanIsMutable();
           positiveSpan_.add(builderForValue.build());
@@ -8162,7 +8162,7 @@ public Builder addPositiveSpan(
        * repeated .io.prometheus.client.BucketSpan positive_span = 12;
        */
       public Builder addPositiveSpan(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder builderForValue) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder builderForValue) {
         if (positiveSpanBuilder_ == null) {
           ensurePositiveSpanIsMutable();
           positiveSpan_.add(index, builderForValue.build());
@@ -8183,7 +8183,7 @@ public Builder addPositiveSpan(
        * repeated .io.prometheus.client.BucketSpan positive_span = 12;
        */
       public Builder addAllPositiveSpan(
-          java.lang.Iterable values) {
+          java.lang.Iterable values) {
         if (positiveSpanBuilder_ == null) {
           ensurePositiveSpanIsMutable();
           com.google.protobuf.AbstractMessageLite.Builder.addAll(
@@ -8244,7 +8244,7 @@ public Builder removePositiveSpan(int index) {
        *
        * repeated .io.prometheus.client.BucketSpan positive_span = 12;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder getPositiveSpanBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder getPositiveSpanBuilder(
           int index) {
         return internalGetPositiveSpanFieldBuilder().getBuilder(index);
       }
@@ -8258,7 +8258,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.BucketSpan positive_span = 12;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpanOrBuilder getPositiveSpanOrBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpanOrBuilder getPositiveSpanOrBuilder(
           int index) {
         if (positiveSpanBuilder_ == null) {
           return positiveSpan_.get(index);  } else {
@@ -8275,7 +8275,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.BucketSpan positive_span = 12;
        */
-      public java.util.List 
+      public java.util.List 
            getPositiveSpanOrBuilderList() {
         if (positiveSpanBuilder_ != null) {
           return positiveSpanBuilder_.getMessageOrBuilderList();
@@ -8293,9 +8293,9 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.BucketSpan positive_span = 12;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder addPositiveSpanBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder addPositiveSpanBuilder() {
         return internalGetPositiveSpanFieldBuilder().addBuilder(
-            io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.getDefaultInstance());
+            io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.getDefaultInstance());
       }
       /**
        * 
@@ -8307,10 +8307,10 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.BucketSpan positive_span = 12;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder addPositiveSpanBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder addPositiveSpanBuilder(
           int index) {
         return internalGetPositiveSpanFieldBuilder().addBuilder(
-            index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.getDefaultInstance());
+            index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.getDefaultInstance());
       }
       /**
        * 
@@ -8322,16 +8322,16 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.BucketSpan positive_span = 12;
        */
-      public java.util.List 
+      public java.util.List 
            getPositiveSpanBuilderList() {
         return internalGetPositiveSpanFieldBuilder().getBuilderList();
       }
       private com.google.protobuf.RepeatedFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpanOrBuilder> 
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpanOrBuilder> 
           internalGetPositiveSpanFieldBuilder() {
         if (positiveSpanBuilder_ == null) {
           positiveSpanBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpanOrBuilder>(
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpanOrBuilder>(
                   positiveSpan_,
                   ((bitField0_ & 0x00001000) != 0),
                   getParentForChildren(),
@@ -8585,17 +8585,17 @@ public Builder clearPositiveCount() {
         return this;
       }
 
-      private java.util.List exemplars_ =
+      private java.util.List exemplars_ =
         java.util.Collections.emptyList();
       private void ensureExemplarsIsMutable() {
         if (!((bitField0_ & 0x00008000) != 0)) {
-          exemplars_ = new java.util.ArrayList(exemplars_);
+          exemplars_ = new java.util.ArrayList(exemplars_);
           bitField0_ |= 0x00008000;
          }
       }
 
       private com.google.protobuf.RepeatedFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder> exemplarsBuilder_;
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder> exemplarsBuilder_;
 
       /**
        * 
@@ -8604,7 +8604,7 @@ private void ensureExemplarsIsMutable() {
        *
        * repeated .io.prometheus.client.Exemplar exemplars = 16;
        */
-      public java.util.List getExemplarsList() {
+      public java.util.List getExemplarsList() {
         if (exemplarsBuilder_ == null) {
           return java.util.Collections.unmodifiableList(exemplars_);
         } else {
@@ -8632,7 +8632,7 @@ public int getExemplarsCount() {
        *
        * repeated .io.prometheus.client.Exemplar exemplars = 16;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar getExemplars(int index) {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar getExemplars(int index) {
         if (exemplarsBuilder_ == null) {
           return exemplars_.get(index);
         } else {
@@ -8647,7 +8647,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        * repeated .io.prometheus.client.Exemplar exemplars = 16;
        */
       public Builder setExemplars(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar value) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar value) {
         if (exemplarsBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -8668,7 +8668,7 @@ public Builder setExemplars(
        * repeated .io.prometheus.client.Exemplar exemplars = 16;
        */
       public Builder setExemplars(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder builderForValue) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder builderForValue) {
         if (exemplarsBuilder_ == null) {
           ensureExemplarsIsMutable();
           exemplars_.set(index, builderForValue.build());
@@ -8685,7 +8685,7 @@ public Builder setExemplars(
        *
        * repeated .io.prometheus.client.Exemplar exemplars = 16;
        */
-      public Builder addExemplars(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar value) {
+      public Builder addExemplars(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar value) {
         if (exemplarsBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -8706,7 +8706,7 @@ public Builder addExemplars(io.prometheus.metrics.expositionformats.generated.co
        * repeated .io.prometheus.client.Exemplar exemplars = 16;
        */
       public Builder addExemplars(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar value) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar value) {
         if (exemplarsBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -8727,7 +8727,7 @@ public Builder addExemplars(
        * repeated .io.prometheus.client.Exemplar exemplars = 16;
        */
       public Builder addExemplars(
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder builderForValue) {
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder builderForValue) {
         if (exemplarsBuilder_ == null) {
           ensureExemplarsIsMutable();
           exemplars_.add(builderForValue.build());
@@ -8745,7 +8745,7 @@ public Builder addExemplars(
        * repeated .io.prometheus.client.Exemplar exemplars = 16;
        */
       public Builder addExemplars(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder builderForValue) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder builderForValue) {
         if (exemplarsBuilder_ == null) {
           ensureExemplarsIsMutable();
           exemplars_.add(index, builderForValue.build());
@@ -8763,7 +8763,7 @@ public Builder addExemplars(
        * repeated .io.prometheus.client.Exemplar exemplars = 16;
        */
       public Builder addAllExemplars(
-          java.lang.Iterable values) {
+          java.lang.Iterable values) {
         if (exemplarsBuilder_ == null) {
           ensureExemplarsIsMutable();
           com.google.protobuf.AbstractMessageLite.Builder.addAll(
@@ -8815,7 +8815,7 @@ public Builder removeExemplars(int index) {
        *
        * repeated .io.prometheus.client.Exemplar exemplars = 16;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder getExemplarsBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder getExemplarsBuilder(
           int index) {
         return internalGetExemplarsFieldBuilder().getBuilder(index);
       }
@@ -8826,7 +8826,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.Exemplar exemplars = 16;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder getExemplarsOrBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder getExemplarsOrBuilder(
           int index) {
         if (exemplarsBuilder_ == null) {
           return exemplars_.get(index);  } else {
@@ -8840,7 +8840,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.Exemplar exemplars = 16;
        */
-      public java.util.List 
+      public java.util.List 
            getExemplarsOrBuilderList() {
         if (exemplarsBuilder_ != null) {
           return exemplarsBuilder_.getMessageOrBuilderList();
@@ -8855,9 +8855,9 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.Exemplar exemplars = 16;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder addExemplarsBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder addExemplarsBuilder() {
         return internalGetExemplarsFieldBuilder().addBuilder(
-            io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.getDefaultInstance());
+            io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.getDefaultInstance());
       }
       /**
        * 
@@ -8866,10 +8866,10 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.Exemplar exemplars = 16;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder addExemplarsBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder addExemplarsBuilder(
           int index) {
         return internalGetExemplarsFieldBuilder().addBuilder(
-            index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.getDefaultInstance());
+            index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.getDefaultInstance());
       }
       /**
        * 
@@ -8878,16 +8878,16 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        *
        * repeated .io.prometheus.client.Exemplar exemplars = 16;
        */
-      public java.util.List 
+      public java.util.List 
            getExemplarsBuilderList() {
         return internalGetExemplarsFieldBuilder().getBuilderList();
       }
       private com.google.protobuf.RepeatedFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder> 
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder> 
           internalGetExemplarsFieldBuilder() {
         if (exemplarsBuilder_ == null) {
           exemplarsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder>(
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder>(
                   exemplars_,
                   ((bitField0_ & 0x00008000) != 0),
                   getParentForChildren(),
@@ -8901,12 +8901,12 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
     }
 
     // @@protoc_insertion_point(class_scope:io.prometheus.client.Histogram)
-    private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram DEFAULT_INSTANCE;
+    private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram DEFAULT_INSTANCE;
     static {
-      DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram();
+      DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram();
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram getDefaultInstance() {
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram getDefaultInstance() {
       return DEFAULT_INSTANCE;
     }
 
@@ -8942,7 +8942,7 @@ public com.google.protobuf.Parser getParserForType() {
     }
 
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram getDefaultInstanceForType() {
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram getDefaultInstanceForType() {
       return DEFAULT_INSTANCE;
     }
 
@@ -9018,11 +9018,11 @@ public interface BucketOrBuilder extends
      * optional .io.prometheus.client.Exemplar exemplar = 3;
      * @return The exemplar.
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar getExemplar();
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar getExemplar();
     /**
      * optional .io.prometheus.client.Exemplar exemplar = 3;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder getExemplarOrBuilder();
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder getExemplarOrBuilder();
   }
   /**
    * 
@@ -9042,7 +9042,7 @@ public static final class Bucket extends
         com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
         /* major= */ 4,
         /* minor= */ 33,
-        /* patch= */ 2,
+        /* patch= */ 5,
         /* suffix= */ "",
         "Bucket");
     }
@@ -9055,15 +9055,15 @@ private Bucket() {
 
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Bucket_descriptor;
+      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Bucket_descriptor;
     }
 
     @java.lang.Override
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Bucket_fieldAccessorTable
+      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Bucket_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.Builder.class);
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.Builder.class);
     }
 
     private int bitField0_;
@@ -9149,7 +9149,7 @@ public double getUpperBound() {
     }
 
     public static final int EXEMPLAR_FIELD_NUMBER = 3;
-    private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar exemplar_;
+    private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar exemplar_;
     /**
      * optional .io.prometheus.client.Exemplar exemplar = 3;
      * @return Whether the exemplar field is set.
@@ -9163,15 +9163,15 @@ public boolean hasExemplar() {
      * @return The exemplar.
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar getExemplar() {
-      return exemplar_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.getDefaultInstance() : exemplar_;
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar getExemplar() {
+      return exemplar_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.getDefaultInstance() : exemplar_;
     }
     /**
      * optional .io.prometheus.client.Exemplar exemplar = 3;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder getExemplarOrBuilder() {
-      return exemplar_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.getDefaultInstance() : exemplar_;
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder getExemplarOrBuilder() {
+      return exemplar_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.getDefaultInstance() : exemplar_;
     }
 
     private byte memoizedIsInitialized = -1;
@@ -9235,10 +9235,10 @@ public boolean equals(final java.lang.Object obj) {
       if (obj == this) {
        return true;
       }
-      if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket)) {
+      if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket)) {
         return super.equals(obj);
       }
-      io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket) obj;
+      io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket) obj;
 
       if (hasCumulativeCount() != other.hasCumulativeCount()) return false;
       if (hasCumulativeCount()) {
@@ -9297,44 +9297,44 @@ public int hashCode() {
       return hash;
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket parseFrom(
         java.nio.ByteBuffer data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket parseFrom(
         java.nio.ByteBuffer data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket parseFrom(byte[] data)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket parseFrom(java.io.InputStream input)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseWithIOException(PARSER, input);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -9342,26 +9342,26 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto
           .parseWithIOException(PARSER, input, extensionRegistry);
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket parseDelimitedFrom(java.io.InputStream input)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseDelimitedWithIOException(PARSER, input);
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket parseDelimitedFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseWithIOException(PARSER, input);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -9374,7 +9374,7 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto
     public static Builder newBuilder() {
       return DEFAULT_INSTANCE.toBuilder();
     }
-    public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket prototype) {
+    public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket prototype) {
       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
     }
     @java.lang.Override
@@ -9400,21 +9400,21 @@ protected Builder newBuilderForType(
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder implements
         // @@protoc_insertion_point(builder_implements:io.prometheus.client.Bucket)
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketOrBuilder {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Bucket_descriptor;
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Bucket_descriptor;
       }
 
       @java.lang.Override
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Bucket_fieldAccessorTable
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Bucket_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.Builder.class);
+                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.Builder.class);
       }
 
-      // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.newBuilder()
+      // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -9448,17 +9448,17 @@ public Builder clear() {
       @java.lang.Override
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Bucket_descriptor;
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Bucket_descriptor;
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket getDefaultInstanceForType() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.getDefaultInstance();
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket getDefaultInstanceForType() {
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.getDefaultInstance();
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket build() {
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket result = buildPartial();
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket build() {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
@@ -9466,14 +9466,14 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket buildPartial() {
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket(this);
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket buildPartial() {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket(this);
         if (bitField0_ != 0) { buildPartial0(result); }
         onBuilt();
         return result;
       }
 
-      private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket result) {
+      private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket result) {
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000001) != 0)) {
@@ -9499,16 +9499,16 @@ private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com
 
       @java.lang.Override
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket) {
-          return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket)other);
+        if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket) {
+          return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket other) {
-        if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket.getDefaultInstance()) return this;
+      public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket other) {
+        if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket.getDefaultInstance()) return this;
         if (other.hasCumulativeCount()) {
           setCumulativeCount(other.getCumulativeCount());
         }
@@ -9754,9 +9754,9 @@ public Builder clearUpperBound() {
         return this;
       }
 
-      private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar exemplar_;
+      private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar exemplar_;
       private com.google.protobuf.SingleFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder> exemplarBuilder_;
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder> exemplarBuilder_;
       /**
        * optional .io.prometheus.client.Exemplar exemplar = 3;
        * @return Whether the exemplar field is set.
@@ -9768,9 +9768,9 @@ public boolean hasExemplar() {
        * optional .io.prometheus.client.Exemplar exemplar = 3;
        * @return The exemplar.
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar getExemplar() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar getExemplar() {
         if (exemplarBuilder_ == null) {
-          return exemplar_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.getDefaultInstance() : exemplar_;
+          return exemplar_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.getDefaultInstance() : exemplar_;
         } else {
           return exemplarBuilder_.getMessage();
         }
@@ -9778,7 +9778,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * optional .io.prometheus.client.Exemplar exemplar = 3;
        */
-      public Builder setExemplar(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar value) {
+      public Builder setExemplar(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar value) {
         if (exemplarBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -9795,7 +9795,7 @@ public Builder setExemplar(io.prometheus.metrics.expositionformats.generated.com
        * optional .io.prometheus.client.Exemplar exemplar = 3;
        */
       public Builder setExemplar(
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder builderForValue) {
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder builderForValue) {
         if (exemplarBuilder_ == null) {
           exemplar_ = builderForValue.build();
         } else {
@@ -9808,11 +9808,11 @@ public Builder setExemplar(
       /**
        * optional .io.prometheus.client.Exemplar exemplar = 3;
        */
-      public Builder mergeExemplar(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar value) {
+      public Builder mergeExemplar(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar value) {
         if (exemplarBuilder_ == null) {
           if (((bitField0_ & 0x00000008) != 0) &&
             exemplar_ != null &&
-            exemplar_ != io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.getDefaultInstance()) {
+            exemplar_ != io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.getDefaultInstance()) {
             getExemplarBuilder().mergeFrom(value);
           } else {
             exemplar_ = value;
@@ -9842,7 +9842,7 @@ public Builder clearExemplar() {
       /**
        * optional .io.prometheus.client.Exemplar exemplar = 3;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder getExemplarBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder getExemplarBuilder() {
         bitField0_ |= 0x00000008;
         onChanged();
         return internalGetExemplarFieldBuilder().getBuilder();
@@ -9850,23 +9850,23 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * optional .io.prometheus.client.Exemplar exemplar = 3;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder getExemplarOrBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder getExemplarOrBuilder() {
         if (exemplarBuilder_ != null) {
           return exemplarBuilder_.getMessageOrBuilder();
         } else {
           return exemplar_ == null ?
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.getDefaultInstance() : exemplar_;
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.getDefaultInstance() : exemplar_;
         }
       }
       /**
        * optional .io.prometheus.client.Exemplar exemplar = 3;
        */
       private com.google.protobuf.SingleFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder> 
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder> 
           internalGetExemplarFieldBuilder() {
         if (exemplarBuilder_ == null) {
           exemplarBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder>(
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder>(
                   getExemplar(),
                   getParentForChildren(),
                   isClean());
@@ -9879,12 +9879,12 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
     }
 
     // @@protoc_insertion_point(class_scope:io.prometheus.client.Bucket)
-    private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket DEFAULT_INSTANCE;
+    private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket DEFAULT_INSTANCE;
     static {
-      DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket();
+      DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket();
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket getDefaultInstance() {
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket getDefaultInstance() {
       return DEFAULT_INSTANCE;
     }
 
@@ -9920,7 +9920,7 @@ public com.google.protobuf.Parser getParserForType() {
     }
 
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Bucket getDefaultInstanceForType() {
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Bucket getDefaultInstanceForType() {
       return DEFAULT_INSTANCE;
     }
 
@@ -9990,7 +9990,7 @@ public static final class BucketSpan extends
         com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
         /* major= */ 4,
         /* minor= */ 33,
-        /* patch= */ 2,
+        /* patch= */ 5,
         /* suffix= */ "",
         "BucketSpan");
     }
@@ -10003,15 +10003,15 @@ private BucketSpan() {
 
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_BucketSpan_descriptor;
+      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_BucketSpan_descriptor;
     }
 
     @java.lang.Override
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_BucketSpan_fieldAccessorTable
+      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_BucketSpan_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder.class);
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder.class);
     }
 
     private int bitField0_;
@@ -10116,10 +10116,10 @@ public boolean equals(final java.lang.Object obj) {
       if (obj == this) {
        return true;
       }
-      if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan)) {
+      if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan)) {
         return super.equals(obj);
       }
-      io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan) obj;
+      io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan) obj;
 
       if (hasOffset() != other.hasOffset()) return false;
       if (hasOffset()) {
@@ -10155,44 +10155,44 @@ public int hashCode() {
       return hash;
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan parseFrom(
         java.nio.ByteBuffer data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan parseFrom(
         java.nio.ByteBuffer data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan parseFrom(byte[] data)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan parseFrom(java.io.InputStream input)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseWithIOException(PARSER, input);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -10200,26 +10200,26 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto
           .parseWithIOException(PARSER, input, extensionRegistry);
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan parseDelimitedFrom(java.io.InputStream input)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseDelimitedWithIOException(PARSER, input);
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan parseDelimitedFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseWithIOException(PARSER, input);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -10232,7 +10232,7 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto
     public static Builder newBuilder() {
       return DEFAULT_INSTANCE.toBuilder();
     }
-    public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan prototype) {
+    public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan prototype) {
       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
     }
     @java.lang.Override
@@ -10262,21 +10262,21 @@ protected Builder newBuilderForType(
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder implements
         // @@protoc_insertion_point(builder_implements:io.prometheus.client.BucketSpan)
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpanOrBuilder {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpanOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_BucketSpan_descriptor;
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_BucketSpan_descriptor;
       }
 
       @java.lang.Override
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_BucketSpan_fieldAccessorTable
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_BucketSpan_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.Builder.class);
+                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.Builder.class);
       }
 
-      // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.newBuilder()
+      // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.newBuilder()
       private Builder() {
 
       }
@@ -10298,17 +10298,17 @@ public Builder clear() {
       @java.lang.Override
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_BucketSpan_descriptor;
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_BucketSpan_descriptor;
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan getDefaultInstanceForType() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.getDefaultInstance();
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan getDefaultInstanceForType() {
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.getDefaultInstance();
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan build() {
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan result = buildPartial();
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan build() {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
@@ -10316,14 +10316,14 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan buildPartial() {
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan(this);
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan buildPartial() {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan(this);
         if (bitField0_ != 0) { buildPartial0(result); }
         onBuilt();
         return result;
       }
 
-      private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan result) {
+      private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan result) {
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000001) != 0)) {
@@ -10339,16 +10339,16 @@ private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com
 
       @java.lang.Override
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan) {
-          return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan)other);
+        if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan) {
+          return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan other) {
-        if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan.getDefaultInstance()) return this;
+      public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan other) {
+        if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan.getDefaultInstance()) return this;
         if (other.hasOffset()) {
           setOffset(other.getOffset());
         }
@@ -10524,12 +10524,12 @@ public Builder clearLength() {
     }
 
     // @@protoc_insertion_point(class_scope:io.prometheus.client.BucketSpan)
-    private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan DEFAULT_INSTANCE;
+    private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan DEFAULT_INSTANCE;
     static {
-      DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan();
+      DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan();
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan getDefaultInstance() {
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan getDefaultInstance() {
       return DEFAULT_INSTANCE;
     }
 
@@ -10565,7 +10565,7 @@ public com.google.protobuf.Parser getParserForType() {
     }
 
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.BucketSpan getDefaultInstanceForType() {
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.BucketSpan getDefaultInstanceForType() {
       return DEFAULT_INSTANCE;
     }
 
@@ -10578,12 +10578,12 @@ public interface ExemplarOrBuilder extends
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
-    java.util.List 
+    java.util.List 
         getLabelList();
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair getLabel(int index);
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair getLabel(int index);
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
@@ -10591,12 +10591,12 @@ public interface ExemplarOrBuilder extends
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
-    java.util.List 
+    java.util.List 
         getLabelOrBuilderList();
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPairOrBuilder getLabelOrBuilder(
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPairOrBuilder getLabelOrBuilder(
         int index);
 
     /**
@@ -10650,7 +10650,7 @@ public static final class Exemplar extends
         com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
         /* major= */ 4,
         /* minor= */ 33,
-        /* patch= */ 2,
+        /* patch= */ 5,
         /* suffix= */ "",
         "Exemplar");
     }
@@ -10664,33 +10664,33 @@ private Exemplar() {
 
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Exemplar_descriptor;
+      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Exemplar_descriptor;
     }
 
     @java.lang.Override
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Exemplar_fieldAccessorTable
+      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Exemplar_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder.class);
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder.class);
     }
 
     private int bitField0_;
     public static final int LABEL_FIELD_NUMBER = 1;
     @SuppressWarnings("serial")
-    private java.util.List label_;
+    private java.util.List label_;
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
     @java.lang.Override
-    public java.util.List getLabelList() {
+    public java.util.List getLabelList() {
       return label_;
     }
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
     @java.lang.Override
-    public java.util.List 
+    public java.util.List 
         getLabelOrBuilderList() {
       return label_;
     }
@@ -10705,14 +10705,14 @@ public int getLabelCount() {
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair getLabel(int index) {
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair getLabel(int index) {
       return label_.get(index);
     }
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPairOrBuilder getLabelOrBuilder(
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPairOrBuilder getLabelOrBuilder(
         int index) {
       return label_.get(index);
     }
@@ -10828,10 +10828,10 @@ public boolean equals(final java.lang.Object obj) {
       if (obj == this) {
        return true;
       }
-      if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar)) {
+      if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar)) {
         return super.equals(obj);
       }
-      io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar) obj;
+      io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar) obj;
 
       if (!getLabelList()
           .equals(other.getLabelList())) return false;
@@ -10875,44 +10875,44 @@ public int hashCode() {
       return hash;
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar parseFrom(
         java.nio.ByteBuffer data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar parseFrom(
         java.nio.ByteBuffer data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar parseFrom(byte[] data)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar parseFrom(java.io.InputStream input)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseWithIOException(PARSER, input);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -10920,26 +10920,26 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto
           .parseWithIOException(PARSER, input, extensionRegistry);
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar parseDelimitedFrom(java.io.InputStream input)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseDelimitedWithIOException(PARSER, input);
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar parseDelimitedFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseWithIOException(PARSER, input);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -10952,7 +10952,7 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto
     public static Builder newBuilder() {
       return DEFAULT_INSTANCE.toBuilder();
     }
-    public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar prototype) {
+    public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar prototype) {
       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
     }
     @java.lang.Override
@@ -10973,21 +10973,21 @@ protected Builder newBuilderForType(
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder implements
         // @@protoc_insertion_point(builder_implements:io.prometheus.client.Exemplar)
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.ExemplarOrBuilder {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.ExemplarOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Exemplar_descriptor;
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Exemplar_descriptor;
       }
 
       @java.lang.Override
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Exemplar_fieldAccessorTable
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Exemplar_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.Builder.class);
+                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.Builder.class);
       }
 
-      // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.newBuilder()
+      // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -11027,17 +11027,17 @@ public Builder clear() {
       @java.lang.Override
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Exemplar_descriptor;
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Exemplar_descriptor;
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar getDefaultInstanceForType() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.getDefaultInstance();
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar getDefaultInstanceForType() {
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.getDefaultInstance();
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar build() {
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar result = buildPartial();
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar build() {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
@@ -11045,15 +11045,15 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar buildPartial() {
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar(this);
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar buildPartial() {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar(this);
         buildPartialRepeatedFields(result);
         if (bitField0_ != 0) { buildPartial0(result); }
         onBuilt();
         return result;
       }
 
-      private void buildPartialRepeatedFields(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar result) {
+      private void buildPartialRepeatedFields(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar result) {
         if (labelBuilder_ == null) {
           if (((bitField0_ & 0x00000001) != 0)) {
             label_ = java.util.Collections.unmodifiableList(label_);
@@ -11065,7 +11065,7 @@ private void buildPartialRepeatedFields(io.prometheus.metrics.expositionformats.
         }
       }
 
-      private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar result) {
+      private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar result) {
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000002) != 0)) {
@@ -11083,16 +11083,16 @@ private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com
 
       @java.lang.Override
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar) {
-          return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar)other);
+        if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar) {
+          return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar other) {
-        if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar.getDefaultInstance()) return this;
+      public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar other) {
+        if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar.getDefaultInstance()) return this;
         if (labelBuilder_ == null) {
           if (!other.label_.isEmpty()) {
             if (label_.isEmpty()) {
@@ -11152,9 +11152,9 @@ public Builder mergeFrom(
                 done = true;
                 break;
               case 10: {
-                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair m =
+                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair m =
                     input.readMessage(
-                        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.parser(),
+                        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.parser(),
                         extensionRegistry);
                 if (labelBuilder_ == null) {
                   ensureLabelIsMutable();
@@ -11193,22 +11193,22 @@ public Builder mergeFrom(
       }
       private int bitField0_;
 
-      private java.util.List label_ =
+      private java.util.List label_ =
         java.util.Collections.emptyList();
       private void ensureLabelIsMutable() {
         if (!((bitField0_ & 0x00000001) != 0)) {
-          label_ = new java.util.ArrayList(label_);
+          label_ = new java.util.ArrayList(label_);
           bitField0_ |= 0x00000001;
          }
       }
 
       private com.google.protobuf.RepeatedFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPairOrBuilder> labelBuilder_;
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPairOrBuilder> labelBuilder_;
 
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public java.util.List getLabelList() {
+      public java.util.List getLabelList() {
         if (labelBuilder_ == null) {
           return java.util.Collections.unmodifiableList(label_);
         } else {
@@ -11228,7 +11228,7 @@ public int getLabelCount() {
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair getLabel(int index) {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair getLabel(int index) {
         if (labelBuilder_ == null) {
           return label_.get(index);
         } else {
@@ -11239,7 +11239,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
       public Builder setLabel(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair value) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair value) {
         if (labelBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -11256,7 +11256,7 @@ public Builder setLabel(
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
       public Builder setLabel(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder builderForValue) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder builderForValue) {
         if (labelBuilder_ == null) {
           ensureLabelIsMutable();
           label_.set(index, builderForValue.build());
@@ -11269,7 +11269,7 @@ public Builder setLabel(
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public Builder addLabel(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair value) {
+      public Builder addLabel(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair value) {
         if (labelBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -11286,7 +11286,7 @@ public Builder addLabel(io.prometheus.metrics.expositionformats.generated.com_go
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
       public Builder addLabel(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair value) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair value) {
         if (labelBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -11303,7 +11303,7 @@ public Builder addLabel(
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
       public Builder addLabel(
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder builderForValue) {
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder builderForValue) {
         if (labelBuilder_ == null) {
           ensureLabelIsMutable();
           label_.add(builderForValue.build());
@@ -11317,7 +11317,7 @@ public Builder addLabel(
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
       public Builder addLabel(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder builderForValue) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder builderForValue) {
         if (labelBuilder_ == null) {
           ensureLabelIsMutable();
           label_.add(index, builderForValue.build());
@@ -11331,7 +11331,7 @@ public Builder addLabel(
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
       public Builder addAllLabel(
-          java.lang.Iterable values) {
+          java.lang.Iterable values) {
         if (labelBuilder_ == null) {
           ensureLabelIsMutable();
           com.google.protobuf.AbstractMessageLite.Builder.addAll(
@@ -11371,14 +11371,14 @@ public Builder removeLabel(int index) {
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder getLabelBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder getLabelBuilder(
           int index) {
         return internalGetLabelFieldBuilder().getBuilder(index);
       }
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPairOrBuilder getLabelOrBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPairOrBuilder getLabelOrBuilder(
           int index) {
         if (labelBuilder_ == null) {
           return label_.get(index);  } else {
@@ -11388,7 +11388,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public java.util.List 
+      public java.util.List 
            getLabelOrBuilderList() {
         if (labelBuilder_ != null) {
           return labelBuilder_.getMessageOrBuilderList();
@@ -11399,31 +11399,31 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder addLabelBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder addLabelBuilder() {
         return internalGetLabelFieldBuilder().addBuilder(
-            io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.getDefaultInstance());
+            io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.getDefaultInstance());
       }
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder addLabelBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder addLabelBuilder(
           int index) {
         return internalGetLabelFieldBuilder().addBuilder(
-            index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.getDefaultInstance());
+            index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.getDefaultInstance());
       }
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public java.util.List 
+      public java.util.List 
            getLabelBuilderList() {
         return internalGetLabelFieldBuilder().getBuilderList();
       }
       private com.google.protobuf.RepeatedFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPairOrBuilder> 
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPairOrBuilder> 
           internalGetLabelFieldBuilder() {
         if (labelBuilder_ == null) {
           labelBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPairOrBuilder>(
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPairOrBuilder>(
                   label_,
                   ((bitField0_ & 0x00000001) != 0),
                   getParentForChildren(),
@@ -11634,12 +11634,12 @@ public com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder() {
     }
 
     // @@protoc_insertion_point(class_scope:io.prometheus.client.Exemplar)
-    private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar DEFAULT_INSTANCE;
+    private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar DEFAULT_INSTANCE;
     static {
-      DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar();
+      DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar();
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar getDefaultInstance() {
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar getDefaultInstance() {
       return DEFAULT_INSTANCE;
     }
 
@@ -11675,7 +11675,7 @@ public com.google.protobuf.Parser getParserForType() {
     }
 
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Exemplar getDefaultInstanceForType() {
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Exemplar getDefaultInstanceForType() {
       return DEFAULT_INSTANCE;
     }
 
@@ -11688,12 +11688,12 @@ public interface MetricOrBuilder extends
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
-    java.util.List 
+    java.util.List 
         getLabelList();
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair getLabel(int index);
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair getLabel(int index);
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
@@ -11701,12 +11701,12 @@ public interface MetricOrBuilder extends
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
-    java.util.List 
+    java.util.List 
         getLabelOrBuilderList();
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPairOrBuilder getLabelOrBuilder(
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPairOrBuilder getLabelOrBuilder(
         int index);
 
     /**
@@ -11718,11 +11718,11 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      * optional .io.prometheus.client.Gauge gauge = 2;
      * @return The gauge.
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge getGauge();
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge getGauge();
     /**
      * optional .io.prometheus.client.Gauge gauge = 2;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.GaugeOrBuilder getGaugeOrBuilder();
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.GaugeOrBuilder getGaugeOrBuilder();
 
     /**
      * optional .io.prometheus.client.Counter counter = 3;
@@ -11733,11 +11733,11 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      * optional .io.prometheus.client.Counter counter = 3;
      * @return The counter.
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter getCounter();
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter getCounter();
     /**
      * optional .io.prometheus.client.Counter counter = 3;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.CounterOrBuilder getCounterOrBuilder();
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.CounterOrBuilder getCounterOrBuilder();
 
     /**
      * optional .io.prometheus.client.Summary summary = 4;
@@ -11748,11 +11748,11 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      * optional .io.prometheus.client.Summary summary = 4;
      * @return The summary.
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary getSummary();
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary getSummary();
     /**
      * optional .io.prometheus.client.Summary summary = 4;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.SummaryOrBuilder getSummaryOrBuilder();
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.SummaryOrBuilder getSummaryOrBuilder();
 
     /**
      * optional .io.prometheus.client.Untyped untyped = 5;
@@ -11763,11 +11763,11 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      * optional .io.prometheus.client.Untyped untyped = 5;
      * @return The untyped.
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped getUntyped();
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped getUntyped();
     /**
      * optional .io.prometheus.client.Untyped untyped = 5;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.UntypedOrBuilder getUntypedOrBuilder();
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.UntypedOrBuilder getUntypedOrBuilder();
 
     /**
      * optional .io.prometheus.client.Histogram histogram = 7;
@@ -11778,11 +11778,11 @@ io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Met
      * optional .io.prometheus.client.Histogram histogram = 7;
      * @return The histogram.
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram getHistogram();
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram getHistogram();
     /**
      * optional .io.prometheus.client.Histogram histogram = 7;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.HistogramOrBuilder getHistogramOrBuilder();
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.HistogramOrBuilder getHistogramOrBuilder();
 
     /**
      * optional int64 timestamp_ms = 6;
@@ -11808,7 +11808,7 @@ public static final class Metric extends
         com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
         /* major= */ 4,
         /* minor= */ 33,
-        /* patch= */ 2,
+        /* patch= */ 5,
         /* suffix= */ "",
         "Metric");
     }
@@ -11822,33 +11822,33 @@ private Metric() {
 
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Metric_descriptor;
+      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Metric_descriptor;
     }
 
     @java.lang.Override
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Metric_fieldAccessorTable
+      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Metric_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.Builder.class);
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.Builder.class);
     }
 
     private int bitField0_;
     public static final int LABEL_FIELD_NUMBER = 1;
     @SuppressWarnings("serial")
-    private java.util.List label_;
+    private java.util.List label_;
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
     @java.lang.Override
-    public java.util.List getLabelList() {
+    public java.util.List getLabelList() {
       return label_;
     }
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
     @java.lang.Override
-    public java.util.List 
+    public java.util.List 
         getLabelOrBuilderList() {
       return label_;
     }
@@ -11863,20 +11863,20 @@ public int getLabelCount() {
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair getLabel(int index) {
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair getLabel(int index) {
       return label_.get(index);
     }
     /**
      * repeated .io.prometheus.client.LabelPair label = 1;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPairOrBuilder getLabelOrBuilder(
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPairOrBuilder getLabelOrBuilder(
         int index) {
       return label_.get(index);
     }
 
     public static final int GAUGE_FIELD_NUMBER = 2;
-    private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge gauge_;
+    private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge gauge_;
     /**
      * optional .io.prometheus.client.Gauge gauge = 2;
      * @return Whether the gauge field is set.
@@ -11890,19 +11890,19 @@ public boolean hasGauge() {
      * @return The gauge.
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge getGauge() {
-      return gauge_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.getDefaultInstance() : gauge_;
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge getGauge() {
+      return gauge_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.getDefaultInstance() : gauge_;
     }
     /**
      * optional .io.prometheus.client.Gauge gauge = 2;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.GaugeOrBuilder getGaugeOrBuilder() {
-      return gauge_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.getDefaultInstance() : gauge_;
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.GaugeOrBuilder getGaugeOrBuilder() {
+      return gauge_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.getDefaultInstance() : gauge_;
     }
 
     public static final int COUNTER_FIELD_NUMBER = 3;
-    private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter counter_;
+    private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter counter_;
     /**
      * optional .io.prometheus.client.Counter counter = 3;
      * @return Whether the counter field is set.
@@ -11916,19 +11916,19 @@ public boolean hasCounter() {
      * @return The counter.
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter getCounter() {
-      return counter_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.getDefaultInstance() : counter_;
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter getCounter() {
+      return counter_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.getDefaultInstance() : counter_;
     }
     /**
      * optional .io.prometheus.client.Counter counter = 3;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.CounterOrBuilder getCounterOrBuilder() {
-      return counter_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.getDefaultInstance() : counter_;
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.CounterOrBuilder getCounterOrBuilder() {
+      return counter_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.getDefaultInstance() : counter_;
     }
 
     public static final int SUMMARY_FIELD_NUMBER = 4;
-    private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary summary_;
+    private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary summary_;
     /**
      * optional .io.prometheus.client.Summary summary = 4;
      * @return Whether the summary field is set.
@@ -11942,19 +11942,19 @@ public boolean hasSummary() {
      * @return The summary.
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary getSummary() {
-      return summary_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.getDefaultInstance() : summary_;
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary getSummary() {
+      return summary_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.getDefaultInstance() : summary_;
     }
     /**
      * optional .io.prometheus.client.Summary summary = 4;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.SummaryOrBuilder getSummaryOrBuilder() {
-      return summary_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.getDefaultInstance() : summary_;
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.SummaryOrBuilder getSummaryOrBuilder() {
+      return summary_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.getDefaultInstance() : summary_;
     }
 
     public static final int UNTYPED_FIELD_NUMBER = 5;
-    private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped untyped_;
+    private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped untyped_;
     /**
      * optional .io.prometheus.client.Untyped untyped = 5;
      * @return Whether the untyped field is set.
@@ -11968,19 +11968,19 @@ public boolean hasUntyped() {
      * @return The untyped.
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped getUntyped() {
-      return untyped_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.getDefaultInstance() : untyped_;
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped getUntyped() {
+      return untyped_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.getDefaultInstance() : untyped_;
     }
     /**
      * optional .io.prometheus.client.Untyped untyped = 5;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.UntypedOrBuilder getUntypedOrBuilder() {
-      return untyped_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.getDefaultInstance() : untyped_;
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.UntypedOrBuilder getUntypedOrBuilder() {
+      return untyped_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.getDefaultInstance() : untyped_;
     }
 
     public static final int HISTOGRAM_FIELD_NUMBER = 7;
-    private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram histogram_;
+    private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram histogram_;
     /**
      * optional .io.prometheus.client.Histogram histogram = 7;
      * @return Whether the histogram field is set.
@@ -11994,15 +11994,15 @@ public boolean hasHistogram() {
      * @return The histogram.
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram getHistogram() {
-      return histogram_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.getDefaultInstance() : histogram_;
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram getHistogram() {
+      return histogram_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.getDefaultInstance() : histogram_;
     }
     /**
      * optional .io.prometheus.client.Histogram histogram = 7;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.HistogramOrBuilder getHistogramOrBuilder() {
-      return histogram_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.getDefaultInstance() : histogram_;
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.HistogramOrBuilder getHistogramOrBuilder() {
+      return histogram_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.getDefaultInstance() : histogram_;
     }
 
     public static final int TIMESTAMP_MS_FIELD_NUMBER = 6;
@@ -12106,10 +12106,10 @@ public boolean equals(final java.lang.Object obj) {
       if (obj == this) {
        return true;
       }
-      if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric)) {
+      if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric)) {
         return super.equals(obj);
       }
-      io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric) obj;
+      io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric) obj;
 
       if (!getLabelList()
           .equals(other.getLabelList())) return false;
@@ -12188,44 +12188,44 @@ public int hashCode() {
       return hash;
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric parseFrom(
         java.nio.ByteBuffer data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric parseFrom(
         java.nio.ByteBuffer data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric parseFrom(byte[] data)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric parseFrom(java.io.InputStream input)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseWithIOException(PARSER, input);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -12233,26 +12233,26 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto
           .parseWithIOException(PARSER, input, extensionRegistry);
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric parseDelimitedFrom(java.io.InputStream input)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseDelimitedWithIOException(PARSER, input);
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric parseDelimitedFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseWithIOException(PARSER, input);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -12265,7 +12265,7 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto
     public static Builder newBuilder() {
       return DEFAULT_INSTANCE.toBuilder();
     }
-    public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric prototype) {
+    public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric prototype) {
       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
     }
     @java.lang.Override
@@ -12286,21 +12286,21 @@ protected Builder newBuilderForType(
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder implements
         // @@protoc_insertion_point(builder_implements:io.prometheus.client.Metric)
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricOrBuilder {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Metric_descriptor;
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Metric_descriptor;
       }
 
       @java.lang.Override
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Metric_fieldAccessorTable
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Metric_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.Builder.class);
+                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.Builder.class);
       }
 
-      // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.newBuilder()
+      // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -12364,17 +12364,17 @@ public Builder clear() {
       @java.lang.Override
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_Metric_descriptor;
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_Metric_descriptor;
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric getDefaultInstanceForType() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.getDefaultInstance();
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric getDefaultInstanceForType() {
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.getDefaultInstance();
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric build() {
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric result = buildPartial();
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric build() {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
@@ -12382,15 +12382,15 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric buildPartial() {
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric(this);
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric buildPartial() {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric(this);
         buildPartialRepeatedFields(result);
         if (bitField0_ != 0) { buildPartial0(result); }
         onBuilt();
         return result;
       }
 
-      private void buildPartialRepeatedFields(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric result) {
+      private void buildPartialRepeatedFields(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric result) {
         if (labelBuilder_ == null) {
           if (((bitField0_ & 0x00000001) != 0)) {
             label_ = java.util.Collections.unmodifiableList(label_);
@@ -12402,7 +12402,7 @@ private void buildPartialRepeatedFields(io.prometheus.metrics.expositionformats.
         }
       }
 
-      private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric result) {
+      private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric result) {
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000002) != 0)) {
@@ -12444,16 +12444,16 @@ private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com
 
       @java.lang.Override
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric) {
-          return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric)other);
+        if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric) {
+          return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric other) {
-        if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.getDefaultInstance()) return this;
+      public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric other) {
+        if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.getDefaultInstance()) return this;
         if (labelBuilder_ == null) {
           if (!other.label_.isEmpty()) {
             if (label_.isEmpty()) {
@@ -12525,9 +12525,9 @@ public Builder mergeFrom(
                 done = true;
                 break;
               case 10: {
-                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair m =
+                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair m =
                     input.readMessage(
-                        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.parser(),
+                        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.parser(),
                         extensionRegistry);
                 if (labelBuilder_ == null) {
                   ensureLabelIsMutable();
@@ -12594,22 +12594,22 @@ public Builder mergeFrom(
       }
       private int bitField0_;
 
-      private java.util.List label_ =
+      private java.util.List label_ =
         java.util.Collections.emptyList();
       private void ensureLabelIsMutable() {
         if (!((bitField0_ & 0x00000001) != 0)) {
-          label_ = new java.util.ArrayList(label_);
+          label_ = new java.util.ArrayList(label_);
           bitField0_ |= 0x00000001;
          }
       }
 
       private com.google.protobuf.RepeatedFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPairOrBuilder> labelBuilder_;
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPairOrBuilder> labelBuilder_;
 
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public java.util.List getLabelList() {
+      public java.util.List getLabelList() {
         if (labelBuilder_ == null) {
           return java.util.Collections.unmodifiableList(label_);
         } else {
@@ -12629,7 +12629,7 @@ public int getLabelCount() {
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair getLabel(int index) {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair getLabel(int index) {
         if (labelBuilder_ == null) {
           return label_.get(index);
         } else {
@@ -12640,7 +12640,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
       public Builder setLabel(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair value) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair value) {
         if (labelBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -12657,7 +12657,7 @@ public Builder setLabel(
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
       public Builder setLabel(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder builderForValue) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder builderForValue) {
         if (labelBuilder_ == null) {
           ensureLabelIsMutable();
           label_.set(index, builderForValue.build());
@@ -12670,7 +12670,7 @@ public Builder setLabel(
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public Builder addLabel(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair value) {
+      public Builder addLabel(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair value) {
         if (labelBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -12687,7 +12687,7 @@ public Builder addLabel(io.prometheus.metrics.expositionformats.generated.com_go
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
       public Builder addLabel(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair value) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair value) {
         if (labelBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -12704,7 +12704,7 @@ public Builder addLabel(
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
       public Builder addLabel(
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder builderForValue) {
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder builderForValue) {
         if (labelBuilder_ == null) {
           ensureLabelIsMutable();
           label_.add(builderForValue.build());
@@ -12718,7 +12718,7 @@ public Builder addLabel(
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
       public Builder addLabel(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder builderForValue) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder builderForValue) {
         if (labelBuilder_ == null) {
           ensureLabelIsMutable();
           label_.add(index, builderForValue.build());
@@ -12732,7 +12732,7 @@ public Builder addLabel(
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
       public Builder addAllLabel(
-          java.lang.Iterable values) {
+          java.lang.Iterable values) {
         if (labelBuilder_ == null) {
           ensureLabelIsMutable();
           com.google.protobuf.AbstractMessageLite.Builder.addAll(
@@ -12772,14 +12772,14 @@ public Builder removeLabel(int index) {
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder getLabelBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder getLabelBuilder(
           int index) {
         return internalGetLabelFieldBuilder().getBuilder(index);
       }
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPairOrBuilder getLabelOrBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPairOrBuilder getLabelOrBuilder(
           int index) {
         if (labelBuilder_ == null) {
           return label_.get(index);  } else {
@@ -12789,7 +12789,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public java.util.List 
+      public java.util.List 
            getLabelOrBuilderList() {
         if (labelBuilder_ != null) {
           return labelBuilder_.getMessageOrBuilderList();
@@ -12800,31 +12800,31 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder addLabelBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder addLabelBuilder() {
         return internalGetLabelFieldBuilder().addBuilder(
-            io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.getDefaultInstance());
+            io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.getDefaultInstance());
       }
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder addLabelBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder addLabelBuilder(
           int index) {
         return internalGetLabelFieldBuilder().addBuilder(
-            index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.getDefaultInstance());
+            index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.getDefaultInstance());
       }
       /**
        * repeated .io.prometheus.client.LabelPair label = 1;
        */
-      public java.util.List 
+      public java.util.List 
            getLabelBuilderList() {
         return internalGetLabelFieldBuilder().getBuilderList();
       }
       private com.google.protobuf.RepeatedFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPairOrBuilder> 
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPairOrBuilder> 
           internalGetLabelFieldBuilder() {
         if (labelBuilder_ == null) {
           labelBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPair.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.LabelPairOrBuilder>(
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPair.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.LabelPairOrBuilder>(
                   label_,
                   ((bitField0_ & 0x00000001) != 0),
                   getParentForChildren(),
@@ -12834,9 +12834,9 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
         return labelBuilder_;
       }
 
-      private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge gauge_;
+      private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge gauge_;
       private com.google.protobuf.SingleFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.GaugeOrBuilder> gaugeBuilder_;
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.GaugeOrBuilder> gaugeBuilder_;
       /**
        * optional .io.prometheus.client.Gauge gauge = 2;
        * @return Whether the gauge field is set.
@@ -12848,9 +12848,9 @@ public boolean hasGauge() {
        * optional .io.prometheus.client.Gauge gauge = 2;
        * @return The gauge.
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge getGauge() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge getGauge() {
         if (gaugeBuilder_ == null) {
-          return gauge_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.getDefaultInstance() : gauge_;
+          return gauge_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.getDefaultInstance() : gauge_;
         } else {
           return gaugeBuilder_.getMessage();
         }
@@ -12858,7 +12858,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * optional .io.prometheus.client.Gauge gauge = 2;
        */
-      public Builder setGauge(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge value) {
+      public Builder setGauge(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge value) {
         if (gaugeBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -12875,7 +12875,7 @@ public Builder setGauge(io.prometheus.metrics.expositionformats.generated.com_go
        * optional .io.prometheus.client.Gauge gauge = 2;
        */
       public Builder setGauge(
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.Builder builderForValue) {
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.Builder builderForValue) {
         if (gaugeBuilder_ == null) {
           gauge_ = builderForValue.build();
         } else {
@@ -12888,11 +12888,11 @@ public Builder setGauge(
       /**
        * optional .io.prometheus.client.Gauge gauge = 2;
        */
-      public Builder mergeGauge(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge value) {
+      public Builder mergeGauge(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge value) {
         if (gaugeBuilder_ == null) {
           if (((bitField0_ & 0x00000002) != 0) &&
             gauge_ != null &&
-            gauge_ != io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.getDefaultInstance()) {
+            gauge_ != io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.getDefaultInstance()) {
             getGaugeBuilder().mergeFrom(value);
           } else {
             gauge_ = value;
@@ -12922,7 +12922,7 @@ public Builder clearGauge() {
       /**
        * optional .io.prometheus.client.Gauge gauge = 2;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.Builder getGaugeBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.Builder getGaugeBuilder() {
         bitField0_ |= 0x00000002;
         onChanged();
         return internalGetGaugeFieldBuilder().getBuilder();
@@ -12930,23 +12930,23 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * optional .io.prometheus.client.Gauge gauge = 2;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.GaugeOrBuilder getGaugeOrBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.GaugeOrBuilder getGaugeOrBuilder() {
         if (gaugeBuilder_ != null) {
           return gaugeBuilder_.getMessageOrBuilder();
         } else {
           return gauge_ == null ?
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.getDefaultInstance() : gauge_;
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.getDefaultInstance() : gauge_;
         }
       }
       /**
        * optional .io.prometheus.client.Gauge gauge = 2;
        */
       private com.google.protobuf.SingleFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.GaugeOrBuilder> 
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.GaugeOrBuilder> 
           internalGetGaugeFieldBuilder() {
         if (gaugeBuilder_ == null) {
           gaugeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Gauge.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.GaugeOrBuilder>(
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Gauge.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.GaugeOrBuilder>(
                   getGauge(),
                   getParentForChildren(),
                   isClean());
@@ -12955,9 +12955,9 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
         return gaugeBuilder_;
       }
 
-      private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter counter_;
+      private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter counter_;
       private com.google.protobuf.SingleFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.CounterOrBuilder> counterBuilder_;
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.CounterOrBuilder> counterBuilder_;
       /**
        * optional .io.prometheus.client.Counter counter = 3;
        * @return Whether the counter field is set.
@@ -12969,9 +12969,9 @@ public boolean hasCounter() {
        * optional .io.prometheus.client.Counter counter = 3;
        * @return The counter.
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter getCounter() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter getCounter() {
         if (counterBuilder_ == null) {
-          return counter_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.getDefaultInstance() : counter_;
+          return counter_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.getDefaultInstance() : counter_;
         } else {
           return counterBuilder_.getMessage();
         }
@@ -12979,7 +12979,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * optional .io.prometheus.client.Counter counter = 3;
        */
-      public Builder setCounter(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter value) {
+      public Builder setCounter(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter value) {
         if (counterBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -12996,7 +12996,7 @@ public Builder setCounter(io.prometheus.metrics.expositionformats.generated.com_
        * optional .io.prometheus.client.Counter counter = 3;
        */
       public Builder setCounter(
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.Builder builderForValue) {
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.Builder builderForValue) {
         if (counterBuilder_ == null) {
           counter_ = builderForValue.build();
         } else {
@@ -13009,11 +13009,11 @@ public Builder setCounter(
       /**
        * optional .io.prometheus.client.Counter counter = 3;
        */
-      public Builder mergeCounter(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter value) {
+      public Builder mergeCounter(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter value) {
         if (counterBuilder_ == null) {
           if (((bitField0_ & 0x00000004) != 0) &&
             counter_ != null &&
-            counter_ != io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.getDefaultInstance()) {
+            counter_ != io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.getDefaultInstance()) {
             getCounterBuilder().mergeFrom(value);
           } else {
             counter_ = value;
@@ -13043,7 +13043,7 @@ public Builder clearCounter() {
       /**
        * optional .io.prometheus.client.Counter counter = 3;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.Builder getCounterBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.Builder getCounterBuilder() {
         bitField0_ |= 0x00000004;
         onChanged();
         return internalGetCounterFieldBuilder().getBuilder();
@@ -13051,23 +13051,23 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * optional .io.prometheus.client.Counter counter = 3;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.CounterOrBuilder getCounterOrBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.CounterOrBuilder getCounterOrBuilder() {
         if (counterBuilder_ != null) {
           return counterBuilder_.getMessageOrBuilder();
         } else {
           return counter_ == null ?
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.getDefaultInstance() : counter_;
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.getDefaultInstance() : counter_;
         }
       }
       /**
        * optional .io.prometheus.client.Counter counter = 3;
        */
       private com.google.protobuf.SingleFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.CounterOrBuilder> 
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.CounterOrBuilder> 
           internalGetCounterFieldBuilder() {
         if (counterBuilder_ == null) {
           counterBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Counter.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.CounterOrBuilder>(
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Counter.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.CounterOrBuilder>(
                   getCounter(),
                   getParentForChildren(),
                   isClean());
@@ -13076,9 +13076,9 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
         return counterBuilder_;
       }
 
-      private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary summary_;
+      private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary summary_;
       private com.google.protobuf.SingleFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.SummaryOrBuilder> summaryBuilder_;
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.SummaryOrBuilder> summaryBuilder_;
       /**
        * optional .io.prometheus.client.Summary summary = 4;
        * @return Whether the summary field is set.
@@ -13090,9 +13090,9 @@ public boolean hasSummary() {
        * optional .io.prometheus.client.Summary summary = 4;
        * @return The summary.
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary getSummary() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary getSummary() {
         if (summaryBuilder_ == null) {
-          return summary_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.getDefaultInstance() : summary_;
+          return summary_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.getDefaultInstance() : summary_;
         } else {
           return summaryBuilder_.getMessage();
         }
@@ -13100,7 +13100,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * optional .io.prometheus.client.Summary summary = 4;
        */
-      public Builder setSummary(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary value) {
+      public Builder setSummary(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary value) {
         if (summaryBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -13117,7 +13117,7 @@ public Builder setSummary(io.prometheus.metrics.expositionformats.generated.com_
        * optional .io.prometheus.client.Summary summary = 4;
        */
       public Builder setSummary(
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.Builder builderForValue) {
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.Builder builderForValue) {
         if (summaryBuilder_ == null) {
           summary_ = builderForValue.build();
         } else {
@@ -13130,11 +13130,11 @@ public Builder setSummary(
       /**
        * optional .io.prometheus.client.Summary summary = 4;
        */
-      public Builder mergeSummary(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary value) {
+      public Builder mergeSummary(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary value) {
         if (summaryBuilder_ == null) {
           if (((bitField0_ & 0x00000008) != 0) &&
             summary_ != null &&
-            summary_ != io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.getDefaultInstance()) {
+            summary_ != io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.getDefaultInstance()) {
             getSummaryBuilder().mergeFrom(value);
           } else {
             summary_ = value;
@@ -13164,7 +13164,7 @@ public Builder clearSummary() {
       /**
        * optional .io.prometheus.client.Summary summary = 4;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.Builder getSummaryBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.Builder getSummaryBuilder() {
         bitField0_ |= 0x00000008;
         onChanged();
         return internalGetSummaryFieldBuilder().getBuilder();
@@ -13172,23 +13172,23 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * optional .io.prometheus.client.Summary summary = 4;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.SummaryOrBuilder getSummaryOrBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.SummaryOrBuilder getSummaryOrBuilder() {
         if (summaryBuilder_ != null) {
           return summaryBuilder_.getMessageOrBuilder();
         } else {
           return summary_ == null ?
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.getDefaultInstance() : summary_;
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.getDefaultInstance() : summary_;
         }
       }
       /**
        * optional .io.prometheus.client.Summary summary = 4;
        */
       private com.google.protobuf.SingleFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.SummaryOrBuilder> 
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.SummaryOrBuilder> 
           internalGetSummaryFieldBuilder() {
         if (summaryBuilder_ == null) {
           summaryBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Summary.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.SummaryOrBuilder>(
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Summary.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.SummaryOrBuilder>(
                   getSummary(),
                   getParentForChildren(),
                   isClean());
@@ -13197,9 +13197,9 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
         return summaryBuilder_;
       }
 
-      private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped untyped_;
+      private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped untyped_;
       private com.google.protobuf.SingleFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.UntypedOrBuilder> untypedBuilder_;
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.UntypedOrBuilder> untypedBuilder_;
       /**
        * optional .io.prometheus.client.Untyped untyped = 5;
        * @return Whether the untyped field is set.
@@ -13211,9 +13211,9 @@ public boolean hasUntyped() {
        * optional .io.prometheus.client.Untyped untyped = 5;
        * @return The untyped.
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped getUntyped() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped getUntyped() {
         if (untypedBuilder_ == null) {
-          return untyped_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.getDefaultInstance() : untyped_;
+          return untyped_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.getDefaultInstance() : untyped_;
         } else {
           return untypedBuilder_.getMessage();
         }
@@ -13221,7 +13221,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * optional .io.prometheus.client.Untyped untyped = 5;
        */
-      public Builder setUntyped(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped value) {
+      public Builder setUntyped(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped value) {
         if (untypedBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -13238,7 +13238,7 @@ public Builder setUntyped(io.prometheus.metrics.expositionformats.generated.com_
        * optional .io.prometheus.client.Untyped untyped = 5;
        */
       public Builder setUntyped(
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.Builder builderForValue) {
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.Builder builderForValue) {
         if (untypedBuilder_ == null) {
           untyped_ = builderForValue.build();
         } else {
@@ -13251,11 +13251,11 @@ public Builder setUntyped(
       /**
        * optional .io.prometheus.client.Untyped untyped = 5;
        */
-      public Builder mergeUntyped(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped value) {
+      public Builder mergeUntyped(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped value) {
         if (untypedBuilder_ == null) {
           if (((bitField0_ & 0x00000010) != 0) &&
             untyped_ != null &&
-            untyped_ != io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.getDefaultInstance()) {
+            untyped_ != io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.getDefaultInstance()) {
             getUntypedBuilder().mergeFrom(value);
           } else {
             untyped_ = value;
@@ -13285,7 +13285,7 @@ public Builder clearUntyped() {
       /**
        * optional .io.prometheus.client.Untyped untyped = 5;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.Builder getUntypedBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.Builder getUntypedBuilder() {
         bitField0_ |= 0x00000010;
         onChanged();
         return internalGetUntypedFieldBuilder().getBuilder();
@@ -13293,23 +13293,23 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * optional .io.prometheus.client.Untyped untyped = 5;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.UntypedOrBuilder getUntypedOrBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.UntypedOrBuilder getUntypedOrBuilder() {
         if (untypedBuilder_ != null) {
           return untypedBuilder_.getMessageOrBuilder();
         } else {
           return untyped_ == null ?
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.getDefaultInstance() : untyped_;
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.getDefaultInstance() : untyped_;
         }
       }
       /**
        * optional .io.prometheus.client.Untyped untyped = 5;
        */
       private com.google.protobuf.SingleFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.UntypedOrBuilder> 
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.UntypedOrBuilder> 
           internalGetUntypedFieldBuilder() {
         if (untypedBuilder_ == null) {
           untypedBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Untyped.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.UntypedOrBuilder>(
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Untyped.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.UntypedOrBuilder>(
                   getUntyped(),
                   getParentForChildren(),
                   isClean());
@@ -13318,9 +13318,9 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
         return untypedBuilder_;
       }
 
-      private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram histogram_;
+      private io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram histogram_;
       private com.google.protobuf.SingleFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.HistogramOrBuilder> histogramBuilder_;
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.HistogramOrBuilder> histogramBuilder_;
       /**
        * optional .io.prometheus.client.Histogram histogram = 7;
        * @return Whether the histogram field is set.
@@ -13332,9 +13332,9 @@ public boolean hasHistogram() {
        * optional .io.prometheus.client.Histogram histogram = 7;
        * @return The histogram.
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram getHistogram() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram getHistogram() {
         if (histogramBuilder_ == null) {
-          return histogram_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.getDefaultInstance() : histogram_;
+          return histogram_ == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.getDefaultInstance() : histogram_;
         } else {
           return histogramBuilder_.getMessage();
         }
@@ -13342,7 +13342,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * optional .io.prometheus.client.Histogram histogram = 7;
        */
-      public Builder setHistogram(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram value) {
+      public Builder setHistogram(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram value) {
         if (histogramBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -13359,7 +13359,7 @@ public Builder setHistogram(io.prometheus.metrics.expositionformats.generated.co
        * optional .io.prometheus.client.Histogram histogram = 7;
        */
       public Builder setHistogram(
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.Builder builderForValue) {
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.Builder builderForValue) {
         if (histogramBuilder_ == null) {
           histogram_ = builderForValue.build();
         } else {
@@ -13372,11 +13372,11 @@ public Builder setHistogram(
       /**
        * optional .io.prometheus.client.Histogram histogram = 7;
        */
-      public Builder mergeHistogram(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram value) {
+      public Builder mergeHistogram(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram value) {
         if (histogramBuilder_ == null) {
           if (((bitField0_ & 0x00000020) != 0) &&
             histogram_ != null &&
-            histogram_ != io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.getDefaultInstance()) {
+            histogram_ != io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.getDefaultInstance()) {
             getHistogramBuilder().mergeFrom(value);
           } else {
             histogram_ = value;
@@ -13406,7 +13406,7 @@ public Builder clearHistogram() {
       /**
        * optional .io.prometheus.client.Histogram histogram = 7;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.Builder getHistogramBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.Builder getHistogramBuilder() {
         bitField0_ |= 0x00000020;
         onChanged();
         return internalGetHistogramFieldBuilder().getBuilder();
@@ -13414,23 +13414,23 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * optional .io.prometheus.client.Histogram histogram = 7;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.HistogramOrBuilder getHistogramOrBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.HistogramOrBuilder getHistogramOrBuilder() {
         if (histogramBuilder_ != null) {
           return histogramBuilder_.getMessageOrBuilder();
         } else {
           return histogram_ == null ?
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.getDefaultInstance() : histogram_;
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.getDefaultInstance() : histogram_;
         }
       }
       /**
        * optional .io.prometheus.client.Histogram histogram = 7;
        */
       private com.google.protobuf.SingleFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.HistogramOrBuilder> 
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.HistogramOrBuilder> 
           internalGetHistogramFieldBuilder() {
         if (histogramBuilder_ == null) {
           histogramBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Histogram.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.HistogramOrBuilder>(
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Histogram.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.HistogramOrBuilder>(
                   getHistogram(),
                   getParentForChildren(),
                   isClean());
@@ -13483,12 +13483,12 @@ public Builder clearTimestampMs() {
     }
 
     // @@protoc_insertion_point(class_scope:io.prometheus.client.Metric)
-    private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric DEFAULT_INSTANCE;
+    private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric DEFAULT_INSTANCE;
     static {
-      DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric();
+      DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric();
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric getDefaultInstance() {
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric getDefaultInstance() {
       return DEFAULT_INSTANCE;
     }
 
@@ -13524,7 +13524,7 @@ public com.google.protobuf.Parser getParserForType() {
     }
 
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric getDefaultInstanceForType() {
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric getDefaultInstanceForType() {
       return DEFAULT_INSTANCE;
     }
 
@@ -13577,17 +13577,17 @@ public interface MetricFamilyOrBuilder extends
      * optional .io.prometheus.client.MetricType type = 3;
      * @return The type.
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricType getType();
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricType getType();
 
     /**
      * repeated .io.prometheus.client.Metric metric = 4;
      */
-    java.util.List 
+    java.util.List 
         getMetricList();
     /**
      * repeated .io.prometheus.client.Metric metric = 4;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric getMetric(int index);
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric getMetric(int index);
     /**
      * repeated .io.prometheus.client.Metric metric = 4;
      */
@@ -13595,12 +13595,12 @@ public interface MetricFamilyOrBuilder extends
     /**
      * repeated .io.prometheus.client.Metric metric = 4;
      */
-    java.util.List 
+    java.util.List 
         getMetricOrBuilderList();
     /**
      * repeated .io.prometheus.client.Metric metric = 4;
      */
-    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricOrBuilder getMetricOrBuilder(
+    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricOrBuilder getMetricOrBuilder(
         int index);
 
     /**
@@ -13633,7 +13633,7 @@ public static final class MetricFamily extends
         com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
         /* major= */ 4,
         /* minor= */ 33,
-        /* patch= */ 2,
+        /* patch= */ 5,
         /* suffix= */ "",
         "MetricFamily");
     }
@@ -13651,15 +13651,15 @@ private MetricFamily() {
 
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_MetricFamily_descriptor;
+      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_MetricFamily_descriptor;
     }
 
     @java.lang.Override
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_MetricFamily_fieldAccessorTable
+      return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_MetricFamily_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily.Builder.class);
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily.Builder.class);
     }
 
     private int bitField0_;
@@ -13774,26 +13774,26 @@ public java.lang.String getHelp() {
      * optional .io.prometheus.client.MetricType type = 3;
      * @return The type.
      */
-    @java.lang.Override public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricType getType() {
-      io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricType result = io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricType.forNumber(type_);
-      return result == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricType.COUNTER : result;
+    @java.lang.Override public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricType getType() {
+      io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricType result = io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricType.forNumber(type_);
+      return result == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricType.COUNTER : result;
     }
 
     public static final int METRIC_FIELD_NUMBER = 4;
     @SuppressWarnings("serial")
-    private java.util.List metric_;
+    private java.util.List metric_;
     /**
      * repeated .io.prometheus.client.Metric metric = 4;
      */
     @java.lang.Override
-    public java.util.List getMetricList() {
+    public java.util.List getMetricList() {
       return metric_;
     }
     /**
      * repeated .io.prometheus.client.Metric metric = 4;
      */
     @java.lang.Override
-    public java.util.List 
+    public java.util.List 
         getMetricOrBuilderList() {
       return metric_;
     }
@@ -13808,14 +13808,14 @@ public int getMetricCount() {
      * repeated .io.prometheus.client.Metric metric = 4;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric getMetric(int index) {
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric getMetric(int index) {
       return metric_.get(index);
     }
     /**
      * repeated .io.prometheus.client.Metric metric = 4;
      */
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricOrBuilder getMetricOrBuilder(
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricOrBuilder getMetricOrBuilder(
         int index) {
       return metric_.get(index);
     }
@@ -13934,10 +13934,10 @@ public boolean equals(final java.lang.Object obj) {
       if (obj == this) {
        return true;
       }
-      if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily)) {
+      if (!(obj instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily)) {
         return super.equals(obj);
       }
-      io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily) obj;
+      io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily other = (io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily) obj;
 
       if (hasName() != other.hasName()) return false;
       if (hasName()) {
@@ -13996,44 +13996,44 @@ public int hashCode() {
       return hash;
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily parseFrom(
         java.nio.ByteBuffer data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily parseFrom(
         java.nio.ByteBuffer data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily parseFrom(byte[] data)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily parseFrom(java.io.InputStream input)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseWithIOException(PARSER, input);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -14041,26 +14041,26 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto
           .parseWithIOException(PARSER, input, extensionRegistry);
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily parseDelimitedFrom(java.io.InputStream input)
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseDelimitedWithIOException(PARSER, input);
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily parseDelimitedFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessage
           .parseWithIOException(PARSER, input);
     }
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily parseFrom(
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -14073,7 +14073,7 @@ public static io.prometheus.metrics.expositionformats.generated.com_google_proto
     public static Builder newBuilder() {
       return DEFAULT_INSTANCE.toBuilder();
     }
-    public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily prototype) {
+    public static Builder newBuilder(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily prototype) {
       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
     }
     @java.lang.Override
@@ -14094,21 +14094,21 @@ protected Builder newBuilderForType(
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder implements
         // @@protoc_insertion_point(builder_implements:io.prometheus.client.MetricFamily)
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamilyOrBuilder {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamilyOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_MetricFamily_descriptor;
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_MetricFamily_descriptor;
       }
 
       @java.lang.Override
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_MetricFamily_fieldAccessorTable
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_MetricFamily_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily.Builder.class);
+                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily.class, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily.Builder.class);
       }
 
-      // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily.newBuilder()
+      // Construct using io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily.newBuilder()
       private Builder() {
 
       }
@@ -14139,17 +14139,17 @@ public Builder clear() {
       @java.lang.Override
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.internal_static_io_prometheus_client_MetricFamily_descriptor;
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.internal_static_io_prometheus_client_MetricFamily_descriptor;
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily getDefaultInstanceForType() {
-        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily.getDefaultInstance();
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily getDefaultInstanceForType() {
+        return io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily.getDefaultInstance();
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily build() {
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily result = buildPartial();
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily build() {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
@@ -14157,15 +14157,15 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       }
 
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily buildPartial() {
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily(this);
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily buildPartial() {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily result = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily(this);
         buildPartialRepeatedFields(result);
         if (bitField0_ != 0) { buildPartial0(result); }
         onBuilt();
         return result;
       }
 
-      private void buildPartialRepeatedFields(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily result) {
+      private void buildPartialRepeatedFields(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily result) {
         if (metricBuilder_ == null) {
           if (((bitField0_ & 0x00000008) != 0)) {
             metric_ = java.util.Collections.unmodifiableList(metric_);
@@ -14177,7 +14177,7 @@ private void buildPartialRepeatedFields(io.prometheus.metrics.expositionformats.
         }
       }
 
-      private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily result) {
+      private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily result) {
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000001) != 0)) {
@@ -14201,16 +14201,16 @@ private void buildPartial0(io.prometheus.metrics.expositionformats.generated.com
 
       @java.lang.Override
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily) {
-          return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily)other);
+        if (other instanceof io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily) {
+          return mergeFrom((io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily other) {
-        if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily.getDefaultInstance()) return this;
+      public Builder mergeFrom(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily other) {
+        if (other == io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily.getDefaultInstance()) return this;
         if (other.hasName()) {
           name_ = other.name_;
           bitField0_ |= 0x00000001;
@@ -14293,8 +14293,8 @@ public Builder mergeFrom(
               } // case 18
               case 24: {
                 int tmpRaw = input.readEnum();
-                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricType tmpValue =
-                    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricType.forNumber(tmpRaw);
+                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricType tmpValue =
+                    io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricType.forNumber(tmpRaw);
                 if (tmpValue == null) {
                   mergeUnknownVarintField(3, tmpRaw);
                 } else {
@@ -14304,9 +14304,9 @@ public Builder mergeFrom(
                 break;
               } // case 24
               case 34: {
-                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric m =
+                io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric m =
                     input.readMessage(
-                        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.parser(),
+                        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.parser(),
                         extensionRegistry);
                 if (metricBuilder_ == null) {
                   ensureMetricIsMutable();
@@ -14511,16 +14511,16 @@ public Builder setHelpBytes(
        * @return The type.
        */
       @java.lang.Override
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricType getType() {
-        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricType result = io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricType.forNumber(type_);
-        return result == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricType.COUNTER : result;
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricType getType() {
+        io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricType result = io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricType.forNumber(type_);
+        return result == null ? io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricType.COUNTER : result;
       }
       /**
        * optional .io.prometheus.client.MetricType type = 3;
        * @param value The type to set.
        * @return This builder for chaining.
        */
-      public Builder setType(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricType value) {
+      public Builder setType(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricType value) {
         if (value == null) { throw new NullPointerException(); }
         bitField0_ |= 0x00000004;
         type_ = value.getNumber();
@@ -14538,22 +14538,22 @@ public Builder clearType() {
         return this;
       }
 
-      private java.util.List metric_ =
+      private java.util.List metric_ =
         java.util.Collections.emptyList();
       private void ensureMetricIsMutable() {
         if (!((bitField0_ & 0x00000008) != 0)) {
-          metric_ = new java.util.ArrayList(metric_);
+          metric_ = new java.util.ArrayList(metric_);
           bitField0_ |= 0x00000008;
          }
       }
 
       private com.google.protobuf.RepeatedFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricOrBuilder> metricBuilder_;
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricOrBuilder> metricBuilder_;
 
       /**
        * repeated .io.prometheus.client.Metric metric = 4;
        */
-      public java.util.List getMetricList() {
+      public java.util.List getMetricList() {
         if (metricBuilder_ == null) {
           return java.util.Collections.unmodifiableList(metric_);
         } else {
@@ -14573,7 +14573,7 @@ public int getMetricCount() {
       /**
        * repeated .io.prometheus.client.Metric metric = 4;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric getMetric(int index) {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric getMetric(int index) {
         if (metricBuilder_ == null) {
           return metric_.get(index);
         } else {
@@ -14584,7 +14584,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
        * repeated .io.prometheus.client.Metric metric = 4;
        */
       public Builder setMetric(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric value) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric value) {
         if (metricBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -14601,7 +14601,7 @@ public Builder setMetric(
        * repeated .io.prometheus.client.Metric metric = 4;
        */
       public Builder setMetric(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.Builder builderForValue) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.Builder builderForValue) {
         if (metricBuilder_ == null) {
           ensureMetricIsMutable();
           metric_.set(index, builderForValue.build());
@@ -14614,7 +14614,7 @@ public Builder setMetric(
       /**
        * repeated .io.prometheus.client.Metric metric = 4;
        */
-      public Builder addMetric(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric value) {
+      public Builder addMetric(io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric value) {
         if (metricBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -14631,7 +14631,7 @@ public Builder addMetric(io.prometheus.metrics.expositionformats.generated.com_g
        * repeated .io.prometheus.client.Metric metric = 4;
        */
       public Builder addMetric(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric value) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric value) {
         if (metricBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
@@ -14648,7 +14648,7 @@ public Builder addMetric(
        * repeated .io.prometheus.client.Metric metric = 4;
        */
       public Builder addMetric(
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.Builder builderForValue) {
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.Builder builderForValue) {
         if (metricBuilder_ == null) {
           ensureMetricIsMutable();
           metric_.add(builderForValue.build());
@@ -14662,7 +14662,7 @@ public Builder addMetric(
        * repeated .io.prometheus.client.Metric metric = 4;
        */
       public Builder addMetric(
-          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.Builder builderForValue) {
+          int index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.Builder builderForValue) {
         if (metricBuilder_ == null) {
           ensureMetricIsMutable();
           metric_.add(index, builderForValue.build());
@@ -14676,7 +14676,7 @@ public Builder addMetric(
        * repeated .io.prometheus.client.Metric metric = 4;
        */
       public Builder addAllMetric(
-          java.lang.Iterable values) {
+          java.lang.Iterable values) {
         if (metricBuilder_ == null) {
           ensureMetricIsMutable();
           com.google.protobuf.AbstractMessageLite.Builder.addAll(
@@ -14716,14 +14716,14 @@ public Builder removeMetric(int index) {
       /**
        * repeated .io.prometheus.client.Metric metric = 4;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.Builder getMetricBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.Builder getMetricBuilder(
           int index) {
         return internalGetMetricFieldBuilder().getBuilder(index);
       }
       /**
        * repeated .io.prometheus.client.Metric metric = 4;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricOrBuilder getMetricOrBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricOrBuilder getMetricOrBuilder(
           int index) {
         if (metricBuilder_ == null) {
           return metric_.get(index);  } else {
@@ -14733,7 +14733,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * repeated .io.prometheus.client.Metric metric = 4;
        */
-      public java.util.List 
+      public java.util.List 
            getMetricOrBuilderList() {
         if (metricBuilder_ != null) {
           return metricBuilder_.getMessageOrBuilderList();
@@ -14744,31 +14744,31 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       /**
        * repeated .io.prometheus.client.Metric metric = 4;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.Builder addMetricBuilder() {
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.Builder addMetricBuilder() {
         return internalGetMetricFieldBuilder().addBuilder(
-            io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.getDefaultInstance());
+            io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.getDefaultInstance());
       }
       /**
        * repeated .io.prometheus.client.Metric metric = 4;
        */
-      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.Builder addMetricBuilder(
+      public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.Builder addMetricBuilder(
           int index) {
         return internalGetMetricFieldBuilder().addBuilder(
-            index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.getDefaultInstance());
+            index, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.getDefaultInstance());
       }
       /**
        * repeated .io.prometheus.client.Metric metric = 4;
        */
-      public java.util.List 
+      public java.util.List 
            getMetricBuilderList() {
         return internalGetMetricFieldBuilder().getBuilderList();
       }
       private com.google.protobuf.RepeatedFieldBuilder<
-          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricOrBuilder> 
+          io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricOrBuilder> 
           internalGetMetricFieldBuilder() {
         if (metricBuilder_ == null) {
           metricBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
-              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.Metric.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricOrBuilder>(
+              io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.Metric.Builder, io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricOrBuilder>(
                   metric_,
                   ((bitField0_ & 0x00000008) != 0),
                   getParentForChildren(),
@@ -14862,12 +14862,12 @@ public Builder setUnitBytes(
     }
 
     // @@protoc_insertion_point(class_scope:io.prometheus.client.MetricFamily)
-    private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily DEFAULT_INSTANCE;
+    private static final io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily DEFAULT_INSTANCE;
     static {
-      DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily();
+      DEFAULT_INSTANCE = new io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily();
     }
 
-    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily getDefaultInstance() {
+    public static io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily getDefaultInstance() {
       return DEFAULT_INSTANCE;
     }
 
@@ -14903,7 +14903,7 @@ public com.google.protobuf.Parser getParserForType() {
     }
 
     @java.lang.Override
-    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics.MetricFamily getDefaultInstanceForType() {
+    public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics.MetricFamily getDefaultInstanceForType() {
       return DEFAULT_INSTANCE;
     }
 
@@ -15028,7 +15028,7 @@ public io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_3
       "\002\022\013\n\007UNTYPED\020\003\022\r\n\tHISTOGRAM\020\004\022\023\n\017GAUGE_H" +
       "ISTOGRAM\020\005B\212\001\nLio.prometheus.metrics.exp" +
       "ositionformats.generated.com_google_prot" +
-      "obuf_4_33_2Z:github.com/prometheus/clien" +
+      "obuf_4_33_5Z:github.com/prometheus/clien" +
       "t_model/go;io_prometheus_client"
     };
     descriptor = com.google.protobuf.Descriptors.FileDescriptor
diff --git a/prometheus-metrics-exposition-formats/src/main/java/io/prometheus/metrics/expositionformats/generated/Metrics.java b/prometheus-metrics-exposition-formats/src/main/java/io/prometheus/metrics/expositionformats/generated/Metrics.java
new file mode 100644
index 000000000..605aa4cd7
--- /dev/null
+++ b/prometheus-metrics-exposition-formats/src/main/java/io/prometheus/metrics/expositionformats/generated/Metrics.java
@@ -0,0 +1,6 @@
+package io.prometheus.metrics.expositionformats.generated;
+
+public final class Metrics
+    extends io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_5.Metrics {
+  private Metrics() {}
+}
diff --git a/prometheus-metrics-exposition-formats/src/main/java/io/prometheus/metrics/expositionformats/internal/PrometheusProtobufWriterImpl.java b/prometheus-metrics-exposition-formats/src/main/java/io/prometheus/metrics/expositionformats/internal/PrometheusProtobufWriterImpl.java
index 13f7f34b9..d714fb5cd 100644
--- a/prometheus-metrics-exposition-formats/src/main/java/io/prometheus/metrics/expositionformats/internal/PrometheusProtobufWriterImpl.java
+++ b/prometheus-metrics-exposition-formats/src/main/java/io/prometheus/metrics/expositionformats/internal/PrometheusProtobufWriterImpl.java
@@ -6,7 +6,8 @@
 import com.google.protobuf.TextFormat;
 import io.prometheus.metrics.config.EscapingScheme;
 import io.prometheus.metrics.expositionformats.ExpositionFormatWriter;
-import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics;
+import io.prometheus.metrics.expositionformats.TextFormatUtil;
+import io.prometheus.metrics.expositionformats.generated.Metrics;
 import io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets;
 import io.prometheus.metrics.model.snapshots.CounterSnapshot;
 import io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot;
@@ -29,6 +30,7 @@
 import java.io.OutputStream;
 import javax.annotation.Nullable;
 
+@SuppressWarnings("NonCanonicalType")
 public class PrometheusProtobufWriterImpl implements ExpositionFormatWriter {
 
   @Override
@@ -43,8 +45,9 @@ public String getContentType() {
 
   @Override
   public String toDebugString(MetricSnapshots metricSnapshots, EscapingScheme escapingScheme) {
+    MetricSnapshots merged = TextFormatUtil.mergeDuplicates(metricSnapshots);
     StringBuilder stringBuilder = new StringBuilder();
-    for (MetricSnapshot s : metricSnapshots) {
+    for (MetricSnapshot s : merged) {
       MetricSnapshot snapshot = SnapshotEscaper.escapeMetricSnapshot(s, escapingScheme);
       if (!snapshot.getDataPoints().isEmpty()) {
         stringBuilder.append(TextFormat.printer().printToString(convert(snapshot, escapingScheme)));
@@ -57,7 +60,8 @@ public String toDebugString(MetricSnapshots metricSnapshots, EscapingScheme esca
   public void write(
       OutputStream out, MetricSnapshots metricSnapshots, EscapingScheme escapingScheme)
       throws IOException {
-    for (MetricSnapshot s : metricSnapshots) {
+    MetricSnapshots merged = TextFormatUtil.mergeDuplicates(metricSnapshots);
+    for (MetricSnapshot s : merged) {
       MetricSnapshot snapshot = SnapshotEscaper.escapeMetricSnapshot(s, escapingScheme);
       if (!snapshot.getDataPoints().isEmpty()) {
         convert(snapshot, escapingScheme).writeDelimitedTo(out);
diff --git a/prometheus-metrics-exposition-formats/src/test/java/io/prometheus/metrics/expositionformats/DuplicateNamesProtobufTest.java b/prometheus-metrics-exposition-formats/src/test/java/io/prometheus/metrics/expositionformats/DuplicateNamesProtobufTest.java
new file mode 100644
index 000000000..c5fc7bf34
--- /dev/null
+++ b/prometheus-metrics-exposition-formats/src/test/java/io/prometheus/metrics/expositionformats/DuplicateNamesProtobufTest.java
@@ -0,0 +1,301 @@
+package io.prometheus.metrics.expositionformats;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.prometheus.metrics.config.EscapingScheme;
+import io.prometheus.metrics.expositionformats.generated.Metrics;
+import io.prometheus.metrics.expositionformats.internal.PrometheusProtobufWriterImpl;
+import io.prometheus.metrics.model.registry.Collector;
+import io.prometheus.metrics.model.registry.PrometheusRegistry;
+import io.prometheus.metrics.model.snapshots.CounterSnapshot;
+import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
+import io.prometheus.metrics.model.snapshots.Labels;
+import io.prometheus.metrics.model.snapshots.MetricSnapshot;
+import io.prometheus.metrics.model.snapshots.MetricSnapshots;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+@SuppressWarnings("NonCanonicalType")
+class DuplicateNamesProtobufTest {
+
+  private static PrometheusRegistry getPrometheusRegistry() {
+    PrometheusRegistry registry = new PrometheusRegistry();
+
+    registry.register(
+        new Collector() {
+          @Override
+          public MetricSnapshot collect() {
+            return CounterSnapshot.builder()
+                .name("api_responses")
+                .help("API responses")
+                .dataPoint(
+                    CounterSnapshot.CounterDataPointSnapshot.builder()
+                        .labels(Labels.of("uri", "/hello", "outcome", "SUCCESS"))
+                        .value(100)
+                        .build())
+                .build();
+          }
+
+          @Override
+          public String getPrometheusName() {
+            return "api_responses";
+          }
+        });
+
+    registry.register(
+        new Collector() {
+          @Override
+          public MetricSnapshot collect() {
+            return CounterSnapshot.builder()
+                .name("api_responses")
+                .help("API responses")
+                .dataPoint(
+                    CounterSnapshot.CounterDataPointSnapshot.builder()
+                        .labels(
+                            Labels.of("uri", "/hello", "outcome", "FAILURE", "error", "TIMEOUT"))
+                        .value(10)
+                        .build())
+                .build();
+          }
+
+          @Override
+          public String getPrometheusName() {
+            return "api_responses";
+          }
+        });
+    return registry;
+  }
+
+  @Test
+  void testDuplicateNames_differentLabels_producesSingleMetricFamily() throws IOException {
+    PrometheusRegistry registry = getPrometheusRegistry();
+
+    MetricSnapshots snapshots = registry.scrape();
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    PrometheusProtobufWriterImpl writer = new PrometheusProtobufWriterImpl();
+    writer.write(out, snapshots, EscapingScheme.UNDERSCORE_ESCAPING);
+
+    List metricFamilies = parseProtobufOutput(out);
+
+    assertThat(metricFamilies).hasSize(1);
+    Metrics.MetricFamily family = metricFamilies.get(0);
+    assertThat(family.getName()).isEqualTo("api_responses_total");
+    assertThat(family.getHelp()).isEqualTo("API responses");
+    assertThat(family.getType()).isEqualTo(Metrics.MetricType.COUNTER);
+    assertThat(family.getMetricCount()).isEqualTo(2);
+
+    Metrics.Metric successMetric =
+        family.getMetricList().stream()
+            .filter(
+                m ->
+                    m.getLabelList().stream()
+                        .anyMatch(
+                            l -> l.getName().equals("outcome") && l.getValue().equals("SUCCESS")))
+            .findFirst()
+            .orElseThrow(() -> new AssertionError("SUCCESS metric not found"));
+    assertThat(successMetric.getCounter().getValue()).isEqualTo(100.0);
+
+    Metrics.Metric failureMetric =
+        family.getMetricList().stream()
+            .filter(
+                m ->
+                    m.getLabelList().stream()
+                            .anyMatch(
+                                l ->
+                                    l.getName().equals("outcome") && l.getValue().equals("FAILURE"))
+                        && m.getLabelList().stream()
+                            .anyMatch(
+                                l -> l.getName().equals("error") && l.getValue().equals("TIMEOUT")))
+            .findFirst()
+            .orElseThrow(() -> new AssertionError("FAILURE metric not found"));
+    assertThat(failureMetric.getCounter().getValue()).isEqualTo(10.0);
+  }
+
+  @Test
+  void testDuplicateNames_multipleDataPoints_producesSingleMetricFamily() throws IOException {
+    PrometheusRegistry registry = new PrometheusRegistry();
+
+    registry.register(
+        new Collector() {
+          @Override
+          public MetricSnapshot collect() {
+            return CounterSnapshot.builder()
+                .name("api_responses")
+                .help("API responses")
+                .dataPoint(
+                    CounterSnapshot.CounterDataPointSnapshot.builder()
+                        .labels(Labels.of("uri", "/hello", "outcome", "SUCCESS"))
+                        .value(100)
+                        .build())
+                .dataPoint(
+                    CounterSnapshot.CounterDataPointSnapshot.builder()
+                        .labels(Labels.of("uri", "/world", "outcome", "SUCCESS"))
+                        .value(200)
+                        .build())
+                .build();
+          }
+
+          @Override
+          public String getPrometheusName() {
+            return "api_responses";
+          }
+        });
+
+    registry.register(
+        new Collector() {
+          @Override
+          public MetricSnapshot collect() {
+            return CounterSnapshot.builder()
+                .name("api_responses")
+                .help("API responses")
+                .dataPoint(
+                    CounterSnapshot.CounterDataPointSnapshot.builder()
+                        .labels(
+                            Labels.of("uri", "/hello", "outcome", "FAILURE", "error", "TIMEOUT"))
+                        .value(10)
+                        .build())
+                .dataPoint(
+                    CounterSnapshot.CounterDataPointSnapshot.builder()
+                        .labels(
+                            Labels.of("uri", "/world", "outcome", "FAILURE", "error", "NOT_FOUND"))
+                        .value(5)
+                        .build())
+                .build();
+          }
+
+          @Override
+          public String getPrometheusName() {
+            return "api_responses";
+          }
+        });
+
+    MetricSnapshots snapshots = registry.scrape();
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    PrometheusProtobufWriterImpl writer = new PrometheusProtobufWriterImpl();
+    writer.write(out, snapshots, EscapingScheme.UNDERSCORE_ESCAPING);
+
+    List metricFamilies = parseProtobufOutput(out);
+
+    assertThat(metricFamilies).hasSize(1);
+    Metrics.MetricFamily family = metricFamilies.get(0);
+    assertThat(family.getName()).isEqualTo("api_responses_total");
+    assertThat(family.getMetricCount()).isEqualTo(4);
+
+    long successCount =
+        family.getMetricList().stream()
+            .filter(
+                m ->
+                    m.getLabelList().stream()
+                        .anyMatch(
+                            l -> l.getName().equals("outcome") && l.getValue().equals("SUCCESS")))
+            .count();
+
+    long failureCount =
+        family.getMetricList().stream()
+            .filter(
+                m ->
+                    m.getLabelList().stream()
+                        .anyMatch(
+                            l -> l.getName().equals("outcome") && l.getValue().equals("FAILURE")))
+            .count();
+
+    assertThat(successCount).isEqualTo(2);
+    assertThat(failureCount).isEqualTo(2);
+  }
+
+  @Test
+  void testDifferentMetrics_producesSeparateMetricFamilies() throws IOException {
+    MetricSnapshots snapshots = getMetricSnapshots();
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    PrometheusProtobufWriterImpl writer = new PrometheusProtobufWriterImpl();
+    writer.write(out, snapshots, EscapingScheme.UNDERSCORE_ESCAPING);
+
+    List metricFamilies = parseProtobufOutput(out);
+
+    assertThat(metricFamilies).hasSize(2);
+
+    Metrics.MetricFamily counterFamily = null;
+    Metrics.MetricFamily gaugeFamily = null;
+    for (Metrics.MetricFamily family : metricFamilies) {
+      if (family.getName().equals("http_requests_total")) {
+        counterFamily = family;
+      } else if (family.getName().equals("active_sessions")) {
+        gaugeFamily = family;
+      }
+    }
+
+    assertThat(counterFamily).isNotNull();
+    assertThat(counterFamily.getType()).isEqualTo(Metrics.MetricType.COUNTER);
+    assertThat(counterFamily.getMetricCount()).isEqualTo(1);
+    assertThat(counterFamily.getMetric(0).getCounter().getValue()).isEqualTo(100.0);
+
+    assertThat(gaugeFamily).isNotNull();
+    assertThat(gaugeFamily.getType()).isEqualTo(Metrics.MetricType.GAUGE);
+    assertThat(gaugeFamily.getMetricCount()).isEqualTo(1);
+    assertThat(gaugeFamily.getMetric(0).getGauge().getValue()).isEqualTo(50.0);
+  }
+
+  private static MetricSnapshots getMetricSnapshots() {
+    PrometheusRegistry registry = new PrometheusRegistry();
+
+    registry.register(
+        new Collector() {
+          @Override
+          public MetricSnapshot collect() {
+            return CounterSnapshot.builder()
+                .name("http_requests")
+                .help("HTTP Request counter")
+                .dataPoint(
+                    CounterSnapshot.CounterDataPointSnapshot.builder()
+                        .labels(Labels.of("method", "GET"))
+                        .value(100)
+                        .build())
+                .build();
+          }
+
+          @Override
+          public String getPrometheusName() {
+            return "http_requests";
+          }
+        });
+
+    registry.register(
+        new Collector() {
+          @Override
+          public MetricSnapshot collect() {
+            return GaugeSnapshot.builder()
+                .name("active_sessions")
+                .help("Active sessions gauge")
+                .dataPoint(
+                    GaugeSnapshot.GaugeDataPointSnapshot.builder()
+                        .labels(Labels.of("region", "us-east-1"))
+                        .value(50)
+                        .build())
+                .build();
+          }
+
+          @Override
+          public String getPrometheusName() {
+            return "active_sessions";
+          }
+        });
+
+    return registry.scrape();
+  }
+
+  private static List parseProtobufOutput(ByteArrayOutputStream out)
+      throws IOException {
+    List metricFamilies = new ArrayList<>();
+    try (ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray())) {
+      Metrics.MetricFamily family;
+      while ((family = Metrics.MetricFamily.parseDelimitedFrom(in)) != null) {
+        metricFamilies.add(family);
+      }
+    }
+    return metricFamilies;
+  }
+}
diff --git a/prometheus-metrics-exposition-formats/src/test/java/io/prometheus/metrics/expositionformats/ProtobufExpositionFormatsTest.java b/prometheus-metrics-exposition-formats/src/test/java/io/prometheus/metrics/expositionformats/ProtobufExpositionFormatsTest.java
index d4ccfcf35..5f871c585 100644
--- a/prometheus-metrics-exposition-formats/src/test/java/io/prometheus/metrics/expositionformats/ProtobufExpositionFormatsTest.java
+++ b/prometheus-metrics-exposition-formats/src/test/java/io/prometheus/metrics/expositionformats/ProtobufExpositionFormatsTest.java
@@ -3,11 +3,12 @@
 import static org.assertj.core.api.Assertions.assertThat;
 
 import io.prometheus.metrics.config.EscapingScheme;
-import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_4_33_2.Metrics;
+import io.prometheus.metrics.expositionformats.generated.Metrics;
 import io.prometheus.metrics.expositionformats.internal.PrometheusProtobufWriterImpl;
 import io.prometheus.metrics.expositionformats.internal.ProtobufUtil;
 import io.prometheus.metrics.model.snapshots.MetricSnapshot;
 
+@SuppressWarnings("NonCanonicalType")
 class ProtobufExpositionFormatsTest extends ExpositionFormatsTest {
 
   @Override
diff --git a/prometheus-metrics-exposition-textformats/pom.xml b/prometheus-metrics-exposition-textformats/pom.xml
index 1aeba0707..16e7b73b6 100644
--- a/prometheus-metrics-exposition-textformats/pom.xml
+++ b/prometheus-metrics-exposition-textformats/pom.xml
@@ -6,7 +6,7 @@
   
     io.prometheus
     client_java
-    1.5.0-SNAPSHOT
+    1.6.0-SNAPSHOT
   
 
   prometheus-metrics-exposition-textformats
@@ -19,7 +19,7 @@
 
   
     io.prometheus.writer.text
-    0.50
+    0.60
   
 
   
diff --git a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/ExpositionFormatWriter.java b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/ExpositionFormatWriter.java
index 67f1ee41e..03ac229ca 100644
--- a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/ExpositionFormatWriter.java
+++ b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/ExpositionFormatWriter.java
@@ -20,6 +20,8 @@ default void write(OutputStream out, MetricSnapshots metricSnapshots) throws IOE
   }
 
   /** Converts the metric snapshots to a debug string using the specified escaping scheme. */
+  // toString with Charset is only available in Java 10+, but we want to support Java 8
+  @SuppressWarnings("JdkObsolete")
   default String toDebugString(MetricSnapshots metricSnapshots, EscapingScheme escapingScheme) {
     ByteArrayOutputStream out = new ByteArrayOutputStream();
     try {
diff --git a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/OpenMetricsTextFormatWriter.java b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/OpenMetricsTextFormatWriter.java
index 1ba1c627d..293fbfb8c 100644
--- a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/OpenMetricsTextFormatWriter.java
+++ b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/OpenMetricsTextFormatWriter.java
@@ -113,7 +113,8 @@ public String getContentType() {
   public void write(OutputStream out, MetricSnapshots metricSnapshots, EscapingScheme scheme)
       throws IOException {
     Writer writer = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8));
-    for (MetricSnapshot s : metricSnapshots) {
+    MetricSnapshots merged = TextFormatUtil.mergeDuplicates(metricSnapshots);
+    for (MetricSnapshot s : merged) {
       MetricSnapshot snapshot = SnapshotEscaper.escapeMetricSnapshot(s, scheme);
       if (!snapshot.getDataPoints().isEmpty()) {
         if (snapshot instanceof CounterSnapshot) {
diff --git a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/PrometheusTextFormatWriter.java b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/PrometheusTextFormatWriter.java
index 73d33504e..cc9f067ba 100644
--- a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/PrometheusTextFormatWriter.java
+++ b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/PrometheusTextFormatWriter.java
@@ -115,7 +115,8 @@ public void write(OutputStream out, MetricSnapshots metricSnapshots, EscapingSch
     // "unknown", "gauge", "counter", "stateset", "info", "histogram", "gaugehistogram", and
     // "summary".
     Writer writer = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8));
-    for (MetricSnapshot s : metricSnapshots) {
+    MetricSnapshots merged = TextFormatUtil.mergeDuplicates(metricSnapshots);
+    for (MetricSnapshot s : merged) {
       MetricSnapshot snapshot = escapeMetricSnapshot(s, scheme);
       if (!snapshot.getDataPoints().isEmpty()) {
         if (snapshot instanceof CounterSnapshot) {
@@ -136,7 +137,7 @@ public void write(OutputStream out, MetricSnapshots metricSnapshots, EscapingSch
       }
     }
     if (writeCreatedTimestamps) {
-      for (MetricSnapshot s : metricSnapshots) {
+      for (MetricSnapshot s : merged) {
         MetricSnapshot snapshot = escapeMetricSnapshot(s, scheme);
         if (!snapshot.getDataPoints().isEmpty()) {
           if (snapshot instanceof CounterSnapshot) {
diff --git a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/TextFormatUtil.java b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/TextFormatUtil.java
index fb9d3f313..5f5f05e8b 100644
--- a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/TextFormatUtil.java
+++ b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/TextFormatUtil.java
@@ -1,14 +1,70 @@
 package io.prometheus.metrics.expositionformats;
 
 import io.prometheus.metrics.config.EscapingScheme;
+import io.prometheus.metrics.model.snapshots.CounterSnapshot;
+import io.prometheus.metrics.model.snapshots.DataPointSnapshot;
+import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
+import io.prometheus.metrics.model.snapshots.HistogramSnapshot;
+import io.prometheus.metrics.model.snapshots.InfoSnapshot;
 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.PrometheusNaming;
 import io.prometheus.metrics.model.snapshots.SnapshotEscaper;
+import io.prometheus.metrics.model.snapshots.StateSetSnapshot;
+import io.prometheus.metrics.model.snapshots.SummarySnapshot;
+import io.prometheus.metrics.model.snapshots.UnknownSnapshot;
 import java.io.IOException;
 import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import javax.annotation.Nullable;
 
+/**
+ * Utility methods for writing Prometheus text exposition formats.
+ *
+ * 

This class provides low-level formatting utilities used by both Prometheus text format and + * OpenMetrics format writers. It handles escaping, label formatting, timestamp conversion, and + * merging of duplicate metric names. + */ public class TextFormatUtil { + /** + * Merges snapshots with duplicate Prometheus names by combining their data points. This ensures + * only one HELP/TYPE declaration per metric family. + */ + public static MetricSnapshots mergeDuplicates(MetricSnapshots metricSnapshots) { + if (metricSnapshots.size() <= 1) { + return metricSnapshots; + } + + Map> grouped = new LinkedHashMap<>(); + + for (MetricSnapshot snapshot : metricSnapshots) { + String prometheusName = snapshot.getMetadata().getPrometheusName(); + List list = grouped.get(prometheusName); + if (list == null) { + list = new ArrayList<>(); + grouped.put(prometheusName, list); + } + list.add(snapshot); + } + + MetricSnapshots.Builder builder = MetricSnapshots.builder(); + for (List group : grouped.values()) { + if (group.size() == 1) { + builder.metricSnapshot(group.get(0)); + } else { + MetricSnapshot merged = mergeSnapshots(group); + builder.metricSnapshot(merged); + } + } + + return builder.build(); + } static void writeLong(Writer writer, long value) throws IOException { writer.append(Long.toString(value)); @@ -155,4 +211,81 @@ static void writeName(Writer writer, String name, NameType nameType) throws IOEx writeEscapedString(writer, name); writer.write('"'); } + + /** + * Merges multiple snapshots of the same type into a single snapshot with combined data points. + */ + @SuppressWarnings("unchecked") + private static MetricSnapshot mergeSnapshots(List snapshots) { + MetricSnapshot first = snapshots.get(0); + + int totalDataPoints = 0; + for (MetricSnapshot snapshot : snapshots) { + if (snapshot.getClass() != first.getClass()) { + throw new IllegalArgumentException( + "Cannot merge snapshots of different types: " + + first.getClass().getName() + + " and " + + snapshot.getClass().getName()); + } + if (first instanceof HistogramSnapshot) { + HistogramSnapshot histogramFirst = (HistogramSnapshot) first; + HistogramSnapshot histogramSnapshot = (HistogramSnapshot) snapshot; + if (histogramFirst.isGaugeHistogram() != histogramSnapshot.isGaugeHistogram()) { + throw new IllegalArgumentException( + "Cannot merge histograms: gauge histogram and classic histogram"); + } + } + // Validate metadata consistency so we don't silently pick one help/unit when they differ. + if (!Objects.equals( + first.getMetadata().getPrometheusName(), snapshot.getMetadata().getPrometheusName())) { + throw new IllegalArgumentException("Cannot merge snapshots: inconsistent metric name"); + } + if (!Objects.equals(first.getMetadata().getUnit(), snapshot.getMetadata().getUnit())) { + throw new IllegalArgumentException( + "Cannot merge snapshots: conflicting unit for metric " + + first.getMetadata().getPrometheusName()); + } + totalDataPoints += snapshot.getDataPoints().size(); + } + + List allDataPoints = new ArrayList<>(totalDataPoints); + for (MetricSnapshot snapshot : snapshots) { + allDataPoints.addAll(snapshot.getDataPoints()); + } + + if (first instanceof CounterSnapshot) { + return new CounterSnapshot( + first.getMetadata(), + (Collection) (Object) allDataPoints); + } else if (first instanceof GaugeSnapshot) { + return new GaugeSnapshot( + first.getMetadata(), + (Collection) (Object) allDataPoints); + } else if (first instanceof HistogramSnapshot) { + HistogramSnapshot histFirst = (HistogramSnapshot) first; + return new HistogramSnapshot( + histFirst.isGaugeHistogram(), + first.getMetadata(), + (Collection) (Object) allDataPoints); + } else if (first instanceof SummarySnapshot) { + return new SummarySnapshot( + first.getMetadata(), + (Collection) (Object) allDataPoints); + } else if (first instanceof InfoSnapshot) { + return new InfoSnapshot( + first.getMetadata(), + (Collection) (Object) allDataPoints); + } else if (first instanceof StateSetSnapshot) { + return new StateSetSnapshot( + first.getMetadata(), + (Collection) (Object) allDataPoints); + } else if (first instanceof UnknownSnapshot) { + return new UnknownSnapshot( + first.getMetadata(), + (Collection) (Object) allDataPoints); + } else { + throw new IllegalArgumentException("Unknown snapshot type: " + first.getClass().getName()); + } + } } diff --git a/prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/DuplicateNamesExpositionTest.java b/prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/DuplicateNamesExpositionTest.java new file mode 100644 index 000000000..bdd21440f --- /dev/null +++ b/prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/DuplicateNamesExpositionTest.java @@ -0,0 +1,258 @@ +package io.prometheus.metrics.expositionformats; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.assertj.core.api.Assertions.assertThat; + +import io.prometheus.metrics.model.registry.Collector; +import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.CounterSnapshot; +import io.prometheus.metrics.model.snapshots.Labels; +import io.prometheus.metrics.model.snapshots.MetricSnapshot; +import io.prometheus.metrics.model.snapshots.MetricSnapshots; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import org.junit.jupiter.api.Test; + +class DuplicateNamesExpositionTest { + + private static PrometheusRegistry getPrometheusRegistry() { + PrometheusRegistry registry = new PrometheusRegistry(); + + registry.register( + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder() + .name("api_responses") + .help("API responses") + .dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(Labels.of("uri", "/hello", "outcome", "SUCCESS")) + .value(100) + .build()) + .build(); + } + + @Override + public String getPrometheusName() { + return "api_responses"; + } + }); + + registry.register( + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder() + .name("api_responses") + .help("API responses") + .dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels( + Labels.of("uri", "/hello", "outcome", "FAILURE", "error", "TIMEOUT")) + .value(10) + .build()) + .build(); + } + + @Override + public String getPrometheusName() { + return "api_responses"; + } + }); + return registry; + } + + @Test + void testDuplicateNames_differentLabels_producesValidOutput() throws IOException { + PrometheusRegistry registry = getPrometheusRegistry(); + + MetricSnapshots snapshots = registry.scrape(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + PrometheusTextFormatWriter writer = PrometheusTextFormatWriter.create(); + writer.write(out, snapshots); + String output = out.toString(UTF_8); + + String expected = + """ + # HELP api_responses_total API responses + # TYPE api_responses_total counter + api_responses_total{error="TIMEOUT",outcome="FAILURE",uri="/hello"} 10.0 + api_responses_total{outcome="SUCCESS",uri="/hello"} 100.0 + """; + + assertThat(output).isEqualTo(expected); + } + + @Test + void testDuplicateNames_multipleDataPoints_producesValidOutput() throws IOException { + PrometheusRegistry registry = new PrometheusRegistry(); + + registry.register( + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder() + .name("api_responses") + .help("API responses") + .dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(Labels.of("uri", "/hello", "outcome", "SUCCESS")) + .value(100) + .build()) + .dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(Labels.of("uri", "/world", "outcome", "SUCCESS")) + .value(200) + .build()) + .build(); + } + + @Override + public String getPrometheusName() { + return "api_responses"; + } + }); + + registry.register( + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder() + .name("api_responses") + .help("API responses") + .dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels( + Labels.of("uri", "/hello", "outcome", "FAILURE", "error", "TIMEOUT")) + .value(10) + .build()) + .dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels( + Labels.of("uri", "/world", "outcome", "FAILURE", "error", "NOT_FOUND")) + .value(5) + .build()) + .build(); + } + + @Override + public String getPrometheusName() { + return "api_responses"; + } + }); + + MetricSnapshots snapshots = registry.scrape(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + PrometheusTextFormatWriter writer = PrometheusTextFormatWriter.create(); + writer.write(out, snapshots); + String output = out.toString(UTF_8); + + String expected = + """ + # HELP api_responses_total API responses + # TYPE api_responses_total counter + api_responses_total{error="NOT_FOUND",outcome="FAILURE",uri="/world"} 5.0 + api_responses_total{error="TIMEOUT",outcome="FAILURE",uri="/hello"} 10.0 + api_responses_total{outcome="SUCCESS",uri="/hello"} 100.0 + api_responses_total{outcome="SUCCESS",uri="/world"} 200.0 + """; + assertThat(output).isEqualTo(expected); + } + + @Test + void testOpenMetricsFormat_withDuplicateNames() throws IOException { + PrometheusRegistry registry = getPrometheusRegistry(); + + MetricSnapshots snapshots = registry.scrape(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter(false, false); + writer.write(out, snapshots); + String output = out.toString(UTF_8); + + String expected = + """ + # TYPE api_responses counter + # HELP api_responses API responses + api_responses_total{error="TIMEOUT",outcome="FAILURE",uri="/hello"} 10.0 + api_responses_total{outcome="SUCCESS",uri="/hello"} 100.0 + # EOF + """; + assertThat(output).isEqualTo(expected); + } + + @Test + void testDuplicateNames_withCreatedTimestamps_emitsSingleHelpTypeAndNoDuplicateCreatedSeries() + throws IOException { + long createdTs = 1672850385800L; + PrometheusRegistry registry = new PrometheusRegistry(); + + registry.register( + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder() + .name("api_responses") + .help("API responses") + .dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(Labels.of("uri", "/hello", "outcome", "SUCCESS")) + .value(100) + .createdTimestampMillis(createdTs) + .build()) + .build(); + } + + @Override + public String getPrometheusName() { + return "api_responses"; + } + }); + + registry.register( + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder() + .name("api_responses") + .help("API responses") + .dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels( + Labels.of("uri", "/hello", "outcome", "FAILURE", "error", "TIMEOUT")) + .value(10) + .createdTimestampMillis(createdTs + 1000) + .build()) + .build(); + } + + @Override + public String getPrometheusName() { + return "api_responses"; + } + }); + + MetricSnapshots snapshots = registry.scrape(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + PrometheusTextFormatWriter writer = + PrometheusTextFormatWriter.builder().setIncludeCreatedTimestamps(true).build(); + writer.write(out, snapshots); + String output = out.toString(UTF_8); + + // Merged snapshots: one metric family with two data points. Created-timestamp section uses + // merged snapshots too, so single HELP/TYPE for _created and one _created line per label set. + String expected = + """ + # HELP api_responses_total API responses + # TYPE api_responses_total counter + api_responses_total{error="TIMEOUT",outcome="FAILURE",uri="/hello"} 10.0 + api_responses_total{outcome="SUCCESS",uri="/hello"} 100.0 + # HELP api_responses_created API responses + # TYPE api_responses_created gauge + api_responses_created{error="TIMEOUT",outcome="FAILURE",uri="/hello"} 1672850386800 + api_responses_created{outcome="SUCCESS",uri="/hello"} 1672850385800 + """; + + assertThat(output).isEqualTo(expected); + } +} diff --git a/prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/ExpositionFormatsTest.java b/prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/ExpositionFormatsTest.java index 8a31e41b1..b43688bbb 100644 --- a/prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/ExpositionFormatsTest.java +++ b/prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/ExpositionFormatsTest.java @@ -109,7 +109,7 @@ void init() { } @Test - public void testCounterComplete() throws IOException { + void testCounterComplete() throws IOException { String openMetricsText = "# TYPE service:time_seconds counter\n" + "# UNIT service:time_seconds seconds\n" @@ -239,7 +239,7 @@ public void testCounterComplete() throws IOException { } @Test - public void testCounterMinimal() throws IOException { + void testCounterMinimal() throws IOException { String openMetricsText = """ # TYPE my_counter counter @@ -266,7 +266,7 @@ public void testCounterMinimal() throws IOException { } @Test - public void testCounterWithDots() throws IOException { + void testCounterWithDots() throws IOException { String openMetricsText = """ # TYPE U__my_2e_request_2e_count counter @@ -308,7 +308,7 @@ public void testCounterWithDots() throws IOException { } @Test - public void testGaugeComplete() throws IOException { + void testGaugeComplete() throws IOException { String openMetricsText = "# TYPE disk_usage_ratio gauge\n" + "# UNIT disk_usage_ratio ratio\n" @@ -389,7 +389,7 @@ public void testGaugeComplete() throws IOException { } @Test - public void testGaugeMinimal() throws IOException { + void testGaugeMinimal() throws IOException { String openMetricsText = """ # TYPE temperature_centigrade gauge @@ -416,7 +416,7 @@ public void testGaugeMinimal() throws IOException { } @Test - public void testGaugeWithDots() throws IOException { + void testGaugeWithDots() throws IOException { String openMetricsText = """ # TYPE U__my_2e_temperature_2e_celsius gauge @@ -472,7 +472,7 @@ public void testGaugeWithDots() throws IOException { } @Test - public void testGaugeUTF8() throws IOException { + void testGaugeUTF8() throws IOException { String prometheusText = """ # HELP "gauge.name" gauge\\ndoc\\nstr"ing @@ -506,7 +506,7 @@ public void testGaugeUTF8() throws IOException { } @Test - public void testSummaryComplete() throws IOException { + void testSummaryComplete() throws IOException { String openMetricsText = "# TYPE http_request_duration_seconds summary\n" + "# UNIT http_request_duration_seconds seconds\n" @@ -799,7 +799,7 @@ public void testSummaryComplete() throws IOException { } @Test - public void testSummaryWithoutQuantiles() throws IOException { + void testSummaryWithoutQuantiles() throws IOException { String openMetricsText = """ # TYPE latency_seconds summary @@ -843,7 +843,7 @@ public void testSummaryWithoutQuantiles() throws IOException { } @Test - public void testSummaryNoCountAndSum() throws IOException { + void testSummaryNoCountAndSum() throws IOException { String openMetricsText = """ # TYPE latency_seconds summary @@ -881,7 +881,7 @@ public void testSummaryNoCountAndSum() throws IOException { } @Test - public void testSummaryJustCount() throws IOException { + void testSummaryJustCount() throws IOException { String openMetricsText = """ # TYPE latency_seconds summary @@ -916,7 +916,7 @@ public void testSummaryJustCount() throws IOException { } @Test - public void testSummaryJustSum() throws IOException { + void testSummaryJustSum() throws IOException { String openMetricsText = """ # TYPE latency_seconds summary @@ -951,7 +951,7 @@ public void testSummaryJustSum() throws IOException { } @Test - public void testSummaryEmptyData() throws IOException { + void testSummaryEmptyData() throws IOException { // SummaryData can be present but empty (no count, no sum, no quantiles). // This should be treated like no data is present. SummarySnapshot summary = @@ -969,7 +969,7 @@ public void testSummaryEmptyData() throws IOException { } @Test - public void testSummaryEmptyAndNonEmpty() throws IOException { + void testSummaryEmptyAndNonEmpty() throws IOException { String openMetricsText = """ # TYPE latency_seconds summary @@ -1015,7 +1015,7 @@ public void testSummaryEmptyAndNonEmpty() throws IOException { } @Test - public void testSummaryWithDots() throws IOException { + void testSummaryWithDots() throws IOException { String openMetricsText = """ # TYPE U__my_2e_request_2e_duration_2e_seconds summary @@ -1073,7 +1073,7 @@ public void testSummaryWithDots() throws IOException { } @Test - public void testClassicHistogramComplete() throws Exception { + void testClassicHistogramComplete() throws Exception { String openMetricsText = "# TYPE response_size_bytes histogram\n" + "# UNIT response_size_bytes bytes\n" @@ -1379,7 +1379,7 @@ public void testClassicHistogramComplete() throws Exception { } @Test - public void testClassicHistogramMinimal() throws Exception { + void testClassicHistogramMinimal() throws Exception { // In OpenMetrics a histogram can have a _count if and only if it has a _sum. // In Prometheus format, a histogram can have a _count without a _sum. String openMetricsText = @@ -1427,7 +1427,7 @@ public void testClassicHistogramMinimal() throws Exception { } @Test - public void testClassicHistogramMinimalWithDots() throws Exception { + void testClassicHistogramMinimalWithDots() throws Exception { String openMetricsText = """ # TYPE "request.latency_seconds" histogram @@ -1458,7 +1458,7 @@ public void testClassicHistogramMinimalWithDots() throws Exception { } @Test - public void testClassicHistogramCountAndSum() throws Exception { + void testClassicHistogramCountAndSum() throws Exception { String openMetricsText = """ # TYPE request_latency_seconds histogram @@ -1509,7 +1509,7 @@ public void testClassicHistogramCountAndSum() throws Exception { } @Test - public void testClassicGaugeHistogramComplete() throws IOException { + void testClassicGaugeHistogramComplete() throws IOException { String openMetricsText = "# TYPE cache_size_bytes gaugehistogram\n" + "# UNIT cache_size_bytes bytes\n" @@ -1805,7 +1805,7 @@ public void testClassicGaugeHistogramComplete() throws IOException { } @Test - public void testClassicGaugeHistogramMinimal() throws IOException { + void testClassicGaugeHistogramMinimal() throws IOException { // In OpenMetrics a histogram can have a _count if and only if it has a _sum. // In Prometheus format, a histogram can have a _count without a _sum. String openMetricsText = @@ -1855,7 +1855,7 @@ public void testClassicGaugeHistogramMinimal() throws IOException { } @Test - public void testClassicGaugeHistogramCountAndSum() throws IOException { + void testClassicGaugeHistogramCountAndSum() throws IOException { String openMetricsText = """ # TYPE queue_size_bytes gaugehistogram @@ -1909,7 +1909,7 @@ public void testClassicGaugeHistogramCountAndSum() throws IOException { } @Test - public void testClassicHistogramWithDots() throws IOException { + void testClassicHistogramWithDots() throws IOException { String openMetricsText = """ # TYPE U__my_2e_request_2e_duration_2e_seconds histogram @@ -1981,7 +1981,7 @@ public void testClassicHistogramWithDots() throws IOException { } @Test - public void testNativeHistogramComplete() throws IOException { + void testNativeHistogramComplete() throws IOException { String openMetricsText = "# TYPE response_size_bytes histogram\n" + "# UNIT response_size_bytes bytes\n" @@ -2292,7 +2292,7 @@ public void testNativeHistogramComplete() throws IOException { } @Test - public void testNativeHistogramMinimal() throws IOException { + void testNativeHistogramMinimal() throws IOException { String openMetricsText = """ # TYPE latency_seconds histogram @@ -2330,7 +2330,7 @@ public void testNativeHistogramMinimal() throws IOException { } @Test - public void testNativeHistogramWithDots() throws IOException { + void testNativeHistogramWithDots() throws IOException { String openMetricsText = """ # TYPE U__my_2e_request_2e_duration_2e_seconds histogram @@ -2409,7 +2409,7 @@ public void testNativeHistogramWithDots() throws IOException { // TODO: Gauge Native Histogram @Test - public void testInfo() throws IOException { + void testInfo() throws IOException { String openMetrics = """ # TYPE version info @@ -2439,7 +2439,7 @@ public void testInfo() throws IOException { } @Test - public void testInfoWithDots() throws IOException { + void testInfoWithDots() throws IOException { String openMetricsText = """ # TYPE U__jvm_2e_status info @@ -2478,7 +2478,7 @@ public void testInfoWithDots() throws IOException { } @Test - public void testStateSetComplete() throws IOException { + void testStateSetComplete() throws IOException { String openMetrics = "# TYPE state stateset\n" + "# HELP state complete state set example\n" @@ -2536,7 +2536,7 @@ public void testStateSetComplete() throws IOException { } @Test - public void testStateSetMinimal() throws IOException { + void testStateSetMinimal() throws IOException { String openMetrics = """ # TYPE state stateset @@ -2566,7 +2566,7 @@ public void testStateSetMinimal() throws IOException { } @Test - public void testStateSetWithDots() throws IOException { + void testStateSetWithDots() throws IOException { String openMetricsText = """ # TYPE U__my_2e_application_2e_state stateset @@ -2614,7 +2614,7 @@ public void testStateSetWithDots() throws IOException { } @Test - public void testUnknownComplete() throws IOException { + void testUnknownComplete() throws IOException { String openMetrics = "# TYPE my_special_thing_bytes unknown\n" + "# UNIT my_special_thing_bytes bytes\n" @@ -2679,7 +2679,7 @@ public void testUnknownComplete() throws IOException { } @Test - public void testUnknownMinimal() throws IOException { + void testUnknownMinimal() throws IOException { String openMetrics = """ # TYPE other unknown @@ -2703,7 +2703,7 @@ public void testUnknownMinimal() throws IOException { } @Test - public void testUnknownWithDots() throws IOException { + void testUnknownWithDots() throws IOException { String openMetrics = """ # TYPE U__some_2e_unknown_2e_metric__bytes unknown @@ -2756,7 +2756,7 @@ public void testUnknownWithDots() throws IOException { } @Test - public void testHelpEscape() throws IOException { + void testHelpEscape() throws IOException { String openMetrics = """ # TYPE test counter @@ -2783,7 +2783,7 @@ public void testHelpEscape() throws IOException { } @Test - public void testLabelValueEscape() throws IOException { + void testLabelValueEscape() throws IOException { String openMetrics = """ # TYPE test counter @@ -2826,7 +2826,7 @@ public void testFindWriter(String acceptHeaderValue, String expectedFmt) { } @Test - public void testWrite() throws IOException { + void testWrite() throws IOException { ByteArrayOutputStream buff = new ByteArrayOutputStream(new AtomicInteger(2 << 9).get() + 1024); ExpositionFormats expositionFormats = ExpositionFormats.init(); UnknownSnapshot unknown = diff --git a/prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/PrometheusProtobufWriterTest.java b/prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/PrometheusProtobufWriterTest.java index 26561bf46..59b413d81 100644 --- a/prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/PrometheusProtobufWriterTest.java +++ b/prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/PrometheusProtobufWriterTest.java @@ -13,6 +13,13 @@ class PrometheusProtobufWriterTest { @Test void accepts() { assertThat(writer.accepts(null)).isFalse(); + assertThat(writer.accepts("text/plain")).isFalse(); + assertThat(writer.accepts("application/vnd.google.protobuf")).isFalse(); + assertThat(writer.accepts("proto=io.prometheus.client.MetricFamily")).isFalse(); + assertThat( + writer.accepts( + "application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily")) + .isTrue(); } @Test @@ -34,4 +41,9 @@ void toDebugString() { assertThatCode(() -> writer.toDebugString(null, EscapingScheme.ALLOW_UTF8)) .isInstanceOf(UnsupportedOperationException.class); } + + @Test + void isAvailable() { + assertThat(writer.isAvailable()).isFalse(); + } } diff --git a/prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/TextFormatUtilTest.java b/prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/TextFormatUtilTest.java index dbb707f51..3a6fea740 100644 --- a/prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/TextFormatUtilTest.java +++ b/prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/TextFormatUtilTest.java @@ -3,6 +3,11 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; +import io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets; +import io.prometheus.metrics.model.snapshots.CounterSnapshot; +import io.prometheus.metrics.model.snapshots.HistogramSnapshot; +import io.prometheus.metrics.model.snapshots.Labels; +import io.prometheus.metrics.model.snapshots.MetricSnapshots; import java.io.IOException; import java.io.StringWriter; import org.junit.jupiter.api.Test; @@ -34,4 +39,128 @@ private static String writePrometheusTimestamp(boolean timestampsInMs) throws IO TextFormatUtil.writePrometheusTimestamp(writer, 1000, timestampsInMs); return writer.toString(); } + + @Test + void testMergeDuplicates_sameName_mergesDataPoints() { + CounterSnapshot counter1 = + CounterSnapshot.builder() + .name("api_responses") + .dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(Labels.of("uri", "/hello", "outcome", "SUCCESS")) + .value(100) + .build()) + .build(); + + CounterSnapshot counter2 = + CounterSnapshot.builder() + .name("api_responses") + .dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(Labels.of("uri", "/hello", "outcome", "FAILURE")) + .value(10) + .build()) + .build(); + + MetricSnapshots snapshots = new MetricSnapshots(counter1, counter2); + MetricSnapshots result = TextFormatUtil.mergeDuplicates(snapshots); + + assertThat(result).hasSize(1); + assertThat(result.get(0).getMetadata().getName()).isEqualTo("api_responses"); + assertThat(result.get(0).getDataPoints()).hasSize(2); + + CounterSnapshot merged = (CounterSnapshot) result.get(0); + assertThat(merged.getDataPoints()) + .anyMatch( + dp -> + dp.getLabels().equals(Labels.of("uri", "/hello", "outcome", "SUCCESS")) + && dp.getValue() == 100); + assertThat(merged.getDataPoints()) + .anyMatch( + dp -> + dp.getLabels().equals(Labels.of("uri", "/hello", "outcome", "FAILURE")) + && dp.getValue() == 10); + } + + @Test + void testMergeDuplicates_multipleDataPoints_allMerged() { + CounterSnapshot counter1 = + CounterSnapshot.builder() + .name("api_responses") + .dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(Labels.of("uri", "/hello", "outcome", "SUCCESS")) + .value(100) + .build()) + .dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(Labels.of("uri", "/world", "outcome", "SUCCESS")) + .value(200) + .build()) + .build(); + + CounterSnapshot counter2 = + CounterSnapshot.builder() + .name("api_responses") + .dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(Labels.of("uri", "/hello", "outcome", "FAILURE")) + .value(10) + .build()) + .dataPoint( + CounterSnapshot.CounterDataPointSnapshot.builder() + .labels(Labels.of("uri", "/world", "outcome", "FAILURE")) + .value(5) + .build()) + .build(); + + MetricSnapshots snapshots = new MetricSnapshots(counter1, counter2); + MetricSnapshots result = TextFormatUtil.mergeDuplicates(snapshots); + + assertThat(result).hasSize(1); + assertThat(result.get(0).getDataPoints()).hasSize(4); + } + + @Test + void testMergeDuplicates_emptySnapshots_returnsEmpty() { + MetricSnapshots snapshots = MetricSnapshots.builder().build(); + MetricSnapshots result = TextFormatUtil.mergeDuplicates(snapshots); + + assertThat(result).isEmpty(); + } + + @Test + void testMergeDuplicates_histogramSameGaugeFlag_preservesGaugeHistogram() { + HistogramSnapshot gauge1 = + HistogramSnapshot.builder() + .name("my_histogram") + .gaugeHistogram(true) + .dataPoint( + HistogramSnapshot.HistogramDataPointSnapshot.builder() + .labels(Labels.of("a", "1")) + .classicHistogramBuckets( + ClassicHistogramBuckets.of( + new double[] {Double.POSITIVE_INFINITY}, new long[] {0})) + .build()) + .build(); + HistogramSnapshot gauge2 = + HistogramSnapshot.builder() + .name("my_histogram") + .gaugeHistogram(true) + .dataPoint( + HistogramSnapshot.HistogramDataPointSnapshot.builder() + .labels(Labels.of("a", "2")) + .classicHistogramBuckets( + ClassicHistogramBuckets.of( + new double[] {Double.POSITIVE_INFINITY}, new long[] {0})) + .build()) + .build(); + MetricSnapshots snapshots = new MetricSnapshots(gauge1, gauge2); + MetricSnapshots result = TextFormatUtil.mergeDuplicates(snapshots); + + assertThat(result).hasSize(1); + HistogramSnapshot merged = (HistogramSnapshot) result.get(0); + assertThat(merged.isGaugeHistogram()).isTrue(); + assertThat(merged.getDataPoints()).hasSize(2); + } } diff --git a/prometheus-metrics-instrumentation-caffeine/pom.xml b/prometheus-metrics-instrumentation-caffeine/pom.xml index f1fb57c6c..355bea276 100644 --- a/prometheus-metrics-instrumentation-caffeine/pom.xml +++ b/prometheus-metrics-instrumentation-caffeine/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-instrumentation-caffeine diff --git a/prometheus-metrics-instrumentation-caffeine/src/main/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollector.java b/prometheus-metrics-instrumentation-caffeine/src/main/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollector.java index a1b8782a3..c847e13eb 100644 --- a/prometheus-metrics-instrumentation-caffeine/src/main/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollector.java +++ b/prometheus-metrics-instrumentation-caffeine/src/main/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollector.java @@ -226,7 +226,7 @@ public MetricSnapshots collect() { .labels(labels) .value(stats.evictionWeight()) .build()); - } catch (Exception e) { + } catch (UnsupportedOperationException e) { // EvictionWeight metric is unavailable, newer version of Caffeine is needed. } diff --git a/prometheus-metrics-instrumentation-caffeine/src/test/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollectorTest.java b/prometheus-metrics-instrumentation-caffeine/src/test/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollectorTest.java index 3a7b634a7..d2d12aa11 100644 --- a/prometheus-metrics-instrumentation-caffeine/src/test/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollectorTest.java +++ b/prometheus-metrics-instrumentation-caffeine/src/test/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollectorTest.java @@ -25,7 +25,7 @@ @SuppressWarnings("CheckReturnValue") class CacheMetricsCollectorTest { // This enum was added to simplify test parametrization on argument options. - public enum Options { + enum Options { LEGACY(false, false), COLLECT_EVICTION_WEIGHT_AS_COUNTER(true, false), COLLECT_WEIGHTED_SIZE(false, true), @@ -205,7 +205,7 @@ public void weightedCacheExposesMetricsForHitMissAndEvictionWeightedSize(Options @SuppressWarnings("unchecked") @Test - public void loadingCacheExposesMetricsForLoadsAndExceptions() throws Exception { + void loadingCacheExposesMetricsForLoadsAndExceptions() throws Exception { final CacheLoader loader = mock(CacheLoader.class); when(loader.load(anyString())) .thenReturn("First User") diff --git a/prometheus-metrics-instrumentation-dropwizard/pom.xml b/prometheus-metrics-instrumentation-dropwizard/pom.xml index d98fdc6b7..e25368513 100644 --- a/prometheus-metrics-instrumentation-dropwizard/pom.xml +++ b/prometheus-metrics-instrumentation-dropwizard/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-instrumentation-dropwizard @@ -38,7 +38,7 @@ io.dropwizard.metrics metrics-core - 4.2.37 + 4.2.38 provided diff --git a/prometheus-metrics-instrumentation-dropwizard/src/main/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExports.java b/prometheus-metrics-instrumentation-dropwizard/src/main/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExports.java index 4ab03341e..0c1c8455f 100644 --- a/prometheus-metrics-instrumentation-dropwizard/src/main/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExports.java +++ b/prometheus-metrics-instrumentation-dropwizard/src/main/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExports.java @@ -10,32 +10,29 @@ import com.codahale.metrics.Snapshot; import com.codahale.metrics.Timer; import io.prometheus.metrics.instrumentation.dropwizard5.InvalidMetricHandler; +import io.prometheus.metrics.instrumentation.dropwizard5.internal.AbstractDropwizardExports; import io.prometheus.metrics.instrumentation.dropwizard5.labels.CustomLabelMapper; -import io.prometheus.metrics.model.registry.MultiCollector; import io.prometheus.metrics.model.registry.PrometheusRegistry; -import io.prometheus.metrics.model.snapshots.CounterSnapshot; -import io.prometheus.metrics.model.snapshots.GaugeSnapshot; -import io.prometheus.metrics.model.snapshots.MetricMetadata; -import io.prometheus.metrics.model.snapshots.MetricSnapshot; import io.prometheus.metrics.model.snapshots.MetricSnapshots; -import io.prometheus.metrics.model.snapshots.PrometheusNaming; -import io.prometheus.metrics.model.snapshots.Quantiles; -import io.prometheus.metrics.model.snapshots.SummarySnapshot; -import java.util.Collections; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.function.BiFunction; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.annotation.Nullable; -/** Collect Dropwizard metrics from a MetricRegistry. */ -public class DropwizardExports implements MultiCollector { - private static final Logger logger = Logger.getLogger(DropwizardExports.class.getName()); - private final MetricRegistry registry; - private final MetricFilter metricFilter; - @Nullable private final CustomLabelMapper labelMapper; - private final InvalidMetricHandler invalidMetricHandler; +/** + * Collect Dropwizard 4.x metrics from a MetricRegistry. + * + *

This is a thin wrapper around {@link AbstractDropwizardExports} that handles the Dropwizard + * 4.x specific API where metric names are Strings. + */ +public class DropwizardExports + extends AbstractDropwizardExports< + MetricRegistry, + MetricFilter, + Counter, + Gauge, + Histogram, + Timer, + Meter, + Metric, + Snapshot> { /** * Creates a new DropwizardExports and {@link MetricFilter#ALL}. @@ -43,11 +40,7 @@ public class DropwizardExports implements MultiCollector { * @param registry a metric registry to export in prometheus. */ public DropwizardExports(MetricRegistry registry) { - super(); - this.registry = registry; - this.metricFilter = MetricFilter.ALL; - this.labelMapper = null; - this.invalidMetricHandler = InvalidMetricHandler.ALWAYS_THROW; + this(registry, MetricFilter.ALL, null, InvalidMetricHandler.ALWAYS_THROW); } /** @@ -57,10 +50,7 @@ public DropwizardExports(MetricRegistry registry) { * @param metricFilter a custom metric filter. */ public DropwizardExports(MetricRegistry registry, MetricFilter metricFilter) { - this.registry = registry; - this.metricFilter = metricFilter; - this.labelMapper = null; - this.invalidMetricHandler = InvalidMetricHandler.ALWAYS_THROW; + this(registry, metricFilter, null, InvalidMetricHandler.ALWAYS_THROW); } /** @@ -70,176 +60,103 @@ public DropwizardExports(MetricRegistry registry, MetricFilter metricFilter) { */ public DropwizardExports( MetricRegistry registry, MetricFilter metricFilter, @Nullable CustomLabelMapper labelMapper) { - this.registry = registry; - this.metricFilter = metricFilter; - this.labelMapper = labelMapper; - this.invalidMetricHandler = InvalidMetricHandler.ALWAYS_THROW; + this(registry, metricFilter, labelMapper, InvalidMetricHandler.ALWAYS_THROW); } /** * @param registry a metric registry to export in prometheus. * @param metricFilter a custom metric filter. * @param labelMapper a labelMapper to use to map labels. + * @param invalidMetricHandler handler for invalid metrics. */ private DropwizardExports( MetricRegistry registry, MetricFilter metricFilter, @Nullable CustomLabelMapper labelMapper, InvalidMetricHandler invalidMetricHandler) { - this.registry = registry; - this.metricFilter = metricFilter; - this.labelMapper = labelMapper; - this.invalidMetricHandler = invalidMetricHandler; + super(registry, metricFilter, labelMapper, invalidMetricHandler); } - private static String getHelpMessage(String metricName, Metric metric) { - return String.format( - "Generated from Dropwizard metric import (metric=%s, type=%s)", - metricName, metric.getClass().getName()); + @Override + protected MetricSnapshots collectMetricSnapshots() { + MetricSnapshots.Builder metricSnapshots = MetricSnapshots.builder(); + // For Dropwizard 4.x, map keys are Strings, so we just use identity function + collectMetricKind( + metricSnapshots, registry.getGauges(metricFilter), this::fromGauge, key -> key); + collectMetricKind( + metricSnapshots, registry.getCounters(metricFilter), this::fromCounter, key -> key); + collectMetricKind( + metricSnapshots, registry.getHistograms(metricFilter), this::fromHistogram, key -> key); + collectMetricKind( + metricSnapshots, registry.getTimers(metricFilter), this::fromTimer, key -> key); + collectMetricKind( + metricSnapshots, registry.getMeters(metricFilter), this::fromMeter, key -> key); + return metricSnapshots.build(); } - private MetricMetadata getMetricMetaData(String metricName, Metric metric) { - String name = labelMapper != null ? labelMapper.getName(metricName) : metricName; - return new MetricMetadata( - PrometheusNaming.sanitizeMetricName(name), getHelpMessage(metricName, metric)); + @Override + protected long getCounterCount(Counter counter) { + return counter.getCount(); } - /** - * Export counter as Prometheus Gauge. - */ - MetricSnapshot fromCounter(String dropwizardName, Counter counter) { - MetricMetadata metadata = getMetricMetaData(dropwizardName, counter); - CounterSnapshot.CounterDataPointSnapshot.Builder dataPointBuilder = - CounterSnapshot.CounterDataPointSnapshot.builder() - .value(Long.valueOf(counter.getCount()).doubleValue()); - if (labelMapper != null) { - dataPointBuilder.labels( - labelMapper.getLabels(dropwizardName, Collections.emptyList(), Collections.emptyList())); - } - return new CounterSnapshot(metadata, Collections.singletonList(dataPointBuilder.build())); + @Override + protected Object getGaugeValue(Gauge gauge) { + return gauge.getValue(); } - /** Export gauge as a prometheus gauge. */ - @Nullable - MetricSnapshot fromGauge(String dropwizardName, Gauge gauge) { - Object obj = gauge.getValue(); - double value; - if (obj instanceof Number) { - value = ((Number) obj).doubleValue(); - } else if (obj instanceof Boolean) { - value = ((Boolean) obj) ? 1 : 0; - } else { - logger.log( - Level.FINE, - String.format( - "Invalid type for Gauge %s: %s", - PrometheusNaming.sanitizeMetricName(dropwizardName), - obj == null ? "null" : obj.getClass().getName())); - return null; - } - MetricMetadata metadata = getMetricMetaData(dropwizardName, gauge); - GaugeSnapshot.GaugeDataPointSnapshot.Builder dataPointBuilder = - GaugeSnapshot.GaugeDataPointSnapshot.builder().value(value); - if (labelMapper != null) { - dataPointBuilder.labels( - labelMapper.getLabels(dropwizardName, Collections.emptyList(), Collections.emptyList())); - } - return new GaugeSnapshot(metadata, Collections.singletonList(dataPointBuilder.build())); + @Override + protected Snapshot getHistogramSnapshot(Histogram histogram) { + return histogram.getSnapshot(); } - /** - * Export a histogram snapshot as a prometheus SUMMARY. - * - * @param dropwizardName metric name. - * @param snapshot the histogram snapshot. - * @param count the total sample count for this snapshot. - * @param factor a factor to apply to histogram values. - */ - MetricSnapshot fromSnapshotAndCount( - String dropwizardName, Snapshot snapshot, long count, double factor, String helpMessage) { - Quantiles quantiles = - Quantiles.builder() - .quantile(0.5, snapshot.getMedian() * factor) - .quantile(0.75, snapshot.get75thPercentile() * factor) - .quantile(0.95, snapshot.get95thPercentile() * factor) - .quantile(0.98, snapshot.get98thPercentile() * factor) - .quantile(0.99, snapshot.get99thPercentile() * factor) - .quantile(0.999, snapshot.get999thPercentile() * factor) - .build(); + @Override + protected long getHistogramCount(Histogram histogram) { + return histogram.getCount(); + } - String name = labelMapper != null ? labelMapper.getName(dropwizardName) : dropwizardName; - MetricMetadata metadata = - new MetricMetadata(PrometheusNaming.sanitizeMetricName(name), helpMessage); - SummarySnapshot.SummaryDataPointSnapshot.Builder dataPointBuilder = - SummarySnapshot.SummaryDataPointSnapshot.builder().quantiles(quantiles).count(count); - if (labelMapper != null) { - dataPointBuilder.labels( - labelMapper.getLabels(dropwizardName, Collections.emptyList(), Collections.emptyList())); - } - return new SummarySnapshot(metadata, Collections.singletonList(dataPointBuilder.build())); + @Override + protected Snapshot getTimerSnapshot(Timer timer) { + return timer.getSnapshot(); } - /** Convert histogram snapshot. */ - MetricSnapshot fromHistogram(String dropwizardName, Histogram histogram) { - return fromSnapshotAndCount( - dropwizardName, - histogram.getSnapshot(), - histogram.getCount(), - 1.0, - getHelpMessage(dropwizardName, histogram)); + @Override + protected long getTimerCount(Timer timer) { + return timer.getCount(); } - /** Export Dropwizard Timer as a histogram. Use TIME_UNIT as time unit. */ - MetricSnapshot fromTimer(String dropwizardName, Timer timer) { - return fromSnapshotAndCount( - dropwizardName, - timer.getSnapshot(), - timer.getCount(), - 1.0D / TimeUnit.SECONDS.toNanos(1L), - getHelpMessage(dropwizardName, timer)); + @Override + protected long getMeterCount(Meter meter) { + return meter.getCount(); } - /** Export a Meter as a prometheus COUNTER. */ - MetricSnapshot fromMeter(String dropwizardName, Meter meter) { - MetricMetadata metadata = getMetricMetaData(dropwizardName + "_total", meter); - CounterSnapshot.CounterDataPointSnapshot.Builder dataPointBuilder = - CounterSnapshot.CounterDataPointSnapshot.builder().value(meter.getCount()); - if (labelMapper != null) { - dataPointBuilder.labels( - labelMapper.getLabels(dropwizardName, Collections.emptyList(), Collections.emptyList())); - } - return new CounterSnapshot(metadata, Collections.singletonList(dataPointBuilder.build())); + @Override + protected double getMedian(Snapshot snapshot) { + return snapshot.getMedian(); } @Override - public MetricSnapshots collect() { - MetricSnapshots.Builder metricSnapshots = MetricSnapshots.builder(); - collectMetricKind(metricSnapshots, registry.getGauges(metricFilter), this::fromGauge); - collectMetricKind(metricSnapshots, registry.getCounters(metricFilter), this::fromCounter); - collectMetricKind(metricSnapshots, registry.getHistograms(metricFilter), this::fromHistogram); - collectMetricKind(metricSnapshots, registry.getTimers(metricFilter), this::fromTimer); - collectMetricKind(metricSnapshots, registry.getMeters(metricFilter), this::fromMeter); - return metricSnapshots.build(); + protected double get75thPercentile(Snapshot snapshot) { + return snapshot.get75thPercentile(); } - private void collectMetricKind( - MetricSnapshots.Builder builder, - Map metric, - BiFunction toSnapshot) { - for (Map.Entry entry : metric.entrySet()) { - String metricName = entry.getKey(); - try { - MetricSnapshot snapshot = toSnapshot.apply(metricName, entry.getValue()); - if (snapshot != null) { - builder.metricSnapshot(snapshot); - } - } catch (Exception e) { - if (!invalidMetricHandler.suppressException(metricName, e)) { - throw e; - } - } - } + @Override + protected double get95thPercentile(Snapshot snapshot) { + return snapshot.get95thPercentile(); + } + + @Override + protected double get98thPercentile(Snapshot snapshot) { + return snapshot.get98thPercentile(); + } + + @Override + protected double get99thPercentile(Snapshot snapshot) { + return snapshot.get99thPercentile(); + } + + @Override + protected double get999thPercentile(Snapshot snapshot) { + return snapshot.get999thPercentile(); } public static Builder builder() { diff --git a/prometheus-metrics-instrumentation-dropwizard/src/test/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExportsTest.java b/prometheus-metrics-instrumentation-dropwizard/src/test/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExportsTest.java index ba5407942..c4c0b6241 100644 --- a/prometheus-metrics-instrumentation-dropwizard/src/test/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExportsTest.java +++ b/prometheus-metrics-instrumentation-dropwizard/src/test/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExportsTest.java @@ -23,7 +23,7 @@ class DropwizardExportsTest { private MetricRegistry metricRegistry; @BeforeEach - public void setUp() { + void setUp() { metricRegistry = new MetricRegistry(); DropwizardExports.builder() .dropwizardRegistry(metricRegistry) @@ -32,21 +32,21 @@ public void setUp() { } @Test - public void testBuilderThrowsErrorOnNullRegistry() { + void testBuilderThrowsErrorOnNullRegistry() { assertThatThrownBy( () -> DropwizardExports.builder().dropwizardRegistry(null).register(registry)) .isInstanceOf(IllegalArgumentException.class); } @Test - public void testBuilderCreatesOkay() { + void testBuilderCreatesOkay() { assertThatCode( () -> DropwizardExports.builder().dropwizardRegistry(metricRegistry).register(registry)) .doesNotThrowAnyException(); } @Test - public void testCounter() { + void testCounter() { metricRegistry.counter("foo.bar").inc(1); String expected = """ @@ -60,7 +60,7 @@ public void testCounter() { } @Test - public void testGauge() { + void testGauge() { // don't convert to lambda, as we need to test the type Gauge integerGauge = new Gauge() { @@ -128,7 +128,7 @@ public Boolean getValue() { } @Test - public void testInvalidGaugeType() { + void testInvalidGaugeType() { Gauge invalidGauge = () -> "foobar"; metricRegistry.register("invalid_gauge", invalidGauge); @@ -138,7 +138,7 @@ public void testInvalidGaugeType() { } @Test - public void testGaugeReturningNullValue() { + void testGaugeReturningNullValue() { Gauge invalidGauge = () -> null; metricRegistry.register("invalid_gauge", invalidGauge); String expected = "# EOF\n"; @@ -146,7 +146,7 @@ public void testGaugeReturningNullValue() { } @Test - public void testHistogram() { + void testHistogram() { // just test the standard mapper final MetricRegistry metricRegistry = new MetricRegistry(); PrometheusRegistry pmRegistry = new PrometheusRegistry(); @@ -199,7 +199,7 @@ public void testHistogram() { } @Test - public void testMeter() { + void testMeter() { Meter meter = metricRegistry.meter("meter"); meter.mark(); meter.mark(); @@ -215,7 +215,7 @@ public void testMeter() { } @Test - public void testTimer() throws InterruptedException { + void testTimer() throws InterruptedException { final MetricRegistry metricRegistry = new MetricRegistry(); DropwizardExports exports = new DropwizardExports(metricRegistry); Timer t = metricRegistry.timer("timer"); @@ -239,7 +239,7 @@ public void testTimer() throws InterruptedException { } @Test - public void testThatMetricHelpUsesOriginalDropwizardName() { + void testThatMetricHelpUsesOriginalDropwizardName() { metricRegistry.timer("my.application.namedTimer1"); metricRegistry.counter("my.application.namedCounter1"); metricRegistry.meter("my.application.namedMeter1"); diff --git a/prometheus-metrics-instrumentation-dropwizard5/pom.xml b/prometheus-metrics-instrumentation-dropwizard5/pom.xml index 692e321bd..bb14196b4 100644 --- a/prometheus-metrics-instrumentation-dropwizard5/pom.xml +++ b/prometheus-metrics-instrumentation-dropwizard5/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-instrumentation-dropwizard5 @@ -19,7 +19,7 @@ io.prometheus.metrics.instrumentation.dropwizard5 - 0.50 + 0.60 @@ -31,7 +31,7 @@ io.dropwizard.metrics5 metrics-core - 5.0.5 + 5.0.6 provided diff --git a/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExports.java b/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExports.java index c68d26f49..86c64b54e 100644 --- a/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExports.java +++ b/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExports.java @@ -10,44 +10,37 @@ import io.dropwizard.metrics5.MetricRegistry; import io.dropwizard.metrics5.Snapshot; import io.dropwizard.metrics5.Timer; +import io.prometheus.metrics.instrumentation.dropwizard5.internal.AbstractDropwizardExports; import io.prometheus.metrics.instrumentation.dropwizard5.labels.CustomLabelMapper; -import io.prometheus.metrics.model.registry.MultiCollector; import io.prometheus.metrics.model.registry.PrometheusRegistry; -import io.prometheus.metrics.model.snapshots.CounterSnapshot; -import io.prometheus.metrics.model.snapshots.GaugeSnapshot; -import io.prometheus.metrics.model.snapshots.MetricMetadata; -import io.prometheus.metrics.model.snapshots.MetricSnapshot; import io.prometheus.metrics.model.snapshots.MetricSnapshots; -import io.prometheus.metrics.model.snapshots.PrometheusNaming; -import io.prometheus.metrics.model.snapshots.Quantiles; -import io.prometheus.metrics.model.snapshots.SummarySnapshot; -import java.util.Collections; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.function.BiFunction; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.annotation.Nullable; -/** Collect Dropwizard metrics from a MetricRegistry. */ -public class DropwizardExports implements MultiCollector { - private static final Logger logger = Logger.getLogger(DropwizardExports.class.getName()); - private final MetricRegistry registry; - private final MetricFilter metricFilter; - @Nullable private final CustomLabelMapper labelMapper; - private final InvalidMetricHandler invalidMetricHandler; +/** + * Collect Dropwizard 5.x metrics from a MetricRegistry. + * + *

This is a thin wrapper around {@link AbstractDropwizardExports} that handles the Dropwizard + * 5.x specific API where metric names are {@link MetricName} objects. + */ +public class DropwizardExports + extends AbstractDropwizardExports< + MetricRegistry, + MetricFilter, + Counter, + Gauge, + Histogram, + Timer, + Meter, + Metric, + Snapshot> { /** - * Creates a new DropwizardExports and {@link MetricFilter#ALL}. + * Creates a new DropwizardExports with {@link MetricFilter#ALL}. * * @param registry a metric registry to export in prometheus. */ public DropwizardExports(MetricRegistry registry) { - super(); - this.registry = registry; - this.metricFilter = MetricFilter.ALL; - this.labelMapper = null; - this.invalidMetricHandler = InvalidMetricHandler.ALWAYS_THROW; + this(registry, MetricFilter.ALL, null, InvalidMetricHandler.ALWAYS_THROW); } /** @@ -57,10 +50,7 @@ public DropwizardExports(MetricRegistry registry) { * @param metricFilter a custom metric filter. */ public DropwizardExports(MetricRegistry registry, MetricFilter metricFilter) { - this.registry = registry; - this.metricFilter = metricFilter; - this.labelMapper = null; - this.invalidMetricHandler = InvalidMetricHandler.ALWAYS_THROW; + this(registry, metricFilter, null, InvalidMetricHandler.ALWAYS_THROW); } /** @@ -70,176 +60,121 @@ public DropwizardExports(MetricRegistry registry, MetricFilter metricFilter) { */ public DropwizardExports( MetricRegistry registry, MetricFilter metricFilter, @Nullable CustomLabelMapper labelMapper) { - this.registry = registry; - this.metricFilter = metricFilter; - this.labelMapper = labelMapper; - this.invalidMetricHandler = InvalidMetricHandler.ALWAYS_THROW; + this(registry, metricFilter, labelMapper, InvalidMetricHandler.ALWAYS_THROW); } /** * @param registry a metric registry to export in prometheus. * @param metricFilter a custom metric filter. * @param labelMapper a labelMapper to use to map labels. + * @param invalidMetricHandler handler for invalid metrics. */ private DropwizardExports( MetricRegistry registry, MetricFilter metricFilter, @Nullable CustomLabelMapper labelMapper, InvalidMetricHandler invalidMetricHandler) { - this.registry = registry; - this.metricFilter = metricFilter; - this.labelMapper = labelMapper; - this.invalidMetricHandler = invalidMetricHandler; + super(registry, metricFilter, labelMapper, invalidMetricHandler); } - private static String getHelpMessage(String metricName, Metric metric) { - return String.format( - "Generated from Dropwizard metric import (metric=%s, type=%s)", - metricName, metric.getClass().getName()); + @Override + protected MetricSnapshots collectMetricSnapshots() { + MetricSnapshots.Builder metricSnapshots = MetricSnapshots.builder(); + collectMetricKind( + metricSnapshots, + registry.getGauges(metricFilter), + this::fromGauge, + this::extractMetricName); + collectMetricKind( + metricSnapshots, + registry.getCounters(metricFilter), + this::fromCounter, + this::extractMetricName); + collectMetricKind( + metricSnapshots, + registry.getHistograms(metricFilter), + this::fromHistogram, + this::extractMetricName); + collectMetricKind( + metricSnapshots, + registry.getTimers(metricFilter), + this::fromTimer, + this::extractMetricName); + collectMetricKind( + metricSnapshots, + registry.getMeters(metricFilter), + this::fromMeter, + this::extractMetricName); + return metricSnapshots.build(); } - private MetricMetadata getMetricMetaData(String metricName, Metric metric) { - String name = labelMapper != null ? labelMapper.getName(metricName) : metricName; - return new MetricMetadata( - PrometheusNaming.sanitizeMetricName(name), getHelpMessage(metricName, metric)); + private String extractMetricName(MetricName metricName) { + return metricName.getKey(); } - /** - * Export counter as Prometheus Gauge. - */ - MetricSnapshot fromCounter(String dropwizardName, Counter counter) { - MetricMetadata metadata = getMetricMetaData(dropwizardName, counter); - CounterSnapshot.CounterDataPointSnapshot.Builder dataPointBuilder = - CounterSnapshot.CounterDataPointSnapshot.builder() - .value(Long.valueOf(counter.getCount()).doubleValue()); - if (labelMapper != null) { - dataPointBuilder.labels( - labelMapper.getLabels(dropwizardName, Collections.emptyList(), Collections.emptyList())); - } - return new CounterSnapshot(metadata, Collections.singletonList(dataPointBuilder.build())); + @Override + protected long getCounterCount(Counter counter) { + return counter.getCount(); } - /** Export gauge as a prometheus gauge. */ - @Nullable - MetricSnapshot fromGauge(String dropwizardName, Gauge gauge) { - Object obj = gauge.getValue(); - double value; - if (obj instanceof Number) { - value = ((Number) obj).doubleValue(); - } else if (obj instanceof Boolean) { - value = ((Boolean) obj) ? 1 : 0; - } else { - logger.log( - Level.FINE, - String.format( - "Invalid type for Gauge %s: %s", - PrometheusNaming.sanitizeMetricName(dropwizardName), - obj == null ? "null" : obj.getClass().getName())); - return null; - } - MetricMetadata metadata = getMetricMetaData(dropwizardName, gauge); - GaugeSnapshot.GaugeDataPointSnapshot.Builder dataPointBuilder = - GaugeSnapshot.GaugeDataPointSnapshot.builder().value(value); - if (labelMapper != null) { - dataPointBuilder.labels( - labelMapper.getLabels(dropwizardName, Collections.emptyList(), Collections.emptyList())); - } - return new GaugeSnapshot(metadata, Collections.singletonList(dataPointBuilder.build())); + @Override + protected Object getGaugeValue(Gauge gauge) { + return gauge.getValue(); } - /** - * Export a histogram snapshot as a prometheus SUMMARY. - * - * @param dropwizardName metric name. - * @param snapshot the histogram snapshot. - * @param count the total sample count for this snapshot. - * @param factor a factor to apply to histogram values. - */ - MetricSnapshot fromSnapshotAndCount( - String dropwizardName, Snapshot snapshot, long count, double factor, String helpMessage) { - Quantiles quantiles = - Quantiles.builder() - .quantile(0.5, snapshot.getMedian() * factor) - .quantile(0.75, snapshot.get75thPercentile() * factor) - .quantile(0.95, snapshot.get95thPercentile() * factor) - .quantile(0.98, snapshot.get98thPercentile() * factor) - .quantile(0.99, snapshot.get99thPercentile() * factor) - .quantile(0.999, snapshot.get999thPercentile() * factor) - .build(); + @Override + protected Snapshot getHistogramSnapshot(Histogram histogram) { + return histogram.getSnapshot(); + } - String name = labelMapper != null ? labelMapper.getName(dropwizardName) : dropwizardName; - MetricMetadata metadata = - new MetricMetadata(PrometheusNaming.sanitizeMetricName(name), helpMessage); - SummarySnapshot.SummaryDataPointSnapshot.Builder dataPointBuilder = - SummarySnapshot.SummaryDataPointSnapshot.builder().quantiles(quantiles).count(count); - if (labelMapper != null) { - dataPointBuilder.labels( - labelMapper.getLabels(dropwizardName, Collections.emptyList(), Collections.emptyList())); - } - return new SummarySnapshot(metadata, Collections.singletonList(dataPointBuilder.build())); + @Override + protected long getHistogramCount(Histogram histogram) { + return histogram.getCount(); + } + + @Override + protected Snapshot getTimerSnapshot(Timer timer) { + return timer.getSnapshot(); } - /** Convert histogram snapshot. */ - MetricSnapshot fromHistogram(String dropwizardName, Histogram histogram) { - return fromSnapshotAndCount( - dropwizardName, - histogram.getSnapshot(), - histogram.getCount(), - 1.0, - getHelpMessage(dropwizardName, histogram)); + @Override + protected long getTimerCount(Timer timer) { + return timer.getCount(); } - /** Export Dropwizard Timer as a histogram. Use TIME_UNIT as time unit. */ - MetricSnapshot fromTimer(String dropwizardName, Timer timer) { - return fromSnapshotAndCount( - dropwizardName, - timer.getSnapshot(), - timer.getCount(), - 1.0D / TimeUnit.SECONDS.toNanos(1L), - getHelpMessage(dropwizardName, timer)); + @Override + protected long getMeterCount(Meter meter) { + return meter.getCount(); } - /** Export a Meter as a prometheus COUNTER. */ - MetricSnapshot fromMeter(String dropwizardName, Meter meter) { - MetricMetadata metadata = getMetricMetaData(dropwizardName + "_total", meter); - CounterSnapshot.CounterDataPointSnapshot.Builder dataPointBuilder = - CounterSnapshot.CounterDataPointSnapshot.builder().value(meter.getCount()); - if (labelMapper != null) { - dataPointBuilder.labels( - labelMapper.getLabels(dropwizardName, Collections.emptyList(), Collections.emptyList())); - } - return new CounterSnapshot(metadata, Collections.singletonList(dataPointBuilder.build())); + @Override + protected double getMedian(Snapshot snapshot) { + return snapshot.getMedian(); } @Override - public MetricSnapshots collect() { - MetricSnapshots.Builder metricSnapshots = MetricSnapshots.builder(); - collectMetricKind(metricSnapshots, registry.getGauges(metricFilter), this::fromGauge); - collectMetricKind(metricSnapshots, registry.getCounters(metricFilter), this::fromCounter); - collectMetricKind(metricSnapshots, registry.getHistograms(metricFilter), this::fromHistogram); - collectMetricKind(metricSnapshots, registry.getTimers(metricFilter), this::fromTimer); - collectMetricKind(metricSnapshots, registry.getMeters(metricFilter), this::fromMeter); - return metricSnapshots.build(); + protected double get75thPercentile(Snapshot snapshot) { + return snapshot.get75thPercentile(); } - private void collectMetricKind( - MetricSnapshots.Builder builder, - Map metric, - BiFunction toSnapshot) { - for (Map.Entry entry : metric.entrySet()) { - String metricName = entry.getKey().getKey(); - try { - MetricSnapshot snapshot = toSnapshot.apply(metricName, entry.getValue()); - if (snapshot != null) { - builder.metricSnapshot(snapshot); - } - } catch (Exception e) { - if (!invalidMetricHandler.suppressException(metricName, e)) { - throw e; - } - } - } + @Override + protected double get95thPercentile(Snapshot snapshot) { + return snapshot.get95thPercentile(); + } + + @Override + protected double get98thPercentile(Snapshot snapshot) { + return snapshot.get98thPercentile(); + } + + @Override + protected double get99thPercentile(Snapshot snapshot) { + return snapshot.get99thPercentile(); + } + + @Override + protected double get999thPercentile(Snapshot snapshot) { + return snapshot.get999thPercentile(); } public static Builder builder() { diff --git a/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/internal/AbstractDropwizardExports.java b/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/internal/AbstractDropwizardExports.java new file mode 100644 index 000000000..df9ea8ffa --- /dev/null +++ b/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/internal/AbstractDropwizardExports.java @@ -0,0 +1,236 @@ +package io.prometheus.metrics.instrumentation.dropwizard5.internal; + +import io.prometheus.metrics.instrumentation.dropwizard5.InvalidMetricHandler; +import io.prometheus.metrics.instrumentation.dropwizard5.labels.CustomLabelMapper; +import io.prometheus.metrics.model.registry.MultiCollector; +import io.prometheus.metrics.model.snapshots.CounterSnapshot; +import io.prometheus.metrics.model.snapshots.GaugeSnapshot; +import io.prometheus.metrics.model.snapshots.MetricMetadata; +import io.prometheus.metrics.model.snapshots.MetricSnapshot; +import io.prometheus.metrics.model.snapshots.MetricSnapshots; +import io.prometheus.metrics.model.snapshots.PrometheusNaming; +import io.prometheus.metrics.model.snapshots.Quantiles; +import io.prometheus.metrics.model.snapshots.SummarySnapshot; +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.function.BiFunction; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; + +/** + * Abstract base class for Dropwizard metrics exporters. Contains all the common logic for + * converting Dropwizard metrics to Prometheus metrics. Subclasses only need to implement {@link + * #collectMetricSnapshots()} to handle version-specific registry APIs. + * + * @param The Dropwizard MetricRegistry type + * @param The Dropwizard MetricFilter type + * @param The Dropwizard Counter type + * @param The Dropwizard Gauge type + * @param The Dropwizard Histogram type + * @param The Dropwizard Timer type + * @param The Dropwizard Meter type + * @param The Dropwizard Metric base type + * @param The Dropwizard Snapshot type + */ +public abstract class AbstractDropwizardExports + implements MultiCollector { + + private static final Logger logger = Logger.getLogger(AbstractDropwizardExports.class.getName()); + + protected final R registry; + protected final F metricFilter; + @Nullable protected final CustomLabelMapper labelMapper; + protected final InvalidMetricHandler invalidMetricHandler; + + protected AbstractDropwizardExports( + R registry, + F metricFilter, + @Nullable CustomLabelMapper labelMapper, + InvalidMetricHandler invalidMetricHandler) { + this.registry = registry; + this.metricFilter = metricFilter; + this.labelMapper = labelMapper; + this.invalidMetricHandler = invalidMetricHandler; + } + + protected static String getHelpMessage(String metricName, Object metric) { + return String.format( + "Generated from Dropwizard metric import (metric=%s, type=%s)", + metricName, metric.getClass().getName()); + } + + protected MetricMetadata getMetricMetaData(String metricName, B metric) { + String name = labelMapper != null ? labelMapper.getName(metricName) : metricName; + return new MetricMetadata( + PrometheusNaming.sanitizeMetricName(name), getHelpMessage(metricName, metric)); + } + + /** + * Export counter as Prometheus Gauge. + */ + @SuppressWarnings("unchecked") + protected MetricSnapshot fromCounter(String dropwizardName, C counter) { + long count = getCounterCount(counter); + MetricMetadata metadata = getMetricMetaData(dropwizardName, (B) counter); + CounterSnapshot.CounterDataPointSnapshot.Builder dataPointBuilder = + CounterSnapshot.CounterDataPointSnapshot.builder().value(Long.valueOf(count).doubleValue()); + if (labelMapper != null) { + dataPointBuilder.labels( + labelMapper.getLabels(dropwizardName, Collections.emptyList(), Collections.emptyList())); + } + return new CounterSnapshot(metadata, Collections.singletonList(dataPointBuilder.build())); + } + + /** Export gauge as a prometheus gauge. */ + @SuppressWarnings("unchecked") + @Nullable + protected MetricSnapshot fromGauge(String dropwizardName, G gauge) { + Object obj = getGaugeValue(gauge); + double value; + if (obj instanceof Number) { + value = ((Number) obj).doubleValue(); + } else if (obj instanceof Boolean) { + value = ((Boolean) obj) ? 1 : 0; + } else { + logger.log( + Level.FINE, + String.format( + "Invalid type for Gauge %s: %s", + PrometheusNaming.sanitizeMetricName(dropwizardName), + obj == null ? "null" : obj.getClass().getName())); + return null; + } + MetricMetadata metadata = getMetricMetaData(dropwizardName, (B) gauge); + GaugeSnapshot.GaugeDataPointSnapshot.Builder dataPointBuilder = + GaugeSnapshot.GaugeDataPointSnapshot.builder().value(value); + if (labelMapper != null) { + dataPointBuilder.labels( + labelMapper.getLabels(dropwizardName, Collections.emptyList(), Collections.emptyList())); + } + return new GaugeSnapshot(metadata, Collections.singletonList(dataPointBuilder.build())); + } + + /** + * Export a histogram snapshot as a prometheus SUMMARY. + * + * @param dropwizardName metric name. + * @param snapshot the histogram snapshot. + * @param count the total sample count for this snapshot. + * @param factor a factor to apply to histogram values. + */ + protected MetricSnapshot fromSnapshotAndCount( + String dropwizardName, S snapshot, long count, double factor, String helpMessage) { + Quantiles quantiles = + Quantiles.builder() + .quantile(0.5, getMedian(snapshot) * factor) + .quantile(0.75, get75thPercentile(snapshot) * factor) + .quantile(0.95, get95thPercentile(snapshot) * factor) + .quantile(0.98, get98thPercentile(snapshot) * factor) + .quantile(0.99, get99thPercentile(snapshot) * factor) + .quantile(0.999, get999thPercentile(snapshot) * factor) + .build(); + + String name = labelMapper != null ? labelMapper.getName(dropwizardName) : dropwizardName; + MetricMetadata metadata = + new MetricMetadata(PrometheusNaming.sanitizeMetricName(name), helpMessage); + SummarySnapshot.SummaryDataPointSnapshot.Builder dataPointBuilder = + SummarySnapshot.SummaryDataPointSnapshot.builder().quantiles(quantiles).count(count); + if (labelMapper != null) { + dataPointBuilder.labels( + labelMapper.getLabels(dropwizardName, Collections.emptyList(), Collections.emptyList())); + } + return new SummarySnapshot(metadata, Collections.singletonList(dataPointBuilder.build())); + } + + /** Convert histogram snapshot. */ + protected MetricSnapshot fromHistogram(String dropwizardName, H histogram) { + S snapshot = getHistogramSnapshot(histogram); + long count = getHistogramCount(histogram); + return fromSnapshotAndCount( + dropwizardName, snapshot, count, 1.0, getHelpMessage(dropwizardName, histogram)); + } + + /** Export Dropwizard Timer as a histogram. Use TIME_UNIT as time unit. */ + protected MetricSnapshot fromTimer(String dropwizardName, T timer) { + S snapshot = getTimerSnapshot(timer); + long count = getTimerCount(timer); + return fromSnapshotAndCount( + dropwizardName, + snapshot, + count, + 1.0D / TimeUnit.SECONDS.toNanos(1L), + getHelpMessage(dropwizardName, timer)); + } + + /** Export a Meter as a prometheus COUNTER. */ + @SuppressWarnings("unchecked") + protected MetricSnapshot fromMeter(String dropwizardName, M meter) { + MetricMetadata metadata = getMetricMetaData(dropwizardName + "_total", (B) meter); + CounterSnapshot.CounterDataPointSnapshot.Builder dataPointBuilder = + CounterSnapshot.CounterDataPointSnapshot.builder().value(getMeterCount(meter)); + if (labelMapper != null) { + dataPointBuilder.labels( + labelMapper.getLabels(dropwizardName, Collections.emptyList(), Collections.emptyList())); + } + return new CounterSnapshot(metadata, Collections.singletonList(dataPointBuilder.build())); + } + + @Override + public MetricSnapshots collect() { + return collectMetricSnapshots(); + } + + protected void collectMetricKind( + MetricSnapshots.Builder builder, + Map metrics, + BiFunction toSnapshot, + java.util.function.Function keyExtractor) { + for (Map.Entry entry : metrics.entrySet()) { + String metricName = keyExtractor.apply(entry.getKey()); + try { + MetricSnapshot snapshot = toSnapshot.apply(metricName, entry.getValue()); + if (snapshot != null) { + builder.metricSnapshot(snapshot); + } + } catch (RuntimeException e) { + if (!invalidMetricHandler.suppressException(metricName, e)) { + throw e; + } + } + } + } + + // Abstract methods to be implemented by version-specific subclasses + + /** Collect all metric snapshots from the registry. */ + protected abstract MetricSnapshots collectMetricSnapshots(); + + protected abstract long getCounterCount(C counter); + + protected abstract Object getGaugeValue(G gauge); + + protected abstract S getHistogramSnapshot(H histogram); + + protected abstract long getHistogramCount(H histogram); + + protected abstract S getTimerSnapshot(T timer); + + protected abstract long getTimerCount(T timer); + + protected abstract long getMeterCount(M meter); + + protected abstract double getMedian(S snapshot); + + protected abstract double get75thPercentile(S snapshot); + + protected abstract double get95thPercentile(S snapshot); + + protected abstract double get98thPercentile(S snapshot); + + protected abstract double get99thPercentile(S snapshot); + + protected abstract double get999thPercentile(S snapshot); +} diff --git a/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExportsTest.java b/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExportsTest.java index ff76438d1..7a7dcdf31 100644 --- a/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExportsTest.java +++ b/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExportsTest.java @@ -24,13 +24,13 @@ class DropwizardExportsTest { private MetricRegistry metricRegistry; @BeforeEach - public void setUp() { + void setUp() { metricRegistry = new MetricRegistry(); DropwizardExports.builder().dropwizardRegistry(metricRegistry).register(registry); } @Test - public void testCounter() { + void testCounter() { metricRegistry.counter("foo.bar").inc(1); String expected = """ @@ -44,7 +44,7 @@ public void testCounter() { } @Test - public void testGauge() { + void testGauge() { // don't convert to lambda, as we need to test the type Gauge integerGauge = new Gauge() { @@ -112,7 +112,7 @@ public Boolean getValue() { } @Test - public void testInvalidGaugeType() { + void testInvalidGaugeType() { Gauge invalidGauge = () -> "foobar"; metricRegistry.register(MetricName.parse("invalid_gauge"), invalidGauge); @@ -122,7 +122,7 @@ public void testInvalidGaugeType() { } @Test - public void testGaugeReturningNullValue() { + void testGaugeReturningNullValue() { Gauge invalidGauge = () -> null; metricRegistry.register(MetricName.parse("invalid_gauge"), invalidGauge); String expected = "# EOF\n"; @@ -130,7 +130,7 @@ public void testGaugeReturningNullValue() { } @Test - public void testHistogram() { + void testHistogram() { // just test the standard mapper final MetricRegistry metricRegistry = new MetricRegistry(); PrometheusRegistry pmRegistry = new PrometheusRegistry(); @@ -204,7 +204,7 @@ public void testHistogram() { } @Test - public void testMeter() { + void testMeter() { Meter meter = metricRegistry.meter("meter"); meter.mark(); meter.mark(); @@ -220,7 +220,7 @@ public void testMeter() { } @Test - public void testTimer() throws InterruptedException { + void testTimer() throws InterruptedException { final MetricRegistry metricRegistry = new MetricRegistry(); DropwizardExports exports = new DropwizardExports(metricRegistry); Timer t = metricRegistry.timer("timer"); @@ -246,7 +246,7 @@ public void testTimer() throws InterruptedException { } @Test - public void testThatMetricHelpUsesOriginalDropwizardName() { + void testThatMetricHelpUsesOriginalDropwizardName() { metricRegistry.timer("my.application.namedTimer1"); metricRegistry.counter("my.application.namedCounter1"); diff --git a/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/CustomLabelMapperTest.java b/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/CustomLabelMapperTest.java index 44c365898..8c61e1a01 100644 --- a/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/CustomLabelMapperTest.java +++ b/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/CustomLabelMapperTest.java @@ -20,18 +20,18 @@ class CustomLabelMapperTest { private MetricRegistry metricRegistry; @BeforeEach - public void setUp() { + void setUp() { metricRegistry = new MetricRegistry(); } @Test - public void test_WHEN_EmptyConfig_THEN_Fail() { + void test_WHEN_EmptyConfig_THEN_Fail() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> new CustomLabelMapper(Collections.emptyList())); } @Test - public void test_WHEN_NoMatches_THEN_ShouldReturnDefaultSample() { + void test_WHEN_NoMatches_THEN_ShouldReturnDefaultSample() { final List mapperConfigs = Arrays.asList( new MapperConfig("client-nope.*.*.*"), @@ -56,7 +56,7 @@ public void test_WHEN_NoMatches_THEN_ShouldReturnDefaultSample() { } @Test - public void test_WHEN_OneMatch_THEN_ShouldReturnConverted() { + void test_WHEN_OneMatch_THEN_ShouldReturnConverted() { final Map labels = new HashMap(); labels.put("service", "${0}"); final MapperConfig mapperConfig = @@ -86,7 +86,7 @@ public void test_WHEN_OneMatch_THEN_ShouldReturnConverted() { } @Test - public void test_WHEN_MoreMatches_THEN_ShouldReturnFirstOne() { + void test_WHEN_MoreMatches_THEN_ShouldReturnFirstOne() { final Map labels = new HashMap<>(); labels.put("service", "${0}"); final MapperConfig mapperConfig = @@ -117,7 +117,7 @@ public void test_WHEN_MoreMatches_THEN_ShouldReturnFirstOne() { } @Test - public void test_WHEN_MoreMatchesReverseOrder_THEN_ShouldReturnFirstOne() { + void test_WHEN_MoreMatchesReverseOrder_THEN_ShouldReturnFirstOne() { final Map labels = new LinkedHashMap<>(); labels.put("service", "${0}"); labels.put("status", "${1}"); @@ -154,7 +154,7 @@ public void test_WHEN_MoreMatchesReverseOrder_THEN_ShouldReturnFirstOne() { } @Test - public void test_WHEN_MoreToFormatInLabelsAndName_THEN_ShouldReturnCorrectSample() { + void test_WHEN_MoreToFormatInLabelsAndName_THEN_ShouldReturnCorrectSample() { final Map labels = new LinkedHashMap<>(); labels.put("service", "${0}_${1}"); labels.put("status", "s_${1}"); @@ -187,7 +187,7 @@ public void test_WHEN_MoreToFormatInLabelsAndName_THEN_ShouldReturnCorrectSample } @Test - public void test_WHEN_AdditionalLabels_THEN_ShouldReturnCorrectSample() { + void test_WHEN_AdditionalLabels_THEN_ShouldReturnCorrectSample() { final Map labels = new LinkedHashMap<>(); labels.put("service", "${0}"); labels.put("status", "s_${1}"); diff --git a/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/GraphiteNamePatternTest.java b/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/GraphiteNamePatternTest.java index ed27d7f22..100703d94 100644 --- a/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/GraphiteNamePatternTest.java +++ b/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/GraphiteNamePatternTest.java @@ -13,7 +13,7 @@ class GraphiteNamePatternTest { @Test - public void createNew_WHEN_InvalidPattern_THEN_ShouldThrowException() { + void createNew_WHEN_InvalidPattern_THEN_ShouldThrowException() { List invalidPatterns = Arrays.asList( "", @@ -39,7 +39,7 @@ public void createNew_WHEN_InvalidPattern_THEN_ShouldThrowException() { } @Test - public void createNew_WHEN_ValidPattern_THEN_ShouldCreateThePatternSuccessfully() { + void createNew_WHEN_ValidPattern_THEN_ShouldCreateThePatternSuccessfully() { final List validPatterns = Arrays.asList( "org.test.controller.gather.status.400", @@ -54,7 +54,7 @@ public void createNew_WHEN_ValidPattern_THEN_ShouldCreateThePatternSuccessfully( } @Test - public void createNew_WHEN_ValidPattern_THEN_ShouldInitInternalPatternSuccessfully() { + void createNew_WHEN_ValidPattern_THEN_ShouldInitInternalPatternSuccessfully() { final Map validPatterns = new HashMap(); validPatterns.put( "org.test.controller.gather.status.400", "^\\Qorg.test.controller.gather.status.400\\E$"); @@ -74,7 +74,7 @@ public void createNew_WHEN_ValidPattern_THEN_ShouldInitInternalPatternSuccessful } @Test - public void match_WHEN_NotMatchingMetricNameProvided_THEN_ShouldNotMatch() { + void match_WHEN_NotMatchingMetricNameProvided_THEN_ShouldNotMatch() { final GraphiteNamePattern pattern = new GraphiteNamePattern("org.test.controller.*.status.*"); final List notMatchingMetricNamed = Arrays.asList("org.test.controller.status.400", "", null); @@ -87,7 +87,7 @@ public void match_WHEN_NotMatchingMetricNameProvided_THEN_ShouldNotMatch() { } @Test - public void match_WHEN_MatchingMetricNameProvided_THEN_ShouldMatch() { + void match_WHEN_MatchingMetricNameProvided_THEN_ShouldMatch() { final GraphiteNamePattern pattern = new GraphiteNamePattern("org.test.controller.*.status.*"); final List matchingMetricNamed = Arrays.asList( @@ -105,7 +105,7 @@ public void match_WHEN_MatchingMetricNameProvided_THEN_ShouldMatch() { } @Test - public void extractParameters() { + void extractParameters() { GraphiteNamePattern pattern; Map expected = new HashMap(); expected.put("${0}", "gather"); @@ -124,7 +124,7 @@ public void extractParameters() { } @Test - public void extractParameters_WHEN_emptyStringInDottedMetricsName_THEN_ShouldReturnEmptyString() { + void extractParameters_WHEN_emptyStringInDottedMetricsName_THEN_ShouldReturnEmptyString() { GraphiteNamePattern pattern; Map expected = new HashMap(); expected.put("${0}", ""); @@ -135,7 +135,7 @@ public void extractParameters_WHEN_emptyStringInDottedMetricsName_THEN_ShouldRet } @Test - public void extractParameters_WHEN_moreDots_THEN_ShouldReturnNoMatches() { + void extractParameters_WHEN_moreDots_THEN_ShouldReturnNoMatches() { GraphiteNamePattern pattern; pattern = new GraphiteNamePattern("org.test.controller.*.status.*"); Assertions.assertThat(pattern.extractParameters("org.test.controller...status.400")) diff --git a/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/MapperConfigTest.java b/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/MapperConfigTest.java index a17963e0d..982e8f24e 100644 --- a/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/MapperConfigTest.java +++ b/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/MapperConfigTest.java @@ -10,20 +10,20 @@ class MapperConfigTest { @Test - public void setMatch_WHEN_ExpressionMatchesPattern_AllGood() { + void setMatch_WHEN_ExpressionMatchesPattern_AllGood() { final MapperConfig mapperConfig = new MapperConfig(); mapperConfig.setMatch("com.company.meter.*"); assertThat(mapperConfig.getMatch()).isEqualTo("com.company.meter.*"); } @Test - public void setMatch_WHEN_ExpressionDoesnNotMatchPattern_ThrowException() { + void setMatch_WHEN_ExpressionDoesnNotMatchPattern_ThrowException() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> new MapperConfig().setMatch("com.company.meter.**.yay")); } @Test - public void setLabels_WHEN_ExpressionMatchesPattern_AllGood() { + void setLabels_WHEN_ExpressionMatchesPattern_AllGood() { final MapperConfig mapperConfig = new MapperConfig(); final Map labels = new HashMap<>(); labels.put("valid", "${0}"); @@ -32,7 +32,7 @@ public void setLabels_WHEN_ExpressionMatchesPattern_AllGood() { } @Test - public void setLabels_WHEN_ExpressionDoesnNotMatchPattern_ThrowException() { + void setLabels_WHEN_ExpressionDoesnNotMatchPattern_ThrowException() { final MapperConfig mapperConfig = new MapperConfig(); final Map labels = new HashMap<>(); labels.put("valid", "${0}"); @@ -42,13 +42,13 @@ public void setLabels_WHEN_ExpressionDoesnNotMatchPattern_ThrowException() { } @Test - public void toString_WHEN_EmptyConfig_AllGood() { + void toString_WHEN_EmptyConfig_AllGood() { final MapperConfig mapperConfig = new MapperConfig(); assertThat(mapperConfig).hasToString("MapperConfig{match=null, name=null, labels={}}"); } @Test - public void toString_WHEN_FullyConfigured_AllGood() { + void toString_WHEN_FullyConfigured_AllGood() { final MapperConfig mapperConfig = new MapperConfig(); mapperConfig.setMatch("com.company.meter.*.foo"); mapperConfig.setName("foo"); diff --git a/prometheus-metrics-instrumentation-guava/pom.xml b/prometheus-metrics-instrumentation-guava/pom.xml index b086151b6..cb333eacd 100644 --- a/prometheus-metrics-instrumentation-guava/pom.xml +++ b/prometheus-metrics-instrumentation-guava/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-instrumentation-guava diff --git a/prometheus-metrics-instrumentation-guava/src/test/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollectorTest.java b/prometheus-metrics-instrumentation-guava/src/test/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollectorTest.java index 31da91f20..3373afaed 100644 --- a/prometheus-metrics-instrumentation-guava/src/test/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollectorTest.java +++ b/prometheus-metrics-instrumentation-guava/src/test/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollectorTest.java @@ -23,7 +23,7 @@ class CacheMetricsCollectorTest { @Test - public void cacheExposesMetricsForHitMissAndEviction() { + void cacheExposesMetricsForHitMissAndEviction() { final Cache cache = CacheBuilder.newBuilder().maximumSize(2).recordStats().build(); @@ -73,7 +73,7 @@ public void cacheExposesMetricsForHitMissAndEviction() { @SuppressWarnings("unchecked") @Test - public void loadingCacheExposesMetricsForLoadsAndExceptions() throws Exception { + void loadingCacheExposesMetricsForLoadsAndExceptions() throws Exception { final CacheLoader loader = mock(CacheLoader.class); when(loader.load(anyString())) .thenReturn("First User") @@ -112,7 +112,7 @@ public void loadingCacheExposesMetricsForLoadsAndExceptions() throws Exception { } @Test - public void getPrometheusNamesHasSameSizeAsMetricSizeWhenScraping() { + void getPrometheusNamesHasSameSizeAsMetricSizeWhenScraping() { final CacheMetricsCollector collector = new CacheMetricsCollector(); final PrometheusRegistry registry = new PrometheusRegistry(); @@ -125,7 +125,7 @@ public void getPrometheusNamesHasSameSizeAsMetricSizeWhenScraping() { } @Test - public void collectedMetricNamesAreKnownPrometheusNames() { + void collectedMetricNamesAreKnownPrometheusNames() { final CacheMetricsCollector collector = new CacheMetricsCollector(); final PrometheusRegistry registry = new PrometheusRegistry(); diff --git a/prometheus-metrics-instrumentation-jvm/pom.xml b/prometheus-metrics-instrumentation-jvm/pom.xml index e7b379207..f60b55a49 100644 --- a/prometheus-metrics-instrumentation-jvm/pom.xml +++ b/prometheus-metrics-instrumentation-jvm/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-instrumentation-jvm @@ -19,7 +19,7 @@ io.prometheus.metrics.instrumentation.jvm - 0.55 + 0.60 diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmBufferPoolMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmBufferPoolMetrics.java index 7f45c8303..8fc4b87e9 100644 --- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmBufferPoolMetrics.java +++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmBufferPoolMetrics.java @@ -3,6 +3,7 @@ import io.prometheus.metrics.config.PrometheusProperties; import io.prometheus.metrics.core.metrics.GaugeWithCallback; import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.Labels; import io.prometheus.metrics.model.snapshots.Unit; import java.lang.management.BufferPoolMXBean; import java.lang.management.ManagementFactory; @@ -48,11 +49,13 @@ public class JvmBufferPoolMetrics { private final PrometheusProperties config; private final List bufferPoolBeans; + private final Labels constLabels; private JvmBufferPoolMetrics( - List bufferPoolBeans, PrometheusProperties config) { + List bufferPoolBeans, PrometheusProperties config, Labels constLabels) { this.config = config; this.bufferPoolBeans = bufferPoolBeans; + this.constLabels = constLabels; } private void register(PrometheusRegistry registry) { @@ -68,6 +71,7 @@ private void register(PrometheusRegistry registry) { callback.call(pool.getMemoryUsed(), pool.getName()); } }) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -81,6 +85,7 @@ private void register(PrometheusRegistry registry) { callback.call(pool.getTotalCapacity(), pool.getName()); } }) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -93,6 +98,7 @@ private void register(PrometheusRegistry registry) { callback.call(pool.getCount(), pool.getName()); } }) + .constLabels(constLabels) .register(registry); } @@ -108,11 +114,17 @@ public static class Builder { private final PrometheusProperties config; @Nullable private List bufferPoolBeans; + private Labels constLabels = Labels.EMPTY; private Builder(PrometheusProperties config) { this.config = config; } + public Builder constLabels(Labels constLabels) { + this.constLabels = constLabels; + return this; + } + /** Package private. For testing only. */ Builder bufferPoolBeans(List bufferPoolBeans) { this.bufferPoolBeans = bufferPoolBeans; @@ -128,7 +140,7 @@ public void register(PrometheusRegistry registry) { if (bufferPoolBeans == null) { bufferPoolBeans = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class); } - new JvmBufferPoolMetrics(bufferPoolBeans, config).register(registry); + new JvmBufferPoolMetrics(bufferPoolBeans, config, constLabels).register(registry); } } } diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmClassLoadingMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmClassLoadingMetrics.java index bc0465a87..34e9dcb8a 100644 --- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmClassLoadingMetrics.java +++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmClassLoadingMetrics.java @@ -4,6 +4,7 @@ import io.prometheus.metrics.core.metrics.CounterWithCallback; import io.prometheus.metrics.core.metrics.GaugeWithCallback; import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.Labels; import java.lang.management.ClassLoadingMXBean; import java.lang.management.ManagementFactory; import javax.annotation.Nullable; @@ -44,10 +45,13 @@ public class JvmClassLoadingMetrics { private final PrometheusProperties config; private final ClassLoadingMXBean classLoadingBean; + private final Labels constLabels; - private JvmClassLoadingMetrics(ClassLoadingMXBean classLoadingBean, PrometheusProperties config) { + private JvmClassLoadingMetrics( + ClassLoadingMXBean classLoadingBean, PrometheusProperties config, Labels constLabels) { this.classLoadingBean = classLoadingBean; this.config = config; + this.constLabels = constLabels; } private void register(PrometheusRegistry registry) { @@ -56,6 +60,7 @@ private void register(PrometheusRegistry registry) { .name(JVM_CLASSES_CURRENTLY_LOADED) .help("The number of classes that are currently loaded in the JVM") .callback(callback -> callback.call(classLoadingBean.getLoadedClassCount())) + .constLabels(constLabels) .register(registry); CounterWithCallback.builder(config) @@ -63,6 +68,7 @@ private void register(PrometheusRegistry registry) { .help( "The total number of classes that have been loaded since the JVM has started execution") .callback(callback -> callback.call(classLoadingBean.getTotalLoadedClassCount())) + .constLabels(constLabels) .register(registry); CounterWithCallback.builder(config) @@ -71,6 +77,7 @@ private void register(PrometheusRegistry registry) { "The total number of classes that have been unloaded since the JVM has " + "started execution") .callback(callback -> callback.call(classLoadingBean.getUnloadedClassCount())) + .constLabels(constLabels) .register(registry); } @@ -86,11 +93,17 @@ public static class Builder { private final PrometheusProperties config; @Nullable private ClassLoadingMXBean classLoadingBean; + private Labels constLabels = Labels.EMPTY; private Builder(PrometheusProperties config) { this.config = config; } + public Builder constLabels(Labels constLabels) { + this.constLabels = constLabels; + return this; + } + /** Package private. For testing only. */ Builder classLoadingBean(ClassLoadingMXBean classLoadingBean) { this.classLoadingBean = classLoadingBean; @@ -106,7 +119,7 @@ public void register(PrometheusRegistry registry) { this.classLoadingBean != null ? this.classLoadingBean : ManagementFactory.getClassLoadingMXBean(); - new JvmClassLoadingMetrics(classLoadingBean, config).register(registry); + new JvmClassLoadingMetrics(classLoadingBean, config, constLabels).register(registry); } } } diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmCompilationMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmCompilationMetrics.java index dfde6c539..975b6c6a3 100644 --- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmCompilationMetrics.java +++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmCompilationMetrics.java @@ -5,6 +5,7 @@ import io.prometheus.metrics.config.PrometheusProperties; import io.prometheus.metrics.core.metrics.CounterWithCallback; import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.Labels; import io.prometheus.metrics.model.snapshots.Unit; import java.lang.management.CompilationMXBean; import java.lang.management.ManagementFactory; @@ -39,10 +40,13 @@ public class JvmCompilationMetrics { private final PrometheusProperties config; private final CompilationMXBean compilationBean; + private final Labels constLabels; - private JvmCompilationMetrics(CompilationMXBean compilationBean, PrometheusProperties config) { + private JvmCompilationMetrics( + CompilationMXBean compilationBean, PrometheusProperties config, Labels constLabels) { this.compilationBean = compilationBean; this.config = config; + this.constLabels = constLabels; } private void register(PrometheusRegistry registry) { @@ -57,6 +61,7 @@ private void register(PrometheusRegistry registry) { .unit(Unit.SECONDS) .callback( callback -> callback.call(millisToSeconds(compilationBean.getTotalCompilationTime()))) + .constLabels(constLabels) .register(registry); } @@ -72,11 +77,17 @@ public static class Builder { private final PrometheusProperties config; @Nullable private CompilationMXBean compilationBean; + private Labels constLabels = Labels.EMPTY; private Builder(PrometheusProperties config) { this.config = config; } + public Builder constLabels(Labels constLabels) { + this.constLabels = constLabels; + return this; + } + /** Package private. For testing only. */ Builder compilationBean(CompilationMXBean compilationBean) { this.compilationBean = compilationBean; @@ -92,7 +103,7 @@ public void register(PrometheusRegistry registry) { this.compilationBean != null ? this.compilationBean : ManagementFactory.getCompilationMXBean(); - new JvmCompilationMetrics(compilationBean, config).register(registry); + new JvmCompilationMetrics(compilationBean, config, constLabels).register(registry); } } } diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmGarbageCollectorMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmGarbageCollectorMetrics.java index 262e2df5f..a87b52a4f 100644 --- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmGarbageCollectorMetrics.java +++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmGarbageCollectorMetrics.java @@ -3,6 +3,7 @@ import io.prometheus.metrics.config.PrometheusProperties; import io.prometheus.metrics.core.metrics.SummaryWithCallback; import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.Labels; import io.prometheus.metrics.model.snapshots.Quantiles; import io.prometheus.metrics.model.snapshots.Unit; import java.lang.management.GarbageCollectorMXBean; @@ -42,11 +43,15 @@ public class JvmGarbageCollectorMetrics { private final PrometheusProperties config; private final List garbageCollectorBeans; + private final Labels constLabels; private JvmGarbageCollectorMetrics( - List garbageCollectorBeans, PrometheusProperties config) { + List garbageCollectorBeans, + PrometheusProperties config, + Labels constLabels) { this.config = config; this.garbageCollectorBeans = garbageCollectorBeans; + this.constLabels = constLabels; } private void register(PrometheusRegistry registry) { @@ -66,6 +71,7 @@ private void register(PrometheusRegistry registry) { gc.getName()); } }) + .constLabels(constLabels) .register(registry); } @@ -81,11 +87,17 @@ public static class Builder { private final PrometheusProperties config; @Nullable private List garbageCollectorBeans; + private Labels constLabels = Labels.EMPTY; private Builder(PrometheusProperties config) { this.config = config; } + public Builder constLabels(Labels constLabels) { + this.constLabels = constLabels; + return this; + } + /** Package private. For testing only. */ Builder garbageCollectorBeans(List garbageCollectorBeans) { this.garbageCollectorBeans = garbageCollectorBeans; @@ -101,7 +113,7 @@ public void register(PrometheusRegistry registry) { if (garbageCollectorBeans == null) { garbageCollectorBeans = ManagementFactory.getGarbageCollectorMXBeans(); } - new JvmGarbageCollectorMetrics(garbageCollectorBeans, config).register(registry); + new JvmGarbageCollectorMetrics(garbageCollectorBeans, config, constLabels).register(registry); } } } diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryMetrics.java index cecfe3c8a..1b34dba6c 100644 --- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryMetrics.java +++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryMetrics.java @@ -3,6 +3,7 @@ import io.prometheus.metrics.config.PrometheusProperties; import io.prometheus.metrics.core.metrics.GaugeWithCallback; import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.Labels; import io.prometheus.metrics.model.snapshots.Unit; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; @@ -127,12 +128,17 @@ public class JvmMemoryMetrics { private final PrometheusProperties config; private final MemoryMXBean memoryBean; private final List poolBeans; + private final Labels constLabels; private JvmMemoryMetrics( - List poolBeans, MemoryMXBean memoryBean, PrometheusProperties config) { + List poolBeans, + MemoryMXBean memoryBean, + PrometheusProperties config, + Labels constLabels) { this.config = config; this.poolBeans = poolBeans; this.memoryBean = memoryBean; + this.constLabels = constLabels; } private void register(PrometheusRegistry registry) { @@ -141,6 +147,7 @@ private void register(PrometheusRegistry registry) { .name(JVM_MEMORY_OBJECTS_PENDING_FINALIZATION) .help("The number of objects waiting in the finalizer queue.") .callback(callback -> callback.call(memoryBean.getObjectPendingFinalizationCount())) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -153,6 +160,7 @@ private void register(PrometheusRegistry registry) { callback.call(memoryBean.getHeapMemoryUsage().getUsed(), "heap"); callback.call(memoryBean.getNonHeapMemoryUsage().getUsed(), "nonheap"); }) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -165,6 +173,7 @@ private void register(PrometheusRegistry registry) { callback.call(memoryBean.getHeapMemoryUsage().getCommitted(), "heap"); callback.call(memoryBean.getNonHeapMemoryUsage().getCommitted(), "nonheap"); }) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -177,6 +186,7 @@ private void register(PrometheusRegistry registry) { callback.call(memoryBean.getHeapMemoryUsage().getMax(), "heap"); callback.call(memoryBean.getNonHeapMemoryUsage().getMax(), "nonheap"); }) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -189,6 +199,7 @@ private void register(PrometheusRegistry registry) { callback.call(memoryBean.getHeapMemoryUsage().getInit(), "heap"); callback.call(memoryBean.getNonHeapMemoryUsage().getInit(), "nonheap"); }) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -197,6 +208,7 @@ private void register(PrometheusRegistry registry) { .unit(Unit.BYTES) .labelNames("pool") .callback(makeCallback(poolBeans, MemoryPoolMXBean::getUsage, MemoryUsage::getUsed)) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -205,6 +217,7 @@ private void register(PrometheusRegistry registry) { .unit(Unit.BYTES) .labelNames("pool") .callback(makeCallback(poolBeans, MemoryPoolMXBean::getUsage, MemoryUsage::getCommitted)) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -213,6 +226,7 @@ private void register(PrometheusRegistry registry) { .unit(Unit.BYTES) .labelNames("pool") .callback(makeCallback(poolBeans, MemoryPoolMXBean::getUsage, MemoryUsage::getMax)) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -221,6 +235,7 @@ private void register(PrometheusRegistry registry) { .unit(Unit.BYTES) .labelNames("pool") .callback(makeCallback(poolBeans, MemoryPoolMXBean::getUsage, MemoryUsage::getInit)) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -230,6 +245,7 @@ private void register(PrometheusRegistry registry) { .labelNames("pool") .callback( makeCallback(poolBeans, MemoryPoolMXBean::getCollectionUsage, MemoryUsage::getUsed)) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -240,6 +256,7 @@ private void register(PrometheusRegistry registry) { .callback( makeCallback( poolBeans, MemoryPoolMXBean::getCollectionUsage, MemoryUsage::getCommitted)) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -249,6 +266,7 @@ private void register(PrometheusRegistry registry) { .labelNames("pool") .callback( makeCallback(poolBeans, MemoryPoolMXBean::getCollectionUsage, MemoryUsage::getMax)) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -258,6 +276,7 @@ private void register(PrometheusRegistry registry) { .labelNames("pool") .callback( makeCallback(poolBeans, MemoryPoolMXBean::getCollectionUsage, MemoryUsage::getInit)) + .constLabels(constLabels) .register(registry); } @@ -288,11 +307,17 @@ public static class Builder { private final PrometheusProperties config; @Nullable private MemoryMXBean memoryBean; @Nullable private List poolBeans; + private Labels constLabels = Labels.EMPTY; private Builder(PrometheusProperties config) { this.config = config; } + public Builder constLabels(Labels constLabels) { + this.constLabels = constLabels; + return this; + } + /** Package private. For testing only. */ Builder withMemoryBean(MemoryMXBean memoryBean) { this.memoryBean = memoryBean; @@ -314,7 +339,7 @@ public void register(PrometheusRegistry registry) { this.memoryBean != null ? this.memoryBean : ManagementFactory.getMemoryMXBean(); List poolBeans = this.poolBeans != null ? this.poolBeans : ManagementFactory.getMemoryPoolMXBeans(); - new JvmMemoryMetrics(poolBeans, bean, config).register(registry); + new JvmMemoryMetrics(poolBeans, bean, config, constLabels).register(registry); } } } diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryPoolAllocationMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryPoolAllocationMetrics.java index 160469b8b..5dfb4199b 100644 --- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryPoolAllocationMetrics.java +++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryPoolAllocationMetrics.java @@ -5,6 +5,7 @@ import io.prometheus.metrics.config.PrometheusProperties; import io.prometheus.metrics.core.metrics.Counter; import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.Labels; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; import java.lang.management.MemoryUsage; @@ -52,9 +53,12 @@ public class JvmMemoryPoolAllocationMetrics { "jvm_memory_pool_allocated_bytes_total"; private final List garbageCollectorBeans; + private final Labels constLabels; - private JvmMemoryPoolAllocationMetrics(List garbageCollectorBeans) { + private JvmMemoryPoolAllocationMetrics( + List garbageCollectorBeans, Labels constLabels) { this.garbageCollectorBeans = garbageCollectorBeans; + this.constLabels = constLabels; } private void register(PrometheusRegistry registry) { @@ -65,6 +69,7 @@ private void register(PrometheusRegistry registry) { "Total bytes allocated in a given JVM memory pool. Only updated after GC, " + "not continuously.") .labelNames("pool") + .constLabels(constLabels) .register(registry); AllocationCountingNotificationListener listener = @@ -152,9 +157,15 @@ public static Builder builder(PrometheusProperties config) { public static class Builder { @Nullable private List garbageCollectorBeans; + private Labels constLabels = Labels.EMPTY; private Builder() {} + public Builder constLabels(Labels constLabels) { + this.constLabels = constLabels; + return this; + } + /** Package private. For testing only. */ Builder withGarbageCollectorBeans(List garbageCollectorBeans) { this.garbageCollectorBeans = garbageCollectorBeans; @@ -170,7 +181,7 @@ public void register(PrometheusRegistry registry) { if (garbageCollectorBeans == null) { garbageCollectorBeans = ManagementFactory.getGarbageCollectorMXBeans(); } - new JvmMemoryPoolAllocationMetrics(garbageCollectorBeans).register(registry); + new JvmMemoryPoolAllocationMetrics(garbageCollectorBeans, constLabels).register(registry); } } } diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMetrics.java index 0f5a56eee..b0abd86b1 100644 --- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMetrics.java +++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMetrics.java @@ -2,6 +2,7 @@ import io.prometheus.metrics.config.PrometheusProperties; import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.Labels; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -32,11 +33,18 @@ public static Builder builder(PrometheusProperties config) { public static class Builder { private final PrometheusProperties config; + private Labels constLabels = Labels.EMPTY; private Builder(PrometheusProperties config) { this.config = config; } + /** Set constant labels that will be applied to all JVM metrics registered by this builder. */ + public Builder constLabels(Labels constLabels) { + this.constLabels = constLabels; + return this; + } + /** * Register all JVM metrics with the default registry. * @@ -55,16 +63,16 @@ public void register() { */ public void register(PrometheusRegistry registry) { if (REGISTERED.add(registry)) { - JvmThreadsMetrics.builder(config).register(registry); - JvmBufferPoolMetrics.builder(config).register(registry); - JvmClassLoadingMetrics.builder(config).register(registry); - JvmCompilationMetrics.builder(config).register(registry); - JvmGarbageCollectorMetrics.builder(config).register(registry); - JvmMemoryPoolAllocationMetrics.builder(config).register(registry); - JvmMemoryMetrics.builder(config).register(registry); - JvmNativeMemoryMetrics.builder(config).register(registry); - JvmRuntimeInfoMetric.builder(config).register(registry); - ProcessMetrics.builder(config).register(registry); + JvmThreadsMetrics.builder(config).constLabels(constLabels).register(registry); + JvmBufferPoolMetrics.builder(config).constLabels(constLabels).register(registry); + JvmClassLoadingMetrics.builder(config).constLabels(constLabels).register(registry); + JvmCompilationMetrics.builder(config).constLabels(constLabels).register(registry); + JvmGarbageCollectorMetrics.builder(config).constLabels(constLabels).register(registry); + JvmMemoryPoolAllocationMetrics.builder(config).constLabels(constLabels).register(registry); + JvmMemoryMetrics.builder(config).constLabels(constLabels).register(registry); + JvmNativeMemoryMetrics.builder(config).constLabels(constLabels).register(registry); + JvmRuntimeInfoMetric.builder(config).constLabels(constLabels).register(registry); + ProcessMetrics.builder(config).constLabels(constLabels).register(registry); } } } diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmNativeMemoryMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmNativeMemoryMetrics.java index 53225edca..6b11df38a 100644 --- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmNativeMemoryMetrics.java +++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmNativeMemoryMetrics.java @@ -3,6 +3,7 @@ import io.prometheus.metrics.config.PrometheusProperties; import io.prometheus.metrics.core.metrics.GaugeWithCallback; import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.Labels; import io.prometheus.metrics.model.snapshots.Unit; import java.lang.management.ManagementFactory; import java.util.concurrent.atomic.AtomicBoolean; @@ -97,10 +98,13 @@ public class JvmNativeMemoryMetrics { private final PrometheusProperties config; private final PlatformMBeanServerAdapter adapter; + private final Labels constLabels; - private JvmNativeMemoryMetrics(PrometheusProperties config, PlatformMBeanServerAdapter adapter) { + private JvmNativeMemoryMetrics( + PrometheusProperties config, PlatformMBeanServerAdapter adapter, Labels constLabels) { this.config = config; this.adapter = adapter; + this.constLabels = constLabels; } private void register(PrometheusRegistry registry) { @@ -115,6 +119,7 @@ private void register(PrometheusRegistry registry) { .unit(Unit.BYTES) .labelNames("pool") .callback(makeCallback(true)) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -125,6 +130,7 @@ private void register(PrometheusRegistry registry) { .unit(Unit.BYTES) .labelNames("pool") .callback(makeCallback(false)) + .constLabels(constLabels) .register(registry); } } @@ -157,8 +163,8 @@ private String vmNativeMemorySummaryInBytesOrEmpty() { } else { return summary; } - } catch (Exception ex) { - // ignore errors + } catch (RuntimeException ex) { + // ignore errors (native memory tracking not enabled or other runtime failures) isEnabled.set(false); return ""; } @@ -200,6 +206,7 @@ public static class Builder { private final PrometheusProperties config; private final PlatformMBeanServerAdapter adapter; + private Labels constLabels = Labels.EMPTY; private Builder(PrometheusProperties config) { this(config, new DefaultPlatformMBeanServerAdapter()); @@ -211,12 +218,17 @@ private Builder(PrometheusProperties config) { this.adapter = adapter; } + public Builder constLabels(Labels constLabels) { + this.constLabels = constLabels; + return this; + } + public void register() { register(PrometheusRegistry.defaultRegistry); } public void register(PrometheusRegistry registry) { - new JvmNativeMemoryMetrics(config, adapter).register(registry); + new JvmNativeMemoryMetrics(config, adapter, constLabels).register(registry); } } } diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmRuntimeInfoMetric.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmRuntimeInfoMetric.java index 5ebd61c21..58363780f 100644 --- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmRuntimeInfoMetric.java +++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmRuntimeInfoMetric.java @@ -3,6 +3,7 @@ import io.prometheus.metrics.config.PrometheusProperties; import io.prometheus.metrics.core.metrics.Info; import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.Labels; import javax.annotation.Nullable; /** @@ -33,13 +34,19 @@ public class JvmRuntimeInfoMetric { private final String version; private final String vendor; private final String runtime; + private final Labels constLabels; private JvmRuntimeInfoMetric( - String version, String vendor, String runtime, PrometheusProperties config) { + String version, + String vendor, + String runtime, + PrometheusProperties config, + Labels constLabels) { this.config = config; this.version = version; this.vendor = vendor; this.runtime = runtime; + this.constLabels = constLabels; } private void register(PrometheusRegistry registry) { @@ -49,6 +56,7 @@ private void register(PrometheusRegistry registry) { .name(JVM_RUNTIME_INFO) .help("JVM runtime info") .labelNames("version", "vendor", "runtime") + .constLabels(constLabels) .register(registry); jvmInfo.setLabelValues(version, vendor, runtime); @@ -68,11 +76,17 @@ public static class Builder { @Nullable private String version; @Nullable private String vendor; @Nullable private String runtime; + private Labels constLabels = Labels.EMPTY; private Builder(PrometheusProperties config) { this.config = config; } + public Builder constLabels(Labels constLabels) { + this.constLabels = constLabels; + return this; + } + /** Package private. For testing only. */ Builder version(String version) { this.version = version; @@ -104,7 +118,7 @@ public void register(PrometheusRegistry registry) { this.vendor != null ? this.vendor : System.getProperty("java.vm.vendor", "unknown"); String runtime = this.runtime != null ? this.runtime : System.getProperty("java.runtime.name", "unknown"); - new JvmRuntimeInfoMetric(version, vendor, runtime, config).register(registry); + new JvmRuntimeInfoMetric(version, vendor, runtime, config, constLabels).register(registry); } } } diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java index d3c69795e..0e98e29d3 100644 --- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java +++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java @@ -6,6 +6,7 @@ import io.prometheus.metrics.core.metrics.CounterWithCallback; import io.prometheus.metrics.core.metrics.GaugeWithCallback; import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.Labels; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; @@ -74,12 +75,17 @@ public class JvmThreadsMetrics { private final PrometheusProperties config; private final ThreadMXBean threadBean; private final boolean isNativeImage; + private final Labels constLabels; private JvmThreadsMetrics( - boolean isNativeImage, ThreadMXBean threadBean, PrometheusProperties config) { + boolean isNativeImage, + ThreadMXBean threadBean, + PrometheusProperties config, + Labels constLabels) { this.config = config; this.threadBean = threadBean; this.isNativeImage = isNativeImage; + this.constLabels = constLabels; } private void register(PrometheusRegistry registry) { @@ -88,24 +94,28 @@ private void register(PrometheusRegistry registry) { .name(JVM_THREADS_CURRENT) .help("Current thread count of a JVM") .callback(callback -> callback.call(threadBean.getThreadCount())) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) .name(JVM_THREADS_DAEMON) .help("Daemon thread count of a JVM") .callback(callback -> callback.call(threadBean.getDaemonThreadCount())) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) .name(JVM_THREADS_PEAK) .help("Peak thread count of a JVM") .callback(callback -> callback.call(threadBean.getPeakThreadCount())) + .constLabels(constLabels) .register(registry); CounterWithCallback.builder(config) .name(JVM_THREADS_STARTED_TOTAL) .help("Started thread count of a JVM") .callback(callback -> callback.call(threadBean.getTotalStartedThreadCount())) + .constLabels(constLabels) .register(registry); if (!isNativeImage) { @@ -116,6 +126,7 @@ private void register(PrometheusRegistry registry) { + "ownable synchronizers") .callback( callback -> callback.call(nullSafeArrayLength(threadBean.findDeadlockedThreads()))) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -124,6 +135,7 @@ private void register(PrometheusRegistry registry) { .callback( callback -> callback.call(nullSafeArrayLength(threadBean.findMonitorDeadlockedThreads()))) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -137,6 +149,7 @@ private void register(PrometheusRegistry registry) { callback.call(entry.getValue(), entry.getKey()); } }) + .constLabels(constLabels) .register(registry); } } @@ -196,11 +209,17 @@ public static class Builder { private final PrometheusProperties config; @Nullable private Boolean isNativeImage; @Nullable private ThreadMXBean threadBean; + private Labels constLabels = Labels.EMPTY; private Builder(PrometheusProperties config) { this.config = config; } + public Builder constLabels(Labels constLabels) { + this.constLabels = constLabels; + return this; + } + /** Package private. For testing only. */ Builder threadBean(ThreadMXBean threadBean) { this.threadBean = threadBean; @@ -222,7 +241,7 @@ public void register(PrometheusRegistry registry) { this.threadBean != null ? this.threadBean : ManagementFactory.getThreadMXBean(); boolean isNativeImage = this.isNativeImage != null ? this.isNativeImage : NativeImageChecker.isGraalVmNativeImage; - new JvmThreadsMetrics(isNativeImage, threadBean, config).register(registry); + new JvmThreadsMetrics(isNativeImage, threadBean, config, constLabels).register(registry); } } } diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/ProcessMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/ProcessMetrics.java index e3363c868..b341f848a 100644 --- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/ProcessMetrics.java +++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/ProcessMetrics.java @@ -4,6 +4,7 @@ import io.prometheus.metrics.core.metrics.CounterWithCallback; import io.prometheus.metrics.core.metrics.GaugeWithCallback; import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.Labels; import io.prometheus.metrics.model.snapshots.Unit; import java.io.BufferedReader; import java.io.File; @@ -82,17 +83,20 @@ public class ProcessMetrics { private final RuntimeMXBean runtimeBean; private final Grepper grepper; private final boolean linux; + private final Labels constLabels; private ProcessMetrics( OperatingSystemMXBean osBean, RuntimeMXBean runtimeBean, Grepper grepper, - PrometheusProperties config) { + PrometheusProperties config, + Labels constLabels) { this.osBean = osBean; this.runtimeBean = runtimeBean; this.grepper = grepper; this.config = config; this.linux = PROC_SELF_STATUS.canRead(); + this.constLabels = constLabels; } private void register(PrometheusRegistry registry) { @@ -118,6 +122,7 @@ private void register(PrometheusRegistry registry) { // Ignored } }) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -125,6 +130,7 @@ private void register(PrometheusRegistry registry) { .help("Start time of the process since unix epoch in seconds.") .unit(Unit.SECONDS) .callback(callback -> callback.call(Unit.millisToSeconds(runtimeBean.getStartTime()))) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -141,6 +147,7 @@ private void register(PrometheusRegistry registry) { // Ignored } }) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -157,6 +164,7 @@ private void register(PrometheusRegistry registry) { // Ignored } }) + .constLabels(constLabels) .register(registry); if (linux) { @@ -174,6 +182,7 @@ private void register(PrometheusRegistry registry) { // Ignored } }) + .constLabels(constLabels) .register(registry); GaugeWithCallback.builder(config) @@ -189,6 +198,7 @@ private void register(PrometheusRegistry registry) { // Ignored } }) + .constLabels(constLabels) .register(registry); } } @@ -275,6 +285,7 @@ public static class Builder { @Nullable private OperatingSystemMXBean osBean; @Nullable private RuntimeMXBean runtimeBean; @Nullable private Grepper grepper; + private Labels constLabels = Labels.EMPTY; private Builder(PrometheusProperties config) { this.config = config; @@ -298,6 +309,11 @@ Builder grepper(Grepper grepper) { return this; } + public Builder constLabels(Labels constLabels) { + this.constLabels = constLabels; + return this; + } + public void register() { register(PrometheusRegistry.defaultRegistry); } @@ -308,7 +324,7 @@ public void register(PrometheusRegistry registry) { RuntimeMXBean bean = this.runtimeBean != null ? this.runtimeBean : ManagementFactory.getRuntimeMXBean(); Grepper grepper = this.grepper != null ? this.grepper : new FileGrepper(); - new ProcessMetrics(osBean, bean, grepper, config).register(registry); + new ProcessMetrics(osBean, bean, grepper, config, constLabels).register(registry); } } } diff --git a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmBufferPoolMetricsTest.java b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmBufferPoolMetricsTest.java index e3bf55fb4..5b320c678 100644 --- a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmBufferPoolMetricsTest.java +++ b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmBufferPoolMetricsTest.java @@ -22,7 +22,7 @@ class JvmBufferPoolMetricsTest { private final BufferPoolMXBean mappedBuffer = Mockito.mock(BufferPoolMXBean.class); @BeforeEach - public void setUp() { + void setUp() { when(directBuffer.getName()).thenReturn("direct"); when(directBuffer.getCount()).thenReturn(2L); when(directBuffer.getMemoryUsed()).thenReturn(1234L); @@ -34,7 +34,7 @@ public void setUp() { } @Test - public void testGoodCase() throws IOException { + void testGoodCase() throws IOException { PrometheusRegistry registry = new PrometheusRegistry(); JvmBufferPoolMetrics.builder() .bufferPoolBeans(Arrays.asList(mappedBuffer, directBuffer)) @@ -64,7 +64,7 @@ public void testGoodCase() throws IOException { } @Test - public void testIgnoredMetricNotScraped() { + void testIgnoredMetricNotScraped() { MetricNameFilter filter = MetricNameFilter.builder().nameMustNotBeEqualTo("jvm_buffer_pool_used_bytes").build(); diff --git a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmClassLoadingMetricsTest.java b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmClassLoadingMetricsTest.java index ac13ab382..7fe86c753 100644 --- a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmClassLoadingMetricsTest.java +++ b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmClassLoadingMetricsTest.java @@ -20,14 +20,14 @@ class JvmClassLoadingMetricsTest { private final ClassLoadingMXBean mockClassLoadingBean = Mockito.mock(ClassLoadingMXBean.class); @BeforeEach - public void setUp() { + void setUp() { when(mockClassLoadingBean.getLoadedClassCount()).thenReturn(1000); when(mockClassLoadingBean.getTotalLoadedClassCount()).thenReturn(2000L); when(mockClassLoadingBean.getUnloadedClassCount()).thenReturn(500L); } @Test - public void testGoodCase() throws IOException { + void testGoodCase() throws IOException { PrometheusRegistry registry = new PrometheusRegistry(); JvmClassLoadingMetrics.builder().classLoadingBean(mockClassLoadingBean).register(registry); MetricSnapshots snapshots = registry.scrape(); @@ -50,7 +50,7 @@ public void testGoodCase() throws IOException { } @Test - public void testIgnoredMetricNotScraped() { + void testIgnoredMetricNotScraped() { MetricNameFilter filter = MetricNameFilter.builder().nameMustNotBeEqualTo("jvm_classes_currently_loaded").build(); diff --git a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmCompilationMetricsTest.java b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmCompilationMetricsTest.java index 73d1a39df..e961d9394 100644 --- a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmCompilationMetricsTest.java +++ b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmCompilationMetricsTest.java @@ -20,13 +20,13 @@ class JvmCompilationMetricsTest { private final CompilationMXBean mockCompilationBean = Mockito.mock(CompilationMXBean.class); @BeforeEach - public void setUp() { + void setUp() { when(mockCompilationBean.getTotalCompilationTime()).thenReturn(10000L); when(mockCompilationBean.isCompilationTimeMonitoringSupported()).thenReturn(true); } @Test - public void testGoodCase() throws IOException { + void testGoodCase() throws IOException { PrometheusRegistry registry = new PrometheusRegistry(); JvmCompilationMetrics.builder().compilationBean(mockCompilationBean).register(registry); MetricSnapshots snapshots = registry.scrape(); @@ -44,7 +44,7 @@ public void testGoodCase() throws IOException { } @Test - public void testIgnoredMetricNotScraped() { + void testIgnoredMetricNotScraped() { MetricNameFilter filter = MetricNameFilter.builder() .nameMustNotBeEqualTo("jvm_compilation_time_seconds_total") diff --git a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmGarbageCollectorMetricsTest.java b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmGarbageCollectorMetricsTest.java index 177f29d2e..0f928ef34 100644 --- a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmGarbageCollectorMetricsTest.java +++ b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmGarbageCollectorMetricsTest.java @@ -23,7 +23,7 @@ class JvmGarbageCollectorMetricsTest { private final GarbageCollectorMXBean mockGcBean2 = Mockito.mock(GarbageCollectorMXBean.class); @BeforeEach - public void setUp() { + void setUp() { when(mockGcBean1.getName()).thenReturn("MyGC1"); when(mockGcBean1.getCollectionCount()).thenReturn(100L); when(mockGcBean1.getCollectionTime()).thenReturn(TimeUnit.SECONDS.toMillis(10)); @@ -33,7 +33,7 @@ public void setUp() { } @Test - public void testGoodCase() throws IOException { + void testGoodCase() throws IOException { PrometheusRegistry registry = new PrometheusRegistry(); JvmGarbageCollectorMetrics.builder() .garbageCollectorBeans(Arrays.asList(mockGcBean1, mockGcBean2)) @@ -56,7 +56,7 @@ public void testGoodCase() throws IOException { } @Test - public void testIgnoredMetricNotScraped() { + void testIgnoredMetricNotScraped() { MetricNameFilter filter = MetricNameFilter.builder().nameMustNotBeEqualTo("jvm_gc_collection_seconds").build(); diff --git a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryMetricsTest.java b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryMetricsTest.java index a79ec3b3b..b1916c064 100644 --- a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryMetricsTest.java +++ b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryMetricsTest.java @@ -32,7 +32,7 @@ class JvmMemoryMetricsTest { @SuppressWarnings("deprecation") @BeforeEach - public void setUp() { + void setUp() { when(mockMemoryBean.getHeapMemoryUsage()).thenReturn(memoryUsageHeap); when(mockMemoryBean.getNonHeapMemoryUsage()).thenReturn(memoryUsageNonHeap); @@ -80,7 +80,7 @@ public void setUp() { } @Test - public void testGoodCase() throws IOException { + void testGoodCase() throws IOException { PrometheusRegistry registry = new PrometheusRegistry(); JvmMemoryMetrics.builder() .withMemoryBean(mockMemoryBean) @@ -160,7 +160,7 @@ public void testGoodCase() throws IOException { } @Test - public void testIgnoredMetricNotScraped() { + void testIgnoredMetricNotScraped() { MetricNameFilter filter = MetricNameFilter.builder().nameMustNotBeEqualTo("jvm_memory_pool_used_bytes").build(); diff --git a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryPoolAllocationMetricsTest.java b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryPoolAllocationMetricsTest.java index 67dd6f2e6..2f681ce89 100644 --- a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryPoolAllocationMetricsTest.java +++ b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryPoolAllocationMetricsTest.java @@ -14,7 +14,7 @@ class JvmMemoryPoolAllocationMetricsTest { @Test - public void testListenerLogic() { + void testListenerLogic() { PrometheusRegistry registry = new PrometheusRegistry(); Counter counter = Counter.builder().name("test").labelNames("pool").register(registry); AllocationCountingNotificationListener listener = @@ -47,6 +47,10 @@ public void testListenerLogic() { // Decrease to 17, then increase by 3 listener.handleMemoryPool("TestPool", 17, 20); assertThat(getCountByPool("test", "TestPool", registry.scrape())).isEqualTo(153); + + // Edge case: before < last (tests diff1 < 0 branch) + listener.handleMemoryPool("TestPool", 10, 15); + assertThat(getCountByPool("test", "TestPool", registry.scrape())).isEqualTo(158); } private double getCountByPool(String metricName, String poolName, MetricSnapshots snapshots) { diff --git a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMetricsTest.java b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMetricsTest.java index 2bb908a37..c0553703d 100644 --- a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMetricsTest.java +++ b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmMetricsTest.java @@ -4,6 +4,10 @@ import io.prometheus.metrics.config.PrometheusProperties; import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.DataPointSnapshot; +import io.prometheus.metrics.model.snapshots.Labels; +import io.prometheus.metrics.model.snapshots.MetricSnapshot; +import io.prometheus.metrics.model.snapshots.MetricSnapshots; import java.lang.management.ManagementFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -16,7 +20,7 @@ void setUp() { } @Test - public void testRegisterIdempotent() { + void testRegisterIdempotent() { PrometheusRegistry registry = new PrometheusRegistry(); assertThat(registry.scrape().size()).isZero(); JvmMetrics.builder().register(registry); @@ -32,6 +36,25 @@ void pool() { .register(); } + @Test + void testConstLabelsApplied() { + PrometheusRegistry registry = new PrometheusRegistry(); + Labels labels = Labels.of("env", "dev"); + JvmMetrics.builder().constLabels(labels).register(registry); + MetricSnapshots snapshots = registry.scrape(); + boolean found = false; + for (MetricSnapshot snapshot : snapshots) { + for (DataPointSnapshot dp : snapshot.getDataPoints()) { + if ("dev".equals(dp.getLabels().get("env"))) { + found = true; + break; + } + } + if (found) break; + } + assertThat(found).isTrue(); + } + @Test void testJvmMetrics() { JvmMetrics.builder(PrometheusProperties.get()).register(); diff --git a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmNativeMemoryMetricsTest.java b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmNativeMemoryMetricsTest.java index bbf42ecc7..e2f2dcdca 100644 --- a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmNativeMemoryMetricsTest.java +++ b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmNativeMemoryMetricsTest.java @@ -14,7 +14,7 @@ class JvmNativeMemoryMetricsTest { @Test - public void testNativeMemoryTrackingFail() throws IOException { + void testNativeMemoryTrackingFail() throws IOException { JvmNativeMemoryMetrics.isEnabled.set(true); JvmNativeMemoryMetrics.PlatformMBeanServerAdapter adapter = @@ -39,7 +39,7 @@ void nativeMemoryTrackingNotEnabled() { } @Test - public void testNativeMemoryTrackingEmpty() throws IOException { + void testNativeMemoryTrackingEmpty() throws IOException { JvmNativeMemoryMetrics.isEnabled.set(true); JvmNativeMemoryMetrics.PlatformMBeanServerAdapter adapter = @@ -56,7 +56,7 @@ public void testNativeMemoryTrackingEmpty() throws IOException { } @Test - public void testNativeMemoryTrackingDisabled() throws IOException { + void testNativeMemoryTrackingDisabled() throws IOException { JvmNativeMemoryMetrics.isEnabled.set(true); JvmNativeMemoryMetrics.PlatformMBeanServerAdapter adapter = @@ -74,7 +74,7 @@ public void testNativeMemoryTrackingDisabled() throws IOException { } @Test - public void testNativeMemoryTrackingEnabled() throws IOException { + void testNativeMemoryTrackingEnabled() throws IOException { JvmNativeMemoryMetrics.isEnabled.set(true); JvmNativeMemoryMetrics.PlatformMBeanServerAdapter adapter = diff --git a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmRuntimeInfoMetricTest.java b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmRuntimeInfoMetricTest.java index a477065c9..2c6a2773f 100644 --- a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmRuntimeInfoMetricTest.java +++ b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmRuntimeInfoMetricTest.java @@ -11,7 +11,7 @@ class JvmRuntimeInfoMetricTest { @Test - public void testGoodCase() throws IOException { + void testGoodCase() throws IOException { PrometheusRegistry registry = new PrometheusRegistry(); JvmRuntimeInfoMetric.builder() .version("1.8.0_382-b05") diff --git a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetricsTest.java b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetricsTest.java index cd651cc7f..f001fad37 100644 --- a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetricsTest.java +++ b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetricsTest.java @@ -30,7 +30,7 @@ class JvmThreadsMetricsTest { private final ThreadInfo mockThreadInfoRunnable2 = Mockito.mock(ThreadInfo.class); @BeforeEach - public void setUp() { + void setUp() { when(mockThreadsBean.getThreadCount()).thenReturn(300); when(mockThreadsBean.getDaemonThreadCount()).thenReturn(200); when(mockThreadsBean.getPeakThreadCount()).thenReturn(301); @@ -49,7 +49,7 @@ public void setUp() { } @Test - public void testGoodCase() throws IOException { + void testGoodCase() throws IOException { PrometheusRegistry registry = new PrometheusRegistry(); JvmThreadsMetrics.builder().threadBean(mockThreadsBean).isNativeImage(false).register(registry); MetricSnapshots snapshots = registry.scrape(); @@ -90,7 +90,7 @@ public void testGoodCase() throws IOException { } @Test - public void testIgnoredMetricNotScraped() { + void testIgnoredMetricNotScraped() { MetricNameFilter filter = MetricNameFilter.builder().nameMustNotBeEqualTo("jvm_threads_deadlocked").build(); @@ -103,7 +103,7 @@ public void testIgnoredMetricNotScraped() { } @Test - public void testInvalidThreadIds() { + void testInvalidThreadIds() { try { String javaVersion = System.getProperty("java.version"); // Example: "21.0.2" String majorJavaVersion = javaVersion.replaceAll("\\..*", ""); // Example: "21" diff --git a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/ProcessMetricsTest.java b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/ProcessMetricsTest.java index f5804ad7f..9c2efd301 100644 --- a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/ProcessMetricsTest.java +++ b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/ProcessMetricsTest.java @@ -30,7 +30,7 @@ class ProcessMetricsTest { private final RuntimeMXBean runtimeBean = Mockito.mock(RuntimeMXBean.class); @BeforeEach - public void setUp() throws IOException { + void setUp() throws IOException { when(sunOsBean.getProcessCpuTime()).thenReturn(TimeUnit.MILLISECONDS.toNanos(72)); when(sunOsBean.getOpenFileDescriptorCount()).thenReturn(127L); when(sunOsBean.getMaxFileDescriptorCount()).thenReturn(244L); @@ -42,7 +42,7 @@ public void setUp() throws IOException { } @Test - public void testGoodCase() throws IOException { + void testGoodCase() throws IOException { PrometheusRegistry registry = new PrometheusRegistry(); ProcessMetrics.builder() .osBean(sunOsBean) @@ -97,7 +97,7 @@ public void testGoodCase() throws IOException { } @Test - public void testMinimal() throws IOException { + void testMinimal() throws IOException { PrometheusRegistry registry = new PrometheusRegistry(); ProcessMetrics.builder() .osBean(javaOsBean) @@ -119,7 +119,7 @@ public void testMinimal() throws IOException { } @Test - public void testIgnoredMetricNotScraped() { + void testIgnoredMetricNotScraped() { MetricNameFilter filter = MetricNameFilter.builder().nameMustNotBeEqualTo("process_max_fds").build(); diff --git a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/TestUtil.java b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/TestUtil.java index 64e15590c..8cdd6b1ae 100644 --- a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/TestUtil.java +++ b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/TestUtil.java @@ -7,7 +7,7 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; -class TestUtil { +public class TestUtil { static String convertToOpenMetricsFormat(MetricSnapshots snapshots) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); diff --git a/prometheus-metrics-model/pom.xml b/prometheus-metrics-model/pom.xml index 1919ee95c..ff07241ce 100644 --- a/prometheus-metrics-model/pom.xml +++ b/prometheus-metrics-model/pom.xml @@ -7,7 +7,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-model diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/Collector.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/Collector.java index b7154ae70..beca6001e 100644 --- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/Collector.java +++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/Collector.java @@ -1,6 +1,8 @@ package io.prometheus.metrics.model.registry; +import io.prometheus.metrics.model.snapshots.MetricMetadata; import io.prometheus.metrics.model.snapshots.MetricSnapshot; +import java.util.Set; import java.util.function.Predicate; import javax.annotation.Nullable; @@ -65,8 +67,8 @@ default MetricSnapshot collect( * and the metric name is excluded. * * - * Returning {@code null} means checks are omitted (registration the metric always succeeds), and - * the collector is always scraped (the result is dropped after scraping if a name filter is + *

Returning {@code null} means checks are omitted (registration the metric always succeeds), + * and the collector is always scraped (the result is dropped after scraping if a name filter is * present and the metric name is excluded). * *

If your metric has a name that does not change at runtime it is a good idea to overwrite @@ -78,4 +80,59 @@ default MetricSnapshot collect( default String getPrometheusName() { return null; } + + /** + * Returns the metric type for registration-time validation. + * + *

This is used to prevent different metric types (e.g., Counter and Gauge) from sharing the + * same name. Returning {@code null} means type validation is skipped for this collector. + * + *

Validation is performed only at registration time. If this method returns {@code null}, no + * type validation is performed for this collector, and duplicate or conflicting metrics may + * result in invalid exposition output. + * + * @return the metric type, or {@code null} to skip validation + */ + @Nullable + default MetricType getMetricType() { + return null; + } + + /** + * Returns the complete set of label names for this metric. + * + *

This includes both dynamic label names (specified in {@code labelNames()}) and constant + * label names (specified in {@code constLabels()}). Label names are normalized using Prometheus + * naming conventions. + * + *

This is used for registration-time validation to prevent duplicate label schemas for the + * same metric name. Two collectors with the same name and type can coexist if they have different + * label name sets. + * + *

Returning {@code null} is treated as an empty label set: the registry normalizes it to + * {@code Collections.emptySet()} and performs full label-schema validation and duplicate + * detection. Two collectors with the same name, type, and {@code null} (or empty) label names are + * considered duplicate and registration of the second will fail. + * + * @return the set of all label names, or {@code null} (treated as empty) for a metric with no + * labels + */ + @Nullable + default Set getLabelNames() { + return null; + } + + /** + * Returns the metric metadata (name, help, unit) for registration-time validation. + * + *

When non-null, the registry uses this to validate that metrics with the same name have + * consistent help and unit. Returning {@code null} means help/unit validation is skipped for this + * collector. + * + * @return the metric metadata, or {@code null} to skip help/unit validation + */ + @Nullable + default MetricMetadata getMetadata() { + return null; + } } diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MetricType.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MetricType.java new file mode 100644 index 000000000..5258da84e --- /dev/null +++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MetricType.java @@ -0,0 +1,18 @@ +package io.prometheus.metrics.model.registry; + +/** + * Represents the type of Prometheus metric. + * + *

This enum is used for registration-time validation to ensure that metrics with the same name + * have consistent types across all registered collectors. + */ +public enum MetricType { + COUNTER, + GAUGE, + HISTOGRAM, + SUMMARY, + INFO, + STATESET, + /** Unknown metric type, used as a fallback. */ + UNKNOWN +} diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MultiCollector.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MultiCollector.java index d1051958d..27ac3e10c 100644 --- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MultiCollector.java +++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MultiCollector.java @@ -1,9 +1,11 @@ package io.prometheus.metrics.model.registry; +import io.prometheus.metrics.model.snapshots.MetricMetadata; import io.prometheus.metrics.model.snapshots.MetricSnapshot; import io.prometheus.metrics.model.snapshots.MetricSnapshots; import java.util.Collections; import java.util.List; +import java.util.Set; import java.util.function.Predicate; import javax.annotation.Nullable; @@ -60,9 +62,9 @@ default MetricSnapshots collect( * and all names are excluded. * * - * Returning an empty list means checks are omitted (registration metric always succeeds), and the - * collector is always scraped (if a name filter is present and all names are excluded the result - * is dropped). + *

Returning an empty list means checks are omitted (registration metric always succeeds), and + * the collector is always scraped (if a name filter is present and all names are excluded the + * result is dropped). * *

If your collector returns a constant list of metrics that have names that do not change at * runtime it is a good idea to overwrite this and return the names. @@ -70,4 +72,60 @@ default MetricSnapshots collect( default List getPrometheusNames() { return Collections.emptyList(); } + + /** + * Returns the metric type for the given Prometheus name. + * + *

This is used for per-name type validation during registration. Returning {@code null} means + * type validation is skipped for that specific metric name. + * + *

Validation is performed only at registration time. If this method returns {@code null}, no + * type validation is performed for that name, and duplicate or conflicting metrics may result in + * invalid exposition output. + * + * @param prometheusName the Prometheus metric name + * @return the metric type for the given name, or {@code null} to skip validation + */ + @Nullable + default MetricType getMetricType(String prometheusName) { + return null; + } + + /** + * Returns the complete set of label names for the given Prometheus name. + * + *

This includes both dynamic label names and constant label names. Label names are normalized + * using Prometheus naming conventions (dots converted to underscores). + * + *

This is used for per-name label schema validation during registration. Two collectors with + * the same name and type can coexist if they have different label name sets. + * + *

Returning {@code null} is treated as an empty label set: the registry normalizes it to + * {@code Collections.emptySet()} and performs full label-schema validation and duplicate + * detection. Two collectors with the same name, type, and {@code null} (or empty) label names are + * considered duplicate and registration of the second will fail. + * + * @param prometheusName the Prometheus metric name + * @return the set of all label names for the given name, or {@code null} (treated as empty) for a + * metric with no labels + */ + @Nullable + default Set getLabelNames(String prometheusName) { + return null; + } + + /** + * Returns the metric metadata (name, help, unit) for the given Prometheus name. + * + *

When non-null, the registry uses this to validate that metrics with the same name have + * consistent help and unit. Returning {@code null} means help/unit validation is skipped for that + * name. + * + * @param prometheusName the Prometheus metric name + * @return the metric metadata for that name, or {@code null} to skip help/unit validation + */ + @Nullable + default MetricMetadata getMetadata(String prometheusName) { + return null; + } } diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/PrometheusRegistry.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/PrometheusRegistry.java index 7db568d95..f66824972 100644 --- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/PrometheusRegistry.java +++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/PrometheusRegistry.java @@ -1,13 +1,18 @@ package io.prometheus.metrics.model.registry; -import static io.prometheus.metrics.model.snapshots.PrometheusNaming.prometheusName; +import static java.util.Collections.emptySet; +import io.prometheus.metrics.model.snapshots.MetricMetadata; import io.prometheus.metrics.model.snapshots.MetricSnapshot; import io.prometheus.metrics.model.snapshots.MetricSnapshots; +import io.prometheus.metrics.model.snapshots.Unit; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Predicate; import javax.annotation.Nullable; @@ -15,52 +20,286 @@ public class PrometheusRegistry { public static final PrometheusRegistry defaultRegistry = new PrometheusRegistry(); - private final Set prometheusNames = ConcurrentHashMap.newKeySet(); - private final List collectors = new CopyOnWriteArrayList<>(); - private final List multiCollectors = new CopyOnWriteArrayList<>(); + private final Set collectors = ConcurrentHashMap.newKeySet(); + private final Set multiCollectors = ConcurrentHashMap.newKeySet(); + private final ConcurrentHashMap registered = new ConcurrentHashMap<>(); + private final ConcurrentHashMap collectorMetadata = + new ConcurrentHashMap<>(); + private final ConcurrentHashMap> + multiCollectorMetadata = new ConcurrentHashMap<>(); + + /** Stores the registration details for a Collector at registration time. */ + private static class CollectorRegistration { + final String prometheusName; + final Set labelNames; + + CollectorRegistration(String prometheusName, @Nullable Set labelNames) { + this.prometheusName = prometheusName; + this.labelNames = immutableLabelNames(labelNames); + } + } + + /** + * Stores the registration details for a single metric within a MultiCollector. A MultiCollector + * can produce multiple metrics, so we need one of these per metric name. + */ + private static class MultiCollectorRegistration { + final String prometheusName; + final Set labelNames; + + MultiCollectorRegistration(String prometheusName, @Nullable Set labelNames) { + this.prometheusName = prometheusName; + this.labelNames = immutableLabelNames(labelNames); + } + } + + /** + * Tracks registration information for each metric name to enable validation of type consistency, + * label schema uniqueness, and help/unit consistency. + */ + private static class RegistrationInfo { + private final MetricType type; + private final Set> labelSchemas; + @Nullable private String help; + @Nullable private Unit unit; + + private RegistrationInfo( + MetricType type, + Set> labelSchemas, + @Nullable String help, + @Nullable Unit unit) { + this.type = type; + this.labelSchemas = labelSchemas; + this.help = help; + this.unit = unit; + } + + static RegistrationInfo of( + MetricType type, + @Nullable Set labelNames, + @Nullable String help, + @Nullable Unit unit) { + Set> labelSchemas = ConcurrentHashMap.newKeySet(); + Set normalized = + (labelNames == null || labelNames.isEmpty()) ? emptySet() : labelNames; + labelSchemas.add(normalized); + return new RegistrationInfo(type, labelSchemas, help, unit); + } + + /** + * Validates that the given help and unit are exactly equal to this registration. Throws if + * values differ, including when one is null and the other is non-null. This ensures consistent + * metadata across all collectors sharing the same metric name. + */ + void validateMetadata(@Nullable String newHelp, @Nullable Unit newUnit) { + if (!Objects.equals(help, newHelp)) { + throw new IllegalArgumentException( + "Conflicting help strings. Existing: \"" + help + "\", new: \"" + newHelp + "\""); + } + if (!Objects.equals(unit, newUnit)) { + throw new IllegalArgumentException( + "Conflicting unit. Existing: " + unit + ", new: " + newUnit); + } + } + + /** + * Adds a label schema to this registration. + * + * @param labelNames the label names to add (null or empty sets are normalized to empty set) + * @return true if the schema was added (new), false if it already existed + */ + boolean addLabelSet(@Nullable Set labelNames) { + Set normalized = + (labelNames == null || labelNames.isEmpty()) ? emptySet() : labelNames; + return labelSchemas.add(normalized); + } + + /** + * Removes a label schema from this registration. + * + * @param labelNames the label names to remove (null or empty sets are normalized to empty set) + */ + void removeLabelSet(@Nullable Set labelNames) { + Set normalized = + (labelNames == null || labelNames.isEmpty()) ? emptySet() : labelNames; + labelSchemas.remove(normalized); + } + + /** Returns true if all label schemas have been unregistered. */ + boolean isEmpty() { + return labelSchemas.isEmpty(); + } + + MetricType getType() { + return type; + } + } + + /** + * Returns an immutable set of label names for storage. Defends against mutation of the set + * returned by {@code Collector.getLabelNames()} after registration, which would break duplicate + * detection and unregistration. + */ + private static Set immutableLabelNames(@Nullable Set labelNames) { + if (labelNames == null || labelNames.isEmpty()) { + return emptySet(); + } + return Collections.unmodifiableSet(new HashSet<>(labelNames)); + } + + /** + * Validates the registration of a metric with the given parameters. Ensures type consistency, + * label schema uniqueness, and help/unit consistency. + */ + private void validateRegistration( + String prometheusName, + MetricType metricType, + Set normalizedLabels, + @Nullable String help, + @Nullable Unit unit) { + final MetricType type = metricType; + final Set names = normalizedLabels; + final String helpForValidation = help; + final Unit unitForValidation = unit; + registered.compute( + prometheusName, + (n, existingInfo) -> { + if (existingInfo == null) { + return RegistrationInfo.of(type, names, helpForValidation, unitForValidation); + } else { + if (existingInfo.getType() != type) { + throw new IllegalArgumentException( + prometheusName + + ": Conflicting metric types. Existing: " + + existingInfo.getType() + + ", new: " + + type); + } + // Check label set first; only mutate help/unit after validation passes. + if (!existingInfo.addLabelSet(names)) { + throw new IllegalArgumentException( + prometheusName + ": duplicate metric name with identical label schema " + names); + } + // Roll back label schema if metadata validation fails + try { + existingInfo.validateMetadata(helpForValidation, unitForValidation); + } catch (IllegalArgumentException e) { + existingInfo.removeLabelSet(names); + throw e; + } + return existingInfo; + } + }); + } public void register(Collector collector) { - String prometheusName = collector.getPrometheusName(); - if (prometheusName != null) { - if (!prometheusNames.add(prometheusName)) { - throw new IllegalStateException( - "Can't register " - + prometheusName - + " because a metric with that name is already registered."); + if (!collectors.add(collector)) { + throw new IllegalArgumentException("Collector instance is already registered"); + } + try { + String prometheusName = collector.getPrometheusName(); + MetricType metricType = collector.getMetricType(); + Set normalizedLabels = immutableLabelNames(collector.getLabelNames()); + MetricMetadata metadata = collector.getMetadata(); + String help = metadata != null ? metadata.getHelp() : null; + Unit unit = metadata != null ? metadata.getUnit() : null; + + // Only perform validation if collector provides sufficient metadata. + // Collectors that don't implement getPrometheusName()/getMetricType() will skip validation. + if (prometheusName != null && metricType != null) { + validateRegistration(prometheusName, metricType, normalizedLabels, help, unit); + collectorMetadata.put( + collector, new CollectorRegistration(prometheusName, normalizedLabels)); } + // Catch RuntimeException broadly because collector methods (getPrometheusName, getMetricType, + // etc.) are user-implemented and could throw any RuntimeException. Ensures cleanup on + // failure. + } catch (RuntimeException e) { + collectors.remove(collector); + CollectorRegistration reg = collectorMetadata.remove(collector); + if (reg != null && reg.prometheusName != null) { + unregisterLabelSchema(reg.prometheusName, reg.labelNames); + } + throw e; } - collectors.add(collector); } public void register(MultiCollector collector) { - for (String prometheusName : collector.getPrometheusNames()) { - if (!prometheusNames.add(prometheusName)) { - throw new IllegalStateException( - "Can't register " + prometheusName + " because that name is already registered."); + if (!multiCollectors.add(collector)) { + throw new IllegalArgumentException("MultiCollector instance is already registered"); + } + List prometheusNamesList = collector.getPrometheusNames(); + List registrations = new ArrayList<>(); + + try { + for (String prometheusName : prometheusNamesList) { + MetricType metricType = collector.getMetricType(prometheusName); + Set normalizedLabels = immutableLabelNames(collector.getLabelNames(prometheusName)); + MetricMetadata metadata = collector.getMetadata(prometheusName); + String help = metadata != null ? metadata.getHelp() : null; + Unit unit = metadata != null ? metadata.getUnit() : null; + + if (metricType != null) { + validateRegistration(prometheusName, metricType, normalizedLabels, help, unit); + registrations.add(new MultiCollectorRegistration(prometheusName, normalizedLabels)); + } } + + multiCollectorMetadata.put(collector, registrations); + // Catch RuntimeException broadly because collector methods (getPrometheusNames, + // getMetricType, etc.) are user-implemented and could throw any RuntimeException. + // Ensures cleanup on failure. + } catch (RuntimeException e) { + multiCollectors.remove(collector); + for (MultiCollectorRegistration registration : registrations) { + unregisterLabelSchema(registration.prometheusName, registration.labelNames); + } + throw e; } - multiCollectors.add(collector); } public void unregister(Collector collector) { collectors.remove(collector); - String prometheusName = collector.getPrometheusName(); - if (prometheusName != null) { - prometheusNames.remove(collector.getPrometheusName()); + + CollectorRegistration registration = collectorMetadata.remove(collector); + if (registration != null && registration.prometheusName != null) { + unregisterLabelSchema(registration.prometheusName, registration.labelNames); } } public void unregister(MultiCollector collector) { multiCollectors.remove(collector); - for (String prometheusName : collector.getPrometheusNames()) { - prometheusNames.remove(prometheusName(prometheusName)); + + List registrations = multiCollectorMetadata.remove(collector); + if (registrations != null) { + for (MultiCollectorRegistration registration : registrations) { + unregisterLabelSchema(registration.prometheusName, registration.labelNames); + } } } + /** + * Removes the label schema for the given metric name. If no label schemas remain for that name, + * removes the metric name entirely from the registry. + */ + private void unregisterLabelSchema(String prometheusName, Set labelNames) { + registered.computeIfPresent( + prometheusName, + (name, info) -> { + info.removeLabelSet(labelNames); + if (info.isEmpty()) { + return null; + } + return info; + }); + } + public void clear() { collectors.clear(); multiCollectors.clear(); - prometheusNames.clear(); + registered.clear(); + collectorMetadata.clear(); + multiCollectorMetadata.clear(); } public MetricSnapshots scrape() { @@ -68,29 +307,26 @@ public MetricSnapshots scrape() { } public MetricSnapshots scrape(@Nullable PrometheusScrapeRequest scrapeRequest) { - MetricSnapshots.Builder result = MetricSnapshots.builder(); + List allSnapshots = new ArrayList<>(); for (Collector collector : collectors) { MetricSnapshot snapshot = scrapeRequest == null ? collector.collect() : collector.collect(scrapeRequest); if (snapshot != null) { - if (result.containsMetricName(snapshot.getMetadata().getName())) { - throw new IllegalStateException( - snapshot.getMetadata().getPrometheusName() + ": duplicate metric name."); - } - result.metricSnapshot(snapshot); + allSnapshots.add(snapshot); } } for (MultiCollector collector : multiCollectors) { MetricSnapshots snapshots = scrapeRequest == null ? collector.collect() : collector.collect(scrapeRequest); for (MetricSnapshot snapshot : snapshots) { - if (result.containsMetricName(snapshot.getMetadata().getName())) { - throw new IllegalStateException( - snapshot.getMetadata().getPrometheusName() + ": duplicate metric name."); - } - result.metricSnapshot(snapshot); + allSnapshots.add(snapshot); } } + + MetricSnapshots.Builder result = MetricSnapshots.builder(); + for (MetricSnapshot snapshot : allSnapshots) { + result.metricSnapshot(snapshot); + } return result.build(); } @@ -106,7 +342,7 @@ public MetricSnapshots scrape( if (includedNames == null) { return scrape(scrapeRequest); } - MetricSnapshots.Builder result = MetricSnapshots.builder(); + List allSnapshots = new ArrayList<>(); for (Collector collector : collectors) { String prometheusName = collector.getPrometheusName(); // prometheusName == null means the name is unknown, and we have to scrape to learn the name. @@ -117,7 +353,7 @@ public MetricSnapshots scrape( ? collector.collect(includedNames) : collector.collect(includedNames, scrapeRequest); if (snapshot != null) { - result.metricSnapshot(snapshot); + allSnapshots.add(snapshot); } } } @@ -141,11 +377,16 @@ public MetricSnapshots scrape( : collector.collect(includedNames, scrapeRequest); for (MetricSnapshot snapshot : snapshots) { if (snapshot != null) { - result.metricSnapshot(snapshot); + allSnapshots.add(snapshot); } } } } + + MetricSnapshots.Builder result = MetricSnapshots.builder(); + for (MetricSnapshot snapshot : allSnapshots) { + result.metricSnapshot(snapshot); + } return result.build(); } } diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/MetricSnapshots.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/MetricSnapshots.java index ecee897e4..cdec0ddaf 100644 --- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/MetricSnapshots.java +++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/MetricSnapshots.java @@ -28,23 +28,46 @@ public MetricSnapshots(MetricSnapshot... snapshots) { * #builder()}. * * @param snapshots the constructor creates a sorted copy of snapshots. - * @throws IllegalArgumentException if snapshots contains duplicate metric names. To avoid - * duplicate metric names use {@link #builder()} and check {@link - * Builder#containsMetricName(String)} before calling {@link - * Builder#metricSnapshot(MetricSnapshot)}. + * @throws IllegalArgumentException if snapshots contain conflicting metric types (same name but + * different metric types like Counter vs Gauge), or if two HistogramSnapshots share a name + * but differ in gauge histogram vs classic histogram. */ public MetricSnapshots(Collection snapshots) { List list = new ArrayList<>(snapshots); list.sort(comparing(s -> s.getMetadata().getPrometheusName())); - for (int i = 0; i < snapshots.size() - 1; i++) { - if (list.get(i) - .getMetadata() - .getPrometheusName() - .equals(list.get(i + 1).getMetadata().getPrometheusName())) { - throw new IllegalArgumentException( - list.get(i).getMetadata().getPrometheusName() + ": duplicate metric name"); + + // Validate no conflicting metric types + for (int i = 0; i < list.size() - 1; i++) { + String name1 = list.get(i).getMetadata().getPrometheusName(); + String name2 = list.get(i + 1).getMetadata().getPrometheusName(); + + if (name1.equals(name2)) { + MetricSnapshot s1 = list.get(i); + MetricSnapshot s2 = list.get(i + 1); + Class type1 = s1.getClass(); + Class type2 = s2.getClass(); + + if (!type1.equals(type2)) { + throw new IllegalArgumentException( + name1 + + ": conflicting metric types: " + + type1.getSimpleName() + + " and " + + type2.getSimpleName()); + } + + // HistogramSnapshot: gauge histogram vs classic histogram are semantically different + if (s1 instanceof HistogramSnapshot) { + HistogramSnapshot h1 = (HistogramSnapshot) s1; + HistogramSnapshot h2 = (HistogramSnapshot) s2; + if (h1.isGaugeHistogram() != h2.isGaugeHistogram()) { + throw new IllegalArgumentException( + name1 + ": conflicting histogram types: gauge histogram and classic histogram"); + } + } } } + this.snapshots = unmodifiableList(list); } diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/PrometheusNaming.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/PrometheusNaming.java index 71de5d0b4..4f766fdad 100644 --- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/PrometheusNaming.java +++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/PrometheusNaming.java @@ -27,7 +27,7 @@ public class PrometheusNaming { *

  • OpenTelemetry: {@code process_runtime_jvm_buffer_count} * * - * We do not treat {@code _count} and {@code _sum} as reserved suffixes here for compatibility + *

    We do not treat {@code _count} and {@code _sum} as reserved suffixes here for compatibility * with these libraries. However, there is a risk of name conflict if someone creates a gauge * named {@code my_data_count} and a histogram or summary named {@code my_data}, because the * histogram or summary will implicitly have a sample named {@code my_data_count}. @@ -47,9 +47,9 @@ public class PrometheusNaming { *

  • The name MUST NOT end with one of the {@link #RESERVED_METRIC_NAME_SUFFIXES}. * * - * If a metric has a {@link Unit}, the metric name SHOULD end with the unit as a suffix. Note that - * OpenMetrics requires metric names to have their unit as - * suffix, and we implement this in {@code prometheus-metrics-core}. However, {@code + *

    If a metric has a {@link Unit}, the metric name SHOULD end with the unit as a suffix. Note + * that OpenMetrics requires metric names to have their unit + * as suffix, and we implement this in {@code prometheus-metrics-core}. However, {@code * prometheus-metrics-model} does not enforce Unit suffixes. * *

    Example: If you create a Counter for a processing time with Unit {@link Unit#SECONDS diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Unit.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Unit.java index 31a9524e7..6e652af13 100644 --- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Unit.java +++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Unit.java @@ -9,8 +9,8 @@ * new Unit("myUnit"); *

  • * - * Note that in Prometheus, units are largely based on SI base units (seconds, bytes, joules, grams, - * meters, ratio, volts, amperes, and Celsius). + *

    Note that in Prometheus, units are largely based on SI base units (seconds, bytes, joules, + * grams, meters, ratio, volts, amperes, and Celsius). */ public final class Unit { diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/registry/MetricNameFilterTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/registry/MetricNameFilterTest.java index 0dc9cdee1..8f554bdc5 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/registry/MetricNameFilterTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/registry/MetricNameFilterTest.java @@ -13,7 +13,7 @@ class MetricNameFilterTest { private final PrometheusRegistry registry = new PrometheusRegistry(); @Test - public void testCounter() { + void testCounter() { registry.register( () -> CounterSnapshot.builder() diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/registry/MultiCollectorNameFilterTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/registry/MultiCollectorNameFilterTest.java index d2a38c3cf..48be456a6 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/registry/MultiCollectorNameFilterTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/registry/MultiCollectorNameFilterTest.java @@ -51,7 +51,7 @@ private boolean collectCalled() { } @Test - public void testPartialFilter() { + void testPartialFilter() { Registry registry = new Registry(Collections.emptyList()); MetricSnapshots snapshots = registry.scrape(name -> name.equals("counter_1")); assertThat(registry.collectCalled()).isTrue(); @@ -60,7 +60,7 @@ public void testPartialFilter() { } @Test - public void testPartialFilterWithPrometheusNames() { + void testPartialFilterWithPrometheusNames() { Registry registry = new Registry(Arrays.asList("counter_1", "gauge_2")); MetricSnapshots snapshots = registry.scrape(name -> name.equals("counter_1")); @@ -70,7 +70,7 @@ public void testPartialFilterWithPrometheusNames() { } @Test - public void testCompleteFilter_CollectCalled() { + void testCompleteFilter_CollectCalled() { Registry registry = new Registry(Collections.emptyList()); MetricSnapshots snapshots = registry.scrape(name -> !name.equals("counter_1") && !name.equals("gauge_2")); @@ -79,7 +79,7 @@ public void testCompleteFilter_CollectCalled() { } @Test - public void testCompleteFilter_CollectNotCalled() { + void testCompleteFilter_CollectNotCalled() { Registry registry = new Registry(Arrays.asList("counter_1", "gauge_2")); MetricSnapshots snapshots = registry.scrape(name -> !name.equals("counter_1") && !name.equals("gauge_2")); diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/registry/OpenTelemetryExporterRegistryCompatibilityTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/registry/OpenTelemetryExporterRegistryCompatibilityTest.java new file mode 100644 index 000000000..166b374b8 --- /dev/null +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/registry/OpenTelemetryExporterRegistryCompatibilityTest.java @@ -0,0 +1,116 @@ +package io.prometheus.metrics.model.registry; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +import io.prometheus.metrics.model.snapshots.CounterSnapshot; +import io.prometheus.metrics.model.snapshots.GaugeSnapshot; +import io.prometheus.metrics.model.snapshots.MetricSnapshot; +import io.prometheus.metrics.model.snapshots.MetricSnapshots; +import java.util.Collections; +import org.junit.jupiter.api.Test; + +/** + * Tests that use the Prometheus registry in the same way as the OpenTelemetry Java SDK Prometheus + * exporter ({@code io.opentelemetry.exporter.prometheus}). The SDK's {@code PrometheusMetricReader} + * implements {@link MultiCollector} with default implementations for all optional methods: {@link + * MultiCollector#getPrometheusNames()} returns an empty list, and {@link + * MultiCollector#getMetricType(String)}, {@link MultiCollector#getLabelNames(String)}, and {@link + * MultiCollector#getMetadata(String)} return null. This test suite ensures that registration, + * scrape, and unregister continue to work for that usage pattern and that a shared registry with + * both SDK-style and validated collectors behaves correctly. + */ +class OpenTelemetryExporterRegistryCompatibilityTest { + + /** + * A MultiCollector that mimics the OpenTelemetry Java SDK's PrometheusMetricReader: it does not + * override getPrometheusNames() (empty list), getMetricType(String), getLabelNames(String), or + * getMetadata(String) (all null). Only collect() is implemented and returns MetricSnapshots. + */ + private static final MultiCollector OTEL_STYLE_MULTI_COLLECTOR = + new MultiCollector() { + @Override + public MetricSnapshots collect() { + return new MetricSnapshots( + CounterSnapshot.builder() + .name("otel_metric") + .help("A metric produced by an OTel-style converter") + .dataPoint(CounterSnapshot.CounterDataPointSnapshot.builder().value(42.0).build()) + .build()); + } + }; + + @Test + void registerOtelStyleMultiCollector_succeeds() { + PrometheusRegistry registry = new PrometheusRegistry(); + + assertThatCode(() -> registry.register(OTEL_STYLE_MULTI_COLLECTOR)).doesNotThrowAnyException(); + } + + @Test + void scrape_afterRegisteringOtelStyleMultiCollector_returnsSnapshotsFromCollector() { + PrometheusRegistry registry = new PrometheusRegistry(); + registry.register(OTEL_STYLE_MULTI_COLLECTOR); + + MetricSnapshots snapshots = registry.scrape(); + + assertThat(snapshots).hasSize(1); + MetricSnapshot snapshot = snapshots.get(0); + assertThat(snapshot.getMetadata().getPrometheusName()).isEqualTo("otel_metric"); + } + + @Test + void unregisterOtelStyleMultiCollector_succeedsAndScrapeNoLongerIncludesIt() { + PrometheusRegistry registry = new PrometheusRegistry(); + registry.register(OTEL_STYLE_MULTI_COLLECTOR); + + assertThat(registry.scrape()).hasSize(1); + + assertThatCode(() -> registry.unregister(OTEL_STYLE_MULTI_COLLECTOR)) + .doesNotThrowAnyException(); + + assertThat(registry.scrape()).isEmpty(); + } + + @Test + void sharedRegistry_otelStyleMultiCollectorAndValidatedCollector_bothParticipateInScrape() { + PrometheusRegistry registry = new PrometheusRegistry(); + + Collector validatedCollector = + new Collector() { + @Override + public MetricSnapshot collect() { + return GaugeSnapshot.builder().name("app_gauge").help("App gauge").build(); + } + + @Override + public String getPrometheusName() { + return "app_gauge"; + } + + @Override + public MetricType getMetricType() { + return MetricType.GAUGE; + } + + @Override + public java.util.Set getLabelNames() { + return Collections.emptySet(); + } + }; + + registry.register(validatedCollector); + registry.register(OTEL_STYLE_MULTI_COLLECTOR); + + MetricSnapshots snapshots = registry.scrape(); + + assertThat(snapshots).hasSize(2); + assertThat(snapshots) + .extracting(s -> s.getMetadata().getPrometheusName()) + .containsExactlyInAnyOrder("app_gauge", "otel_metric"); + + registry.unregister(OTEL_STYLE_MULTI_COLLECTOR); + assertThat(registry.scrape()).hasSize(1); + assertThat(registry.scrape().get(0).getMetadata().getPrometheusName()).isEqualTo("app_gauge"); + } +} diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/registry/PrometheusRegistryTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/registry/PrometheusRegistryTest.java index 9e87f1fc9..90a04934e 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/registry/PrometheusRegistryTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/registry/PrometheusRegistryTest.java @@ -1,15 +1,19 @@ package io.prometheus.metrics.model.registry; +import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import io.prometheus.metrics.model.snapshots.CounterSnapshot; import io.prometheus.metrics.model.snapshots.GaugeSnapshot; +import io.prometheus.metrics.model.snapshots.MetricMetadata; import io.prometheus.metrics.model.snapshots.MetricSnapshot; import io.prometheus.metrics.model.snapshots.MetricSnapshots; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.junit.jupiter.api.Test; class PrometheusRegistryTest { @@ -82,29 +86,429 @@ public List getPrometheusNames() { }; @Test - public void registerNoName() { + void register_sameInstanceTwice_notAllowed() { PrometheusRegistry registry = new PrometheusRegistry(); - // If the collector does not have a name at registration time, there is no conflict during - // registration. - registry.register(noName); + registry.register(noName); - // However, at scrape time the collector has to provide a metric name, and then we'll get a - // duplicate name error. - assertThatCode(registry::scrape) - .hasMessageContaining("duplicate") - .hasMessageContaining("no_name_gauge"); + + assertThatThrownBy(() -> registry.register(noName)) + .hasMessageContaining("Collector instance is already registered"); } @Test - public void registerDuplicateName() { + void register_duplicateName_differentTypes_notAllowed() { PrometheusRegistry registry = new PrometheusRegistry(); + + Collector counterA1 = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("counter_a").build(); + } + + @Override + public String getPrometheusName() { + return "counter_a"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + }; + + Collector gaugeA1 = + new Collector() { + @Override + public MetricSnapshot collect() { + return GaugeSnapshot.builder().name("counter_a").build(); + } + + @Override + public String getPrometheusName() { + return "counter_a"; + } + + @Override + public MetricType getMetricType() { + return MetricType.GAUGE; + } + }; + registry.register(counterA1); - assertThatExceptionOfType(IllegalStateException.class) - .isThrownBy(() -> registry.register(counterA2)); + + assertThatThrownBy(() -> registry.register(gaugeA1)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Conflicting metric types"); + } + + @Test + void register_sameName_sameType_differentLabelSchemas_allowed() { + PrometheusRegistry registry = new PrometheusRegistry(); + + Collector counterWithPathLabel = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests_total").build(); + } + + @Override + public String getPrometheusName() { + return "requests_total"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("path", "status")); + } + }; + + Collector counterWithRegionLabel = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests_total").build(); + } + + @Override + public String getPrometheusName() { + return "requests_total"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("region")); + } + }; + + // Both collectors have same name and type, but different label schemas + // This should succeed + registry.register(counterWithPathLabel); + assertThatCode(() -> registry.register(counterWithRegionLabel)).doesNotThrowAnyException(); + } + + @Test + void register_sameName_sameType_sameLabelSchema_notAllowed() { + PrometheusRegistry registry = new PrometheusRegistry(); + + Collector counter1 = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests_total").build(); + } + + @Override + public String getPrometheusName() { + return "requests_total"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("path", "status")); + } + }; + + Collector counter2 = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests_total").build(); + } + + @Override + public String getPrometheusName() { + return "requests_total"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("path", "status")); + } + }; + + registry.register(counter1); + + // Second collector has same name, type, and label schema - should fail + assertThatThrownBy(() -> registry.register(counter2)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("duplicate metric name with identical label schema"); + } + + @Test + void register_duplicateLabelSchema_rollsBackCollectorOnFailure() { + PrometheusRegistry registry = new PrometheusRegistry(); + + Collector counter1 = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("http_requests").build(); + } + + @Override + public String getPrometheusName() { + return "http_requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("path", "status")); + } + }; + + Collector counter2 = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("http_requests").build(); + } + + @Override + public String getPrometheusName() { + return "http_requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("path", "status")); + } + }; + + registry.register(counter1); + + // Second collector has same name and label schema - registration fails during metadata + // validation. The failed collector must be rolled back (not present in the registry). + assertThatThrownBy(() -> registry.register(counter2)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("duplicate metric name with identical label schema"); + + // Only the first collector should be in the registry; counter2 was removed on rollback. + assertThat(registry.scrape().size()).isEqualTo(1); + } + + @Test + void register_metadataValidationFailure_rollsBackLabelSchema() { + PrometheusRegistry registry = new PrometheusRegistry(); + + Collector counterWithHelpOne = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("path")); + } + + @Override + public MetricMetadata getMetadata() { + return new MetricMetadata("requests", "First help", null); + } + }; + + Collector counterWithHelpTwo = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("status")); + } + + @Override + public MetricMetadata getMetadata() { + return new MetricMetadata("requests", "Second help", null); + } + }; + + Collector counterWithCorrectHelp = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("status")); + } + + @Override + public MetricMetadata getMetadata() { + return new MetricMetadata("requests", "First help", null); + } + }; + + registry.register(counterWithHelpOne); + + // Second collector has conflicting help - should fail and roll back its label schema + assertThatThrownBy(() -> registry.register(counterWithHelpTwo)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Conflicting help strings"); + + // Third collector has same label schema as second (which failed), but correct help. + // If label schema wasn't rolled back, this would fail with "duplicate label schema". + // If rollback worked, this should succeed. + assertThatCode(() -> registry.register(counterWithCorrectHelp)).doesNotThrowAnyException(); + + // Verify both collectors are in the registry + assertThat(registry.scrape().size()).isEqualTo(2); + } + + @Test + void register_nullType_skipsValidation() { + PrometheusRegistry registry = new PrometheusRegistry(); + + // Collectors without getMetricType() skip registration-time validation. + // This allows legacy collectors to work without implementing all getters. + Collector legacyCollector1 = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("legacy_metric").build(); + } + + @Override + public String getPrometheusName() { + return "legacy_metric"; + } + }; + + Collector legacyCollector2 = + new Collector() { + @Override + public MetricSnapshot collect() { + return GaugeSnapshot.builder().name("legacy_metric").build(); + } + + @Override + public String getPrometheusName() { + return "legacy_metric"; + } + }; + + // Both collectors can register successfully since validation is skipped + assertThatCode(() -> registry.register(legacyCollector1)).doesNotThrowAnyException(); + assertThatCode(() -> registry.register(legacyCollector2)).doesNotThrowAnyException(); } @Test - public void registerOk() { + void register_multiCollector_withTypeValidation() { + PrometheusRegistry registry = new PrometheusRegistry(); + + Collector counter = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("shared_metric").build(); + } + + @Override + public String getPrometheusName() { + return "shared_metric"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + }; + + MultiCollector multiWithGauge = + new MultiCollector() { + @Override + public MetricSnapshots collect() { + return new MetricSnapshots(GaugeSnapshot.builder().name("shared_metric").build()); + } + + @Override + public List getPrometheusNames() { + return asList("shared_metric"); + } + + @Override + public MetricType getMetricType(String prometheusName) { + return MetricType.GAUGE; + } + }; + + registry.register(counter); + + // MultiCollector tries to register a Gauge with the same name as existing Counter + assertThatThrownBy(() -> registry.register(multiWithGauge)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Conflicting metric types"); + } + + @Test + void registerOk() { PrometheusRegistry registry = new PrometheusRegistry(); registry.register(counterA1); registry.register(counterB); @@ -122,15 +526,17 @@ public void registerOk() { } @Test - public void registerDuplicateMultiCollector() { + void registerDuplicateMultiCollector() { PrometheusRegistry registry = new PrometheusRegistry(); registry.register(multiCollector); - assertThatExceptionOfType(IllegalStateException.class) - .isThrownBy(() -> registry.register(multiCollector)); + // Registering the same instance twice should fail + assertThatThrownBy(() -> registry.register(multiCollector)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("already registered"); } @Test - public void registerOkMultiCollector() { + void registerOkMultiCollector() { PrometheusRegistry registry = new PrometheusRegistry(); registry.register(multiCollector); MetricSnapshots snapshots = registry.scrape(); @@ -142,7 +548,7 @@ public void registerOkMultiCollector() { } @Test - public void clearOk() { + void clearOk() { PrometheusRegistry registry = new PrometheusRegistry(); registry.register(counterA1); registry.register(counterB); @@ -152,4 +558,533 @@ public void clearOk() { registry.clear(); assertThat(registry.scrape().size()).isZero(); } + + @Test + void unregister_shouldRemoveLabelSchemaFromRegistrationInfo() { + PrometheusRegistry registry = new PrometheusRegistry(); + + Collector counterWithPathLabel = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests_total").build(); + } + + @Override + public String getPrometheusName() { + return "requests_total"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("path", "status")); + } + }; + + Collector counterWithRegionLabel = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests_total").build(); + } + + @Override + public String getPrometheusName() { + return "requests_total"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("region")); + } + }; + + Collector counterWithPathLabelAgain = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests_total").build(); + } + + @Override + public String getPrometheusName() { + return "requests_total"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("path", "status")); + } + }; + + registry.register(counterWithPathLabel); + registry.register(counterWithRegionLabel); + + registry.unregister(counterWithPathLabel); + + assertThatCode(() -> registry.register(counterWithPathLabelAgain)).doesNotThrowAnyException(); + } + + @Test + void register_withEmptyLabelSets_shouldDetectDuplicates() { + PrometheusRegistry registry = new PrometheusRegistry(); + + Collector collector1 = + new Collector() { + @Override + public MetricSnapshot collect() { + return GaugeSnapshot.builder().name("requests").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.GAUGE; + } + + // getLabelNames() returns null by default + }; + + // Register another collector with same name and type, also no labels + Collector collector2 = + new Collector() { + @Override + public MetricSnapshot collect() { + return GaugeSnapshot.builder().name("requests").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.GAUGE; + } + + // getLabelNames() returns null by default + }; + + registry.register(collector1); + + assertThatThrownBy(() -> registry.register(collector2)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("duplicate metric name with identical label schema"); + } + + @Test + void register_withMixedNullAndEmptyLabelSets_shouldDetectDuplicates() { + PrometheusRegistry registry = new PrometheusRegistry(); + + Collector collector1 = + new Collector() { + @Override + public MetricSnapshot collect() { + return GaugeSnapshot.builder().name("requests").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.GAUGE; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(); + } + }; + + Collector collector2 = + new Collector() { + @Override + public MetricSnapshot collect() { + return GaugeSnapshot.builder().name("requests").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.GAUGE; + } + + // getLabelNames() returns null by default + }; + + registry.register(collector1); + + // null and empty should be treated the same + assertThatThrownBy(() -> registry.register(collector2)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("duplicate metric name with identical label schema"); + } + + @Test + void register_sameName_differentHelp_notAllowed() { + PrometheusRegistry registry = new PrometheusRegistry(); + + Collector withHelpOne = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests").help("First help").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("path")); + } + + @Override + public MetricMetadata getMetadata() { + return new MetricMetadata("requests", "First help", null); + } + }; + + Collector withHelpTwo = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests").help("Second help").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("status")); + } + + @Override + public MetricMetadata getMetadata() { + return new MetricMetadata("requests", "Second help", null); + } + }; + + registry.register(withHelpOne); + assertThatThrownBy(() -> registry.register(withHelpTwo)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Conflicting help strings"); + } + + @Test + void register_sameName_nullVsNonNullHelp_notAllowed() { + PrometheusRegistry registry = new PrometheusRegistry(); + + Collector withHelp = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests").help("Total requests").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("path")); + } + + @Override + public MetricMetadata getMetadata() { + return new MetricMetadata("requests", "Total requests", null); + } + }; + + Collector withoutHelp = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("status")); + } + + @Override + public MetricMetadata getMetadata() { + return new MetricMetadata("requests", null, null); + } + }; + + registry.register(withHelp); + assertThatThrownBy(() -> registry.register(withoutHelp)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Conflicting help strings"); + } + + @Test + void register_sameName_sameHelpAndUnit_allowed() { + PrometheusRegistry registry = new PrometheusRegistry(); + + Collector withPath = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests").help("Total requests").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("path")); + } + + @Override + public MetricMetadata getMetadata() { + return new MetricMetadata("requests", "Total requests", null); + } + }; + + Collector withStatus = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests").help("Total requests").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("status")); + } + + @Override + public MetricMetadata getMetadata() { + return new MetricMetadata("requests", "Total requests", null); + } + }; + + registry.register(withPath); + assertThatCode(() -> registry.register(withStatus)).doesNotThrowAnyException(); + } + + @Test + void unregister_lastCollector_removesPrometheusName() { + PrometheusRegistry registry = new PrometheusRegistry(); + + Collector counter1 = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("path")); + } + }; + + Collector counter2 = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + + @Override + public Set getLabelNames() { + return new HashSet<>(asList("status")); + } + }; + + registry.register(counter1); + registry.register(counter2); + + // Unregister first collector - name should still be registered + registry.unregister(counter1); + MetricSnapshots snapshots = registry.scrape(); + assertThat(snapshots.size()).isEqualTo(1); + + // Unregister second collector - name should be removed + registry.unregister(counter2); + snapshots = registry.scrape(); + assertThat(snapshots.size()).isEqualTo(0); + + // Should be able to register again with same name + assertThatCode(() -> registry.register(counter1)).doesNotThrowAnyException(); + } + + @Test + void unregister_multiCollector_removesAllLabelSchemas() { + PrometheusRegistry registry = new PrometheusRegistry(); + + MultiCollector multi = + new MultiCollector() { + @Override + public MetricSnapshots collect() { + return new MetricSnapshots( + CounterSnapshot.builder().name("requests").build(), + GaugeSnapshot.builder().name("connections").build()); + } + + @Override + public List getPrometheusNames() { + return asList("requests", "connections"); + } + + @Override + public MetricType getMetricType(String prometheusName) { + return prometheusName.equals("requests") ? MetricType.COUNTER : MetricType.GAUGE; + } + }; + + registry.register(multi); + assertThat(registry.scrape().size()).isEqualTo(2); + + registry.unregister(multi); + assertThat(registry.scrape().size()).isEqualTo(0); + + // Should be able to register collectors with same names again + Collector counter = + new Collector() { + @Override + public MetricSnapshot collect() { + return CounterSnapshot.builder().name("requests").build(); + } + + @Override + public String getPrometheusName() { + return "requests"; + } + + @Override + public MetricType getMetricType() { + return MetricType.COUNTER; + } + }; + + assertThatCode(() -> registry.register(counter)).doesNotThrowAnyException(); + } + + @Test + void unregister_legacyCollector_noErrors() { + PrometheusRegistry registry = new PrometheusRegistry(); + + Collector legacy = + new Collector() { + @Override + public MetricSnapshot collect() { + return GaugeSnapshot.builder().name("legacy_metric").build(); + } + + @Override + public String getPrometheusName() { + return "legacy_metric"; + } + // No getMetricType() - returns null + }; + + registry.register(legacy); + assertThat(registry.scrape().size()).isEqualTo(1); + + // Unregister should work without errors even for legacy collectors + assertThatCode(() -> registry.unregister(legacy)).doesNotThrowAnyException(); + assertThat(registry.scrape().size()).isEqualTo(0); + } } diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ClassicHistogramBucketsTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ClassicHistogramBucketsTest.java index d39b32436..d06c2ac70 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ClassicHistogramBucketsTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ClassicHistogramBucketsTest.java @@ -11,7 +11,7 @@ class ClassicHistogramBucketsTest { @Test - public void testGoodCase() { + void testGoodCase() { ClassicHistogramBuckets buckets = ClassicHistogramBuckets.builder() .bucket(Double.NEGATIVE_INFINITY, 0) @@ -23,7 +23,7 @@ public void testGoodCase() { } @Test - public void testSort() { + void testSort() { ClassicHistogramBuckets buckets = ClassicHistogramBuckets.builder() .bucket(7, 2) @@ -40,21 +40,21 @@ public void testSort() { } @Test - public void testMinimalBuckets() { + void testMinimalBuckets() { ClassicHistogramBuckets buckets = ClassicHistogramBuckets.builder().bucket(Double.POSITIVE_INFINITY, 0).build(); assertThat(buckets.size()).isOne(); } @Test - public void testInfBucketMissing() { + void testInfBucketMissing() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> ClassicHistogramBuckets.builder().bucket(Double.NEGATIVE_INFINITY, 0).build()); } @Test - public void testNegativeCount() { + void testNegativeCount() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> @@ -65,7 +65,7 @@ public void testNegativeCount() { } @Test - public void testNaNBoundary() { + void testNaNBoundary() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> @@ -77,7 +77,7 @@ public void testNaNBoundary() { } @Test - public void testDuplicateBoundary() { + void testDuplicateBoundary() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> @@ -90,13 +90,13 @@ public void testDuplicateBoundary() { } @Test - public void testEmptyBuckets() { + void testEmptyBuckets() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> ClassicHistogramBuckets.builder().build()); } @Test - public void testDifferentLength() { + void testDifferentLength() { double[] upperBounds = new double[] {0.7, 1.3, Double.POSITIVE_INFINITY}; long[] counts = new long[] {13, 178, 1024, 3000}; assertThatExceptionOfType(IllegalArgumentException.class) @@ -104,7 +104,7 @@ public void testDifferentLength() { } @Test - public void testImmutable() { + void testImmutable() { ClassicHistogramBuckets buckets = ClassicHistogramBuckets.builder() .bucket(1.0, 7) @@ -117,7 +117,7 @@ public void testImmutable() { } @Test - public void compare() { + void compare() { ClassicHistogramBuckets buckets = ClassicHistogramBuckets.builder() .bucket(1.0, 7) diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/CounterSnapshotTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/CounterSnapshotTest.java index a69ccfbab..ca4346cdb 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/CounterSnapshotTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/CounterSnapshotTest.java @@ -11,7 +11,7 @@ class CounterSnapshotTest { @Test - public void testCompleteGoodCase() { + void testCompleteGoodCase() { long createdTimestamp1 = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1); long createdTimestamp2 = System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(2); long exemplarTimestamp = System.currentTimeMillis(); @@ -68,7 +68,7 @@ public void testCompleteGoodCase() { } @Test - public void testMinimalGoodCase() { + void testMinimalGoodCase() { CounterSnapshot snapshot = CounterSnapshot.builder() .name("events") @@ -85,25 +85,25 @@ public void testMinimalGoodCase() { } @Test - public void testEmptyCounter() { + void testEmptyCounter() { CounterSnapshot snapshot = CounterSnapshot.builder().name("events").build(); assertThat(snapshot.getDataPoints()).isEmpty(); } @Test - public void testTotalSuffixPresent() { + void testTotalSuffixPresent() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> CounterSnapshot.builder().name("test_total").build()); } @Test - public void testValueMissing() { + void testValueMissing() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> CounterDataPointSnapshot.builder().build()); } @Test - public void testDataImmutable() { + void testDataImmutable() { CounterSnapshot snapshot = CounterSnapshot.builder() .name("events") diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ExemplarTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ExemplarTest.java index 4a40b47ef..db7ad2426 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ExemplarTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ExemplarTest.java @@ -9,7 +9,7 @@ class ExemplarTest { @Test - public void testGoodCaseComplete() { + void testGoodCaseComplete() { long timestamp = System.currentTimeMillis(); Exemplar exemplar = Exemplar.builder() @@ -36,13 +36,13 @@ public void testGoodCaseComplete() { } @Test - public void testValueMissing() { + void testValueMissing() { assertThatExceptionOfType(IllegalStateException.class) .isThrownBy(() -> Exemplar.builder().build()); } @Test - public void testMinimal() { + void testMinimal() { Exemplar exemplar = Exemplar.builder().value(0.0).build(); assertThat(exemplar.getValue()).isEqualTo(0.0); assertLabels(exemplar.getLabels()).isEqualTo(Labels.EMPTY); @@ -50,7 +50,7 @@ public void testMinimal() { } @Test - public void testLabelsMergeTraceId() { + void testLabelsMergeTraceId() { Exemplar exemplar = Exemplar.builder().value(0.0).labels(Labels.of("a", "b")).traceId("abc").build(); assertLabels(exemplar.getLabels()).isEqualTo(Labels.of("a", "b", "trace_id", "abc")); @@ -61,14 +61,14 @@ private static IterableAssert assertLabels(Labels labels) { } @Test - public void testLabelsMergeSpanId() { + void testLabelsMergeSpanId() { Exemplar exemplar = Exemplar.builder().value(0.0).labels(Labels.of("a", "b")).spanId("abc").build(); assertLabels(exemplar.getLabels()).isEqualTo(Labels.of("a", "b", "span_id", "abc")); } @Test - public void testLabelsMergeTraceIdAndSpanId() { + void testLabelsMergeTraceIdAndSpanId() { Exemplar exemplar = Exemplar.builder() .value(0.0) @@ -81,7 +81,7 @@ public void testLabelsMergeTraceIdAndSpanId() { } @Test - public void testLabelsMergeNone() { + void testLabelsMergeNone() { Exemplar exemplar = Exemplar.builder().value(0.0).labels(Labels.of("a", "b")).build(); assertLabels(exemplar.getLabels()).isEqualTo(Labels.of("a", "b")); } diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ExemplarsTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ExemplarsTest.java index cd38342cd..be69e7f16 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ExemplarsTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ExemplarsTest.java @@ -9,7 +9,7 @@ class ExemplarsTest { @Test - public void testUpperBound() { + void testUpperBound() { Exemplars exemplars = Exemplars.of( Exemplar.builder().value(1.0).build(), @@ -26,7 +26,7 @@ public void testUpperBound() { } @Test - public void testImmutable() { + void testImmutable() { Exemplars exemplars = Exemplars.of( Exemplar.builder().value(1.0).build(), @@ -38,7 +38,7 @@ public void testImmutable() { } @Test - public void testGet() { + void testGet() { Exemplar oldest = Exemplar.builder().timestampMillis(System.currentTimeMillis() - 100).value(1.8).build(); Exemplar middle = diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/GaugeSnapshotTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/GaugeSnapshotTest.java index c469647e0..5154e1eb1 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/GaugeSnapshotTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/GaugeSnapshotTest.java @@ -11,7 +11,7 @@ class GaugeSnapshotTest { @Test - public void testCompleteGoodCase() { + void testCompleteGoodCase() { long exemplarTimestamp = System.currentTimeMillis(); GaugeSnapshot snapshot = GaugeSnapshot.builder() @@ -63,7 +63,7 @@ public void testCompleteGoodCase() { } @Test - public void testMinimalGoodCase() { + void testMinimalGoodCase() { GaugeSnapshot snapshot = GaugeSnapshot.builder() .name("temperature") @@ -80,31 +80,31 @@ public void testMinimalGoodCase() { } @Test - public void testEmptyGauge() { + void testEmptyGauge() { GaugeSnapshot snapshot = GaugeSnapshot.builder().name("temperature").build(); assertThat(snapshot.getDataPoints().size()).isZero(); } @Test - public void testTotalSuffixPresent() { + void testTotalSuffixPresent() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> CounterSnapshot.builder().name("test_total").build()); } @Test - public void testTotalSuffixPresentDot() { + void testTotalSuffixPresentDot() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> CounterSnapshot.builder().name("test.total").build()); } @Test - public void testValueMissing() { + void testValueMissing() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> CounterDataPointSnapshot.builder().build()); } @Test - public void testDataImmutable() { + void testDataImmutable() { GaugeSnapshot snapshot = GaugeSnapshot.builder() .name("gauge") diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/HistogramSnapshotTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/HistogramSnapshotTest.java index 54eefbe66..6233481df 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/HistogramSnapshotTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/HistogramSnapshotTest.java @@ -13,7 +13,7 @@ class HistogramSnapshotTest { @Test - public void testGoodCaseComplete() { + void testGoodCaseComplete() { long createdTimestamp = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1); long scrapeTimestamp = System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(2); long exemplarTimestamp = System.currentTimeMillis(); @@ -170,7 +170,7 @@ public void testGoodCaseComplete() { } @Test - public void testEmptyHistogram() { + void testEmptyHistogram() { assertThat(HistogramSnapshot.builder().name("empty_histogram").build().getDataPoints()) .isEmpty(); HistogramSnapshot snapshot = @@ -181,7 +181,7 @@ public void testEmptyHistogram() { } @Test - public void testMinimalClassicHistogram() { + void testMinimalClassicHistogram() { HistogramSnapshot snapshot = HistogramSnapshot.builder() .name("minimal_histogram") @@ -198,7 +198,7 @@ public void testMinimalClassicHistogram() { } @Test - public void testMinimalNativeHistogram() { + void testMinimalNativeHistogram() { HistogramSnapshot snapshot = HistogramSnapshot.builder() .name("hist") @@ -218,7 +218,7 @@ public void testMinimalNativeHistogram() { } @Test - public void testClassicCount() { + void testClassicCount() { HistogramSnapshot snapshot = HistogramSnapshot.builder() .name("test_histogram") @@ -239,21 +239,21 @@ public void testClassicCount() { } @Test - public void testEmptyData() { + void testEmptyData() { // This will fail because one of nativeSchema and classicHistogramBuckets is required assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> HistogramDataPointSnapshot.builder().build()); } @Test - public void testEmptyNativeData() { + void testEmptyNativeData() { HistogramDataPointSnapshot data = HistogramDataPointSnapshot.builder().nativeSchema(5).build(); assertThat(data.getNativeBucketsForNegativeValues().size()).isZero(); assertThat(data.getNativeBucketsForPositiveValues().size()).isZero(); } @Test - public void testDataImmutable() { + void testDataImmutable() { HistogramSnapshot snapshot = HistogramSnapshot.builder() .name("test_histogram") @@ -278,7 +278,7 @@ public void testDataImmutable() { } @Test - public void testEmptyClassicBuckets() { + void testEmptyClassicBuckets() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> @@ -287,7 +287,7 @@ public void testEmptyClassicBuckets() { } @Test - public void testMinimalNativeData() { + void testMinimalNativeData() { new HistogramDataPointSnapshot( ClassicHistogramBuckets.EMPTY, 0, @@ -302,7 +302,7 @@ public void testMinimalNativeData() { } @Test - public void testMinimalClassicData() { + void testMinimalClassicData() { ClassicHistogramBuckets buckets = ClassicHistogramBuckets.builder().bucket(Double.POSITIVE_INFINITY, 0).build(); new HistogramDataPointSnapshot( diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/InfoSnapshotTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/InfoSnapshotTest.java index 983450181..3cf7d69af 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/InfoSnapshotTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/InfoSnapshotTest.java @@ -9,7 +9,7 @@ class InfoSnapshotTest { @Test - public void testCompleteGoodCase() { + void testCompleteGoodCase() { InfoSnapshot snapshot = InfoSnapshot.builder() .name("target") @@ -33,13 +33,13 @@ void create() { } @Test - public void testEmptyInfo() { + void testEmptyInfo() { InfoSnapshot snapshot = InfoSnapshot.builder().name("target").build(); assertThat(snapshot.getDataPoints()).isEmpty(); } @Test - public void testDataImmutable() { + void testDataImmutable() { InfoSnapshot snapshot = InfoSnapshot.builder() .name("target") @@ -60,13 +60,13 @@ public void testDataImmutable() { } @Test - public void testNameMustNotIncludeSuffix() { + void testNameMustNotIncludeSuffix() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> InfoSnapshot.builder().name("jvm_info").build()); } @Test - public void testNameMustNotIncludeSuffixDot() { + void testNameMustNotIncludeSuffixDot() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> InfoSnapshot.builder().name("jvm.info").build()); } diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/LabelsTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/LabelsTest.java index 5bdd285e3..3dc8f639f 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/LabelsTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/LabelsTest.java @@ -17,7 +17,7 @@ private > void assertGreaterThan(T a, T b) { } @Test - public void testCompareDifferentLabelNames() { + void testCompareDifferentLabelNames() { Labels labels1 = Labels.of("env", "prod", "status2", "200"); Labels labels2 = Labels.of("env", "prod", "status1", "200"); assertGreaterThan(labels1, labels2); @@ -31,7 +31,7 @@ private static IterableAssert assertLabels(Labels labels) { } @Test - public void testCompareSameLabelNames() { + void testCompareSameLabelNames() { // If all label names are the same, labels should be sorted by label value. Labels labels1 = Labels.of("env", "prod", "status", "200"); Labels labels2 = Labels.of("env", "prod", "status", "500"); @@ -42,7 +42,7 @@ public void testCompareSameLabelNames() { } @Test - public void testCompareDifferentNumberOfLabels() { + void testCompareDifferentNumberOfLabels() { Labels labels1 = Labels.of("env", "prod", "status", "200"); Labels labels2 = Labels.of("env", "prod", "status", "200", "x_code", "none"); assertLessThan(labels1, labels2); @@ -52,14 +52,14 @@ public void testCompareDifferentNumberOfLabels() { } @Test - public void testComparePrometheusNames() { + void testComparePrometheusNames() { Labels labels1 = Labels.of("my_a", "val"); Labels labels2 = Labels.of("my.b", "val"); assertLessThan(labels1, labels2); // this is true because it compares "my_a" to "my_b". } @Test - public void testEqualsHashcodeDots() { + void testEqualsHashcodeDots() { Labels labels1 = Labels.of("my_a", "val"); Labels labels2 = Labels.of("my.a", "val"); assertLabels(labels2).isEqualTo(labels1).hasSameHashCodeAs(labels1); @@ -67,7 +67,7 @@ public void testEqualsHashcodeDots() { @SuppressWarnings({"unchecked", "rawtypes"}) @Test - public void testCompareEquals() { + void testCompareEquals() { Labels labels1 = Labels.of("env", "prod", "status", "200"); Labels labels2 = Labels.of("env", "prod", "status", "200"); assertThat((Comparable) labels1).isEqualByComparingTo(labels2); @@ -77,19 +77,19 @@ public void testCompareEquals() { } @Test - public void testReservedLabelName() { + void testReservedLabelName() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> Labels.of("__name__", "requests_total")); } @Test - public void testDuplicateLabelName() { + void testDuplicateLabelName() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> Labels.of("name1", "value1", "name2", "value2", "name1", "value3")); } @Test - public void testMakePrometheusNames() { + void testMakePrometheusNames() { String[] names = new String[] {}; String[] prometheusNames = Labels.makePrometheusNames(names); assertThat(prometheusNames).isSameAs(names); @@ -107,7 +107,7 @@ public void testMakePrometheusNames() { } @Test - public void testMerge() { + void testMerge() { Labels labels1 = Labels.of("key.1", "value 1", "key.3", "value 3"); Labels labels2 = Labels.of("key_2", "value 2"); Labels merged = labels2.merge(labels1); @@ -117,7 +117,7 @@ public void testMerge() { } @Test - public void testMergeDuplicateName() { + void testMergeDuplicateName() { Labels labels1 = Labels.of("key_one", "v1"); Labels labels2 = Labels.of("key.one", "v2"); assertThatExceptionOfType(IllegalArgumentException.class) @@ -125,7 +125,7 @@ public void testMergeDuplicateName() { } @Test - public void testDuplicateName() { + void testDuplicateName() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> Labels.of("key_one", "v1", "key.one", "v2")); } diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/MetricMetadataTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/MetricMetadataTest.java index f2d6a6ba4..41efe043b 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/MetricMetadataTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/MetricMetadataTest.java @@ -9,19 +9,19 @@ class MetricMetadataTest { @Test - public void testEmptyName() { + void testEmptyName() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> new MetricMetadata("")); } @Test - public void testNullName() { + void testNullName() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> new MetricMetadata(null)); } @Test - public void testSanitizationIllegalCharacters() { + void testSanitizationIllegalCharacters() { MetricMetadata metadata = new MetricMetadata( sanitizeMetricName("my_namespace/http.server.duration", Unit.SECONDS), @@ -34,42 +34,42 @@ public void testSanitizationIllegalCharacters() { } @Test - public void testSanitizationCounter() { + void testSanitizationCounter() { MetricMetadata metadata = new MetricMetadata(sanitizeMetricName("my_events_total")); assertThat(metadata.getName()).isEqualTo("my_events"); } @Test - public void testSanitizationInfo() { + void testSanitizationInfo() { MetricMetadata metadata = new MetricMetadata(sanitizeMetricName("target_info")); assertThat(metadata.getName()).isEqualTo("target"); } @Test - public void testSanitizationWeirdCornerCase() { + void testSanitizationWeirdCornerCase() { MetricMetadata metadata = new MetricMetadata(sanitizeMetricName("_total_created")); assertThat(metadata.getName()).isEqualTo("total"); } @Test - public void testSanitizeEmptyString() { + void testSanitizeEmptyString() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> sanitizeMetricName("")); } @Test - public void testUnitSuffixRequired() { + void testUnitSuffixRequired() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> new MetricMetadata("my_counter", "help", Unit.SECONDS)); } @Test - public void testUnitSuffixAdded() { + void testUnitSuffixAdded() { new MetricMetadata(sanitizeMetricName("my_counter", Unit.SECONDS), "help", Unit.SECONDS); } @Test - public void testUnitNotDuplicated() { + void testUnitNotDuplicated() { assertThat(sanitizeMetricName("my_counter_bytes", Unit.BYTES)).isEqualTo("my_counter_bytes"); } } diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/MetricSnapshotTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/MetricSnapshotTest.java index 2c1c04bb6..199cb8f4c 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/MetricSnapshotTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/MetricSnapshotTest.java @@ -8,7 +8,7 @@ class MetricSnapshotTest { @Test - public void testDuplicateLabels() { + void testDuplicateLabels() { assertThatExceptionOfType(DuplicateLabelsException.class) .isThrownBy( () -> @@ -39,13 +39,13 @@ public void testDuplicateLabels() { } @Test - public void testNoData() { + void testNoData() { MetricSnapshot snapshot = CounterSnapshot.builder().name("test").build(); assertThat(snapshot.getDataPoints().size()).isEqualTo(0); } @Test - public void testNullData() { + void testNullData() { assertThatExceptionOfType(NullPointerException.class) .isThrownBy(() -> new CounterSnapshot(new MetricMetadata("test"), null)); } diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/MetricSnapshotsTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/MetricSnapshotsTest.java index 04a824f02..224ca691a 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/MetricSnapshotsTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/MetricSnapshotsTest.java @@ -9,13 +9,13 @@ class MetricSnapshotsTest { @Test - public void testEmpty() { + void testEmpty() { MetricSnapshots snapshots = MetricSnapshots.builder().build(); assertThat(snapshots.stream().findAny()).isNotPresent(); } @Test - public void testSort() { + void testSort() { CounterSnapshot c1 = CounterSnapshot.builder() .name("counter1") @@ -39,7 +39,7 @@ public void testSort() { } @Test - public void testDuplicateName() { + void testDuplicateName() { // Q: What if you have a counter named "foo" and a gauge named "foo"? // A: Great question. You might think this is a valid scenario, because the counter will produce // the values "foo_total" and "foo_created" while the gauge will produce the value "foo". @@ -62,7 +62,35 @@ public void testDuplicateName() { } @Test - public void testBuilder() { + void testDuplicateName_histogramGaugeVsClassic_throws() { + HistogramSnapshot classic = + HistogramSnapshot.builder() + .name("my_histogram") + .dataPoint( + HistogramSnapshot.HistogramDataPointSnapshot.builder() + .classicHistogramBuckets( + ClassicHistogramBuckets.of( + new double[] {Double.POSITIVE_INFINITY}, new long[] {0})) + .build()) + .build(); + HistogramSnapshot gauge = + HistogramSnapshot.builder() + .name("my_histogram") + .gaugeHistogram(true) + .dataPoint( + HistogramSnapshot.HistogramDataPointSnapshot.builder() + .classicHistogramBuckets( + ClassicHistogramBuckets.of( + new double[] {Double.POSITIVE_INFINITY}, new long[] {0})) + .build()) + .build(); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> new MetricSnapshots(classic, gauge)) + .withMessageContaining("conflicting histogram types"); + } + + @Test + void testBuilder() { CounterSnapshot counter = CounterSnapshot.builder() .name("my_metric") @@ -75,7 +103,7 @@ public void testBuilder() { } @Test - public void testImmutable() { + void testImmutable() { CounterSnapshot c1 = CounterSnapshot.builder() .name("counter1") diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/NativeHistogramBucketsTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/NativeHistogramBucketsTest.java index 32c7f3eb3..ed52a7d1a 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/NativeHistogramBucketsTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/NativeHistogramBucketsTest.java @@ -9,7 +9,7 @@ class NativeHistogramBucketsTest { @Test - public void testGoodCase() { + void testGoodCase() { NativeHistogramBuckets buckets = NativeHistogramBuckets.builder().bucket(-10, 12).bucket(120, 17).build(); assertThat(buckets.size()).isEqualTo(2); @@ -20,13 +20,13 @@ public void testGoodCase() { } @Test - public void testEmpty() { + void testEmpty() { NativeHistogramBuckets buckets = NativeHistogramBuckets.builder().build(); assertThat(buckets.size()).isZero(); } @Test - public void testSort() { + void testSort() { NativeHistogramBuckets buckets = NativeHistogramBuckets.builder().bucket(7, 4).bucket(2, 0).bucket(5, 3).build(); assertThat(buckets.size()).isEqualTo(3); @@ -39,7 +39,7 @@ public void testSort() { } @Test - public void testDifferentLength() { + void testDifferentLength() { int[] bucketIndexes = new int[] {0, 1, 2}; long[] cumulativeCounts = new long[] {13, 178, 1024, 3000}; assertThatExceptionOfType(IllegalArgumentException.class) @@ -47,7 +47,7 @@ public void testDifferentLength() { } @Test - public void testImmutable() { + void testImmutable() { NativeHistogramBuckets buckets = NativeHistogramBuckets.builder().bucket(1, 1).bucket(2, 1).build(); Iterator iterator = buckets.iterator(); diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/PrometheusNamingTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/PrometheusNamingTest.java index 40c1f1bde..847bb0f38 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/PrometheusNamingTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/PrometheusNamingTest.java @@ -21,7 +21,7 @@ class PrometheusNamingTest { @Test - public void testSanitizeMetricName() { + void testSanitizeMetricName() { assertThat(sanitizeMetricName("my_counter_total")).isEqualTo("my_counter"); assertThat(sanitizeMetricName("jvm.info")).isEqualTo("jvm"); assertThat(sanitizeMetricName("jvm_info")).isEqualTo("jvm"); @@ -32,7 +32,7 @@ public void testSanitizeMetricName() { } @Test - public void testSanitizeMetricNameWithUnit() { + void testSanitizeMetricNameWithUnit() { assertThat(prometheusName(sanitizeMetricName("def", Unit.RATIO))) .isEqualTo("def_" + Unit.RATIO); assertThat(prometheusName(sanitizeMetricName("my_counter_total", Unit.RATIO))) @@ -43,7 +43,7 @@ public void testSanitizeMetricNameWithUnit() { } @Test - public void testSanitizeLabelName() { + void testSanitizeLabelName() { assertThat(prometheusName(sanitizeLabelName("0abc.def"))).isEqualTo("_abc_def"); assertThat(prometheusName(sanitizeLabelName("_abc"))).isEqualTo("_abc"); assertThat(prometheusName(sanitizeLabelName("__abc"))).isEqualTo("_abc"); @@ -54,7 +54,7 @@ public void testSanitizeLabelName() { } @Test - public void testValidateUnitName() { + void testValidateUnitName() { assertThat(validateUnitName("secondstotal")).isNotNull(); assertThat(validateUnitName("total")).isNotNull(); assertThat(validateUnitName("seconds_total")).isNotNull(); @@ -66,7 +66,7 @@ public void testValidateUnitName() { } @Test - public void testSanitizeUnitName() { + void testSanitizeUnitName() { assertThat(sanitizeUnitName("seconds")).isEqualTo("seconds"); assertThat(sanitizeUnitName("seconds_total")).isEqualTo("seconds"); assertThat(sanitizeUnitName("seconds_total_total")).isEqualTo("seconds"); @@ -76,25 +76,25 @@ public void testSanitizeUnitName() { } @Test - public void testInvalidUnitName1() { + void testInvalidUnitName1() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> sanitizeUnitName("total")); } @Test - public void testInvalidUnitName2() { + void testInvalidUnitName2() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> sanitizeUnitName("_total")); } @Test - public void testInvalidUnitName3() { + void testInvalidUnitName3() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> sanitizeUnitName("%")); } @Test - public void testEmptyUnitName() { + void testEmptyUnitName() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> sanitizeUnitName("")); } diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/QuantilesTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/QuantilesTest.java index 8703657ca..4ccadddc8 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/QuantilesTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/QuantilesTest.java @@ -9,7 +9,7 @@ class QuantilesTest { @Test - public void testSort() { + void testSort() { Quantiles quantiles = Quantiles.builder().quantile(0.99, 0.23).quantile(0.5, 0.2).quantile(0.95, 0.22).build(); assertThat(quantiles.size()).isEqualTo(3); @@ -22,7 +22,7 @@ public void testSort() { } @Test - public void testImmutable() { + void testImmutable() { Quantiles quantiles = Quantiles.builder().quantile(0.99, 0.23).quantile(0.5, 0.2).quantile(0.95, 0.22).build(); Iterator iterator = quantiles.iterator(); @@ -31,12 +31,12 @@ public void testImmutable() { } @Test - public void testEmpty() { + void testEmpty() { assertThat(Quantiles.EMPTY.size()).isZero(); } @Test - public void testDuplicate() { + void testDuplicate() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/SnapshotEscaperTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/SnapshotEscaperTest.java index f84024e95..5c04719c0 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/SnapshotEscaperTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/SnapshotEscaperTest.java @@ -15,7 +15,7 @@ class SnapshotEscaperTest { @Test - public void testEscapeMetricSnapshotEmpty() { + void testEscapeMetricSnapshotEmpty() { MetricSnapshot original = CounterSnapshot.builder().name("empty").build(); MetricSnapshot got = escapeMetricSnapshot(original, EscapingScheme.VALUE_ENCODING_ESCAPING); assertThat(Objects.requireNonNull(got).getMetadata().getName()).isEqualTo("empty"); @@ -23,7 +23,7 @@ public void testEscapeMetricSnapshotEmpty() { } @Test - public void testEscapeMetricSnapshotSimpleNoEscapingNeeded() { + void testEscapeMetricSnapshotSimpleNoEscapingNeeded() { testEscapeMetricSnapshot( "my_metric", "some_label", @@ -36,7 +36,7 @@ public void testEscapeMetricSnapshotSimpleNoEscapingNeeded() { } @Test - public void testEscapeMetricSnapshotLabelNameEscapingNeeded() { + void testEscapeMetricSnapshotLabelNameEscapingNeeded() { testEscapeMetricSnapshot( "my_metric", "some.label", @@ -49,7 +49,7 @@ public void testEscapeMetricSnapshotLabelNameEscapingNeeded() { } @Test - public void testEscapeMetricSnapshotCounterEscapingNeeded() { + void testEscapeMetricSnapshotCounterEscapingNeeded() { testEscapeMetricSnapshot( "my.metric", "some?label", @@ -62,7 +62,7 @@ public void testEscapeMetricSnapshotCounterEscapingNeeded() { } @Test - public void testEscapeMetricSnapshotGaugeEscapingNeeded() { + void testEscapeMetricSnapshotGaugeEscapingNeeded() { testEscapeMetricSnapshot( "unicode.and.dots.花火", "some_label", diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/SnapshotTestUtil.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/SnapshotTestUtil.java index d8e8d33e4..8a8a7f93b 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/SnapshotTestUtil.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/SnapshotTestUtil.java @@ -2,7 +2,7 @@ import static org.assertj.core.api.Assertions.assertThat; -class SnapshotTestUtil { +public class SnapshotTestUtil { public static void assertMetadata( MetricSnapshot snapshot, String name, String help, String unit) { diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/StateSetSnapshotTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/StateSetSnapshotTest.java index 05e102b9d..02d16e64f 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/StateSetSnapshotTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/StateSetSnapshotTest.java @@ -10,7 +10,7 @@ class StateSetSnapshotTest { @Test - public void testCompleteGoodCase() { + void testCompleteGoodCase() { long scrapeTimestamp = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1); StateSetSnapshot snapshot = StateSetSnapshot.builder() @@ -49,7 +49,7 @@ public void testCompleteGoodCase() { } @Test - public void testStateSetDataSorted() { + void testStateSetDataSorted() { StateSetSnapshot.StateSetDataPointSnapshot data = StateSetSnapshot.StateSetDataPointSnapshot.builder() .state("b", true) @@ -69,14 +69,14 @@ public void testStateSetDataSorted() { } @Test - public void testMustHaveState() { + void testMustHaveState() { // Must have at least one state. assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> StateSetSnapshot.StateSetDataPointSnapshot.builder().build()); } @Test - public void testMinimal() { + void testMinimal() { StateSetSnapshot snapshot = StateSetSnapshot.builder() .name("my_flag") @@ -87,13 +87,13 @@ public void testMinimal() { } @Test - public void testEmpty() { + void testEmpty() { StateSetSnapshot snapshot = StateSetSnapshot.builder().name("my_flag").build(); assertThat(snapshot.dataPoints).isEmpty(); } @Test - public void testDataImmutable() { + void testDataImmutable() { StateSetSnapshot.StateSetDataPointSnapshot data = StateSetSnapshot.StateSetDataPointSnapshot.builder() .state("a", true) @@ -111,7 +111,7 @@ public void testDataImmutable() { } @Test - public void testDuplicateState() { + void testDuplicateState() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> @@ -123,13 +123,13 @@ public void testDuplicateState() { } @Test - public void noUnit() { + void noUnit() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> StateSetSnapshot.builder().name("flags").unit(Unit.BYTES).build()); } @Test - public void testStateSetImmutable() { + void testStateSetImmutable() { StateSetSnapshot snapshot = StateSetSnapshot.builder() .name("flags") @@ -151,7 +151,7 @@ public void testStateSetImmutable() { } @Test - public void testLabelsUnique() { + void testLabelsUnique() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/SummarySnapshotTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/SummarySnapshotTest.java index df423ba97..8cd9571f5 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/SummarySnapshotTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/SummarySnapshotTest.java @@ -9,7 +9,7 @@ class SummarySnapshotTest { @Test - public void testCompleteGoodCase() { + void testCompleteGoodCase() { long createdTimestamp = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1); long scrapeTimestamp = System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(2); long exemplarTimestamp = System.currentTimeMillis(); @@ -82,7 +82,7 @@ public void testCompleteGoodCase() { } @Test - public void testMinimal() { + void testMinimal() { SummarySnapshot snapshot = SummarySnapshot.builder() .name("size_bytes") @@ -95,13 +95,13 @@ public void testMinimal() { } @Test - public void testEmptySnapshot() { + void testEmptySnapshot() { SummarySnapshot snapshot = SummarySnapshot.builder().name("empty_summary").build(); assertThat(snapshot.getDataPoints()).isEmpty(); } @Test - public void testEmptyData() { + void testEmptyData() { SummarySnapshot.SummaryDataPointSnapshot data = SummarySnapshot.SummaryDataPointSnapshot.builder().build(); assertThat(data.getQuantiles().size()).isZero(); diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/UnitTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/UnitTest.java index 4585e7281..e288a2375 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/UnitTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/UnitTest.java @@ -8,12 +8,12 @@ class UnitTest { @Test - public void testEmpty() { + void testEmpty() { assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> new Unit(" ")); } @Test - public void testEquals1() { + void testEquals1() { Unit unit1 = Unit.BYTES; Unit unit2 = new Unit("bytes"); @@ -21,7 +21,7 @@ public void testEquals1() { } @Test - public void testEquals2() { + void testEquals2() { Unit unit1 = new Unit("bytes "); Unit unit2 = new Unit("bytes"); @@ -29,7 +29,7 @@ public void testEquals2() { } @Test - public void testEquals3() { + void testEquals3() { Unit unit1 = new Unit(" bytes"); Unit unit2 = new Unit("bytes"); @@ -37,7 +37,7 @@ public void testEquals3() { } @Test - public void testEquals4() { + void testEquals4() { Unit unit1 = new Unit(" bytes "); Unit unit2 = new Unit("bytes"); diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/UnknownSnapshotTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/UnknownSnapshotTest.java index 53df0a95d..33b4ac2b4 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/UnknownSnapshotTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/UnknownSnapshotTest.java @@ -9,7 +9,7 @@ class UnknownSnapshotTest { @Test - public void testCompleteGoodCase() { + void testCompleteGoodCase() { long exemplarTimestamp = System.currentTimeMillis(); UnknownSnapshot snapshot = UnknownSnapshot.builder() @@ -46,7 +46,7 @@ public void testCompleteGoodCase() { } @Test - public void testMinimal() { + void testMinimal() { UnknownSnapshot snapshot = UnknownSnapshot.builder() .name("test") @@ -56,25 +56,25 @@ public void testMinimal() { } @Test - public void testEmpty() { + void testEmpty() { UnknownSnapshot snapshot = UnknownSnapshot.builder().name("test").build(); assertThat(snapshot.getDataPoints()).isEmpty(); } @Test - public void testNameMissing() { + void testNameMissing() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> UnknownSnapshot.builder().build()); } @Test - public void testValueMissing() { + void testValueMissing() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> UnknownSnapshot.UnknownDataPointSnapshot.builder().build()); } @Test - public void testUnknownDataPointSnapshot() { + void testUnknownDataPointSnapshot() { Labels labels = Labels.of("k1", "v1"); Exemplar exemplar = Exemplar.builder().value(2.0).build(); diff --git a/prometheus-metrics-otel-support/pom.xml b/prometheus-metrics-otel-support/pom.xml new file mode 100644 index 000000000..18328637e --- /dev/null +++ b/prometheus-metrics-otel-support/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + + io.prometheus + client_java + 1.6.0-SNAPSHOT + + + prometheus-metrics-otel-support + pom + + Prometheus Metrics OpenTelemetry Support + + Bundles the OpenTelemetry SDK and Prometheus exporter so that users + who want to combine OTel instrumentations with the Prometheus Java + client only need a single dependency. + + + + true + true + true + true + + + + + + io.opentelemetry.instrumentation + opentelemetry-instrumentation-bom-alpha + ${otel.instrumentation.version} + pom + import + + + + + + + io.opentelemetry + opentelemetry-sdk + + + io.opentelemetry + opentelemetry-exporter-prometheus + + + diff --git a/prometheus-metrics-parent/pom.xml b/prometheus-metrics-parent/pom.xml index 075eaf782..f70317154 100644 --- a/prometheus-metrics-parent/pom.xml +++ b/prometheus-metrics-parent/pom.xml @@ -7,7 +7,7 @@ io.prometheus client_java_parent - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT Prometheus Metrics Library Parent http://github.com/prometheus/client_java @@ -68,29 +68,39 @@ - - com.diffplug.spotless - spotless-maven-plugin - 3.1.0 - - - - - ${spotless.skip} - - - - verify - - check - - - - + + java17-plus + + [17,) + + + + + com.diffplug.spotless + spotless-maven-plugin + 3.2.1 + + + + + ${spotless.skip} + + + + verify + + check + + + + + + + release diff --git a/prometheus-metrics-simpleclient-bridge/pom.xml b/prometheus-metrics-simpleclient-bridge/pom.xml index e15a5631c..80ae0b6e4 100644 --- a/prometheus-metrics-simpleclient-bridge/pom.xml +++ b/prometheus-metrics-simpleclient-bridge/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-simpleclient-bridge diff --git a/prometheus-metrics-simpleclient-bridge/src/test/java/io/prometheus/metrics/simpleclient/bridge/SimpleclientCollectorTest.java b/prometheus-metrics-simpleclient-bridge/src/test/java/io/prometheus/metrics/simpleclient/bridge/SimpleclientCollectorTest.java index a17ed8bc4..3905f8f42 100644 --- a/prometheus-metrics-simpleclient-bridge/src/test/java/io/prometheus/metrics/simpleclient/bridge/SimpleclientCollectorTest.java +++ b/prometheus-metrics-simpleclient-bridge/src/test/java/io/prometheus/metrics/simpleclient/bridge/SimpleclientCollectorTest.java @@ -30,14 +30,14 @@ class SimpleclientCollectorTest { private PrometheusRegistry newRegistry; @BeforeEach - public void setUp() { + void setUp() { origRegistry = new CollectorRegistry(); newRegistry = new PrometheusRegistry(); SimpleclientCollector.builder().collectorRegistry(origRegistry).register(newRegistry); } @Test - public void testCounterComplete() throws IOException, InterruptedException { + void testCounterComplete() throws IOException, InterruptedException { Counter counter = Counter.build() .name("service_time_seconds_total") @@ -52,14 +52,14 @@ public void testCounterComplete() throws IOException, InterruptedException { } @Test - public void testCounterMinimal() throws IOException { + void testCounterMinimal() throws IOException { Counter.build().name("events").help("total number of events").register(origRegistry); assertThat(sort(newOpenMetrics())).isEqualTo(fixTimestamps(sort(origOpenMetrics()))); } @Test - public void testGaugeComplete() throws IOException, InterruptedException { + void testGaugeComplete() throws IOException, InterruptedException { Gauge gauge = Gauge.build() .name("disk_usage_ratio") @@ -75,7 +75,7 @@ public void testGaugeComplete() throws IOException, InterruptedException { } @Test - public void testGaugeMinimal() throws IOException { + void testGaugeMinimal() throws IOException { Gauge gauge = Gauge.build() .name("temperature_centigrade") @@ -88,7 +88,7 @@ public void testGaugeMinimal() throws IOException { } @Test - public void testHistogramComplete() throws IOException, InterruptedException { + void testHistogramComplete() throws IOException, InterruptedException { Histogram histogram = Histogram.build() .name("response_size_bytes") @@ -108,14 +108,14 @@ public void testHistogramComplete() throws IOException, InterruptedException { } @Test - public void testHistogramMinimal() throws IOException { + void testHistogramMinimal() throws IOException { Histogram.build().name("request_latency").help("request latency").register(origRegistry); assertThat(sort(newOpenMetrics())).isEqualTo(fixCounts(fixTimestamps(sort(origOpenMetrics())))); } @Test - public void testSummaryComplete() throws IOException, InterruptedException { + void testSummaryComplete() throws IOException, InterruptedException { Summary summary = Summary.build() .name("http_request_duration_seconds") @@ -139,14 +139,14 @@ public void testSummaryComplete() throws IOException, InterruptedException { } @Test - public void testSummaryMinimal() throws IOException { + void testSummaryMinimal() throws IOException { Summary.build().name("request_size").help("request size").register(origRegistry); assertThat(sort(newOpenMetrics())).isEqualTo(fixCounts(fixTimestamps(sort(origOpenMetrics())))); } @Test - public void testInfoComplete() throws IOException, InterruptedException { + void testInfoComplete() throws IOException, InterruptedException { Info info = Info.build() .name("version") @@ -161,7 +161,7 @@ public void testInfoComplete() throws IOException, InterruptedException { } @Test - public void testInfoMinimal() throws IOException { + void testInfoMinimal() throws IOException { Info info = Info.build().name("jvm").help("JVM info").register(origRegistry); info.info("version", "17"); @@ -169,7 +169,7 @@ public void testInfoMinimal() throws IOException { } @Test - public void testStateSetComplete() throws IOException { + void testStateSetComplete() throws IOException { Collector stateSet = new Collector() { @Override @@ -192,7 +192,7 @@ public List collect() { } @Test - public void testUnknownComplete() throws IOException { + void testUnknownComplete() throws IOException { Collector unknown = new Collector() { @Override diff --git a/prometheus-metrics-tracer/pom.xml b/prometheus-metrics-tracer/pom.xml index 15ea09307..a97ae0a54 100644 --- a/prometheus-metrics-tracer/pom.xml +++ b/prometheus-metrics-tracer/pom.xml @@ -6,7 +6,7 @@ io.prometheus client_java - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-tracer diff --git a/prometheus-metrics-tracer/prometheus-metrics-tracer-common/pom.xml b/prometheus-metrics-tracer/prometheus-metrics-tracer-common/pom.xml index 573e78801..11d4fcc80 100644 --- a/prometheus-metrics-tracer/prometheus-metrics-tracer-common/pom.xml +++ b/prometheus-metrics-tracer/prometheus-metrics-tracer-common/pom.xml @@ -6,7 +6,7 @@ io.prometheus prometheus-metrics-tracer - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-tracer-common diff --git a/prometheus-metrics-tracer/prometheus-metrics-tracer-initializer/pom.xml b/prometheus-metrics-tracer/prometheus-metrics-tracer-initializer/pom.xml index 2d15be029..07dc768f5 100644 --- a/prometheus-metrics-tracer/prometheus-metrics-tracer-initializer/pom.xml +++ b/prometheus-metrics-tracer/prometheus-metrics-tracer-initializer/pom.xml @@ -6,7 +6,7 @@ io.prometheus prometheus-metrics-tracer - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-tracer-initializer diff --git a/prometheus-metrics-tracer/prometheus-metrics-tracer-otel-agent/pom.xml b/prometheus-metrics-tracer/prometheus-metrics-tracer-otel-agent/pom.xml index be140167d..4db6ea530 100644 --- a/prometheus-metrics-tracer/prometheus-metrics-tracer-otel-agent/pom.xml +++ b/prometheus-metrics-tracer/prometheus-metrics-tracer-otel-agent/pom.xml @@ -7,7 +7,7 @@ io.prometheus prometheus-metrics-tracer - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-tracer-otel-agent diff --git a/prometheus-metrics-tracer/prometheus-metrics-tracer-otel/pom.xml b/prometheus-metrics-tracer/prometheus-metrics-tracer-otel/pom.xml index 3dda51c6b..955d1cf34 100644 --- a/prometheus-metrics-tracer/prometheus-metrics-tracer-otel/pom.xml +++ b/prometheus-metrics-tracer/prometheus-metrics-tracer-otel/pom.xml @@ -6,7 +6,7 @@ io.prometheus prometheus-metrics-tracer - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT prometheus-metrics-tracer-otel