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

Handle server info for envoy <= 1.8 #6740

Merged
merged 8 commits into from
May 26, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
25 changes: 23 additions & 2 deletions envoy/datadog_checks/envoy/envoy.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from .errors import UnknownMetric, UnknownTags
from .parser import parse_histogram, parse_metric

LEGACY_VERSION_RE = re.compile(r'/(\d\.\d\.\d)/')


class Envoy(AgentCheck):
HTTP_CONFIG_REMAPPER = {'verify_ssl': {'name': 'tls_verify'}}
Expand Down Expand Up @@ -145,6 +147,7 @@ def whitelisted_metric(self, metric):
def _collect_metadata(self, stats_url):
# From http://domain/thing/stats to http://domain/thing/server_info
server_info_url = urljoin(stats_url, 'server_info')
raw_version = None

try:
response = self.http.get(server_info_url)
Expand All @@ -159,7 +162,24 @@ def _collect_metadata(self, stats_url):
# "state": "LIVE",
# ...
# }
raw_version = response.json()["version"].split('/')[1]
try:
raw_version = response.json()["version"].split('/')[1]
except Exception as e:
self.log.debug('Error decoding json for url=`%s`. Error: %s', server_info_url, str(e))

if raw_version is None:
# Search version in server info for Envoy version <= 1.8
# Example:
# envoy 5d25f466c3410c0dfa735d7d4358beb76b2da507/1.8.0/Clean/RELEASE live 581130 581130 0
content = response.content.decode()
found = LEGACY_VERSION_RE.search(content)
ofek marked this conversation as resolved.
Show resolved Hide resolved
self.log.debug('Looking for version in content: %s', content)
if found:
raw_version = found.group(1)
else:
self.log.debug('Version not matched.')
return

except requests.exceptions.Timeout:
self.log.warning(
'Envoy endpoint `%s` timed out after %s seconds', server_info_url, self.http.options['timeout']
Expand All @@ -169,4 +189,5 @@ def _collect_metadata(self, stats_url):
self.log.warning('Error collecting Envoy version with url=`%s`. Error: %s', server_info_url, str(e))
return

self.set_metadata('version', raw_version)
if raw_version:
self.set_metadata('version', raw_version)
8 changes: 2 additions & 6 deletions envoy/tests/common.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
import os

from datadog_checks.base.utils.common import get_docker_hostname
Expand All @@ -23,10 +24,6 @@
'metric_blacklist': [r'envoy\.cluster\.out\.'],
},
}
SERVER_INFO = {
"version": "222aaacccfff888/1.14.1/Clean/RELEASE/BoringSSL",
"state": "LIVE",
}
ENVOY_VERSION = os.getenv('ENVOY_VERSION')


Expand All @@ -36,8 +33,7 @@ def __init__(self, content, status_code):
self.status_code = status_code

def json(self):
# Metadata
return SERVER_INFO
return json.loads(self.content)


@lru_cache(maxsize=None)
Expand Down
1 change: 1 addition & 0 deletions envoy/tests/fixtures/server_info
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"version": "222aaacccfff888/1.14.1/Clean/RELEASE/BoringSSL", "state": "LIVE"}
1 change: 1 addition & 0 deletions envoy/tests/fixtures/server_info_before_1_9
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
envoy 5d25f466c3410c0dfa735d7d4358beb76b2da507/1.8.0/Clean/RELEASE live 581130 581130 0
1 change: 1 addition & 0 deletions envoy/tests/fixtures/server_info_invalid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ABC
32 changes: 30 additions & 2 deletions envoy/tests/test_envoy.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def test_config(test_case, extra_config, expected_http_kwargs):
r.get.assert_called_with('http://{}:8001/stats'.format(HOST), **http_wargs)


def test_metadata(datadog_agent):
def test_metadata_unit(datadog_agent):
instance = INSTANCES['main']
check = Envoy(CHECK_NAME, {}, [instance])
check.check_id = 'test:123'
Expand All @@ -136,13 +136,15 @@ def test_metadata(datadog_agent):
'Envoy endpoint `%s` timed out after %s seconds', 'http://localhost:8001/server_info', (10.0, 10.0)
)

datadog_agent.reset()
with mock.patch('requests.get', side_effect=IndexError()):
check._collect_metadata(instance['stats_url'])
datadog_agent.assert_metadata_count(0)
check.log.warning.assert_called_with(
'Error collecting Envoy version with url=`%s`. Error: %s', 'http://localhost:8001/server_info', ''
)

datadog_agent.reset()
with mock.patch('requests.get', side_effect=requests.exceptions.RequestException('Req Exception')):
check._collect_metadata(instance['stats_url'])
datadog_agent.assert_metadata_count(0)
Expand All @@ -152,7 +154,8 @@ def test_metadata(datadog_agent):
'Req Exception',
)

with mock.patch('requests.get', return_value=response('multiple_services')):
datadog_agent.reset()
with mock.patch('requests.get', return_value=response('server_info')):
check._collect_metadata(instance['stats_url'])

major, minor, patch = ENVOY_VERSION.split('.')
Expand All @@ -167,6 +170,31 @@ def test_metadata(datadog_agent):
datadog_agent.assert_metadata('test:123', version_metadata)
datadog_agent.assert_metadata_count(len(version_metadata))

datadog_agent.reset()
with mock.patch('requests.get', return_value=response('server_info_before_1_9')):
check._collect_metadata(instance['stats_url'])

expected_version = '1.8.0'
major, minor, patch = expected_version.split('.')
version_metadata = {
'version.scheme': 'semver',
'version.major': major,
'version.minor': minor,
'version.patch': patch,
'version.raw': expected_version,
}

datadog_agent.assert_metadata('test:123', version_metadata)
datadog_agent.assert_metadata_count(len(version_metadata))

datadog_agent.reset()
with mock.patch('requests.get', return_value=response('server_info_invalid')):
check._collect_metadata(instance['stats_url'])

datadog_agent.assert_metadata('test:123', {})
datadog_agent.assert_metadata_count(0)
check.log.debug.assert_called_with('Version not matched.')


@pytest.mark.usefixtures('dd_environment')
def test_metadata_integration(aggregator, datadog_agent):
Expand Down