Skip to content

feat!: Send product metadata in custom header#13

Open
liamhughes wants to merge 16 commits into
mainfrom
liamhughes/devex-43-send-product-metadata-from-provider-libraries
Open

feat!: Send product metadata in custom header#13
liamhughes wants to merge 16 commits into
mainfrom
liamhughes/devex-43-send-product-metadata-from-provider-libraries

Conversation

@liamhughes
Copy link
Copy Markdown
Contributor

@liamhughes liamhughes commented May 25, 2026

Background

We want to be able to observe the usage of the OctoToggle service and its different API endpoints over time. For example, if we wish to deprecate an endpoint or know which customers are using a particular version of a provider library.

This PR is the Java equivalent of OctopusDeploy/openfeature-provider-dotnet#52.

Changes

  • Added ProductMetadata class to clean, validate and contain the consumer provided product name and version values.
    • These values must contain at least one valid character (per RFC 9110). Any invalid characters are silently stripped out.
  • Added ProductMetadata required argument to OctopusConfiguration (breaking change).
  • Added project.properties file with resource filtering to allow access to the provider library version (as defined in pom.xml) in the Java code.
  • Added X-Octopus-Client header to HTTP request builder calls.
    • The value of this header contains:
      • Consumer provided product name.
      • Optionally: consumer provided product version.
      • Hard coded provider library repo name.
      • The provider library's version number.
    • e.g. MyProduct/2024.1.0 openfeature-provider-java/0.4.0-SNAPSHOT

Testing

In addition to automated tests, I have tested against an OctoToggle ephemeral environment.

With product version

image

Without product version

image

logger.log(System.Logger.Level.WARNING, "Unable to load project properties to determine provider version.", e);
}

clientHeaderValueBuilder.append(" openfeature-provider-java/").append(providerVersion);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If providerVersion is null this will append "null".

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds consumer-supplied product metadata (name + optional version) into an X-Octopus-Client header on OctoToggle HTTP requests, enabling endpoint/version usage observability for the Java provider. This introduces a breaking change by making ProductMetadata a required part of OctopusConfiguration.

Changes:

  • Introduce ProductMetadata for cleaning/validating product name/version (RFC 9110 token chars) and add corresponding unit tests.
  • Make OctopusConfiguration require ProductMetadata and plumb it through request-building to emit X-Octopus-Client.
  • Add Maven resource filtering + project.properties to inject the provider library version into the header, with tests for the composed header value.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/main/java/com/octopus/openfeature/provider/ProductMetadata.java Adds a value object that sanitizes and validates product name/version inputs.
src/main/java/com/octopus/openfeature/provider/OctopusConfiguration.java Makes ProductMetadata a required configuration field and exposes it to internal components.
src/main/java/com/octopus/openfeature/provider/OctopusClient.java Adds X-Octopus-Client header and builds its value including provider version.
src/main/resources/project.properties New filtered resource to surface ${project.version} at runtime.
pom.xml Enables resource filtering so project.properties is populated during build.
src/test/java/com/octopus/openfeature/provider/ProductMetadataTests.java Unit tests for sanitization/validation rules in ProductMetadata.
src/test/java/com/octopus/openfeature/provider/OctopusClientTests.java Tests for the constructed X-Octopus-Client header value and filtered version injection.
src/test/java/com/octopus/openfeature/provider/OctopusConfigurationTests.java Updates tests for the new OctopusConfiguration constructor signature.
src/test/java/com/octopus/openfeature/provider/SpecificationTests.java Updates spec tests to pass required ProductMetadata.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/main/java/com/octopus/openfeature/provider/OctopusClient.java Outdated
Comment thread src/main/java/com/octopus/openfeature/provider/OctopusClient.java Outdated
Comment thread src/main/java/com/octopus/openfeature/provider/OctopusClient.java
Comment thread src/test/java/com/octopus/openfeature/provider/OctopusClientTests.java Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comment thread pom.xml
@liamhughes liamhughes marked this pull request as ready for review May 25, 2026 06:25
@liamhughes liamhughes requested a review from a team as a code owner May 25, 2026 06:25
private static String loadProviderVersion() {
try {
var projectProperties = new Properties();
try (var resourceStream = OctopusClient.class.getClassLoader().getResourceAsStream("project.properties"))
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this try is a try-with-resources block; equivalent to C# using(var ...)


private static final String PROVIDER_VERSION = loadProviderVersion();

private static String loadProviderVersion() {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought from a background thread in my brain: perhaps I should just load this value directly from the pom.xml file in the tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants