Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added default mapper for mapping logstash config models to data prepper plugin model #559

Merged
merged 3 commits into from
Nov 11, 2021

Conversation

asifsmohammed
Copy link
Collaborator

@asifsmohammed asifsmohammed commented Nov 9, 2021

Signed-off-by: Asif Sohail Mohammed [email protected]

Description

Added default plugin mapper to convert Logstash config to Data Prepper models.
Added LogstashMappingException class for exceptions during mapping

Issues Resolved

#466

Check List

  • New functionality includes testing.
    • All tests pass
  • New functionality has been documented.
    • New functionality has javadoc added
  • Commits are signed per the DCO using --signoff

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.

@codecov-commenter
Copy link

codecov-commenter commented Nov 9, 2021

Codecov Report

Merging #559 (90af350) into main (52e0468) will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff            @@
##               main     #559   +/-   ##
=========================================
  Coverage     92.28%   92.28%           
  Complexity      569      569           
=========================================
  Files            71       71           
  Lines          1725     1725           
  Branches        144      144           
=========================================
  Hits           1592     1592           
  Misses          102      102           
  Partials         31       31           

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 52e0468...90af350. Read the comment docs.

@@ -12,5 +14,5 @@
* @param logstashPlugin A Logstash plugin with its attributes
* @return A Data Prepper plugin with its attributes
*/
PluginModel mapPlugin(LogstashPlugin logstashPlugin);
PluginModel mapPlugin(LogstashPlugin logstashPlugin) throws IOException;
Copy link
Member

Choose a reason for hiding this comment

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

This should not throw IOException. We should wrap any such exceptions in the LogstashMappingException.

throw new LogstashMappingException("file not found! " + logstashPlugin.getPluginName() + ".mapping.yaml");
}

LogstashMappingModel logstashMappingModel = objectMapper.readValue(inputStream, LogstashMappingModel.class);
Copy link
Member

Choose a reason for hiding this comment

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

Please catch this IOException and wrap it in a LogstashMappingException.

Something like:

try {
    logstashMappingModel = objectMapper.readValue(inputStream, LogstashMappingModel.class);
} catch(IOException ex) {
    throw new LogstashMappingException("Unable to parse mapping file " + logstashPlugin.getPluginName() + ".mapping.yaml", ex);
}

You will need to add an overloaded constructor to LogstashMappingException.

*/
public class LogstashMappingException extends LogstashConfigurationException{

public LogstashMappingException(String errorMessage) {
Copy link
Member

Choose a reason for hiding this comment

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

Per my comment on wrapping IOException, you will need another constructor with (String message, Exception inner).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks, I'll update LogstashMappingException

@Override
public PluginModel mapPlugin(LogstashPlugin logstashPlugin) throws IOException {

InputStream inputStream = getClass().getClassLoader().getResourceAsStream(logstashPlugin.getPluginName() + ".mapping.yaml");
Copy link
Member

Choose a reason for hiding this comment

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

Please extract a variable for this: logstashPlugin.getPluginName() + ".mapping.yaml".

You use it below.

And another comment suggests another place to use it.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would like to get a uniform naming convention on this.
Are we using extension .yml or .yaml or supporting both?
In our configuration README, we mention .yaml but in our examples we use .yml

Copy link
Member

Choose a reason for hiding this comment

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

I think we should use .yaml consistently.

It is also FAQ 1 out of 2.

https://yaml.org/faq.html


InputStream inputStream = getClass().getClassLoader().getResourceAsStream(logstashPlugin.getPluginName() + ".mapping.yaml");
if (inputStream == null) {
throw new LogstashMappingException("file not found! " + logstashPlugin.getPluginName() + ".mapping.yaml");
Copy link
Member

Choose a reason for hiding this comment

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

Please rename this to: "Unable to find mapping resource " + ....


LogstashMappingModel logstashMappingModel = objectMapper.readValue(inputStream, LogstashMappingModel.class);
if (logstashMappingModel.getPluginName() == null)
throw new LogstashMappingException("plugin name cannot be null in mapping.yaml");
Copy link
Member

Choose a reason for hiding this comment

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

I'd like to see the following in this message:

  • The actual name of the mapping resources (using extracted variable I suggested above).
  • The property name as defined in the LogstashMappingModel: pluginName.

Perhaps something like: "The mapping file " + mappingResourceName + " has a null value for 'pluginName'.".

(String) logstashMappingModel.getMappedAttributes().get(logstashAttribute.getAttributeName()),
logstashAttribute.getAttributeValue().getValue()
);
}
Copy link
Member

Choose a reason for hiding this comment

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

I think we may wish to log a warning for unmapped Logstash attributes, in an else.

logstashPlugin.getAttributes().forEach(logstashAttribute -> {
if (logstashMappingModel.getMappedAttributes().containsKey(logstashAttribute.getAttributeName())) {
pluginSettings.put(
(String) logstashMappingModel.getMappedAttributes().get(logstashAttribute.getAttributeName()),
Copy link
Member

Choose a reason for hiding this comment

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

We should change the model for getMappedAttributes. It should be Map<String, String> since it always maps names.

Also, I think it might be clearer to rename it to attributeNames.

*
* @since 1.2
*/
public class DefaultPluginMapper implements LogstashPluginMapper {
Copy link
Member

Choose a reason for hiding this comment

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

This class should have unit tests as well.

@@ -11,6 +11,9 @@ repositories {
dependencies {
antlr "org.antlr:antlr4:4.9.2"
implementation project(':data-prepper-api')
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml'
implementation 'com.fasterxml.jackson.core:jackson-databind'
implementation 'org.slf4j:slf4j-simple:1.7.32'
Copy link
Member

Choose a reason for hiding this comment

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

This should be testImplementation if we use it all. Otherwise, it goes into the main classpath, but there should be only one SLF4J in the classpath.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Without this there's a warning and it's not showing the Log.warn message in log
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.


@BeforeEach
void createObjectUnderTest() {
defaultPluginMapper = spy(new DefaultPluginMapper());
Copy link
Member

Choose a reason for hiding this comment

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

Does this need to be a Spy?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, It's not required

dlvenable
dlvenable previously approved these changes Nov 11, 2021
@@ -0,0 +1,8 @@
pluginName: opensearch
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor: Would it be clearer if the file name is something like: logstash_to_dataprepper_config.mapping.yaml
Minor: it would be nicer to cover more valid configuration mappings in the unit tests, such as username, password, and many more.

It's unit test. I am OK with you adding more tests later. I will approve the pull request now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks, I'll will add more tests later

@asifsmohammed asifsmohammed merged commit cd0f617 into opensearch-project:main Nov 11, 2021
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.

5 participants