zabbix_export:
  version: '7.0'
  template_groups:
    - uuid: c2c162144c2d4c5491c8801193af4945
      name: Templates/Cloud
  templates:
    - uuid: dce23cdaef364e139efa580d8a304ffe
      template: 'AWS Cost Explorer by HTTP'
      name: 'AWS Cost Explorer by HTTP'
      description: |
        The template gets AWS Cost Explorer metrics and uses the script item to make HTTP requests to the Cost Explorer API.
        The Cost Explorer API can access the historical data over up to 12 months and the data for current month.
        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: 5bfda2617dfc43edbe524a5c44b39f18
          name: 'Get daily costs'
          type: SCRIPT
          key: aws.get.daily.costs
          delay: 0s;h/6
          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'].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];
            		});
            
            		today = new Date();
            		AWS.params.end_date = today.toDateString();
            		today.setDate(today.getDate() - 1);
            		AWS.params.start_time = today.toDateString();
            	},
            
            	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;
            	},
            
            	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;
            
            	},
            
            	request: function (method, region, service, host, data, uri, target) {
            		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' + '' + '\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;
            
            		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-amz-json-1.1');
            		request.addHeader('Content-Encoding: amz-1.0');
            		request.addHeader('X-Amz-Target: ' + target);
            		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 Billing ] Sending request: ' + url);
            
            		response = request.post(url, data);
            
            		Zabbix.log(4, '[ AWS Billing ] Received response with the status code ' + request.getStatus() + ': ' + response);
            
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with the status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse the response received from AWS API. Check debug log for more information.';
            		}
            
            		return response;
            	},
            
            	getDimensionValues: function () {
            		var body_raw_dimension = {
            			'TimePeriod': {
            				'Start': AWS.params.start_time,
            				'End': AWS.params.end_date
            			},
            			'Dimension': 'SERVICE'
            		};
            		return AWS.getField(AWS.request('POST', AWS.params.region, 'ce', 'ce.' + AWS.params.region + '.amazonaws.com', JSON.stringify(body_raw_dimension), '', 'AWSInsightsIndexService.GetDimensionValues'), 'DimensionValues');
            
            	},
            
            	getCostAndUsage: function () {
            		var body_raw_cost = {
            
            			'TimePeriod': {
            				'Start': AWS.params.start_time,
            				'End': AWS.params.end_date
            			},
            			'Granularity': 'DAILY',
            			'DimensionValues': AWS.getDimensionValues(),
            			'GroupBy': [
            				{
            					'Type': 'DIMENSION',
            					'Key': 'SERVICE'
            				}
            			],
            			'Metrics': ['BlendedCost']
            		};
            
            		return AWS.getField(AWS.request('POST', AWS.params.region, 'ce', 'ce.' + AWS.params.region + '.amazonaws.com', JSON.stringify(body_raw_cost), '', 'AWSInsightsIndexService.GetCostAndUsage'), 'ResultsByTime');
            
            	}
            
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	return JSON.stringify(AWS.getCostAndUsage());
            
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS Billing ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: 'Get raw data on the daily costs by service'
          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: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.BILLING.REGION}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
          tags:
            - tag: component
              value: raw
        - uuid: 7139ce562d3c439e9686ad5b17ed0f1c
          name: 'Get monthly costs'
          type: SCRIPT
          key: aws.get.monthly.costs
          delay: 0s;h9
          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', 'month'].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];
            		});
            
            		today = new Date();
            		AWS.params.end_date = today.toDateString();
            		month = today.getMonth();
            		today.setMonth(month - params.month);
            		AWS.params.start_time = new Date(today.getFullYear(), today.getMonth()).toDateString();
            	},
            
            	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;
            	},
            
            	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;
            
            	},
            
            	request: function (method, region, service, host, data, uri, target) {
            		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' + '' + '\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;
            
            		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-amz-json-1.1');
            		request.addHeader('Content-Encoding: amz-1.0');
            		request.addHeader('X-Amz-Target: ' + target);
            		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 Billing ] Sending request: ' + url);
            
            		response = request.post(url, data);
            
            		Zabbix.log(4, '[ AWS Billing ] Received response with the status code ' + request.getStatus() + ': ' + response);
            
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with the status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse the response received from AWS API. Check debug log for more information.';
            		}
            
            		return response;
            	},
            
            	getDimensionValues: function () {
            		var body_raw_dimension = {
            			'TimePeriod': {
            				'Start': AWS.params.start_time,
            				'End': AWS.params.end_date
            			},
            			'Dimension': 'SERVICE'
            		};
            		return AWS.getField(AWS.request('POST', AWS.params.region, 'ce', 'ce.' + AWS.params.region + '.amazonaws.com', JSON.stringify(body_raw_dimension), '', 'AWSInsightsIndexService.GetDimensionValues'), 'DimensionValues');
            
            	},
            
            	getCostMonth: function () {
            		var body_raw_cost = {
            			'TimePeriod': {
            				'Start': AWS.params.start_time,
            				'End': AWS.params.end_date
            			},
            			'Granularity': 'MONTHLY',
            			'Metrics': ['BlendedCost']
            		};
            		result = AWS.getField(AWS.request('POST', AWS.params.region, 'ce', 'ce.' + AWS.params.region + '.amazonaws.com', JSON.stringify(body_raw_cost), '', 'AWSInsightsIndexService.GetCostAndUsage'), 'ResultsByTime');
            
            		return result.map(function (data) {
            			return {
            				'amount': AWS.getField(data, 'Total.BlendedCost.Amount'),
            				'unit': AWS.getField(data, 'Total.BlendedCost.Unit'),
            				'month': AWS.getField(data, 'TimePeriod.Start').slice(0, 7)
            			};
            		});
            	},
            
            	getCostMonthService: function () {
            		var body_raw_cost = {
            			'TimePeriod': {
            				'Start': AWS.params.start_time,
            				'End': AWS.params.end_date
            			},
            			'DimensionValues': AWS.getDimensionValues(),
            			'GroupBy': [
            				{
            					'Type': 'DIMENSION',
            					'Key': 'SERVICE'
            				}
            			],
            			'Granularity': 'MONTHLY',
            			'Metrics': ['BlendedCost']
            		};
            		MetricData = AWS.getField(AWS.request('POST', AWS.params.region, 'ce', 'ce.' + AWS.params.region + '.amazonaws.com', JSON.stringify(body_raw_cost), '', 'AWSInsightsIndexService.GetCostAndUsage'), 'ResultsByTime');
            		var services = [];
            		MetricData.forEach(function (data) {
            			month = AWS.getField(data, 'TimePeriod.Start').slice(0, 7);
            			groups = AWS.getField(data, 'Groups');
            			groups.forEach(function (group) {
            				group.month = month;
            				services.push(group);
            			})
            		});
            
            		return services;
            
            	}
            
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	monthly_costs = AWS.getCostMonth();
            	monthly_service_costs = AWS.getCostMonthService();
            
            	return JSON.stringify({ monthly_costs, monthly_service_costs });
            
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS Billing ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          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: month
              value: '{$AWS.BILLING.MONTH}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.BILLING.REGION}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
          tags:
            - tag: component
              value: raw
      discovery_rules:
        - uuid: 5773c41da90d4a38aff02fccec733741
          name: 'AWS monthly costs by services discovery'
          type: DEPENDENT
          key: aws.cost.service.monthly.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.BILLING.SERVICE.NAME}'
                value: '{$AWS.BILLING.LLD.FILTER.SERVICE.MATCHES}'
              - macro: '{#AWS.BILLING.SERVICE.NAME}'
                value: '{$AWS.BILLING.LLD.FILTER.SERVICE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery of monthly costs by services.'
          item_prototypes:
            - uuid: d01ee8df0e204f1a857b8188df47402a
              name: '[{#AWS.BILLING.SERVICE.NAME}]: Month [{#AWS.BILLING.MONTH}] Blended cost'
              type: DEPENDENT
              key: 'aws.monthly.service.cost["{#AWS.BILLING.SERVICE.NAME}", "{#AWS.BILLING.MONTH}"]'
              value_type: FLOAT
              units: '{#AWS.BILLING.UNIT}'
              description: 'The monthly cost by service {#AWS.BILLING.SERVICE.NAME}.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.monthly_service_costs.[?(@.month == "{#AWS.BILLING.MONTH}")]'
                  error_handler: DISCARD_VALUE
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Keys =~ "{#AWS.BILLING.SERVICE.NAME}")]..Metrics.BlendedCost.Amount.first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.get.monthly.costs
              tags:
                - tag: component
                  value: billing
                - tag: month
                  value: '{#AWS.BILLING.MONTH}'
                - tag: service
                  value: '{#AWS.BILLING.SERVICE.NAME}'
          graph_prototypes:
            - uuid: b267e0ae08d34a7dae730848577aea68
              name: 'AWS Cost: [{#AWS.BILLING.SERVICE.NAME}]: Month [{#AWS.BILLING.MONTH}] Blended cost'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2E7D32
                  item:
                    host: 'AWS Cost Explorer by HTTP'
                    key: 'aws.monthly.service.cost["{#AWS.BILLING.SERVICE.NAME}", "{#AWS.BILLING.MONTH}"]'
          master_item:
            key: aws.get.monthly.costs
          lld_macro_paths:
            - lld_macro: '{#AWS.BILLING.MONTH}'
              path: $..month.first()
            - lld_macro: '{#AWS.BILLING.SERVICE.NAME}'
              path: $..Keys.first().first()
            - lld_macro: '{#AWS.BILLING.UNIT}'
              path: $..Metrics.BlendedCost.Unit.first()
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.monthly_service_costs
        - uuid: 6e65d15251ea4355ac41ed7956f9e5b0
          name: 'AWS daily costs by services discovery'
          type: DEPENDENT
          key: aws.daily.services.costs.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.BILLING.SERVICE.NAME}'
                value: '{$AWS.BILLING.LLD.FILTER.SERVICE.MATCHES}'
              - macro: '{#AWS.BILLING.SERVICE.NAME}'
                value: '{$AWS.BILLING.LLD.FILTER.SERVICE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery of daily blended costs by services.'
          item_prototypes:
            - uuid: b6e121c3a1eb49858e942beab12660e2
              name: 'Service [{#AWS.BILLING.SERVICE.NAME}]: Blended daily cost'
              type: DEPENDENT
              key: 'aws.daily.service.cost["{#AWS.BILLING.SERVICE.NAME}"]'
              value_type: FLOAT
              units: '{#AWS.BILLING.UNIT}'
              description: 'The daily blended cost of the {#AWS.BILLING.SERVICE.NAME} service for the previous day.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$..Groups..[?(@.Keys =~ "{#AWS.BILLING.SERVICE.NAME}")]..Metrics.BlendedCost.Amount.first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.get.daily.costs
              tags:
                - tag: component
                  value: billing
                - tag: service
                  value: '{#AWS.BILLING.SERVICE.NAME}'
          graph_prototypes:
            - uuid: 71646982ab55405dbc10f200e8050c93
              name: 'AWS Cost: Service [{#AWS.BILLING.SERVICE.NAME}]: Blended daily cost'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2E7D32
                  item:
                    host: 'AWS Cost Explorer by HTTP'
                    key: 'aws.daily.service.cost["{#AWS.BILLING.SERVICE.NAME}"]'
          master_item:
            key: aws.get.daily.costs
          lld_macro_paths:
            - lld_macro: '{#AWS.BILLING.SERVICE.NAME}'
              path: $..Keys.first().first()
            - lld_macro: '{#AWS.BILLING.UNIT}'
              path: $..Metrics.BlendedCost.Unit.first()
          preprocessing:
            - type: JSONPATH
              parameters:
                - $..Groups.first()
        - uuid: b554f00ba68e4ea391f7c7d029efde4f
          name: 'AWS monthly costs discovery'
          type: DEPENDENT
          key: aws.monthly.cost.discovery
          description: 'Discovery of monthly costs.'
          item_prototypes:
            - uuid: aaf85a53d1804c858fc20189f0483bad
              name: '[{#AWS.BILLING.MONTH}]: Blended cost per month'
              type: DEPENDENT
              key: 'aws.monthly.cost["{#AWS.BILLING.MONTH}"]'
              value_type: FLOAT
              units: '{#AWS.BILLING.UNIT}'
              description: 'The blended cost by month {#AWS.BILLING.MONTH}.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.monthly_costs.[?(@.month == "{#AWS.BILLING.MONTH}")].amount.first()'
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: aws.get.monthly.costs
              tags:
                - tag: component
                  value: billing
                - tag: month
                  value: '{#AWS.BILLING.MONTH}'
          graph_prototypes:
            - uuid: 3e01a98ed70149e3a6a083bb103aa496
              name: 'AWS Cost: [{#AWS.BILLING.MONTH}]: Monthly blended cost'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2E7D32
                  item:
                    host: 'AWS Cost Explorer by HTTP'
                    key: 'aws.monthly.cost["{#AWS.BILLING.MONTH}"]'
          master_item:
            key: aws.get.monthly.costs
          lld_macro_paths:
            - lld_macro: '{#AWS.BILLING.MONTH}'
              path: $..month.first()
            - lld_macro: '{#AWS.BILLING.UNIT}'
              path: $..unit.first()
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.monthly_costs
      tags:
        - tag: class
          value: software
        - tag: target
          value: aws
        - tag: target
          value: cost
      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.BILLING.LLD.FILTER.SERVICE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable discovered billing service by name.'
        - macro: '{$AWS.BILLING.LLD.FILTER.SERVICE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered billing service by name.'
        - macro: '{$AWS.BILLING.MONTH}'
          value: '11'
          description: 'Months to get historical data from AWS Cost Explore API, no more than 12 months.'
        - macro: '{$AWS.BILLING.REGION}'
          value: us-east-1
          description: 'Amazon Billing region code.'
        - macro: '{$AWS.PROXY}'
          description: 'Sets HTTP proxy value. If this macro is empty, then no proxy is used.'
        - macro: '{$AWS.SECRET.ACCESS.KEY}'
          type: SECRET_TEXT
          description: 'Secret access key.'
      dashboards:
        - uuid: e1e4edbf129142b4b27a9471db1ed8e2
          name: 'Overview AWS Costs'
          pages:
            - name: 'Monthly costs'
              widgets:
                - type: graphprototype
                  width: '72'
                  height: '25'
                  fields:
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'AWS Cost Explorer by HTTP'
                        name: 'AWS Cost: [{#AWS.BILLING.MONTH}]: Monthly blended cost'
                    - type: STRING
                      name: reference
                      value: AAAAA
                    - type: INTEGER
                      name: rows
                      value: '6'
            - name: 'Monthly costs by service'
              widgets:
                - type: graphprototype
                  width: '72'
                  height: '25'
                  fields:
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'AWS Cost Explorer by HTTP'
                        name: 'AWS Cost: [{#AWS.BILLING.SERVICE.NAME}]: Month [{#AWS.BILLING.MONTH}] Blended cost'
                    - type: STRING
                      name: reference
                      value: AAAAB
                    - type: INTEGER
                      name: rows
                      value: '6'
            - name: 'Daily costs by service'
              widgets:
                - type: graphprototype
                  width: '72'
                  height: '20'
                  fields:
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'AWS Cost Explorer by HTTP'
                        name: 'AWS Cost: Service [{#AWS.BILLING.SERVICE.NAME}]: Blended daily cost'
                    - type: STRING
                      name: reference
                      value: AAAAC
                    - type: INTEGER
                      name: rows
                      value: '5'
