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

External Logging link for container nodes #13704

Merged
merged 1 commit into from
Mar 13, 2017

Conversation

enoodle
Copy link

@enoodle enoodle commented Jan 31, 2017

Adding the common logging link support for container nodes.

gifrecord_2017-03-01_231329

@enoodle
Copy link
Author

enoodle commented Jan 31, 2017

This depends on #13319 (I pulled over the commit from there, will rebase once its merged)

@@ -79,4 +80,19 @@ def ipaddress
def cockpit_url
URI::HTTP.build(:host => ipaddress, :port => 9090)
end

supports :common_logging do
Copy link
Member

Choose a reason for hiding this comment

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

Not sure I like the phrase "common logging" as that is a Red Hat idiom. cc @blomquisg

Copy link
Author

Choose a reason for hiding this comment

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

I'll answer on #13319

@@ -80,6 +80,8 @@
:scan_via_host: true
:use_vim_broker: true
:use_vim_broker_ems: true
:container_logging:
:common_logging_route: logging-kibana-ops
Copy link
Member

Choose a reason for hiding this comment

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

This feels wrong as a setting in the general settings...feels like it should a per-provider settings or perhaps a special endpoint on each provider.

Copy link
Author

Choose a reason for hiding this comment

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

Ill answer on #13319

@enoodle enoodle force-pushed the kibana_link_for_container_nodes branch from 67db9e5 to 0144a88 Compare February 1, 2017 14:14
@enoodle
Copy link
Author

enoodle commented Feb 1, 2017

I removed the commit from the parent PR so this will only be green after it is merged.

@enoodle enoodle closed this Feb 7, 2017
@enoodle enoodle reopened this Feb 7, 2017
@miq-bot
Copy link
Member

miq-bot commented Feb 14, 2017

This pull request is not mergeable. Please rebase and repush.

@simon3z
Copy link
Contributor

simon3z commented Feb 14, 2017

@enoodle can you handle the rebase?

@enoodle enoodle force-pushed the kibana_link_for_container_nodes branch from 0144a88 to 82b5cc3 Compare February 22, 2017 09:33
@enoodle enoodle force-pushed the kibana_link_for_container_nodes branch 2 times, most recently from 6505533 to fdf76bd Compare February 23, 2017 12:38
@simon3z
Copy link
Contributor

simon3z commented Feb 24, 2017

@enoodle remind me, I think there was no real conclusion on what the kibana search should be for nodes. Is it reliable enough in this PR? cc @portante

@portante
Copy link

@enoodle, this looks like it tries to catch both hostnames and ManageIQ names. Ideally we'd have all logs from a given cluster tagged with a certain value in the "tags" field so that we can query like so to using the shortened hostname, tags:clusterA AND (hostname:${hostname} OR hostname:$(basename ${hostname}) (syntax here using bash for example purposes).

@enoodle enoodle force-pushed the kibana_link_for_container_nodes branch from fdf76bd to d9c40c4 Compare February 26, 2017 11:06
@enoodle enoodle changed the title Kibana link for container nodes External Logging link for container nodes Feb 27, 2017
@enoodle enoodle force-pushed the kibana_link_for_container_nodes branch from d9c40c4 to a2dc0bc Compare February 28, 2017 10:42
@enoodle
Copy link
Author

enoodle commented Feb 28, 2017

@portante I changed to try the hostname from the kubernetes label first. I also changed to make the query itself easier to read.
About the tag: currently it is not available to me, so my only suggestion is that we can add it later when it is more commonly available.

def external_logging_path
hostname = (ipaddress || name || "").split('.').first
query = "bool:(filter:(or:!((term:(hostname:#{hostname})),(term:(hostname:#{name})))))"
"/#/discover?_g=()&_a=(columns:!(_source),filters:!((meta:(disabled:!f,index:'.operations.*',key:hostname,negate:!f),#{query})),index:'.operations.*',interval:auto,query:(query_string:(analyze_wildcard:!t,query:'*')),sort:!(time,desc))"
Copy link

Choose a reason for hiding this comment

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

Can you factor out the .operations.* index name as a variable? It appears in two places in the string. Also, I tried to use this URL with a few adjustments for names in my Kibana instance, but I get an error. Are you sure this is right?

Additionally, could we add some fields by default so that it is not just the _source field, which is large blob? Perhaps adding hostname, level, pod_name, and message would be sufficient initially.

Copy link
Author

Choose a reason for hiding this comment

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

I am not sure that this URL is right, but it is working for me (I have added a gif, made it for the UI Patch but it fits here too).
To get this URL I opened Kibana and told it to filter by hostname. I then changed the query to catch the both fqdn and hostname and trimmed it a little. This is where the _source came from. To my understanding after playing with this a little this changes the columns that are displayed next to each message in the list. I will set this to the columns you suggested.
The field level is empty for me on all messages but I assume that future improvments with the data model will change that.


supports :external_logging_support do
unless ext_management_system.respond_to?(:external_logging_route_name)
unsupported_reason_add(:external_logging_support, _('This provider type does not support external_logging_support'))
Copy link

Choose a reason for hiding this comment

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

Is this message from the department of the redundancy department? ;)

Copy link
Author

Choose a reason for hiding this comment

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

I will un-robotize this. This message is not for the end user though.

@enoodle enoodle force-pushed the kibana_link_for_container_nodes branch 2 times, most recently from ff3c930 to d4299b9 Compare March 1, 2017 10:11
@portante
Copy link

portante commented Mar 1, 2017

@enoodle, I'll try to get this URL working for me in my kibana instance and report back.

@enoodle enoodle force-pushed the kibana_link_for_container_nodes branch from d4299b9 to f80a208 Compare March 1, 2017 14:26
@portante
Copy link

portante commented Mar 1, 2017

I made a simple python script to verify the base string works now. Looks good!

#!/usr/bin/env python

def external_logging_path(index, hostname_l):
    hostname_s = (hostname_l or "*").split('.')[0]
    query = "bool:(filter:(or:!((term:(hostname:'%(hostname_s)s')),(term:(hostname:'%(hostname_l)s')))))" % { 'hostname_l': hostname_l, 'hostname_s': hostname_s }
    return  "#/discover?_g=()&_a=(columns:!(hostname,level,kubernetes.pod_name,message),filters:!((meta:(disabled:!f,index:%(index)s,key:hostname,negate:!f),%(query)s)),index:%(index)s,interval:auto,query:(query_string:(analyze_wildcard:!t,query:'*')),sort:!('@timestamp',desc))" % { 'index': index, 'query': query }

print external_logging_path("[logstash-]YYYY.MM.DD", "perf44.example.com")
print external_logging_path("[logstash-]YYYY.MM.DD", "gprfs003.example.com")
print external_logging_path("[logstash-]YYYY.MM.DD", "172.17.40.144")

@enoodle
Copy link
Author

enoodle commented Mar 1, 2017

@simon3z I verified this with the latest update to the UI PR. updated the GIF.


def external_logging_path
fqdn = (ipaddress || name || "")
hostname = fqdn.split('.').first
Copy link
Contributor

Choose a reason for hiding this comment

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

@enoodle @portante if fqdn is an ipaddress... wouldn't hostname be the first octet?

Also shouldn't you protect against hostname possibly being nil?

If neither ipaddress or name are defined why do we continue with ""? Wouldn't it generate a meaningless query?

Copy link
Author

Choose a reason for hiding this comment

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

@simon3z The name of the method was misleading so I changed it from ipaddress to kubernetes_hostname. If it is indeed returning an IP address instead of an hostname then we will add a search for the first octect (OR the full IP). It will not be optimal but won't crush anything and considering that none of our options gave a valid hostname it seems like an acceptable option.

I fixed hostname to have a default value of ""

@enoodle enoodle force-pushed the kibana_link_for_container_nodes branch from 06a2dcc to 2f2e527 Compare March 2, 2017 13:00
def external_logging_path
fqdn = (kubernetes_hostname || name || "")
hostname = fqdn.split('.').first || ""
query = "bool:(filter:(or:!((term:(hostname:'#{hostname}')),(term:(hostname:'#{fqdn}')))))"
Copy link
Contributor

Choose a reason for hiding this comment

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

@enoodle I don't understand, why do you still use the hostname here even if it's empty.
I have the feeling we should be smarter on how to build this query.

Implicitly I believe that what you're saying here is:

  1. if fqdn is empty (and therefore hostname is empty), return all logs
  2. if hostname is empty, just use fqdn
  3. use both fqdn and hostname if available

Although I assume that the above relies on Kibana treating an empty string "" as a search term not to consider.

I'd prefer to see all the logic expressed in code rather than relying on Kibana behavior.

Copy link

Choose a reason for hiding this comment

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

@simon3z, unfortunately, the logging subsystem does not return a consistent set of hostnames for the same entity. So some parts of the logging subsystem gather the FQDN, other parts might use the shortened name. I believe this query is trying to account for that. We have to file bugs with the logging subsystem to fix the collectors to ensure an FQDN.

Having said that, data collection is never going to be perfect, so it is likely we'll need to keep this around.

Copy link
Author

Choose a reason for hiding this comment

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

@simon3z I want a query to get all the message with hostname that equals to the fqdn of the node OR the hostname of the node. This is derived from looking at the values of this field in the logs that are currently being collected.
I have tested that if either fqdn or hostname will be empty string "" it will not add results to the search query results.

Copy link
Contributor

Choose a reason for hiding this comment

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

I have tested that if either fqdn or hostname will be empty string "" it will not add results to the search query results.

@enoodle as mentioned above I think this should be explicit in the logic that builds the query rather than implicit in the empty string handling of kibana.

@enoodle enoodle force-pushed the kibana_link_for_container_nodes branch from 2f2e527 to cda3b14 Compare March 7, 2017 10:11
@enoodle
Copy link
Author

enoodle commented Mar 7, 2017

@simon3z PTAL

query = "#{query}," if !hostname.blank? && !fqdn.blank?
query = "#{query}(term:(hostname:'#{hostname}'))" if !hostname.blank?
query = "#{query})))"
index = ".operations.*"
Copy link
Contributor

Choose a reason for hiding this comment

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

@enoodle mmmm... logic is still incomplete because fqdn.split('.').first could generate an hostname that is == fqdn:

fqdn = "node_short_hostname"
hostname = fqdn.split('.').first || ""
=> "node_short_hostname"

Also you check multiple times (at least 4) for !fqdn.blank? and !hostname.blank?

Since this search is term-based couldn't you just do something like:

node_hostnames = [kubernetes_hostname || name]  # node name cannot be empty, it's an ID
node_hostnames.push(node_hostnames.first.split('.').first)
node_hostnames_query = node_hostnames.uniq.map{|x| "(term:(hostname:'#{x}'))"}.join(",")
...

Which for test.example.com would generate a node_hostnames_query = "(term:(hostname:'test.example.com')),(term:(hostname:'test'))"

Also it seems that the URL may deserve a constant.

@enoodle enoodle force-pushed the kibana_link_for_container_nodes branch from cda3b14 to 9a08f62 Compare March 8, 2017 14:22
it "queries only for the name/fqdn when hostname can't be parsed" do
node = FactoryGirl.create(:container_node, :name => "hello")
query = get_query(node.external_logging_path)
expect(query).to eq("bool:(filter:(or:!((term:(hostname:'hello')),(term:(hostname:'hello')))))")
Copy link
Contributor

Choose a reason for hiding this comment

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

@enoodle shouldn't this fail now?

Copy link
Author

Choose a reason for hiding this comment

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

@simon3z Yes, I am on it. This is not working as intended yet.

@enoodle enoodle force-pushed the kibana_link_for_container_nodes branch from 9a08f62 to fccc487 Compare March 8, 2017 16:05
@enoodle
Copy link
Author

enoodle commented Mar 8, 2017

@simon3z PTAL

@simon3z
Copy link
Contributor

simon3z commented Mar 8, 2017

@enoodle please add a test that takes advantage of kubernetes.io/hostname

@enoodle enoodle force-pushed the kibana_link_for_container_nodes branch from fccc487 to 9fcafb0 Compare March 8, 2017 16:15
Copy link
Contributor

@simon3z simon3z left a comment

Choose a reason for hiding this comment

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

LGTM 👍

@miq-bot assign Fryguy

@simon3z
Copy link
Contributor

simon3z commented Mar 8, 2017

@miq-bot assign Fryguy

@miq-bot miq-bot assigned Fryguy and unassigned simon3z Mar 8, 2017
end

def evaluate_alert(_alert_id, _event)
# currently only EmsEvents from hawkular are tested for node alerts,
# and these should automaticaly be translated to alerts.
true
end

supports :external_logging_support do
Copy link
Member

@Fryguy Fryguy Mar 10, 2017

Choose a reason for hiding this comment

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

This name is funny because it duplicates the word support in certain caller paths. I think you just want supports :external_logging.

Copy link
Author

Choose a reason for hiding this comment

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

Right, do you want me to change this name in this PR? This will involve changing it in "app/models/mixins/support_feature_mixin.rb" and "app/models/manageiq/providers/container_manager.rb" too.

Copy link
Member

Choose a reason for hiding this comment

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

I opt for changing it 👍 But in it's own PR - and check if the UI depends on it

Copy link
Member

Choose a reason for hiding this comment

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

Oh I didn't realize it wasn't introduced in this PR. Yeah, then separate PR for sure.


supports :external_logging_support do
unless ext_management_system.respond_to?(:external_logging_route_name)
unsupported_reason_add(:external_logging_support, _('This provider type does not support Extrenal Logging'))
Copy link
Member

Choose a reason for hiding this comment

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

Typo Extrenal -> External

Copy link
Member

@Fryguy Fryguy Mar 10, 2017

Choose a reason for hiding this comment

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

Does it make sense to make this a dynamic supports method? Why not just supports_not :external_logging. @durandom Thoughts here?

Copy link
Author

Choose a reason for hiding this comment

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

@Fryguy This is for the Kubernetes container provider. It doesn't use routes so it can't support this feature.

describe "#external_logging_path" do
def get_query(path)
index = ".operations.*"
prefix_len = "/#/discover?_g=()&_a=(columns:!(hostname,level,kubernetes.pod_name,message),filters:!((meta:(disabled:!f,index:'#{index}',key:hostname,negate:!f),".length
Copy link
Member

Choose a reason for hiding this comment

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

It feels wrong to duplicate this string in the test. Is there a way to keep it in the model? Perhaps a pair of methods for constructing and desconstructing the query string in the model?

@enoodle enoodle force-pushed the kibana_link_for_container_nodes branch 2 times, most recently from 9729627 to a3bc353 Compare March 12, 2017 10:04
container node ipaddress rename to kubernetes_hostname

the previous name, "ipaddress" is confusing and does not reflect well on
the return value.
@enoodle enoodle force-pushed the kibana_link_for_container_nodes branch from a3bc353 to c025dcd Compare March 12, 2017 15:54
@miq-bot
Copy link
Member

miq-bot commented Mar 12, 2017

Checked commit enoodle@c025dcd with ruby 2.2.6, rubocop 0.47.1, and haml-lint 0.20.0
2 files checked, 0 offenses detected
Everything looks good. 🏆

@Fryguy Fryguy merged commit 1b5655f into ManageIQ:master Mar 13, 2017
@Fryguy Fryguy added this to the Sprint 56 Ending Mar 13, 2017 milestone Mar 13, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants