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

Add support for NGINX Plus versions 4-7 #10750

Merged
merged 22 commits into from
Dec 7, 2021
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
22d1d8c
Add test data and limit_reqs endpoint
sarah-witt Nov 9, 2021
082073a
Add support for new endpoints in check
sarah-witt Nov 11, 2021
80549e2
Merge branch 'master' into sarah/nginx-v6
sarah-witt Nov 11, 2021
ab85b55
Update metadata with new metrics
sarah-witt Nov 12, 2021
a5865ab
add more tests for tags
sarah-witt Nov 15, 2021
a198d3f
Apply refactoring changes
sarah-witt Nov 25, 2021
51fb1d5
Add more tests and http limit conns endpoint
sarah-witt Nov 25, 2021
ad9e1c3
Add tests for all plus api versions
sarah-witt Nov 25, 2021
a69fd4e
Reformat code and fix typos
sarah-witt Nov 28, 2021
eba4919
Remove unneeded mappings
sarah-witt Nov 29, 2021
4b145fc
Remove unneeded mapping and test fixture
sarah-witt Nov 29, 2021
a23af73
Properly handle metrics that should be counts
sarah-witt Nov 29, 2021
c3e6fe6
Change more metrics to count
sarah-witt Nov 29, 2021
cedecf2
Fix short names of metrics
sarah-witt Nov 29, 2021
a32393e
Update style and add assertion for all count metrics
sarah-witt Nov 29, 2021
f6fd2ee
Update conf.example with new description
sarah-witt Nov 29, 2021
6372505
Update test folder structure and add mapping for plus api endpoints
sarah-witt Nov 30, 2021
9fe03b3
Assert metadata in all tests
sarah-witt Nov 30, 2021
63c10f5
Add missing count metrics, assert metrics covered, and refactor tests
sarah-witt Dec 1, 2021
41396c2
Remove slashes in directories
sarah-witt Dec 2, 2021
3e7ca52
Update comment typo and fix units in metadata.csv
sarah-witt Dec 6, 2021
95b8455
Remove peer unit
sarah-witt Dec 6, 2021
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
2 changes: 1 addition & 1 deletion nginx/assets/configuration/spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ files:
example: false
display_default: true
- name: plus_api_version
description: Specify the version of the Plus API to use. The check supports versions 1-3.
description: Specify the version of the Plus API to use. The check supports versions 1-7.
value:
type: integer
display_default: 2
Expand Down
2 changes: 1 addition & 1 deletion nginx/datadog_checks/nginx/data/conf.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ instances:
# use_plus_api_stream: false

## @param plus_api_version - integer - optional - default: 2
## Specify the version of the Plus API to use. The check supports versions 1-3.
## Specify the version of the Plus API to use. The check supports versions 1-7.
#
# plus_api_version: <PLUS_API_VERSION>

Expand Down
45 changes: 45 additions & 0 deletions nginx/datadog_checks/nginx/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
'nginx.upstream.down': 'nginx.upstream.peers.health_checks.last_passed',
}

# NGNINX Plus metrics that are sent as both a count and gauge for backwards compatibility
# The count metrics with have _count appended to their names
METRICS_SEND_AS_COUNT = [
'nginx.upstream.peers.responses.1xx',
'nginx.upstream.peers.responses.2xx',
Expand Down Expand Up @@ -98,6 +100,7 @@
'nginx.stream.upstream.peers.received',
'nginx.stream.upstream.peers.sent',
'nginx.stream.upstream.peers.unavail',
'nginx.stream.zone_sync.zone.records_total',
'nginx.upstream.peers.fails',
'nginx.upstream.peers.health_checks.checks',
'nginx.upstream.peers.health_checks.fails',
Expand All @@ -106,3 +109,45 @@
'nginx.upstream.peers.responses.total',
'nginx.upstream.peers.unavail',
]


# NGNINX Plus metrics that are sent as only a count.
# These metrics will not have _count appended to their names
COUNT_METRICS = [
'nginx.location_zone.responses.total',
'nginx.location_zone.discarded',
'nginx.location_zone.received',
'nginx.location_zone.requests',
'nginx.location_zone.responses.1xx',
'nginx.location_zone.responses.2xx',
'nginx.location_zone.responses.3xx',
'nginx.location_zone.responses.4xx',
'nginx.location_zone.responses.5xx',
'nginx.location_zone.responses.code',
'nginx.location_zone.responses.total',
'nginx.location_zone.sent',
'nginx.resolver.requests.addr',
'nginx.resolver.requests.name',
'nginx.resolver.requests.srv',
'nginx.resolver.responses.formerr',
'nginx.resolver.responses.noerror',
'nginx.resolver.responses.notimp',
'nginx.resolver.responses.nxdomain',
'nginx.resolver.responses.refused',
'nginx.resolver.responses.servfail',
'nginx.resolver.responses.timedout',
'nginx.resolver.responses.unknown',
'nginx.limit_req.delayed_dry_run',
'nginx.limit_req.delayed',
'nginx.limit_req.passed',
'nginx.limit_req.rejected_dry_run',
'nginx.limit_req.rejected',
'nginx.limit_conn.passed',
'nginx.limit_conn.rejected',
'nginx.limit_conn.rejected_dry_run',
'nginx.stream.limit_conn.passed',
'nginx.stream.limit_conn.rejected',
'nginx.stream.limit_conn.rejected_dry_run',
'nginx.server_zone.responses.code',
'nginx.upstream.peers.responses.code',
]
56 changes: 47 additions & 9 deletions nginx/datadog_checks/nginx/nginx.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from datadog_checks.base import AgentCheck, ConfigurationError, to_native_string
from datadog_checks.base.utils.time import get_timestamp

from .metrics import METRICS_SEND_AS_COUNT, VTS_METRIC_MAP
from .metrics import COUNT_METRICS, METRICS_SEND_AS_COUNT, VTS_METRIC_MAP

if PY3:
long = int
Expand Down Expand Up @@ -48,14 +48,33 @@ def fromisoformat(ts):
"stream/zone_sync": ["stream", "zone_sync"],
}

PLUS_API_V6_STREAM_ENDPOINTS = {
"stream/limit_conns": ["stream", "limit_conns"],
}

PLUS_API_V5_ENDPOINTS = {
"http/location_zones": ["location_zones"],
"resolvers": ["resolvers"],
}

PLUS_API_V6_ENDPOINTS = {
"http/limit_reqs": ["limit_reqs"],
"http/limit_conns": ["limit_conns"],
}

coignetp marked this conversation as resolved.
Show resolved Hide resolved
TAGGED_KEYS = {
'caches': 'cache',
'codes': 'code',
'limit_conns': 'limit_conn',
'limit_reqs': 'limit_req',
'location_zones': 'location_zone',
'resolvers': 'resolver',
'server_zones': 'server_zone',
'serverZones': 'server_zone', # VTS
'upstreams': 'upstream',
'upstreamZones': 'upstream', # VTS
'slabs': 'slab',
'slots': 'slot',
'upstreams': 'upstream',
'upstreamZones': 'upstream', # VTS
'zones': 'zone',
}

Expand Down Expand Up @@ -111,7 +130,11 @@ def check(self, _):
# since we can't get everything in one place anymore.

if self.use_plus_api_stream:
plus_api_chain_list = chain(iteritems(PLUS_API_ENDPOINTS), self._get_plus_api_stream_endpoints())
plus_api_chain_list = chain(
self._get_plus_api_endpoints(),
self._get_plus_api_stream_endpoints(),
)

else:
plus_api_chain_list = chain(iteritems(PLUS_API_ENDPOINTS))

Expand Down Expand Up @@ -158,11 +181,16 @@ def check(self, _):
if name is None:
continue

if name in METRICS_SEND_AS_COUNT:
if name in COUNT_METRICS:
func_count = funcs['count']
func_count(name + "_count", value, tags)
func = funcs[metric_type]
func(name, value, tags)
func_count(name, value, tags)
else:
if name in METRICS_SEND_AS_COUNT:
func_count = funcs['count']
func_count(name + "_count", value, tags)

func = funcs[metric_type]
func(name, value, tags)

except Exception as e:
self.log.error('Could not submit metric: %s: %s', repr(row), e)
Expand Down Expand Up @@ -205,10 +233,21 @@ def _nest_payload(self, keys, payload):

return {keys[0]: self._nest_payload(keys[1:], payload)}

def _get_plus_api_endpoints(self):
endpoints = iteritems(PLUS_API_ENDPOINTS)

if int(self.plus_api_version) >= 5:
endpoints = chain(endpoints, iteritems(PLUS_API_V5_ENDPOINTS))
if int(self.plus_api_version) >= 6:
endpoints = chain(endpoints, iteritems(PLUS_API_V6_ENDPOINTS))
return endpoints

def _get_plus_api_stream_endpoints(self):
endpoints = iteritems(PLUS_API_STREAM_ENDPOINTS)
if int(self.plus_api_version) >= 3:
endpoints = chain(endpoints, iteritems(PLUS_API_V3_STREAM_ENDPOINTS))
if int(self.plus_api_version) >= 6:
endpoints = chain(endpoints, iteritems(PLUS_API_V6_STREAM_ENDPOINTS))
return endpoints

def _get_plus_api_data(self, endpoint, nest):
Expand Down Expand Up @@ -297,7 +336,6 @@ def _flatten_json(cls, metric_base, val, tags):
Recursively flattens the nginx json object. Returns the following: [(metric_name, value, tags)]
"""
output = []

if isinstance(val, dict):
# Pull out the server as a tag instead of trying to read as a metric
if 'server' in val and val['server']:
Expand Down
Loading