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
NIFI-2565: add Grok parser #1108
Conversation
@selim-namsi thanks for putting together. I was coding this processor but happy to review it. Few comments:
Thank you again, looking forward your modifications |
@trixpan Thank you for all this useful feedback, I'll start working on these modifications. Thanks |
You can certainly include a file with the default patterns, however you should not hardcode them. By hardcoding them you prevent the user from optimising for speed by removing unused patterns from the pattern files (I realise they can remove from the default packaged patterns but that means they would be changing packaged files after an install, something you should always avoid) |
By the way, most of these modifications are already available here: |
Please rebase this PR so it only include your changes. Cheers |
5cb2a31
to
632df23
Compare
@trixpan I figured out how to rebase the pull request :) Cheers |
632df23
to
94f8a96
Compare
@selim-namsi Thanks for contributing this! I have actually been very interested in using NiFi to do some log parsing but hadn't really dug in very much to understand the best way to go about it. This looks like it could be very powerful! Before we get this merged into the codebase, though, it looks like there is some work that needs to be done to the PR. The concern stems, I think, from you not yet being overly familiar with the API, as there are empty @ReadsAttributes, @WritesAttributes annotations, etc. But the great news is that the NiFi community tends to be very inclusive and will help to get everything in great shape! One thing that I did notice is that you updated the Licensing information, which is one of the most commonly overlooked issues. So very glad that's there. I'll leave some inline feedback on things that I notice, but very much looking forward to this getting in! |
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.
I did a fairly thorough code review here. There are a lot of comments, but most of them should be very easy to address. Looking forward to seeing a revised version and merging things in!
@SeeAlso({}) | ||
@ReadsAttributes({@ReadsAttribute(attribute="", description="")}) | ||
@WritesAttributes({@WritesAttribute(attribute="", description="")}) | ||
public class GrokParser extends AbstractProcessor { |
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 naming convention that we try to stick with for Processors is . While this may be counter-intuitive for a Java Developer, it results in making the flow much more readable for users. So we should consider ParseLog or GrokLog.
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.
@markap14 - this is not a parser but an extractor (Grok is a hyper regex) so I suggest the name to be ExtractGrok (after ExtractText)
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.
To this point, similar nomenclature has been used in other places:
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.
So the pattern of naming is 'Verb Subject'. It appears the point of this processor, from a users point of view (not the developers), is to evaluate Grok expressions against flow file content to replace that content with the result or to update a flow file attribute with that result. If that is the case we could take the approach of 'EvaluateGrok' or 'GrokEvaluateText' or 'ExtractGrok' is also fair game I think.
|
||
|
||
@Tags({"Grok Processor"}) | ||
@CapabilityDescription("Use Grok expression ,a la logstash, to parse data.") |
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 probably expand on this a bit more. Many users will not know what Grok is.
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.
Perhaps you can use the description used as part of my WIP.
"Evaluates one or more Grok Expressions against the content of a FlowFile, adding the results as attributes or replacing the content of the FlowFile with a JSON notation of the matched content"
?
import java.util.Collections; | ||
|
||
|
||
@Tags({"Grok Processor"}) |
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 consider several more tags: grok, log, text, parse, delimit, extract
|
||
@Tags({"Grok Processor"}) | ||
@CapabilityDescription("Use Grok expression ,a la logstash, to parse data.") | ||
@SeeAlso({}) |
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.
No need for the @Seealso, @ReadsAtributes, and @WritesAttributes annotations if they are not being used.
public static final PropertyDescriptor GROK_PATTERN_FILE = new PropertyDescriptor | ||
.Builder().name("Grok Pattern file") | ||
.description("Grok Pattern file definition") | ||
.required(false) |
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.
If this is not required, how will the processor work if not set?
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.
@markap14 In the first version of the code, I was loading few useful pattern files by default, so the user's custom pattern file was not required, but after removing that part I forgot to update the required attribute, I'll fix it
import java.nio.file.Paths; | ||
|
||
/** | ||
* Created by snamsi on 05/10/16. |
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 not have usernames here, as Git will provide this information for us.
|
||
} | ||
|
||
@Test(expected = java.lang.AssertionError.class) |
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.
Rather than expected an AssertionError, we should avoid calling testRunner.run() and instead just use testRunner.assertNotValid()
} | ||
|
||
|
||
@Test(expected = java.lang.AssertionError.class) |
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.
Rather than expected an AssertionError, we should avoid calling testRunner.run() and instead just use testRunner.assertNotValid()
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.
For this method "testGrokParserWithBadGrokExpression", although the processor is throwing GrokException, when I use assertNotValid, the test fails with the following message "java.lang.AssertionError: Processor appears to be valid but expected it to be invalid"
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.
After Adding a custom validator the test passes using assertNotValid
@@ -0,0 +1,108 @@ | |||
# Forked from https://github.com/elasticsearch/logstash/tree/v1.4.0/patterns |
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 have to ensure that we have proper licensing for these test files.
@@ -0,0 +1 @@ | |||
64.242.88.10 - - [07/Mar/2004:16:05:49 -0800] "GET /twiki/bin/edit/Main/Double_bounce_sender?topicparent=Main.ConfigurationVariables HTTP/1.1" 401 12846 |
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 have to ensure that we have proper licensing for these test files. This one may be one that you created yourself? If not, we need to ensure that its license is properly accounted for - or just mock out a new one.
@markap14 Thanks for all this suggestions, I'll update the code ASAP and push the changes! |
@selim-namsi - good work. We are getting there. |
e7a2833
to
44e6b64
Compare
Looks like there are new merge issues, do you mind rebasing against the latest master? |
4a4d733
to
3227372
Compare
341243b
to
7c0f6a8
Compare
@@ -26,6 +26,8 @@ | |||
import java.util.concurrent.TimeUnit; | |||
import java.util.regex.Pattern; | |||
|
|||
import oi.thekraken.grok.api.Grok; |
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 validation routine should not be added to standard validators in order to avoid importing grok into the standard validator
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.
agreed. Would just pull it into the processor class itself.
THE SOFTWARE. |
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 whole license section can be removed. This is the assembly license which is to cover all binary artifacts and source in the build of nifi itself. The dependency of java-grok is binary only (not source) and is ASLv2 so nothing needs to be in this license for it. There should be an entry for this in the notice similar to the many ASLv2 examples in there. The only thing needing mentioned then is the copyright line from the project's license file https://github.com/thekrakken/java-grok/blob/master/LICENSE. Also, this nifi-asembly/NOTICE change needed will also need to be in the NOTICE of the nifi-standard-nar as well.
Lots of words above but the short version is "No license change needed. Just add a small section to the nar NOTICE and assembly NOTICE to reflect this ASLv2 dependency specifically because it has a copyright reference in the license."
<dependency> | ||
<groupId>io.thekraken</groupId> | ||
<artifactId>grok</artifactId> | ||
<version>0.1.4</version> |
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.
A new version has been released today and contains important fixes (reduced depencies, better feature parity with logstash, etc). May I suggest we upgrade the dependency?
5eccbc5
to
291e855
Compare
291e855
to
c09d2cc
Compare
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.
@selim-namsi thanks for putting this together. I have made some minor feedback but they are minor so I don't think they should block merge.
import java.util.concurrent.TimeUnit; | ||
|
||
|
||
@Tags({"Grok Processor", "grok", "log", "text", "parse", "delimit", "extract"}) |
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.
"Grok Processor" looks a bit out of place but should not prevent merge.
"adding the results as attributes or replacing the content of the FlowFile with a JSON " + | ||
"notation of the matched content") | ||
@WritesAttributes({ | ||
@WritesAttribute(attribute = "grok.XXX", description = "Each of the Grok identifier that is matched in the flowfile will be added as an attribute, prefixed with \"grok.\" For example," + |
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.
Isn't this just applicable if using flowfile-attribute as destination?
@joewitt when you have time can you have a final look on this one? LGTM and I am happy to address the two remaining cosmetic comments as part of a separate PR. |
This closes apache#1108. Signed-off-by: Andre F de Miranda <trixpan@users.noreply.github.com>
Thank you for submitting a contribution to Apache NiFi.
In order to streamline the review of the contribution we ask you
to ensure the following steps have been taken:
For all changes:
in the commit message?
For code changes:
For documentation related changes:
Note:
Please ensure that once the PR is submitted, you check travis-ci for build issues and submit an update to your PR as soon as possible.