alert_definitions_mapper_test.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with this
  4. * work for additional information regarding copyright ownership. The ASF
  5. * licenses this file to you under the Apache License, Version 2.0 (the
  6. * "License"); you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  13. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  14. * License for the specific language governing permissions and limitations under
  15. * the License.
  16. */
  17. var App = require('app');
  18. require('mappers/alert_definitions_mapper');
  19. var testHelpers = require('test/helpers');
  20. describe('App.alertDefinitionsMapper', function () {
  21. /*eslint-disable mocha-cleanup/asserts-limit */
  22. describe('#map', function () {
  23. var json = {
  24. items: [
  25. {
  26. "AlertDefinition" : {
  27. "component_name" : "RESOURCEMANAGER",
  28. "enabled" : true,
  29. "id" : 1,
  30. "ignore_host" : false,
  31. "interval" : 5,
  32. "label" : "ResourceManager RPC Latency",
  33. "name" : "yarn_resourcemanager_rpc_latency",
  34. "description" : "some description",
  35. "scope" : "ANY",
  36. "service_name" : "YARN",
  37. "source" : {
  38. "jmx" : {
  39. "property_list" : [
  40. "Hadoop:service=ResourceManager,name=RpcActivityForPort*/RpcQueueTimeAvgTime",
  41. "Hadoop:service=ResourceManager,name=RpcActivityForPort*/RpcProcessingTimeAvgTime"
  42. ],
  43. "value" : "{0}"
  44. },
  45. "reporting" : {
  46. "ok" : {
  47. "text" : "Average Queue Time:[{0}], Average Processing Time:[{1}]"
  48. },
  49. "warning" : {
  50. "text" : "Average Queue Time:[{0}], Average Processing Time:[{1}]",
  51. "value" : 3000.0
  52. },
  53. "critical" : {
  54. "text" : "Average Queue Time:[{0}], Average Processing Time:[{1}]",
  55. "value" : 5000.0
  56. }
  57. },
  58. "type" : "METRIC",
  59. "uri" : {
  60. "http" : "{{yarn-site/yarn.resourcemanager.webapp.address}}",
  61. "https" : "{{yarn-site/yarn.resourcemanager.webapp.https.address}}",
  62. "https_property" : "{{yarn-site/yarn.http.policy}}",
  63. "https_property_value" : "HTTPS_ONLY",
  64. "default_port" : 0.0
  65. }
  66. }
  67. }
  68. },
  69. {
  70. "AlertDefinition" : {
  71. "component_name" : "RESOURCEMANAGER",
  72. "enabled" : true,
  73. "id" : 2,
  74. "ignore_host" : false,
  75. "interval" : 1,
  76. "label" : "ResourceManager Web UI",
  77. "name" : "yarn_resourcemanager_webui",
  78. "description" : "",
  79. "scope" : "ANY",
  80. "service_name" : "YARN",
  81. "source" : {
  82. "reporting" : {
  83. "ok" : {
  84. "text" : "HTTP {0} response in {2:.4f} seconds"
  85. },
  86. "warning" : {
  87. "text" : "HTTP {0} response in {2:.4f} seconds"
  88. },
  89. "critical" : {
  90. "text" : "Connection failed to {1}"
  91. }
  92. },
  93. "type" : "WEB",
  94. "uri" : {
  95. "http" : "{{yarn-site/yarn.resourcemanager.webapp.address}}",
  96. "https" : "{{yarn-site/yarn.resourcemanager.webapp.https.address}}",
  97. "https_property" : "{{yarn-site/yarn.http.policy}}",
  98. "https_property_value" : "HTTPS_ONLY",
  99. "connection_timeout" : 5.0,
  100. "default_port" : 0.0
  101. }
  102. }
  103. }
  104. },
  105. {
  106. "AlertDefinition" : {
  107. "component_name" : null,
  108. "enabled" : true,
  109. "id" : 3,
  110. "ignore_host" : false,
  111. "interval" : 1,
  112. "label" : "Percent NodeManagers Available",
  113. "name" : "yarn_nodemanager_webui_percent",
  114. "description" : null,
  115. "scope" : "SERVICE",
  116. "service_name" : "YARN",
  117. "source" : {
  118. "alert_name" : "yarn_nodemanager_webui",
  119. "reporting" : {
  120. "ok" : {
  121. "text" : "affected: [{1}], total: [{0}]"
  122. },
  123. "warning" : {
  124. "text" : "affected: [{1}], total: [{0}]",
  125. "value" : 0.1
  126. },
  127. "critical" : {
  128. "text" : "affected: [{1}], total: [{0}]",
  129. "value" : 0.3
  130. }
  131. },
  132. "type" : "AGGREGATE"
  133. }
  134. }
  135. },
  136. {
  137. "AlertDefinition" : {
  138. "component_name" : "NODEMANAGER",
  139. "enabled" : true,
  140. "id" : 4,
  141. "ignore_host" : false,
  142. "interval" : 1,
  143. "label" : "NodeManager Health",
  144. "name" : "yarn_nodemanager_health",
  145. "description" : "some description",
  146. "scope" : "HOST",
  147. "service_name" : "YARN",
  148. "source" : {
  149. "parameters" : [
  150. {
  151. "name" : "connection.timeout",
  152. "display_name" : "Connection Timeout",
  153. "units" : "seconds",
  154. "value" : 5.0,
  155. "description" : "The maximum time before this alert is considered to be CRITICAL",
  156. "type" : "NUMERIC",
  157. "threshold" : "CRITICAL"
  158. }
  159. ],
  160. "path" : "HDP/2.0.6/services/YARN/package/files/alert_nodemanager_health.py",
  161. "type" : "SCRIPT"
  162. }
  163. }
  164. },
  165. {
  166. "AlertDefinition" : {
  167. "component_name" : "ZOOKEEPER_SERVER",
  168. "enabled" : true,
  169. "id" : 5,
  170. "ignore_host" : false,
  171. "interval" : 1,
  172. "label" : "ZooKeeper Server Process",
  173. "name" : "zookeeper_server_process",
  174. "description" : "some description",
  175. "scope" : "ANY",
  176. "service_name" : "ZOOKEEPER",
  177. "source" : {
  178. "default_port" : 2181.0,
  179. "reporting" : {
  180. "ok" : {
  181. "text" : "TCP OK - {0:.4f} response on port {1}"
  182. },
  183. "critical" : {
  184. "text" : "Connection failed: {0} to {1}:{2}"
  185. }
  186. },
  187. "type" : "PORT",
  188. "uri" : "{{zookeeper-env/clientPort}}"
  189. }
  190. }
  191. },
  192. {
  193. "AlertDefinition" : {
  194. "component_name" : "NAMENODE",
  195. "description" : "This service-level alert is triggered if the NN heap usage deviation has grown beyond the specified threshold within a given time interval.",
  196. "enabled" : true,
  197. "help_url" : "http://test.test",
  198. "id" : 6,
  199. "ignore_host" : false,
  200. "interval" : 1,
  201. "label" : "NameNode Heap Usage (Hourly)",
  202. "name" : "namenode_free_heap_size_deviation_percentage",
  203. "repeat_tolerance" : 1,
  204. "repeat_tolerance_enabled" : true,
  205. "scope" : "SERVICE",
  206. "service_name" : "HDFS",
  207. "source" : {
  208. "ams" : {
  209. "metric_list" : [
  210. "jvm.JvmMetrics.MemHeapUsedM",
  211. "jvm.JvmMetrics.MemHeapMaxM"
  212. ],
  213. "value" : "{1} - {0}",
  214. "interval" : 60.0,
  215. "compute" : "sample_standard_deviation_percentage",
  216. "app_id" : "NAMENODE",
  217. "minimum_value" : 1.0
  218. },
  219. "reporting" : {
  220. "ok" : {
  221. "text" : "The sample standard deviation percentage is {0}%"
  222. },
  223. "warning" : {
  224. "text" : "The sample standard deviation percentage is {0}%",
  225. "value" : 20.0
  226. },
  227. "critical" : {
  228. "text" : "The sample standard deviation percentage is {0}%",
  229. "value" : 50.0
  230. },
  231. "units" : "%"
  232. },
  233. "type" : "AMS",
  234. "uri" : {
  235. "http" : "{{ams-site/timeline.metrics.service.webapp.address}}",
  236. "https" : "{{ams-site/timeline.metrics.service.webapp.address}}",
  237. "https_property" : "{{ams-site/timeline.metrics.service.http.policy}}",
  238. "https_property_value" : "HTTPS_ONLY",
  239. "default_port" : 0.0,
  240. "connection_timeout" : 5.0
  241. }
  242. }
  243. }
  244. }
  245. ]
  246. };
  247. beforeEach(function () {
  248. App.alertDefinitionsMapper.setProperties({
  249. 'model': {},
  250. 'parameterModel': {},
  251. 'reportModel': {},
  252. 'metricsSourceModel': {},
  253. 'metricsUriModel': {},
  254. 'metricsAmsModel': {}
  255. });
  256. sinon.stub(App.alertDefinitionsMapper, 'deleteRecord', Em.K);
  257. sinon.stub(App.store, 'commit', Em.K);
  258. sinon.stub(App.store, 'loadMany', function (type, content) {
  259. type.content = content;
  260. });
  261. sinon.stub(App.router, 'get', function() {return false;});
  262. App.cache.previousAlertGroupsMap = {};
  263. sinon.stub(App.alertDefinitionsMapper, 'setMetricsSourcePropertyLists', Em.K);
  264. sinon.stub(App.alertDefinitionsMapper, 'setAlertDefinitionsRawSourceData', Em.K);
  265. });
  266. afterEach(function () {
  267. App.store.commit.restore();
  268. App.store.loadMany.restore();
  269. App.alertDefinitionsMapper.setProperties({
  270. 'model': App.AlertDefinition,
  271. 'reportModel': App.AlertReportDefinition,
  272. 'metricsSourceModel': App.AlertMetricsSourceDefinition,
  273. 'metricsUriModel': App.AlertMetricsUriDefinition,
  274. 'metricsAmsModel': App.AlertMetricsAmsDefinition
  275. });
  276. App.alertDefinitionsMapper.deleteRecord.restore();
  277. App.router.get.restore();
  278. App.cache.previousAlertGroupsMap = {};
  279. App.alertDefinitionsMapper.setMetricsSourcePropertyLists.restore();
  280. App.alertDefinitionsMapper.setAlertDefinitionsRawSourceData.restore();
  281. });
  282. describe('should parse METRIC alertDefinitions', function () {
  283. var data = {items: [json.items[0]]},
  284. expected = [{
  285. id: 1,
  286. "name": "yarn_resourcemanager_rpc_latency",
  287. "label": "ResourceManager RPC Latency",
  288. "description" : "some description",
  289. "service_id": "YARN",
  290. "component_name": "RESOURCEMANAGER",
  291. "enabled": true,
  292. "scope": "ANY",
  293. "interval": 5,
  294. "type": "METRIC",
  295. "jmx_id": "1jmx",
  296. "uri_id": "1uri"
  297. }],
  298. expectedMetricsSource = [{
  299. "id":"1jmx",
  300. "value":"{0}",
  301. "property_list":[
  302. "Hadoop:service=ResourceManager,name=RpcActivityForPort*/RpcQueueTimeAvgTime",
  303. "Hadoop:service=ResourceManager,name=RpcActivityForPort*/RpcProcessingTimeAvgTime"
  304. ]
  305. }],
  306. expectedMetricsUri = [{
  307. "id":"1uri",
  308. "http":"{{yarn-site/yarn.resourcemanager.webapp.address}}",
  309. "https":"{{yarn-site/yarn.resourcemanager.webapp.https.address}}",
  310. "https_property":"{{yarn-site/yarn.http.policy}}",
  311. "https_property_value":"HTTPS_ONLY"
  312. }];
  313. beforeEach(function () {
  314. App.alertDefinitionsMapper.map(data);
  315. });
  316. it('parsing metrics model', function() {
  317. testHelpers.nestedExpect(expected, App.alertDefinitionsMapper.get('model.content'));
  318. });
  319. it('parse metrics source', function() {
  320. testHelpers.nestedExpect(expectedMetricsSource, App.alertDefinitionsMapper.get('metricsSourceModel.content'));
  321. });
  322. it('parse metrics uri', function() {
  323. testHelpers.nestedExpect(expectedMetricsUri, App.alertDefinitionsMapper.get('metricsUriModel.content'));
  324. });
  325. });
  326. describe('should parse WEB alertDefinitions', function () {
  327. var data = {items: [json.items[1]]},
  328. expected = [
  329. {
  330. "id": 2,
  331. "name": "yarn_resourcemanager_webui",
  332. "label": "ResourceManager Web UI",
  333. "description" : "",
  334. "service_id": "YARN",
  335. "component_name": "RESOURCEMANAGER",
  336. "enabled": true,
  337. "scope": "ANY",
  338. "interval": 1,
  339. "type": "WEB",
  340. "uri_id": "2uri"
  341. }
  342. ],
  343. expectedMetricsUri = [{
  344. "id":"2uri",
  345. "http":"{{yarn-site/yarn.resourcemanager.webapp.address}}",
  346. "https":"{{yarn-site/yarn.resourcemanager.webapp.https.address}}",
  347. "https_property":"{{yarn-site/yarn.http.policy}}",
  348. "https_property_value":"HTTPS_ONLY",
  349. "connection_timeout" : 5.0
  350. }];
  351. beforeEach(function () {
  352. App.alertDefinitionsMapper.map(data);
  353. });
  354. it('parsing web model', function() {
  355. testHelpers.nestedExpect(expected, App.alertDefinitionsMapper.get('model.content'));
  356. });
  357. it('parse metrics uri', function() {
  358. testHelpers.nestedExpect(expectedMetricsUri, App.alertDefinitionsMapper.get('metricsUriModel.content'));
  359. });
  360. });
  361. it('should parse AGGREGATE alertDefinitions', function () {
  362. var data = {items: [json.items[2]]},
  363. expected = [
  364. {
  365. "id":3,
  366. "name":"yarn_nodemanager_webui_percent",
  367. "label":"Percent NodeManagers Available",
  368. "description" : "",
  369. "service_id":"YARN",
  370. "component_name":null,
  371. "enabled":true,
  372. "scope":"SERVICE",
  373. "interval":1,
  374. "type":"AGGREGATE",
  375. "alert_name":"yarn_nodemanager_webui"
  376. }
  377. ];
  378. App.alertDefinitionsMapper.map(data);
  379. testHelpers.nestedExpect(expected, App.alertDefinitionsMapper.get('model.content'));
  380. });
  381. describe('should parse SCRIPT alertDefinitions', function () {
  382. var data = {items: [json.items[3]]},
  383. expected = [
  384. {
  385. "id":4,
  386. "name":"yarn_nodemanager_health",
  387. "label":"NodeManager Health",
  388. "description" : "some description",
  389. "service_id":"YARN",
  390. "component_name":"NODEMANAGER",
  391. "enabled":true,
  392. "scope":"HOST",
  393. "interval":1,
  394. "type":"SCRIPT",
  395. "location":"HDP/2.0.6/services/YARN/package/files/alert_nodemanager_health.py"
  396. }
  397. ];
  398. var expectedParameters = [{
  399. "id": "4connection.timeout",
  400. "name": "connection.timeout",
  401. "display_name": "Connection Timeout",
  402. "units": "seconds",
  403. "value": 5,
  404. "description": "The maximum time before this alert is considered to be CRITICAL",
  405. "type": "NUMERIC",
  406. "threshold": "CRITICAL"
  407. }];
  408. beforeEach(function () {
  409. App.alertDefinitionsMapper.map(data);
  410. });
  411. it('should map definition', function () {
  412. testHelpers.nestedExpect(expected, App.alertDefinitionsMapper.get('model.content'));
  413. });
  414. it('should map parameters', function () {
  415. testHelpers.nestedExpect(expectedParameters, App.alertDefinitionsMapper.get('parameterModel.content'));
  416. });
  417. });
  418. it('should parse PORT alertDefinitions', function () {
  419. var data = {items: [json.items[4]]},
  420. expected = [
  421. {
  422. "id":5,
  423. "name":"zookeeper_server_process",
  424. "label":"ZooKeeper Server Process",
  425. "description" : "some description",
  426. "service_id":"ZOOKEEPER",
  427. "component_name":"ZOOKEEPER_SERVER",
  428. "enabled":true,
  429. "scope":"ANY",
  430. "interval":1,
  431. "type":"PORT",
  432. "default_port":2181,
  433. "port_uri":"{{zookeeper-env/clientPort}}"
  434. }
  435. ];
  436. App.alertDefinitionsMapper.map(data);
  437. testHelpers.nestedExpect(expected, App.alertDefinitionsMapper.get('model.content'));
  438. });
  439. describe('should parse AMS alertDefinitions', function () {
  440. var data = {items: [json.items[5]]};
  441. var expected = [
  442. {
  443. "id" : 6,
  444. "interval" : 1,
  445. "label" : "NameNode Heap Usage (Hourly)",
  446. "name" : "namenode_free_heap_size_deviation_percentage",
  447. "repeat_tolerance" : 1,
  448. "repeat_tolerance_enabled" : true,
  449. "scope" : "SERVICE",
  450. "service_name" : "HDFS",
  451. "component_name" : "NAMENODE",
  452. "help_url" : "http://test.test"
  453. }
  454. ];
  455. var expectedMetricsUri = [{
  456. "id":"6uri",
  457. "http" : "{{ams-site/timeline.metrics.service.webapp.address}}",
  458. "https" : "{{ams-site/timeline.metrics.service.webapp.address}}",
  459. "https_property" : "{{ams-site/timeline.metrics.service.http.policy}}",
  460. "https_property_value" : "HTTPS_ONLY",
  461. "connection_timeout" : 5.0
  462. }];
  463. var expectedAms = [{
  464. "id": "6ams",
  465. "value": "{1} - {0}",
  466. "minimal_value": 1,
  467. "interval": 60
  468. }];
  469. beforeEach(function () {
  470. App.alertDefinitionsMapper.map(data);
  471. });
  472. it('should map definition', function () {
  473. testHelpers.nestedExpect(expected, App.alertDefinitionsMapper.get('model.content'));
  474. });
  475. it('parse metrics uri', function() {
  476. testHelpers.nestedExpect(expectedMetricsUri, App.alertDefinitionsMapper.get('metricsUriModel.content'));
  477. });
  478. it('parse ams parameters', function () {
  479. testHelpers.nestedExpect(expectedAms, App.alertDefinitionsMapper.get('metricsAmsModel.content'));
  480. });
  481. });
  482. /*eslint-disable mocha-cleanup/complexity-it */
  483. it('should set groups from App.cache.previousAlertGroupsMap', function () {
  484. App.cache.previousAlertGroupsMap = {
  485. 1: [5,1],
  486. 2: [4,3],
  487. 3: [3,2],
  488. 4: [2,5],
  489. 5: [1,4]
  490. };
  491. App.alertDefinitionsMapper.map(json);
  492. expect(App.alertDefinitionsMapper.get('model.content')[0].groups).to.eql([5, 1]);
  493. expect(App.alertDefinitionsMapper.get('model.content')[1].groups).to.eql([4, 3]);
  494. expect(App.alertDefinitionsMapper.get('model.content')[2].groups).to.eql([3, 2]);
  495. expect(App.alertDefinitionsMapper.get('model.content')[3].groups).to.eql([2, 5]);
  496. expect(App.alertDefinitionsMapper.get('model.content')[4].groups).to.eql([1, 4]);
  497. });
  498. /*eslint-enable mocha-cleanup/complexity-it */
  499. describe('should delete not existing definitions', function () {
  500. var definitions = [
  501. Em.Object.create({id: 100500, type: 'PORT'})
  502. ];
  503. beforeEach(function () {
  504. sinon.stub(App.AlertDefinition, 'find', function () {
  505. return definitions;
  506. });
  507. });
  508. afterEach(function() {
  509. App.AlertDefinition.find.restore();
  510. });
  511. it('should delete PORT alert definition with id 100500', function () {
  512. App.alertDefinitionsMapper.map(json);
  513. expect(App.alertDefinitionsMapper.deleteRecord.calledOnce).to.be.true;
  514. expect(App.alertDefinitionsMapper.deleteRecord.args[0][0].id).to.equal(100500);
  515. });
  516. });
  517. });
  518. /*eslint-enable mocha-cleanup/asserts-limit */
  519. });