zabbix_export:
  version: '7.0'
  template_groups:
    - uuid: c2c162144c2d4c5491c8801193af4945
      name: Templates/Cloud
  templates:
    - uuid: c94105c23220452baed03ba87f09ca12
      template: 'AWS ECS Cluster by HTTP'
      name: 'AWS ECS Cluster by HTTP'
      description: |
        The template gets AWS ECS Cluster metrics and uses the script item to make HTTP requests to the CloudWatch API.
        Don't forget to read the README.md for the correct setup of the template.
        
        You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
        
        Generated by official Zabbix template tool "Templator"
      vendor:
        name: Zabbix
        version: 7.0-0
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 9c4a894d46174d679c58c9a1339dec2f
          name: 'Get alarms check'
          type: DEPENDENT
          key: aws.ecs.alarms.check
          value_type: CHAR
          description: 'Data collection check.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.ecs.get_alarms
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: f8ff542b35a345e490910323d5dee19c
              expression: 'length(last(/AWS ECS Cluster by HTTP/aws.ecs.alarms.check))>0'
              name: 'Failed to get alarms data'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              tags:
                - tag: scope
                  value: availability
        - uuid: c9d2dff2619d41c1a0d1a528fecab461
          name: 'Container Instance Count'
          type: DEPENDENT
          key: aws.ecs.container_instance_count
          value_type: FLOAT
          description: '''The number of EC2 instances running the Amazon ECS agent that are registered with a cluster.'''
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.MetricData[?(@.Label == "ContainerInstanceCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: system
        - uuid: 161886f00f91479597db4bfaae27db46
          name: 'CPU Reserved'
          type: DEPENDENT
          key: aws.ecs.cpu_reserved
          value_type: FLOAT
          description: |
            'A number of CPU units reserved by tasks in the resource that is specified by the dimension set that you're using.
             This metric is only collected for tasks that have a defined CPU reservation in their task definition.'
          valuemap:
            name: 'CPU Reserved'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "CpuReserved")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: cpu
        - uuid: fc4c44d533304ac3a4f59773c7424324
          name: 'CPU Utilization'
          type: DEPENDENT
          key: aws.ecs.cpu_utilization
          value_type: FLOAT
          units: '%'
          description: 'Cluster CPU utilization'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.CPUUtilization
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: cpu
          triggers:
            - uuid: 5395c1d6d27c495a8972d2ea8ca8b02a
              expression: 'min(/AWS ECS Cluster by HTTP/aws.ecs.cpu_utilization,15m)>{$AWS.ECS.CLUSTER.CPU.UTIL.WARN}'
              name: 'High CPU utilization'
              event_name: 'High CPU utilization (over {$AWS.ECS.CLUSTER.CPU.UTIL.WARN}% for 15m)'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The CPU utilization is too high. The system might be slow to respond.'
              tags:
                - tag: scope
                  value: capacity
                - tag: scope
                  value: performance
        - uuid: 9aefed8b23ee41a7941e41f33fc95ebe
          name: 'Get alarms data'
          type: SCRIPT
          key: aws.ecs.get_alarms
          delay: 0s;m/1
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/meta-data/iam/security-credentials',
            
            	getField: function (data, path) {
            		var steps = path.split('.');
            		for (var i = 0; i < steps.length; i++) {
            			var step = steps[i];
            			if (typeof data !== 'object' || typeof data[step] === 'undefined') {
            				throw 'Required field was not found: ' + path;
            			}
            
            			data = data[step];
            		}
            
            		return data;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				var IamRoleName = request.get(AWS.metadata);
            
            				if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            					throw 'Error getting security credentials from instance metadata. Role not found.';
            				}
            
            				credentials = request.get(AWS.metadata + '/' + encodeURI(IamRoleName));
            
            				if (request.getStatus() !== 200 || credentials === null || credentials === '') {
            					throw 'Error getting security credentials from instance metadata.';
            				}
            
            				try {
            					credentials = JSON.parse(credentials);
            				}
            				catch (error) {
            					throw 'Failed to parse response received from instance metadata. Check debug log for more information.';
            				}
            
            				['AccessKeyId', 'SecretAccessKey', 'Token'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials is not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			case 'access_key':
            			default:
            				AWS.params['auth_type'] = 'access_key';
            				['AccessKeyId', 'SecretAccessKey'].forEach(function (field) {
            					if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            						throw 'Required param is not set: "' + field + '".';
            					}
            					AWS.params[field] = params[field];
            				});
            		}
            		['region', 'cluster_name'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: "' + field + '".';
            			}
            			AWS.params[field] = params[field];
            		});
            	},
            
            	sign: function (key, message) {
            		var hex = hmac('sha256', key, message);
            
            		if ((hex.length % 2) === 1) {
            			throw 'Invalid length of a hex string!';
            		}
            
            		var result = new Int8Array(hex.length / 2);
            		for (var i = 0, b = 0; i < hex.length; i += 2, b++) {
            			result[b] = parseInt(hex.substring(i, i + 2), 16);
            		}
            
            		return result;
            	},
            
            	prepareParams: function (params) {
            		var result = [];
            
            		Object.keys(params).sort().forEach(function (key) {
            			if (typeof params[key] !== 'object') {
            				result.push(key + '=' + encodeURIComponent(params[key]));
            			}
            			else {
            				result.push(prepareObject(key, params[key]));
            			}
            		});
            
            		return result.join('&');
            	},
            
            	request: function (method, region, service, params, data) {
            		if (typeof data === 'undefined' || data === null) {
            			data = '';
            		}
            
            		var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''),
            			date = amzdate.replace(/T\d+Z/, ''),
            			host = service + '.' + region + '.amazonaws.com',
            			canonical_uri = '/',
            			canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n',
            			signed_headers = 'content-encoding;host;x-amz-date',
            			canonical_request = method + '\n' + canonical_uri + '\n' + params + '\n' + canonical_headers + '\n' + signed_headers + '\n' + sha256(data),
            			credential_scope = date + '/' + region + '/' + service + '/' + 'aws4_request',
            			request_string = 'AWS4-HMAC-SHA256' + '\n' + amzdate + '\n' + credential_scope + '\n' + sha256(canonical_request),
            			key = AWS.sign('AWS4' + AWS.params.SecretAccessKey, date);
            
            		key = AWS.sign(key, region);
            		key = AWS.sign(key, service);
            		key = AWS.sign(key, 'aws4_request');
            
            		var request = new HttpRequest(),
            			url = 'https://' + host + canonical_uri + '?' + params;
            
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('x-amz-date: ' + amzdate);
            		request.addHeader('Accept: application/json');
            		request.addHeader('Content-Type: application/json');
            		request.addHeader('Content-Encoding: amz-1.0');
            		request.addHeader('Authorization: ' + 'AWS4-HMAC-SHA256 Credential=' + AWS.params.AccessKeyId + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + hmac('sha256', key, request_string));
            		if (AWS.params.auth_type === 'role_base')
            			request.addHeader('X-Amz-Security-Token: ' + AWS.params.Token);
            
            		Zabbix.log(4, '[ AWS ECS ] Sending request: ' + url);
            
            		response = request.get(url);
            
            		Zabbix.log(4, '[ AWS ECS ] Received response with status code ' + request.getStatus() + ': ' + response);
            
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		if (response[0] === '<') {
            			try {
            				response = XML.toJson(response);
            			}
            			catch (error) {
            				throw 'Failed to parse response received from AWS CloudWatch API. Check debug log for more information.';
            			}
            		}
            
            		if (response !== null) {
            			try {
            				response = JSON.parse(response);
            			}
            			catch (error) {
            				throw 'Failed to parse response received from AWS CloudWatch API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	getAlarms: function () {
            		var payload = {
            			'Action': 'DescribeAlarms',
            			'Version': '2010-08-01',
            			'MaxRecords': 100
            		},
            			result = [];
            
            		while (payload.NextToken !== '') {
            			var alarms = AWS.getField(AWS.request('GET', AWS.params.region, 'monitoring', AWS.prepareParams(payload)), 'DescribeAlarmsResponse.DescribeAlarmsResult');
            			payload.NextToken = alarms.NextToken || '';
            			alarms_list = AWS.getField(alarms, 'MetricAlarms');
            
            			if (!Array.isArray(alarms_list))
            				alarms_list = [alarms_list]
            			alarms_list.forEach(function (alarm) {
            				var dimensions = alarm.Dimensions;
            
            				Zabbix.log(4, '[ AWS ECS ] dimensions: ' + JSON.stringify(dimensions));
            				if (Array.isArray(alarm.Metrics)) {
            					alarm.Metrics.forEach(function (metric) {
            						if (typeof metric.MetricStat === 'object' && metric.MetricStat !== null
            							&& typeof metric.MetricStat.Metric === 'object' && metric.MetricStat.Metric !== null
            							&& Array.isArray(metric.MetricStat.Metric.Dimensions)) {
            							dimensions = dimensions.concat(metric.MetricStat.Metric.Dimensions);
            						}
            					});
            				}
            				for (var i in dimensions) {
            					if (dimensions[i].Name === 'ClusterName' && dimensions[i].Value === AWS.params.cluster_name) {
            						result.push(alarm);
            						break;
            					}
            				}
            			});
            		}
            
            		return result;
            	}
            }
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	return JSON.stringify(AWS.getAlarms());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS ECS ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: |
            Get alarms data.
            DescribeAlarms API method: https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html
          preprocessing:
            - type: CHECK_NOT_SUPPORTED
              parameters:
                - '-1'
          timeout: 15s
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: cluster_name
              value: '{$AWS.ECS.CLUSTER.NAME}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
          tags:
            - tag: component
              value: raw
        - uuid: fa8f1dc24615438e98cbad686d40eaf7
          name: 'Get cluster services'
          type: SCRIPT
          key: aws.ecs.get_cluster_services
          delay: 5m
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/meta-data/iam/security-credentials',
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				var IamRoleName = request.get(AWS.metadata);
            
            				if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            					throw 'Error getting security credentials from instance metadata. Role not found.';
            				}
            
            				credentials = request.get(AWS.metadata + '/' + encodeURI(IamRoleName));
            
            				if (request.getStatus() !== 200 || credentials === null || credentials === '') {
            					throw 'Error getting security credentials from instance metadata.';
            				}
            
            				try {
            					credentials = JSON.parse(credentials);
            				}
            				catch (error) {
            					throw 'Failed to parse response received from instance metadata. Check debug log for more information.';
            				}
            
            				['AccessKeyId', 'SecretAccessKey', 'Token'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials is not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			case 'access_key':
            			default:
            				AWS.params['auth_type'] = 'access_key';
            				['AccessKeyId', 'SecretAccessKey'].forEach(function (field) {
            					if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            						throw 'Required param is not set: "' + field + '".';
            					}
            					AWS.params[field] = params[field];
            				});
            		}
            		['region', 'cluster_name'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: "' + field + '".';
            			}
            			AWS.params[field] = params[field];
            		});
            	},
            
            	getField: function (data, path) {
            		var steps = path.split('.');
            		for (var i = 0; i < steps.length; i++) {
            			var step = steps[i];
            			if (typeof data !== 'object' || typeof data[step] === 'undefined') {
            				throw 'Required field was not found: ' + path;
            			}
            
            			data = data[step];
            		}
            
            		return data;
            	},
            
            	sign: function (key, message) {
            		var hex = hmac('sha256', key, message);
            
            		if ((hex.length % 2) === 1) {
            			throw 'Invalid length of a hex string!';
            		}
            
            		var result = new Int8Array(hex.length / 2);
            		for (var i = 0, b = 0; i < hex.length; i += 2, b++) {
            			result[b] = parseInt(hex.substring(i, i + 2), 16);
            		}
            
            		return result;
            	},
            
            	prepareParams: function (params) {
            		var result = [];
            
            		Object.keys(params).sort().forEach(function (key) {
            			if (typeof params[key] !== 'object') {
            				result.push(key + '=' + encodeURIComponent(params[key]));
            			}
            			else {
            				result.push(prepareObject(key, params[key]));
            			}
            		});
            
            		return result.join('&');
            	},
            
            	request: function (method, region, service, host, params, data, uri) {
            		if (typeof data === 'undefined' || data === null) {
            			data = '';
            		}
            
            		var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''),
            			date = amzdate.replace(/T\d+Z/, ''),
            
            			canonical_uri = '/' + uri,
            			canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n',
            			signed_headers = 'content-encoding;host;x-amz-date',
            			canonical_request = method + '\n' + canonical_uri + '\n' + params + '\n' + canonical_headers + '\n' + signed_headers + '\n' + sha256(data),
            			credential_scope = date + '/' + region + '/' + service + '/' + 'aws4_request',
            			request_string = 'AWS4-HMAC-SHA256' + '\n' + amzdate + '\n' + credential_scope + '\n' + sha256(canonical_request),
            			key = AWS.sign('AWS4' + AWS.params.SecretAccessKey, date);
            
            		key = AWS.sign(key, region);
            		key = AWS.sign(key, service);
            		key = AWS.sign(key, 'aws4_request');
            
            		var request = new HttpRequest(),
            			url = 'https://' + host + canonical_uri + '?' + params;
            
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('x-amz-date: ' + amzdate);
            		request.addHeader('x-amz-content-sha256:' + sha256(data));
            		request.addHeader('Accept: application/json');
            		request.addHeader('Content-Type: application/x-www-form-urlencoded');
            		request.addHeader('Content-Encoding: amz-1.0');
            		request.addHeader('Authorization: ' + 'AWS4-HMAC-SHA256 Credential=' + AWS.params.AccessKeyId + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + hmac('sha256', key, request_string));
            		if (AWS.params.auth_type === 'role_base')
            			request.addHeader('X-Amz-Security-Token: ' + AWS.params.Token);
            
            		Zabbix.log(4, '[ AWS ECS ] Sending request: ' + url);
            
            		response = request.post(url, data);
            
            		Zabbix.log(4, '[ AWS ECS ] Received response with status code ' + request.getStatus() + ': ' + response);
            
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from AWS API. Check debug log for more information.';
            		}
            
            		return response;
            	},
            
            	listServices: function () {
            		var payload = {},
            			result,
            			ECSClusters_Services,
            			services = [];
            
            		payload['Action'] = 'ListServices';
            		payload['Version'] = '2014-11-13';
            		payload['cluster'] = AWS.params.cluster_name;
            
            		result = AWS.request('POST', AWS.params.region, 'ecs', 'ecs.' + AWS.params.region + '.amazonaws.com', AWS.prepareParams(payload), '', '');
            		ECSClusters_Services = AWS.getField(result, 'ListServicesResponse.ListServicesResult.serviceArns')
            
            		for (k in ECSClusters_Services) {
            			id = ECSClusters_Services[k];
            
            			json = {};
            			input = id.split(AWS.params.cluster_name + '/');
            			for (var i = 1; i < input.length; i += 2) {
            				json[input[i]] = input[i + 1];
            			}
            			services.push({
            				'service_name': input[1],
            			});
            		}
            
            		if (Array.isArray(services))
            			return services;
            		else
            			return [services];
            
            	},
            
            
            	ListTasks: function () {
            		var payload = {},
            			result,
            			ECSClusters_Services_Tasks,
            			tasks = [];
            
            		payload['Action'] = 'ListTasks';
            		payload['Version'] = '2014-11-13';
            		payload['cluster'] = AWS.params.cluster_name;
            		payload['status'] = AWS.params.status;
            
            		result = AWS.request('POST', AWS.params.region, 'ecs', 'ecs.' + AWS.params.region + '.amazonaws.com', AWS.prepareParams(payload), '', '');
            		ECSClusters_Services_Tasks = AWS.getField(result, 'ListTasksResponse.ListTasksResult.taskArns')
            		for (k in ECSClusters_Services_Tasks) {
            			id = ECSClusters_Services_Tasks[k];
            			json = {};
            			input = id.split(AWS.params.cluster_name + '/');
            			for (var i = 1; i < input.length; i += 2) {
            				json[input[i]] = input[i + 1];
            			}
            			tasks.push({
            				'task_id': input[1],
            			});
            		}
            
            		if (Array.isArray(tasks))
            			return tasks;
            		else
            			return [tasks];
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            	var services = AWS.listServices(),
            		tasks = AWS.ListTasks();
            	return JSON.stringify(({ services, tasks }));
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS ECS ] ERROR: ' + error);
            	return JSON.stringify({ 'error': error });
            }
          description: |
            Get cluster services.
            Full metrics list related to ECS: https://docs.aws.amazon.com/AmazonECS/latest/userguide/metrics-dimensions.html
          preprocessing:
            - type: CHECK_NOT_SUPPORTED
              parameters:
                - '-1'
          timeout: 15s
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: cluster_name
              value: '{$AWS.ECS.CLUSTER.NAME}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
          tags:
            - tag: component
              value: raw
        - uuid: f45389a638c645f8905dc69d6cafb8b3
          name: 'Get cluster metrics'
          type: SCRIPT
          key: aws.ecs.get_metrics
          delay: 0s;m/1
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	request_period: 600,
            	metadata: 'http://169.254.169.254/latest/meta-data/iam/security-credentials',
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				var IamRoleName = request.get(AWS.metadata);
            
            				if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            					throw 'Error getting security credentials from instance metadata. Role not found.';
            				}
            
            				credentials = request.get(AWS.metadata + '/' + encodeURI(IamRoleName));
            
            				if (request.getStatus() !== 200 || credentials === null || credentials === '') {
            					throw 'Error getting security credentials from instance metadata.';
            				}
            
            				try {
            					credentials = JSON.parse(credentials);
            				}
            				catch (error) {
            					throw 'Failed to parse response received from instance metadata. Check debug log for more information.';
            				}
            
            				['AccessKeyId', 'SecretAccessKey', 'Token'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials is not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			case 'access_key':
            			default:
            				AWS.params['auth_type'] = 'access_key';
            				['AccessKeyId', 'SecretAccessKey'].forEach(function (field) {
            					if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            						throw 'Required param is not set: "' + field + '".';
            					}
            					AWS.params[field] = params[field];
            				});
            		}
            		['region', 'cluster_name'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: "' + field + '".';
            			}
            			AWS.params[field] = params[field];
            		});
            	},
            
            	getField: function (data, path) {
            		var steps = path.split('.');
            		for (var i = 0; i < steps.length; i++) {
            			var step = steps[i];
            			if (typeof data !== 'object' || typeof data[step] === 'undefined') {
            				throw 'Required field was not found: ' + path;
            			}
            
            			data = data[step];
            		}
            
            		return data;
            	},
            
            	sign: function (key, message) {
            		var hex = hmac('sha256', key, message);
            
            		if ((hex.length % 2) === 1) {
            			throw 'Invalid length of a hex string!';
            		}
            
            		var result = new Int8Array(hex.length / 2);
            		for (var i = 0, b = 0; i < hex.length; i += 2, b++) {
            			result[b] = parseInt(hex.substring(i, i + 2), 16);
            		}
            
            		return result;
            	},
            
            	prepareRecursive: function (prefix, param) {
            		var result = {};
            
            		if (typeof param === 'object') {
            			if (Array.isArray(param)) {
            				param.forEach(function (value, index) {
            					var nested = AWS.prepareRecursive(prefix + '.member.' + (index + 1), value);
            					Object.keys(nested).forEach(function (key) {
            						result[key] = nested[key];
            					});
            				});
            			}
            			else {
            				Object.keys(param).forEach(function (k) {
            					var nested = AWS.prepareRecursive(prefix + '.' + k, param[k]);
            					Object.keys(nested).forEach(function (key) {
            						result[key] = nested[key];
            					});
            				});
            			}
            		}
            		else {
            			result[prefix] = param;
            		}
            
            		return result;
            	},
            
            	renderPayload: function (period, cluster_name) {
            		var metrics_list = [
            			'ContainerInstanceCount:Count',
            			'ServiceCount:Count',
            			'CpuReserved:None',
            			'CpuUtilized:None',
            			'MemoryReserved:Megabytes',
            			'MemoryUtilized:Megabytes',
            			'NetworkRxBytes:Bytes/Second',
            			'NetworkTxBytes:Bytes/Second',
            			'StorageReadBytes:Bytes',
            			'StorageWriteBytes:Bytes',
            			'TaskCount:Count'
            		];
            
            		var metric_payload = [];
            		metrics_list.forEach(function (metric) {
            			var parts = metric.split(':', 2);
            			var name = parts[0].replace(/[^a-zA-Z0-9]/g, '');
            			metric_payload.push({
            				'Id': name.charAt(0).toLowerCase() + name.slice(1),
            				'MetricStat': {
            					'Metric': {
            						'MetricName': parts[0],
            						'Namespace': 'ECS/ContainerInsights',
            						'Dimensions': [
            							{
            								'Name': 'ClusterName',
            								'Value': cluster_name
            							}
            						]
            					},
            					'Period': period,
            					'Stat': 'Average',
            					'Unit': parts[1]
            				}
            			});
            		});
            
            		return metric_payload;
            	},
            
            	prepareParams: function (params) {
            		var result = [];
            
            		Object.keys(params).sort().forEach(function (key) {
            			if (typeof params[key] !== 'object') {
            				result.push(key + '=' + encodeURIComponent(params[key]));
            			}
            			else {
            				result.push(prepareObject(key, params[key]));
            			}
            		});
            
            		return result.join('&');
            	},
            
            	request: function (method, region, service, params, data) {
            		if (typeof data === 'undefined' || data === null) {
            			data = '';
            		}
            
            		var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''),
            			date = amzdate.replace(/T\d+Z/, ''),
            			host = service + '.' + region + '.amazonaws.com',
            			canonical_uri = '/',
            			canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n',
            			signed_headers = 'content-encoding;host;x-amz-date',
            			canonical_request = method + '\n' + canonical_uri + '\n' + params + '\n' + canonical_headers + '\n' + signed_headers + '\n' + sha256(data),
            			credential_scope = date + '/' + region + '/' + service + '/' + 'aws4_request',
            			request_string = 'AWS4-HMAC-SHA256' + '\n' + amzdate + '\n' + credential_scope + '\n' + sha256(canonical_request),
            			key = AWS.sign('AWS4' + AWS.params.SecretAccessKey, date);
            
            		key = AWS.sign(key, region);
            		key = AWS.sign(key, service);
            		key = AWS.sign(key, 'aws4_request');
            
            		var request = new HttpRequest(),
            			url = 'https://' + host + canonical_uri + '?' + params;
            
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('x-amz-date: ' + amzdate);
            		request.addHeader('Accept: application/json');
            		request.addHeader('Content-Type: application/json');
            		request.addHeader('Content-Encoding: amz-1.0');
            		request.addHeader('Authorization: ' + 'AWS4-HMAC-SHA256 Credential=' + AWS.params.AccessKeyId + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + hmac('sha256', key, request_string));
            		if (AWS.params.auth_type === 'role_base')
            			request.addHeader('X-Amz-Security-Token: ' + AWS.params.Token);
            
            		Zabbix.log(4, '[ AWS ECS  ] Sending request: ' + url);
            
            		response = request.get(url);
            
            		Zabbix.log(4, '[ AWS ECS ] Received response with status code ' + request.getStatus() + ': ' + response);
            
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		if (response !== null) {
            			try {
            				response = JSON.parse(response);
            			}
            			catch (error) {
            				throw 'Failed to parse response received from AWS CloudWatch API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	getMetricsData: function () {
            		var timestamp = new Date().getTime(),
            			MetricData = [],
            			CPUUtilization,
            			MemoryUtilization,
            			DiskUtilization,
            			obj = {},
            			metrics = ['CpuReserved', 'CpuUtilized', 'MemoryReserved', 'MemoryUtilized'],
            			end_time = new Date(timestamp).toISOString().replace(/\.\d+Z/, 'Z'),
            			start_time = new Date(timestamp - AWS.request_period * 1000).toISOString().replace(/\.\d+Z/, 'Z'),
            			payload = AWS.prepareRecursive('MetricDataQueries', AWS.renderPayload(AWS.request_period, AWS.params.cluster_name));
            
            		payload['Action'] = 'GetMetricData';
            		payload['Version'] = '2010-08-01';
            		payload['StartTime'] = start_time;
            		payload['EndTime'] = end_time;
            		payload['ScanBy'] = 'TimestampDescending';
            
            		result = AWS.request('GET', AWS.params.region, 'monitoring', AWS.prepareParams(payload));
            		MetricData = AWS.getField(result, 'GetMetricDataResponse.GetMetricDataResult.MetricDataResults')
            
            		MetricData.forEach(function (id) {
            			for (i in metrics) {
            				if (AWS.getField(id, 'Label') === metrics[i]) {
            					obj[metrics[i]] = AWS.getField(id, 'Values');
            				}
            			}
            		});
            		CPUUtilization = Math.abs(obj.CpuUtilized * 100 / obj.CpuReserved);
            		MemoryUtilization = Math.abs(obj.MemoryUtilized * 100 / obj.MemoryReserved);
            		return ({ MetricData, MemoryUtilization, CPUUtilization, DiskUtilization });
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	return JSON.stringify(AWS.getMetricsData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS ECS ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: |
            Get cluster metrics.
            Full metrics list related to ECS: https://docs.aws.amazon.com/AmazonECS/latest/userguide/metrics-dimensions.html
          preprocessing:
            - type: CHECK_NOT_SUPPORTED
              parameters:
                - '-1'
          timeout: 15s
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: cluster_name
              value: '{$AWS.ECS.CLUSTER.NAME}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
          tags:
            - tag: component
              value: raw
        - uuid: 0e1c53da0225410ea835f5d471afac13
          name: 'Memory Utilization'
          type: DEPENDENT
          key: aws.ecs.memory_utilization
          value_type: FLOAT
          units: '%'
          description: |
            'The memory being used by tasks in the resource that is specified by the dimension set that you're using.
             This metric is only collected for tasks that have a defined memory reservation in their task definition.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.MemoryUtilization
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: memory
          triggers:
            - uuid: a7df755466704f339e5479aeeca3fe30
              expression: 'min(/AWS ECS Cluster by HTTP/aws.ecs.memory_utilization,15m)>{$AWS.ECS.CLUSTER.MEMORY.UTIL.WARN}'
              name: 'High memory utilization'
              event_name: 'High memory utilization (over {$AWS.ECS.CLUSTER.MEMORY.UTIL.WARN}% for 15m)'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The system is running out of free memory.'
              tags:
                - tag: scope
                  value: capacity
                - tag: scope
                  value: performance
        - uuid: a214cef0377b4901afc2cb90186e5e46
          name: 'Get metrics check'
          type: DEPENDENT
          key: aws.ecs.metrics.check
          value_type: CHAR
          description: 'Data collection check.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: b475c468dbe0477f92b40122321235b0
              expression: 'length(last(/AWS ECS Cluster by HTTP/aws.ecs.metrics.check))>0'
              name: 'Failed to get metrics data'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              tags:
                - tag: scope
                  value: availability
        - uuid: 4daa5e7b1bc64b3cbd54d9addea571cd
          name: 'Network rx bytes'
          type: DEPENDENT
          key: aws.ecs.network.rx
          value_type: FLOAT
          units: Bps
          description: |
            'The number of bytes received by the resource that is specified by the dimensions that you're using.
             This metric is only available for containers in tasks using the awsvpc or bridge network modes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.MetricData[?(@.Label == "NetworkRxBytes")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: network
        - uuid: 59882985019d42009a1993bf8bfd1a31
          name: 'Network tx bytes'
          type: DEPENDENT
          key: aws.ecs.network.tx
          value_type: FLOAT
          units: Bps
          description: |
            'The number of bytes transmitted by the resource that is specified by the dimensions that you're using.
             This metric is only available for containers in tasks using the awsvpc or bridge network modes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.MetricData[?(@.Label == "NetworkTxBytes")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: network
        - uuid: 26970ea823294cf2b87a158d8feee872
          name: 'Service Count'
          type: DEPENDENT
          key: aws.ecs.service_count
          value_type: FLOAT
          description: '''The number of services in the cluster.'''
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.MetricData[?(@.Label == "ServiceCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: system
        - uuid: 3cc6d826052c4da49bd8891a99ec2816
          name: 'Task Count'
          type: DEPENDENT
          key: aws.ecs.task_count
          value_type: FLOAT
          description: '''The number of tasks running in the cluster.'''
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.MetricData[?(@.Label == "TaskCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: system
      discovery_rules:
        - uuid: 5e1b53e77fd74b61864ed8437c635346
          name: 'Cluster Alarms discovery'
          type: DEPENDENT
          key: aws.ecs.alarms.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.ECS.LLD.FILTER.ALARM_NAME.MATCHES}'
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.ECS.LLD.FILTER.ALARM_NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#ALARM_SERVICE_NAMESPACE}'
                value: '{$AWS.ECS.LLD.FILTER.ALARM_SERVICE_NAMESPACE.MATCHES}'
              - macro: '{#ALARM_SERVICE_NAMESPACE}'
                value: '{$AWS.ECS.LLD.FILTER.ALARM_SERVICE_NAMESPACE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery instance alarms.'
          item_prototypes:
            - uuid: 98d3f64416f746639055abdda6dfc374
              name: '[{#ALARM_NAME}]: Get metrics'
              type: DEPENDENT
              key: 'aws.ecs.alarm.get_metrics["{#ALARM_NAME}"]'
              history: '0'
              value_type: TEXT
              description: 'Get alarm metrics about the state and its reason.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.AlarmName == "{#ALARM_NAME}")].first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.ecs.get_alarms
              tags:
                - tag: component
                  value: raw
            - uuid: 8a862dd5444f459b88f91a9fdb2ddc5e
              name: '[{#ALARM_NAME}]: State'
              type: DEPENDENT
              key: 'aws.ecs.alarm.state["{#ALARM_NAME}"]'
              description: |
                The state value for the alarm. Possible values: 0 (OK), 1 (INSUFFICIENT_DATA), 2 (ALARM).
                Alarm description:
                {#ALARM_DESCRIPTION}
              valuemap:
                name: 'Alarm state'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.StateValue
                  error_handler: CUSTOM_VALUE
                  error_handler_params: '3'
                - type: JAVASCRIPT
                  parameters:
                    - |
                      var state = ['OK', 'INSUFFICIENT_DATA', 'ALARM'];
                      
                      return state.indexOf(value.trim()) === -1 ? 255 : state.indexOf(value.trim());
              master_item:
                key: 'aws.ecs.alarm.get_metrics["{#ALARM_NAME}"]'
              tags:
                - tag: component
                  value: alarms
              trigger_prototypes:
                - uuid: 50061fea24e744298732167898c34e5f
                  expression: 'last(/AWS ECS Cluster by HTTP/aws.ecs.alarm.state["{#ALARM_NAME}"])=1'
                  name: '[{#ALARM_NAME}] has ''Insufficient data'' state'
                  priority: INFO
                  tags:
                    - tag: scope
                      value: notice
            - uuid: eacb27b638924fa289e7c119f97879d8
              name: '[{#ALARM_NAME}]: State reason'
              type: DEPENDENT
              key: 'aws.ecs.alarm.state_reason["{#ALARM_NAME}"]'
              value_type: TEXT
              description: |
                An explanation for the alarm state, in text format.
                Alarm description:
                {#ALARM_DESCRIPTION}
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.StateReason
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'aws.ecs.alarm.get_metrics["{#ALARM_NAME}"]'
              tags:
                - tag: component
                  value: alarms
          trigger_prototypes:
            - uuid: 25d14cc75ade4f7881825d5ab7864ca0
              expression: 'last(/AWS ECS Cluster by HTTP/aws.ecs.alarm.state["{#ALARM_NAME}"])=2 and length(last(/AWS ECS Cluster by HTTP/aws.ecs.alarm.state_reason["{#ALARM_NAME}"]))>0'
              name: '[{#ALARM_NAME}] has ''Alarm'' state'
              priority: AVERAGE
              description: |
                Alarm "{#ALARM_NAME}" has 'Alarm' state. 
                Reason: {ITEM.LASTVALUE2}
              tags:
                - tag: scope
                  value: availability
          master_item:
            key: aws.ecs.get_alarms
          preprocessing:
            - type: JAVASCRIPT
              parameters:
                - |
                  var result = [];
                  var alarms = JSON.parse(value);
                  
                  alarms.forEach(function(alarm) {
                  
                   result.push({
                  '{#ALARM_DESCRIPTION}': alarm.AlarmDescription !== null ? alarm.AlarmDescription : 'None' ,
                  '{#ALARM_NAME}': alarm.AlarmName,
                  '{#ALARM_PERIOD}': alarm.Period,
                  '{#METRIC_NAME}': alarm.MetricName,
                  '{#ALARM_SERVICE_NAMESPACE}': alarm.Namespace !== null ? alarm.Namespace : 'None'
                    });
                  });
                  
                  return JSON.stringify(result);
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
        - uuid: 7ab2cc38ab6f4400b42bee282a7e25e1
          name: 'Cluster Services discovery'
          type: DEPENDENT
          key: aws.ecs.services.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.ECS.SERVICE.NAME}'
                value: '{$AWS.ECS.LLD.FILTER.SERVICE.MATCHES}'
              - macro: '{#AWS.ECS.SERVICE.NAME}'
                value: '{$AWS.ECS.LLD.FILTER.SERVICE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery {$AWS.ECS.CLUSTER.NAME} services.'
          item_prototypes:
            - uuid: 51de81c8bdcb4359b347e9d9226fcb4b
              name: '[{#AWS.ECS.SERVICE.NAME}]: CPU Utilization'
              type: DEPENDENT
              key: 'aws.ecs.services.cpu.utilization["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: '%'
              description: |
                "A number of CPU units used by tasks in the resource that is specified by the dimension set that you're using.
                 This metric is only collected for tasks that have a defined CPU reservation in their task definition."
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "AWS/ECS CPUUtilization")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: cpu
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
              trigger_prototypes:
                - uuid: 3e8d8d35d5ad4f70ad792fe943a499d2
                  expression: 'min(/AWS ECS Cluster by HTTP/aws.ecs.services.cpu.utilization["{#AWS.ECS.SERVICE.NAME}"],15m)>{$AWS.ECS.CLUSTER.SERVICE.CPU.UTIL.WARN}'
                  name: '[{#AWS.ECS.SERVICE.NAME}]: High CPU utilization'
                  event_name: '[{#AWS.ECS.SERVICE.NAME}]: High CPU utilization (over {$AWS.ECS.CLUSTER.SERVICE.CPU.UTIL.WARN}% for 15m)'
                  opdata: 'Current utilization: {ITEM.LASTVALUE1}'
                  priority: WARNING
                  description: 'The CPU utilization is too high. The system might be slow to respond.'
                  tags:
                    - tag: scope
                      value: capacity
                    - tag: scope
                      value: performance
                    - tag: service
                      value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: ba01726f96354fe681fb4d916d461460
              name: '[{#AWS.ECS.SERVICE.NAME}]: CPU Reserved'
              type: DEPENDENT
              key: 'aws.ecs.services.cpu_reserved["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              description: |
                "A number of CPU units reserved by tasks in the resource that is specified by the dimension set that you're using.
                 This metric is only collected for tasks that have a defined CPU reservation in their task definition."
              valuemap:
                name: 'CPU Reserved'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights CpuReserved")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: cpu
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 785fd19ab3344e749ce486e4601f4d8e
              name: '[{#AWS.ECS.SERVICE.NAME}]: Desired Task'
              type: DEPENDENT
              key: 'aws.ecs.services.desired.task["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              description: 'The desired number of tasks for an {#AWS.ECS.SERVICE.NAME} service.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights DesiredTaskCount")].Values.first().first()'
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: d12aae43f0f3446d96e2141a0bf303b8
              name: '[{#AWS.ECS.SERVICE.NAME}]: Get metrics'
              type: SCRIPT
              key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              delay: 0s;m/5
              history: '0'
              value_type: TEXT
              params: |
                var AWS = {
                	params: {},
                	request_period: 600,
                	metadata: 'http://169.254.169.254/latest/meta-data/iam/security-credentials',
                
                	setParams: function (params) {
                		AWS.params['proxy'] = params.proxy;
                		switch (AWS.getField(params, 'auth_type')) {
                			case 'role_base':
                				AWS.params['auth_type'] = 'role_base';
                				var request = new HttpRequest();
                				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
                					request.setProxy(AWS.params.proxy);
                				}
                				var IamRoleName = request.get(AWS.metadata);
                
                				if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
                					throw 'Error getting security credentials from instance metadata. Role not found.';
                				}
                
                				credentials = request.get(AWS.metadata + '/' + encodeURI(IamRoleName));
                
                				if (request.getStatus() !== 200 || credentials === null || credentials === '') {
                					throw 'Error getting security credentials from instance metadata.';
                				}
                
                				try {
                					credentials = JSON.parse(credentials);
                				}
                				catch (error) {
                					throw 'Failed to parse response received from instance metadata. Check debug log for more information.';
                				}
                
                				['AccessKeyId', 'SecretAccessKey', 'Token'].forEach(function (field) {
                					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
                						throw 'Required credentials is not set: "' + field + '".';
                					};
                					AWS.params[field] = credentials[field];
                				});
                				break;
                			case 'access_key':
                			default:
                				AWS.params['auth_type'] = 'access_key';
                				['AccessKeyId', 'SecretAccessKey'].forEach(function (field) {
                					if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
                						throw 'Required param is not set: "' + field + '".';
                					}
                					AWS.params[field] = params[field];
                				});
                		}
                		['region', 'cluster_name', 'service_name'].forEach(function (field) {
                			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
                				throw 'Required param is not set: "' + field + '".';
                			}
                			AWS.params[field] = params[field];
                		});
                	},
                
                	getField: function (data, path) {
                		var steps = path.split('.');
                		for (var i = 0; i < steps.length; i++) {
                			var step = steps[i];
                			if (typeof data !== 'object' || typeof data[step] === 'undefined') {
                				throw 'Required field was not found: ' + path;
                			}
                
                			data = data[step];
                		}
                
                		return data;
                	},
                
                	sign: function (key, message) {
                		var hex = hmac('sha256', key, message);
                
                		if ((hex.length % 2) === 1) {
                			throw 'Invalid length of a hex string!';
                		}
                
                		var result = new Int8Array(hex.length / 2);
                		for (var i = 0, b = 0; i < hex.length; i += 2, b++) {
                			result[b] = parseInt(hex.substring(i, i + 2), 16);
                		}
                
                		return result;
                	},
                
                	prepareRecursive: function (prefix, param) {
                		var result = {};
                
                		if (typeof param === 'object') {
                			if (Array.isArray(param)) {
                				param.forEach(function (value, index) {
                					var nested = AWS.prepareRecursive(prefix + '.member.' + (index + 1), value);
                					Object.keys(nested).forEach(function (key) {
                						result[key] = nested[key];
                					});
                				});
                			}
                			else {
                				Object.keys(param).forEach(function (k) {
                					var nested = AWS.prepareRecursive(prefix + '.' + k, param[k]);
                					Object.keys(nested).forEach(function (key) {
                						result[key] = nested[key];
                					});
                				});
                			}
                		}
                		else {
                			result[prefix] = param;
                		}
                
                		return result;
                	},
                
                	renderPayload: function (period, cluster_name, service_name) {
                		var metrics_list = [
                			'CpuReserved:None:ECS/ContainerInsights',
                			'CpuUtilized:None:ECS/ContainerInsights',
                			'CPUUtilization:Percent:AWS/ECS',
                			'MemoryUtilization:Percent:AWS/ECS',
                			'MemoryReserved:Megabytes:ECS/ContainerInsights',
                			'MemoryUtilized:Megabytes:ECS/ContainerInsights',
                			'NetworkRxBytes:Bytes/Second:ECS/ContainerInsights',
                			'NetworkTxBytes:Bytes/Second:ECS/ContainerInsights',
                			'StorageReadBytes:Bytes:ECS/ContainerInsights',
                			'StorageWriteBytes:Bytes:ECS/ContainerInsights',
                			'DeploymentCount:Count:ECS/ContainerInsights',
                			'TaskSetCount:Count:ECS/ContainerInsights',
                			'DesiredTaskCount:Count:ECS/ContainerInsights',
                			'PendingTaskCount:Count:ECS/ContainerInsights',
                			'RunningTaskCount:Count:ECS/ContainerInsights',
                			'EphemeralStorageReserved:Gigabytes:ECS/ContainerInsights',
                			'EphemeralStorageUtilized:Gigabytes:ECS/ContainerInsights'
                		];
                
                		var metric_payload = [];
                		metrics_list.forEach(function (metric) {
                			var parts = metric.split(':', 3);
                			var name = parts[0].replace(/[^a-zA-Z0-9]/g, '');
                			metric_payload.push({
                				'Id': name.charAt(0).toLowerCase() + name.slice(1),
                				'MetricStat': {
                					'Metric': {
                						'MetricName': parts[0],
                						'Namespace': parts[2],
                						'Dimensions': [
                							{
                								'Name': 'ClusterName',
                								'Value': cluster_name
                							}
                							,
                							{
                								'Name': 'ServiceName',
                								'Value': service_name
                							}
                						]
                					},
                					'Period': period,
                					'Stat': 'Average',
                					'Unit': parts[1]
                				}
                			});
                		});
                
                		return metric_payload;
                	},
                
                	prepareParams: function (params) {
                		var result = [];
                
                		Object.keys(params).sort().forEach(function (key) {
                			if (typeof params[key] !== 'object') {
                				result.push(key + '=' + encodeURIComponent(params[key]));
                			}
                			else {
                				result.push(prepareObject(key, params[key]));
                			}
                		});
                
                		return result.join('&');
                	},
                
                	request: function (method, region, service, params, data) {
                		if (typeof data === 'undefined' || data === null) {
                			data = '';
                		}
                
                		var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''),
                			date = amzdate.replace(/T\d+Z/, ''),
                			host = service + '.' + region + '.amazonaws.com',
                			canonical_uri = '/',
                			canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n',
                			signed_headers = 'content-encoding;host;x-amz-date',
                			canonical_request = method + '\n' + canonical_uri + '\n' + params + '\n' + canonical_headers + '\n' + signed_headers + '\n' + sha256(data),
                			credential_scope = date + '/' + region + '/' + service + '/' + 'aws4_request',
                			request_string = 'AWS4-HMAC-SHA256' + '\n' + amzdate + '\n' + credential_scope + '\n' + sha256(canonical_request),
                			key = AWS.sign('AWS4' + AWS.params.SecretAccessKey, date);
                
                		key = AWS.sign(key, region);
                		key = AWS.sign(key, service);
                		key = AWS.sign(key, 'aws4_request');
                
                		var request = new HttpRequest(),
                			url = 'https://' + host + canonical_uri + '?' + params;
                
                		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
                			request.setProxy(AWS.params.proxy);
                		}
                		request.addHeader('x-amz-date: ' + amzdate);
                		request.addHeader('Accept: application/json');
                		request.addHeader('Content-Type: application/json');
                		request.addHeader('Content-Encoding: amz-1.0');
                		request.addHeader('Authorization: ' + 'AWS4-HMAC-SHA256 Credential=' + AWS.params.AccessKeyId + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + hmac('sha256', key, request_string));
                		if (AWS.params.auth_type === 'role_base')
                			request.addHeader('X-Amz-Security-Token: ' + AWS.params.Token);
                
                		Zabbix.log(4, '[ AWS ECS  ] Sending request: ' + url);
                
                		response = request.get(url);
                
                		Zabbix.log(4, '[ AWS ECS ] Received response with status code ' + request.getStatus() + ': ' + response);
                
                		if (request.getStatus() !== 200) {
                			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
                		}
                
                		if (response !== null) {
                			try {
                				response = JSON.parse(response);
                			}
                			catch (error) {
                				throw 'Failed to parse response received from AWS CloudWatch API. Check debug log for more information.';
                			}
                		}
                
                		return response;
                	},
                
                	getMetricsData: function () {
                		var timestamp = new Date().getTime(),
                			end_time = new Date(timestamp).toISOString().replace(/\.\d+Z/, 'Z'),
                			start_time = new Date(timestamp - AWS.request_period * 1000).toISOString().replace(/\.\d+Z/, 'Z'),
                			payload = AWS.prepareRecursive('MetricDataQueries', AWS.renderPayload(AWS.request_period, AWS.params.cluster_name, AWS.params.service_name));
                
                		payload['Action'] = 'GetMetricData';
                		payload['Version'] = '2010-08-01';
                		payload['StartTime'] = start_time;
                		payload['EndTime'] = end_time;
                		payload['ScanBy'] = 'TimestampDescending';
                
                		result = AWS.request('GET', AWS.params.region, 'monitoring', AWS.prepareParams(payload));
                		MetricData = AWS.getField(result, 'GetMetricDataResponse.GetMetricDataResult.MetricDataResults')
                
                		return MetricData;
                	}
                };
                
                try {
                	AWS.setParams(JSON.parse(value));
                
                	return JSON.stringify(AWS.getMetricsData());
                }
                catch (error) {
                	error += (String(error).endsWith('.')) ? '' : '.';
                	Zabbix.log(3, '[ AWS ECS ] ERROR: ' + error);
                
                	return JSON.stringify({ 'error': error });
                }
              description: |
                Get metrics of ESC services.
                Full metrics list related to ECS : https://docs.aws.amazon.com/ecs/index.html
              preprocessing:
                - type: CHECK_NOT_SUPPORTED
                  parameters:
                    - '-1'
              timeout: 15s
              parameters:
                - name: AccessKeyId
                  value: '{$AWS.ACCESS.KEY.ID}'
                - name: auth_type
                  value: '{$AWS.AUTH_TYPE}'
                - name: cluster_name
                  value: '{$AWS.ECS.CLUSTER.NAME}'
                - name: proxy
                  value: '{$AWS.PROXY}'
                - name: region
                  value: '{$AWS.REGION}'
                - name: SecretAccessKey
                  value: '{$AWS.SECRET.ACCESS.KEY}'
                - name: service_name
                  value: '{#AWS.ECS.SERVICE.NAME}'
              tags:
                - tag: component
                  value: raw
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 685671b8a8c34f35ada959c2c6aca1e3
              name: '[{#AWS.ECS.SERVICE.NAME}]: Memory utilization'
              type: DEPENDENT
              key: 'aws.ecs.services.memory.utilization["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: '%'
              description: |
                'The memory being used by tasks in the resource that is specified by the dimension set that you're using.
                This metric is only collected for tasks that have a defined memory reservation in their task definition.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "AWS/ECS MemoryUtilization")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: memory
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
              trigger_prototypes:
                - uuid: a1116a5e75f24b50864a0fb5ea7ad99d
                  expression: 'min(/AWS ECS Cluster by HTTP/aws.ecs.services.memory.utilization["{#AWS.ECS.SERVICE.NAME}"],15m)>{$AWS.ECS.CLUSTER.SERVICE.MEMORY.UTIL.WARN}'
                  name: '[{#AWS.ECS.SERVICE.NAME}]: High memory utilization'
                  event_name: '[{#AWS.ECS.SERVICE.NAME}]: High memory utilization (over {$AWS.ECS.CLUSTER.SERVICE.MEMORY.UTIL.WARN}% for 15m)'
                  opdata: 'Current utilization: {ITEM.LASTVALUE1}'
                  priority: WARNING
                  description: 'The system is running out of free memory.'
                  tags:
                    - tag: scope
                      value: capacity
                    - tag: scope
                      value: performance
                    - tag: service
                      value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 538e0157704e40ffa124d6b74208f71b
              name: '[{#AWS.ECS.SERVICE.NAME}]: Memory reserved'
              type: DEPENDENT
              key: 'aws.ecs.services.memory_reserved["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: B
              description: |
                'The memory that is reserved by tasks in the resource that is specified by the dimension set that you're using.
                This metric is only collected for tasks that have a defined memory reservation in their task definition.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights MemoryReserved")].Values.first().first()'
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '1048576'
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: memory
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 80471d41639f4e7a87174cad13f7f3a4
              name: '[{#AWS.ECS.SERVICE.NAME}]: Memory utilized'
              type: DEPENDENT
              key: 'aws.ecs.services.memory_utilized["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: B
              description: |
                'The memory being used by tasks in the resource that is specified by the dimension set that you're using.
                This metric is only collected for tasks that have a defined memory reservation in their task definition.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights MemoryUtilized")].Values.first().first()'
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '1048576'
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: memory
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 52c14dd824174368acc0918d1c4670e4
              name: '[{#AWS.ECS.SERVICE.NAME}]: Network rx bytes'
              type: DEPENDENT
              key: 'aws.ecs.services.network.rx["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: Bps
              description: |
                'The number of bytes received by the resource that is specified by the dimensions that you're using.
                This metric is only available for containers in tasks using the awsvpc or bridge network modes.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights NetworkRxBytes")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: network
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 598337e977b2460ca3ce0844061a619c
              name: '[{#AWS.ECS.SERVICE.NAME}]: Network tx bytes'
              type: DEPENDENT
              key: 'aws.ecs.services.network.tx["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: Bps
              description: |
                'The number of bytes transmitted by the resource that is specified by the dimensions that you're using.
                This metric is only available for containers in tasks using the awsvpc or bridge network modes.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights NetworkTxBytes")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: network
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 38d4200dad444b42b77e3fd1fe355007
              name: '[{#AWS.ECS.SERVICE.NAME}]: Pending Task'
              type: DEPENDENT
              key: 'aws.ecs.services.pending.task["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              description: 'The number of tasks currently in the `pending` state.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights PendingTaskCount")].Values.first().first()'
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 3e1538ea18d7417889536bfce39bc22c
              name: '[{#AWS.ECS.SERVICE.NAME}]: Running Task'
              type: DEPENDENT
              key: 'aws.ecs.services.running.task["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              description: 'The number of tasks currently in the `running` state.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights RunningTaskCount")].Values.first().first()'
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 46b30a391af44cc5b9a70832189ffb2b
              name: '[{#AWS.ECS.SERVICE.NAME}]: Task Set'
              type: DEPENDENT
              key: 'aws.ecs.services.task.set["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              description: 'The number of task sets in the {#AWS.ECS.SERVICE.NAME} service.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights TaskSetCount")].Values.first().first()'
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
          graph_prototypes:
            - uuid: e4034a72c2834434b5b15f96469e97ff
              name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: CPU Utilization'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2196F3
                  item:
                    host: 'AWS ECS Cluster by HTTP'
                    key: 'aws.ecs.services.cpu.utilization["{#AWS.ECS.SERVICE.NAME}"]'
            - uuid: 5c5da1e0886740ed80d43597c2b6ee96
              name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: Memory Utilization'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2196F3
                  item:
                    host: 'AWS ECS Cluster by HTTP'
                    key: 'aws.ecs.services.memory.utilization["{#AWS.ECS.SERVICE.NAME}"]'
            - uuid: 2057845fb9b641299c7406f1c1127710
              name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: Network'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'AWS ECS Cluster by HTTP'
                    key: 'aws.ecs.services.network.rx["{#AWS.ECS.SERVICE.NAME}"]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'AWS ECS Cluster by HTTP'
                    key: 'aws.ecs.services.network.tx["{#AWS.ECS.SERVICE.NAME}"]'
          master_item:
            key: aws.ecs.get_cluster_services
          lld_macro_paths:
            - lld_macro: '{#AWS.ECS.SERVICE.NAME}'
              path: $.service_name
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.services
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
      tags:
        - tag: class
          value: software
        - tag: target
          value: aws
        - tag: target
          value: ecs
      macros:
        - macro: '{$AWS.ACCESS.KEY.ID}'
          description: 'Access key ID.'
        - macro: '{$AWS.AUTH_TYPE}'
          value: access_key
          description: 'Authorization method. Possible values: role_base, access_key.'
        - macro: '{$AWS.ECS.CLUSTER.CPU.UTIL.WARN}'
          value: '70'
          description: 'The warning threshold of the cluster CPU utilization expressed in %.'
        - macro: '{$AWS.ECS.CLUSTER.MEMORY.UTIL.WARN}'
          value: '70'
          description: 'The warning threshold of the cluster memory utilization expressed in %.'
        - macro: '{$AWS.ECS.CLUSTER.NAME}'
          description: 'ECS cluster name.'
        - macro: '{$AWS.ECS.CLUSTER.SERVICE.CPU.UTIL.WARN}'
          value: '80'
          description: 'The warning threshold of the cluster service CPU utilization expressed in %.'
        - macro: '{$AWS.ECS.CLUSTER.SERVICE.MEMORY.UTIL.WARN}'
          value: '80'
          description: 'The warning threshold of the cluster service memory utilization expressed in %.'
        - macro: '{$AWS.ECS.LLD.FILTER.ALARM_NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable alarms by name.'
        - macro: '{$AWS.ECS.LLD.FILTER.ALARM_NAME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered alarms by name.'
        - macro: '{$AWS.ECS.LLD.FILTER.ALARM_SERVICE_NAMESPACE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable alarms by namespace.'
        - macro: '{$AWS.ECS.LLD.FILTER.ALARM_SERVICE_NAMESPACE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered alarms by namespace.'
        - macro: '{$AWS.ECS.LLD.FILTER.SERVICE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable services by name.'
        - macro: '{$AWS.ECS.LLD.FILTER.SERVICE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered services by name.'
        - macro: '{$AWS.PROXY}'
          description: 'Sets HTTP proxy value. If this macro is empty then no proxy is used.'
        - macro: '{$AWS.REGION}'
          value: us-west-1
          description: 'Amazon ECS Region code.'
        - macro: '{$AWS.SECRET.ACCESS.KEY}'
          type: SECRET_TEXT
          description: 'Secret access key.'
      dashboards:
        - uuid: d06afc9b9488445d887659b67d955384
          name: 'Overview AWS ECS Cluster'
          pages:
            - name: Cluster
              widgets:
                - type: item
                  name: 'Service count'
                  width: '24'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        key: aws.ecs.service_count
                    - type: INTEGER
                      name: show.0
                      value: '2'
                - type: graph
                  'y': '5'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        name: 'AWS ECS Cluster: CPU Utilization'
                    - type: STRING
                      name: reference
                      value: AAAAC
                - type: graph
                  'y': '10'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        name: 'AWS ECS Cluster: Memory Utilization'
                    - type: STRING
                      name: reference
                      value: AAAAB
                - type: graph
                  'y': '15'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        name: 'AWS ECS Cluster: Network'
                    - type: STRING
                      name: reference
                      value: AAAAA
                - type: item
                  name: 'Task count'
                  x: '24'
                  width: '24'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        key: aws.ecs.task_count
                    - type: INTEGER
                      name: show.0
                      value: '2'
                - type: item
                  name: 'Container instance count'
                  x: '48'
                  width: '24'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        key: aws.ecs.container_instance_count
                    - type: INTEGER
                      name: show.0
                      value: '2'
            - name: Services
              widgets:
                - type: graphprototype
                  width: '72'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: columns
                      value: '1'
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: CPU Utilization'
                    - type: STRING
                      name: reference
                      value: AAAAD
                - type: graphprototype
                  'y': '5'
                  width: '72'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: columns
                      value: '1'
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: Memory Utilization'
                    - type: STRING
                      name: reference
                      value: AAAAE
                - type: graphprototype
                  'y': '10'
                  width: '72'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: columns
                      value: '1'
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: Network'
                    - type: STRING
                      name: reference
                      value: AAAAF
      valuemaps:
        - uuid: 6b0f40b56f1c49f0beb66ffb85009c15
          name: 'Alarm state'
          mappings:
            - value: '0'
              newvalue: OK
            - value: '1'
              newvalue: 'Insufficient data'
            - value: '2'
              newvalue: Alarm
            - value: '255'
              newvalue: Unknown
        - uuid: bb1024c6e5a14c05a8a91ea36aff6d99
          name: 'CPU Reserved'
          mappings:
            - value: '256'
              newvalue: '.25 vCPU'
            - value: '512'
              newvalue: '.5 vCPU'
            - value: '1024'
              newvalue: '1 vCPU'
            - value: '2048'
              newvalue: '2 vCPU'
            - value: '4096'
              newvalue: '4 vCPU'
            - value: '8192'
              newvalue: '8 vCPU'
            - value: '16384'
              newvalue: '16 vCPU'
            - value: '32768'
              newvalue: '32 vCPU'
  graphs:
    - uuid: e962b86d53c749b6914c3d50fb8757ff
      name: 'AWS ECS Cluster: CPU Utilization'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 2196F3
          item:
            host: 'AWS ECS Cluster by HTTP'
            key: aws.ecs.cpu_utilization
    - uuid: 5f9d5878b5954d59bee0ca5d977f3dc7
      name: 'AWS ECS Cluster: Memory Utilization'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 2196F3
          item:
            host: 'AWS ECS Cluster by HTTP'
            key: aws.ecs.memory_utilization
    - uuid: 503c0a606b1440f4bc02f115196ef9ad
      name: 'AWS ECS Cluster: Network'
      graph_items:
        - color: 199C0D
          item:
            host: 'AWS ECS Cluster by HTTP'
            key: aws.ecs.network.rx
        - sortorder: '1'
          color: F63100
          item:
            host: 'AWS ECS Cluster by HTTP'
            key: aws.ecs.network.tx
