Skip to content

Commit 0369d53

Browse files
authored
Merge pull request #3041 from DataDog/feature/configure_application_tags
[yarn] Add configurable application tags
2 parents a687cd0 + 0358b58 commit 0369d53

File tree

3 files changed

+80
-28
lines changed

3 files changed

+80
-28
lines changed

checks.d/yarn.py

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,33 @@ class YarnCheck(AgentCheck):
143143
'''
144144
Extract statistics from YARN's ResourceManger REST API
145145
'''
146+
_ALLOWED_APPLICATION_TAGS = [
147+
'applicationTags',
148+
'applicationType',
149+
'name',
150+
'queue',
151+
'user'
152+
]
146153

147154
def check(self, instance):
148155

149156
# Get properties from conf file
150157
rm_address = instance.get('resourcemanager_uri', DEFAULT_RM_URI)
158+
app_tags = instance.get('application_tags', {})
159+
160+
if type(app_tags) is not dict:
161+
self.log.error('application_tags is incorrect: %s is not a dictionary', app_tags)
162+
app_tags = {}
163+
164+
filtered_app_tags = {}
165+
for dd_prefix, yarn_key in app_tags.iteritems():
166+
if yarn_key in self._ALLOWED_APPLICATION_TAGS:
167+
filtered_app_tags[dd_prefix] = yarn_key
168+
app_tags = filtered_app_tags
169+
170+
# Collected by default
171+
app_tags['app_name'] = 'name'
172+
151173

152174
# Get additional tags from the conf file
153175
tags = instance.get('tags', [])
@@ -166,7 +188,7 @@ def check(self, instance):
166188

167189
# Get metrics from the Resource Manager
168190
self._yarn_cluster_metrics(rm_address, tags)
169-
self._yarn_app_metrics(rm_address, tags)
191+
self._yarn_app_metrics(rm_address, app_tags, tags)
170192
self._yarn_node_metrics(rm_address, tags)
171193

172194
def _yarn_cluster_metrics(self, rm_address, addl_tags):
@@ -182,44 +204,50 @@ def _yarn_cluster_metrics(self, rm_address, addl_tags):
182204
if yarn_metrics is not None:
183205
self._set_yarn_metrics_from_json(addl_tags, yarn_metrics, YARN_CLUSTER_METRICS)
184206

185-
def _yarn_app_metrics(self, rm_address, addl_tags):
207+
def _yarn_app_metrics(self, rm_address, app_tags, addl_tags):
186208
'''
187209
Get metrics for running applications
188210
'''
189-
metrics_json = self._rest_request_to_json(rm_address,
211+
metrics_json = self._rest_request_to_json(
212+
rm_address,
190213
YARN_APPS_PATH,
191-
states=YARN_APPLICATION_STATES)
214+
states=YARN_APPLICATION_STATES
215+
)
192216

193-
if metrics_json:
194-
if metrics_json['apps'] is not None:
195-
if metrics_json['apps']['app'] is not None:
217+
if (metrics_json and metrics_json['apps'] is not None and
218+
metrics_json['apps']['app'] is not None):
196219

197-
for app_json in metrics_json['apps']['app']:
220+
for app_json in metrics_json['apps']['app']:
198221

199-
app_name = app_json['name']
222+
tags = []
223+
for dd_tag, yarn_key in app_tags.iteritems():
224+
try:
225+
tags.append("{tag}:{value}".format(
226+
tag=dd_tag, value=app_json[yarn_key]
227+
))
228+
except KeyError:
229+
self.log.error("Invalid value %s for application_tag", yarn_key)
200230

201-
tags = ['app_name:%s' % str(app_name)]
202-
tags.extend(addl_tags)
231+
tags.extend(addl_tags)
203232

204-
self._set_yarn_metrics_from_json(tags, app_json, YARN_APP_METRICS)
233+
self._set_yarn_metrics_from_json(tags, app_json, YARN_APP_METRICS)
205234

206235
def _yarn_node_metrics(self, rm_address, addl_tags):
207236
'''
208237
Get metrics related to YARN nodes
209238
'''
210239
metrics_json = self._rest_request_to_json(rm_address, YARN_NODES_PATH)
211240

212-
if metrics_json:
213-
if metrics_json['nodes'] is not None:
214-
if metrics_json['nodes']['node'] is not None:
241+
if (metrics_json and metrics_json['nodes'] is not None and
242+
metrics_json['nodes']['node'] is not None):
215243

216-
for node_json in metrics_json['nodes']['node']:
217-
node_id = node_json['id']
244+
for node_json in metrics_json['nodes']['node']:
245+
node_id = node_json['id']
218246

219-
tags = ['node_id:%s' % str(node_id)]
220-
tags.extend(addl_tags)
247+
tags = ['node_id:%s' % str(node_id)]
248+
tags.extend(addl_tags)
221249

222-
self._set_yarn_metrics_from_json(tags, node_json, YARN_NODE_METRICS)
250+
self._set_yarn_metrics_from_json(tags, node_json, YARN_NODE_METRICS)
223251

224252
def _set_yarn_metrics_from_json(self, tags, metrics_json, yarn_metrics):
225253
'''
@@ -243,7 +271,7 @@ def _set_metric(self, metric_name, metric_type, value, tags=None, device_name=No
243271
elif metric_type == INCREMENT:
244272
self.increment(metric_name, value, tags=tags, device_name=device_name)
245273
else:
246-
self.log.error('Metric type "%s" unknown' % (metric_type))
274+
self.log.error('Metric type "%s" unknown', metric_type)
247275

248276
def _rest_request_to_json(self, address, object_path, *args, **kwargs):
249277
'''

conf.d/yarn.yaml.example

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ init_config:
33
instances:
44
# The YARN check retrieves metrics from YARNS's ResourceManager. This
55
# check must be run from the Master Node and the ResourceManager URI must
6-
# be specified below. The ResourceManager URI is composed of the
6+
# be specified below. The ResourceManager URI is composed of the
77
# ResourceManager's hostname and port.
88
#
99
# The ResourceManager hostname can be found in the yarn-site.xml conf file
@@ -19,5 +19,16 @@ instances:
1919

2020
# Optional tags to be applied to every emitted metric.
2121
# tags:
22-
# - key:value
23-
# - instance:production
22+
# - "key:value"
23+
# - "instance:production"
24+
25+
# Optional tags retrieved from the application data to be applied to the
26+
# application metrics.
27+
# application_tags:
28+
# # tag_prefix: yarn_key
29+
# app_queue: queue
30+
# This will add a tag 'app_queue:name_of_the_queue' to the app metrics,
31+
# app_queue being the tag_prefix and queue the actual YARN key.
32+
# Allowed yarn keys: applicationType, applicationTags, name, queue, user
33+
# By default, the application name is collected with the prefix app_name.
34+

tests/checks/mock/test_yarn.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,14 @@ class YARNCheck(AgentCheckTest):
5353

5454
YARN_CONFIG = {
5555
'resourcemanager_uri': 'http://localhost:8088',
56-
'cluster_name': CLUSTER_NAME
56+
'cluster_name': CLUSTER_NAME,
57+
'tags': [
58+
'opt_key:opt_value'
59+
],
60+
'application_tags': {
61+
'app_id': 'id',
62+
'app_queue': 'queue'
63+
}
5764
}
5865

5966
YARN_CLUSTER_METRICS_VALUES = {
@@ -82,7 +89,10 @@ class YARNCheck(AgentCheckTest):
8289
'yarn.metrics.rebooted_nodes': 0,
8390
}
8491

85-
YARN_CLUSTER_METRICS_TAGS = ['cluster_name:%s' % CLUSTER_NAME]
92+
YARN_CLUSTER_METRICS_TAGS = [
93+
'cluster_name:%s' % CLUSTER_NAME,
94+
'opt_key:opt_value'
95+
]
8696

8797
YARN_APP_METRICS_VALUES = {
8898
'yarn.apps.progress': 100,
@@ -98,7 +108,9 @@ class YARNCheck(AgentCheckTest):
98108

99109
YARN_APP_METRICS_TAGS = [
100110
'cluster_name:%s' % CLUSTER_NAME,
101-
'app_name:word count'
111+
'app_name:word count',
112+
'app_queue:default',
113+
'opt_key:opt_value'
102114
]
103115

104116
YARN_NODE_METRICS_VALUES = {
@@ -112,7 +124,8 @@ class YARNCheck(AgentCheckTest):
112124

113125
YARN_NODE_METRICS_TAGS = [
114126
'cluster_name:%s' % CLUSTER_NAME,
115-
'node_id:h2:1235'
127+
'node_id:h2:1235',
128+
'opt_key:opt_value'
116129
]
117130

118131
@mock.patch('requests.get', side_effect=requests_get_mock)

0 commit comments

Comments
 (0)