Skip to content

Added custom headers to cloudwatch logs sink#5906

Merged
dlvenable merged 2 commits into
opensearch-project:mainfrom
mzurita-amz:cwl-custom-headers
Jul 29, 2025
Merged

Added custom headers to cloudwatch logs sink#5906
dlvenable merged 2 commits into
opensearch-project:mainfrom
mzurita-amz:cwl-custom-headers

Conversation

@mzurita-amz
Copy link
Copy Markdown
Contributor

Description

This change adds support for custom HTTP headers in the CloudWatch Logs sink plugin. Users can now configure custom headers that will be included in all CloudWatch Logs API requests. The implementation includes:

• New custom_headers configuration option in CloudWatchLogsSinkConfig
• Updated CloudWatchLogsClientFactory to accept and apply custom headers to the AWS SDK client
• Comprehensive validation for header names and values following HTTP standards
• Maximum limit of 10 custom headers to prevent configuration bloat
• Logging of configured headers (names only, values redacted for security)
• Full backward compatibility - existing configurations continue to work unchanged

Issues Resolved

Resolves #5905

Check List

• [x] New functionality includes testing.
• Added comprehensive unit tests for configuration validation
• Added tests for client factory header integration
• Added tests for sink initialization with custom headers
• [ ] New functionality has a documentation issue. Please link to it in this PR.
• [x] New functionality has javadoc added
• [x] Commits are signed with a real name per the DCO

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

Signed-off-by: Manuel Mangas Zurita <mzurita@amazon.com>
Copy link
Copy Markdown
Member

@dlvenable dlvenable left a comment

Choose a reason for hiding this comment

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

Thank you @mzurita-amz for this contribution.

@Max(50)
private int workers = DEFAULT_NUM_WORKERS;

@JsonProperty("custom_headers")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For STS, we use a configuration named sts_header_overrides. We should stay consistent. So perhaps header_overrides would be a better name.

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.

Addressed

@Constraint(validatedBy = ValidCustomHeaders.CustomHeadersValidator.class)
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@interface ValidCustomHeaders {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Java standards call for one class per file. Please move this into another file in the same directory named ValidCustomHeaders.java.

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.

Addressed.

*
* @param customHeaders The custom headers map to log
*/
private void logCustomHeadersConfiguration(Map<String, String> customHeaders) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please add a conditional to prevent running any of this code (e.g. String.join) when the INFO logger is not enabled.

Here is an example on debug logging. It would be similar for INFO.

if (LOG.isDebugEnabled()) {
LOG.debug("Found {} extension classes.", extensionClasses.size());
LOG.debug("Extensions classes: {}",
extensionClasses.stream().map(Class::getName).collect(Collectors.joining(", ")));
}

Copy link
Copy Markdown
Contributor Author

@mzurita-amz mzurita-amz Jul 29, 2025

Choose a reason for hiding this comment

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

Addressed. I also removed the debug logging, as it was redundant.

public static CloudWatchLogsClient createCwlClient(final AwsConfig awsConfig,
final AwsCredentialsSupplier awsCredentialsSupplier,
final Map<String, String> customHeaders) {
final AwsCredentialsProvider awsCredentialsProvider = awsConfig != null
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please change this logic a little.

final AwsCredentialsOptions awsCredentialsOptions = awsConfig != null
  ? convertToCredentialOptions(awsConfig)
  : AwsCredentialsOptions.defaultOptions();
final AwsCredentialsProvider awsCredentialsProvider = awsCredentialsSupplier.getProvider(awsCredentialsOptions);

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.

Addressed

@mzurita-amz mzurita-amz force-pushed the cwl-custom-headers branch 2 times, most recently from 6c7e313 to be176b5 Compare July 29, 2025 09:04
@mzurita-amz
Copy link
Copy Markdown
Contributor Author

@dlvenable I've addressed your comments. The changes are in commit be176b5. Please take a look!

@mzurita-amz mzurita-amz requested a review from dlvenable July 29, 2025 09:07
dlvenable
dlvenable previously approved these changes Jul 29, 2025
Copy link
Copy Markdown
Member

@dlvenable dlvenable left a comment

Choose a reason for hiding this comment

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

Thank you @mzurita-amz !

* Rename custom_headers to header_overrides
* Move validator to separate file
* Refactor logging and credentials logic

Signed-off-by: Manuel Mangas Zurita <mzurita@amazon.com>
@mzurita-amz
Copy link
Copy Markdown
Contributor Author

mzurita-amz commented Jul 29, 2025

@dlvenable apologies, but I forgot to cleanup some unused imports on tests, and build failed after your approval. I think that by amending I can't access now the error. But I cleaned up the imports, and now I see it passing by running:


1. Compile the plugin:
  bash
   ./gradlew :data-prepper-plugins:cloudwatch-logs:compileJava


2. Run tests:
  bash
   ./gradlew :data-prepper-plugins:cloudwatch-logs:test


3. Run checkstyle on main source code:
  bash
   ./gradlew :data-prepper-plugins:cloudwatch-logs:checkstyleMain


4. Run checkstyle on test code:
  bash
   ./gradlew :data-prepper-plugins:cloudwatch-logs:checkstyleTest

@mzurita-amz mzurita-amz requested a review from dlvenable July 29, 2025 16:00
@dlvenable dlvenable merged commit 70ce8f7 into opensearch-project:main Jul 29, 2025
47 of 51 checks passed
@mzurita-amz mzurita-amz deleted the cwl-custom-headers branch July 30, 2025 08:41
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.

[CloudWatch Logs sink] Support for HTTP headers

3 participants