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

Refactor to support different versions of istio #6360

Merged
merged 8 commits into from
Apr 17, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion istio/assets/configuration/spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,26 @@ files:
- template: init_config/openmetrics
- template: instances
options:
- name: istiod_endpoint
description: |
Collect mixer, galley, pilot, and citadel metrics available from the istiod deployment.
Only available for Istio >= v1.5.
value:
default: null
example: http://istiod.istio-system:8080/metrics
type: string
- name: istio_mesh_endpoint
description: |
To enable Istio metrics you must specify the url exposing the API.
Note for RHEL and SUSE users: due to compatibility issues, the check does not make use of
the CPP extension to process Protocol buffer messages coming from the api. Depending
on the metrics volume, the check may run very slowly.

If collecting mesh metrics in Istio < v1.5, use
ChristineTChen marked this conversation as resolved.
Show resolved Hide resolved
istio_mesh_endpoint: http://istio-telemetry.istio-system:42422/metrics
value:
default: null
example: http://istio-telemetry.istio-system:42422/metrics
example: http://istio-proxy.istio-system:15090/stats/prometheus
type: string
- name: mixer_endpoint
description: |
Expand Down
11 changes: 10 additions & 1 deletion istio/datadog_checks/istio/data/conf.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,22 @@ init_config:
instances:

-
## @param istiod_endpoint - string - optional
## Collect mixer, galley, pilot, and citadel metrics available from the istiod deployment.
## Only available for Istio >= v1.5.
#
# istiod_endpoint: http://istiod.istio-system:8080/metrics

## @param istio_mesh_endpoint - string - optional
## To enable Istio metrics you must specify the url exposing the API.
## Note for RHEL and SUSE users: due to compatibility issues, the check does not make use of
## the CPP extension to process Protocol buffer messages coming from the api. Depending
## on the metrics volume, the check may run very slowly.
##
## If collecting mesh metrics in Istio < v1.5, use
ChristineTChen marked this conversation as resolved.
Show resolved Hide resolved
## istio_mesh_endpoint: http://istio-telemetry.istio-system:42422/metrics
#
# istio_mesh_endpoint: http://istio-telemetry.istio-system:42422/metrics
# istio_mesh_endpoint: http://istio-proxy.istio-system:15090/stats/prometheus

## @param mixer_endpoint - string - optional
## Define the mixer endpoint in order to collect all Prometheus metrics on the Mixer process as well
Expand Down
190 changes: 11 additions & 179 deletions istio/datadog_checks/istio/istio.py
Original file line number Diff line number Diff line change
@@ -1,191 +1,23 @@
# (C) Datadog, Inc. 2018-present
# (C) Datadog, Inc. 2020 - Present
ChristineTChen marked this conversation as resolved.
Show resolved Hide resolved
# All rights reserved
# Licensed under Simplified BSD License (see LICENSE)

from copy import deepcopy

from datadog_checks.base.checks.openmetrics import OpenMetricsBaseCheck
ChristineTChen marked this conversation as resolved.
Show resolved Hide resolved
from datadog_checks.base.errors import CheckException

from .constants import CITADEL_NAMESPACE, GALLEY_NAMESPACE, MESH_NAMESPACE, MIXER_NAMESPACE, PILOT_NAMESPACE
from .metrics import CITADEL_METRICS, GALLEY_METRICS, GENERIC_METRICS, MESH_METRICS, MIXER_METRICS, PILOT_METRICS
from .legacy_1_4 import LegacyIstioCheck_1_4


class Istio(OpenMetricsBaseCheck):

DEFAULT_METRIC_LIMIT = 0

def __init__(self, name, init_config, instances):
__NAMESPACE__ = 'istio'
ChristineTChen marked this conversation as resolved.
Show resolved Hide resolved

# Create instances we can use in OpenMetricsBaseCheck
generic_instances = None
if instances is not None:
generic_instances = self.create_generic_instances(instances)
DEFAULT_METRIC_LIMIT = 0

# Set up OpenMetricsBaseCheck with our generic instances
super(Istio, self).__init__(name, init_config, generic_instances)
def __new__(cls, name, init_config, instances):
instance = instances[0]
if instance.get('istiod_endpoint'):
return super(Istio, cls).__new__(cls)
else:
return LegacyIstioCheck_1_4(name, init_config, instances)

def check(self, instance):
"""
Process all the endpoints associated with this instance.
All the endpoints themselves are optional, but at least one must be passed.
"""
processed = False
# Get the config for the istio_mesh instance
istio_mesh_endpoint = instance.get('istio_mesh_endpoint')
if istio_mesh_endpoint:
istio_mesh_config = self.config_map[istio_mesh_endpoint]

# Process istio_mesh
self.process(istio_mesh_config)
processed = True

# Get the config for the process_mixer instance
process_mixer_endpoint = instance.get('mixer_endpoint')
if process_mixer_endpoint:
process_mixer_config = self.config_map[process_mixer_endpoint]

# Process process_mixer
self.process(process_mixer_config)
processed = True

# Get the config for the process_pilot instance
process_pilot_endpoint = instance.get('pilot_endpoint')
if process_pilot_endpoint:
process_pilot_config = self.config_map[process_pilot_endpoint]

# Process process_pilot
self.process(process_pilot_config)
processed = True

# Get the config for the process_galley instance
process_galley_endpoint = instance.get('galley_endpoint')
if process_galley_endpoint:
process_galley_config = self.config_map[process_galley_endpoint]

# Process process_galley
self.process(process_galley_config)
processed = True

# Get the config for the process_citadel instance
process_citadel_endpoint = instance.get('citadel_endpoint')
if process_citadel_endpoint:
process_citadel_config = self.config_map[process_citadel_endpoint]

# Process process_citadel
self.process(process_citadel_config)
processed = True

# Check that at least 1 endpoint is configured
if not processed:
raise CheckException("At least one of Mixer, Mesh, Pilot, Galley or Citadel endpoints must be configured")

def create_generic_instances(self, instances):
"""
Generalize each (single) Istio instance into OpenMetricsBaseCheck instances.
"""
result = []
for instance in instances:
if 'istio_mesh_endpoint' in instance:
result.append(self._create_istio_mesh_instance(instance))
if 'mixer_endpoint' in instance:
result.append(self._create_process_mixer_instance(instance))
if 'pilot_endpoint' in instance:
result.append(self._create_process_pilot_instance(instance))
if 'galley_endpoint' in instance:
result.append(self._create_process_galley_instance(instance))
if 'citadel_endpoint' in instance:
result.append(self._create_process_citadel_instance(instance))
return result

def _create_istio_mesh_instance(self, instance):
"""
Grab the istio mesh scraper from the dict and return it if it exists,
otherwise create the scraper and add it to the dict.
"""
endpoint = instance.get('istio_mesh_endpoint')

istio_mesh_instance = deepcopy(instance)
istio_mesh_instance.update(
{
'namespace': MESH_NAMESPACE,
'prometheus_url': endpoint,
'label_to_hostname': endpoint,
'metrics': [MESH_METRICS],
# Defaults that were set when istio was based on PrometheusCheck
'send_monotonic_counter': instance.get('send_monotonic_counter', False),
'health_service_check': instance.get('health_service_check', False),
}
)

return istio_mesh_instance

def _create_process_mixer_instance(self, instance):
"""
Grab the mixer scraper from the dict and return it if it exists,
otherwise create the scraper and add it to the dict.
"""
endpoint = instance.get('mixer_endpoint')

process_mixer_instance = deepcopy(instance)
MIXER_METRICS.update(GENERIC_METRICS)
process_mixer_instance.update(
{
'namespace': MIXER_NAMESPACE,
'prometheus_url': endpoint,
'metrics': [MIXER_METRICS],
# Defaults that were set when istio was based on PrometheusCheck
'send_monotonic_counter': instance.get('send_monotonic_counter', False),
'health_service_check': instance.get('health_service_check', False),
}
)
return process_mixer_instance

def _create_process_pilot_instance(self, instance):
"""
Grab the pilot scraper from the dict and return it if it exists,
otherwise create the scraper and add it to the dict.
"""
endpoint = instance.get('pilot_endpoint')

process_pilot_instance = deepcopy(instance)
PILOT_METRICS.update(GENERIC_METRICS)
process_pilot_instance.update(
{'namespace': PILOT_NAMESPACE, 'prometheus_url': endpoint, 'metrics': [PILOT_METRICS]}
)
return process_pilot_instance

def _create_process_galley_instance(self, instance):
"""
Grab the galley scraper from the dict and return it if it exists,
otherwise create the scraper and add it to the dict.
"""
endpoint = instance.get('galley_endpoint')

process_galley_instance = deepcopy(instance)
GALLEY_METRICS.update(GENERIC_METRICS)
process_galley_instance.update(
{
'namespace': GALLEY_NAMESPACE,
'prometheus_url': endpoint,
'metrics': [GALLEY_METRICS],
# The following metrics have been blakclisted due to high cardinality of tags
'ignore_metrics': ['galley_mcp_source_message_size_bytes', 'galley_mcp_source_request_acks_total'],
}
)
process_galley_instance['ignore_metrics'].extend(instance.get('ignore_metrics', []))
return process_galley_instance

def _create_process_citadel_instance(self, instance):
"""
Grab the citadel scraper from the dict and return it if it exists,
otherwise create the scraper and add it to the dict.
"""
endpoint = instance.get('citadel_endpoint')

process_citadel_instance = deepcopy(instance)
CITADEL_METRICS.update(GENERIC_METRICS)
process_citadel_instance.update(
{'namespace': CITADEL_NAMESPACE, 'prometheus_url': endpoint, 'metrics': [CITADEL_METRICS]}
)
return process_citadel_instance
raise NotImplementedError()
Loading