From d44952ec6c10f5ae41e60528b8d224aca8b90a08 Mon Sep 17 00:00:00 2001 From: Xavier Vello Date: Wed, 2 Aug 2017 18:01:23 +0200 Subject: [PATCH] add labels_mapper option to kubernetes_state to allow tag renaming --- kubernetes_state/CHANGELOG.md | 3 ++- kubernetes_state/auto_conf.yaml | 4 ++++ kubernetes_state/check.py | 25 +++++++++++++++++++------ kubernetes_state/conf.yaml.example | 6 ++++++ 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/kubernetes_state/CHANGELOG.md b/kubernetes_state/CHANGELOG.md index 906ed91bf66ee0..a3b38c6be4b355 100644 --- a/kubernetes_state/CHANGELOG.md +++ b/kubernetes_state/CHANGELOG.md @@ -5,7 +5,8 @@ ### Changes -* [FEATURE] Support for StatefulSet metrics +* [FEATURE] Support for StatefulSet metrics. See [#561][] +* [FEATURE] Support tag renaming via the labels_mapper option. See [#651][] 1.2.0 / 2017-07-18 ================== diff --git a/kubernetes_state/auto_conf.yaml b/kubernetes_state/auto_conf.yaml index 50f46847da3882..24ca28df4b33ad 100644 --- a/kubernetes_state/auto_conf.yaml +++ b/kubernetes_state/auto_conf.yaml @@ -2,6 +2,10 @@ docker_images: - kube-state-metrics init_config: + # Tags are reported as set by kube-state-metrics. If you want to translate + # them to other tags, you can use the labels_mapper dictionary + # labels_mapper: + # namespace: kube_namespace instances: # To enable Kube State metrics you must specify the url exposing the API - kube_state_url: http://%%host%%:%%port%%/metrics diff --git a/kubernetes_state/check.py b/kubernetes_state/check.py index 09f5094e408c94..9cd6007522998d 100644 --- a/kubernetes_state/check.py +++ b/kubernetes_state/check.py @@ -17,6 +17,12 @@ def __init__(self, name, init_config, agentConfig, instances=None): super(KubernetesState, self).__init__(name, init_config, agentConfig, instances) self.NAMESPACE = 'kubernetes_state' + if 'labels_mapper' in init_config: + if isinstance(init_config['labels_mapper'], dict): + self.labels_mapper = init_config['labels_mapper'] + else: + self.log.warning("labels_mapper should be a dictionnary") + self.pod_phase_to_status = { 'pending': self.WARNING, 'running': self.OK, @@ -169,6 +175,13 @@ def _extract_label_value(self, name, labels): return label.value return None + def _format_tag(self, name, value): + """ + Lookups the labels_mapper table to see if replacing the tag name is + necessary, then returns a "name:value" tag string + """ + return '%s:%s' % (self.labels_mapper.get(name, name), value) + def _label_to_tag(self, name, labels, tag_name=None): """ Search for `name` in labels name and returns corresponding tag string. @@ -177,7 +190,7 @@ def _label_to_tag(self, name, labels, tag_name=None): """ value = self._extract_label_value(name, labels) if value: - return '%s:%s' % (tag_name or name, value) + return self._format_tag(tag_name or name, value) else: return None @@ -194,7 +207,7 @@ def kube_pod_status_phase(self, message, **kwargs): if label.name == 'phase': phase = label.value.lower() else: - tags.append('{}:{}'.format(label.name, label.value)) + tags.append(self._format_tag(label.name, label.value)) #TODO: add deployment/replicaset? status = self.pod_phase_to_status.get(phase, self.UNKNOWN) self.service_check(check_basename + phase, status, tags=tags) @@ -204,7 +217,7 @@ def kube_job_complete(self, message, **kwargs): for metric in message.metric: tags = [] for label in metric.label: - tags.append('{}:{}'.format(label.name, label.value)) + tags.append(self._format_tag(label.name, label.value)) self.service_check(service_check_name, self.OK, tags=tags) def kube_job_failed(self, message, **kwargs): @@ -212,7 +225,7 @@ def kube_job_failed(self, message, **kwargs): for metric in message.metric: tags = [] for label in metric.label: - tags.append('{}:{}'.format(label.name, label.value)) + tags.append(self._format_tag(label.name, label.value)) self.service_check(service_check_name, self.CRITICAL, tags=tags) def kube_node_status_ready(self, message, **kwargs): @@ -256,9 +269,9 @@ def kube_node_spec_unschedulable(self, message, **kwargs): statuses = ('schedulable', 'unschedulable') if message.type < len(METRIC_TYPES): for metric in message.metric: - tags = ['{}:{}'.format(label.name, label.value) for label in metric.label] + tags = [self._format_tag(label.name, label.value) for label in metric.label] status = statuses[int(getattr(metric, METRIC_TYPES[message.type]).value)] # value can be 0 or 1 - tags.append('status:{}'.format(status)) + tags.append(self._format_tag('status', status)) self.gauge(metric_name, 1, tags) # metric value is always one, value is on the tags else: self.log.error("Metric type %s unsupported for metric %s" % (message.type, message.name)) diff --git a/kubernetes_state/conf.yaml.example b/kubernetes_state/conf.yaml.example index ef32a7a1c5d248..91d746c1dac156 100644 --- a/kubernetes_state/conf.yaml.example +++ b/kubernetes_state/conf.yaml.example @@ -1,4 +1,10 @@ init_config: + # Tags are reported as set by kube-state-metrics. If you want to translate + # them to other tags, you can use the labels_mapper dictionary + # labels_mapper: + # namespace: kube_namespace + + # Custom tags can be added to all metrics reported by this integration # tags: # - optional_tag1 # - optional_tag2