-
Notifications
You must be signed in to change notification settings - Fork 207
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
Grok Prepper Configuration and Boilerplate #302
Conversation
Signed-off-by: graytaylor0 <[email protected]>
} | ||
|
||
dependencies { | ||
implementation "com.fasterxml.jackson.core:jackson-databind:2.12.4" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we have this already defined higher up in the hierarchy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We actually don't. Could add this as a dependency to data-prepper-plugins but right now each individual plugin adds this if it is used. We do have mavenCentral() as part of the project's build.gradle but other plugins that have used dependencies from mavenCentral() had it again. Maybe they don't need it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not a dependency, but you can inherit the version number. So, you should remove the version number from this line.
See: https://github.com/opensearch-project/data-prepper/blob/main/build.gradle#L74
import java.util.Collections; | ||
import java.util.List; | ||
|
||
public class GrokPrepperTests { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are going to be adding more tests in here, right? ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha there will be more when actual functionality is added.
((List<?>) object).stream().filter(o -> !(o instanceof String)).forEach(o -> { | ||
throw new IllegalArgumentException(String.format(UNEXPECTED_ATTRIBUTE_TYPE_MSG, object.getClass(), attribute)); | ||
}); | ||
return (List<String>) object; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be simplified:
((List<?>) object).).forEach(o -> {
if (!(o instanceof String)) {
throw new IllegalArgumentException(String.format(UNEXPECTED_ATTRIBUTE_TYPE_MSG, object.getClass(), attribute));
}
}
* @return the value of the specified attribute, or {@code defaultValue} if this settings contains no value for | ||
* the attribute | ||
*/ | ||
@SuppressWarnings("unchecked") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is dangerous. What are we suppressing here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It suppresses this warning which only comes from Intellij as far as I can tell.
Unchecked cast: 'java.lang.Object' to 'java.util.Map<java.lang.String,java.util.List<java.lang.String>>'
. It is because of the cast on the return values from Object.
((List<?>) value).stream().filter(o -> !(o instanceof String)).forEach(o -> { | ||
throw new IllegalArgumentException(String.format(UNEXPECTED_ATTRIBUTE_TYPE_MSG, object.getClass(), attribute)); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See other comment above about improving this check
Signed-off-by: graytaylor0 <[email protected]>
import com.amazon.dataprepper.model.record.Record; | ||
import org.junit.After; | ||
import org.junit.Before; | ||
import org.junit.Test; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should start using JUnit 5 for tests.
import java.util.Collection; | ||
|
||
|
||
@DataPrepperPlugin(name = "grok_prepper", type = PluginType.PREPPER) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should name this grok
so that users need only type grok
in the configuration file.
e.g.
prepper:
grok:
match: "log"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good note
dependencies { | ||
implementation project(':data-prepper-api') | ||
implementation project(':data-prepper-plugins:common') | ||
testImplementation project(':data-prepper-api').sourceSets.test.output |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we actually use this? Or was this line copied from another project?
* @return the value of the specified attribute, or {@code defaultValue} if this settings contains no value for | ||
* the attribute | ||
*/ | ||
public List<String> getStringListOrDefault(final String attribute, final List<String> defaultValue) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method and the other methods can probably be made somewhat more generic.
public <T> List<T> getTypedListOrDefault(final String attribute, final Class<T> type, final List<T> defaultValue)
You can replace your instanceof
with isAssignableFrom
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had thought about this and wasn't sure if passing the Class type was considered good practice. Doing this definitely scales PluginSettings better though.
Object object = getAttributeOrDefault(attribute, defaultValue); | ||
if (object == null) { | ||
return null; | ||
} else if (object instanceof Map) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code can be cleaner by throwing first.
I'd also create a variable just to avoid operating immediately after a cast, but I think that is of less importance.
if ( !(object instanceof Map))
throw new IllegalArgumentException(...)
Map<?, ?> map = object;
map.forEach( ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is definitely cleaner. Just to clarify you are not suggesting that this is done immediately after the getAttributeOrDefault call, but after the if statement for checking if object is null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the behavior of a null
value is to return null
, then it should be after the null check.
Object object = getAttributeOrDefault(attribute, defaultValue);
if (object == null) {
return null;
if ( !(object instanceof Map))
throw new IllegalArgumentException(...)
Map<?, ?> map = object;
map.forEach( ...
Object object = getAttributeOrDefault(attribute, defaultValue); | ||
if (object == null) { | ||
return null; | ||
} else if (object instanceof Map) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should try to avoid this nesting by throwing immediately. See my note above.
if (key instanceof String) { | ||
if (value instanceof List){ | ||
((List<?>) value).forEach(val -> { | ||
if (!(val instanceof String)) { | ||
throw new IllegalArgumentException(String.format(UNEXPECTED_ATTRIBUTE_TYPE_MSG, object.getClass(), attribute)); | ||
} | ||
}); | ||
} else { | ||
throw new IllegalArgumentException(String.format(UNEXPECTED_ATTRIBUTE_TYPE_MSG, object.getClass(), attribute)); | ||
} | ||
} else { | ||
throw new IllegalArgumentException(String.format(UNEXPECTED_ATTRIBUTE_TYPE_MSG, object.getClass(), attribute)); | ||
} | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instance check for String, List, Map is repeated in this class. Consider defining a function or java BiPredicate that takes in the object & type, and checks if they are of same type else throws exception. This code can be reused in different methods in this class.
Signed-off-by: graytaylor0 <[email protected]>
c49ec4e
to
40af804
Compare
@@ -180,4 +254,17 @@ public Long getLongOrDefault(final String attribute, final long defaultValue) { | |||
throw new IllegalArgumentException(String.format(UNEXPECTED_ATTRIBUTE_TYPE_MSG, object.getClass(), attribute)); | |||
} | |||
|
|||
private <T> void checkObjectType(String attribute, Object object, Class<T> type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: final for method params line 257 & 263 to be consistent with other methods
@@ -35,4 +35,5 @@ include 'data-prepper-plugins:otel-trace-group-prepper' | |||
include 'data-prepper-plugins:otel-trace-source' | |||
include 'data-prepper-plugins:peer-forwarder' | |||
include 'data-prepper-plugins:blocking-buffer' | |||
include 'data-prepper-plugins:grok-prepper' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you add this dependency? In general, our plugins should not depend on each other.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The settings.gradle file defines all of the internal projects. All of the plugin projects are required to go in here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are correct on this.
@@ -35,4 +35,5 @@ include 'data-prepper-plugins:otel-trace-group-prepper' | |||
include 'data-prepper-plugins:otel-trace-source' | |||
include 'data-prepper-plugins:peer-forwarder' | |||
include 'data-prepper-plugins:blocking-buffer' | |||
include 'data-prepper-plugins:grok-prepper' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are correct on this.
Signed-off-by: graytaylor0 [email protected]
Description
Issues Resolved
#301
Check List
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.