-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Add IP-addresses and MAC-addresses to event #6878
Conversation
Since this is a community submitted pull request, a Jenkins build has not been kicked off automatically. Can an Elastic organization member please verify the contents of this patch and then kick off a build manually? |
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.
@hypp Thanks a lot for taking a stab at this. Code makes it much easier to discuss it.
I left a few comments in the code. Let's sort these out first.
Afterwards you will have to run make update
to make sure the fields end up in the auto generate docs. Also please add a changelog entry and we will have to add a note to the docs. But the docs will depend on the conclusions of the comments.
List of IP-addresses. | ||
- name: net.hw | ||
description: > | ||
List of hardware-addresses, usually MAC-addresses. |
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 assume the type here would be keyword
.
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.
Ok, I'll fix that
@@ -31,3 +31,10 @@ | |||
type: keyword | |||
description: > | |||
OS family (e.g. redhat, debian, freebsd, windows). | |||
- name: net.ip | |||
description: > | |||
List of IP-addresses. |
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 can use the type ip
here: https://www.elastic.co/guide/en/elasticsearch/reference/6.2/ip.html
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, of course! I'll fix that too.
@@ -71,10 +72,54 @@ func (p *addHostMetadata) loadData() { | |||
if p.info.OS.Build != "" { | |||
p.data.Put("host.os.build", p.info.OS.Build) | |||
} | |||
|
|||
// IP-address and MAC-address | |||
var ipList, hwList = p.getNetInfo() |
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'm thinking to make this information optional, meaning it is not sent by default but we have a config option in the processor to enable it. Not sure yet how we should call the config options, any suggestions?
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
netinfo: enabled/disabled
or
add_netinfo: true/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.
Looking at the code I was even wondering if we should separate mac address and ip. I think lots of people want to have the list of ip addresses but are less interested in the actual mac address. This could lead to a config like:
add_fields: [`ip`, `mac`]
I don't like add_fields name to much but the gist is that we could add more fields in the future here.
@andrewkroh Thoughts?
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 think this a good idea, because without the feature you would then have to add a drop_fields processor causing unnecessary work.
I'd have a default set of fields built into the processor's defaultConfig. Then if you want to change anything you must specific the full set of fields you want the process to add.
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.
Should we do that for all fields or just for ip and mac?
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.
@andrewkroh If I understand this correctly, my config example above would mean host.name
for example would not be sent?
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.
add_fields: [
ip
,mac
]
Correct. That would give you only those two fields. But I wouldn't call it add_fields
if we went with this behavior.
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.
My main issue going with the above suggestion is that if someone wants ip and mac in addition, he has to know all the other fields that are there to add them to the list.
To not block the PR on this discussion perhaps we can go first with the initial suggestion of netinfo.enabled: true
and continue the field list discussion separately as I think such a logic would have to be applied to all add_
processors.
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 have time to work on this on friday, so it would be great to have a decision by then.
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.
@hypp We had a quick internal chat and decided to go with the proposal for netinfo.enabled
for now and we can still improve it later.
|
||
// IP-address and MAC-address | ||
var ipList, hwList = p.getNetInfo() | ||
p.data.Put("host.net.ip", ipList) |
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 suggest to call these fields host.ip
and host.mac
.
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.
Fine by me!
@@ -0,0 +1,16 @@ | |||
package add_host_metadata |
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 use an underscore in package name
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.
Change LGTM. To make CI happy you need to run make fmt
first to format the Golang files and then make update
in the metricbeat directory to generate the docs with the new fields.
assert.Error(t, err) | ||
assert.Nil(t, v) | ||
|
||
event = &beat.Event{ |
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.
Could you split this up into 2 tests? Like this if the tests fail we can already tell based on the name which part is probably not working.
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.
@ruflin Is it really enough to make update
in the metricbeat directory? Or should I do it for every beat?
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.
Sorry, my mistake. You have to run it in the top level beats
directory. Same for make fmt
.
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 had again a look at the code. One question that got raised on my end is what is the behaviour in case of errors. Do we continue trying to get the information or do we abort?
Could you update the two following files with the new config option and run make update
again?
- reference config file: https://github.com/elastic/beats/blob/master/libbeat/_meta/config.reference.yml#L186
- asciidoc: https://github.com/elastic/beats/blob/master/libbeat/docs/processors-using.asciidoc#add-host-metadata
Sorry for the additional iteration but I think we are close to get it in.
// Get all interfaces and loop through them | ||
ifaces, err := net.Interfaces() | ||
if err != nil { | ||
return ipList, hwList |
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.
Instead or returning the empty lists could we return here the error? Meaning it would return nil, nil, err
. On line 89 we could then check for the error and would not add the fields in case of an error and could also log the error.
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.
Sure, do you have a code example of logging, that I could look at?
|
||
addrs, err := i.Addrs() | ||
if err != nil { | ||
return ipList, hwList |
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.
Similar question as above. I wonder if in case of an error we should just log it but continue trying to collect the addresses from the interfaces instead of returning.
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 a matter of taste, I prefer to fail fast. You decide.
if p.config.NetInfoEnabled { | ||
// IP-address and MAC-address | ||
var ipList, hwList = p.getNetInfo() | ||
p.data.Put("host.ip", ipList) |
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.
Reviewing the code below and the possibility that ipList and hwList can be empty, we should check for len(x) == 0
and in case of 0 not add the field.
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.
Ok, I'll fix that
@@ -0,0 +1,16 @@ | |||
package add_host_metadata | |||
|
|||
//import ( |
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.
leftover?
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 like your current implementation that if one address fetching fails we still continue like this the user still has the chance to get some data.
processors: | ||
- add_host_metadata: | ||
netinfo.enabled: 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.
Here the end of the source block seems to be missing.
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.
Should be fixed now
// IP-address and MAC-address | ||
var ipList, hwList, err = p.getNetInfo() | ||
if err != nil { | ||
logp.Warn("Error when getting network information %v", err) |
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 prefer not to use Warn
as it's not clear if this is something that needs action. I suggest we set it to Info
for now.
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.
Ok!
// Get all interfaces and loop through them | ||
ifaces, err := net.Interfaces() | ||
if err != nil { | ||
return ipList, hwList, err |
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.
Can you use return nil, nil, err
here? This makes it clear that both ipList and hwList do not have any values yet. Code logic is exactly the same as before.
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.
Ok!
addrs, err := i.Addrs() | ||
if err != nil { | ||
// If we get an error, log it and continue with the next interface | ||
logp.Warn("Error when getting IP address %v", err) |
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.
Lets not log each error but add it to the list. We can use multierror
here. Outside the loop you can specify var errs multierror.Errors
and then use errs = append(errs, err)
. On line 145 you can then return errs.Err()
.
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.
Ok!
jenkins, test this |
@hypp Thanks a lot for your contribution. |
@ruflin So it is all done now? Great! |
@hypp Yes. This should automatically end up in the 6.4 release. If you want to test it earlier, there are snapshot build available: https://beats-package-snapshots.s3.amazonaws.com/index.html?prefix=metricbeat/ (warning, just saw they are not 100% up-to-date. Need to check why). |
This is a pull request for issue #5396