zabbix_export:
  version: '8.0'
  template_groups:
    - uuid: c2c162144c2d4c5491c8801193af4945
      name: Templates/Cloud
  templates:
    - uuid: 024cf4f0711c4c39a4e016858efc5e37
      template: 'AWS Backup Vault by HTTP'
      name: 'AWS Backup Vault by HTTP'
      description: |
        The template is designed to monitor AWS Backup vaults and jobs by HTTP via Zabbix, and it works without any external scripts.
        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"
      wizard_ready: 'YES'
      readme: |
        ## Overview
        
        This template uses the AWS Backup API calls to list and retrieve metrics.
        For more information, please refer to the [AWS Backup API](https://docs.aws.amazon.com/aws-backup/latest/devguide/api-reference.html) page.
        
        Additional information about metrics and API methods used in the template:
        * [Metrics related to a Backup vault](https://docs.aws.amazon.com/aws-backup/latest/devguide/API_BackupVaultListMember.html)
        * [Metrics related to a Backup job](https://docs.aws.amazon.com/aws-backup/latest/devguide/API_BackupJob.html)
        
        
        ## Setup
        
        The template gets AWS Backup vault metrics and uses the script item to make HTTP requests to the AWS Backup API.
        
        Before using the template, you need to create an IAM policy with the necessary permissions for the Zabbix role in your AWS account.
        
        ### Required Permissions
        Add the following required permissions to your Zabbix IAM policy in order to collect AWS Backup vaults and jobs.
        
        ```json
        {
            "Version":"2012-10-17",
            "Statement":[
                {
                    "Action":[
                        "backup:ListBackupVaults",
                        "backup:ListBackupJobs",
                        "backup:ListCopyJobs",
                        "backup:ListRestoreJobs"
                    ],
                    "Effect":"Allow",
                    "Resource":"*"
                }
            ]
            }
        ```
        
        ### Access Key Authorization
        If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
        
        1. Create an IAM user with programmatic access.
        2. Attach the required policy to the IAM user.
        3. Generate an access key and secret key.
        4. Use the generated credentials in the macros `{$AWS.ACCESS.KEY.ID}` and `{$AWS.SECRET.ACCESS.KEY}`.
        
        ### Assume Role Authorization
        For using assume role authorization, add the appropriate permissions to the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "sts:AssumeRole",
                    "Resource": "arn:aws:iam::{Account}:user/{UserName}"
                },
                {
                    "Effect": "Allow",
                    "Action": [
                        "backup:ListBackupVaults",
                        "backup:ListBackupJobs",
                        "backup:ListCopyJobs",
                        "backup:ListRestoreJobs"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        
        #### Trust Relationships for Assume Role Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                "AWS": "arn:aws:iam::{Account}:user/{UserName}"
                },
                "Action": "sts:AssumeRole"
            }
            ]
        }
        ```
        Set the following macros: `{$AWS.ACCESS.KEY.ID}`, `{$AWS.SECRET.ACCESS.KEY}`, `{$AWS.STS.REGION}`, `{$AWS.ASSUME.ROLE.ARN}`.
        
        ### Role-Based Authorization
        If you are using role-based authorization, set the appropriate permissions:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "iam:PassRole",
                    "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
                },
                {
                    "Sid": "VisualEditor1",
                    "Effect": "Allow",
                    "Action": [
                        "backup:ListBackupVaults",
                        "backup:ListBackupJobs",
                        "backup:ListCopyJobs",
                        "backup:ListRestoreJobs"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        
        #### Trust Relationships for Role-Based Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": [
                            "backup.amazonaws.com"
                        ]
                    },
                    "Action": [
                        "sts:AssumeRole"
                    ]
                }
            ]
        }
        ```
        
        **Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
        
        Set the macros: `{$AWS.AUTH_TYPE}`, `{$AWS.REGION}`, and `{$AWS.BACKUP_VAULT.NAME}`.
        
        For more information about managing access keys, see the [official AWS documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).
        
        See the section below for a list of macros used for LLD filters.
      vendor:
        name: Zabbix
        version: 8.0-1
      groups:
        - name: Templates/Cloud
      items:
        - uuid: cc5d272814ab457c99127d3d42ca8d54
          name: Age
          type: DEPENDENT
          key: aws.backup_vault.age
          units: uptime
          description: 'The age of the vault.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.CreationDate
            - type: JAVASCRIPT
              parameters:
                - 'return Date.now() / 1000 - value'
          master_item:
            key: aws.backup_vault.data.get
          tags:
            - tag: component
              value: backup_vault
        - uuid: 0a02ff6671484ce4bf32c128aa337f14
          name: 'Get data'
          type: SCRIPT
          key: aws.backup_vault.data.get
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload)), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', 'vault'].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, canonical_uri, 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_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'),
            			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/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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS Backup vault ] Sending request: ' + url);
            		response = request.get(url);
            		Zabbix.log(4, '[ AWS Backup vault ] 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) {
            			try {
            				response = JSON.parse(XML.toJson(response));
            			}
            			catch (error) {
            				throw 'Failed to parse response received from AWS API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	getVaultData: function () {
            		var result = AWS.request('GET', '/backup-vaults/' + AWS.params.vault, AWS.params.region, 'backup', '');
            
            		if (typeof result !== 'object') {
            			throw 'Cannot get backup vault list from AWS API. Check debug log for more information.';
            		}
            
            		if (result === null) {
            			return [];
            		}
            
            		return result;
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            	return JSON.stringify(AWS.getVaultData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS Backup vault ] ERROR: ' + error);
            	return JSON.stringify({ 'error': error });
            }
          description: |
            Retrieve AWS backup vault metrics.
            More information here: https://docs.aws.amazon.com/aws-backup/latest/devguide/API_BackupVaultListMember.html
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
            - name: vault
              value: '{$AWS.BACKUP_VAULT.NAME}'
          tags:
            - tag: component
              value: raw
        - uuid: 4bf53a35af804262a4e0250a01d6c962
          name: 'Jobs: Backup'
          type: DEPENDENT
          key: aws.backup_vault.job.backup.count
          description: 'The number of backup jobs in the vault over the last `{$AWS.BACKUP_JOB.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.job_type == "backup-job")].length()'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: aws.backup_vault.job.get
          tags:
            - tag: component
              value: backup_vault
        - uuid: b1e841181aac401e927b27dc6bca6736
          name: 'Jobs: Failed backup'
          type: DEPENDENT
          key: aws.backup_vault.job.backup.failed.count
          description: 'The number of failed backup jobs in the vault over the last `{$AWS.BACKUP_JOB.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.job_type == "backup-job" && @.job_state == "FAILED")].length()'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: aws.backup_vault.job.get
          tags:
            - tag: component
              value: backup_vault
        - uuid: d8ea077804634388bcb15bc99ad9839e
          name: 'Jobs: Copy'
          type: DEPENDENT
          key: aws.backup_vault.job.copy.count
          description: 'The number of copy jobs in the vault over the last `{$AWS.BACKUP_JOB.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.job_type == "copy-job")].length()'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: aws.backup_vault.job.get
          tags:
            - tag: component
              value: backup_vault
          triggers:
            - uuid: 6a5ed839d0d049f58775e46ee86e83ee
              expression: 'change(/AWS Backup Vault by HTTP/aws.backup_vault.job.copy.count)>0'
              recovery_mode: NONE
              name: 'AWS Backup vault: Copy job has appeared'
              opdata: 'Current amount: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'New copy job has appeared.'
              manual_close: 'YES'
              tags:
                - tag: scope
                  value: notice
        - uuid: a2a8734311c84c05b72738ce0d8192f5
          name: 'Jobs: Failed copy'
          type: DEPENDENT
          key: aws.backup_vault.job.copy.failed.count
          description: 'The number of failed copy jobs in the vault over the last `{$AWS.BACKUP_JOB.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.job_type == "copy-job" && @.job_state == "FAILED")].length()'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: aws.backup_vault.job.get
          tags:
            - tag: component
              value: backup_vault
        - uuid: 81d17a83dddf4a4292428ae0644d83ca
          name: 'Get jobs'
          type: SCRIPT
          key: aws.backup_vault.job.get
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload)), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', 'vault', 'period'].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, canonical_uri, 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_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'),
            			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/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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS Backup vault ] Sending request: ' + url);
            		response = request.get(url);
            		Zabbix.log(4, '[ AWS Backup vault ] 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) {
            			try {
            				response = JSON.parse(XML.toJson(response));
            			}
            			catch (error) {
            				throw 'Failed to parse response received from AWS API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	listJobs: function () {
            		var lld_array = [],
            			job_types = [
            				'backup-job',
            				'copy-job',
            				'restore-job'
            			],
            			created_after = Date.now() / 1000 - AWS.params.period * 86400
            			payload = {
            				'backupVaultName': AWS.params.vault,
            				'createdAfter': created_after
            			};
            
            		job_types.forEach(function (job_type) {
            			while (payload.nextToken !== null) {
            				var result = AWS.request('GET', '/' + job_type + 's', AWS.params.region, 'backup', AWS.prepareParams(payload));
            
            				payload.nextToken = result.NextToken;
            
            				if (typeof result !== 'object') {
            							throw 'Cannot get job list from AWS API. Check debug log for more information.';
            				}
            
            				switch (job_type) {
            					case 'backup-job': {
            						if (typeof result.BackupJobs !== 'object') {
            							throw 'Cannot get backup job list from AWS API. Check debug log for more information.';
            						}
            						result.BackupJobs.forEach(function (job) {
            							lld_array.push({
            								job_id: AWS.getField(job, 'BackupJobId'),
            								job_type: job_type,
            								resource_type: AWS.getField(job, 'ResourceType'),
            								resource_name: AWS.getField(job, 'ResourceName'),
            								job_state: AWS.getField(job, 'State'),
            								job_size: AWS.getField(job, 'BackupSizeInBytes')
            							});
            						});
            						break;
            					}
            					case 'copy-job': {
            						if (typeof result.CopyJobs !== 'object') {
            							throw 'Cannot get copy job list from AWS API. Check debug log for more information.';
            						}
            						result.CopyJobs.forEach(function (job) {
            							lld_array.push({
            								job_id: AWS.getField(job, 'CopyJobId'),
            								job_type: job_type,
            								resource_type: AWS.getField(job, 'ResourceType'),
            								resource_name: AWS.getField(job, 'ResourceName'),
            								job_state: AWS.getField(job, 'State'),
            								job_size: AWS.getField(job, 'BackupSizeInBytes')
            							});
            						});
            						break;
            					}
            					case 'restore-job': {
            						if (typeof result.RestoreJobs !== 'object') {
            							throw 'Cannot get restore job list from AWS API. Check debug log for more information.';
            						}
            						result.RestoreJobs.forEach(function (job) {
            							lld_array.push({
            								job_id: AWS.getField(job, 'RestoreJobId'),
            								job_type: job_type,
            								resource_type: AWS.getField(job, 'ResourceType'),
            								resource_name: null,
            								job_state: AWS.getField(job, 'Status'),
            								job_size: AWS.getField(job, 'BackupSizeInBytes')
            							});
            						});
            						break;
            					}
            				}
            			};
            			delete payload.nextToken;
            		})
            		return lld_array;
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            	return JSON.stringify(AWS.listJobs());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS Backup vault ] ERROR: ' + error);
            	return JSON.stringify({ 'error': error });
            }
          description: 'Get a list of jobs in the vault.'
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: period
              value: '{$AWS.BACKUP_JOB.PERIOD}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
            - name: vault
              value: '{$AWS.BACKUP_VAULT.NAME}'
          tags:
            - tag: component
              value: raw
        - uuid: fa781abfaa014fcdab62321fc9940ac7
          name: 'Jobs: Restore'
          type: DEPENDENT
          key: aws.backup_vault.job.restore.count
          description: 'The number of restore jobs in the vault over the last `{$AWS.BACKUP_JOB.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.job_type == "restore-job")].length()'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: aws.backup_vault.job.get
          tags:
            - tag: component
              value: backup_vault
          triggers:
            - uuid: 31f7e20621f249138df7aea59df927dc
              expression: 'change(/AWS Backup Vault by HTTP/aws.backup_vault.job.restore.count)>0'
              recovery_mode: NONE
              name: 'AWS Backup vault: Restore job has appeared'
              opdata: 'Current amount: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'New restore job has appeared.'
              manual_close: 'YES'
              tags:
                - tag: scope
                  value: notice
        - uuid: acae9cf0a32c42dead1651fc911afc3b
          name: 'Jobs: Failed restore'
          type: DEPENDENT
          key: aws.backup_vault.job.restore.failed.count
          description: 'The number of failed restore jobs in the vault over the last `{$AWS.BACKUP_JOB.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.job_type == "restore-job" && @.job_state == "FAILED")].length()'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: aws.backup_vault.job.get
          tags:
            - tag: component
              value: backup_vault
        - uuid: 5a9a604c70844ab8bffe4bf96ceeb761
          name: 'Jobs: Size, avg'
          type: DEPENDENT
          key: aws.backup_vault.job.size.avg
          units: B
          description: |
            The average size, in bytes, of a backup (recovery point).
            This value can render differently depending on the resource type as AWS Backup pulls in data information from other AWS services. For example, the value returned may show a value of `0`, which may differ from the anticipated value.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$[?(@.job_size > 0)].job_size.avg()'
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: aws.backup_vault.job.get
          tags:
            - tag: component
              value: backup_vault
        - uuid: 90600e647d2a40ccbe1ced317c03abb4
          name: 'Jobs: Size, max'
          type: DEPENDENT
          key: aws.backup_vault.job.size.max
          units: B
          description: |
            The maximum size, in bytes, of a backup (recovery point).
            This value can render differently depending on the resource type as AWS Backup pulls in data information from other AWS services. For example, the value returned may show a value of `0`, which may differ from the anticipated value.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$[?(@.job_size > 0)].job_size.max()'
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: aws.backup_vault.job.get
          tags:
            - tag: component
              value: backup_vault
        - uuid: 0ad8090097e64cf3bf28710f423a6164
          name: 'Jobs: Size, min'
          type: DEPENDENT
          key: aws.backup_vault.job.size.min
          units: B
          description: |
            The minimum size, in bytes, of a backup (recovery point).
            This value can render differently depending on the resource type as AWS Backup pulls in data information from other AWS services. For example, the value returned may show a value of `0`, which may differ from the anticipated value.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$[?(@.job_size > 0)].job_size.min()'
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: aws.backup_vault.job.get
          tags:
            - tag: component
              value: backup_vault
        - uuid: 886b2b55cfbf42d58f01cfad66cc1ad5
          name: 'Jobs: Total'
          type: DEPENDENT
          key: aws.backup_vault.job.total.count
          description: 'The total number of jobs in the vault over the last `{$AWS.BACKUP_JOB.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.length()
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: aws.backup_vault.job.get
          tags:
            - tag: component
              value: backup_vault
        - uuid: 0faeb1eedbb64fa7848a475fb8da1808
          name: 'Lock date'
          type: DEPENDENT
          key: aws.backup_vault.lock.date
          units: unixtime
          description: 'The date and time when AWS Backup Vault Lock configuration becomes immutable, meaning it cannot be changed or deleted.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.LockDate
            - type: NOT_MATCHES_REGEX
              parameters:
                - 'null'
              error_handler: CUSTOM_ERROR
              error_handler_params: 'Either the vault is not locked, or the lock date is not specified.'
          master_item:
            key: aws.backup_vault.data.get
          tags:
            - tag: component
              value: backup_vault
        - uuid: 477eb6a9728e4fb4aadd8b9903ef6fb1
          name: 'Lock status'
          type: DEPENDENT
          key: aws.backup_vault.lock.status
          description: 'Indicates whether AWS Backup Vault Lock is applied to the selected backup vault. When the vault is locked, delete and update operations on recovery points in that vault are prevented.'
          valuemap:
            name: 'AWS Backup vault lock status'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.Locked
            - type: STR_REPLACE
              parameters:
                - 'false'
                - '0'
            - type: STR_REPLACE
              parameters:
                - 'true'
                - '1'
          master_item:
            key: aws.backup_vault.data.get
          tags:
            - tag: component
              value: backup_vault
        - uuid: b886025d57d345298e6739972b328223
          name: 'Lock time remain'
          type: DEPENDENT
          key: aws.backup_vault.lock.time_left
          units: uptime
          description: 'The remaining time before AWS Backup Vault Lock configuration becomes immutable, meaning it cannot be changed or deleted.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.LockDate
            - type: NOT_MATCHES_REGEX
              parameters:
                - 'null'
              error_handler: CUSTOM_ERROR
              error_handler_params: 'Either the vault is not locked, or the lock date is not specified.'
            - type: JAVASCRIPT
              parameters:
                - |
                  now = Date.now() / 1000;
                  if (value > now) {
                    return value - now
                  } else {
                    return 0
                  }
          master_item:
            key: aws.backup_vault.data.get
          tags:
            - tag: component
              value: backup_vault
        - uuid: abab51050d0a4fbbb976db8b6fe51494
          name: 'Recovery points'
          type: DEPENDENT
          key: aws.backup_vault.recovery_points
          description: 'The total number of recovery points in the backup vault.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.NumberOfRecoveryPoints
            - type: NOT_MATCHES_REGEX
              parameters:
                - 'null'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.backup_vault.data.get
          tags:
            - tag: component
              value: backup_vault
        - uuid: 9d8c6dc0c1dc4b65a2a2edd299bf7855
          name: 'Retention period, max'
          type: DEPENDENT
          key: aws.backup_vault.retention.max
          units: '!day(s)'
          description: 'The maximum retention period that the vault retains its recovery points.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.MaxRetentionDays
            - type: NOT_MATCHES_REGEX
              parameters:
                - 'null'
              error_handler: CUSTOM_ERROR
              error_handler_params: 'The vault does not have the maximum retention period set.'
          master_item:
            key: aws.backup_vault.data.get
          tags:
            - tag: component
              value: backup_vault
        - uuid: 6bbb460c7630455db019528e2fa4333b
          name: 'Retention period, min'
          type: DEPENDENT
          key: aws.backup_vault.retention.min
          units: '!day(s)'
          description: 'The minimum retention period that the vault retains its recovery points.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.MinRetentionDays
            - type: NOT_MATCHES_REGEX
              parameters:
                - 'null'
              error_handler: CUSTOM_ERROR
              error_handler_params: 'The vault does not have the minimum retention period set.'
          master_item:
            key: aws.backup_vault.data.get
          tags:
            - tag: component
              value: backup_vault
        - uuid: b289382581d741e8b420bf6db3eaf073
          name: State
          type: DEPENDENT
          key: aws.backup_vault.state
          description: |
            The current state of the backup vault.
            Possible values are:
            - Unknown
            - Creating
            - Available
            - Failed
          valuemap:
            name: 'AWS Backup vault state'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.VaultState
            - type: JAVASCRIPT
              parameters:
                - |
                  const idx = {
                  	'CREATING': 1,
                  	'AVAILABLE': 2,
                  	'FAILED': 3
                    };
                  
                    return typeof idx[value] === 'undefined' ? 0 : idx[value];
          master_item:
            key: aws.backup_vault.data.get
          tags:
            - tag: component
              value: backup_vault
      discovery_rules:
        - uuid: 1e96003b5bd949f08684cee42c1aa4d7
          name: 'AWS Backup job discovery'
          type: DEPENDENT
          key: aws.backup_vault.job.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.BACKUP_JOB.RESOURCE_NAME}'
                value: '{$AWS.BACKUP_JOB.RESOURCE_NAME.MATCHES}'
              - macro: '{#AWS.BACKUP_JOB.RESOURCE_NAME}'
                value: '{$AWS.BACKUP_JOB.RESOURCE_NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#AWS.BACKUP_JOB.RESOURCE_TYPE}'
                value: '{$AWS.BACKUP_JOB.RESOURCE_TYPE.MATCHES}'
              - macro: '{#AWS.BACKUP_JOB.RESOURCE_TYPE}'
                value: '{$AWS.BACKUP_JOB.RESOURCE_TYPE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#AWS.BACKUP_JOB.STATE}'
                value: '{$AWS.BACKUP_JOB.STATE.MATCHES}'
              - macro: '{#AWS.BACKUP_JOB.STATE}'
                value: '{$AWS.BACKUP_JOB.STATE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          lifetime: '0'
          description: 'AWS Backup job discovery.'
          item_prototypes:
            - uuid: cc978e4977c94e0ca743757d9d254f14
              name: 'Job state [{#AWS.BACKUP_JOB.RESOURCE_NAME}][{#AWS.BACKUP_JOB.ID}]'
              type: DEPENDENT
              key: 'aws.backup_vault.job.state["{#AWS.BACKUP_JOB.ID}"]'
              description: |
                The state of the job.
                Possible values are:
                - Unknown
                - Created
                - Pending
                - Running
                - Aborting
                - Aborted
                - Completed
                - Failed
                - Expired
                - Partial
              valuemap:
                name: 'AWS Backup job state'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.job_id == "{#AWS.BACKUP_JOB.ID}")].job_state.first()'
                  error_handler: DISCARD_VALUE
                - type: JAVASCRIPT
                  parameters:
                    - |
                      const idx = {
                      	'CREATED': 1,
                      	'PENDING': 2,
                      	'RUNNING': 3,
                      	'ABORTING': 4,
                      	'ABORTED': 5,
                      	'COMPLETED': 6,
                      	'FAILED': 7,
                      	'EXPIRED ': 8,
                      	'PARTIAL': 9
                        };
                      
                        return typeof idx[value] === 'undefined' ? 0 : idx[value];
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 1h
              master_item:
                key: aws.backup_vault.job.get
              tags:
                - tag: component
                  value: backup_vault
                - tag: job_type
                  value: '{#AWS.BACKUP_JOB.TYPE}'
                - tag: resource_name
                  value: '{#AWS.BACKUP_JOB.RESOURCE_NAME}'
                - tag: resource_type
                  value: '{#AWS.BACKUP_JOB.RESOURCE_TYPE}'
              trigger_prototypes:
                - uuid: d32bba2d26514a2381a18415f26c7591
                  expression: 'last(/AWS Backup Vault by HTTP/aws.backup_vault.job.state["{#AWS.BACKUP_JOB.ID}"])=7'
                  name: 'AWS Backup vault: Job failed [{#AWS.BACKUP_JOB.ID}]'
                  event_name: 'AWS Backup vault: Job type [{#AWS.BACKUP_JOB.TYPE}] for [{#AWS.BACKUP_JOB.RESOURCE_NAME}] with ID [{#AWS.BACKUP_JOB.ID}] has failed.'
                  opdata: 'Current status: {ITEM.LASTVALUE1}'
                  priority: HIGH
                  description: 'Job has failed.'
                  manual_close: 'YES'
                  tags:
                    - tag: scope
                      value: notice
                - uuid: 06182df42e5d4777b8506726c2793dee
                  expression: 'last(/AWS Backup Vault by HTTP/aws.backup_vault.job.state["{#AWS.BACKUP_JOB.ID}"])=5'
                  name: 'AWS Backup vault: Job has been aborted [{#AWS.BACKUP_JOB.ID}]'
                  event_name: 'AWS Backup vault: Job type [{#AWS.BACKUP_JOB.TYPE}] for [{#AWS.BACKUP_JOB.RESOURCE_NAME}] with ID [{#AWS.BACKUP_JOB.ID}] has been aborted.'
                  opdata: 'Current status: {ITEM.LASTVALUE1}'
                  priority: AVERAGE
                  description: 'Job has been aborted.'
                  manual_close: 'YES'
                  tags:
                    - tag: scope
                      value: notice
                - uuid: e1fb82528ca34849b75200b417036037
                  expression: 'last(/AWS Backup Vault by HTTP/aws.backup_vault.job.state["{#AWS.BACKUP_JOB.ID}"])=8'
                  name: 'AWS Backup vault: Job has expired [{#AWS.BACKUP_JOB.ID}]'
                  event_name: 'AWS Backup vault: Job type [{#AWS.BACKUP_JOB.TYPE}] for [{#AWS.BACKUP_JOB.RESOURCE_NAME}] with ID [{#AWS.BACKUP_JOB.ID}] has expired.'
                  opdata: 'Current status: {ITEM.LASTVALUE1}'
                  priority: WARNING
                  description: 'Job expired.'
                  manual_close: 'YES'
                  tags:
                    - tag: scope
                      value: notice
                - uuid: e449b1999f09469bbf71e531afebc26b
                  expression: 'last(/AWS Backup Vault by HTTP/aws.backup_vault.job.state["{#AWS.BACKUP_JOB.ID}"])=0'
                  name: 'AWS Backup vault: Job is in an unknown state [{#AWS.BACKUP_JOB.ID}]'
                  event_name: 'AWS Backup vault: Job type [{#AWS.BACKUP_JOB.TYPE}] for [{#AWS.BACKUP_JOB.RESOURCE_NAME}] with ID [{#AWS.BACKUP_JOB.ID}] is in an unknown state.'
                  opdata: 'Current status: {ITEM.LASTVALUE1}'
                  priority: WARNING
                  description: 'Job is in unknown state.'
                  manual_close: 'YES'
                  tags:
                    - tag: scope
                      value: notice
          master_item:
            key: aws.backup_vault.job.get
          lld_macro_paths:
            - lld_macro: '{#AWS.BACKUP_JOB.ID}'
              path: $.job_id
            - lld_macro: '{#AWS.BACKUP_JOB.RESOURCE_NAME}'
              path: $.resource_name
            - lld_macro: '{#AWS.BACKUP_JOB.RESOURCE_TYPE}'
              path: $.resource_type
            - lld_macro: '{#AWS.BACKUP_JOB.STATE}'
              path: $.job_state
            - lld_macro: '{#AWS.BACKUP_JOB.TYPE}'
              path: $.job_type
          preprocessing:
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          overrides:
            - name: 'Copy job excludes'
              step: '1'
              filter:
                conditions:
                  - macro: '{#AWS.BACKUP_JOB.TYPE}'
                    value: '^copy-job&'
              operations:
                - operationobject: TRIGGER_PROTOTYPE
                  operator: LIKE
                  value: 'Job aborted'
                  discover: NO_DISCOVER
                - operationobject: TRIGGER_PROTOTYPE
                  operator: LIKE
                  value: 'Job expired'
                  discover: NO_DISCOVER
            - name: 'Restore job excludes'
              step: '2'
              filter:
                conditions:
                  - macro: '{#AWS.BACKUP_JOB.TYPE}'
                    value: '^restore-job&'
              operations:
                - operationobject: TRIGGER_PROTOTYPE
                  operator: LIKE
                  value: 'Job expired'
                  discover: NO_DISCOVER
                - operationobject: TRIGGER_PROTOTYPE
                  operator: LIKE
                  value: 'Job partially completed'
                  discover: NO_DISCOVER
      tags:
        - tag: class
          value: cloud
        - tag: target
          value: aws
        - tag: target
          value: backup_vault
      macros:
        - macro: '{$AWS.ACCESS.KEY.ID}'
          description: 'Access key ID.'
          config:
            type: TEXT
            priority: '3'
            label: 'Access key ID'
            description: 'Access keys are long-term credentials for an IAM user.'
        - macro: '{$AWS.ASSUME.ROLE.ARN}'
          description: 'ARN assume role; add when using the `assume_role` authorization method.'
          config:
            type: TEXT
            priority: '9'
            label: 'ARN assume role'
            description: 'The ARN of the role to assume when using the assume_role authorization method.'
        - macro: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
          value: 'false'
          description: 'Add when using the `assume_role` through instance metadata or environment authorization method. Possible values: `false`, `true`.'
          config:
            type: LIST
            priority: '7'
            label: 'Assume Role Metadata Authorization'
            description: 'Chose `True` when use instance metadata service to retrieve role credentials.'
            options:
              - value: 'false'
                text: 'False'
              - value: 'true'
                text: 'True'
        - macro: '{$AWS.AUTH_TYPE}'
          value: access_key
          description: 'Authorization method. Possible values: `access_key`, `assume_role`, `role_base`.'
          config:
            type: LIST
            priority: '6'
            label: 'Authorization method'
            description: 'Authorization method used to access AWS.'
            required: 'YES'
            options:
              - value: access_key
                text: 'Access key'
              - value: assume_role
                text: AssumeRole
              - value: role_base
                text: 'Role-based access'
        - macro: '{$AWS.BACKUP_JOB.PERIOD}'
          value: '7'
          description: 'The number of days over which to retrieve backup jobs.'
          config:
            type: TEXT
            priority: '17'
            label: 'Job discovery period'
            description: 'The number of days over which to retrieve backup jobs. No less than 1.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.BACKUP_JOB.RESOURCE_NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable jobs by resource name.'
          config:
            type: TEXT
            priority: '15'
            section_name: Filters
            label: 'Job filter by resource name'
            description: 'Filter of discoverable jobs by resource name.'
        - macro: '{$AWS.BACKUP_JOB.RESOURCE_NAME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered jobs by resource name.'
          config:
            type: TEXT
            priority: '16'
            section_name: Filters
            label: 'Job filter by resource name (exclude)'
            description: 'Filter to exclude discoverable jobs by resource name.'
        - macro: '{$AWS.BACKUP_JOB.RESOURCE_TYPE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable jobs by resource type.'
          config:
            type: TEXT
            priority: '13'
            section_name: Filters
            label: 'Job filter by resource type'
            description: 'Filter of discoverable jobs by resource type.'
        - macro: '{$AWS.BACKUP_JOB.RESOURCE_TYPE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered jobs by resource type.'
          config:
            type: TEXT
            priority: '14'
            section_name: Filters
            label: 'Job filter by resource type (exclude)'
            description: 'Filter to exclude discoverable jobs by resource type.'
        - macro: '{$AWS.BACKUP_JOB.STATE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable jobs by state.'
          config:
            type: TEXT
            priority: '11'
            section_name: Filters
            label: 'Job filter by state'
            description: 'Filter of discoverable jobs by state.'
        - macro: '{$AWS.BACKUP_JOB.STATE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered jobs by state.'
          config:
            type: TEXT
            priority: '12'
            section_name: Filters
            label: 'Job filter by state (exclude)'
            description: 'Filter to exclude discoverable jobs by state.'
        - macro: '{$AWS.BACKUP_VAULT.NAME}'
          description: 'AWS backup vault name.'
          config:
            type: TEXT
            priority: '10'
            label: 'Backup vault name'
            description: 'AWS Backup vault name.'
        - macro: '{$AWS.DATA.TIMEOUT}'
          value: 60s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '1'
            section_name: Other
            label: 'API response timeout'
            description: 'Timeout for API responses in seconds.'
        - macro: '{$AWS.PROXY}'
          description: 'Sets the HTTP proxy value. If this macro is empty, no proxy is used.'
          config:
            type: TEXT
            priority: '2'
            section_name: Other
            label: 'HTTP Proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AWS.REGION}'
          value: us-west-1
          description: 'AWS backup vault region code.'
          config:
            type: TEXT
            priority: '5'
            label: 'AWS Region'
            description: 'The AWS region where your backup vaults are located.'
        - macro: '{$AWS.SECRET.ACCESS.KEY}'
          type: SECRET_TEXT
          description: 'Secret access key.'
          config:
            type: TEXT
            priority: '4'
            label: 'Secret access key'
            description: 'Secret access key can be retrieved only at the time you create it.'
        - macro: '{$AWS.STS.REGION}'
          value: us-east-1
          description: 'Region used in assume role request.'
          config:
            type: TEXT
            priority: '8'
            label: 'STS Region'
            description: 'The AWS region for the assume role request.'
      dashboards:
        - uuid: 92a5197bbdeb403cabb6dd12eabb7deb
          name: 'AWS Backup vault'
          pages:
            - name: 'Backup vault overview'
              widgets:
                - type: item
                  name: 'Vault age'
                  width: '26'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS Backup Vault by HTTP'
                        key: aws.backup_vault.age
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: item
                  name: 'Backup jobs'
                  'y': '2'
                  width: '13'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS Backup Vault by HTTP'
                        key: aws.backup_vault.job.backup.count
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: show.1
                      value: '4'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: itemnavigator
                  name: 'Jobs grouped'
                  'y': '4'
                  width: '28'
                  height: '8'
                  fields:
                    - type: INTEGER
                      name: group_by.0.attribute
                      value: '3'
                    - type: STRING
                      name: group_by.0.tag_name
                      value: resource_type
                    - type: INTEGER
                      name: group_by.1.attribute
                      value: '3'
                    - type: STRING
                      name: group_by.1.tag_name
                      value: resource_name
                    - type: STRING
                      name: items.0
                      value: 'Job state [*]'
                    - type: STRING
                      name: reference
                      value: DTQLA
                    - type: INTEGER
                      name: show_lines
                      value: '300'
                - type: item
                  name: 'Selected job'
                  'y': '12'
                  width: '28'
                  height: '1'
                  hide_header: 'YES'
                  fields:
                    - type: STRING
                      name: description
                      value: 'Selected job status:'
                    - type: INTEGER
                      name: desc_h_pos
                      value: '0'
                    - type: INTEGER
                      name: desc_size
                      value: '60'
                    - type: INTEGER
                      name: desc_v_pos
                      value: '1'
                    - type: STRING
                      name: itemid._reference
                      value: DTQLA._itemid
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: show.1
                      value: '1'
                    - type: INTEGER
                      name: value_h_pos
                      value: '2'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: item
                  name: 'Restore jobs'
                  x: '13'
                  'y': '2'
                  width: '13'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS Backup Vault by HTTP'
                        key: aws.backup_vault.job.restore.count
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: show.1
                      value: '4'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: item
                  name: 'Recovery points'
                  x: '26'
                  width: '13'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS Backup Vault by HTTP'
                        key: aws.backup_vault.recovery_points
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: show.1
                      value: '4'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: item
                  name: 'Copy jobs'
                  x: '26'
                  'y': '2'
                  width: '13'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS Backup Vault by HTTP'
                        key: aws.backup_vault.job.copy.count
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: show.1
                      value: '4'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: honeycomb
                  name: Jobs
                  x: '28'
                  'y': '4'
                  width: '44'
                  height: '8'
                  fields:
                    - type: STRING
                      name: items.0
                      value: 'Job state [*]'
                    - type: STRING
                      name: reference
                      value: ZMGLG
                    - type: INTEGER
                      name: secondary_label_units_show
                      value: '0'
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: STRING
                      name: thresholds.0.color
                      value: EC1594
                    - type: STRING
                      name: thresholds.0.threshold
                      value: '0'
                    - type: STRING
                      name: thresholds.1.color
                      value: 6AC8FF
                    - type: STRING
                      name: thresholds.1.threshold
                      value: '1'
                    - type: STRING
                      name: thresholds.2.color
                      value: 6AC8FF
                    - type: STRING
                      name: thresholds.2.threshold
                      value: '2'
                    - type: STRING
                      name: thresholds.3.color
                      value: 00A1FF
                    - type: STRING
                      name: thresholds.3.threshold
                      value: '3'
                    - type: STRING
                      name: thresholds.4.color
                      value: FFD54F
                    - type: STRING
                      name: thresholds.4.threshold
                      value: '4'
                    - type: STRING
                      name: thresholds.5.color
                      value: BF00FF
                    - type: STRING
                      name: thresholds.5.threshold
                      value: '5'
                    - type: STRING
                      name: thresholds.6.color
                      value: 0EC9AC
                    - type: STRING
                      name: thresholds.6.threshold
                      value: '6'
                    - type: STRING
                      name: thresholds.7.color
                      value: FF465C
                    - type: STRING
                      name: thresholds.7.threshold
                      value: '7'
                    - type: STRING
                      name: thresholds.8.color
                      value: BAE37D
                    - type: STRING
                      name: thresholds.8.threshold
                      value: '8'
                - type: item
                  name: 'Selected job'
                  x: '28'
                  'y': '12'
                  width: '44'
                  height: '1'
                  hide_header: 'YES'
                  fields:
                    - type: STRING
                      name: description
                      value: '{{ITEM.NAME}.regsub("(Job state \[)(.*)(, )(.*)(\])","Resource: \2, Job ID: \4")}'
                    - type: INTEGER
                      name: desc_h_pos
                      value: '0'
                    - type: INTEGER
                      name: desc_size
                      value: '60'
                    - type: INTEGER
                      name: desc_v_pos
                      value: '1'
                    - type: STRING
                      name: itemid._reference
                      value: ZMGLG._itemid
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: show.1
                      value: '1'
                    - type: INTEGER
                      name: value_h_pos
                      value: '2'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: item
                  name: 'Average size'
                  x: '39'
                  width: '13'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '1'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS Backup Vault by HTTP'
                        key: aws.backup_vault.job.size.avg
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: show.1
                      value: '4'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: item
                  name: 'Total jobs'
                  x: '39'
                  'y': '2'
                  width: '13'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS Backup Vault by HTTP'
                        key: aws.backup_vault.job.total.count
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: show.1
                      value: '4'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: item
                  name: 'Lock status'
                  x: '52'
                  width: '20'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS Backup Vault by HTTP'
                        key: aws.backup_vault.lock.status
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: show.1
                      value: '4'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: item
                  name: 'Vault state'
                  x: '52'
                  'y': '2'
                  width: '20'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS Backup Vault by HTTP'
                        key: aws.backup_vault.state
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: value_size
                      value: '60'
      valuemaps:
        - uuid: 0296c0c525304ea2ad91070346669b42
          name: 'AWS Backup job state'
          mappings:
            - value: '0'
              newvalue: Unknown
            - value: '1'
              newvalue: Created
            - value: '2'
              newvalue: Pending
            - value: '3'
              newvalue: Running
            - value: '4'
              newvalue: Aborting
            - value: '5'
              newvalue: Aborted
            - value: '6'
              newvalue: Completed
            - value: '7'
              newvalue: Failed
            - value: '8'
              newvalue: Expired
            - value: '9'
              newvalue: Partial
        - uuid: b5821fcd5f3444198570b8dfb925ce0a
          name: 'AWS Backup vault lock status'
          mappings:
            - value: '0'
              newvalue: Unlocked
            - value: '1'
              newvalue: Locked
        - uuid: d591fd3704ff4fc3a7e5ee6b206190ad
          name: 'AWS Backup vault state'
          mappings:
            - value: '0'
              newvalue: Unknown
            - value: '1'
              newvalue: Creating
            - value: '2'
              newvalue: Available
            - value: '3'
              newvalue: Failed
    - uuid: 7af6d68b223a43d4bf8526cc5dc3fe2e
      template: 'AWS EC2 by HTTP'
      name: 'AWS EC2 by HTTP'
      description: |
        Get AWS EC2 and attached AWS EBS volumes 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"
      wizard_ready: 'YES'
      readme: |
        ## Overview
        
        The template to monitor AWS EC2 and attached AWS EBS volumes by HTTP via Zabbix that works without any external scripts.
        Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
        
        **Note:** This template uses the GetMetricData CloudWatch API calls to list and retrieve metrics.
        For more information, please refer to the [CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) page.
        
        Additional information about metrics and used API methods:
        * [Full metrics list related to EBS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using_cloudwatch_ebs.html)
        * [Full metrics list related to EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html)
        * [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
        * [DescribeVolumes API method](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVolumes.html)
        
        
        ## Setup
        
        The template get AWS EC2 and attached AWS EBS volumes metrics and uses the script item to make HTTP requests to the CloudWatch API.
        Before using the template, you need to create an IAM policy with the necessary permissions for the Zabbix role in your AWS account.
        
        ### Required Permissions
        Add the following required permissions to your Zabbix IAM policy in order to collect Amazon EC2 metrics.
        
        ```json
        {
            "Version":"2012-10-17",
            "Statement":[
                {
                  "Action":[
                      "ec2:DescribeVolumes",
                      "cloudwatch:"DescribeAlarms",
                      "cloudwatch:GetMetricData"
                  ],
                  "Effect":"Allow",
                  "Resource":"*"
                }
            ]
          }
        ```
        
        ### Access Key Authorization
        
        If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
        
        1. Create an IAM user with programmatic access.
        2. Attach the required policy to the IAM user.
        3. Generate an access key and secret key.
        4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
        
        ### Assume Role Authorization
        For using assume role authorization, add the appropriate permissions to the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "sts:AssumeRole",
                    "Resource": "arn:aws:iam::{Account}:user/{UserName}"
                },
                {
                    "Effect": "Allow",
                    "Action": [
                        "ec2:DescribeVolumes",
                        "cloudwatch:"DescribeAlarms",
                        "cloudwatch:GetMetricData"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        
        #### Trust Relationships for Assume Role Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "AWS": "arn:aws:iam::{Account}:user/{UserName}"
              },
              "Action": "sts:AssumeRole"
            }
          ]
        }
        ```
        Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
        
        ### Role-Based Authorization
        If you are using role-based authorization, set the appropriate permissions:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "iam:PassRole",
                    "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
                },
                {
                    "Sid": "VisualEditor1",
                    "Effect": "Allow",
                    "Action": [
                        "ec2:DescribeVolumes",
                        "cloudwatch:"DescribeAlarms",
                        "cloudwatch:GetMetricData"
                        "ec2:AssociateIamInstanceProfile",
                        "ec2:ReplaceIamInstanceProfileAssociation"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        
        #### Trust Relationships for Role-Based Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": [
                            "ec2.amazonaws.com"
                        ]
                    },
                    "Action": [
                        "sts:AssumeRole"
                    ]
                }
            ]
        }
        ```
        
        **Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
        
        For more information, see the [EC2 policies](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-iam.html) on the AWS website.
        
        Set the following fields: `Authorization method`, `AWS Region`, `EC2 instance ID`.
        
        For more information about managing access keys, see [official documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).
      vendor:
        name: Zabbix
        version: 8.0-3
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 22b61bf7ebba43e8aef544385448d18c
          name: 'Get alarms check'
          type: DEPENDENT
          key: aws.ec2.alarms.check
          value_type: CHAR
          description: 'Check result of the alarm data has been got correctly.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.ec2.get_alarms
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: 1d017a1213fb4bc9896add10a2b97dd6
              expression: 'length(last(/AWS EC2 by HTTP/aws.ec2.alarms.check))>0'
              name: 'AWS EC2: Failed to get alarms data'
              priority: WARNING
              description: 'Failed to get CloudWatch alarms for EC2.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 0384bacca1e14994a5c38dc55b73e8bb
          name: 'Credit CPU: Balance'
          type: DEPENDENT
          key: aws.ec2.cpu.credit_balance
          value_type: FLOAT
          description: |
            The number of earned CPU credits that an instance has accrued since it was launched or started. For T2 Standard, the CPUCreditBalance also includes the number of launch credits that have been accrued.
            Credits are accrued in the credit balance after they are earned, and removed from the credit balance when they are spent. The credit balance has a maximum limit, determined by the instance size. After the limit is reached, any new credits that are earned are discarded. For T2 Standard, launch credits do not count towards the limit.
            The credits in the CPUCreditBalance are available for the instance to spend to burst beyond its baseline CPU utilization.
            When an instance is running, credits in the CPUCreditBalance do not expire. When a T3 or T3a instance stops, the CPUCreditBalance value persists for seven days. Thereafter, all accrued credits are lost. When a T2 instance stops, the CPUCreditBalance value does not persist, and all accrued credits are lost.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "CPUCreditBalance")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: cpu
            - tag: component
              value: credit
          triggers:
            - uuid: 4e67cac1f58a478fb0e47c52b402fd92
              expression: 'max(/AWS EC2 by HTTP/aws.ec2.cpu.credit_balance,5m)<{$AWS.EC2.CPU.CREDIT.BALANCE.MIN.WARN}'
              name: 'AWS EC2: Instance CPU Credit balance is too low'
              event_name: 'AWS EC2: Instance CPU Credit balance is too low (less {$AWS.EC2.CPU.CREDIT.BALANCE.MIN.WARN} for 5m)'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The number of earned CPU credits has been less than {$AWS.EC2.CPU.CREDIT.BALANCE.MIN.WARN} in the last 5 minutes.'
              tags:
                - tag: scope
                  value: capacity
        - uuid: b445a56de3194f6f9b4bf9dd85fcbe52
          name: 'Credit CPU: Usage'
          type: DEPENDENT
          key: aws.ec2.cpu.credit_usage
          value_type: FLOAT
          description: |
            The number of CPU credits spent by the instance for CPU utilization.
            One CPU credit equals one vCPU running at 100% utilization for one minute or an equivalent combination of vCPUs, utilization, and time (for example, one vCPU running at 50% utilization for two minutes or two vCPUs running at 25% utilization for two minutes).
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "CPUCreditUsage")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: cpu
            - tag: component
              value: credit
        - uuid: 285ec6451412450c963e3a24d2aa74e1
          name: 'Credit CPU: Surplus balance'
          type: DEPENDENT
          key: aws.ec2.cpu.surplus_credit_balance
          value_type: FLOAT
          description: |
            The number of surplus credits that have been spent by an unlimited instance when its CPUCreditBalance value is zero.
            The CPUSurplusCreditBalance value is paid down by earned CPU credits. If the number of surplus credits exceeds the maximum number of credits that the instance can earn in a 24-hour period, the spent surplus credits above the maximum incur an additional charge.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "CPUSurplusCreditBalance")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: cpu
            - tag: component
              value: credit
        - uuid: 77a32118a77e4836a945c7b0954ef64a
          name: 'Credit CPU: Surplus charged'
          type: DEPENDENT
          key: aws.ec2.cpu.surplus_credit_charged
          value_type: FLOAT
          description: |
            The number of spent surplus credits that are not paid down by earned CPU credits, and which thus incur an additional charge.
            
            Spent surplus credits are charged when any of the following occurs:
            - The spent surplus credits exceed the maximum number of credits that the instance can earn in a 24-hour period. Spent surplus credits above the maximum are charged at the end of the hour;
            - The instance is stopped or terminated;
            - The instance is switched from unlimited to standard.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "CPUSurplusCreditsCharged")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: cpu
            - tag: component
              value: credit
          triggers:
            - uuid: 644ace5510164f329d9af65bd0ed4f34
              expression: 'last(/AWS EC2 by HTTP/aws.ec2.cpu.surplus_credit_charged)>{$AWS.EC2.CPU.CREDIT.SURPLUS.BALANCE.MAX.WARN}'
              name: 'AWS EC2: Instance has spent too many CPU surplus credits'
              event_name: 'AWS EC2: Instance has spent too many CPU surplus credits (over {$AWS.EC2.CPU.CREDIT.SURPLUS.BALANCE.MAX.WARN} for 15m)'''
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The number of spent surplus credits that are not paid down and which thus incur an additional charge is over {$AWS.EC2.CPU.CREDIT.SURPLUS.BALANCE.MAX.WARN}.'
              tags:
                - tag: scope
                  value: capacity
        - uuid: 7fd871e7eed54845ad069c3e7d3cad56
          name: 'CPU: Utilization'
          type: DEPENDENT
          key: aws.ec2.cpu_utilization
          value_type: FLOAT
          units: '%'
          description: |
            The percentage of allocated EC2 compute units that are currently in use on the instance. This metric identifies the processing power required to run an application on a selected instance.
            Depending on the instance type, tools in your operating system can show a lower percentage than CloudWatch when the instance is not allocated a full processor core.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "CPUUtilization")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: cpu
          triggers:
            - uuid: ea74d00067874b609e4846847033058f
              expression: 'min(/AWS EC2 by HTTP/aws.ec2.cpu_utilization,15m)>{$AWS.EC2.CPU.UTIL.WARN.MAX}'
              name: 'AWS EC2: High CPU utilization'
              event_name: 'AWS EC2: High CPU utilization (over {$AWS.EC2.CPU.UTIL.WARN.MAX}% 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: 49aecab5c7df407b9cbfe80ad8790492
          name: 'Disk: Read bytes, rate'
          type: DEPENDENT
          key: aws.ec2.disk.read_bytes.rate
          value_type: FLOAT
          units: Bps
          description: |
            Bytes read from all instance store volumes available to the instance.
            This metric is used to determine the volume of the data the application reads from the hard disk of the instance.
            This can be used to determine the speed of the application.
            If there are no instance store volumes, either the value is 0 or the metric is not reported.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "DiskReadBytes")].Values.first().first()'
              error_handler: DISCARD_VALUE
            - type: JAVASCRIPT
              parameters:
                - 'return value / 300;'
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: d6bb726f9f1b4d5b889ede0ae2c73613
          name: 'Disk: Read, rate'
          type: DEPENDENT
          key: aws.ec2.disk.read_ops.rate
          value_type: FLOAT
          units: Ops
          description: |
            Completed read operations from all instance store volumes available to the instance in a specified period of time.
            If there are no instance store volumes, either the value is 0 or the metric is not reported.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "DiskReadOps")].Values.first().first()'
              error_handler: DISCARD_VALUE
            - type: JAVASCRIPT
              parameters:
                - 'return value / 300;'
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: 95bcfd522147498688555e2cab5c00e2
          name: 'Disk: Write bytes, rate'
          type: DEPENDENT
          key: aws.ec2.disk_write_bytes.rate
          value_type: FLOAT
          units: Bps
          description: |
            Bytes written to all instance store volumes available to the instance.
            This metric is used to determine the volume of the data the application writes onto the hard disk of the instance.
            This can be used to determine the speed of the application.
            If there are no instance store volumes, either the value is 0 or the metric is not reported.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "DiskWriteBytes")].Values.first().first()'
              error_handler: DISCARD_VALUE
            - type: JAVASCRIPT
              parameters:
                - 'return value / 300;'
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: 28496d5aa03742feb85ae000deb616d1
          name: 'Disk: Write ops, rate'
          type: DEPENDENT
          key: aws.ec2.disk_write_ops.rate
          value_type: FLOAT
          units: Ops
          description: |
            Completed write operations to all instance store volumes available to the instance in a specified period of time.
            If there are no instance store volumes, either the value is 0 or the metric is not reported.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "DiskWriteOps")].Values.first().first()'
              error_handler: DISCARD_VALUE
            - type: JAVASCRIPT
              parameters:
                - 'return value / 300;'
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: 64180ec5dae84f588006bb1dd0ce6980
          name: 'EBS: Byte balance'
          type: DEPENDENT
          key: aws.ec2.ebs.byte_balance
          value_type: FLOAT
          units: '%'
          description: 'Percentage of throughput credits remaining in the burst bucket for Nitro-based instances.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "EBSByteBalance%")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: ebs
          triggers:
            - uuid: 27f3b00e295d4aeb9a2d0519e95da4e0
              expression: 'max(/AWS EC2 by HTTP/aws.ec2.ebs.byte_balance,5m)<{$AWS.EBS.BYTE.CREDIT.BALANCE.MIN.WARN}'
              name: 'AWS EC2: Byte Credit balance is too low'
              event_name: 'AWS EC2: Byte Credit balance is too low (less {$AWS.EBS.BYTE.CREDIT.BALANCE.MIN.WARN}% for 5m)'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              tags:
                - tag: scope
                  value: capacity
        - uuid: 7b8a2b6941d04cde8edc511752755c8f
          name: 'EBS: IO balance'
          type: DEPENDENT
          key: aws.ec2.ebs.io_balance
          value_type: FLOAT
          units: '%'
          description: 'Percentage of I/O credits remaining in the burst bucket for Nitro-based instances.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "EBSIOBalance%")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: ebs
          triggers:
            - uuid: f4b9c2238b5443eab31255422bc22d7d
              expression: 'max(/AWS EC2 by HTTP/aws.ec2.ebs.io_balance,5m)<{$AWS.EBS.IO.CREDIT.BALANCE.MIN.WARN}'
              name: 'AWS EC2: I/O Credit balance is too low'
              event_name: 'AWS EC2: I/O Credit balance is too low (less {$AWS.EBS.IO.CREDIT.BALANCE.MIN.WARN}% for 5m)'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              tags:
                - tag: scope
                  value: capacity
        - uuid: 251c9a3b0afd4930b822f7310f3fda43
          name: 'EBS: Read bytes, rate'
          type: DEPENDENT
          key: aws.ec2.ebs.read_bytes.rate
          value_type: FLOAT
          units: Bps
          description: 'Bytes read from all EBS volumes attached to the instance for Nitro-based instances.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "EBSReadBytes")].Values.first().first()'
              error_handler: DISCARD_VALUE
            - type: JAVASCRIPT
              parameters:
                - 'return value / 300;'
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: ebs
        - uuid: 29eff02b7c464605bc6d69a963d232b5
          name: 'EBS: Read, rate'
          type: DEPENDENT
          key: aws.ec2.ebs.read_ops.rate
          value_type: FLOAT
          units: Ops
          description: 'Completed read operations from all Amazon EBS volumes attached to the instance for Nitro-based instances.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "EBSReadOps")].Values.first().first()'
              error_handler: DISCARD_VALUE
            - type: JAVASCRIPT
              parameters:
                - 'return value / 300;'
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: ebs
        - uuid: 9dafe0bcfb214d46975f570e2836e9cd
          name: 'EBS: Write bytes, rate'
          type: DEPENDENT
          key: aws.ec2.ebs.write_bytes.rate
          value_type: FLOAT
          units: Bps
          description: 'Bytes written to all EBS volumes attached to the instance for Nitro-based instances.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "EBSWriteBytes")].Values.first().first()'
              error_handler: DISCARD_VALUE
            - type: JAVASCRIPT
              parameters:
                - 'return value / 300;'
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: ebs
        - uuid: 2da28e61261746d6b94b244b8f0cf2a8
          name: 'EBS: Write, rate'
          type: DEPENDENT
          key: aws.ec2.ebs.write_ops.rate
          value_type: FLOAT
          description: 'Completed write operations to all EBS volumes attached to the instance in a specified period of time.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "EBSWriteOps")].Values.first().first()'
              error_handler: DISCARD_VALUE
            - type: JAVASCRIPT
              parameters:
                - 'return value / 300;'
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: ebs
        - uuid: 4e0b2ed29500487092148b14245839d4
          name: 'Get instance alarms data'
          type: SCRIPT
          key: aws.ec2.get_alarms
          delay: 0s;m/1
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	getField: function (data, path, val) {
            		var steps = path.split('.');
            		for (var i = 0; i < steps.length; i++) {
            			var step = steps[i];
            			if (typeof data !== 'object' || data === null || typeof data[step] === 'undefined') {
            				if (typeof val === 'undefined') {
            					throw 'Required field was not found: ' + path;
            				}
            				return val
            			}
            
            			data = data[step];
            		}
            
            		return data;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', 'instance_id'].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'),
            			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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS EC2  ] Sending request: ' + url);
            		response = request.get(url);
            		Zabbix.log(4, '[ AWS EC2 ] 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) {
            			try {
            				response = JSON.parse(XML.toJson(response));
            			}
            			catch (error) {
            				throw 'Failed to parse response received from AWS CloudWatch API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	getVolumes: function () {
            		var payload = {
            			'Action': 'DescribeVolumes',
            			'Version': '2016-11-15',
            			'MaxResults': 100,
            			'Filter.1.Name': 'attachment.instance-id',
            			'Filter.1.Value': AWS.params.instance_id
            		},
            			value = [],
            			volumes = [],
            			volumes_list = [];
            
            		while (payload.NextToken !== '') {
            			var result = AWS.getField(AWS.request('GET', AWS.params.region, 'ec2', AWS.prepareParams(payload)), 'DescribeVolumesResponse');
            			payload.NextToken = result.nextToken || '';
            			volumes = AWS.getField(result, 'volumeSet.item', value);
            			volumes_list.push(Array.isArray(volumes) ? volumes : [volumes])
            
            		}
            		var flattenedData = volumes_list.reduce(function (acc, val) {
            			return acc.concat(val);
            		}, []);
            		return flattenedData;
            	},
            
            	getAlarms: function () {
            		var payload = {
            			'Action': 'DescribeAlarms',
            			'Version': '2010-08-01',
            			'MaxRecords': 100
            		},
            			result = [],
            			volumes = AWS.getVolumes()
            
            		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;
            
            				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 === 'InstanceId' && dimensions[i].Value === AWS.params.instance_id) {
            						result.push(alarm);
            						break;
            					}
            					if (dimensions[i].Name === 'VolumeId' && volumes.indexOf(dimensions[i].Value)) {
            						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 EC2 ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: '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: instance_id
              value: '{$AWS.EC2.INSTANCE.ID}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: 63ab011505f24885b843a9ac48b36a84
          name: 'Get metrics data'
          type: SCRIPT
          key: aws.ec2.get_metrics
          delay: 0s;m/5
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	request_period: 600,
            	metadata: 'http://169.254.169.254/latest/',
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', 'instance_id'].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;
            	},
            
            	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, instance_id) {
            		var metrics_list = [
            			'StatusCheckFailed:Count',
            			'StatusCheckFailed_Instance:Count',
            			'StatusCheckFailed_System:Count',
            			'CPUUtilization:Percent',
            			'NetworkIn:Bytes',
            			'NetworkOut:Bytes',
            			'NetworkPacketsIn:Count',
            			'NetworkPacketsOut:Count',
            			'DiskReadOps:Count',
            			'DiskWriteOps:Count',
            			'DiskReadBytes:Bytes',
            			'DiskWriteBytes:Bytes',
            			'MetadataNoToken:Count',
            			'CPUCreditUsage:Count',
            			'CPUCreditBalance:Count',
            			'CPUSurplusCreditBalance:Count',
            			'CPUSurplusCreditsCharged:Count',
            			'EBSReadOps:Count',
            			'EBSWriteOps:Count',
            			'EBSReadBytes:Bytes',
            			'EBSWriteBytes:Bytes',
            			'EBSIOBalance %:Percent',
            			'EBSByteBalance %:Percent'
            		];
            
            		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': 'AWS/EC2',
            						'Dimensions': [
            							{
            								'Name': 'InstanceId',
            								'Value': instance_id
            							}
            						]
            					},
            					'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'),
            			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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS EC2 ] Sending request: ' + url);
            		response = request.get(url);
            		Zabbix.log(4, '[ AWS EC2 ] 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) {
            			try {
            				response = JSON.parse(XML.toJson(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.instance_id));
            
            		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));
            
            		if (typeof result !== 'object'
            			|| typeof result.GetMetricDataResponse !== 'object'
            			|| typeof result.GetMetricDataResponse.GetMetricDataResult !== 'object'
            			|| typeof result.GetMetricDataResponse.GetMetricDataResult.MetricDataResults !== 'object') {
            			throw 'Cannot get metrics data from AWS CloudWatch API. Check debug log for more information.';
            		}
            
            		return result.GetMetricDataResponse.GetMetricDataResult.MetricDataResults;
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	return JSON.stringify(AWS.getMetricsData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS EC2 ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: |
            Get instance metrics.
            Full metrics list related to EC2: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.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: instance_id
              value: '{$AWS.EC2.INSTANCE.ID}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: 9ec4650b564c41bca9893eca279a8cc7
          name: 'Get volumes data'
          type: SCRIPT
          key: aws.ec2.get_volumes
          delay: 5m
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	request_period: 600,
            	metadata: 'http://169.254.169.254/latest/',
            
            	getField: function (data, path, val) {
            		var steps = path.split('.');
            		for (var i = 0; i < steps.length; i++) {
            			var step = steps[i];
            			if (typeof data !== 'object' || data === null || typeof data[step] === 'undefined') {
            				if (typeof val === 'undefined') {
            					throw 'Required field was not found: ' + path;
            				}
            				return val
            			}
            			data = data[step];
            		}
            
            		return data;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', 'instance_id'].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'),
            			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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS EBS ] Sending request: ' + url);
            		response = request.get(url);
            		Zabbix.log(4, '[ AWS EBS ] 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) {
            			try {
            				response = JSON.parse(XML.toJson(response));
            			}
            			catch (error) {
            				throw 'Failed to parse response received from AWS CloudWatch API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	getVolumesData: function () {
            		var payload = {
            			'Action': 'DescribeVolumes',
            			'Version': '2016-11-15',
            			'Filter.1.Name': 'attachment.instance-id',
            			'Filter.1.Value': AWS.params.instance_id,
            			'MaxResults': 100
            		},
            			value = [],
            			volumes_list = [];
            
            		while (payload.NextToken !== '') {
            			var result = AWS.getField(AWS.request('GET', AWS.params.region, 'ec2', AWS.prepareParams(payload)), 'DescribeVolumesResponse'),
            				volumes_set = AWS.getField(result, 'volumeSet'),
            				volumes = AWS.getField(volumes_set, 'item', value);
            			volumes_list.push(Array.isArray(volumes) ? volumes : [volumes]);
            			payload.NextToken = result.nextToken || '';
            		}
            		var flattenedData = volumes_list.reduce(function (acc, val) {
            			return acc.concat(val);
            		}, []);
            		return flattenedData;
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	return JSON.stringify(AWS.getVolumesData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS EBS ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: |
            Get volumes attached to instance.
            DescribeVolumes API method: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVolumes.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: instance_id
              value: '{$AWS.EC2.INSTANCE.ID}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: adbe9cd98ffa41dda981c7f4e27a0d3b
          name: 'Metadata: No token'
          type: DEPENDENT
          key: aws.ec2.metadata.no_token
          value_type: FLOAT
          description: |
            The number of times the instance metadata service was successfully accessed using a method that does not use a token.
            This metric is used to determine if there are any processes accessing instance metadata that are using Instance Metadata Service Version 1, which does not use a token.
            If all requests use token-backed sessions, i.e., Instance Metadata Service Version 2, the value is 0.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "MetadataNoToken")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: metadata
        - uuid: 7c264d8d5d934f898f7c745acd429d25
          name: 'Get metrics check'
          type: DEPENDENT
          key: aws.ec2.metrics.check
          value_type: CHAR
          description: 'Check result of the instance metric data has been got correctly.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: c2cf3f875aa14416a108dd05df7b053a
              expression: 'length(last(/AWS EC2 by HTTP/aws.ec2.metrics.check))>0'
              name: 'AWS EC2: Failed to get metrics data'
              priority: WARNING
              description: 'Failed to get CloudWatch metrics for EC2.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 2b16d3c6457842d892d06249a5fcd670
          name: 'Network: Bytes in, rate'
          type: DEPENDENT
          key: aws.ec2.network_in.rate
          value_type: FLOAT
          units: Bps
          description: |
            The number of bytes received on all network interfaces by the instance.
            This metric identifies the volume of incoming network traffic to a single instance.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "NetworkIn")].Values.first().first()'
              error_handler: DISCARD_VALUE
            - type: JAVASCRIPT
              parameters:
                - 'return value / 300;'
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: network
        - uuid: 87fb8b61f115487696f02e50d98996ac
          name: 'Network: Bytes out, rate'
          type: DEPENDENT
          key: aws.ec2.network_out.rate
          value_type: FLOAT
          units: Bps
          description: |
            The number of bytes sent out on all network interfaces by the instance.
            This metric identifies the volume of outgoing network traffic from a single instance.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "NetworkOut")].Values.first().first()'
            - type: JAVASCRIPT
              parameters:
                - 'return value / 300;'
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: network
        - uuid: a6b74493528b486782c4b73e080019e1
          name: 'Network: Packets in, rate'
          type: DEPENDENT
          key: aws.ec2.packets_in.rate
          value_type: FLOAT
          description: |
            The number of packets received on all network interfaces by the instance.
            This metric identifies the volume of incoming traffic in terms of the number of packets on a single instance.
            This metric is available for basic monitoring only.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "NetworkPacketsIn")].Values.first().first()'
              error_handler: DISCARD_VALUE
            - type: JAVASCRIPT
              parameters:
                - 'return value / 300;'
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: network
        - uuid: 5d998e1680af4410b34fa9071bb7db78
          name: 'Network: Packets out, rate'
          type: DEPENDENT
          key: aws.ec2.packets_out.rate
          value_type: FLOAT
          description: |
            The number of packets sent out on all network interfaces by the instance.
            This metric identifies the volume of outgoing traffic in terms of the number of packets on a single instance.
            This metric is available for basic monitoring only.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "NetworkPacketsOut")].Values.first().first()'
              error_handler: DISCARD_VALUE
            - type: JAVASCRIPT
              parameters:
                - 'return value / 300;'
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: network
        - uuid: 30156f76599147eaa5bcd4ca39816bbb
          name: 'Status: Check failed'
          type: DEPENDENT
          key: aws.ec2.status_check_failed
          description: |
            Reports whether the instance has passed both the instance status check and the system status check in the last minute.
            This metric can be either 0 (passed) or 1 (failed).
          valuemap:
            name: 'Status check'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "StatusCheckFailed")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: instance
        - uuid: b373f0994e784caf8f5f39da20d2f5c8
          name: 'Status: Check failed, instance'
          type: DEPENDENT
          key: aws.ec2.status_check_failed_instance
          description: |
            Reports whether the instance has passed the instance status check in the last minute.
            This metric can be either 0 (passed) or 1 (failed).
          valuemap:
            name: 'Status check'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "StatusCheckFailed_Instance")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: instance
          triggers:
            - uuid: 0fdd6b02eea948d3a6c958af7f195dc3
              expression: 'last(/AWS EC2 by HTTP/aws.ec2.status_check_failed_instance)=1'
              name: 'AWS EC2: Instance status check failed'
              priority: AVERAGE
              description: |
                These checks detect problems that require your involvement to repair.
                The following are examples of problems that can cause instance status checks to fail:
                
                Failed system status checks
                Incorrect networking or startup configuration
                Exhausted memory
                Corrupted file system
                Incompatible kernel
              tags:
                - tag: scope
                  value: availability
        - uuid: c7063824e3a74e6fa55ba21ecba35ca1
          name: 'Status: Check failed, system'
          type: DEPENDENT
          key: aws.ec2.status_check_failed_system
          description: |
            Reports whether the instance has passed the system status check in the last minute.
            This metric can be either 0 (passed) or 1 (failed).
          valuemap:
            name: 'Status check'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "StatusCheckFailed_System")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ec2.get_metrics
          tags:
            - tag: component
              value: instance
          triggers:
            - uuid: 723a254ffd72404ea0cc2366ff186c1c
              expression: 'last(/AWS EC2 by HTTP/aws.ec2.status_check_failed_system)=1'
              name: 'AWS EC2: System status check failed'
              priority: AVERAGE
              description: |
                These checks detect underlying problems with your instance that require AWS involvement to repair.
                The following are examples of problems that can cause system status checks to fail:
                
                Loss of network connectivity
                Loss of system power
                Software issues on the physical host
                Hardware issues on the physical host that impact network reachability
              tags:
                - tag: scope
                  value: availability
        - uuid: 3c819ed899c044ae8455266292f65632
          name: 'Get volumes info check'
          type: DEPENDENT
          key: aws.ec2.volumes.check
          value_type: CHAR
          description: 'Check result of the volume information has been got correctly.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.ec2.get_volumes
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: 844fb22685804fe7894af7c64b420824
              expression: 'length(last(/AWS EC2 by HTTP/aws.ec2.volumes.check))>0'
              name: 'AWS EC2: Failed to get volumes info'
              priority: WARNING
              description: 'Failed to get CloudWatch volumes for EC2.'
              tags:
                - tag: scope
                  value: availability
      discovery_rules:
        - uuid: 318c50196d2b442e9b702f63e70c0820
          name: 'Instance Alarms discovery'
          type: DEPENDENT
          key: aws.ec2.alarms.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.EC2.LLD.FILTER.ALARM_NAME.MATCHES}'
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.EC2.LLD.FILTER.ALARM_NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#ALARM_SERVICE_NAMESPACE}'
                value: '{$AWS.EC2.LLD.FILTER.ALARM_SERVICE_NAMESPACE.MATCHES}'
              - macro: '{#ALARM_SERVICE_NAMESPACE}'
                value: '{$AWS.EC2.LLD.FILTER.ALARM_SERVICE_NAMESPACE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery instance and attached EBS volumes alarms.'
          item_prototypes:
            - uuid: 6294e05dc170431bb3af2caf1ccf6d40
              name: '[{#ALARM_NAME}]: Get metrics'
              type: DEPENDENT
              key: 'aws.ec2.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.ec2.get_alarms
              tags:
                - tag: component
                  value: raw
            - uuid: 87a163166aed40b786785b64122ab365
              name: '[{#ALARM_NAME}]: State'
              type: DEPENDENT
              key: 'aws.ec2.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.ec2.alarm.get_metrics["{#ALARM_NAME}"]'
              tags:
                - tag: component
                  value: alarms
              trigger_prototypes:
                - uuid: be1301d97b5a47cc81dd6c2b76349f5d
                  expression: 'last(/AWS EC2 by HTTP/aws.ec2.alarm.state["{#ALARM_NAME}"])=1'
                  name: 'AWS EC2: [{#ALARM_NAME}] has ''Insufficient data'' state'
                  priority: INFO
                  description: 'Either the alarm has just started, the metric is not available, or not enough data is available for the metric to determine the alarm state.'
                  tags:
                    - tag: scope
                      value: notice
            - uuid: 92a33b49f010464db7e6c7ef586240e9
              name: '[{#ALARM_NAME}]: State reason'
              type: DEPENDENT
              key: 'aws.ec2.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.ec2.alarm.get_metrics["{#ALARM_NAME}"]'
              tags:
                - tag: component
                  value: alarms
          trigger_prototypes:
            - uuid: 93813bd6aaf14fcb84068cb2c2e5d47e
              expression: 'last(/AWS EC2 by HTTP/aws.ec2.alarm.state["{#ALARM_NAME}"])=2 and length(last(/AWS EC2 by HTTP/aws.ec2.alarm.state_reason["{#ALARM_NAME}"]))>0'
              name: 'AWS EC2: [{#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.ec2.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: 6cf7fc98fea44b0789a5aaa837042699
          name: 'Instance Volumes discovery'
          type: DEPENDENT
          key: aws.ec2.volumes.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#VOLUME_TYPE}'
                value: '{$AWS.EC2.LLD.FILTER.VOLUME_TYPE.MATCHES}'
              - macro: '{#VOLUME_TYPE}'
                value: '{$AWS.EC2.LLD.FILTER.VOLUME_TYPE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery attached EBS volumes.'
          item_prototypes:
            - uuid: cc0ece769d954bb590fb1a1a3d20e559
              name: '[{#VOLUME_ID}]: Attachment state'
              type: DEPENDENT
              key: 'aws.ec2.ebs.attachment_status["{#VOLUME_ID}"]'
              description: 'The attachment state of the volume. Possible values: 0 (attaching), 1 (attached), 2 (detaching).'
              valuemap:
                name: 'Volume attachment state'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.attachmentSet..[?(@.instanceId == "{$AWS.EC2.INSTANCE.ID}")].status.first()'
                  error_handler: DISCARD_VALUE
                - type: JAVASCRIPT
                  parameters:
                    - |
                      var state = ['attaching', 'attached', 'detaching'];
                      
                      return state.indexOf(value.trim()) === -1 ? 255 : state.indexOf(value.trim());
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'aws.ec2.ebs.get_volume["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
            - uuid: 639e7ddcac6345239fa27549ad35e799
              name: '[{#VOLUME_ID}]: Attachment time'
              type: DEPENDENT
              key: 'aws.ec2.ebs.attachment_time["{#VOLUME_ID}"]'
              value_type: CHAR
              description: 'The time stamp when the attachment initiated.'
              valuemap:
                name: 'Volume attachment state'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.attachmentSet..[?(@.instanceId == "{$AWS.EC2.INSTANCE.ID}")].attachTime.first()'
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'aws.ec2.ebs.get_volume["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
            - uuid: 2df96e6c726e40c6a257c00ae26e8902
              name: '[{#VOLUME_ID}]: Create time'
              type: DEPENDENT
              key: 'aws.ec2.ebs.create_time["{#VOLUME_ID}"]'
              value_type: CHAR
              description: 'The time stamp when volume creation was initiated.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.createTime
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'aws.ec2.ebs.get_volume["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
            - uuid: 141205eac3e4437d824794f8e6c76e90
              name: '[{#VOLUME_ID}]: Device'
              type: DEPENDENT
              key: 'aws.ec2.ebs.device["{#VOLUME_ID}"]'
              value_type: CHAR
              description: 'The device name specified in the block device mapping (for example, /dev/sda1).'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.attachmentSet..[?(@.instanceId == "{$AWS.EC2.INSTANCE.ID}")].device.first()'
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'aws.ec2.ebs.get_volume["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
            - uuid: 6145bf692ea0469eb5583485b6622a59
              name: '[{#VOLUME_ID}]: Get volume data'
              type: DEPENDENT
              key: 'aws.ec2.ebs.get_volume["{#VOLUME_ID}"]'
              history: '0'
              value_type: TEXT
              description: 'Get data of the "{#VOLUME_ID}" volume.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.volumeId == "{#VOLUME_ID}")].first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.ec2.get_volumes
              tags:
                - tag: component
                  value: raw
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
            - uuid: 95add92252e24ab8b596c539d8090f3d
              name: '[{#VOLUME_ID}]: Status'
              type: DEPENDENT
              key: 'aws.ec2.ebs.status["{#VOLUME_ID}"]'
              description: |
                The state of the volume.
                Possible values: 0 (creating), 1 (available), 2 (in-use), 3 (deleting), 4 (deleted), 5 (error).
              valuemap:
                name: 'Volume status'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.status
                  error_handler: DISCARD_VALUE
                - type: JAVASCRIPT
                  parameters:
                    - |
                      var state = ['creating', 'available', 'in-use', 'deleting', 'deleted', 'error'];
                      
                      return state.indexOf(value.trim()) === -1 ? 255 : state.indexOf(value.trim());
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'aws.ec2.ebs.get_volume["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
              trigger_prototypes:
                - uuid: 2d4de438bdaa49b2930496ce6ddbe52d
                  expression: 'last(/AWS EC2 by HTTP/aws.ec2.ebs.status["{#VOLUME_ID}"])=5'
                  name: 'AWS EC2: Volume [{#VOLUME_ID}] has ''error'' state'
                  priority: WARNING
                  tags:
                    - tag: scope
                      value: availability
            - uuid: fd10966f674e430a9dd70b148dcfa002
              name: '[{#VOLUME_ID}]: Burst balance'
              type: DEPENDENT
              key: 'aws.ec2.ebs.volume.burst_balance["{#VOLUME_ID}"]'
              value_type: FLOAT
              units: '%'
              description: |
                Used with General Purpose SSD (gp2), Throughput Optimized HDD (st1), and Cold HDD (sc1) volumes only.
                Provides information about the percentage of I/O credits (for gp2) or throughput credits (for st1 and sc1) remaining in the burst bucket.
                Data is reported to CloudWatch only when the volume is active. If the volume is not attached, no data is reported.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "BurstBalance")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ec2.get_ebs_metrics["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
              trigger_prototypes:
                - uuid: 9b2f5687020c4a5987c1b1b35a57d8b9
                  expression: 'max(/AWS EC2 by HTTP/aws.ec2.ebs.volume.burst_balance["{#VOLUME_ID}"],5m)<{$AWS.EBS.BURST.CREDIT.BALANCE.MIN.WARN}'
                  name: 'AWS EC2: Burst balance is too low'
                  event_name: 'AWS EC2: Burst balance is too low (less {$AWS.EBS.BURST.CREDIT.BALANCE.MIN.WARN}% for 5m)'
                  opdata: 'Current value: {ITEM.LASTVALUE1}'
                  priority: WARNING
                  tags:
                    - tag: scope
                      value: capacity
            - uuid: 8b936cef38294799a6826764eae68850
              name: '[{#VOLUME_ID}]: Consumed Read/Write, ops'
              type: DEPENDENT
              key: 'aws.ec2.ebs.volume.consumed_read_write_ops["{#VOLUME_ID}"]'
              value_type: FLOAT
              description: |
                Used with Provisioned IOPS SSD volumes only.
                The total amount of read and write operations (normalized to 256K capacity units) consumed in a specified period of time.
                I/O operations that are smaller than 256K each count as 1 consumed IOPS. I/O operations that are larger than 256K are counted in 256K capacity units.
                For example, a 1024K I/O would count as 4 consumed IOPS.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "VolumeConsumedReadWriteOps")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ec2.get_ebs_metrics["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
            - uuid: 5476d32c036d49588238cb2d2a4d652f
              name: '[{#VOLUME_ID}]: Idle time'
              type: DEPENDENT
              key: 'aws.ec2.ebs.volume.idle_time["{#VOLUME_ID}"]'
              value_type: FLOAT
              units: s
              description: |
                This metric is not supported with Multi-Attach enabled volumes.
                The total number of seconds in a specified period of time when no read or write operations were submitted.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "VolumeIdleTime")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ec2.get_ebs_metrics["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
            - uuid: 4dbb00e53cd84b9f88c44c765e73bd85
              name: '[{#VOLUME_ID}]: Queue length'
              type: DEPENDENT
              key: 'aws.ec2.ebs.volume.queue_length["{#VOLUME_ID}"]'
              value_type: FLOAT
              description: 'The number of read and write operation requests waiting to be completed in a specified period of time.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "VolumeQueueLength")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ec2.get_ebs_metrics["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
            - uuid: 7313a503be27469ea82733ed965b57e4
              name: '[{#VOLUME_ID}]: Read, bytes'
              type: DEPENDENT
              key: 'aws.ec2.ebs.volume.read_bytes["{#VOLUME_ID}"]'
              value_type: FLOAT
              units: Bps
              description: |
                Provides information on the read operations in a specified period of time.
                The average size of each read operation during the period, except on volumes attached to a Nitro-based instance, where the average represents the average over the specified period.
                For Xen instances, data is reported only when there is read activity on the volume.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "VolumeReadBytes")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ec2.get_ebs_metrics["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
            - uuid: 13d3dce70956402c945421c87e8eb784
              name: '[{#VOLUME_ID}]: Read, ops'
              type: DEPENDENT
              key: 'aws.ec2.ebs.volume.read_ops["{#VOLUME_ID}"]'
              value_type: FLOAT
              units: Ops
              description: 'The total number of read operations in a specified period of time. Note: read operations are counted on completion.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "VolumeReadOps")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ec2.get_ebs_metrics["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
            - uuid: 8d0b610ac0e3479a921720ef623ef896
              name: '[{#VOLUME_ID}]: Throughput, pct'
              type: DEPENDENT
              key: 'aws.ec2.ebs.volume.throughput_percentage["{#VOLUME_ID}"]'
              value_type: FLOAT
              units: '%'
              description: |
                This metric is not supported with Multi-Attach enabled volumes.
                Used with Provisioned IOPS SSD volumes only. The percentage of I/O operations per second (IOPS) delivered of the total IOPS provisioned for an Amazon EBS volume.
                Provisioned IOPS SSD volumes deliver their provisioned performance 99.9 percent of the time.
                During a write, if there are no other pending I/O requests in a minute, the metric value will be 100 percent.
                Also, a volume's I/O performance may become degraded temporarily due to an action you have taken (for example, creating a snapshot of a volume during peak usage, running the volume on a non-EBS-optimized instance, or accessing data on the volume for the first time).
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "VolumeThroughputPercentage")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ec2.get_ebs_metrics["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
            - uuid: 58163c98e1b943ceae5fcb52ff85dcfd
              name: '[{#VOLUME_ID}]: Read time, total'
              type: DEPENDENT
              key: 'aws.ec2.ebs.volume.total_read_time["{#VOLUME_ID}"]'
              value_type: FLOAT
              units: s
              description: |
                This metric is not supported with Multi-Attach enabled volumes.
                The total number of seconds spent by all read operations that completed in a specified period of time.
                If multiple requests are submitted at the same time, this total could be greater than the length of the period.
                For example, for a period of 1 minutes (60 seconds): if 150 operations completed during that period, and each operation took 1 second, the value would be 150 seconds.
                For Xen instances, data is reported only when there is read activity on the volume.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "VolumeTotalReadTime")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ec2.get_ebs_metrics["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
            - uuid: 264a8f7df9e64d219082d5239b90cdf3
              name: '[{#VOLUME_ID}]: Write time, total'
              type: DEPENDENT
              key: 'aws.ec2.ebs.volume.total_write_time["{#VOLUME_ID}"]'
              value_type: FLOAT
              units: s
              description: |
                This metric is not supported with Multi-Attach enabled volumes.
                The total number of seconds spent by all write operations that completed in a specified period of time.
                If multiple requests are submitted at the same time, this total could be greater than the length of the period.
                For example, for a period of 1 minute (60 seconds): if 150 operations completed during that period, and each operation took 1 second, the value would be 150 seconds.
                For Xen instances, data is reported only when there is write activity on the volume.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "VolumeTotalWriteTime")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ec2.get_ebs_metrics["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
            - uuid: 459900740e784ca9ba7a8baf5b95734e
              name: '[{#VOLUME_ID}]: Write, bytes'
              type: DEPENDENT
              key: 'aws.ec2.ebs.volume.write_bytes["{#VOLUME_ID}"]'
              value_type: FLOAT
              units: Bps
              description: |
                Provides information on the write operations in a specified period of time.
                The average size of each write operation during the period, except on volumes attached to a Nitro-based instance, where the average represents the average over the specified period.
                For Xen instances, data is reported only when there is write activity on the volume.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "VolumeWriteBytes")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ec2.get_ebs_metrics["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
            - uuid: 7216494987dc45f59fc3a4b9100e4159
              name: '[{#VOLUME_ID}]: Write, ops'
              type: DEPENDENT
              key: 'aws.ec2.ebs.volume.write_ops["{#VOLUME_ID}"]'
              value_type: FLOAT
              units: Ops
              description: 'The total number of write operations in a specified period of time. Note: write operations are counted on completion.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "VolumeWriteOps")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ec2.get_ebs_metrics["{#VOLUME_ID}"]'
              tags:
                - tag: component
                  value: volumes
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
            - uuid: 8b3b008f7f65408fbd49e46186b01cfb
              name: '[{#VOLUME_ID}]: Get metrics'
              type: SCRIPT
              key: 'aws.ec2.get_ebs_metrics["{#VOLUME_ID}"]'
              delay: 0s;m/5
              history: '0'
              value_type: TEXT
              params: |
                var AWS = {
                	params: {},
                	request_period: 600,
                	metadata: 'http://169.254.169.254/latest/',
                
                	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;
                	},
                
                	getRoleBaseCredentials: function () {
                		AWS.params['auth_type'] = 'role_base';
                		var request = new HttpRequest();
                		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
                			request.setProxy(AWS.params.proxy);
                		}
                		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
                		var token = request.put(AWS.metadata + 'api/token');
                
                		if (request.getStatus() !== 200 || token === null || token === '') {
                			throw 'Error getting IMDSv2 session token.';
                		}
                		request.addHeader('X-aws-ec2-metadata-token: ' + token);
                		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
                
                		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
                			throw 'Error getting security credentials from instance metadata. Role not found.';
                		}
                
                		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
                			};
                			AWS.params[field] = credentials[field];
                		});
                	},
                
                	setParams: function (params) {
                		AWS.params['proxy'] = params.proxy;
                		switch (AWS.getField(params, 'auth_type')) {
                			case 'role_base':
                				AWS.getRoleBaseCredentials();
                				break;
                			case 'assume_role':
                				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
                					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
                				}
                				if (params.metadata_auth === 'true') {
                					AWS.getRoleBaseCredentials();
                					AWS.params['SessionToken'] = AWS.params['Token'];
                					AWS.params['auth_type'] = 'assume_role_metadata';
                
                					['sts_region', 'role_arn'].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];
                					});
                				}
                
                				if (params.metadata_auth === 'false') {
                					AWS.params['auth_type'] = 'assume_role';
                
                					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
                					});
                				}
                
                				const role_arn_regex = /role\/(.+)$/;
                				const match = AWS.params.role_arn.match(role_arn_regex);
                				if (!match) {
                					throw 'Invalid role ARN format.';
                				}
                
                				const payload = {
                					'Action': 'AssumeRole',
                					'Version': '2011-06-15',
                					'RoleArn': AWS.params.role_arn,
                					'RoleSessionName': match[1] + 'Session',
                				};
                
                				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
                
                				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
                					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
                						throw 'Required credentials are not set: "' + field + '".';
                					};
                					AWS.params[field] = credentials[field];
                				});
                				break;
                			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', 'volume_id'].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;
                	},
                
                	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, volume_id) {
                		var metrics_list = [
                			'VolumeReadBytes:Bytes',
                			'VolumeWriteBytes:Bytes',
                			'VolumeReadOps:Count',
                			'VolumeWriteOps:Count',
                			'VolumeTotalReadTime:Seconds',
                			'VolumeTotalWriteTime:Seconds',
                			'VolumeIdleTime:Seconds',
                			'VolumeQueueLength:Count',
                			'VolumeThroughputPercentage:Percent',
                			'VolumeConsumedReadWriteOps:Count',
                			'BurstBalance:Percent'
                		];
                
                		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': 'AWS/EBS',
                						'Dimensions': [
                							{
                								'Name': 'VolumeId',
                								'Value': volume_id
                							}
                						]
                					},
                					'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'),
                			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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
                			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
                		}
                
                		Zabbix.log(4, '[ AWS EBS ] Sending request: ' + url);
                		response = request.get(url);
                		Zabbix.log(4, '[ AWS EBS ] 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.volume_id));
                
                		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));
                
                		if (typeof result !== 'object'
                			|| typeof result.GetMetricDataResponse !== 'object'
                			|| typeof result.GetMetricDataResponse.GetMetricDataResult !== 'object'
                			|| typeof result.GetMetricDataResponse.GetMetricDataResult.MetricDataResults !== 'object') {
                			throw 'Cannot get metrics data from AWS CloudWatch API. Check debug log for more information.';
                		}
                
                		return result.GetMetricDataResponse.GetMetricDataResult.MetricDataResults;
                	}
                };
                
                try {
                	AWS.setParams(JSON.parse(value));
                
                	return JSON.stringify(AWS.getMetricsData());
                }
                catch (error) {
                	error += (String(error).endsWith('.')) ? '' : '.';
                	Zabbix.log(3, '[ AWS EBS ] ERROR: ' + error);
                
                	return JSON.stringify({ 'error': error });
                }
              description: |
                Get metrics of EBS volume.
                Full metrics list related to EBS: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using_cloudwatch_ebs.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: metadata_auth
                  value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
                - name: proxy
                  value: '{$AWS.PROXY}'
                - name: region
                  value: '{$AWS.REGION}'
                - name: role_arn
                  value: '{$AWS.ASSUME.ROLE.ARN}'
                - name: SecretAccessKey
                  value: '{$AWS.SECRET.ACCESS.KEY}'
                - name: sts_region
                  value: '{$AWS.STS.REGION}'
                - name: volume_id
                  value: '{#VOLUME_ID}'
              tags:
                - tag: component
                  value: raw
                - tag: type
                  value: '{#VOLUME_TYPE}'
                - tag: volume
                  value: '{#VOLUME_ID}'
          graph_prototypes:
            - uuid: dbf87c66b9034e1ab40f3a2d4adb1a5a
              name: 'AWS EBS: [{#VOLUME_ID}]: Volume read/write bytes'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'AWS EC2 by HTTP'
                    key: 'aws.ec2.ebs.volume.write_bytes["{#VOLUME_ID}"]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'AWS EC2 by HTTP'
                    key: 'aws.ec2.ebs.volume.read_bytes["{#VOLUME_ID}"]'
            - uuid: 97faf8177efd46f2b90a7078e532f623
              name: 'AWS EBS: [{#VOLUME_ID}]: Volume read/write ops'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'AWS EC2 by HTTP'
                    key: 'aws.ec2.ebs.volume.write_ops["{#VOLUME_ID}"]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'AWS EC2 by HTTP'
                    key: 'aws.ec2.ebs.volume.read_ops["{#VOLUME_ID}"]'
            - uuid: c27e794ff80a4335874ae9b58c8ce6b8
              name: 'AWS EBS: [{#VOLUME_ID}]: Volume read/write time'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'AWS EC2 by HTTP'
                    key: 'aws.ec2.ebs.volume.total_write_time["{#VOLUME_ID}"]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'AWS EC2 by HTTP'
                    key: 'aws.ec2.ebs.volume.total_read_time["{#VOLUME_ID}"]'
          master_item:
            key: aws.ec2.get_volumes
          preprocessing:
            - type: JAVASCRIPT
              parameters:
                - |
                  var result = [];
                  var volumes = JSON.parse(value);
                  
                  volumes.forEach(function(volume) {
                  
                   result.push({
                  '{#VOLUME_ID}': volume.volumeId,
                  '{#VOLUME_TYPE}': volume.volumeType,
                    });
                  });
                  
                  return JSON.stringify(result);
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: computing
        - tag: target
          value: aws
        - tag: target
          value: ec2
      macros:
        - macro: '{$AWS.ACCESS.KEY.ID}'
          description: 'Access key ID.'
          config:
            type: TEXT
            priority: '3'
            label: 'Access key ID'
            description: 'Access keys are long-term credentials for an IAM user.'
        - macro: '{$AWS.ASSUME.ROLE.ARN}'
          description: 'ARN assume role; add when using the `assume_role` authorization method.'
          config:
            type: TEXT
            priority: '5'
            label: 'ARN assume role'
            description: 'The ARN of the role to assume when using the assume_role authorization method.'
        - macro: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
          value: 'false'
          description: 'Add when using the `assume_role` through instance metadata or environment authorization method. Possible values: `false`, `true`.'
          config:
            type: LIST
            priority: '2'
            label: 'Assume Role Metadata Authorization'
            description: 'Chose `True` when use instance metadata service to retrieve role credentials.'
            options:
              - value: 'false'
                text: 'False'
              - value: 'true'
                text: 'True'
        - macro: '{$AWS.AUTH_TYPE}'
          value: access_key
          description: 'Authorization method. Possible values: `access_key`, `assume_role`, `role_base`.'
          config:
            type: LIST
            priority: '1'
            label: 'Authorization method'
            description: 'Authorization method used to access AWS.'
            required: 'YES'
            options:
              - value: access_key
                text: 'Access key'
              - value: assume_role
                text: AssumeRole
              - value: role_base
                text: 'Role-based access'
        - macro: '{$AWS.EBS.BURST.CREDIT.BALANCE.MIN.WARN}'
          value: '20'
          description: 'Minimum percentage of Byte credits remaining for trigger expression.'
          config:
            type: TEXT
            priority: '21'
            section_name: Thresholds
            label: 'Minimum Burst Credit Balance Warning'
            description: 'The minimum percentage of Burst credits before a warning is triggered.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.EBS.BYTE.CREDIT.BALANCE.MIN.WARN}'
          value: '20'
          description: 'Minimum percentage of Byte credits remaining for trigger expression.'
          config:
            type: TEXT
            priority: '20'
            section_name: Thresholds
            label: 'Minimum Byte Credit Balance Warning'
            description: 'The minimum percentage of Byte credits before a warning is triggered.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.EBS.IO.CREDIT.BALANCE.MIN.WARN}'
          value: '20'
          description: 'Minimum percentage of I/O credits remaining for trigger expression.'
          config:
            type: TEXT
            priority: '19'
            section_name: Thresholds
            label: 'Minimum I/O Credit Balance Warning'
            description: 'The minimum percentage of I/O credits before a warning is triggered.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.EC2.CPU.CREDIT.BALANCE.MIN.WARN}'
          value: '50'
          description: 'Minimum number of free earned CPU credits for trigger expression.'
          config:
            type: TEXT
            priority: '17'
            section_name: Thresholds
            label: 'Minimum CPU Credit Balance Warning'
            description: 'The minimum number of CPU credits before a warning is triggered.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.EC2.CPU.CREDIT.SURPLUS.BALANCE.MAX.WARN}'
          value: '100'
          description: 'Maximum number of spent CPU Surplus credits for trigger expression.'
          config:
            type: TEXT
            priority: '18'
            section_name: Thresholds
            label: 'Maximum Surplus CPU Credit Balance Warning'
            description: 'The maximum number of surplus CPU credits before a warning is triggered.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.EC2.CPU.UTIL.WARN.MAX}'
          value: '85'
          description: 'The warning threshold of the CPU utilization expressed in %.'
          config:
            type: TEXT
            priority: '16'
            section_name: Thresholds
            label: 'CPU Utilization Warning Threshold'
            description: 'The maximum CPU utilization percentage before a warning is triggered. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.EC2.INSTANCE.ID}'
          description: 'EC2 instance ID.'
          config:
            type: TEXT
            priority: '9'
            label: 'EC2 Instance ID'
            description: 'The ID of the EC2 instance to monitor.'
        - macro: '{$AWS.EC2.LLD.FILTER.ALARM_NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable alarms by name.'
          config:
            type: TEXT
            priority: '14'
            section_name: Filters
            label: 'Alarm Name Filter (Matches)'
            description: 'A regex to match discoverable alarm names.'
        - macro: '{$AWS.EC2.LLD.FILTER.ALARM_NAME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered alarms by name.'
          config:
            type: TEXT
            priority: '15'
            section_name: Filters
            label: 'Alarm Name Filter (Not Matches)'
            description: 'A regex to exclude certain alarm names from discovery.'
        - macro: '{$AWS.EC2.LLD.FILTER.ALARM_SERVICE_NAMESPACE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable alarms by namespace.'
          config:
            type: TEXT
            priority: '12'
            section_name: Filters
            label: 'Alarm Namespace Filter (Matches)'
            description: 'A regex to match discoverable alarm namespaces.'
        - macro: '{$AWS.EC2.LLD.FILTER.ALARM_SERVICE_NAMESPACE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered alarms by namespace.'
          config:
            type: TEXT
            priority: '13'
            section_name: Filters
            label: 'Alarm Namespace Filter (Not Matches)'
            description: 'A regex to exclude certain alarm namespaces from discovery.'
        - macro: '{$AWS.EC2.LLD.FILTER.VOLUME_TYPE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable volumes by type.'
          config:
            type: TEXT
            priority: '10'
            section_name: Filters
            label: 'Volume Type Filter (Matches)'
            description: 'A regex to match discoverable volume types.'
        - macro: '{$AWS.EC2.LLD.FILTER.VOLUME_TYPE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered volumes by type.'
          config:
            type: TEXT
            priority: '11'
            section_name: Filters
            label: 'Volume Type Filter (Not Matches)'
            description: 'A regex to exclude certain volume types from discovery.'
        - macro: '{$AWS.PROXY}'
          description: 'Sets HTTP proxy value. If this macro is empty then no proxy is used.'
          config:
            type: TEXT
            priority: '8'
            section_name: Other
            label: 'HTTP Proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AWS.REGION}'
          value: us-west-1
          description: 'Amazon EC2 Region code.'
          config:
            type: TEXT
            priority: '6'
            label: 'AWS Region'
            description: 'The AWS region where your EC2 instances are located.'
        - macro: '{$AWS.SECRET.ACCESS.KEY}'
          type: SECRET_TEXT
          description: 'Secret access key.'
          config:
            type: TEXT
            priority: '4'
            label: 'Secret access key'
            description: 'Secret access key can be retrieved only at the time you create it.'
        - macro: '{$AWS.STS.REGION}'
          value: us-east-1
          description: 'Region used in assume role request.'
          config:
            type: TEXT
            priority: '7'
            label: 'STS Region'
            description: 'The AWS region for the assume role request.'
      valuemaps:
        - uuid: 50b7fdfdf6de41f4b4b210a07c10cd77
          name: 'Alarm state'
          mappings:
            - value: '0'
              newvalue: OK
            - value: '1'
              newvalue: 'Insufficient data'
            - value: '2'
              newvalue: Alarm
            - value: '255'
              newvalue: Unknown
        - uuid: d59e4f0c6aaa40bcb5f504f6743d9201
          name: 'Status check'
          mappings:
            - value: '0'
              newvalue: Passed
            - value: '1'
              newvalue: Failed
        - uuid: cf0267337f284182a43db45d823824b7
          name: 'Volume attachment state'
          mappings:
            - value: '0'
              newvalue: Attaching
            - value: '1'
              newvalue: Attached
            - value: '2'
              newvalue: Detaching
            - value: '255'
              newvalue: Unknown
        - uuid: 4f31d29791b94e37b065f790609c50b5
          name: 'Volume status'
          mappings:
            - value: '0'
              newvalue: Creating
            - value: '1'
              newvalue: Available
            - value: '2'
              newvalue: In-use
            - value: '3'
              newvalue: Deleting
            - value: '4'
              newvalue: Deleted
            - value: '5'
              newvalue: Error
            - value: '255'
              newvalue: Unknown
    - uuid: 5e225ad1c2cc4d0bbf75586e7bf8871b
      template: 'AWS ECS Serverless Cluster by HTTP'
      name: 'AWS ECS Serverless Cluster by HTTP'
      description: |
        The template gets AWS ECS Serverless 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"
      wizard_ready: 'YES'
      readme: |
        ## Overview
        
        The template to monitor AWS ECS Serverless Cluster by HTTP via Zabbix that works without any external scripts.
        Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
        
        **Note:** This template uses the GetMetricData CloudWatch API calls to list and retrieve metrics.
        For more information, please refer to the [CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) page.
        
        Additional information about the metrics and used API methods:
        
        * [Full metrics list related to ECS](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-metrics-ECS.html)
        * [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
        
        ## Setup
        
        The template gets AWS ECS metrics and uses the script item to make HTTP requests to the CloudWatch API.
        Before using the template, you need to create an IAM policy for the Zabbix role in your AWS account with the necessary permissions.
        
        ### Required Permissions
        Add the following required permissions to your Zabbix IAM policy in order to collect Amazon ECS metrics.
        
        ```json
        {
            "Version":"2012-10-17",
            "Statement":[
                {
                  "Action":[
                      "cloudwatch:DescribeAlarms",
                      "cloudwatch:GetMetricData",
                      "ecs:ListServices"
                  ],
                  "Effect":"Allow",
                  "Resource":"*"
                }
            ]
          }
        ```
        
        ### Access Key Authorization
        
        If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
        
        1. Create an IAM user with programmatic access.
        2. Attach the required policy to the IAM user.
        3. Generate an access key and secret key.
        4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
        
        ### Assume role authorization
        For using assume role authorization, add the appropriate permissions to the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "sts:AssumeRole",
                    "Resource": "arn:aws:iam::{Account}:user/{UserName}"
                },
                {
                    "Effect": "Allow",
                    "Action": [
                        "cloudwatch:DescribeAlarms",
                        "cloudwatch:GetMetricData",
                        "ecs:ListServices"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        
        #### Trust Relationships for Assume Role Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "AWS": "arn:aws:iam::{Account}:user/{UserName}"
              },
              "Action": "sts:AssumeRole"
            }
          ]
        }
        ```
        Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
        
        ### Role-Based Authorization
        If you are using role-based authorization, set the appropriate permissions:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "iam:PassRole",
                    "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
                },
                {
                    "Sid": "VisualEditor1",
                    "Effect": "Allow",
                    "Action": [
                        "cloudwatch:DescribeAlarms",
                        "cloudwatch:GetMetricData",
                        "ecs:ListServices",
                        "ec2:AssociateIamInstanceProfile",
                        "ec2:ReplaceIamInstanceProfileAssociation"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        #### Trust Relationships for Role-Based Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": [
                            "ec2.amazonaws.com"
                        ]
                    },
                    "Action": [
                        "sts:AssumeRole"
                    ]
                }
            ]
        }
        ```
        
        **Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
        
        Set the following host wizard configuration fields `Authorization method`, `AWS Region`, `ECS cluster name`.
        
        For more information about managing access keys, see [official documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).
      vendor:
        name: Zabbix
        version: 8.0-4
      groups:
        - name: Templates/Cloud
      items:
        - uuid: eb064f2ac4f54a5baf05940fc58e651f
          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: 76b9777749a041049faaa469daf82c4e
              expression: 'length(last(/AWS ECS Serverless Cluster by HTTP/aws.ecs.alarms.check))>0'
              name: 'AWS ECS Serverless: Failed to get alarms data'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Failed to get CloudWatch alarms for ECS Cluster.'
              tags:
                - tag: scope
                  value: availability
        - uuid: fe542fdbef9d4889a7443ee761a46119
          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: bbfd5c05bd5f49ec984d849b6d45dfdd
          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: d8b5d12b4c6b4b2386fe2540dc387fa7
              expression: 'min(/AWS ECS Serverless Cluster by HTTP/aws.ecs.cpu_utilization,15m)>{$AWS.ECS.CLUSTER.CPU.UTIL.WARN}'
              name: 'AWS ECS Serverless: High CPU utilization'
              event_name: 'AWS ECS Serverless: 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: 32f0b934b2d14b008780e73371328eac
          name: 'Ephemeral Storage Utilization'
          type: DEPENDENT
          key: aws.ecs.disk.utilization
          value_type: FLOAT
          units: '%'
          description: 'The calculated Disk Utilization.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.DiskUtilization
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: storage
        - uuid: d3d2c2df9fd54d24b4598ec247152ca4
          name: 'Ephemeral Storage Reserved'
          type: DEPENDENT
          key: aws.ecs.ephemeral.storage.reserved
          value_type: FLOAT
          units: B
          description: |
            The number of bytes reserved from ephemeral storage in the resource that is specified by the dimensions that you're using. Ephemeral storage is used for the container root filesystem and any bind mount host volumes defined in the container image and task definition. The amount of ephemeral storage can’t be changed in a running task.
            This metric is only available for tasks that run on Fargate Linux platform version 1.4.0 or later.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.MetricData[?(@.Label == "EphemeralStorageReserved")].Values.first().first()'
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '1073741824'
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: storage
        - uuid: 36556a43a93d436db94685441a12273f
          name: 'Ephemeral Storage Utilized'
          type: DEPENDENT
          key: aws.ecs.ephemeral.storage.utilized
          value_type: FLOAT
          units: B
          description: |
            The number of bytes used from ephemeral storage in the resource that is specified by the dimensions that you're using. Ephemeral storage is used for the container root filesystem and any bind mount host volumes defined in the container image and task definition. The amount of ephemeral storage can’t be changed in a running task.
            This metric is only available for tasks that run on Fargate Linux platform version 1.4.0 or later.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.MetricData[?(@.Label == "EphemeralStorageUtilized")].Values.first().first()'
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '1073741824'
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: storage
        - uuid: ee28426c92874a99b998198a5539599d
          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/',
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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'),
            			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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		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;
            		}
            
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			try {
            				response = JSON.parse(XML.toJson(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: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: 9818272bc51e4848bba7b2863dda9424
          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/',
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload)), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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, 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/, ''),
            			canonical_uri = '/',
            			host = service + '.' + region + '.amazonaws.com',
            			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'),
            			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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		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;
            		}
            
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			try {
            				response = JSON.parse(XML.toJson(response));
            			}
            			catch (error) {
            				throw 'Failed to parse response received from AWS CloudWatch API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	listServices: function () {
            		var payload = {
            			'Action': 'ListServices',
            			'Version': '2014-11-13',
            			'maxResults': 100,
            			'cluster': AWS.params.cluster_name
            		},
            			services = [];
            
            		while (payload.nextToken !== '') {
            			var services_list = AWS.getField(AWS.request('GET', AWS.params.region, 'ecs', AWS.prepareParams(payload)), 'ListServicesResponse.ListServicesResult');
            			payload.nextToken = services_list.nextToken || '';
            			services_arns = AWS.getField(services_list, 'serviceArns');
            
            			for (k in services_arns) {
            				id = services_arns[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];
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            	return JSON.stringify(AWS.listServices());
            }
            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: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: 01f1a371b56e4945b604cd8b396c85f5
          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/',
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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',
            			'EphemeralStorageReserved:Gigabytes',
            			'EphemeralStorageUtilized:Gigabytes'
            		];
            
            		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'),
            			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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		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;
            		}
            
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			try {
            				response = JSON.parse(XML.toJson(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', 'EphemeralStorageReserved', 'EphemeralStorageUtilized'],
            			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);
            		DiskUtilization = Math.abs(obj.EphemeralStorageUtilized * 100 / obj.EphemeralStorageReserved);
            		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: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: 66b7893a750144fa9c02391bc6b4c79c
          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: 2f0d82467a754fada1ab4f38ce2c2c5b
              expression: 'min(/AWS ECS Serverless Cluster by HTTP/aws.ecs.memory_utilization,15m)>{$AWS.ECS.CLUSTER.MEMORY.UTIL.WARN}'
              name: 'AWS ECS Serverless: High memory utilization'
              event_name: 'AWS ECS Serverless: 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: 852512ccdd9e48f9849ac019d94cdf55
          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: 91ce423ddff44f0b8364e6d6470b15c5
              expression: 'length(last(/AWS ECS Serverless Cluster by HTTP/aws.ecs.metrics.check))>0'
              name: 'AWS ECS Serverless: Failed to get metrics data'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Failed to get CloudWatch metrics for ECS Cluster.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 203c0c6607034e79ac9038d65cc4ee54
          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: ff917b212098496e814f259c6bf71146
          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: b7aa2555bbc24d8587f89e39a4929e7e
          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: 81d2ab08f2aa4608921269da28778e76
          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: 8cc32fccef92436eb0aabf7888e43735
          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: a0cee89be68746ad8ad30de7ba1f444c
              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: 7224b197422a4b8583a4a6ce43117153
              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: 78c58e8dddd34d7cbb5a9bdaada6db6d
                  expression: 'last(/AWS ECS Serverless Cluster by HTTP/aws.ecs.alarm.state["{#ALARM_NAME}"])=1'
                  name: 'AWS ECS Serverless: [{#ALARM_NAME}] has ''Insufficient data'' state'
                  priority: INFO
                  description: 'Either the alarm has just started, the metric is not available, or not enough data is available for the metric to determine the alarm state.'
                  tags:
                    - tag: scope
                      value: notice
            - uuid: a45dcc184496489aa4564b290392a0b6
              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: 64c6b0244f5a49f89465595d74b35880
              expression: 'last(/AWS ECS Serverless Cluster by HTTP/aws.ecs.alarm.state["{#ALARM_NAME}"])=2 and length(last(/AWS ECS Serverless Cluster by HTTP/aws.ecs.alarm.state_reason["{#ALARM_NAME}"]))>0'
              name: 'AWS ECS Serverless: [{#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: adc6dcb0deef4aa79f8f39f4c8198871
          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: e098ff8ab20a468ba4a38ff621ff7aa6
              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: 9c0d75d7b6ad40e18afa52cbcde3c2d9
                  expression: 'min(/AWS ECS Serverless Cluster by HTTP/aws.ecs.services.cpu.utilization["{#AWS.ECS.SERVICE.NAME}"],15m)>{$AWS.ECS.CLUSTER.SERVICE.CPU.UTIL.WARN}'
                  name: 'AWS ECS Serverless: [{#AWS.ECS.SERVICE.NAME}]: High CPU utilization'
                  event_name: 'AWS ECS Serverless: [{#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: a1e8143735f246cb9daf660bde09e908
              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: 23f91e8623604201be2e8c194e5f0ba7
              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: 84b099e6e7b243f69a8b840d03b1035e
              name: '[{#AWS.ECS.SERVICE.NAME}]: Ephemeral storage reserved'
              type: DEPENDENT
              key: 'aws.ecs.services.ephemeral.storage.reserved["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: B
              description: |
                The number of bytes reserved from ephemeral storage in the resource that is specified by the dimensions that you're using. Ephemeral storage is used for the container root filesystem and any bind mount host volumes defined in the container image and task definition. The amount of ephemeral storage can’t be changed in a running task.
                This metric is only available for tasks that run on Fargate Linux platform version 1.4.0 or later.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights EphemeralStorageReserved")].Values.first().first()'
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '1073741824'
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: services
                - tag: component
                  value: storage
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: fa0a602c008346318dd2b747ecd3a6cf
              name: '[{#AWS.ECS.SERVICE.NAME}]: Ephemeral storage utilized'
              type: DEPENDENT
              key: 'aws.ecs.services.ephemeral.storage.utilized["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: B
              description: |
                The number of bytes used from ephemeral storage in the resource that is specified by the dimensions that you're using. Ephemeral storage is used for the container root filesystem and any bind mount host volumes defined in the container image and task definition. The amount of ephemeral storage can’t be changed in a running task.
                This metric is only available for tasks that run on Fargate Linux platform version 1.4.0 or later.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights EphemeralStorageUtilized")].Values.first().first()'
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '1073741824'
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: services
                - tag: component
                  value: storage
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 0f80f5477ed04dbfbcb241c06854a6ff
              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/',
                
                	getRoleBaseCredentials: function () {
                		AWS.params['auth_type'] = 'role_base';
                		var request = new HttpRequest();
                		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
                			request.setProxy(AWS.params.proxy);
                		}
                		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
                		var token = request.put(AWS.metadata + 'api/token');
                
                		if (request.getStatus() !== 200 || token === null || token === '') {
                			throw 'Error getting IMDSv2 session token.';
                		}
                		request.addHeader('X-aws-ec2-metadata-token: ' + token);
                		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
                
                		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
                			throw 'Error getting security credentials from instance metadata. Role not found.';
                		}
                
                		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
                			};
                			AWS.params[field] = credentials[field];
                		});
                	},
                
                	setParams: function (params) {
                		AWS.params['proxy'] = params.proxy;
                		switch (AWS.getField(params, 'auth_type')) {
                			case 'role_base':
                				AWS.getRoleBaseCredentials();
                				break;
                			case 'assume_role':
                				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
                					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
                				}
                				if (params.metadata_auth === 'true') {
                					AWS.getRoleBaseCredentials();
                					AWS.params['SessionToken'] = AWS.params['Token'];
                					AWS.params['auth_type'] = 'assume_role_metadata';
                
                					['sts_region', 'role_arn'].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];
                					});
                				}
                
                				if (params.metadata_auth === 'false') {
                					AWS.params['auth_type'] = 'assume_role';
                
                					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
                					});
                				}
                
                				const role_arn_regex = /role\/(.+)$/;
                				const match = AWS.params.role_arn.match(role_arn_regex);
                				if (!match) {
                					throw 'Invalid role ARN format.';
                				}
                
                				const payload = {
                					'Action': 'AssumeRole',
                					'Version': '2011-06-15',
                					'RoleArn': AWS.params.role_arn,
                					'RoleSessionName': match[1] + 'Session',
                				};
                
                				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
                
                				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
                					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
                						throw 'Required credentials are not set: "' + field + '".';
                					};
                					AWS.params[field] = credentials[field];
                				});
                				break;
                			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'),
                			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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
                			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
                		}
                
                		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;
                		}
                
                		try {
                			response = JSON.parse(response);
                		}
                		catch (error) {
                			try {
                				response = JSON.parse(XML.toJson(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: metadata_auth
                  value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
                - name: proxy
                  value: '{$AWS.PROXY}'
                - name: region
                  value: '{$AWS.REGION}'
                - name: role_arn
                  value: '{$AWS.ASSUME.ROLE.ARN}'
                - name: SecretAccessKey
                  value: '{$AWS.SECRET.ACCESS.KEY}'
                - name: service_name
                  value: '{#AWS.ECS.SERVICE.NAME}'
                - name: sts_region
                  value: '{$AWS.STS.REGION}'
              tags:
                - tag: component
                  value: raw
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 869a2921e0e44163b45c18786ea92471
              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: 7146da954a6d40d4ad8aa83ee3bdb1eb
                  expression: 'min(/AWS ECS Serverless Cluster by HTTP/aws.ecs.services.memory.utilization["{#AWS.ECS.SERVICE.NAME}"],15m)>{$AWS.ECS.CLUSTER.SERVICE.MEMORY.UTIL.WARN}'
                  name: 'AWS ECS Serverless: [{#AWS.ECS.SERVICE.NAME}]: High memory utilization'
                  event_name: 'AWS ECS Serverless: [{#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: bd7bbc9699b8404592a8d67b437f1315
              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: a00e917d61a24df4b4f0234643667ad9
              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: 517dd17172554f3bae93ccb030c75c3a
              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: bd99f218853b4f6bac3020d9a7f8a544
              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: e9e3c9ed4ac44d8e8c0f1e3ad55cc114
              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: f2f7feb7a3194221aae8ed71b12e49eb
              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: 4c9ea34655f44192be806b3225a38233
              name: '[{#AWS.ECS.SERVICE.NAME}]: Storage read bytes'
              type: DEPENDENT
              key: 'aws.ecs.services.storage.read.bytes["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: B
              description: 'The number of bytes read from storage in the resource that is specified by the dimensions that you''re using.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights StorageReadBytes")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: services
                - tag: component
                  value: storage
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: a240f6821aab42a8aa97a2263f126356
              name: '[{#AWS.ECS.SERVICE.NAME}]: Storage write bytes'
              type: DEPENDENT
              key: 'aws.ecs.services.storage.write.bytes["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: B
              description: 'The number of bytes written to storage in the resource that is specified by the dimensions that you''re using.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights StorageWriteBytes")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: services
                - tag: component
                  value: storage
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 6e80c7b477b648329480ad2dfb19f282
              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: 2c511d8c02bb47e6954bce0e8d35d713
              name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: CPU Utilization'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2196F3
                  item:
                    host: 'AWS ECS Serverless Cluster by HTTP'
                    key: 'aws.ecs.services.cpu.utilization["{#AWS.ECS.SERVICE.NAME}"]'
            - uuid: 962375e2a79a4b26b8c1f42f008158ae
              name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: Memory Utilization'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2196F3
                  item:
                    host: 'AWS ECS Serverless Cluster by HTTP'
                    key: 'aws.ecs.services.memory.utilization["{#AWS.ECS.SERVICE.NAME}"]'
            - uuid: 0823c8464d1d4f0ba4aef10f02c24cb3
              name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: Network'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'AWS ECS Serverless Cluster by HTTP'
                    key: 'aws.ecs.services.network.rx["{#AWS.ECS.SERVICE.NAME}"]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'AWS ECS Serverless 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: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: containers
        - tag: subclass
          value: deploy
        - tag: subclass
          value: virtualization
        - tag: target
          value: aws
        - tag: target
          value: ecs
      macros:
        - macro: '{$AWS.ACCESS.KEY.ID}'
          description: 'Access key ID.'
          config:
            type: TEXT
            priority: '3'
            label: 'Access key ID'
            description: 'Access keys are long-term credentials for an IAM user.'
        - macro: '{$AWS.ASSUME.ROLE.ARN}'
          description: 'ARN assume role; add when using the `assume_role` authorization method.'
          config:
            type: TEXT
            priority: '5'
            label: 'ARN assume role'
            description: 'The ARN of the role to assume when using the assume_role authorization method.'
        - macro: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
          value: 'false'
          description: 'Add when using the `assume_role` through instance metadata or environment authorization method. Possible values: `false`, `true`.'
          config:
            type: LIST
            priority: '2'
            label: 'Assume Role Metadata Authorization'
            description: 'Chose `True` when use instance metadata service to retrieve role credentials.'
            options:
              - value: 'false'
                text: 'False'
              - value: 'true'
                text: 'True'
        - macro: '{$AWS.AUTH_TYPE}'
          value: access_key
          description: 'Authorization method. Possible values: `access_key`, `assume_role`, `role_base`.'
          config:
            type: LIST
            priority: '1'
            label: 'Authorization method'
            description: 'Authorization method used to access AWS.'
            required: 'YES'
            options:
              - value: access_key
                text: 'Access key'
              - value: assume_role
                text: AssumeRole
              - value: role_base
                text: 'Role-based access'
        - macro: '{$AWS.ECS.CLUSTER.CPU.UTIL.WARN}'
          value: '70'
          description: 'The warning threshold of the cluster CPU utilization expressed in %.'
          config:
            type: TEXT
            priority: '16'
            section_name: Thresholds
            label: 'Cluster CPU Utilization Warning Threshold'
            description: 'The warning threshold for cluster CPU utilization in percentage. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.ECS.CLUSTER.MEMORY.UTIL.WARN}'
          value: '70'
          description: 'The warning threshold of the cluster memory utilization expressed in %.'
          config:
            type: TEXT
            priority: '17'
            section_name: Thresholds
            label: 'Cluster Memory Utilization Warning Threshold'
            description: 'The warning threshold for cluster memory utilization in percentage. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.ECS.CLUSTER.NAME}'
          description: 'ECS cluster name.'
          config:
            type: TEXT
            priority: '9'
            section_name: Filters
            label: 'ECS Cluster Name'
            description: 'The name of the ECS cluster to monitor.'
        - macro: '{$AWS.ECS.CLUSTER.SERVICE.CPU.UTIL.WARN}'
          value: '80'
          description: 'The warning threshold of the cluster service CPU utilization expressed in %.'
          config:
            type: TEXT
            priority: '18'
            section_name: Thresholds
            label: 'Service CPU Utilization Warning Threshold'
            description: 'The warning threshold for service CPU utilization in percentage. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.ECS.CLUSTER.SERVICE.MEMORY.UTIL.WARN}'
          value: '80'
          description: 'The warning threshold of the cluster service memory utilization expressed in %.'
          config:
            type: TEXT
            priority: '19'
            section_name: Thresholds
            label: 'Service Memory Utilization Warning Threshold'
            description: 'The warning threshold for service memory utilization in percentage. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.ECS.LLD.FILTER.ALARM_NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable alarms by name.'
          config:
            type: TEXT
            priority: '10'
            section_name: Filters
            label: 'Alarm Name Filter (Matches)'
            description: 'A regex to filter 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.'
          config:
            type: TEXT
            priority: '11'
            section_name: Filters
            label: 'Alarm Name Filter (Not Matches)'
            description: 'A regex to exclude discovered alarms by name.'
        - macro: '{$AWS.ECS.LLD.FILTER.ALARM_SERVICE_NAMESPACE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable alarms by namespace.'
          config:
            type: TEXT
            priority: '12'
            section_name: Filters
            label: 'Alarm Namespace Filter (Matches)'
            description: 'A regex to filter 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.'
          config:
            type: TEXT
            priority: '13'
            section_name: Filters
            label: 'Alarm Namespace Filter (Not Matches)'
            description: 'A regex to exclude discovered alarms by namespace.'
        - macro: '{$AWS.ECS.LLD.FILTER.SERVICE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable services by name.'
          config:
            type: TEXT
            priority: '14'
            section_name: Filters
            label: 'Service Name Filter (Matches)'
            description: 'A regex to filter discoverable services by name.'
        - macro: '{$AWS.ECS.LLD.FILTER.SERVICE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered services by name.'
          config:
            type: TEXT
            priority: '15'
            section_name: Filters
            label: 'Service Name Filter (Not Matches)'
            description: 'A regex to exclude discovered services by name.'
        - macro: '{$AWS.PROXY}'
          description: 'Sets HTTP proxy value. If this macro is empty then no proxy is used.'
          config:
            type: TEXT
            priority: '8'
            section_name: Other
            label: 'HTTP Proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AWS.REGION}'
          value: us-west-1
          description: 'Amazon ECS Region code.'
          config:
            type: TEXT
            priority: '6'
            label: 'AWS Region'
            description: 'The AWS region where your ECS cluster is located.'
        - macro: '{$AWS.SECRET.ACCESS.KEY}'
          type: SECRET_TEXT
          description: 'Secret access key.'
          config:
            type: TEXT
            priority: '4'
            label: 'Secret access key'
            description: 'Secret access key can be retrieved only at the time you create it.'
        - macro: '{$AWS.STS.REGION}'
          value: us-east-1
          description: 'Region used in assume role request.'
          config:
            type: TEXT
            priority: '7'
            label: 'STS Region'
            description: 'The AWS region for the assume role request.'
      dashboards:
        - uuid: 21cc12db2b0f4289b0660fcf5538b65d
          name: 'Overview AWS ECS Serverless 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 Serverless 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 Serverless Cluster by HTTP'
                        name: 'AWS ECS Cluster: CPU Utilization'
                    - type: STRING
                      name: reference
                      value: AAAAD
                - type: graph
                  'y': '10'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ECS Serverless Cluster by HTTP'
                        name: 'AWS ECS Cluster: Memory Utilization'
                    - type: STRING
                      name: reference
                      value: AAAAC
                - type: graph
                  'y': '15'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ECS Serverless Cluster by HTTP'
                        name: 'AWS ECS Cluster: Disk Utilization'
                    - type: STRING
                      name: reference
                      value: AAAAB
                - type: graph
                  'y': '20'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ECS Serverless 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 Serverless 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 Serverless 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 Serverless Cluster by HTTP'
                        name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: CPU Utilization'
                    - type: STRING
                      name: reference
                      value: AAAAE
                - 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 Serverless Cluster by HTTP'
                        name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: Memory Utilization'
                    - type: STRING
                      name: reference
                      value: AAAAF
                - 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 Serverless Cluster by HTTP'
                        name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: Network'
                    - type: STRING
                      name: reference
                      value: AAAAG
      valuemaps:
        - uuid: 2de56a6f2b004624976a39e7b58ea193
          name: 'Alarm state'
          mappings:
            - value: '0'
              newvalue: OK
            - value: '1'
              newvalue: 'Insufficient data'
            - value: '2'
              newvalue: Alarm
            - value: '255'
              newvalue: Unknown
        - uuid: e49859d7e9b1494181dec88a386b4bb2
          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'
    - uuid: f59c8b4156ec4386a7c724534ddd384d
      template: 'AWS ELB Application Load Balancer by HTTP'
      name: 'AWS ELB Application Load Balancer by HTTP'
      description: |
        The template is designed to monitor AWS ELB Application Load Balancer by HTTP via Zabbix, and it works without any external scripts.
        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"
      wizard_ready: 'YES'
      readme: |
        ## Overview
        
        *Please scroll down for AWS ELB Network Load Balancer by HTTP.*
        
        The template is designed to monitor AWS ELB Application Load Balancer by HTTP via Zabbix, and it works without any external scripts.
        Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
        
        This template uses the GetMetricData CloudWatch API calls to list and retrieve metrics.
        For more information, please refer to the [CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) page.
        
        Additional information about metrics and API methods used in the template:
        * [Full metrics list related to AWS ELB Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html)
        * [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
        * [DescribeTargetGroups API method](https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_DescribeTargetGroups.html)
        
        
        ## Setup
        
        The template gets AWS ELB Application Load Balancer metrics and uses the script item to make HTTP requests to the CloudWatch API.
        
        Before using the template, you need to create an IAM policy with the necessary permissions for the Zabbix role in your AWS account. For more information, visit the [ELB policies page](https://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/elb-api-permissions.html) on the AWS website.
        
        ### Required Permissions
        Add the following required permissions to your Zabbix IAM policy in order to collect AWS ELB Application Load Balancer metrics.
        
        ```json
        {
            "Version":"2012-10-17",
            "Statement":[
                {
                  "Action":[
                      "cloudwatch:DescribeAlarms",
                      "cloudwatch:GetMetricData",
                      "elasticloadbalancing:DescribeTargetGroups"
                  ],
                  "Effect":"Allow",
                  "Resource":"*"
                }
            ]
          }
        ```
        
        ### Access Key Authorization
        
        If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
        
        1. Create an IAM user with programmatic access.
        2. Attach the required policy to the IAM user.
        3. Generate an access key and secret key.
        4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
        
        ### Assume role authorization
        For using assume role authorization, add the appropriate permissions to the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "sts:AssumeRole",
                    "Resource": "arn:aws:iam::{Account}:user/{UserName}"
                },
                {
                    "Effect": "Allow",
                    "Action": [
                        "cloudwatch:DescribeAlarms",
                        "cloudwatch:GetMetricData",
                        "elasticloadbalancing:DescribeTargetGroups"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        
        #### Trust Relationships for Assume Role Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "AWS": "arn:aws:iam::{Account}:user/{UserName}"
              },
              "Action": "sts:AssumeRole"
            }
          ]
        }
        ```
        Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
        
        ### Role-Based Authorization
        If you are using role-based authorization, set the appropriate permissions:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "iam:PassRole",
                    "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
                },
                {
                    "Sid": "VisualEditor1",
                    "Effect": "Allow",
                    "Action": [
                        "cloudwatch:DescribeAlarms",
                        "cloudwatch:GetMetricData",
                        "elasticloadbalancing:DescribeTargetGroups",
                        "ec2:AssociateIamInstanceProfile",
                        "ec2:ReplaceIamInstanceProfileAssociation"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        
        #### Trust Relationships for Role-Based Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": [
                            "ec2.amazonaws.com"
                        ]
                    },
                    "Action": [
                        "sts:AssumeRole"
                    ]
                }
            ]
        }
        ```
        
        **Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
        
        Set the following fields: `Authorization method`, `AWS Region`, and `Load Balancer ARN`.
        
        For more information about managing access keys, see [official AWS documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).
      vendor:
        name: Zabbix
        version: 8.0-3
      groups:
        - name: Templates/Cloud
      items:
        - uuid: cf1a45ea7ad74602b675d1fbe137c53d
          name: 'Active Connection Count'
          type: DEPENDENT
          key: aws.elb.alb.active_connection_count
          description: 'The total number of active concurrent TCP connections from clients to the load balancer and from the load balancer to targets.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ActiveConnectionCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: connections
        - uuid: 4bd5c4e139374a60a42eb86a343f315e
          name: 'Get alarms check'
          type: DEPENDENT
          key: aws.elb.alb.alarms.check
          value_type: CHAR
          description: 'Check that the alarm data has been received correctly.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.elb.alb.get_alarms
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: 3fd832d1a2cc4cff955554cbd8c4b3c7
              expression: 'length(last(/AWS ELB Application Load Balancer by HTTP/aws.elb.alb.alarms.check))>0'
              name: 'AWS ELB ALB: Failed to get alarms data'
              event_name: 'AWS ELB ALB: Failed to get CloudWatch alarms for Application Load Balancer'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Failed to get CloudWatch alarms for Application Load Balancer.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 0f966c0ff2f344f58a5c049ea2bc503a
          name: 'ELB Auth Error'
          type: DEPENDENT
          key: aws.elb.alb.auth_error
          description: 'The number of user authentications that could not be completed because an authenticate action was misconfigured, the load balancer could not establish a connection with the IdP, or the load balancer could not complete the authentication flow due to an internal error.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ELBAuthError")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: authorization
            - tag: component
              value: errors
        - uuid: 5f516687f9364f2f87b7fd1d2cbc8054
          name: 'ELB Auth Failure'
          type: DEPENDENT
          key: aws.elb.alb.auth_failure
          description: 'The number of user authentications that could not be completed because the IdP denied access to the user or an authorization code was used more than once.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ELBAuthFailure")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: authorization
            - tag: component
              value: errors
        - uuid: bfae078db4a14fd6a31b94e87552e430
          name: 'ELB Auth Latency'
          type: DEPENDENT
          key: aws.elb.alb.auth_latency
          value_type: FLOAT
          units: ms
          description: |
            The time elapsed, in milliseconds, to query the IdP for the ID token and user info.
            If one or more of these operations fail, this is the time to failure.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ELBAuthLatency")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: authorization
        - uuid: 3eed720ae5f948b287cf6ee0bdda41f1
          name: 'ELB Auth Success'
          type: DEPENDENT
          key: aws.elb.alb.auth_success
          description: |
            The number of authenticate actions that were successful.
            This metric is incremented at the end of the authentication workflow, after the load balancer has retrieved the user claims from the IdP.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ELBAuthSuccess")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: authorization
        - uuid: 8562bd314951443faed4039c2c36b127
          name: 'ELB Auth User Claims Size Exceeded'
          type: DEPENDENT
          key: aws.elb.alb.auth_user_claims_size_exceeded
          description: 'The number of times that a configured IdP returned user claims that exceeded 11K bytes in size.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ELBAuthUserClaimsSizeExceeded")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: authorization
            - tag: component
              value: errors
        - uuid: 4f06db3a2da446c28228a20ed04847e1
          name: 'Consumed LCUs'
          type: DEPENDENT
          key: aws.elb.alb.capacity_units
          value_type: FLOAT
          description: |
            The number of load balancer capacity units (LCU) used by your load balancer.
            You pay for the number of LCUs that you use per hour.
            More information on Elastic Load Balancing pricing here: https://aws.amazon.com/elasticloadbalancing/pricing/
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ConsumedLCUs")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: capacity
        - uuid: c7e81227b5a648de9413ffcb6b9746ee
          name: 'Client TLS Negotiation Error Count'
          type: DEPENDENT
          key: aws.elb.alb.client_tls_negotiation_error_count
          description: |
            The number of TLS connections initiated by the client that did not establish a session with the load balancer due to a TLS error.
            Possible causes include a mismatch of ciphers or protocols or the client failing to verify the server certificate and closing the connection.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ClientTLSNegotiationErrorCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: errors
        - uuid: 059b7697baba46b2a7f138a1011a0e0c
          name: 'Get ELB ALB alarms data'
          type: SCRIPT
          key: aws.elb.alb.get_alarms
          delay: 0s;m/1
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', 'arn', 'loadbalancer_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'),
            			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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS ELB ] Sending request: ' + url);
            		response = request.get(url);
            		Zabbix.log(4, '[ AWS ELB ] 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) {
            			try {
            				response = JSON.parse(XML.toJson(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');
            			regex = /loadbalancer\/(.+)$/;
            
            			if (!Array.isArray(alarms_list))
            				alarms_list = [alarms_list];
            			alarms_list.forEach(function (alarm) {
            				var dimensions = alarm.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 === 'LoadBalancer' && dimensions[i].Value === AWS.params.arn.match(regex)[1])
            						|| (dimensions[i].Name === 'LoadBalancerName' && dimensions[i].Value === AWS.params.loadbalancer_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 ELB Alarms ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: '`DescribeAlarms` API method: https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html'
          preprocessing:
            - type: CHECK_NOT_SUPPORTED
              parameters:
                - '-1'
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: arn
              value: '{$AWS.ELB.ARN}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: loadbalancer_name
              value: '{$AWS.ELB.NAME}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: c7b4e867ff8246058d931ca76d18d4e7
          name: 'Get metrics data'
          type: SCRIPT
          key: aws.elb.alb.get_metrics
          delay: 0s;m/1
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            	request_period: 60,
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('POST', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', 'arn'].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('&');
            	},
            
            	renderMetricQuery: function (period, arn) {
            		var metrics_list = [
            			'ActiveConnectionCount:Sum',
            			'ClientTLSNegotiationErrorCount:Sum',
            			'ConsumedLCUs:Sum',
            			'DesyncMitigationMode_NonCompliant_Request_Count:Sum',
            			'HTTP_Fixed_Response_Count:Sum',
            			'HTTP_Redirect_Count:Sum',
            			'HTTP_Redirect_Url_Limit_Exceeded_Count:Sum',
            			'HTTPCode_ELB_3XX_Count:Sum',
            			'HTTPCode_ELB_4XX_Count:Sum',
            			'HTTPCode_ELB_5XX_Count:Sum',
            			'HTTPCode_ELB_500_Count:Sum',
            			'HTTPCode_ELB_502_Count:Sum',
            			'HTTPCode_ELB_503_Count:Sum',
            			'HTTPCode_ELB_504_Count:Sum',
            			'NewConnectionCount:Sum',
            			'ProcessedBytes:Sum',
            			'RejectedConnectionCount:Sum',
            			'RequestCount:Sum',
            			'RuleEvaluations:Sum',
            			'TargetResponseTime:Average',
            			'TargetTLSNegotiationErrorCount:Sum',
            			'TargetConnectionErrorCount:Sum',
            			'ELBAuthError:Sum',
            			'ELBAuthFailure:Sum',
            			'ELBAuthLatency:Sum',
            			'ELBAuthSuccess:Sum',
            			'ELBAuthUserClaimsSizeExceeded:Sum',
            		],
            			regex = /loadbalancer\/(.+)$/;
            
            		var metric_payload = [];
            		metrics_list.forEach(function (metric, index) {
            			var parts = metric.split(':', 2);
            			metric_payload.push({
            				'Id': 'm' + index,
            				'MetricStat': {
            					'Metric': {
            						'MetricName': parts[0],
            						'Namespace': 'AWS/ApplicationELB',
            						'Dimensions': [
            							{
            								'Name': 'LoadBalancer',
            								'Value': arn.match(regex)[1],
            							}
            						]
            					},
            					'Period': period,
            					'Stat': parts[1],
            				}
            			});
            		});
            
            		return metric_payload;
            	},
            
            	request: function (method, region, service, params, data) {
            		if (typeof data === 'undefined' || data === null) {
            			data = JSON.stringify([]);
            		}
            		else {
            			data = JSON.stringify(data)
            		}
            		var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''),
            			date = amzdate.replace(/T\d+Z/, ''),
            			canonical_uri = '/',
            			host = service + '.' + region + '.amazonaws.com',
            			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'),
            			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('X-Amz-Target: GraniteServiceVersion20100801.GetMetricData')
            		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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS ELB ] Sending request: ' + url);
            		response = request.post(url, data);
            		Zabbix.log(4, '[ AWS ELB ] Received response with status code ' + request.getStatus() + ': ' + response);
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		return JSON.parse(response);
            	},
            
            	getMetricsData: function () {
            		var end_time = Math.floor((new Date().getTime()) / 1000),
            			start_time = end_time - AWS.request_period * 60;
            		payload = {
            			'StartTime': start_time,
            			'EndTime': end_time,
            			'ScanBy': 'TimestampDescending',
            			'MetricDataQueries': AWS.renderMetricQuery(AWS.request_period, AWS.params.arn)
            		};
            
            		return AWS.getField(AWS.request('POST', AWS.params.region, 'monitoring', '', payload), 'MetricDataResults');
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            	return JSON.stringify(AWS.getMetricsData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS ELB Get metrics] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: |
            Get ELB Application Load Balancer metrics.
            Full metrics list related to Application Load Balancer: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html
          preprocessing:
            - type: CHECK_NOT_SUPPORTED
              parameters:
                - '-1'
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: arn
              value: '{$AWS.ELB.ARN}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: 9b118d348b934146bab54e2df582e2b0
          name: 'Get target groups'
          type: SCRIPT
          key: aws.elb.alb.get_target_groups
          delay: 0s;m/30
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', 'arn'].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 = JSON.stringify([]);
            		}
            		var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''),
            			date = amzdate.replace(/T\d+Z/, ''),
            			canonical_uri = '/',
            			host = service + '.' + region + '.amazonaws.com',
            			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'),
            			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/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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS ELB ] Sending request: ' + url);
            		response = request.get(url);
            		Zabbix.log(4, '[ AWS ELB ] Received response with status code ' + request.getStatus() + ': ' + response);
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		return JSON.parse(response);
            	},
            
            	listTargetGroups: function () {
            		var lld_array = [],
            			regex = /targetgroup\/(.+)$/,
            			payload = {
            				'Action': 'DescribeTargetGroups',
            				'LoadBalancerArn': AWS.params.arn,
            				'Version': '2015-12-01'
            			};
            		targets = AWS.getField(AWS.request('GET', AWS.params.region, 'elasticloadbalancing', AWS.prepareParams(payload), ''), 'DescribeTargetGroupsResponse.DescribeTargetGroupsResult.TargetGroups');
            
            		if (!Array.isArray(targets))
            			targets = [targets]
            
            		targets.forEach(function (targets) {
            			lld_array.push(
            				{
            					target_name: AWS.getField(targets, 'TargetGroupName'),
            					target_arn: AWS.getField(targets, 'TargetGroupArn').match(regex)[0],
            					type: AWS.getField(targets, 'TargetType'),
            					protocol: AWS.getField(targets, 'Protocol')
            				}
            			)
            		});
            
            		return lld_array;
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            	return JSON.stringify(AWS.listTargetGroups());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS ELB Target groups ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: |
            Get ELB target group.
            `DescribeTargetGroups` API method: https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_DescribeTargetGroups.html
          preprocessing:
            - type: CHECK_NOT_SUPPORTED
              parameters:
                - '-1'
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: arn
              value: '{$AWS.ELB.ARN}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: eabcf1ef1514451087d08d739cf55d94
          name: 'ELB HTTP 3XX Count'
          type: DEPENDENT
          key: aws.elb.alb.http_3xx_count
          description: |
            The number of HTTP 3XX redirection codes that originate from the load balancer.
            This count does not include response codes generated by targets.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "HTTPCode_ELB_3XX_Count")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: http
            - tag: http-code
              value: 3xx
        - uuid: c714c1f2185b4b0b8b86e3ad336d7888
          name: 'ELB HTTP 4XX Count'
          type: DEPENDENT
          key: aws.elb.alb.http_4xx_count
          description: |
            The number of HTTP 4XX client error codes that originate from the load balancer.
            Client errors are generated when requests are malformed or incomplete. These requests were not received by the target, other than in the case where the load balancer returns an HTTP 460 error code.
            This count does not include any response codes generated by the targets.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "HTTPCode_ELB_4XX_Count")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: http
            - tag: http-code
              value: 4xx
          triggers:
            - uuid: 922bd3ab505b420984c93dfdfc417a56
              expression: 'min(/AWS ELB Application Load Balancer by HTTP/aws.elb.alb.http_4xx_count,5m)>{$AWS.HTTP.4XX.FAIL.MAX.WARN}'
              name: 'AWS ELB ALB: Too many HTTP 4XX error codes'
              event_name: 'AWS ELB ALB: Too many HTTP 4XX error codes (over {$AWS.HTTP.4XX.FAIL.MAX.WARN} for 5m)'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Too many requests failed with HTTP 4XX code.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 6395ef49a60546ec8d3ce117867cbb43
          name: 'ELB HTTP 5XX Count'
          type: DEPENDENT
          key: aws.elb.alb.http_5xx_count
          description: |
            The number of HTTP 5XX server error codes that originate from the load balancer.
            This count does not include any response codes generated by the targets.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "HTTPCode_ELB_5XX_Count")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: http
            - tag: http-code
              value: 5xx
          triggers:
            - uuid: 883fc396e7da4806943cd70688c057a3
              expression: 'min(/AWS ELB Application Load Balancer by HTTP/aws.elb.alb.http_5xx_count,5m)>{$AWS.HTTP.5XX.FAIL.MAX.WARN}'
              name: 'AWS ELB ALB: Too many HTTP 5XX error codes'
              event_name: 'AWS ELB ALB: Too many HTTP 5XX error codes (over {$AWS.HTTP.5XX.FAIL.MAX.WARN} for 5m)'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Too many requests failed with HTTP 5XX code.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 7bf9230aa56b4196b386d23358da75ed
          name: 'ELB HTTP 500 Count'
          type: DEPENDENT
          key: aws.elb.alb.http_500_count
          description: 'The number of HTTP 500 error codes that originate from the load balancer.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "HTTPCode_ELB_500_Count")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: http
            - tag: http-code
              value: 5xx
            - tag: http-code
              value: '500'
        - uuid: f89bee8030774615a132d25a6d1b7a2a
          name: 'ELB HTTP 502 Count'
          type: DEPENDENT
          key: aws.elb.alb.http_502_count
          description: 'The number of HTTP 502 error codes that originate from the load balancer.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "HTTPCode_ELB_502_Count")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: http
            - tag: http-code
              value: 5xx
            - tag: http-code
              value: '502'
        - uuid: bca5eaf0b96c496395ed98e8d4705153
          name: 'ELB HTTP 503 Count'
          type: DEPENDENT
          key: aws.elb.alb.http_503_count
          description: 'The number of HTTP 503 error codes that originate from the load balancer.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "HTTPCode_ELB_503_Count")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: http
            - tag: http-code
              value: 5xx
            - tag: http-code
              value: '503'
        - uuid: 5d1c57a6483c4b84b992f9677f6216c1
          name: 'ELB HTTP 504 Count'
          type: DEPENDENT
          key: aws.elb.alb.http_504_count
          description: 'The number of HTTP 504 error codes that originate from the load balancer.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "HTTPCode_ELB_504_Count")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: http
            - tag: http-code
              value: 5xx
            - tag: http-code
              value: '504'
        - uuid: 115bdaf06c554f9a8b3a486c28d218cd
          name: 'HTTP Fixed Response Count'
          type: DEPENDENT
          key: aws.elb.alb.http_fixed_response_count
          description: 'The number of fixed-response actions that were successful.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "HTTP_Fixed_Response_Count")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: responses
        - uuid: 4edc1d8d4eb84832996943ac571afb5f
          name: 'HTTP Redirect Count'
          type: DEPENDENT
          key: aws.elb.alb.http_redirect_count
          description: 'The number of redirect actions that were successful.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "HTTP_Redirect_Count")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: http
        - uuid: fbf24a4f2110416d973a8f11c8770d98
          name: 'HTTP Redirect Url Limit Exceeded Count'
          type: DEPENDENT
          key: aws.elb.alb.http_redirect_url_limit_exceeded_count
          description: 'The number of redirect actions that could not be completed because the URL in the response location header is larger than 8K bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "HTTP_Redirect_Url_Limit_Exceeded_Count")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: http
        - uuid: 7fdd931458ba4fa5b3baff1d67e4a32f
          name: 'Get metrics check'
          type: DEPENDENT
          key: aws.elb.alb.metrics.check
          value_type: CHAR
          description: 'Check that the Application Load Balancer metrics data has been received correctly.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: 70282eb6c0c442f9a4f4c49b10f54a4d
              expression: 'length(last(/AWS ELB Application Load Balancer by HTTP/aws.elb.alb.metrics.check))>0'
              name: 'AWS ELB ALB: Failed to get metrics data'
              event_name: 'AWS ELB ALB: Failed to get CloudWatch metrics for Application Load Balancer'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Failed to get CloudWatch metrics for Application Load Balancer.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 740872a3328e4c12827d8fcd16eb43ea
          name: 'New Connection Count'
          type: DEPENDENT
          key: aws.elb.alb.new_connection_count
          description: 'The total number of new TCP connections established from clients to the load balancer and from the load balancer to targets.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "NewConnectionCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: connections
        - uuid: 4e3cf684607741e39248929e6b917be7
          name: 'Desync Mitigation Mode Non Compliant Request Count'
          type: DEPENDENT
          key: aws.elb.alb.non_compliant_request_count
          description: 'The number of requests that fail to comply with HTTP protocols.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "DesyncMitigationMode_NonCompliant_Request_Count")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: errors
        - uuid: 32b5fbc67cec4d739bbd95ba1cd77ab9
          name: 'Processed Bytes'
          type: DEPENDENT
          key: aws.elb.alb.processed_bytes
          value_type: FLOAT
          units: B
          description: |
            The total number of bytes processed by the load balancer over IPv4 and IPv6 (HTTP header and HTTP payload).
            This count includes traffic to and from clients and Lambda functions, and traffic from an Identity Provider (IdP) if user authentication is enabled.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ProcessedBytes")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: capacity
        - uuid: ed3c4ebc1faf43ff9be134ae98aac0e9
          name: 'Rejected Connection Count'
          type: DEPENDENT
          key: aws.elb.alb.rejected_connection_count
          description: 'The number of connections that were rejected because the load balancer had reached its maximum number of connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "RejectedConnectionCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: connections
        - uuid: 4b5b059c30ef4f8bb4d11a273d071db1
          name: 'Requests Count'
          type: DEPENDENT
          key: aws.elb.alb.requests_count
          description: |
            The number of requests processed over IPv4 and IPv6.
            This metric is only incremented for requests where the load balancer node was able to choose a target.
            Requests that are rejected before a target is chosen are not reflected in this metric.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "RequestCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: requests
        - uuid: b5105b9e48f4482db42ff948f906be6f
          name: 'Rule Evaluations'
          type: DEPENDENT
          key: aws.elb.alb.rule_evaluations
          description: 'The number of rules processed by the load balancer given a request rate averaged over an hour.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "RuleEvaluations")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: requests
        - uuid: 09cd066b48544eb7ac818bc6171e3e87
          name: 'Target Connection Error Count'
          type: DEPENDENT
          key: aws.elb.alb.target_connection_error_count
          description: |
            The number of connections that were not successfully established between the load balancer and target.
            This metric does not apply if the target is a Lambda function.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "TargetConnectionErrorCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: errors
        - uuid: 560c74f7011b4b9c821dfdf7f8d8e93a
          name: 'Target Response Time'
          type: DEPENDENT
          key: aws.elb.alb.target_response_time
          value_type: FLOAT
          units: s
          description: |
            The time elapsed, in seconds, after the request leaves the load balancer until a response from the target is received.
            This is equivalent to the `target_processing_time` field in the access logs.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "TargetResponseTime")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: responses
        - uuid: 66d56d14553d4de69a63745ab02f2611
          name: 'Target TLS Negotiation Error Count'
          type: DEPENDENT
          key: aws.elb.alb.target_tls_negotiation_error_count
          description: |
            The number of TLS connections initiated by the load balancer that did not establish a session with the target.
            Possible causes include a mismatch of ciphers or protocols. This metric does not apply if the target is a Lambda function.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "TargetTLSNegotiationErrorCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.alb.get_metrics
          tags:
            - tag: component
              value: errors
      discovery_rules:
        - uuid: 065ef42ebea5448896db5fcc5baa2f81
          name: 'Load Balancer alarm discovery'
          type: DEPENDENT
          key: aws.elb.alb.alarms.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.ELB.LLD.FILTER.ALARM_NAME.MATCHES}'
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.ELB.LLD.FILTER.ALARM_NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#ALARM_SERVICE_NAMESPACE}'
                value: '{$AWS.ELB.LLD.FILTER.ALARM_SERVICE_NAMESPACE.MATCHES}'
              - macro: '{#ALARM_SERVICE_NAMESPACE}'
                value: '{$AWS.ELB.LLD.FILTER.ALARM_SERVICE_NAMESPACE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Used for the discovery of alarm balancers.'
          item_prototypes:
            - uuid: fca522690827426bb63f93e90d98aa54
              name: '[{#ALARM_NAME}]: Get metrics'
              type: DEPENDENT
              key: 'aws.elb.alb.alarm.get_metrics["{#ALARM_NAME}"]'
              history: '0'
              value_type: TEXT
              description: 'Get metrics about the alarm state and its reason.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.AlarmName == "{#ALARM_NAME}")].first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.elb.alb.get_alarms
              tags:
                - tag: component
                  value: raw
            - uuid: 3ef62eb9b0824f8ea3c2c1e8e15ce1fd
              name: '[{#ALARM_NAME}]: State'
              type: DEPENDENT
              key: 'aws.elb.alb.alarm.state["{#ALARM_NAME}"]'
              description: |
                The value of the alarm state. 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.elb.alb.alarm.get_metrics["{#ALARM_NAME}"]'
              tags:
                - tag: component
                  value: alarms
              trigger_prototypes:
                - uuid: b8bbc96a20bc4ab393d1fa76a3cf5254
                  expression: 'last(/AWS ELB Application Load Balancer by HTTP/aws.elb.alb.alarm.state["{#ALARM_NAME}"])=1'
                  name: 'AWS ELB ALB: [{#ALARM_NAME}] has ''Insufficient data'' state'
                  event_name: 'AWS ELB ALB: [{#ALARM_NAME}] has ''Insufficient data'' state'
                  opdata: 'Current value: {ITEM.LASTVALUE1}'
                  priority: INFO
                  description: 'Either the alarm has just started, the metric is not available, or not enough data is available for the metric to determine the alarm state.'
                  tags:
                    - tag: scope
                      value: notice
            - uuid: 8839a61a10f7453ebfdcae0ef16eb37c
              name: '[{#ALARM_NAME}]: State reason'
              type: DEPENDENT
              key: 'aws.elb.alb.alarm.state_reason["{#ALARM_NAME}"]'
              value_type: TEXT
              description: |
                An explanation for the alarm state reason 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.elb.alb.alarm.get_metrics["{#ALARM_NAME}"]'
              tags:
                - tag: component
                  value: alarms
          trigger_prototypes:
            - uuid: a1b8587c80dd41ef8b185cf62e563bcb
              expression: 'last(/AWS ELB Application Load Balancer by HTTP/aws.elb.alb.alarm.state["{#ALARM_NAME}"])=2 and length(last(/AWS ELB Application Load Balancer by HTTP/aws.elb.alb.alarm.state_reason["{#ALARM_NAME}"]))>0'
              name: 'AWS ELB ALB: [{#ALARM_NAME}] has ''Alarm'' state'
              event_name: 'AWS ELB ALB: [{#ALARM_NAME}] has ''Alarm'' state (reason: {ITEM.LASTVALUE2})'
              opdata: 'Reason: {ITEM.LASTVALUE2}'
              priority: AVERAGE
              description: |
                The alarm `{#ALARM_NAME}` is in the ALARM state.
                Reason: `{ITEM.LASTVALUE2}`
              tags:
                - tag: scope
                  value: availability
          master_item:
            key: aws.elb.alb.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: 1002081ffffd40828ff5419c50bc16d5
          name: 'Target groups discovery'
          type: DEPENDENT
          key: aws.elb.alb.target_groups.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.ELB.TARGET.GROUP.NAME}'
                value: '{$AWS.ELB.LLD.FILTER.TARGET.GROUP.MATCHES}'
              - macro: '{#AWS.ELB.TARGET.GROUP.NAME}'
                value: '{$AWS.ELB.LLD.FILTER.TARGET.GROUP.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Used for the discovery of `{$AWS.ELB.TARGET.GROUP.NAME}` target groups.'
          item_prototypes:
            - uuid: 21d1830526e14fb99b2288d79747d472
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: Anomalous Host Count'
              type: DEPENDENT
              key: 'aws.elb.alb.target_groups.anomalous_host_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: 'The number of hosts detected with anomalies.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "AnomalousHostCount")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.alb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: target-groups
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
            - uuid: 306971d2e8fb441d8ae4a658b26304c3
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: Get metrics'
              type: SCRIPT
              key: 'aws.elb.alb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              delay: 0s;m/5
              history: '0'
              value_type: TEXT
              params: |
                var AWS = {
                	params: {},
                	metadata: 'http://169.254.169.254/latest/',
                	request_period: 60,
                
                	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;
                	},
                
                	getRoleBaseCredentials: function () {
                		AWS.params['auth_type'] = 'role_base';
                		var request = new HttpRequest();
                		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
                			request.setProxy(AWS.params.proxy);
                		}
                		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
                		var token = request.put(AWS.metadata + 'api/token');
                
                		if (request.getStatus() !== 200 || token === null || token === '') {
                			throw 'Error getting IMDSv2 session token.';
                		}
                		request.addHeader('X-aws-ec2-metadata-token: ' + token);
                		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
                
                		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
                			throw 'Error getting security credentials from instance metadata. Role not found.';
                		}
                
                		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
                			};
                			AWS.params[field] = credentials[field];
                		});
                	},
                
                	setParams: function (params) {
                		AWS.params['proxy'] = params.proxy;
                		switch (AWS.getField(params, 'auth_type')) {
                			case 'role_base':
                				AWS.getRoleBaseCredentials();
                				break;
                			case 'assume_role':
                				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
                					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
                				}
                				if (params.metadata_auth === 'true') {
                					AWS.getRoleBaseCredentials();
                					AWS.params['SessionToken'] = AWS.params['Token'];
                					AWS.params['auth_type'] = 'assume_role_metadata';
                
                					['sts_region', 'role_arn'].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];
                					});
                				}
                
                				if (params.metadata_auth === 'false') {
                					AWS.params['auth_type'] = 'assume_role';
                
                					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
                					});
                				}
                
                				const role_arn_regex = /role\/(.+)$/;
                				const match = AWS.params.role_arn.match(role_arn_regex);
                				if (!match) {
                					throw 'Invalid role ARN format.';
                				}
                
                				const payload = {
                					'Action': 'AssumeRole',
                					'Version': '2011-06-15',
                					'RoleArn': AWS.params.role_arn,
                					'RoleSessionName': match[1] + 'Session',
                				};
                
                				credentials = AWS.getField(AWS.request('POST', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
                
                				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
                					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
                						throw 'Required credentials are not set: "' + field + '".';
                					};
                					AWS.params[field] = credentials[field];
                				});
                				break;
                			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', 'arn', 'target_arn'].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('&');
                	},
                
                	renderMetricQuery: function (period, arn, target_arn) {
                		var metrics_list = [
                			'HTTPCode_Target_2XX_Count:Sum',
                			'HTTPCode_Target_3XX_Count:Sum',
                			'HTTPCode_Target_4XX_Count:Sum',
                			'HTTPCode_Target_5XX_Count:Sum',
                			'HealthyHostCount:Average',
                			'UnHealthyHostCount:Average',
                			'HealthyStateRouting:Sum',
                			'UnhealthyStateRouting:Sum',
                			'UnhealthyRoutingRequestCount:Sum',
                			'HealthyStateDNS:Sum',
                			'UnhealthyStateDNS:Sum',
                			'RequestCountPerTarget:Sum',
                			'MitigatedHostCount:Average',
                			'AnomalousHostCount:Average',
                		],
                			regex = /loadbalancer\/(.+)$/;
                
                		var metric_payload = [];
                		metrics_list.forEach(function (metric, index) {
                			var parts = metric.split(':', 2);
                			metric_payload.push({
                				'Id': 'm' + index,
                				'MetricStat': {
                					'Metric': {
                						'MetricName': parts[0],
                						'Namespace': 'AWS/ApplicationELB',
                						'Dimensions': [
                							{
                								'Name': 'LoadBalancer',
                								'Value': arn.match(regex)[1],
                							},
                							{
                								'Name': 'TargetGroup',
                								'Value': target_arn
                							}
                						]
                					},
                					'Period': period,
                					'Stat': parts[1],
                				}
                			});
                		});
                
                		return metric_payload;
                	},
                
                	request: function (method, region, service, params, data) {
                		if (typeof data === 'undefined' || data === null) {
                			data = JSON.stringify([]);
                		}
                		else {
                			data = JSON.stringify(data)
                		}
                		var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''),
                			date = amzdate.replace(/T\d+Z/, ''),
                			canonical_uri = '/',
                			host = service + '.' + region + '.amazonaws.com',
                			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'),
                			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('X-Amz-Target: GraniteServiceVersion20100801.GetMetricData')
                		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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
                			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
                		}
                
                		Zabbix.log(4, '[ AWS ELB ] Sending request: ' + url);
                		response = request.post(url, data);
                		Zabbix.log(4, '[ AWS ELB ] Received response with status code ' + request.getStatus() + ': ' + response);
                		if (request.getStatus() !== 200) {
                			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
                		}
                
                		return JSON.parse(response);
                	},
                
                	getMetricsData: function () {
                		var end_time = Math.floor((new Date().getTime()) / 1000),
                			start_time = end_time - AWS.request_period * 60;
                		payload = {
                			'StartTime': start_time,
                			'EndTime': end_time,
                			'ScanBy': 'TimestampDescending',
                			'MetricDataQueries': AWS.renderMetricQuery(AWS.request_period, AWS.params.arn, AWS.params.target_arn)
                		};
                
                		return AWS.getField(AWS.request('POST', AWS.params.region, 'monitoring', '', payload), 'MetricDataResults');
                	}
                };
                
                try {
                	AWS.setParams(JSON.parse(value));
                	return JSON.stringify(AWS.getMetricsData());
                }
                catch (error) {
                	error += (String(error).endsWith('.')) ? '' : '.';
                	Zabbix.log(3, '[ AWS ELB Get targets group metrics] ERROR: ' + error);
                
                	return JSON.stringify({ 'error': error });
                }
              description: |
                Get the metrics of the ELB target group `{#AWS.ELB.TARGET.GROUP.NAME}`.
                Full list of metrics related to AWS ELB here: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html#user-authentication-metric-table
              preprocessing:
                - type: CHECK_NOT_SUPPORTED
                  parameters:
                    - '-1'
              timeout: '{$AWS.DATA.TIMEOUT}'
              parameters:
                - name: AccessKeyId
                  value: '{$AWS.ACCESS.KEY.ID}'
                - name: arn
                  value: '{$AWS.ELB.ARN}'
                - name: auth_type
                  value: '{$AWS.AUTH_TYPE}'
                - name: metadata_auth
                  value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
                - name: proxy
                  value: '{$AWS.PROXY}'
                - name: region
                  value: '{$AWS.REGION}'
                - name: role_arn
                  value: '{$AWS.ASSUME.ROLE.ARN}'
                - name: SecretAccessKey
                  value: '{$AWS.SECRET.ACCESS.KEY}'
                - name: sts_region
                  value: '{$AWS.STS.REGION}'
                - name: target_arn
                  value: '{#AWS.ELB.TARGET.GROUP.ARN}'
              tags:
                - tag: component
                  value: raw
                - tag: component
                  value: target-groups
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
            - uuid: e4cd95136bb04981b15a508aa73f5723
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: Healthy Host Count'
              type: DEPENDENT
              key: 'aws.elb.alb.target_groups.healthy_host_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: 'The number of targets that are considered healthy.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "HealthyHostCount")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.alb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: health
                - tag: component
                  value: target-groups
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
            - uuid: b96ad1d2f5064cc99c49eeec3801418e
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: Healthy State DNS'
              type: DEPENDENT
              key: 'aws.elb.alb.target_groups.healthy_state_dns["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: 'The number of zones that meet the DNS healthy state requirements.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "HealthyStateDNS")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.alb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: health
                - tag: component
                  value: target-groups
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
            - uuid: 030c4fe8b7f44bf3a290b1b5da9319d8
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: Healthy State Routing'
              type: DEPENDENT
              key: 'aws.elb.alb.target_groups.healthy_state_routing["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: 'The number of zones that meet the routing healthy state requirements.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "HealthyStateRouting")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.alb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: health
                - tag: component
                  value: target-groups
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
            - uuid: fa9da54b4feb4fc79fbf74c491eb23ba
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: HTTP Code Target 2XX Count'
              type: DEPENDENT
              key: 'aws.elb.alb.target_groups.http_2xx_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: |
                The number of HTTP response 2XX codes generated by the targets.
                This does not include any response codes generated by the load balancer.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "HTTPCode_Target_2XX_Count")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.alb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: http
                - tag: component
                  value: target-groups
                - tag: http-code
                  value: 2xx
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
            - uuid: 50e78304f9e74019b7e06310d6dd2e6f
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: HTTP Code Target 3XX Count'
              type: DEPENDENT
              key: 'aws.elb.alb.target_groups.http_3xx_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: |
                The number of HTTP response 3XX codes generated by the targets.
                This does not include any response codes generated by the load balancer.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "HTTPCode_Target_3XX_Count")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.alb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: http
                - tag: component
                  value: target-groups
                - tag: http-code
                  value: 3xx
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
            - uuid: ec7b92c79c6f441cadb8994b906753f4
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: HTTP Code Target 4XX Count'
              type: DEPENDENT
              key: 'aws.elb.alb.target_groups.http_4xx_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: |
                The number of HTTP response 4XX codes generated by the targets.
                This does not include any response codes generated by the load balancer.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "HTTPCode_Target_4XX_Count")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.alb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: http
                - tag: component
                  value: target-groups
                - tag: http-code
                  value: 4xx
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
            - uuid: c9e61f9d2f12496d90693a83cb829b66
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: HTTP Code Target 5XX Count'
              type: DEPENDENT
              key: 'aws.elb.alb.target_groups.http_5xx_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: |
                The number of HTTP response 5XX codes generated by the targets.
                This does not include any response codes generated by the load balancer.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "HTTPCode_Target_5XX_Count")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.alb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: http
                - tag: component
                  value: target-groups
                - tag: http-code
                  value: 5xx
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
            - uuid: 0ad4d9a933944c7d979da411d24b165e
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: Mitigated Host Count'
              type: DEPENDENT
              key: 'aws.elb.alb.target_groups.mitigated_host_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: 'The number of targets under mitigation.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "MitigatedHostCount")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.alb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: target-groups
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
            - uuid: 31a579ac8de9402bae3a3668779ec6c5
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: Request Count Per Target'
              type: DEPENDENT
              key: 'aws.elb.alb.target_groups.request["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: |
                The average request count per target, in a target group.
                You must specify the target group using the TargetGroup dimension.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "RequestCountPerTarget")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.alb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: requests
                - tag: component
                  value: target-groups
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
            - uuid: c158172738084d38aec424505a7a86a5
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: Unhealthy Host Count'
              type: DEPENDENT
              key: 'aws.elb.alb.target_groups.unhealthy_host_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: 'The number of targets that are considered unhealthy.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "UnHealthyHostCount")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.alb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: health
                - tag: component
                  value: target-groups
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
            - uuid: 9fea4b63067445d98d29de566d50b0a4
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: Unhealthy Routing Request Count'
              type: DEPENDENT
              key: 'aws.elb.alb.target_groups.unhealthy_routing_request_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: 'The average request count per target, in a target group.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "UnhealthyRoutingRequestCount")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.alb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: requests
                - tag: component
                  value: target-groups
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
            - uuid: f050e9610eb64251b55e843fc5eb5876
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: Unhealthy State DNS'
              type: DEPENDENT
              key: 'aws.elb.alb.target_groups.unhealthy_state_dns["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: 'The number of zones that do not meet the DNS healthy state requirements and therefore were marked unhealthy in DNS.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "UnhealthyStateDNS")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.alb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: health
                - tag: component
                  value: target-groups
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
            - uuid: 2a446451893e4f70a0d4ac4b1bb969fb
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: Unhealthy State Routing'
              type: DEPENDENT
              key: 'aws.elb.alb.target_groups.unhealthy_state_routing["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: 'The number of zones that do not meet the routing healthy state requirements, and therefore the load balancer distributes traffic to all targets in the zone, including the unhealthy targets.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "UnhealthyStateRouting")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.alb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: health
                - tag: component
                  value: target-groups
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
          graph_prototypes:
            - uuid: f426eff334d449ff9ec0a2ff8f6ee103
              name: 'AWS ELB ALB Target Groups: [{#AWS.ELB.TARGET.GROUP.NAME}]: Healthy Host'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 199C0D
                  item:
                    host: 'AWS ELB Application Load Balancer by HTTP'
                    key: 'aws.elb.alb.target_groups.healthy_host_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
            - uuid: f6f8d317322a420ab4e0025b3b284a98
              name: 'AWS ELB ALB Target Groups: [{#AWS.ELB.TARGET.GROUP.NAME}]: Healthy State DNS'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 199C0D
                  item:
                    host: 'AWS ELB Application Load Balancer by HTTP'
                    key: 'aws.elb.alb.target_groups.healthy_state_dns["{#AWS.ELB.TARGET.GROUP.NAME}"]'
            - uuid: 40922ff1845141c7a2488fe24debeae0
              name: 'AWS ELB ALB Target Groups: [{#AWS.ELB.TARGET.GROUP.NAME}]: Healthy State Routing'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 199C0D
                  item:
                    host: 'AWS ELB Application Load Balancer by HTTP'
                    key: 'aws.elb.alb.target_groups.healthy_state_routing["{#AWS.ELB.TARGET.GROUP.NAME}"]'
            - uuid: ec38c670cabf422ea79f41866c90ee66
              name: 'AWS ELB ALB Target Groups: [{#AWS.ELB.TARGET.GROUP.NAME}]: HTTP Code Target Group'
              graph_items:
                - drawtype: BOLD_LINE
                  color: 199C0D
                  item:
                    host: 'AWS ELB Application Load Balancer by HTTP'
                    key: 'aws.elb.alb.target_groups.http_2xx_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
                - sortorder: '1'
                  drawtype: BOLD_LINE
                  color: F63100
                  item:
                    host: 'AWS ELB Application Load Balancer by HTTP'
                    key: 'aws.elb.alb.target_groups.http_3xx_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
                - sortorder: '2'
                  drawtype: BOLD_LINE
                  color: 00611C
                  item:
                    host: 'AWS ELB Application Load Balancer by HTTP'
                    key: 'aws.elb.alb.target_groups.http_4xx_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
                - sortorder: '3'
                  drawtype: BOLD_LINE
                  color: F7941D
                  item:
                    host: 'AWS ELB Application Load Balancer by HTTP'
                    key: 'aws.elb.alb.target_groups.http_5xx_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
            - uuid: a2668f5bf6a240a296b047c1b979f9dc
              name: 'AWS ELB ALB Target Groups: [{#AWS.ELB.TARGET.GROUP.NAME}]: Unhealthy Host'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: FF0000
                  item:
                    host: 'AWS ELB Application Load Balancer by HTTP'
                    key: 'aws.elb.alb.target_groups.unhealthy_host_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
            - uuid: 54645b74585c4b45a971c13d1127698d
              name: 'AWS ELB ALB Target Groups: [{#AWS.ELB.TARGET.GROUP.NAME}]: Unhealthy State DNS'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: FF0000
                  item:
                    host: 'AWS ELB Application Load Balancer by HTTP'
                    key: 'aws.elb.alb.target_groups.unhealthy_state_dns["{#AWS.ELB.TARGET.GROUP.NAME}"]'
            - uuid: 8da12e20218e4367968b8fcf0f56991a
              name: 'AWS ELB ALB Target Groups: [{#AWS.ELB.TARGET.GROUP.NAME}]: Unhealthy State Routing'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: FF0000
                  item:
                    host: 'AWS ELB Application Load Balancer by HTTP'
                    key: 'aws.elb.alb.target_groups.unhealthy_state_routing["{#AWS.ELB.TARGET.GROUP.NAME}"]'
          master_item:
            key: aws.elb.alb.get_target_groups
          lld_macro_paths:
            - lld_macro: '{#AWS.ELB.TARGET.GROUP.ARN}'
              path: $.target_arn
            - lld_macro: '{#AWS.ELB.TARGET.GROUP.NAME}'
              path: $.target_name
            - lld_macro: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
              path: $.protocol
            - lld_macro: '{#AWS.ELB.TARGET.GROUP.TYPE}'
              path: $.type
          preprocessing:
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: automation
        - tag: target
          value: alb
        - tag: target
          value: aws
        - tag: target
          value: elb
      macros:
        - macro: '{$AWS.ACCESS.KEY.ID}'
          description: 'Access key ID.'
          config:
            type: TEXT
            priority: '3'
            label: 'Access key ID'
            description: 'Access keys are long-term credentials for an IAM user.'
        - macro: '{$AWS.ASSUME.ROLE.ARN}'
          description: 'ARN assume role; add when using the `assume_role` authorization method.'
          config:
            type: TEXT
            priority: '5'
            label: 'ARN assume role'
            description: 'The ARN for the assume role when using the `assume_role` method.'
        - macro: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
          value: 'false'
          description: 'Add when using the `assume_role` through instance metadata or environment authorization method. Possible values: `false`, `true`.'
          config:
            type: LIST
            priority: '2'
            label: 'Assume Role Metadata Authorization'
            description: 'Chose `True` when use instance metadata service to retrieve role credentials.'
            options:
              - value: 'false'
                text: 'False'
              - value: 'true'
                text: 'True'
        - macro: '{$AWS.AUTH_TYPE}'
          value: access_key
          description: 'Authorization method. Possible values: `access_key`, `assume_role`, `role_base`.'
          config:
            type: LIST
            priority: '1'
            label: 'Authorization method'
            description: 'Authorization method used to access AWS.'
            required: 'YES'
            options:
              - value: access_key
                text: 'Access key'
              - value: assume_role
                text: AssumeRole
              - value: role_base
                text: 'Role-based access'
        - macro: '{$AWS.DATA.TIMEOUT}'
          value: 60s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '7'
            label: 'API response timeout'
            description: 'Timeout for API responses in seconds.'
        - macro: '{$AWS.ELB.ARN}'
          description: 'Amazon Resource Names (ARN) of the load balancer.'
          config:
            type: TEXT
            priority: '10'
            label: 'Load Balancer ARN'
            description: 'The ARN of the load balancer.'
        - macro: '{$AWS.ELB.LLD.FILTER.ALARM_NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable alarms by name.'
          config:
            type: TEXT
            priority: '17'
            section_name: Filters
            label: 'Alarm Name Filter (Matches)'
            description: 'Regex filter for discoverable alarms by name.'
        - macro: '{$AWS.ELB.LLD.FILTER.ALARM_NAME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered alarms by name.'
          config:
            type: TEXT
            priority: '18'
            section_name: Filters
            label: 'Alarm Name Filter (Not Matches)'
            description: 'Regex filter to exclude discovered alarms by name.'
        - macro: '{$AWS.ELB.LLD.FILTER.ALARM_SERVICE_NAMESPACE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable alarms by namespace.'
          config:
            type: TEXT
            priority: '15'
            section_name: Filters
            label: 'Alarm Namespace Filter (Matches)'
            description: 'Regex filter for discoverable alarms by namespace.'
        - macro: '{$AWS.ELB.LLD.FILTER.ALARM_SERVICE_NAMESPACE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered alarms by namespace.'
          config:
            type: TEXT
            priority: '16'
            section_name: Filters
            label: 'Alarm Namespace Filter (Not Matches)'
            description: 'Regex filter to exclude discovered alarms by namespace.'
        - macro: '{$AWS.ELB.LLD.FILTER.TARGET.GROUP.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable target groups by name.'
          config:
            type: TEXT
            priority: '13'
            section_name: Filters
            label: 'Target Group Filter (Matches)'
            description: 'Regex filter for discoverable target groups by name.'
        - macro: '{$AWS.ELB.LLD.FILTER.TARGET.GROUP.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered target groups by name.'
          config:
            type: TEXT
            priority: '14'
            section_name: Filters
            label: 'Target Group Filter (Not Matches)'
            description: 'Regex filter to exclude discovered target groups by name.'
        - macro: '{$AWS.HTTP.4XX.FAIL.MAX.WARN}'
          value: '5'
          description: 'Maximum number of HTTP request failures for a trigger expression.'
          config:
            type: TEXT
            priority: '11'
            section_name: Thresholds
            label: 'HTTP 4XX Failures Threshold'
            description: 'Maximum number of HTTP 4XX failures allowed before triggering a warning.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.HTTP.5XX.FAIL.MAX.WARN}'
          value: '5'
          description: 'Maximum number of HTTP request failures for a trigger expression.'
          config:
            type: TEXT
            priority: '12'
            section_name: Thresholds
            label: 'HTTP 5XX Failures Threshold'
            description: 'Maximum number of HTTP 5XX failures allowed before triggering a warning.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.PROXY}'
          description: 'Sets the HTTP proxy value. If this macro is empty, no proxy is used.'
          config:
            type: TEXT
            priority: '8'
            section_name: Other
            label: 'HTTP Proxy'
            description: 'HTTP proxy to use.'
        - macro: '{$AWS.REGION}'
          value: us-west-1
          description: 'AWS Application Load Balancer region code.'
          config:
            type: TEXT
            priority: '6'
            label: 'AWS Region'
            description: 'The AWS region for the Application Load Balancer.'
        - macro: '{$AWS.SECRET.ACCESS.KEY}'
          type: SECRET_TEXT
          description: 'Secret access key.'
          config:
            type: TEXT
            priority: '4'
            label: 'Secret access key'
            description: 'Secret access key can be retrieved only at the time you create it.'
        - macro: '{$AWS.STS.REGION}'
          value: us-east-1
          description: 'Region used in assume role request.'
          config:
            type: TEXT
            priority: '9'
            label: 'STS Region'
            description: 'The AWS region for the assume role request.'
      dashboards:
        - uuid: 1020fa347dd24a2ba4091528e63639d4
          name: 'Overview AWS ELB Application Load Balancer'
          pages:
            - name: 'AWS ELB ALB: Metrics'
              widgets:
                - type: svggraph
                  name: 'AWS ELB ALB: HTTP Code'
                  width: '72'
                  height: '5'
                  fields:
                    - type: STRING
                      name: ds.0.color.0
                      value: FFA726
                    - type: STRING
                      name: ds.0.color.1
                      value: FF465C
                    - type: STRING
                      name: ds.0.color.2
                      value: FF5722
                    - type: INTEGER
                      name: ds.0.dataset_type
                      value: '0'
                    - type: ITEM
                      name: ds.0.itemids.0
                      value:
                        host: 'AWS ELB Application Load Balancer by HTTP'
                        key: aws.elb.alb.http_3xx_count
                    - type: ITEM
                      name: ds.0.itemids.1
                      value:
                        host: 'AWS ELB Application Load Balancer by HTTP'
                        key: aws.elb.alb.http_4xx_count
                    - type: ITEM
                      name: ds.0.itemids.2
                      value:
                        host: 'AWS ELB Application Load Balancer by HTTP'
                        key: aws.elb.alb.http_5xx_count
                    - type: STRING
                      name: reference
                      value: AAAAD
                    - type: INTEGER
                      name: simple_triggers
                      value: '1'
                    - type: INTEGER
                      name: working_time
                      value: '1'
                - type: svggraph
                  name: 'AWS ELB ALB: Connection Count'
                  'y': '5'
                  width: '72'
                  height: '5'
                  fields:
                    - type: STRING
                      name: ds.0.color.0
                      value: 4CAF50
                    - type: STRING
                      name: ds.0.color.1
                      value: 0080FF
                    - type: STRING
                      name: ds.0.color.2
                      value: CC6600
                    - type: STRING
                      name: ds.0.color.3
                      value: B71C1C
                    - type: INTEGER
                      name: ds.0.dataset_type
                      value: '0'
                    - type: ITEM
                      name: ds.0.itemids.0
                      value:
                        host: 'AWS ELB Application Load Balancer by HTTP'
                        key: aws.elb.alb.active_connection_count
                    - type: ITEM
                      name: ds.0.itemids.1
                      value:
                        host: 'AWS ELB Application Load Balancer by HTTP'
                        key: aws.elb.alb.new_connection_count
                    - type: ITEM
                      name: ds.0.itemids.2
                      value:
                        host: 'AWS ELB Application Load Balancer by HTTP'
                        key: aws.elb.alb.rejected_connection_count
                    - type: ITEM
                      name: ds.0.itemids.3
                      value:
                        host: 'AWS ELB Application Load Balancer by HTTP'
                        key: aws.elb.alb.target_connection_error_count
                    - type: STRING
                      name: reference
                      value: AAAAC
                    - type: INTEGER
                      name: simple_triggers
                      value: '1'
                    - type: INTEGER
                      name: working_time
                      value: '1'
                - type: svggraph
                  name: 'AWS ELB ALB: Requests Count and Response Time'
                  'y': '10'
                  width: '72'
                  height: '5'
                  fields:
                    - type: STRING
                      name: ds.0.color.0
                      value: 0080FF
                    - type: INTEGER
                      name: ds.0.dataset_type
                      value: '0'
                    - type: ITEM
                      name: ds.0.itemids.0
                      value:
                        host: 'AWS ELB Application Load Balancer by HTTP'
                        key: aws.elb.alb.requests_count
                    - type: INTEGER
                      name: ds.1.axisy
                      value: '1'
                    - type: STRING
                      name: ds.1.color.0
                      value: B0AF07
                    - type: INTEGER
                      name: ds.1.dataset_type
                      value: '0'
                    - type: ITEM
                      name: ds.1.itemids.0
                      value:
                        host: 'AWS ELB Application Load Balancer by HTTP'
                        key: aws.elb.alb.target_response_time
                    - type: STRING
                      name: reference
                      value: AAAAB
                    - type: INTEGER
                      name: working_time
                      value: '1'
                - type: svggraph
                  name: 'AWS ELB ALB: Consumed LCUs and Processed Bytes'
                  'y': '15'
                  width: '72'
                  height: '5'
                  fields:
                    - type: STRING
                      name: ds.0.color.0
                      value: 78909C
                    - type: INTEGER
                      name: ds.0.dataset_type
                      value: '0'
                    - type: ITEM
                      name: ds.0.itemids.0
                      value:
                        host: 'AWS ELB Application Load Balancer by HTTP'
                        key: aws.elb.alb.capacity_units
                    - type: INTEGER
                      name: ds.1.axisy
                      value: '1'
                    - type: STRING
                      name: ds.1.color.0
                      value: AB47BC
                    - type: INTEGER
                      name: ds.1.dataset_type
                      value: '0'
                    - type: ITEM
                      name: ds.1.itemids.0
                      value:
                        host: 'AWS ELB Application Load Balancer by HTTP'
                        key: aws.elb.alb.processed_bytes
                    - type: STRING
                      name: reference
                      value: AAAAA
                    - type: INTEGER
                      name: working_time
                      value: '1'
            - name: 'AWS ELB ALB Target Groups: Metrics'
              widgets:
                - type: piechart
                  name: 'Healthy Host Count'
                  width: '12'
                  height: '4'
                  fields:
                    - type: INTEGER
                      name: draw_type
                      value: '1'
                    - type: STRING
                      name: ds.0.color
                      value: 00FF00
                    - type: STRING
                      name: ds.0.data_set_label
                      value: 'Healthy Host Count'
                    - type: STRING
                      name: ds.0.items.0
                      value: '*: Healthy Host Count'
                    - type: INTEGER
                      name: legend_aggregation
                      value: '1'
                    - type: INTEGER
                      name: total_show
                      value: '1'
                - type: svggraph
                  name: 'HTTP Code Target Group'
                  'y': '4'
                  width: '72'
                  height: '5'
                  fields:
                    - type: STRING
                      name: ds.0.data_set_label
                      value: 'HTTP Code Target Group'
                    - type: STRING
                      name: ds.0.items.0
                      value: '*: HTTP Code Target*'
                    - type: INTEGER
                      name: ds.0.transparency
                      value: '6'
                    - type: INTEGER
                      name: ds.0.type
                      value: '3'
                    - type: STRING
                      name: reference
                      value: QZUQY
                - type: svggraph
                  name: 'Request Count Per Target'
                  'y': '9'
                  width: '72'
                  height: '5'
                  fields:
                    - type: STRING
                      name: ds.0.color
                      value: 388E3C
                    - type: STRING
                      name: ds.0.data_set_label
                      value: 'Request Count Per Target'
                    - type: INTEGER
                      name: ds.0.fill
                      value: '5'
                    - type: STRING
                      name: ds.0.items.0
                      value: '*: Request Count Per Target'
                    - type: INTEGER
                      name: ds.0.missingdatafunc
                      value: '2'
                    - type: INTEGER
                      name: ds.0.transparency
                      value: '7'
                    - type: INTEGER
                      name: ds.0.width
                      value: '6'
                    - type: STRING
                      name: reference
                      value: COJBR
                - type: piechart
                  name: 'Unhealthy Host Count'
                  x: '12'
                  width: '12'
                  height: '4'
                  fields:
                    - type: INTEGER
                      name: draw_type
                      value: '1'
                    - type: STRING
                      name: ds.0.data_set_label
                      value: 'Unhealthy Host Count'
                    - type: STRING
                      name: ds.0.items.0
                      value: '*: Unhealthy Host Count'
                    - type: INTEGER
                      name: legend_aggregation
                      value: '1'
                    - type: INTEGER
                      name: total_show
                      value: '1'
                - type: piechart
                  name: 'Healthy State Routing'
                  x: '24'
                  width: '12'
                  height: '4'
                  fields:
                    - type: INTEGER
                      name: draw_type
                      value: '1'
                    - type: STRING
                      name: ds.0.color
                      value: 00897B
                    - type: STRING
                      name: ds.0.data_set_label
                      value: 'Healthy State Routing'
                    - type: STRING
                      name: ds.0.items.0
                      value: '*: Healthy State Routing'
                    - type: INTEGER
                      name: legend_aggregation
                      value: '1'
                    - type: INTEGER
                      name: total_show
                      value: '1'
                - type: piechart
                  name: 'Unhealthy State Routing'
                  x: '36'
                  width: '12'
                  height: '4'
                  fields:
                    - type: INTEGER
                      name: draw_type
                      value: '1'
                    - type: STRING
                      name: ds.0.data_set_label
                      value: 'Unhealthy State Routing'
                    - type: STRING
                      name: ds.0.items.0
                      value: '*: Unhealthy State Routing'
                    - type: INTEGER
                      name: legend_aggregation
                      value: '1'
                    - type: INTEGER
                      name: total_show
                      value: '1'
                - type: piechart
                  name: 'Healthy State DNS'
                  x: '48'
                  width: '12'
                  height: '4'
                  fields:
                    - type: INTEGER
                      name: draw_type
                      value: '1'
                    - type: STRING
                      name: ds.0.color
                      value: '283593'
                    - type: STRING
                      name: ds.0.data_set_label
                      value: 'Healthy State DNS'
                    - type: STRING
                      name: ds.0.items.0
                      value: '*: Healthy State DNS'
                    - type: INTEGER
                      name: legend_aggregation
                      value: '1'
                    - type: INTEGER
                      name: total_show
                      value: '1'
                - type: piechart
                  name: 'Unhealthy State DNS'
                  x: '60'
                  width: '12'
                  height: '4'
                  fields:
                    - type: INTEGER
                      name: draw_type
                      value: '1'
                    - type: STRING
                      name: ds.0.data_set_label
                      value: 'Unhealthy State DNS'
                    - type: STRING
                      name: ds.0.items.0
                      value: '*: Unhealthy State DNS'
                    - type: INTEGER
                      name: legend_aggregation
                      value: '1'
                    - type: INTEGER
                      name: total_show
                      value: '1'
      valuemaps:
        - uuid: 4bb749152d5d452ead36c5a98c3cac16
          name: 'Alarm state'
          mappings:
            - value: '0'
              newvalue: OK
            - value: '1'
              newvalue: 'Insufficient data'
            - value: '2'
              newvalue: Alarm
            - value: '255'
              newvalue: Unknown
    - uuid: 4c7d0c6e342b40458611bdb6e9dd958f
      template: 'AWS ELB Network Load Balancer by HTTP'
      name: 'AWS ELB Network Load Balancer by HTTP'
      description: |
        The template is designed to monitor AWS ELB Network Load Balancer by HTTP via Zabbix, and it works without any external scripts.
        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"
      wizard_ready: 'YES'
      readme: |
        ## Overview
        
        The template is designed to monitor AWS ELB Network Load Balancer by HTTP via Zabbix, and it works without any external scripts.
        Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
        
        This template uses the GetMetricData CloudWatch API calls to list and retrieve metrics.
        For more information, please refer to the [CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) page.
        
        Additional information about metrics and API methods used in the template:
        * [Full metrics list related to AWS ELB Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-cloudwatch-metrics.html)
        * [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
        * [DescribeTargetGroups API method](https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_DescribeTargetGroups.html)
        
        
        ## Setup
        
        The template gets AWS ELB Network Load Balancer metrics and uses the script item to make HTTP requests to the CloudWatch API.
        
        Before using the template, you need to create an IAM policy with the necessary permissions for the Zabbix role in your AWS account. For more information, visit the [ELB policies page](https://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/elb-api-permissions.html) on the AWS website.
        
        ### Required Permissions
        Add the following required permissions to your Zabbix IAM policy in order to collect AWS ELB Network Load Balancer metrics.
        
        ```json
        {
            "Version":"2012-10-17",
            "Statement":[
                {
                  "Action":[
                      "cloudwatch:DescribeAlarms",
                      "cloudwatch:GetMetricData",
                      "elasticloadbalancing:DescribeTargetGroups"
                  ],
                  "Effect":"Allow",
                  "Resource":"*"
                }
            ]
          }
        ```
        
        ### Access Key Authorization
        
        If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
        
        1. Create an IAM user with programmatic access.
        2. Attach the required policy to the IAM user.
        3. Generate an access key and secret key.
        4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
        
        ### Assume role authorization
        For using assume role authorization, add the appropriate permissions to the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "sts:AssumeRole",
                    "Resource": "arn:aws:iam::{Account}:user/{UserName}"
                },
                {
                    "Effect": "Allow",
                    "Action": [
                        "cloudwatch:DescribeAlarms",
                        "cloudwatch:GetMetricData",
                        "elasticloadbalancing:DescribeTargetGroups"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        
        #### Trust Relationships for Assume Role Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "AWS": "arn:aws:iam::{Account}:user/{UserName}"
              },
              "Action": "sts:AssumeRole"
            }
          ]
        }
        ```
        Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
        
        ### Role-Based Authorization
        If you are using role-based authorization, set the appropriate permissions:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "iam:PassRole",
                    "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
                },
                {
                    "Sid": "VisualEditor1",
                    "Effect": "Allow",
                    "Action": [
                        "cloudwatch:DescribeAlarms",
                        "cloudwatch:GetMetricData",
                        "elasticloadbalancing:DescribeTargetGroups",
                        "ec2:AssociateIamInstanceProfile",
                        "ec2:ReplaceIamInstanceProfileAssociation"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        
        #### Trust Relationships for Role-Based Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": [
                            "ec2.amazonaws.com"
                        ]
                    },
                    "Action": [
                        "sts:AssumeRole"
                    ]
                }
            ]
        }
        ```
        
        **Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
        
        Set the following fields: `Authorization method`, `AWS Region`, and `Load Balancer ARN`.
        
        For more information about managing access keys, see [official AWS documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).
      vendor:
        name: Zabbix
        version: 8.0-3
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 170a4e084c3748dfa1cfcbb1b168ff4c
          name: 'Active Flow Count'
          type: DEPENDENT
          key: aws.elb.nlb.active_flow_count
          description: |
            The total number of concurrent flows (or connections) from clients to targets.
            This metric includes connections in the `SYN_SENT` and `ESTABLISHED` states.
            TCP connections are not terminated at the load balancer, so a client opening a TCP connection to a target counts as a single flow.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ActiveFlowCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: connections
        - uuid: fd00c2998ae145ab821acde0a1515fbb
          name: 'Active Flow Count TCP'
          type: DEPENDENT
          key: aws.elb.nlb.active_flow_count_tcp
          description: |
            The total number of concurrent TCP flows (or connections) from clients to targets.
            This metric includes connections in the `SYN_SENT` and `ESTABLISHED` states.
            TCP connections are not terminated at the load balancer, so a client opening a TCP connection to a target counts as a single flow.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ActiveFlowCount_TCP")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: connections
            - tag: component
              value: tcp
        - uuid: 31ae92c16e5643d3a67f392661518723
          name: 'Active Flow Count TLS'
          type: DEPENDENT
          key: aws.elb.nlb.active_flow_count_tls
          description: |
            The total number of concurrent TLS flows (or connections) from clients to targets.
            This metric includes connections in the `SYN_SENT` and `ESTABLISHED` states.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ActiveFlowCount_TLS")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: connections
            - tag: component
              value: tls
        - uuid: 7ba1f232eacc41cfa6e38939128b9ee1
          name: 'Active Flow Count UDP'
          type: DEPENDENT
          key: aws.elb.nlb.active_flow_count_udp
          description: 'The total number of concurrent UDP flows (or connections) from clients to targets.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ActiveFlowCount_UDP")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: connections
            - tag: component
              value: udp
        - uuid: 397ce9711a404da48ebdfde65c24ff3b
          name: 'Get alarms check'
          type: DEPENDENT
          key: aws.elb.nlb.alarms.check
          value_type: CHAR
          description: 'Check that the alarm data has been received correctly.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.elb.nlb.get_alarms
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: 4319dc0d484b456a9343535db3c079f4
              expression: 'length(last(/AWS ELB Network Load Balancer by HTTP/aws.elb.nlb.alarms.check))>0'
              name: 'AWS ELB NLB: Failed to get alarms data'
              event_name: 'AWS ELB NLB: Failed to get CloudWatch alarms for Network Load Balancer'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Failed to get CloudWatch alarms for Network Load Balancer.'
              tags:
                - tag: scope
                  value: availability
        - uuid: b2ef5e512e674a969853b389f308664e
          name: 'Consumed LCUs'
          type: DEPENDENT
          key: aws.elb.nlb.capacity_units
          description: |
            The number of load balancer capacity units (LCU) used by your load balancer.
            You pay for the number of LCUs that you use per hour.
            More information on Elastic Load Balancing pricing here: https://aws.amazon.com/elasticloadbalancing/pricing/
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ConsumedLCUs")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: capacity
        - uuid: 33c9d9d275c04811b7dcb6806e8a9d9a
          name: 'Consumed LCUs TCP'
          type: DEPENDENT
          key: aws.elb.nlb.capacity_units_tcp
          description: |
            The number of load balancer capacity units (LCU) used by your load balancer for TCP.
            You pay for the number of LCUs that you use per hour.
            More information on Elastic Load Balancing pricing here: https://aws.amazon.com/elasticloadbalancing/pricing/
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ConsumedLCUs_TCP")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: capacity
            - tag: component
              value: tcp
        - uuid: bbcd303cbf654dc68fb40216994eef84
          name: 'Consumed LCUs TLS'
          type: DEPENDENT
          key: aws.elb.nlb.capacity_units_tls
          description: |
            The number of load balancer capacity units (LCU) used by your load balancer for TLS.
            You pay for the number of LCUs that you use per hour.
            More information on Elastic Load Balancing pricing here: https://aws.amazon.com/elasticloadbalancing/pricing/
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ConsumedLCUs_TLS")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: capacity
            - tag: component
              value: tls
        - uuid: 90742c0ffb4844668f59a75f26132b18
          name: 'Consumed LCUs UDP'
          type: DEPENDENT
          key: aws.elb.nlb.capacity_units_udp
          description: |
            The number of load balancer capacity units (LCU) used by your load balancer for UDP.
            You pay for the number of LCUs that you use per hour.
            More information on Elastic Load Balancing pricing here: https://aws.amazon.com/elasticloadbalancing/pricing/
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ConsumedLCUs_UDP")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: capacity
            - tag: component
              value: udp
        - uuid: 6bbe06db758f40da9c2e0cb825b2aac3
          name: 'Client TLS Negotiation Error Count'
          type: DEPENDENT
          key: aws.elb.nlb.client_tls_negotiation_error_count
          description: 'The total number of TLS handshakes that failed during negotiation between a client and a TLS listener.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ClientTLSNegotiationErrorCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: health
            - tag: component
              value: tls
        - uuid: 6d74c1a68ea9476dadc39b785f333d5d
          name: 'Get ELB NLB alarms data'
          type: SCRIPT
          key: aws.elb.nlb.get_alarms
          delay: 0s;m/1
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', 'arn', 'loadbalancer_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'),
            			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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS ELB ] Sending request: ' + url);
            		response = request.get(url);
            		Zabbix.log(4, '[ AWS ELB ] 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) {
            			try {
            				response = JSON.parse(XML.toJson(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');
            			regex = /loadbalancer\/(.+)$/;
            
            			if (!Array.isArray(alarms_list))
            				alarms_list = [alarms_list];
            			alarms_list.forEach(function (alarm) {
            				var dimensions = alarm.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 === 'LoadBalancer' && dimensions[i].Value === AWS.params.arn.match(regex)[1])
            						|| (dimensions[i].Name === 'LoadBalancerName' && dimensions[i].Value === AWS.params.loadbalancer_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 ELB Alarms ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: '`DescribeAlarms` API method: https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html'
          preprocessing:
            - type: CHECK_NOT_SUPPORTED
              parameters:
                - '-1'
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: arn
              value: '{$AWS.ELB.ARN}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: loadbalancer_name
              value: '{$AWS.ELB.NAME}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: 76d374302b29430c8fe5813656ffd928
          name: 'Get metrics data'
          type: SCRIPT
          key: aws.elb.nlb.get_metrics
          delay: 0s;m/1
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            	request_period: 60,
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('POST', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', 'arn'].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('&');
            	},
            
            	renderMetricQuery: function (period, arn) {
            		var metrics_list = [
            			'ActiveFlowCount:Average',
            			'ActiveFlowCount_TCP:Average',
            			'ActiveFlowCount_TLS:Average',
            			'ActiveFlowCount_UDP:Average',
            			'ClientTLSNegotiationErrorCount:Sum',
            			'ConsumedLCUs:Sum',
            			'ConsumedLCUs_TCP:Sum',
            			'ConsumedLCUs_TLS:Sum',
            			'ConsumedLCUs_UDP:Sum',
            			'NewFlowCount:Sum',
            			'NewFlowCount_TCP:Sum',
            			'NewFlowCount_TLS:Sum',
            			'NewFlowCount_UDP:Sum',
            			'PeakPacketsPerSecond:Maximum',
            			'PortAllocationErrorCount:Sum',
            			'SecurityGroupBlockedFlowCount_Inbound_ICMP:Sum',
            			'SecurityGroupBlockedFlowCount_Inbound_TCP:Sum',
            			'SecurityGroupBlockedFlowCount_Inbound_UDP:Sum',
            			'SecurityGroupBlockedFlowCount_Outbound_ICMP:Sum',
            			'SecurityGroupBlockedFlowCount_Outbound_TCP:Sum',
            			'SecurityGroupBlockedFlowCount_Outbound_UDP:Sum',
            			'ProcessedBytes:Sum',
            			'ProcessedBytes_TCP:Sum',
            			'ProcessedBytes_TLS:Sum',
            			'ProcessedBytes_UDP:Sum',
            			'ProcessedPackets:Sum',
            			'TargetTLSNegotiationErrorCount:Sum',
            			'TCP_Client_Reset_Count:Sum',
            			'TCP_ELB_Reset_Count:Sum',
            			'TCP_Target_Reset_Count:Sum',
            			'UnhealthyRoutingFlowCount:Sum'
            		],
            			regex = /loadbalancer\/(.+)$/;
            
            		var metric_payload = [];
            		metrics_list.forEach(function (metric, index) {
            			var parts = metric.split(':', 2);
            			metric_payload.push({
            				'Id': 'm' + index,
            				'MetricStat': {
            					'Metric': {
            						'MetricName': parts[0],
            						'Namespace': 'AWS/NetworkELB',
            						'Dimensions': [
            							{
            								'Name': 'LoadBalancer',
            								'Value': arn.match(regex)[1],
            							}
            						]
            					},
            					'Period': period,
            					'Stat': parts[1],
            				}
            			});
            		});
            
            		return metric_payload;
            	},
            
            	request: function (method, region, service, params, data) {
            		if (typeof data === 'undefined' || data === null) {
            			data = JSON.stringify([]);
            		}
            		else {
            			data = JSON.stringify(data)
            		}
            		var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''),
            			date = amzdate.replace(/T\d+Z/, ''),
            			canonical_uri = '/',
            			host = service + '.' + region + '.amazonaws.com',
            			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'),
            			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('X-Amz-Target: GraniteServiceVersion20100801.GetMetricData')
            		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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS ELB ] Sending request: ' + url);
            		response = request.post(url, data);
            		Zabbix.log(4, '[ AWS ELB ] Received response with status code ' + request.getStatus() + ': ' + response);
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		return JSON.parse(response);
            	},
            
            	getMetricsData: function () {
            		var end_time = Math.floor((new Date().getTime()) / 1000),
            			start_time = end_time - AWS.request_period * 60;
            		payload = {
            			'StartTime': start_time,
            			'EndTime': end_time,
            			'ScanBy': 'TimestampDescending',
            			'MetricDataQueries': AWS.renderMetricQuery(AWS.request_period, AWS.params.arn)
            		};
            
            		return AWS.getField(AWS.request('POST', AWS.params.region, 'monitoring', '', payload), 'MetricDataResults');
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            	return JSON.stringify(AWS.getMetricsData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS ELB Get metrics] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: |
            Get ELB Network Load Balancer metrics.
            Full metrics list related to Network Load Balancer: https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-cloudwatch-metrics.html
          preprocessing:
            - type: CHECK_NOT_SUPPORTED
              parameters:
                - '-1'
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: arn
              value: '{$AWS.ELB.ARN}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: d80c238267744bc9b46de217acd93842
          name: 'Get target groups'
          type: SCRIPT
          key: aws.elb.nlb.get_target_groups
          delay: 0s;m/30
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', 'arn'].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 = JSON.stringify([]);
            		}
            		var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''),
            			date = amzdate.replace(/T\d+Z/, ''),
            			canonical_uri = '/',
            			host = service + '.' + region + '.amazonaws.com',
            			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'),
            			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/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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS ELB ] Sending request: ' + url);
            		response = request.get(url);
            		Zabbix.log(4, '[ AWS ELB ] Received response with status code ' + request.getStatus() + ': ' + response);
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		return JSON.parse(response);
            	},
            
            	listTargetGroups: function () {
            		var lld_array = [],
            			regex = /targetgroup\/(.+)$/,
            			payload = {
            				'Action': 'DescribeTargetGroups',
            				'LoadBalancerArn': AWS.params.arn,
            				'Version': '2015-12-01'
            			};
            		targets = AWS.getField(AWS.request('GET', AWS.params.region, 'elasticloadbalancing', AWS.prepareParams(payload), ''), 'DescribeTargetGroupsResponse.DescribeTargetGroupsResult.TargetGroups');
            
            		if (!Array.isArray(targets))
            			targets = [targets]
            
            		targets.forEach(function (targets) {
            			lld_array.push(
            				{
            					target_name: AWS.getField(targets, 'TargetGroupName'),
            					target_arn: AWS.getField(targets, 'TargetGroupArn').match(regex)[0],
            					type: AWS.getField(targets, 'TargetType'),
            					protocol: AWS.getField(targets, 'Protocol')
            				}
            			)
            		});
            
            		return lld_array;
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            	return JSON.stringify(AWS.listTargetGroups());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS ELB Target groups ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: |
            Get ELB target group.
            `DescribeTargetGroups` API method: https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_DescribeTargetGroups.html
          preprocessing:
            - type: CHECK_NOT_SUPPORTED
              parameters:
                - '-1'
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: arn
              value: '{$AWS.ELB.ARN}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: 13516270f6124bf09a308bc20565528c
          name: 'Get metrics check'
          type: DEPENDENT
          key: aws.elb.nlb.metrics.check
          value_type: CHAR
          description: 'Check that the Network Load Balancer metrics data has been received correctly.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: c2ba26fed3324a2bb9b90493a99db088
              expression: 'length(last(/AWS ELB Network Load Balancer by HTTP/aws.elb.nlb.metrics.check))>0'
              name: 'AWS ELB NLB: Failed to get metrics data'
              event_name: 'AWS ELB NLB: Failed to get CloudWatch metrics for Network Load Balancer'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Failed to get CloudWatch metrics for Network Load Balancer.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 38a2dca1cca34a1988dd8713552c952b
          name: 'New Flow Count'
          type: DEPENDENT
          key: aws.elb.nlb.new_flow_count
          description: 'The total number of new flows (or connections) established from clients to targets in the specified time period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "NewFlowCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: connections
        - uuid: a34d5ded1ec445b89a681a39b854b6cd
          name: 'New Flow Count TCP'
          type: DEPENDENT
          key: aws.elb.nlb.new_flow_count_tcp
          description: 'The total number of new TCP flows (or connections) established from clients to targets in the specified time period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "NewFlowCount_TCP")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: connections
            - tag: component
              value: tcp
        - uuid: 25ec5461aa3f477c8698d3b31ed3263c
          name: 'New Flow Count TLS'
          type: DEPENDENT
          key: aws.elb.nlb.new_flow_count_tls
          description: 'The total number of new TLS flows (or connections) established from clients to targets in the specified time period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "NewFlowCount_TLS")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: connections
            - tag: component
              value: tls
        - uuid: 3f8fb9c0de524d0b9f157a9291fd7f27
          name: 'New Flow Count UDP'
          type: DEPENDENT
          key: aws.elb.nlb.new_flow_count_udp
          description: 'The total number of new UDP flows (or connections) established from clients to targets in the specified time period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "NewFlowCount_UDP")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: connections
            - tag: component
              value: udp
        - uuid: ffda7926a52c438c8195f70d772a4f7e
          name: 'Peak Packets per second'
          type: DEPENDENT
          key: aws.elb.nlb.peak_packets.rate
          description: |
            Highest average packet rate (packets processed per second), calculated every 10 seconds during the sampling window.
            This metric includes health check traffic.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "PeakPacketsPerSecond")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: health
            - tag: component
              value: traffic
        - uuid: e83d4c875f414628987989a8e5e27c9e
          name: 'Port Allocation Error Count'
          type: DEPENDENT
          key: aws.elb.nlb.port_allocation_error_count
          description: |
            The total number of ephemeral port allocation errors during a client IP translation operation. A non-zero value indicates dropped client connections.
            Note: Network Load Balancers support 55,000 simultaneous connections or about 55,000 connections per minute to each unique target (IP address and port) when performing client address translation.
            To fix port allocation errors, add more targets to the target group.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "PortAllocationErrorCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: connections
            - tag: component
              value: health
        - uuid: 38cca57bd12048558d8569e6a9d18492
          name: 'Processed Bytes'
          type: DEPENDENT
          key: aws.elb.nlb.processed_bytes
          units: B
          description: 'The total number of bytes processed by the load balancer, including TCP/IP headers. This count includes traffic to and from targets, minus health check traffic.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ProcessedBytes")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: traffic
        - uuid: a6b272d40c3d4b72adcced4aadaa607c
          name: 'Processed Bytes TCP'
          type: DEPENDENT
          key: aws.elb.nlb.processed_bytes_tcp
          units: B
          description: 'The total number of bytes processed by TCP listeners.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ProcessedBytes_TCP")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: tcp
            - tag: component
              value: traffic
        - uuid: c1e6456cd23446808299396f6368d6a9
          name: 'Processed Bytes TLS'
          type: DEPENDENT
          key: aws.elb.nlb.processed_bytes_tls
          units: B
          description: 'The total number of bytes processed by TLS listeners.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ProcessedBytes_TLS")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: tls
            - tag: component
              value: traffic
        - uuid: 5c5e1be4725d4908adc0c506c98a6cab
          name: 'Processed Bytes UDP'
          type: DEPENDENT
          key: aws.elb.nlb.processed_bytes_udp
          units: B
          description: 'The total number of bytes processed by UDP listeners.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ProcessedBytes_UDP")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: traffic
            - tag: component
              value: udp
        - uuid: c41394db6dba4693b4c19aebdc2e8f69
          name: 'Processed Packets'
          type: DEPENDENT
          key: aws.elb.nlb.processed_packets
          description: 'The total number of packets processed by the load balancer. This count includes traffic to and from targets, including health check traffic.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ProcessedPackets")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: traffic
        - uuid: 28bb42c1af9d4ee782a4ac1e75194293
          name: 'Security Group Blocked Flow Count Inbound ICMP'
          type: DEPENDENT
          key: aws.elb.nlb.sg_blocked_inbound_icmp
          description: 'The number of new ICMP messages rejected by the inbound rules of the load balancer security groups.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "SecurityGroupBlockedFlowCount_Inbound_ICMP")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: icmp
            - tag: component
              value: security-group
        - uuid: 95db8688978d4fc0b3a54c01c34cd0c7
          name: 'Security Group Blocked Flow Count Inbound TCP'
          type: DEPENDENT
          key: aws.elb.nlb.sg_blocked_inbound_tcp
          description: 'The number of new TCP flows rejected by the inbound rules of the load balancer security groups.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "SecurityGroupBlockedFlowCount_Inbound_TCP")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: security-group
            - tag: component
              value: tcp
        - uuid: 287e26627214470bba9589af506ca832
          name: 'Security Group Blocked Flow Count Inbound UDP'
          type: DEPENDENT
          key: aws.elb.nlb.sg_blocked_inbound_udp
          description: 'The number of new UDP flows rejected by the inbound rules of the load balancer security groups.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "SecurityGroupBlockedFlowCount_Inbound_UDP")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: security-group
            - tag: component
              value: udp
        - uuid: 65a6fb4771114377bcdf93dc09665b2b
          name: 'Security Group Blocked Flow Count Outbound ICMP'
          type: DEPENDENT
          key: aws.elb.nlb.sg_blocked_outbound_icmp
          description: 'The number of new ICMP messages rejected by the outbound rules of the load balancer security groups.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "SecurityGroupBlockedFlowCount_Outbound_ICMP")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: icmp
            - tag: component
              value: security-group
        - uuid: 343b254cfc1a48cc8e401cd3514c76b3
          name: 'Security Group Blocked Flow Count Outbound TCP'
          type: DEPENDENT
          key: aws.elb.nlb.sg_blocked_outbound_tcp
          description: 'The number of new TCP flows rejected by the outbound rules of the load balancer security groups.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "SecurityGroupBlockedFlowCount_Outbound_TCP")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: security-group
            - tag: component
              value: tcp
        - uuid: 5a9126687a964f969270bc1855081a7a
          name: 'Security Group Blocked Flow Count Outbound UDP'
          type: DEPENDENT
          key: aws.elb.nlb.sg_blocked_outbound_udp
          description: 'The number of new UDP flows rejected by the outbound rules of the load balancer security groups.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "SecurityGroupBlockedFlowCount_Outbound_UDP")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: security-group
            - tag: component
              value: udp
        - uuid: 583872d175174881a8cdcede4fe641e7
          name: 'Target TLS Negotiation Error Count'
          type: DEPENDENT
          key: aws.elb.nlb.target_tls_negotiation_error_count
          description: 'The total number of TLS handshakes that failed during negotiation between a TLS listener and a target.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "TargetTLSNegotiationErrorCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: health
            - tag: component
              value: tls
        - uuid: 035021358b9f4ae2b0478d5168fc1501
          name: 'TCP Client Reset Count'
          type: DEPENDENT
          key: aws.elb.nlb.tcp_client_reset_count
          description: |
            The total number of reset (RST) packets sent from a client to a target.
            These resets are generated by the client and forwarded by the load balancer.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "TCP_Client_Reset_Count")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: health
            - tag: component
              value: tcp
        - uuid: 84f23b89fb414731979941a9a4701025
          name: 'TCP ELB Reset Count'
          type: DEPENDENT
          key: aws.elb.nlb.tcp_elb_reset_count
          description: |
            The total number of reset (RST) packets generated by the load balancer.
            For more information, see: https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-troubleshooting.html#elb-reset-count-metric
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "TCP_ELB_Reset_Count")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: health
            - tag: component
              value: tcp
        - uuid: 3318c330736e406c9eec5f581f3fc59b
          name: 'TCP Target Reset Count'
          type: DEPENDENT
          key: aws.elb.nlb.tcp_target_reset_count
          description: |
            The total number of reset (RST) packets sent from a target to a client.
            These resets are generated by the target and forwarded by the load balancer.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "TCP_Target_Reset_Count")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: health
            - tag: component
              value: tcp
        - uuid: 706019d7a11e48a9aaa1b5484c93fd8e
          name: 'Unhealthy Routing Flow Count'
          type: DEPENDENT
          key: aws.elb.nlb.unhealthy_routing_flow_count
          description: 'The number of flows (or connections) that are routed using the routing failover action (fail open).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "UnhealthyRoutingFlowCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.elb.nlb.get_metrics
          tags:
            - tag: component
              value: health
      discovery_rules:
        - uuid: 92bef05094464c16b03b37f1f797d436
          name: 'Load Balancer alarm discovery'
          type: DEPENDENT
          key: aws.elb.nlb.alarms.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.ELB.LLD.FILTER.ALARM_NAME.MATCHES}'
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.ELB.LLD.FILTER.ALARM_NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#ALARM_SERVICE_NAMESPACE}'
                value: '{$AWS.ELB.LLD.FILTER.ALARM_SERVICE_NAMESPACE.MATCHES}'
              - macro: '{#ALARM_SERVICE_NAMESPACE}'
                value: '{$AWS.ELB.LLD.FILTER.ALARM_SERVICE_NAMESPACE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Used for the discovery of alarm balancers.'
          item_prototypes:
            - uuid: c9f5791fe83743739ab74289126c7843
              name: '[{#ALARM_NAME}]: Get metrics'
              type: DEPENDENT
              key: 'aws.elb.nlb.alarm.get_metrics["{#ALARM_NAME}"]'
              history: '0'
              value_type: TEXT
              description: 'Get metrics about the alarm state and its reason.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.AlarmName == "{#ALARM_NAME}")].first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.elb.nlb.get_alarms
              tags:
                - tag: component
                  value: raw
            - uuid: 3e039e2d86654095b0c9fa93f7273cab
              name: '[{#ALARM_NAME}]: State'
              type: DEPENDENT
              key: 'aws.elb.nlb.alarm.state["{#ALARM_NAME}"]'
              description: |
                The value of the alarm state. 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.elb.nlb.alarm.get_metrics["{#ALARM_NAME}"]'
              tags:
                - tag: component
                  value: alarms
              trigger_prototypes:
                - uuid: 0df06bb3cad742368204984c83f3c161
                  expression: 'last(/AWS ELB Network Load Balancer by HTTP/aws.elb.nlb.alarm.state["{#ALARM_NAME}"])=1'
                  name: 'AWS ELB NLB: [{#ALARM_NAME}] has ''Insufficient data'' state'
                  event_name: 'AWS ELB NLB: [{#ALARM_NAME}] has ''Insufficient data'' state'
                  opdata: 'Current value: {ITEM.LASTVALUE1}'
                  priority: INFO
                  description: 'Either the alarm has just started, the metric is not available, or not enough data is available for the metric to determine the alarm state.'
                  tags:
                    - tag: scope
                      value: notice
            - uuid: 8be7e86d50be4324ac6b7b8f20350eb0
              name: '[{#ALARM_NAME}]: State reason'
              type: DEPENDENT
              key: 'aws.elb.nlb.alarm.state_reason["{#ALARM_NAME}"]'
              value_type: TEXT
              description: |
                An explanation for the alarm state reason 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.elb.nlb.alarm.get_metrics["{#ALARM_NAME}"]'
              tags:
                - tag: component
                  value: alarms
          trigger_prototypes:
            - uuid: a4558b07342b4e758cde7866e9027acf
              expression: 'last(/AWS ELB Network Load Balancer by HTTP/aws.elb.nlb.alarm.state["{#ALARM_NAME}"])=2 and length(last(/AWS ELB Network Load Balancer by HTTP/aws.elb.nlb.alarm.state_reason["{#ALARM_NAME}"]))>0'
              name: 'AWS ELB NLB: [{#ALARM_NAME}] has ''Alarm'' state'
              event_name: 'AWS ELB NLB: [{#ALARM_NAME}] has ''Alarm'' state (reason: {ITEM.LASTVALUE2})'
              opdata: 'Reason: {ITEM.LASTVALUE2}'
              priority: AVERAGE
              description: |
                The alarm `{#ALARM_NAME}` is in the ALARM state.
                Reason: `{ITEM.LASTVALUE2}`
              tags:
                - tag: scope
                  value: availability
          master_item:
            key: aws.elb.nlb.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: bc0fa68299464e2ebb031b005bd7041a
          name: 'Target groups discovery'
          type: DEPENDENT
          key: aws.elb.nlb.target_groups.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.ELB.TARGET.GROUP.NAME}'
                value: '{$AWS.ELB.LLD.FILTER.TARGET.GROUP.MATCHES}'
              - macro: '{#AWS.ELB.TARGET.GROUP.NAME}'
                value: '{$AWS.ELB.LLD.FILTER.TARGET.GROUP.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Used for the discovery of `{$AWS.ELB.TARGET.GROUP.NAME}` target groups.'
          item_prototypes:
            - uuid: 9438a03b48bd4617a2363f83f758f107
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: Get metrics'
              type: SCRIPT
              key: 'aws.elb.nlb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              delay: 0s;m/5
              history: '0'
              value_type: TEXT
              params: |
                var AWS = {
                	params: {},
                	metadata: 'http://169.254.169.254/latest/',
                	request_period: 60,
                
                	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;
                	},
                
                	getRoleBaseCredentials: function () {
                		AWS.params['auth_type'] = 'role_base';
                		var request = new HttpRequest();
                		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
                			request.setProxy(AWS.params.proxy);
                		}
                		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
                		var token = request.put(AWS.metadata + 'api/token');
                
                		if (request.getStatus() !== 200 || token === null || token === '') {
                			throw 'Error getting IMDSv2 session token.';
                		}
                		request.addHeader('X-aws-ec2-metadata-token: ' + token);
                		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
                
                		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
                			throw 'Error getting security credentials from instance metadata. Role not found.';
                		}
                
                		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
                			};
                			AWS.params[field] = credentials[field];
                		});
                	},
                
                	setParams: function (params) {
                		AWS.params['proxy'] = params.proxy;
                		switch (AWS.getField(params, 'auth_type')) {
                			case 'role_base':
                				AWS.getRoleBaseCredentials();
                				break;
                			case 'assume_role':
                				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
                					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
                				}
                				if (params.metadata_auth === 'true') {
                					AWS.getRoleBaseCredentials();
                					AWS.params['SessionToken'] = AWS.params['Token'];
                					AWS.params['auth_type'] = 'assume_role_metadata';
                
                					['sts_region', 'role_arn'].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];
                					});
                				}
                
                				if (params.metadata_auth === 'false') {
                					AWS.params['auth_type'] = 'assume_role';
                
                					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
                					});
                				}
                
                				const role_arn_regex = /role\/(.+)$/;
                				const match = AWS.params.role_arn.match(role_arn_regex);
                				if (!match) {
                					throw 'Invalid role ARN format.';
                				}
                
                				const payload = {
                					'Action': 'AssumeRole',
                					'Version': '2011-06-15',
                					'RoleArn': AWS.params.role_arn,
                					'RoleSessionName': match[1] + 'Session',
                				};
                
                				credentials = AWS.getField(AWS.request('POST', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
                
                				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
                					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
                						throw 'Required credentials are not set: "' + field + '".';
                					};
                					AWS.params[field] = credentials[field];
                				});
                				break;
                			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', 'arn', 'target_arn'].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('&');
                	},
                
                	renderMetricQuery: function (period, arn, target_arn) {
                		var metrics_list = [
                			'HealthyHostCount:Minimum',
                			'UnHealthyHostCount:Maximum'
                		],
                			regex = /loadbalancer\/(.+)$/;
                
                		var metric_payload = [];
                		metrics_list.forEach(function (metric, index) {
                			var parts = metric.split(':', 2);
                			metric_payload.push({
                				'Id': 'm' + index,
                				'MetricStat': {
                					'Metric': {
                						'MetricName': parts[0],
                						'Namespace': 'AWS/NetworkELB',
                						'Dimensions': [
                							{
                								'Name': 'LoadBalancer',
                								'Value': arn.match(regex)[1],
                							},
                							{
                								'Name': 'TargetGroup',
                								'Value': target_arn
                							}
                						]
                					},
                					'Period': period,
                					'Stat': parts[1],
                				}
                			});
                		});
                
                		return metric_payload;
                	},
                
                	request: function (method, region, service, params, data) {
                		if (typeof data === 'undefined' || data === null) {
                			data = JSON.stringify([]);
                		}
                		else {
                			data = JSON.stringify(data)
                		}
                		var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''),
                			date = amzdate.replace(/T\d+Z/, ''),
                			canonical_uri = '/',
                			host = service + '.' + region + '.amazonaws.com',
                			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'),
                			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('X-Amz-Target: GraniteServiceVersion20100801.GetMetricData')
                		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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
                			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
                		}
                
                		Zabbix.log(4, '[ AWS ELB ] Sending request: ' + url);
                		response = request.post(url, data);
                		Zabbix.log(4, '[ AWS ELB ] Received response with status code ' + request.getStatus() + ': ' + response);
                		if (request.getStatus() !== 200) {
                			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
                		}
                
                		return JSON.parse(response);
                	},
                
                	getMetricsData: function () {
                		var end_time = Math.floor((new Date().getTime()) / 1000),
                			start_time = end_time - AWS.request_period * 60;
                		payload = {
                			'StartTime': start_time,
                			'EndTime': end_time,
                			'ScanBy': 'TimestampDescending',
                			'MetricDataQueries': AWS.renderMetricQuery(AWS.request_period, AWS.params.arn, AWS.params.target_arn)
                		};
                
                		return AWS.getField(AWS.request('POST', AWS.params.region, 'monitoring', '', payload), 'MetricDataResults');
                	}
                };
                
                try {
                	AWS.setParams(JSON.parse(value));
                	return JSON.stringify(AWS.getMetricsData());
                }
                catch (error) {
                	error += (String(error).endsWith('.')) ? '' : '.';
                	Zabbix.log(3, '[ AWS ELB Get targets group metrics] ERROR: ' + error);
                
                	return JSON.stringify({ 'error': error });
                }
              description: |
                Get the metrics of the ELB target group `{#AWS.ELB.TARGET.GROUP.NAME}`.
                Full list of metrics related to AWS ELB here: https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-cloudwatch-metrics.html#user-authentication-metric-table
              preprocessing:
                - type: CHECK_NOT_SUPPORTED
                  parameters:
                    - '-1'
              timeout: '{$AWS.DATA.TIMEOUT}'
              parameters:
                - name: AccessKeyId
                  value: '{$AWS.ACCESS.KEY.ID}'
                - name: arn
                  value: '{$AWS.ELB.ARN}'
                - name: auth_type
                  value: '{$AWS.AUTH_TYPE}'
                - name: metadata_auth
                  value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
                - name: proxy
                  value: '{$AWS.PROXY}'
                - name: region
                  value: '{$AWS.REGION}'
                - name: role_arn
                  value: '{$AWS.ASSUME.ROLE.ARN}'
                - name: SecretAccessKey
                  value: '{$AWS.SECRET.ACCESS.KEY}'
                - name: sts_region
                  value: '{$AWS.STS.REGION}'
                - name: target_arn
                  value: '{#AWS.ELB.TARGET.GROUP.ARN}'
              tags:
                - tag: component
                  value: raw
                - tag: component
                  value: target-groups
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
            - uuid: 8a42548bf31843acb0b021dfa0cf7f38
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: Healthy Host Count'
              type: DEPENDENT
              key: 'aws.elb.nlb.target_groups.healthy_host_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: 'The number of targets that are considered healthy.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "HealthyHostCount")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.nlb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: health
                - tag: component
                  value: target-groups
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
              trigger_prototypes:
                - uuid: dd527fbba0a84a1b8abe77dc34f7474c
                  expression: 'last(/AWS ELB Network Load Balancer by HTTP/aws.elb.nlb.target_groups.healthy_host_count["{#AWS.ELB.TARGET.GROUP.NAME}"]) = 0'
                  name: 'AWS ELB NLB: [{#AWS.ELB.TARGET.GROUP.NAME}]: Target have become unhealthy'
                  event_name: 'AWS ELB NLB: [{#AWS.ELB.TARGET.GROUP.NAME}]: Healthy Host Count = 0'
                  opdata: 'Current value: {ITEM.LASTVALUE1}'
                  priority: AVERAGE
                  description: 'This trigger helps in identifying when your targets have become unhealthy.'
                  tags:
                    - tag: scope
                      value: availability
            - uuid: b5e01700b1a14cd1bcfb676c69490f86
              name: '[{#AWS.ELB.TARGET.GROUP.NAME}]: Unhealthy Host Count'
              type: DEPENDENT
              key: 'aws.elb.nlb.target_groups.unhealthy_host_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              description: 'The number of targets that are considered unhealthy.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "UnHealthyHostCount")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.elb.nlb.target_groups.get_metrics["{#AWS.ELB.TARGET.GROUP.NAME}"]'
              tags:
                - tag: component
                  value: health
                - tag: component
                  value: target-groups
                - tag: protocol
                  value: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
                - tag: target-group
                  value: '{#AWS.ELB.TARGET.GROUP.NAME}'
                - tag: type
                  value: '{#AWS.ELB.TARGET.GROUP.TYPE}'
              trigger_prototypes:
                - uuid: 8de0720e39eb4759bec17431a596c3d4
                  expression: 'last(/AWS ELB Network Load Balancer by HTTP/aws.elb.nlb.target_groups.unhealthy_host_count["{#AWS.ELB.TARGET.GROUP.NAME}"]) > {$AWS.ELB.UNHEALTHY.HOST.MAX}'
                  name: 'AWS ELB NLB: [{#AWS.ELB.TARGET.GROUP.NAME}]: Target have unhealthy host'
                  event_name: 'AWS ELB NLB: [{#AWS.ELB.TARGET.GROUP.NAME}]: Unhealthy Host Count > {$AWS.ELB.UNHEALTHY.HOST.MAX}'
                  opdata: 'Current value: {ITEM.LASTVALUE1}'
                  priority: WARNING
                  description: 'This trigger allows you to become aware when there are no more registered targets.'
                  dependencies:
                    - name: 'AWS ELB NLB: [{#AWS.ELB.TARGET.GROUP.NAME}]: Target have become unhealthy'
                      expression: 'last(/AWS ELB Network Load Balancer by HTTP/aws.elb.nlb.target_groups.healthy_host_count["{#AWS.ELB.TARGET.GROUP.NAME}"]) = 0'
                  tags:
                    - tag: scope
                      value: availability
          graph_prototypes:
            - uuid: c83f16408b0e42b1b985fa02e00d49da
              name: 'AWS ELB NLB Target Groups: [{#AWS.ELB.TARGET.GROUP.NAME}]: Healthy Host'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 199C0D
                  item:
                    host: 'AWS ELB Network Load Balancer by HTTP'
                    key: 'aws.elb.nlb.target_groups.healthy_host_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
            - uuid: 2ddcf506cb344d58a8b2b555c0b90952
              name: 'AWS ELB NLB Target Groups: [{#AWS.ELB.TARGET.GROUP.NAME}]: Unhealthy Host'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: FF0000
                  item:
                    host: 'AWS ELB Network Load Balancer by HTTP'
                    key: 'aws.elb.nlb.target_groups.unhealthy_host_count["{#AWS.ELB.TARGET.GROUP.NAME}"]'
          master_item:
            key: aws.elb.nlb.get_target_groups
          lld_macro_paths:
            - lld_macro: '{#AWS.ELB.TARGET.GROUP.ARN}'
              path: $.target_arn
            - lld_macro: '{#AWS.ELB.TARGET.GROUP.NAME}'
              path: $.target_name
            - lld_macro: '{#AWS.ELB.TARGET.GROUP.PROTOCOL}'
              path: $.protocol
            - lld_macro: '{#AWS.ELB.TARGET.GROUP.TYPE}'
              path: $.type
          preprocessing:
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: automation
        - tag: target
          value: aws
        - tag: target
          value: elb
        - tag: target
          value: nlb
      macros:
        - macro: '{$AWS.ACCESS.KEY.ID}'
          description: 'Access key ID.'
          config:
            type: TEXT
            priority: '3'
            label: 'Access key ID'
            description: 'Access keys are long-term credentials for an IAM user.'
        - macro: '{$AWS.ASSUME.ROLE.ARN}'
          description: 'ARN assume role; add when using the `assume_role` authorization method.'
          config:
            type: TEXT
            priority: '5'
            label: 'ARN assume role'
            description: 'The ARN for the assume role when using the `assume_role` method.'
        - macro: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
          value: 'false'
          description: 'Add when using the `assume_role` through instance metadata or environment authorization method. Possible values: `false`, `true`.'
          config:
            type: LIST
            priority: '2'
            label: 'Assume Role Metadata Authorization'
            description: 'Chose `True` when use instance metadata service to retrieve role credentials.'
            options:
              - value: 'false'
                text: 'False'
              - value: 'true'
                text: 'True'
        - macro: '{$AWS.AUTH_TYPE}'
          value: access_key
          description: 'Authorization method. Possible values: `access_key`, `assume_role`, `role_base`.'
          config:
            type: LIST
            priority: '1'
            label: 'Authorization method'
            description: 'Authorization method used to access AWS.'
            required: 'YES'
            options:
              - value: access_key
                text: 'Access key'
              - value: assume_role
                text: AssumeRole
              - value: role_base
                text: 'Role-based access'
        - macro: '{$AWS.DATA.TIMEOUT}'
          value: 60s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '9'
            section_name: Other
            label: 'API response timeout'
            description: 'Timeout for API responses in seconds.'
        - macro: '{$AWS.ELB.ARN}'
          description: 'Amazon Resource Names (ARN) of the load balancer.'
          config:
            type: TEXT
            priority: '10'
            label: 'Load Balancer ARN'
            description: 'The ARN of the load balancer.'
        - macro: '{$AWS.ELB.LLD.FILTER.ALARM_NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable alarms by name.'
          config:
            type: TEXT
            priority: '15'
            section_name: Filters
            label: 'Alarm Name Filter (Matches)'
            description: 'Regex filter for discoverable alarms by name.'
        - macro: '{$AWS.ELB.LLD.FILTER.ALARM_NAME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered alarms by name.'
          config:
            type: TEXT
            priority: '16'
            section_name: Filters
            label: 'Alarm Name Filter (Not Matches)'
            description: 'Regex filter to exclude discovered alarms by name.'
        - macro: '{$AWS.ELB.LLD.FILTER.ALARM_SERVICE_NAMESPACE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable alarms by namespace.'
          config:
            type: TEXT
            priority: '13'
            section_name: Filters
            label: 'Alarm Namespace Filter (Matches)'
            description: 'Regex filter for discoverable alarms by namespace.'
        - macro: '{$AWS.ELB.LLD.FILTER.ALARM_SERVICE_NAMESPACE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered alarms by namespace.'
          config:
            type: TEXT
            priority: '14'
            section_name: Filters
            label: 'Alarm Namespace Filter (Not Matches)'
            description: 'Regex filter to exclude discovered alarms by namespace.'
        - macro: '{$AWS.ELB.LLD.FILTER.TARGET.GROUP.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable target groups by name.'
          config:
            type: TEXT
            priority: '11'
            section_name: Filters
            label: 'Target Group Filter (Matches)'
            description: 'Regex filter for discoverable target groups by name.'
        - macro: '{$AWS.ELB.LLD.FILTER.TARGET.GROUP.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered target groups by name.'
          config:
            type: TEXT
            priority: '12'
            section_name: Filters
            label: 'Target Group Filter (Not Matches)'
            description: 'Regex filter to exclude discovered target groups by name.'
        - macro: '{$AWS.ELB.UNHEALTHY.HOST.MAX}'
          value: '0'
          description: 'Maximum number of unhealthy hosts for a trigger expression.'
          config:
            type: TEXT
            priority: '17'
            section_name: Thresholds
            label: 'Unhealthy Host Count'
            description: 'Maximum number of unhealthy hosts allowed before triggering a warning.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.PROXY}'
          description: 'Sets the HTTP proxy value. If this macro is empty, no proxy is used.'
          config:
            type: TEXT
            priority: '7'
            section_name: Other
            label: 'HTTP Proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AWS.REGION}'
          value: us-west-1
          description: 'AWS Network Load Balancer region code.'
          config:
            type: TEXT
            priority: '6'
            label: 'AWS Region'
            description: 'The AWS region for the Network Load Balancer.'
        - macro: '{$AWS.SECRET.ACCESS.KEY}'
          type: SECRET_TEXT
          description: 'Secret access key.'
          config:
            type: TEXT
            priority: '4'
            label: 'Secret access key'
            description: 'Secret access key can be retrieved only at the time you create it.'
        - macro: '{$AWS.STS.REGION}'
          value: us-east-1
          description: 'Region used in assume role request.'
          config:
            type: TEXT
            priority: '8'
            label: 'STS Region'
            description: 'The AWS region for the assume role request.'
      dashboards:
        - uuid: 3b69323b2b8940b0a1fd0ae2ae2dc156
          name: 'Overview AWS ELB Network Load Balancer'
          pages:
            - name: 'AWS ELB NLB: Main'
              widgets:
                - type: item
                  name: 'Port Allocation Error Count'
                  width: '18'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        key: aws.elb.nlb.port_allocation_error_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 ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB: Peak Packets per second'
                    - type: STRING
                      name: reference
                      value: BDBEE
                - type: graph
                  'y': '10'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB: Concurrent Flows Count'
                    - type: STRING
                      name: reference
                      value: CFDBA
                - type: graph
                  'y': '15'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB: Consumed LCUs and Processed Bytes'
                    - type: STRING
                      name: reference
                      value: DECEC
                - type: graph
                  'y': '20'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB: Security Group Blocked Flow Count ICMP'
                    - type: STRING
                      name: reference
                      value: ADEED
                - type: graphprototype
                  x: '18'
                  width: '18'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: columns
                      value: '1'
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB Target Groups: [{#AWS.ELB.TARGET.GROUP.NAME}]: Healthy Host'
                    - type: STRING
                      name: reference
                      value: FDEFC
                - type: graphprototype
                  x: '36'
                  width: '18'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: columns
                      value: '1'
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB Target Groups: [{#AWS.ELB.TARGET.GROUP.NAME}]: Unhealthy Host'
                    - type: STRING
                      name: reference
                      value: EAAFA
                - type: item
                  name: 'Unhealthy Routing Flow Count'
                  x: '54'
                  width: '18'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        key: aws.elb.nlb.unhealthy_routing_flow_count
                    - type: INTEGER
                      name: show.0
                      value: '2'
            - name: 'AWS ELB NLB: TCP'
              widgets:
                - type: graph
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB: TCP Reset Count'
                    - type: STRING
                      name: reference
                      value: CCAAA
                - type: graph
                  'y': '5'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB: Consumed LCUs TCP and Processed Bytes TCP'
                    - type: STRING
                      name: reference
                      value: BEEDA
                - type: graph
                  'y': '10'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB: Concurrent Flows Count TCP'
                    - type: STRING
                      name: reference
                      value: FEBCF
                - type: graph
                  'y': '15'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB: Security Group Blocked Flow Count TCP'
                    - type: STRING
                      name: reference
                      value: ECBEF
            - name: 'AWS ELB NLB: TLS'
              widgets:
                - type: graph
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB: TLS Negotiation Error Count'
                    - type: STRING
                      name: reference
                      value: CEAFF
                - type: graph
                  'y': '5'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB: Consumed LCUs TLS and Processed Bytes TLS'
                    - type: STRING
                      name: reference
                      value: DDCEF
                - type: graph
                  'y': '10'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB: Concurrent Flows Count TLS'
                    - type: STRING
                      name: reference
                      value: FABDD
            - name: 'AWS ELB NLB: UDP'
              widgets:
                - type: graph
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB: Consumed LCUs UDP and Processed Bytes UDP'
                    - type: STRING
                      name: reference
                      value: AEAEF
                - type: graph
                  'y': '5'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB: Concurrent Flows Count UDP'
                    - type: STRING
                      name: reference
                      value: EBDBF
                - type: graph
                  'y': '10'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ELB Network Load Balancer by HTTP'
                        name: 'AWS ELB NLB: Security Group Blocked Flow Count UDP'
                    - type: STRING
                      name: reference
                      value: CFFDB
      valuemaps:
        - uuid: e0e5308401bd4abfa79ba604c0481d2a
          name: 'Alarm state'
          mappings:
            - value: '0'
              newvalue: OK
            - value: '1'
              newvalue: 'Insufficient data'
            - value: '2'
              newvalue: Alarm
            - value: '255'
              newvalue: Unknown
    - uuid: fd36e0a231d343d38a95d1ed789584ca
      template: 'AWS Lambda by HTTP'
      name: 'AWS Lambda by HTTP'
      description: |
        The template is designed to monitor AWS Lambda by HTTP via Zabbix, and it works without any external scripts.
        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"
      wizard_ready: 'YES'
      readme: |
        ## Overview
        
        This template uses the GetMetricData CloudWatch API calls to list and retrieve metrics.
        For more information, please refer to the [CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) page.
        
        Additional information about metrics and API methods used in the template:
        * [Full metrics list related to AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-metrics.html)
        * [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
        
        
        ## Setup
        
        The template gets AWS Lambda metrics and uses the script item to make HTTP requests to the CloudWatch API.
        
        Before using the template, you need to create an IAM policy with the necessary permissions for the Zabbix role in your AWS account. For more information, visit the [Lambda permissions page](https://docs.aws.amazon.com/lambda/latest/dg/lambda-permissions.html) on the AWS website.
        
        ### Required Permissions
        Add the following required permissions to your Zabbix IAM policy in order to collect AWS Lambda metrics.
        
        ```json
        {
            "Version":"2012-10-17",
            "Statement":[
                {
                  "Action":[
                      "cloudwatch:DescribeAlarms",
                      "cloudwatch:GetMetricData"
                  ],
                  "Effect":"Allow",
                  "Resource":"*"
                }
            ]
          }
        ```
        
        ### Access Key Authorization
        
        If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
        
        1. Create an IAM user with programmatic access.
        2. Attach the required policy to the IAM user.
        3. Generate an access key and secret key.
        4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
        
        ### Assume role authorization
        For using assume role authorization, add the appropriate permissions to the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "sts:AssumeRole",
                    "Resource": "arn:aws:iam::{Account}:user/{UserName}"
                },
                {
                    "Effect": "Allow",
                    "Action": [
                        "cloudwatch:DescribeAlarms",
                        "cloudwatch:GetMetricData"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        
        #### Trust Relationships for Assume Role Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "AWS": "arn:aws:iam::{Account}:user/{UserName}"
              },
              "Action": "sts:AssumeRole"
            }
          ]
        }
        ```
        Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
        
        ### Role-Based Authorization
        If you are using role-based authorization, set the appropriate permissions:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "iam:PassRole",
                    "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
                },
                {
                    "Sid": "VisualEditor1",
                    "Effect": "Allow",
                    "Action": [
                        "cloudwatch:DescribeAlarms",
                        "cloudwatch:GetMetricData",
                        "ec2:AssociateIamInstanceProfile",
                        "ec2:ReplaceIamInstanceProfileAssociation"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        #### Trust Relationships for Role-Based Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": [
                            "ec2.amazonaws.com"
                        ]
                    },
                    "Action": [
                        "sts:AssumeRole"
                    ]
                }
            ]
        }
        ```
        
        **Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
        
        Set the following fields: `Authorization method`, `AWS Region`, and `Lambda function ARN`.
        
        For more information about managing access keys, see the [official AWS documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).
      vendor:
        name: Zabbix
        version: 8.0-3
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 397bcf955a7449b79dab4770fe17922f
          name: 'Get alarms check'
          type: DEPENDENT
          key: aws.lambda.alarms.check
          value_type: CHAR
          description: 'Check that the alarm data has been received correctly.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.lambda.get_alarms
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: 77f2bf7f1086488289b1cf1931e8fd90
              expression: 'length(last(/AWS Lambda by HTTP/aws.lambda.alarms.check))>0'
              name: 'AWS Lambda: Failed to get alarms data'
              event_name: 'AWS Lambda: Failed to get CloudWatch alarms for the Lambda function'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Failed to get CloudWatch alarms for the Lambda function.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 57c7e41184d74cc98c2eea33bfe28028
          name: 'Async events dropped sum'
          type: DEPENDENT
          key: aws.lambda.async_events_dropped.sum
          description: 'The number of events that are dropped without successfully executing the function. If you configure a dead-letter queue (DLQ) or an `OnFailure` destination, events are sent there before they''re dropped.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "AsyncEventsDropped")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.lambda.get_metrics
          tags:
            - tag: component
              value: asynchronous
        - uuid: d8000a6335b14e0dae702787e4bf9db2
          name: 'Async events received sum'
          type: DEPENDENT
          key: aws.lambda.async_events_received.sum
          description: 'The number of events that Lambda successfully queues for processing. This metric provides insight into the number of events that a Lambda function receives.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "AsyncEventsReceived")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.lambda.get_metrics
          tags:
            - tag: component
              value: asynchronous
        - uuid: 48b180f52bbf4c93b64433a97e00a029
          name: 'Async event age average'
          type: DEPENDENT
          key: aws.lambda.async_event_age.avg
          value_type: FLOAT
          units: s
          description: 'The time between when Lambda successfully queues the event and when the function is invoked. The value of this metric increases when events are being retried due to invocation failures or throttling.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "AsyncEventAge")].Values.first().first()'
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '0.001'
          master_item:
            key: aws.lambda.get_metrics
          tags:
            - tag: component
              value: asynchronous
        - uuid: 7eaf67dc1859405aa55f22ea8d85e7c5
          name: 'Total concurrent executions'
          type: DEPENDENT
          key: aws.lambda.concurrent_executions.max
          description: 'The number of function instances that are processing events. If this number reaches your concurrent executions quota for the Region or the reserved concurrency limit on the function, then Lambda will throttle additional invocation requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ConcurrentExecutions")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.lambda.get_metrics
          tags:
            - tag: component
              value: concurrency
        - uuid: 82536a92c0f84d67aabbe69e38e7f3a2
          name: 'Dead letter errors sum'
          type: DEPENDENT
          key: aws.lambda.dead_letter_errors.sum
          description: 'For asynchronous invocation, the number of times that Lambda attempts to send an event to a dead-letter queue (DLQ) but fails. Dead-letter errors can occur due to misconfigured resources or size limits.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "DeadLetterErrors")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.lambda.get_metrics
          tags:
            - tag: component
              value: invocation
        - uuid: 370d8ac63e024a94a493c95e528f4604
          name: 'Duration average'
          type: DEPENDENT
          key: aws.lambda.duration.avg
          value_type: FLOAT
          units: s
          description: 'The amount of time that your function code spends processing an event. The billed duration for an invocation is the value of `Duration` rounded up to the nearest millisecond. Duration does not include cold start time.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "Duration")].Values.first().first()'
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '0.001'
          master_item:
            key: aws.lambda.get_metrics
          tags:
            - tag: component
              value: performance
        - uuid: 1b16f879dc5648d0b50e060d1f056fab
          name: 'Errors sum'
          type: DEPENDENT
          key: aws.lambda.errors.sum
          description: 'The number of invocations that result in a function error. Function errors include exceptions that your code throws and exceptions that the Lambda runtime throws. The runtime returns errors for issues such as timeouts and configuration errors.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "Errors")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.lambda.get_metrics
          tags:
            - tag: component
              value: invocation
        - uuid: c80b25e889004287b6131c00000a3ad7
          name: 'Get Lambda alarms data'
          type: SCRIPT
          key: aws.lambda.get_alarms
          delay: 0s;m/1
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', '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'),
            			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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS Lambda Alarms ] Sending request: ' + url);
            		response = request.get(url);
            		Zabbix.log(4, '[ AWS Lambda Alarms ] 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) {
            			try {
            				response = JSON.parse(XML.toJson(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;
            
            				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 === 'FunctionName' && dimensions[i].Value === AWS.params.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 Lambda Alarms ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: '`DescribeAlarms` API method: https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html'
          preprocessing:
            - type: CHECK_NOT_SUPPORTED
              parameters:
                - '-1'
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: name
              value: '{$AWS.LAMBDA.NAME}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: 24c4972d090f4e72abc473752aac27d8
          name: 'Get metrics data'
          type: SCRIPT
          key: aws.lambda.get_metrics
          delay: 0s;m/1
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            	request_period: 60,
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('POST', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', '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('&');
            	},
            
            	renderMetricQuery: function (period, name) {
            		var metrics_list = [
            			'AsyncEventsReceived:Average',
            			'AsyncEventAge:Average',
            			'AsyncEventsDropped:Average',
            			'ConcurrentExecutions:Average',
            			'UnreservedConcurrentExecutions:Sum',
            			'Invocations:Sum',
            			'Errors:Sum',
            			'Throttles:Sum',
            			'Duration:Average'
            		];
            
            		var metric_payload = [];
            		metrics_list.forEach(function (metric, index) {
            			var parts = metric.split(':', 2);
            			metric_payload.push({
            				'Id': 'm' + index,
            				'MetricStat': {
            					'Metric': {
            						'MetricName': parts[0],
            						'Namespace': 'AWS/Lambda',
            						'Dimensions': [
            							{
            								'Name': 'FunctionName',
            								'Value': name,
            							}
            						]
            					},
            					'Period': period,
            					'Stat': parts[1],
            				}
            			});
            		});
            
            		return metric_payload;
            	},
            
            	request: function (method, region, service, params, data) {
            		if (typeof data === 'undefined' || data === null) {
            			data = JSON.stringify([]);
            		}
            		else {
            			data = JSON.stringify(data)
            		}
            		var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''),
            			date = amzdate.replace(/T\d+Z/, ''),
            			canonical_uri = '/',
            			host = service + '.' + region + '.amazonaws.com',
            			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'),
            			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('X-Amz-Target: GraniteServiceVersion20100801.GetMetricData')
            		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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS Lambda Get metrics ] Sending request: ' + url);
            		response = request.post(url, data);
            		Zabbix.log(4, '[ AWS Lambda Get metrics ] Received response with status code ' + request.getStatus() + ': ' + response);
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		return JSON.parse(response);
            	},
            
            	getMetricsData: function () {
            		var end_time = Math.floor((new Date().getTime()) / 1000),
            			start_time = end_time - AWS.request_period * 60;
            		payload = {
            			'StartTime': start_time,
            			'EndTime': end_time,
            			'ScanBy': 'TimestampDescending',
            			'MetricDataQueries': AWS.renderMetricQuery(AWS.request_period, AWS.params.name)
            		};
            
            		return AWS.getField(AWS.request('POST', AWS.params.region, 'monitoring', '', payload), 'MetricDataResults');
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            	return JSON.stringify(AWS.getMetricsData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS Lambda Get metrics ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: |
            Get Lambda function metrics.
            Full metrics list related to the Lambda function: https://docs.aws.amazon.com/lambda/latest/dg/monitoring-metrics.html
          preprocessing:
            - type: CHECK_NOT_SUPPORTED
              parameters:
                - '-1'
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: name
              value: '{$AWS.LAMBDA.NAME}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: 1bab5865e01b4233bc2bb5cb17516360
          name: 'Invocations sum'
          type: DEPENDENT
          key: aws.lambda.invocations.sum
          description: 'The number of times that your function code is invoked, including successful invocations and invocations that result in a function error. Invocations aren''t recorded if the invocation request is throttled or otherwise results in an invocation error. The value of `Invocations` equals the number of requests billed.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "Invocations")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.lambda.get_metrics
          tags:
            - tag: component
              value: invocation
        - uuid: 2bfa15a2c1ef4f66a8b2065e34a1a690
          name: 'Get metrics check'
          type: DEPENDENT
          key: aws.lambda.metrics.check
          value_type: CHAR
          description: 'Check that the Lambda function metrics data has been received correctly.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.lambda.get_metrics
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: 95ed5e8c560f4c6e89ed9d1a754ed032
              expression: 'length(last(/AWS Lambda by HTTP/aws.lambda.metrics.check))>0'
              name: 'AWS Lambda: Failed to get metrics data'
              event_name: 'AWS Lambda: Failed to get CloudWatch metrics for the Lambda function'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Failed to get CloudWatch metrics for the Lambda function.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 9f141ce56187497794d109c030c43a06
          name: 'Throttles sum'
          type: DEPENDENT
          key: aws.lambda.throttles.sum
          description: 'The number of invocation requests that are throttled. When all function instances are processing requests and no concurrency is available to scale up, Lambda rejects additional requests with a `TooManyRequestsException` error.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "Throttles")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.lambda.get_metrics
          tags:
            - tag: component
              value: invocation
        - uuid: b0ecd33e96734ac69447c095032dea55
          name: 'Unreserved concurrent executions maximum'
          type: DEPENDENT
          key: aws.lambda.unreserved_concurrent_executions.max
          description: 'For a Region, the number of events that function without reserved concurrency are processing.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "UnreservedConcurrentExecutions")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.lambda.get_metrics
          tags:
            - tag: component
              value: concurrency
      discovery_rules:
        - uuid: 7b00199cc6c041f5998c798884305f9e
          name: 'Lambda alarm discovery'
          type: DEPENDENT
          key: aws.lambda.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.LAMBDA.LLD.FILTER.ALARM_NAME.MATCHES}'
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.LAMBDA.LLD.FILTER.ALARM_NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#ALARM_SERVICE_NAMESPACE}'
                value: '{$AWS.LAMBDA.LLD.FILTER.ALARM_SERVICE_NAMESPACE.MATCHES}'
              - macro: '{#ALARM_SERVICE_NAMESPACE}'
                value: '{$AWS.LAMBDA.LLD.FILTER.ALARM_SERVICE_NAMESPACE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Used for the discovery of alarm Lambda functions.'
          item_prototypes:
            - uuid: 893819314ae34f31bde78612679da46b
              name: '[{#ALARM_NAME}]: Get metrics'
              type: DEPENDENT
              key: 'aws.lambda.alarm.get_metrics["{#ALARM_NAME}"]'
              history: '0'
              value_type: TEXT
              description: 'Get metrics about the alarm state and its reason.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.AlarmName == "{#ALARM_NAME}")].first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.lambda.get_alarms
              tags:
                - tag: component
                  value: raw
            - uuid: 2e34c9ed36c64a6aade389e739340529
              name: '[{#ALARM_NAME}]: State'
              type: DEPENDENT
              key: 'aws.lambda.alarm.state["{#ALARM_NAME}"]'
              description: |
                The value of the alarm state. 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.lambda.alarm.get_metrics["{#ALARM_NAME}"]'
              tags:
                - tag: component
                  value: alarms
              trigger_prototypes:
                - uuid: fc0d5744b0284362897a2d3191727d66
                  expression: 'last(/AWS Lambda by HTTP/aws.lambda.alarm.state["{#ALARM_NAME}"])=1'
                  name: 'AWS Lambda: [{#ALARM_NAME}] has ''Insufficient data'' state'
                  event_name: 'AWS Lambda: [{#ALARM_NAME}] has ''Insufficient data'' state'
                  opdata: 'Current value: {ITEM.LASTVALUE1}'
                  priority: INFO
                  description: 'Either the alarm has just started, the metric is not available, or not enough data is available for the metric to determine the alarm state.'
                  tags:
                    - tag: scope
                      value: notice
            - uuid: 7a314dfe3f4e4142bf4827f6cb6285bd
              name: '[{#ALARM_NAME}]: State reason'
              type: DEPENDENT
              key: 'aws.lambda.alarm.state_reason["{#ALARM_NAME}"]'
              value_type: TEXT
              description: |
                An explanation for the alarm state reason 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.lambda.alarm.get_metrics["{#ALARM_NAME}"]'
              tags:
                - tag: component
                  value: alarms
          trigger_prototypes:
            - uuid: c3ce7372e8cf4ff48eee7f91870dc58d
              expression: 'last(/AWS Lambda by HTTP/aws.lambda.alarm.state["{#ALARM_NAME}"])=2 and length(last(/AWS Lambda by HTTP/aws.lambda.alarm.state_reason["{#ALARM_NAME}"]))>0'
              name: 'AWS Lambda: [{#ALARM_NAME}] has ''Alarm'' state'
              event_name: 'AWS Lambda: [{#ALARM_NAME}] has ''Alarm'' state (reason: {ITEM.LASTVALUE2})'
              opdata: 'Reason: {ITEM.LASTVALUE2}'
              priority: AVERAGE
              description: |
                The alarm `{#ALARM_NAME}` is in the ALARM state.
                Reason: `{ITEM.LASTVALUE2}`
              tags:
                - tag: scope
                  value: availability
          master_item:
            key: aws.lambda.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
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: automation
        - tag: subclass
          value: computing
        - tag: target
          value: aws
        - tag: target
          value: lambda
      macros:
        - macro: '{$AWS.ACCESS.KEY.ID}'
          description: 'Access key ID.'
          config:
            type: TEXT
            priority: '3'
            label: 'Access key ID'
            description: 'Access keys are long-term credentials for an IAM user.'
        - macro: '{$AWS.ASSUME.ROLE.ARN}'
          description: 'ARN assume role; add when using the `assume_role` authorization method.'
          config:
            type: TEXT
            priority: '5'
            label: 'ARN assume role'
            description: 'ARN for the assume role when using the assume_role authorization method.'
        - macro: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
          value: 'false'
          description: 'Add when using the `assume_role` through instance metadata or environment authorization method. Possible values: `false`, `true`.'
          config:
            type: LIST
            priority: '2'
            label: 'Assume Role Metadata Authorization'
            description: 'Chose `True` when use instance metadata service to retrieve role credentials.'
            options:
              - value: 'false'
                text: 'False'
              - value: 'true'
                text: 'True'
        - macro: '{$AWS.AUTH_TYPE}'
          value: access_key
          description: 'Authorization method. Possible values: `access_key`, `assume_role`, `role_base`.'
          config:
            type: LIST
            priority: '1'
            label: 'Authorization method'
            description: 'Authorization method used to access AWS.'
            required: 'YES'
            options:
              - value: access_key
                text: 'Access key'
              - value: assume_role
                text: AssumeRole
              - value: role_base
                text: 'Role-based access'
        - macro: '{$AWS.DATA.TIMEOUT}'
          value: 60s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '9'
            section_name: Other
            label: 'API response timeout'
            description: 'Timeout for API responses in seconds.'
        - macro: '{$AWS.LAMBDA.ARN}'
          description: 'The Amazon Resource Names (ARN) of the Lambda function.'
          config:
            type: TEXT
            priority: '10'
            label: 'Lambda function ARN'
            description: 'The ARN of the Lambda function.'
        - macro: '{$AWS.LAMBDA.LLD.FILTER.ALARM_NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable alarms by name.'
          config:
            type: TEXT
            priority: '13'
            section_name: Filters
            label: 'Alarm name filter (matches)'
            description: 'A regex to filter discoverable alarms by name.'
        - macro: '{$AWS.LAMBDA.LLD.FILTER.ALARM_NAME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered alarms by name.'
          config:
            type: TEXT
            priority: '14'
            section_name: Filters
            label: 'Alarm name filter (not matches)'
            description: 'A regex to exclude discovered alarms by name.'
        - macro: '{$AWS.LAMBDA.LLD.FILTER.ALARM_SERVICE_NAMESPACE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable alarms by namespace.'
          config:
            type: TEXT
            priority: '11'
            section_name: Filters
            label: 'Alarm namespace filter (matches)'
            description: 'A regex to filter discoverable alarms by namespace.'
        - macro: '{$AWS.LAMBDA.LLD.FILTER.ALARM_SERVICE_NAMESPACE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered alarms by namespace.'
          config:
            type: TEXT
            priority: '12'
            section_name: Filters
            label: 'Alarm namespace filter (not matches)'
            description: 'A regex to exclude discovered alarms by namespace.'
        - macro: '{$AWS.PROXY}'
          description: 'Sets the HTTP proxy value. If this macro is empty, no proxy is used.'
          config:
            type: TEXT
            priority: '7'
            section_name: Other
            label: 'HTTP proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AWS.REGION}'
          value: us-west-1
          description: 'AWS Lambda function region code.'
          config:
            type: TEXT
            priority: '6'
            label: 'AWS region'
            description: 'The AWS region where the Lambda function is located.'
        - macro: '{$AWS.SECRET.ACCESS.KEY}'
          type: SECRET_TEXT
          description: 'Secret access key.'
          config:
            type: TEXT
            priority: '4'
            label: 'Secret access key'
            description: 'Secret access key can be retrieved only at the time you create it.'
        - macro: '{$AWS.STS.REGION}'
          value: us-east-1
          description: 'Region used in assume role request.'
          config:
            type: TEXT
            priority: '8'
            label: 'STS region'
            description: 'The AWS region for the assume role request.'
      dashboards:
        - uuid: aab5dac54efa4d0cbc0f7980220e172e
          name: 'Overview AWS Lambda function'
          pages:
            - name: 'Invocation metrics'
              widgets:
                - type: graph
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS Lambda by HTTP'
                        name: 'AWS Lambda: Invocations'
                    - type: STRING
                      name: reference
                      value: ECCBA
                - type: graph
                  'y': '5'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS Lambda by HTTP'
                        name: 'AWS Lambda: Errors'
                    - type: STRING
                      name: reference
                      value: DBBFF
                - type: graph
                  'y': '10'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS Lambda by HTTP'
                        name: 'AWS Lambda: Duration'
                    - type: STRING
                      name: reference
                      value: FBDDF
                - type: graph
                  'y': '15'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS Lambda by HTTP'
                        name: 'AWS Lambda: Throttles'
                    - type: STRING
                      name: reference
                      value: BDAAA
            - name: 'Asynchronous invocation metrics'
              widgets:
                - type: graph
                  width: '24'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS Lambda by HTTP'
                        name: 'AWS Lambda: Asynchronous events'
                    - type: STRING
                      name: reference
                      value: CAADA
                - type: graph
                  x: '24'
                  width: '24'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS Lambda by HTTP'
                        name: 'AWS Lambda: Async event age'
                    - type: STRING
                      name: reference
                      value: EAFEB
                - type: graph
                  x: '48'
                  width: '24'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS Lambda by HTTP'
                        name: 'AWS Lambda: Async dropped events'
                    - type: STRING
                      name: reference
                      value: ECADD
            - name: 'Concurrency metrics'
              widgets:
                - type: graph
                  width: '36'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS Lambda by HTTP'
                        name: 'AWS Lambda: Concurrent executions'
                    - type: STRING
                      name: reference
                      value: CAECA
                - type: graph
                  x: '36'
                  width: '36'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS Lambda by HTTP'
                        name: 'AWS Lambda: Unreserved concurrent executions'
                    - type: STRING
                      name: reference
                      value: CFEBE
      valuemaps:
        - uuid: a61fdde5c78748339a903f1224524deb
          name: 'Alarm state'
          mappings:
            - value: '0'
              newvalue: OK
            - value: '1'
              newvalue: 'Insufficient data'
            - value: '2'
              newvalue: Alarm
            - value: '255'
              newvalue: Unknown
    - uuid: c6d9475847f44d9193f8253e5995b8f8
      template: 'AWS RDS instance by HTTP'
      name: 'AWS RDS instance by HTTP'
      description: |
        The template gets AWS RDS instance 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"
      wizard_ready: 'YES'
      readme: |
        ## Overview
        
        The template to monitor AWS RDS instance by HTTP via Zabbix that works without any external scripts.
        Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
        
        **Note:** This template uses the GetMetricData CloudWatch API calls to list and retrieve metrics.
        For more information, please refer to the [CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) page.
        
        Additional information about metrics and used API methods:
        
        * [Full metrics list related to RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-metrics.html)
        * [Full metrics list related to Amazon Aurora](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.AuroraMySQL.Monitoring.Metrics.html#Aurora.AuroraMySQL.Monitoring.Metrics.instances)
        * [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
        
        
        ## Setup
        
        The template get AWS RDS instance metrics and uses the script item to make HTTP requests to the CloudWatch API.
        Before using the template, you need to create an IAM policy with the necessary permissions for the Zabbix role in your AWS account.
        
        ### Required Permissions
        Add the following required permissions to your Zabbix IAM policy in order to collect Amazon RDS metrics.
        
        ```json
        {
            "Version":"2012-10-17",
            "Statement":[
                {
                  "Action":[
                        "cloudwatch:DescribeAlarms",
                        "cloudwatch:GetMetricData",
                        "rds:DescribeEvents",
                        "rds:DescribeDBInstances"
                  ],
                  "Effect":"Allow",
                  "Resource":"*"
                }
            ]
          }
        ```
        
        ### Access Key Authorization
        
        If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
        
        1. Create an IAM user with programmatic access.
        2. Attach the required policy to the IAM user.
        3. Generate an access key and secret key.
        4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
        
        ### Assume Role Authorization
        For using assume role authorization, add the appropriate permissions to the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "sts:AssumeRole",
                    "Resource": "arn:aws:iam::{Account}:user/{UserName}"
                },
                {
                    "Effect": "Allow",
                    "Action": [
                        "cloudwatch:DescribeAlarms",
                        "cloudwatch:GetMetricData",
                        "rds:DescribeEvents",
                        "rds:DescribeDBInstances"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        
        #### Trust Relationships for Assume Role Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "AWS": "arn:aws:iam::{Account}:user/{UserName}"
              },
              "Action": "sts:AssumeRole"
            }
          ]
        }
        ```
        Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
        
        ### Role-Based Authorization
        If you are using role-based authorization, set the appropriate permissions:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "iam:PassRole",
                    "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
                },
                {
                    "Sid": "VisualEditor1",
                    "Effect": "Allow",
                    "Action": [
                        "cloudwatch:DescribeAlarms",
                        "cloudwatch:GetMetricData",
                        "rds:DescribeEvents",
                        "rds:DescribeDBInstances",
                        "ec2:AssociateIamInstanceProfile",
                        "ec2:ReplaceIamInstanceProfileAssociation"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        
        #### Trust Relationships for Role-Based Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": [
                            "ec2.amazonaws.com"
                        ]
                    },
                    "Action": [
                        "sts:AssumeRole"
                    ]
                }
            ]
        }
        ```
        
        **Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
        
        Set the following fields: `Authorization method`, `AWS Region`, `RDS DB Instance identifier`.
        
        For more information about managing access keys, see [official documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).
      vendor:
        name: Zabbix
        version: 8.0-3
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 94471806c4cf482fb66cbe305a0e87a5
          name: 'Get alarms check'
          type: DEPENDENT
          key: aws.rds.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.rds.get_alarms
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: 112da2ba956740fda7edcd9bd3a8651c
              expression: 'length(last(/AWS RDS instance by HTTP/aws.rds.alarms.check))>0'
              name: 'AWS RDS: Failed to get alarms data'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Failed to get CloudWatch alarms for RDS.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 9e40764a74e54c3b8bf0e7f75fe5f115
          name: 'Disk: Binlog Usage'
          type: DEPENDENT
          key: aws.rds.bin_log_disk_usage
          value_type: FLOAT
          units: B
          description: 'The amount of disk space occupied by binary logs on the master. Applies to MySQL read replicas.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "BinLogDiskUsage")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
            - tag: engine
              value: mariadb
            - tag: engine
              value: mysql
        - uuid: 7b7273f5d9144dd1b82c8c3fb649f593
          name: 'Burst balance'
          type: DEPENDENT
          key: aws.rds.burst_balance
          value_type: FLOAT
          units: '%'
          description: 'The percent of General Purpose SSD (gp2) burst-bucket I/O credits available.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "BurstBalance")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
          triggers:
            - uuid: 730337e340cf4b129d4b38f1c7c82cf6
              expression: 'max(/AWS RDS instance by HTTP/aws.rds.burst_balance,5m)<{$AWS.RDS.BURST.CREDIT.BALANCE.MIN.WARN}'
              name: 'AWS RDS: Burst balance is too low'
              event_name: 'AWS RDS: Burst balance is too low (less {$AWS.RDS.BURST.CREDIT.BALANCE.MIN.WARN}% for 5m)'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              tags:
                - tag: scope
                  value: capacity
        - uuid: 975ee74af92c4b589f2488d403fdb18d
          name: Class
          type: DEPENDENT
          key: aws.rds.class
          value_type: CHAR
          description: 'Contains the name of the compute and memory capacity class of the DB instance.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$[*].DBInstanceClass.first()'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.rds.get_instance_info
          tags:
            - tag: component
              value: instance
        - uuid: 83d19e8a062b4890a4897e97bb1d5a24
          name: 'Credit CPU: Balance'
          type: DEPENDENT
          key: aws.rds.cpu.credit_balance
          value_type: FLOAT
          description: |
            The number of CPU credits that an instance has accumulated, reported at 5-minute intervals.
            You can use this metric to determine how long a DB instance can burst beyond its baseline performance level at a given rate.
            When an instance is running, credits in the CPUCreditBalance don't expire. When the instance stops, the CPUCreditBalance does not persist, and all accrued credits are lost.
            
            This metric applies only to db.t2.small and db.t2.medium instances for Aurora MySQL, and to db.t3 instances for Aurora PostgreSQL.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "CPUCreditBalance")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: cpu
            - tag: component
              value: credit
          triggers:
            - uuid: 32994f2b06b8491b9b13d0b280e09001
              expression: 'max(/AWS RDS instance by HTTP/aws.rds.cpu.credit_balance,5m)<{$AWS.RDS.CPU.CREDIT.BALANCE.MIN.WARN}'
              name: 'AWS RDS: Instance CPU Credit balance is too low'
              event_name: 'AWS RDS: Instance CPU Credit balance is too low (less {$AWS.RDS.CPU.CREDIT.BALANCE.MIN.WARN} for 5m)'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The number of earned CPU credits has been less than {$AWS.RDS.CPU.CREDIT.BALANCE.MIN.WARN} in the last 5 minutes.'
              tags:
                - tag: scope
                  value: capacity
        - uuid: 14c1c44a312b4343b0ded785a7ae910c
          name: 'Credit CPU: Usage'
          type: DEPENDENT
          key: aws.rds.cpu.credit_usage
          value_type: FLOAT
          description: |
            The number of CPU credits consumed during the specified period, reported at 5-minute intervals.
            This metric measures the amount of time during which physical CPUs have been used for processing instructions by virtual CPUs allocated to the DB instance.
            
            This metric applies only to db.t2.small and db.t2.medium instances for Aurora MySQL, and to db.t3 instances for Aurora PostgreSQL
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "CPUCreditUsage")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: cpu
            - tag: component
              value: credit
        - uuid: b69d180c94a34882bd3faa58f8847f65
          name: 'CPU: Utilization'
          type: DEPENDENT
          key: aws.rds.cpu.utilization
          value_type: FLOAT
          units: '%'
          description: 'The percentage of CPU utilization.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "CPUUtilization")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: cpu
          triggers:
            - uuid: 0272980a53e14f22b06db30af49a1233
              expression: 'min(/AWS RDS instance by HTTP/aws.rds.cpu.utilization,15m)>{$AWS.RDS.CPU.UTIL.WARN.MAX}'
              name: 'AWS RDS: High CPU utilization'
              event_name: 'AWS RDS: High CPU utilization (over {$AWS.RDS.CPU.UTIL.WARN.MAX}% 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: 8b4cbe054bd04d67bf7bcca006740599
          name: 'Create time'
          type: DEPENDENT
          key: aws.rds.create_time
          value_type: FLOAT
          units: unixtime
          description: 'Provides the date and time the DB instance was created.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $..InstanceCreateTime.first()
          master_item:
            key: aws.rds.get_instance_info
          tags:
            - tag: component
              value: instance
        - uuid: 9def6dbb88c249e8bdbac484f2e1cfb0
          name: Connections
          type: DEPENDENT
          key: aws.rds.database_connections
          value_type: FLOAT
          description: |
            The number of client network connections to the database instance.
            The number of database sessions can be higher than the metric value because the metric value doesn't include the following:
            
            - Sessions that no longer have a network connection but which the database hasn't cleaned up
            - Sessions created by the database engine for its own purposes
            - Sessions created by the database engine's parallel execution capabilities
            - Sessions created by the database engine job scheduler
            - Amazon Aurora/RDS connections
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "DatabaseConnections")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: connections
        - uuid: a60833d27daf49329c58a4ca0d9affa5
          name: 'Disk: Queue depth'
          type: DEPENDENT
          key: aws.rds.disk_queue_depth
          value_type: FLOAT
          description: 'The number of outstanding read/write requests waiting to access the disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "DiskQueueDepth")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: 1fb56b1936024dfca328660471827ce2
          name: 'EBS: Byte balance'
          type: DEPENDENT
          key: aws.rds.ebs_byte_balance
          value_type: FLOAT
          units: '%'
          description: |
            The percentage of throughput credits remaining in the burst bucket of your RDS database. This metric is available for basic monitoring only.
            To find the instance sizes that support this metric, see the instance sizes with an asterisk (*) in the EBS optimized by default table (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-optimized.html#current) in Amazon RDS User Guide for Linux Instances.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "EBSByteBalance%")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: ebs
          triggers:
            - uuid: b878ee69a01a47a09677b184f8352668
              expression: 'max(/AWS RDS instance by HTTP/aws.rds.ebs_byte_balance,5m)<{$AWS.EBS.BYTE.CREDIT.BALANCE.MIN.WARN}'
              name: 'AWS RDS: Byte Credit balance is too low'
              event_name: 'AWS RDS: Byte Credit balance is too low (less {$AWS.EBS.BYTE.CREDIT.BALANCE.MIN.WARN}% for 5m)'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              tags:
                - tag: scope
                  value: capacity
        - uuid: 44eadf0d51244375a302110cb00e8e88
          name: 'EBS: IO balance'
          type: DEPENDENT
          key: aws.rds.ebs_io_balance
          value_type: FLOAT
          units: '%'
          description: |
            The percentage of I/O credits remaining in the burst bucket of your RDS database. This metric is available for basic monitoring only.
            To find the instance sizes that support this metric, see the instance sizes with an asterisk (*) in the EBS optimized by default table (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-optimized.html#current) in Amazon RDS User Guide for Linux Instances.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "EBSIOBalance%")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: ebs
          triggers:
            - uuid: 556100b7e8414543bf88017e13fb718f
              expression: 'max(/AWS RDS instance by HTTP/aws.rds.ebs_io_balance,5m)<{$AWS.EBS.IO.CREDIT.BALANCE.MIN.WARN}'
              name: 'AWS RDS: I/O Credit balance is too low'
              event_name: 'AWS RDS: I/O Credit balance is too low (less {$AWS.EBS.IO.CREDIT.BALANCE.MIN.WARN}% for 5m)'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: WARNING
              tags:
                - tag: scope
                  value: capacity
        - uuid: cad47e37ddc04100a8a7c3bca5f9049f
          name: Engine
          type: DEPENDENT
          key: aws.rds.engine
          value_type: CHAR
          description: 'Database engine.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $..Engine.first()
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.rds.get_instance_info
          tags:
            - tag: component
              value: instance
        - uuid: fefdac322230485cb792f295bb1420af
          name: 'Engine version'
          type: DEPENDENT
          key: aws.rds.engine.version
          value_type: CHAR
          description: 'Indicates the database engine version.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$[*].EngineVersion.first()'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.rds.get_instance_info
          tags:
            - tag: component
              value: instance
        - uuid: 5e83a36bcbf64098938ab7bb4725c39c
          name: 'Get events check'
          type: DEPENDENT
          key: aws.rds.events.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.rds.get_events
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: 600805420f704d4daca1ac20903f27f5
              expression: 'length(last(/AWS RDS instance by HTTP/aws.rds.events.check))>0'
              name: 'AWS RDS: Failed to get events data'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Failed to get CloudWatch events for RDS.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 641677b6f7c147058b1e77967754028f
          name: 'SQLServer: Failed agent jobs'
          type: DEPENDENT
          key: aws.rds.failed_sql_server_agent_jobs_count
          value_type: FLOAT
          units: Rpm
          description: 'The number of failed Microsoft SQL Server Agent jobs during the last minute.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "FailedSQLServerAgentJobsCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: application
            - tag: engine
              value: sqlserver
        - uuid: df8b49f346f8468b887526700295a6c4
          name: 'Memory, freeable'
          type: DEPENDENT
          key: aws.rds.freeable_memory
          value_type: FLOAT
          units: B
          description: |
            The amount of available random access memory.
            
            For MariaDB, MySQL, Oracle, and PostgreSQL DB instances, this metric reports the value of the MemAvailable field of /proc/meminfo.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "FreeableMemory")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: memory
        - uuid: 33dfd559dd93470cabf27f3a9a0968f1
          name: 'Storage: Local free'
          type: DEPENDENT
          key: aws.rds.free_local_storage
          value_type: FLOAT
          units: B
          description: |
            The amount of local storage available, in bytes.
            
            Unlike for other DB engines, for Aurora DB instances this metric reports the amount of storage available to each DB instance.
            This value depends on the DB instance class. You can increase the amount of free storage space for an instance by choosing a larger DB instance class for your instance.
            (This doesn't apply to Aurora Serverless v2.)
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "FreeLocalStorage")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: fc3fbf1da0b9481c9eee00838c05157f
          name: 'Storage: Space free'
          type: DEPENDENT
          key: aws.rds.free_storage_space
          value_type: FLOAT
          units: B
          description: 'The amount of available storage space.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "FreeStorageSpace")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: a2f85e777eae4fe789446de21136c510
          name: 'Get instance alarms data'
          type: SCRIPT
          key: aws.rds.get_alarms
          delay: 0s;m/1
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', 'db_instance_id'].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'),
            			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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS RDS ] Sending request: ' + url);
            		response = request.get(url);
            		Zabbix.log(4, '[ AWS RDS ] 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) {
            			try {
            				response = JSON.parse(XML.toJson(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;
            
            				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 === 'DBInstanceIdentifier' && dimensions[i].Value === AWS.params.db_instance_id) {
            						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 RDS ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: '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: db_instance_id
              value: '{$AWS.RDS.INSTANCE.ID}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: f0d1041fa09d4ba38c9d0b39c4b76b0b
          name: 'Get instance events data'
          type: SCRIPT
          key: aws.rds.get_events
          delay: 0s;m/10
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', 'db_instance_id'].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'),
            			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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS RDS ] Sending request: ' + url);
            		response = request.get(url);
            		Zabbix.log(4, '[ AWS RDS ] 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) {
            			try {
            				response = JSON.parse(XML.toJson(response));
            			}
            			catch (error) {
            				throw 'Failed to parse response received from AWS RDS API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	getEvents: function () {
            		var payload = {
            			'Action': 'DescribeEvents',
            			'Version': '2014-09-01',
            			'MaxRecords': 100,
            			'Duration': 30,
            			'SourceType': 'db-instance',
            			'SourceIdentifier': AWS.params.db_instance_id
            		},
            			result = [];
            
            		while (payload.nextToken !== '') {
            			var events = AWS.getField(AWS.request('GET', AWS.params.region, 'rds', AWS.prepareParams(payload)), 'DescribeEventsResponse.DescribeEventsResult');
            			events_list = AWS.getField(events, 'Events');
            
            			if (!Array.isArray(events_list))
            				events_list = [events_list];
            			events_list.forEach(function (event) {
            				event.EventCategories = event.EventCategories.toString();
            				result.push(event);
            			});
            			payload.nextToken = events.nextToken || '';
            
            
            		};
            
            		return result;
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	return JSON.stringify(AWS.getEvents());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS RDS ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: 'DescribeEvents API method: https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DescribeEvents.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: db_instance_id
              value: '{$AWS.RDS.INSTANCE.ID}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: 85ac4a5313994e0f94fe6480d3c85193
          name: 'Get instance info'
          type: SCRIPT
          key: aws.rds.get_instance_info
          delay: 5m
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	request_period: 600,
            	metadata: 'http://169.254.169.254/latest/',
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', 'db_instance_id'].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'),
            			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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS RDS ] Sending request: ' + url);
            		response = request.get(url);
            		Zabbix.log(4, '[ AWS RDS ] 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) {
            			try {
            				response = JSON.parse(XML.toJson(response));
            			}
            			catch (error) {
            				throw 'Failed to parse response received from AWS RDS API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	getInstanceData: function () {
            		var payload = {};
            
            		payload['Action'] = 'DescribeDBInstances',
            			payload['Version'] = '2014-10-31',
            			payload['DBInstanceIdentifier'] = AWS.params.db_instance_id;
            
            		result = AWS.request('GET', AWS.params.region, 'rds', AWS.prepareParams(payload));
            		if (typeof result !== 'object'
            			|| typeof result.DescribeDBInstancesResponse !== 'object'
            			|| typeof result.DescribeDBInstancesResponse.DescribeDBInstancesResult !== 'object'
            			|| typeof result.DescribeDBInstancesResponse.DescribeDBInstancesResult.DBInstances !== 'object') {
            			throw 'Cannot get metrics data from AWS RDS API. Check debug log for more information.';
            		}
            
            		return result.DescribeDBInstancesResponse.DescribeDBInstancesResult.DBInstances;
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	return JSON.stringify(AWS.getInstanceData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS RDS ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: |
            Get instance info.
            DescribeDBInstances API method: https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DescribeDBInstances.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: db_instance_id
              value: '{$AWS.RDS.INSTANCE.ID}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: b22171fe7de44ac3952468ceb0c1a9b0
          name: 'Get metrics data'
          type: SCRIPT
          key: aws.rds.get_metrics
          delay: 0s;m/5
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	request_period: 600,
            	metadata: 'http://169.254.169.254/latest/',
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('POST', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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', 'db_instance_id'].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('&');
            	},
            
            	renderMetricQuery: function (period, db_instance_id) {
            		var metrics_list = [
            			'AbortedClients:Count',
            			'ActiveTransactions:Count/Second',
            			'AuroraBinlogReplicaLag:Seconds',
            			'AuroraReplicaLag:Milliseconds',
            			'AuroraReplicaLagMaximum:Milliseconds',
            			'AuroraReplicaLagMinimum:Milliseconds',
            			'BacktrackWindowActual:Count',
            			'BacktrackWindowAlert:Count',
            			'BinLogDiskUsage:Bytes',
            			'BlockedTransactions:Count/Second',
            			'BufferCacheHitRatio:Percent',
            			'CheckpointLag:Seconds',
            			'CommitLatency:Milliseconds',
            			'CommitThroughput:Count/Second',
            			'CPUCreditBalance:Count',
            			'CPUCreditUsage:Count',
            			'CPUUtilization:Percent',
            			'DatabaseConnections:Count',
            			'DDLLatency:Milliseconds',
            			'DDLThroughput:Count/Second',
            			'Deadlocks:Count/Second',
            			'DeleteLatency:Milliseconds',
            			'DeleteThroughput:Count/Second',
            			'DiskQueueDepth:Count',
            			'DMLLatency:Milliseconds',
            			'DMLThroughput:Count/Second',
            			'EBSByteBalance%:Percent',
            			'EBSIOBalance%:Percent',
            			'EngineUptime:Seconds',
            			'FailedSQLServerAgentJobsCount:Count/Second',
            			'FreeableMemory:Bytes',
            			'FreeLocalStorage:Bytes',
            			'InsertLatency:Milliseconds',
            			'InsertThroughput:Count/Second',
            			'LoginFailures:Count/Second',
            			'MaximumUsedTransactionIDs:Count',
            			'NetworkReceiveThroughput:Bytes/Second',
            			'NetworkThroughput:Bytes/Second',
            			'NetworkTransmitThroughput:Bytes/Second',
            			'NumBinaryLogFiles:Count',
            			'Queries:Count/Second',
            			'RDSToAuroraPostgreSQLReplicaLag:Seconds',
            			'ReadIOPS:Count/Second',
            			'ReadLatency:Seconds',
            			'ReadLatencyLocalStorage:Seconds',
            			'ReadThroughput:Bytes/Second',
            			'ReadThroughputLocalStorage:Bytes/Second',
            			'ReplicationSlotDiskUsage:Bytes',
            			'ResultSetCacheHitRatio:Percent',
            			'RollbackSegmentHistoryListLength:Count',
            			'RowLockTime:Milliseconds',
            			'SelectLatency:Milliseconds',
            			'SelectThroughput:Count/Second',
            			'StorageNetworkReceiveThroughput:Bytes/Second',
            			'StorageNetworkThroughput:Bytes/Second',
            			'StorageNetworkTransmitThroughput:Bytes/Second',
            			'SumBinaryLogSize:Bytes',
            			'SwapUsage:Bytes',
            			'TransactionLogsDiskUsage:Bytes',
            			'UpdateLatency:Milliseconds',
            			'UpdateThroughput:Count/Second',
            			'WriteIOPS:Count/Second',
            			'WriteLatency:Seconds',
            			'WriteThroughput:Bytes/Second',
            			'BurstBalance:Percent',
            			'FreeStorageSpace:Bytes',
            			'OldestReplicationSlotLag:Bytes',
            			'ReplicaLag:Seconds',
            			'TransactionLogsGeneration:Bytes/Second'
            		];
            
            		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': 'AWS/RDS',
            						'Dimensions': [
            							{
            								'Name': 'DBInstanceIdentifier',
            								'Value': db_instance_id
            							}
            						]
            					},
            					'Period': period,
            					'Stat': 'Average',
            					'Unit': parts[1]
            				}
            			});
            		});
            
            		return metric_payload;
            
            	},
            
            	request: function (method, region, service, params, data) {
            		if (typeof data === 'undefined' || data === null) {
            			data = '';
            		}
            		else {
            			data = JSON.stringify(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'),
            			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-Target: GraniteServiceVersion20100801.GetMetricData');
            		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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + (AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken));
            		}
            
            		Zabbix.log(4, '[ AWS RDS ] Sending request: ' + url);
            		response = request.post(url, data);
            		Zabbix.log(4, '[ AWS RDS ] 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) {
            			try {
            				response = JSON.parse(XML.toJson(response));
            			}
            			catch (error) {
            				throw 'Failed to parse response received from AWS CloudWatch API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	getMetricsData: function () {
            		var payload = {},
            			end_time = Math.floor((new Date().getTime()) / 1000),
            			start_time = end_time - AWS.request_period;
            
            		payload['StartTime'] = start_time;
            		payload['EndTime'] = end_time;
            		payload['ScanBy'] = 'TimestampDescending';
            		payload['MetricDataQueries'] = AWS.renderMetricQuery(AWS.request_period, AWS.params.db_instance_id);
            		result = AWS.request('POST', AWS.params.region, 'monitoring', '', payload);
            		if (typeof result !== 'object' || typeof result.MetricDataResults !== 'object') {
            			throw 'Cannot get metrics data from AWS CloudWatch API. Check debug log for more information.';
            		}
            
            		return result.MetricDataResults;
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	return JSON.stringify(AWS.getMetricsData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS RDS ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: |
            Get instance metrics.
            Full metrics list related to RDS: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-metrics.html
            Full metrics list related to Amazon Aurora: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.AuroraMySQL.Monitoring.Metrics.html#Aurora.AuroraMySQL.Monitoring.Metrics.instances
          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: db_instance_id
              value: '{$AWS.RDS.INSTANCE.ID}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: 72fb52bfbcf44ad58df0d49525654cde
          name: 'Get instance info check'
          type: DEPENDENT
          key: aws.rds.instance_info.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.rds.get_instance_info
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: 452195309f1f4211aeb71b43a373f86f
              expression: 'length(last(/AWS RDS instance by HTTP/aws.rds.instance_info.check))>0'
              name: 'AWS RDS: Failed to get instance data'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Failed to get CloudWatch instance info for RDS.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 8f651a01cd1d4639b6a4ef443285b24c
          name: 'Get metrics check'
          type: DEPENDENT
          key: aws.rds.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.rds.get_metrics
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: 54c70842bf314ce2a9c95e0cfc57cc21
              expression: 'length(last(/AWS RDS instance by HTTP/aws.rds.metrics.check))>0'
              name: 'AWS RDS: Failed to get metrics data'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Failed to get CloudWatch metrics for RDS.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 4d5ce2d0bb0648a6b4e4df98dc20fb49
          name: 'Network: Receive throughput'
          type: DEPENDENT
          key: aws.rds.network_receive_throughput.rate
          value_type: FLOAT
          units: Bps
          description: 'The incoming (Receive) network traffic on the DB instance, including both customer database traffic and Amazon RDS traffic used for monitoring and replication.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "NetworkReceiveThroughput")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: network
        - uuid: 8de924155ca646e0a63de9fb4184e2b7
          name: 'Network: Throughput'
          type: DEPENDENT
          key: aws.rds.network_throughput.rate
          value_type: FLOAT
          units: Bps
          description: 'The amount of network throughput both received from and transmitted to clients by each instance in the Aurora MySQL DB cluster, in bytes per second. This throughput doesn''t include network traffic between instances in the DB cluster and the cluster volume.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "NetworkThroughput")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: network
        - uuid: a97083537fce49c99caf71d1b0b2926f
          name: 'Network: Transmit throughput'
          type: DEPENDENT
          key: aws.rds.network_transmit_throughput.rate
          value_type: FLOAT
          units: Bps
          description: 'The outgoing (Transmit) network traffic on the DB instance, including both customer database traffic and Amazon RDS traffic used for monitoring and replication.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "NetworkTransmitThroughput")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: network
        - uuid: 3f9ac8ce149e4fb2a65580941c4d5428
          name: 'Disk: Read IOPS'
          type: DEPENDENT
          key: aws.rds.read_iops.rate
          value_type: FLOAT
          units: Rps
          description: 'The average number of disk I/O operations per second. Aurora PostgreSQL-Compatible Edition reports read and write IOPS separately, in 1-minute intervals.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ReadIOPS")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: bd55865999364de890e87da30676adea
          name: 'Disk: Read IOPS, local storage'
          type: DEPENDENT
          key: aws.rds.read_iops_local_storage.rate
          value_type: FLOAT
          units: Rps
          description: 'The average number of disk read I/O operations to local storage per second. Only applies to Multi-AZ DB clusters.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ReadIOPSLocalStorage")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: 3ad5d0d0bbbb4e579c74dd54923ccd8b
          name: 'Disk: Read latency'
          type: DEPENDENT
          key: aws.rds.read_latency
          value_type: FLOAT
          units: s
          description: 'The average amount of time taken per disk I/O operation.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ReadLatency")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: 2d85eb0d8e2641bf95b3c5dbbb125089
          name: 'Disk: Read latency, local storage'
          type: DEPENDENT
          key: aws.rds.read_latency_local_storage
          value_type: FLOAT
          units: s
          description: 'The average amount of time taken per disk I/O operation for local storage. Only applies to Multi-AZ DB clusters.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ReadLatencyLocalStorage")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: 9253279ef6c34d86a2b1750c8d8b29d0
          name: 'Read replica: State'
          type: DEPENDENT
          key: aws.rds.read_replica_state
          value_type: CHAR
          description: |
            The status of a read replica. If the instance isn't a read replica, this is blank.
            Boolean value that is true if the instance is operating normally, or false if the instance is in an error state.
          valuemap:
            name: 'Read replica state'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $..StatusInfos..Normal.first()
              error_handler: DISCARD_VALUE
            - type: BOOL_TO_DECIMAL
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.rds.get_instance_info
          tags:
            - tag: component
              value: replication
          triggers:
            - uuid: 1f4767ba167f43b7ae9730ec834152a4
              expression: 'last(/AWS RDS instance by HTTP/aws.rds.read_replica_state)=0'
              name: 'AWS RDS: Read replica in error state'
              priority: AVERAGE
              description: |
                The status of a read replica.
                False if the instance is in an error state.
              tags:
                - tag: scope
                  value: availability
        - uuid: 8fd266a7e4744395b21638b58c939072
          name: 'Read replica: Status'
          type: DEPENDENT
          key: aws.rds.read_replica_status
          value_type: CHAR
          description: |
            The status of a read replica. If the instance isn't a read replica, this is blank.
            Status of the DB instance. For a StatusType of read replica, the values can be replicating, replication stop point set, replication stop point reached, error, stopped, or terminated.
          preprocessing:
            - type: JSONPATH
              parameters:
                - $..StatusInfos..Status.first()
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.rds.get_instance_info
          tags:
            - tag: component
              value: replication
        - uuid: 14b63bcb60fd4c91b87357d3f77e71df
          name: 'Disk: Read throughput'
          type: DEPENDENT
          key: aws.rds.read_throughput.rate
          value_type: FLOAT
          units: Bps
          description: 'The average number of bytes read from disk per second.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ReadThroughput")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: bc963bae1664421c8874d77b085006a6
          name: 'Disk: Read throughput, local storage'
          type: DEPENDENT
          key: aws.rds.read_throughput_local_storage.rate
          value_type: FLOAT
          units: Bps
          description: 'The average number of bytes read from disk per second for local storage. Only applies to Multi-AZ DB clusters.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ReadThroughputLocalStorage")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: 7be22cd083bc401bbbd2d75f2f6816de
          name: 'Replication: Lag'
          type: DEPENDENT
          key: aws.rds.replica_lag
          value_type: FLOAT
          units: s
          description: 'The amount of time a read replica DB instance lags behind the source DB instance. Applies to MySQL, MariaDB, Oracle, PostgreSQL, and SQL Server read replicas.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "ReplicaLag")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: replication
            - tag: engine
              value: mariadb
            - tag: engine
              value: mysql
            - tag: engine
              value: oracle
            - tag: engine
              value: postgres
            - tag: engine
              value: sqlserver
        - uuid: f6fe45dc205241cb99b1822d3f78cce6
          name: Status
          type: DEPENDENT
          key: aws.rds.status
          value_type: CHAR
          description: |
            Specifies the current state of this database.
            All possible status values and their description: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/accessing-monitoring.html#Overview.DBInstance.Status
          preprocessing:
            - type: JSONPATH
              parameters:
                - $..DBInstanceStatus.first()
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.rds.get_instance_info
          tags:
            - tag: component
              value: instance
        - uuid: 2694163a440f40e4a5ec41111f9abf59
          name: 'Storage: Allocated'
          type: DEPENDENT
          key: aws.rds.storage.allocated
          value_type: FLOAT
          units: '!GiB'
          description: 'Specifies the allocated storage size specified in gibibytes (GiB).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$[*].AllocatedStorage.first()'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.rds.get_instance_info
          tags:
            - tag: component
              value: storage
        - uuid: 1aafa7a752274a1abb30b7b2e067b857
          name: 'Storage: Max allocated'
          type: DEPENDENT
          key: aws.rds.storage.max_allocated
          value_type: FLOAT
          units: '!GiB'
          description: |
            The upper limit in gibibytes (GiB) to which Amazon RDS can automatically scale the storage of the DB instance.
            If limit is not specified returns -1.
          preprocessing:
            - type: JAVASCRIPT
              parameters:
                - |
                  var data = JSON.parse(value);
                  return (typeof data.MaxAllocatedStorage === 'undefined') ? -1 : data.MaxAllocatedStorage;
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.rds.get_instance_info
          tags:
            - tag: component
              value: storage
        - uuid: 842f80f586794da39562ceb3cb09d5a4
          name: 'Network: Receive throughput'
          type: DEPENDENT
          key: aws.rds.storage_network_receive_throughput
          value_type: FLOAT
          units: Bps
          description: |
            The incoming (receive) network traffic on the DB instance, including both customer database traffic and Amazon RDS traffic used for monitoring and replication.
            For Amazon Aurora: The amount of network throughput received from the Aurora storage subsystem by each instance in the DB cluster.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "StorageNetworkReceiveThroughput")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: network
        - uuid: bab141cde0114edf8b02211565df5b1f
          name: 'Network: Transmit throughput'
          type: DEPENDENT
          key: aws.rds.storage_network_transmit_throughput
          value_type: FLOAT
          units: Bps
          description: |
            The outgoing (transmit) network traffic on the DB instance, including both customer database traffic and Amazon RDS traffic used for monitoring and replication.
            For Amazon Aurora: The amount of network throughput sent to the Aurora storage subsystem by each instance in the Aurora MySQL DB cluster.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "StorageNetworkTransmitThroughput")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: network
        - uuid: 6b3a8fd76fe6466395dcc4926d7177b4
          name: 'Storage type'
          type: DEPENDENT
          key: aws.rds.storage_type
          value_type: CHAR
          description: 'Specifies the storage type associated with DB instance.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$[*].StorageType.first()'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.rds.get_instance_info
          tags:
            - tag: component
              value: instance
        - uuid: f9d1a5169ec54f648937eac63b3ebcbb
          name: 'Swap usage'
          type: DEPENDENT
          key: aws.rds.swap_usage
          value_type: FLOAT
          units: B
          description: |
            The amount of swap space used.
            This metric is available for the Aurora PostgreSQL DB instance classes db.t3.medium, db.t3.large, db.r4.large, db.r4.xlarge, db.r5.large, db.r5.xlarge, db.r6g.large, and db.r6g.xlarge.
            For Aurora MySQL, this metric applies only to db.t* DB instance classes.
            This metric is not available for SQL Server.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "SwapUsage")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: memory
        - uuid: a64c2caccd884f0f9bb7c9c9295baf45
          name: 'Disk: Write IOPS'
          type: DEPENDENT
          key: aws.rds.write_iops.rate
          value_type: FLOAT
          units: Rps
          description: 'The number of write records generated per second. This is more or less the number of log records generated by the database. These do not correspond to 8K page writes, and do not correspond to network packets sent.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "WriteIOPS")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: 19dc221c59ec4587af496bd644830869
          name: 'Disk: Write IOPS, local storage'
          type: DEPENDENT
          key: aws.rds.write_iops_local_storage.rate
          value_type: FLOAT
          units: Rps
          description: 'The average number of disk write I/O operations per second on local storage in a Multi-AZ DB cluster.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "WriteIOPSLocalStorage")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: 57e84381425d4706a2bcea41e0373157
          name: 'Disk: Write latency'
          type: DEPENDENT
          key: aws.rds.write_latency
          value_type: FLOAT
          units: s
          description: 'The average amount of time taken per disk I/O operation.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "WriteLatency")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: b34b656492e8479ea03b97815d368752
          name: 'Disk: Write latency, local storage'
          type: DEPENDENT
          key: aws.rds.write_latency_local_storage
          value_type: FLOAT
          units: s
          description: 'The average amount of time taken per disk I/O operation on local storage in a Multi-AZ DB cluster.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "WriteLatencyLocalStorage")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: db6932f63f7843508bb9e5559a69e8c3
          name: 'Disk: Write throughput'
          type: DEPENDENT
          key: aws.rds.write_throughput.rate
          value_type: FLOAT
          units: Bps
          description: 'The average number of bytes written to persistent storage every second.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "WriteThroughput")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
        - uuid: f30df9f386be49948bce7817d56dae09
          name: 'Disk: Write throughput, local storage'
          type: DEPENDENT
          key: aws.rds.write_throughput_local_storage.rate
          value_type: FLOAT
          units: Bps
          description: 'The average number of bytes written to disk per second for local storage.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "WriteThroughputLocalStorage")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.rds.get_metrics
          tags:
            - tag: component
              value: disk
      discovery_rules:
        - uuid: 29b2b32b0d82450393f77ec7e093ef81
          name: 'Instance Alarms discovery'
          type: DEPENDENT
          key: aws.rds.alarms.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.RDS.LLD.FILTER.ALARM_NAME.MATCHES}'
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.RDS.LLD.FILTER.ALARM_NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#ALARM_SERVICE_NAMESPACE}'
                value: '{$AWS.RDS.LLD.FILTER.ALARM_SERVICE_NAMESPACE.MATCHES}'
              - macro: '{#ALARM_SERVICE_NAMESPACE}'
                value: '{$AWS.RDS.LLD.FILTER.ALARM_SERVICE_NAMESPACE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery instance alarms.'
          item_prototypes:
            - uuid: aab5aaf6e27740c6ac92f5494b3aef4b
              name: '[{#ALARM_NAME}]: State'
              type: DEPENDENT
              key: 'aws.rds.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:
                    - '$.[?(@.AlarmName == "{#ALARM_NAME}")].StateValue.first()'
                  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.rds.get_alarms
              tags:
                - tag: component
                  value: alarms
              trigger_prototypes:
                - uuid: 7d87b8d84fef4aff8aa9c0fd49e49619
                  expression: 'last(/AWS RDS instance by HTTP/aws.rds.alarm.state["{#ALARM_NAME}"])=1'
                  name: 'AWS RDS: [{#ALARM_NAME}] has ''Insufficient data'' state'
                  priority: INFO
                  description: 'Either the alarm has just started, the metric is not available, or not enough data is available for the metric to determine the alarm state.'
                  tags:
                    - tag: scope
                      value: notice
            - uuid: 6e95f834b2284447b5ab0f6516d29946
              name: '[{#ALARM_NAME}]: State reason'
              type: DEPENDENT
              key: 'aws.rds.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:
                    - '$.[?(@.AlarmName == "{#ALARM_NAME}")].StateReason.first()'
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: aws.rds.get_alarms
              tags:
                - tag: component
                  value: alarms
          trigger_prototypes:
            - uuid: 0f70f3d91d9c403c9d4c3cfb3283865f
              expression: 'last(/AWS RDS instance by HTTP/aws.rds.alarm.state["{#ALARM_NAME}"])=2 and length(last(/AWS RDS instance by HTTP/aws.rds.alarm.state_reason["{#ALARM_NAME}"]))>0'
              name: 'AWS RDS: [{#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.rds.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: f13154dfb6b547718d1bf4b0ed12d35f
          name: 'Aurora metrics discovery'
          type: DEPENDENT
          key: aws.rds.aurora.discovery
          description: |
            Discovery Amazon Aurora metrics.
            https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.AuroraMySQL.Monitoring.Metrics.html#Aurora.AuroraMySQL.Monitoring.Metrics.instances
          item_prototypes:
            - uuid: 28df1a214515425099514140a1244cc4
              name: 'Replication: Lag, max'
              type: DEPENDENT
              key: 'aws.rds.aurora_replica_lag.max[{#SINGLETON}]'
              value_type: FLOAT
              units: ms
              description: 'The maximum amount of lag between the primary instance and each Aurora DB instance in the DB cluster.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "AuroraReplicaLagMaximum")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: replication
                - tag: engine
                  value: aurora
            - uuid: 39e226420be740bd81712624d4d86882
              name: 'Replication: Lag, min'
              type: DEPENDENT
              key: 'aws.rds.aurora_replica_lag.min[{#SINGLETON}]'
              value_type: FLOAT
              units: ms
              description: 'The minimum amount of lag between the primary instance and each Aurora DB instance in the DB cluster.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "AuroraReplicaLagMinimum")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: replication
                - tag: engine
                  value: aurora
            - uuid: 966022d4bc484918b9497d3515c35f9d
              name: 'Replication: Lag'
              type: DEPENDENT
              key: 'aws.rds.aurora_replica_lag[{#SINGLETON}]'
              value_type: FLOAT
              units: ms
              description: 'For an Aurora replica, the amount of lag when replicating updates from the primary instance.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "AuroraReplicaLag")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: replication
                - tag: engine
                  value: aurora
            - uuid: 4a76341c354540b48677c29a92270d57
              name: 'Buffer Cache hit ratio'
              type: DEPENDENT
              key: 'aws.rds.buffer_cache_hit_ratio[{#SINGLETON}]'
              value_type: FLOAT
              units: '%'
              description: 'The percentage of requests that are served by the buffer cache.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "BufferCacheHitRatio")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: cache
                - tag: engine
                  value: aurora
            - uuid: a988ecbcb5804916a37e2c4270cf1261
              name: 'Operations: Commit latency'
              type: DEPENDENT
              key: 'aws.rds.commit_latency[{#SINGLETON}]'
              value_type: FLOAT
              units: ms
              description: 'The amount of latency for commit operations.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "CommitLatency")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: operations
                - tag: engine
                  value: aurora
            - uuid: 0892af875af04dbebd3954b37a196605
              name: 'Operations: Commit throughput'
              type: DEPENDENT
              key: 'aws.rds.commit_throughput.rate[{#SINGLETON}]'
              value_type: FLOAT
              description: 'The average number of commit operations per second.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "CommitThroughput")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: operations
                - tag: engine
                  value: aurora
            - uuid: febdffdd64974deb91185af1bbc78ffd
              name: 'Deadlocks, rate'
              type: DEPENDENT
              key: 'aws.rds.deadlocks.rate[{#SINGLETON}]'
              value_type: FLOAT
              description: 'The average number of deadlocks in the database per second.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "Deadlocks")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: operations
                - tag: engine
                  value: aurora
            - uuid: 24d139d74b034e2096f50943fa003e4f
              name: 'Engine uptime'
              type: DEPENDENT
              key: 'aws.rds.engine_uptime[{#SINGLETON}]'
              value_type: FLOAT
              units: s
              description: 'The amount of time that the instance has been running.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "EngineUptime")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: instance
                - tag: engine
                  value: aurora
            - uuid: 65ee7a93945d4c7baf6c20137e62b9dc
              name: 'Rollback segment history list length'
              type: DEPENDENT
              key: 'aws.rds.rollback_segment_history_list_length[{#SINGLETON}]'
              value_type: FLOAT
              description: 'The undo logs that record committed transactions with delete-marked records. These records are scheduled to be processed by the InnoDB purge operation.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "RollbackSegmentHistoryListLength")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: application
                - tag: engine
                  value: aurora-mysql
            - uuid: 2c1b3f9701f343e5845c78c52e71f72f
              name: 'Row lock time'
              type: DEPENDENT
              key: 'aws.rds.row_locktime[{#SINGLETON}]'
              value_type: FLOAT
              units: ms
              description: 'The total time spent acquiring row locks for InnoDB tables.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "RowLockTime")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: application
                - tag: engine
                  value: aurora-mysql
            - uuid: 05218f79a137466392af0652acfe2db5
              name: 'Operations: Select latency'
              type: DEPENDENT
              key: 'aws.rds.select_latency[{#SINGLETON}]'
              value_type: FLOAT
              units: ms
              description: 'The amount of latency for select queries.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "SelectLatency")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: operations
                - tag: engine
                  value: aurora-mysql
            - uuid: 849c0bd9b5d940568bc1e71eb6318738
              name: 'Operations: Select throughput'
              type: DEPENDENT
              key: 'aws.rds.select_throughput.rate[{#SINGLETON}]'
              value_type: FLOAT
              units: rps
              description: 'The average number of select queries per second.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "SelectThroughput")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: operations
                - tag: engine
                  value: aurora-mysql
            - uuid: 62e6fa21b2f54030bbbd04f268de5737
              name: 'Network: Throughput'
              type: DEPENDENT
              key: 'aws.rds.storage_network_throughput[{#SINGLETON}]'
              value_type: FLOAT
              units: Bps
              description: 'The amount of network throughput received from and sent to the Aurora storage subsystem by each instance in the Aurora MySQL DB cluster.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "StorageNetworkThroughput")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: network
                - tag: engine
                  value: aurora
          graph_prototypes:
            - uuid: 3a753d02e4b8465a9f4da698c2acd387
              name: 'AWS RDS: [{#SINGLETON}]Operations Latency (commit/select)'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'AWS RDS instance by HTTP'
                    key: 'aws.rds.commit_latency[{#SINGLETON}]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'AWS RDS instance by HTTP'
                    key: 'aws.rds.select_latency[{#SINGLETON}]'
            - uuid: c856d61be8594efda8f87396c6ba31f9
              name: 'AWS RDS: [{#SINGLETON}]Operations Throughput (commit/select)'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'AWS RDS instance by HTTP'
                    key: 'aws.rds.commit_throughput.rate[{#SINGLETON}]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'AWS RDS instance by HTTP'
                    key: 'aws.rds.select_throughput.rate[{#SINGLETON}]'
          master_item:
            key: aws.rds.engine
          preprocessing:
            - type: JAVASCRIPT
              parameters:
                - 'return JSON.stringify(value.includes(''aurora'') ? [{ ''{#SINGLETON}'': '''' }] : []);'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 6h
        - uuid: cb9080a3bf4c4c51936bb8d818f69adc
          name: 'Instance Events discovery'
          type: DEPENDENT
          key: aws.rds.events.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#EVENT_CATEGORY}'
                value: '{$AWS.RDS.LLD.FILTER.EVENT_CATEGORY.MATCHES}'
              - macro: '{#EVENT_CATEGORY}'
                value: '{$AWS.RDS.LLD.FILTER.EVENT_CATEGORY.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#EVENT_SOURCE_TYPE}'
                value: '{$AWS.RDS.LLD.FILTER.EVENT_SOURCE_TYPE.MATCHES}'
              - macro: '{#EVENT_SOURCE_TYPE}'
                value: '{$AWS.RDS.LLD.FILTER.EVENT_SOURCE_TYPE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery instance events.'
          item_prototypes:
            - uuid: 21b9df85f2e841c48204c7cb4fb5caeb
              name: '[{#EVENT_CATEGORY}]: {#EVENT_SOURCE_TYPE}/{#EVENT_SOURCE_ID} : Date'
              type: DEPENDENT
              key: 'aws.rds.event_date["{#EVENT_CATEGORY}/{#EVENT_SOURCE_TYPE}/{#EVENT_SOURCE_ID}"]'
              value_type: FLOAT
              units: unixtime
              description: 'Provides the text of this event.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.SourceIdentifier == "{#EVENT_SOURCE_ID}" && @.SourceType == "{#EVENT_SOURCE_TYPE}" && @.EventCategories == "{#EVENT_CATEGORY}")].Date'
                  error_handler: DISCARD_VALUE
                - type: JSONPATH
                  parameters:
                    - '$[-1]'
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: aws.rds.get_events
              tags:
                - tag: component
                  value: events
                - tag: event-categories
                  value: '{#EVENT_CATEGORY}'
            - uuid: 10cf420329fa42c08266a5d38bc7678b
              name: '[{#EVENT_CATEGORY}]: {#EVENT_SOURCE_TYPE}/{#EVENT_SOURCE_ID}: Message'
              type: DEPENDENT
              key: 'aws.rds.event_message["{#EVENT_CATEGORY}/{#EVENT_SOURCE_TYPE}/{#EVENT_SOURCE_ID}"]'
              value_type: TEXT
              description: 'Provides the text of this event.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.SourceIdentifier == "{#EVENT_SOURCE_ID}" && @.SourceType == "{#EVENT_SOURCE_TYPE}" && @.EventCategories == "{#EVENT_CATEGORY}")].Message'
                  error_handler: DISCARD_VALUE
                - type: JSONPATH
                  parameters:
                    - '$[-1]'
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: aws.rds.get_events
              tags:
                - tag: component
                  value: events
                - tag: event-categories
                  value: '{#EVENT_CATEGORY}'
          master_item:
            key: aws.rds.get_events
          preprocessing:
            - type: JAVASCRIPT
              parameters:
                - |
                  var lookup = {},
                  	result = [];
                  
                  JSON.parse(value).forEach(function (event) {
                  	var filter = event.EventCategories + event.SourceIdentifier + event.SourceType;
                  	if (!(lookup[filter])) {
                  		lookup[filter] = 1;
                  		result.push({
                  			'{#EVENT_CATEGORY}': event.EventCategories,
                  			'{#EVENT_SOURCE_ID}': event.SourceIdentifier,
                  			'{#EVENT_SOURCE_TYPE}': event.SourceType
                  		});
                  	}
                  });
                  
                  return JSON.stringify(result);
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
        - uuid: ec07301eaaad4f32a3759692d96150ab
          name: 'Aurora MySQL metrics discovery'
          type: DEPENDENT
          key: aws.rds.postgresql.discovery
          description: |
            Discovery Aurora MySQL metrics.
            Storage types:
             aurora (for MySQL 5.6-compatible Aurora)
             aurora-mysql (for MySQL 5.7-compatible and MySQL 8.0-compatible Aurora)
          item_prototypes:
            - uuid: 3842a935bedf446d8b8b9a7fd58fc24b
              name: 'Connections: Aborted'
              type: DEPENDENT
              key: 'aws.rds.aurora_clients_aborted[{#SINGLETON}]'
              value_type: FLOAT
              description: 'The number of client connections that have not been closed properly.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "AbortedClients")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: connections
                - tag: engine
                  value: aurora-mysql
            - uuid: 8b87e0f4f1fc4290a7c72ec382b74941
              name: 'Replication: Binlog lag'
              type: DEPENDENT
              key: 'aws.rds.aurora_replication_binlog_lag[{#SINGLETON}]'
              value_type: FLOAT
              units: s
              description: |
                The amount of time that a binary log replica DB cluster running on Aurora MySQL-Compatible Edition lags behind the binary log replication source.
                A lag means that the source is generating records faster than the replica can apply them.
                The metric value indicates the following:
                
                A high value: The replica is lagging the replication source.
                0 or a value close to 0: The replica process is active and current.
                -1: Aurora can't determine the lag, which can happen during replica setup or when the replica is in an error state
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "AuroraBinlogReplicaLag")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: replication
                - tag: engine
                  value: aurora-mysql
            - uuid: 97f85bd65fc64b66b57b122f8689bc38
              name: 'Transactions: Active, rate'
              type: DEPENDENT
              key: 'aws.rds.aurora_transactions_active.rate[{#SINGLETON}]'
              value_type: FLOAT
              units: Rps
              description: |
                The average number of current transactions executing on an Aurora database instance per second.
                By default, Aurora doesn't enable this metric. To begin measuring this value, set innodb_monitor_enable='all' in the DB parameter group for a specific DB instance.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ActiveTransactions")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: transactions
                - tag: engine
                  value: aurora-mysql
            - uuid: 44ca3ca16bd1450790099a0354e78f13
              name: 'Backtrack: Window, actual'
              type: DEPENDENT
              key: 'aws.rds.backtrack_window_actual[{#SINGLETON}]'
              value_type: FLOAT
              units: '!minutes'
              description: 'The difference between the target backtrack window and the actual backtrack window.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "BacktrackWindowActual")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: backtrack
                - tag: engine
                  value: aurora-mysql
            - uuid: 20de520b7f53459db765eb221fcef248
              name: 'Backtrack: Window, alert'
              type: DEPENDENT
              key: 'aws.rds.backtrack_window_alert[{#SINGLETON}]'
              value_type: FLOAT
              description: 'The number of times that the actual backtrack window is smaller than the target backtrack window for a given period of time.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "BacktrackWindowAlert")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: backtrack
                - tag: engine
                  value: aurora-mysql
            - uuid: 570e88d397524dfeb10d6c46cc859404
              name: 'Transactions: Blocked, rate'
              type: DEPENDENT
              key: 'aws.rds.blocked_transactions.rate[{#SINGLETON}]'
              value_type: FLOAT
              units: Rps
              description: 'The average number of transactions in the database that are blocked per second.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "BlockedTransactions")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: transactions
                - tag: engine
                  value: aurora-mysql
            - uuid: 3033650e795943bfab73e9d7347f3d24
              name: 'DDL: Latency'
              type: DEPENDENT
              key: 'aws.rds.ddl_latency[{#SINGLETON}]'
              value_type: FLOAT
              units: ms
              description: 'The amount of latency for data definition language (DDL) requests - for example, create, alter, and drop requests.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "DDLLatency")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: requests
                - tag: engine
                  value: aurora-mysql
            - uuid: 1ee5fdb6ed004e708ebe5ec8b2d039ba
              name: 'DDL: Throughput'
              type: DEPENDENT
              key: 'aws.rds.ddl_throughput.rate[{#SINGLETON}]'
              value_type: FLOAT
              units: Rps
              description: 'The average number of DDL requests per second.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "DDLThroughput")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: requests
                - tag: engine
                  value: aurora-mysql
            - uuid: ab6a2d6f9c04497c86464f10aafa178c
              name: 'Operations: Delete latency'
              type: DEPENDENT
              key: 'aws.rds.delete_latency[{#SINGLETON}]'
              value_type: FLOAT
              units: ms
              description: 'The amount of latency for delete queries.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "DeleteLatency")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: operations
                - tag: engine
                  value: aurora-mysql
            - uuid: 9a28a1a0e1194d4fb55a5c2e926a7142
              name: 'Operations: Delete throughput'
              type: DEPENDENT
              key: 'aws.rds.delete_throughput.rate[{#SINGLETON}]'
              value_type: FLOAT
              units: Rps
              description: 'The average number of delete queries per second.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "DeleteThroughput")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: operations
                - tag: engine
                  value: aurora-mysql
            - uuid: 0ff7f102065a450cb77030c5f2e9cc76
              name: 'DML: Latency'
              type: DEPENDENT
              key: 'aws.rds.dml_latency[{#SINGLETON}]'
              value_type: FLOAT
              units: ms
              description: 'The amount of latency for inserts, updates, and deletes.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "DMLLatency")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: requests
                - tag: engine
                  value: aurora-mysql
            - uuid: 97ce5f3d119c4381a99ead5effe6af44
              name: 'DML: Throughput'
              type: DEPENDENT
              key: 'aws.rds.dml_throughput.rate[{#SINGLETON}]'
              value_type: FLOAT
              units: rate
              description: 'The average number of inserts, updates, and deletes per second.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "DMLThroughput")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: requests
                - tag: engine
                  value: aurora-mysql
            - uuid: 182efdd016e9473eb4791e5343043b57
              name: 'Operations: Insert latency'
              type: DEPENDENT
              key: 'aws.rds.insert_latency[{#SINGLETON}]'
              value_type: FLOAT
              units: ms
              description: 'The amount of latency for insert queries, in milliseconds.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "InsertLatency")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: operations
                - tag: engine
                  value: aurora-mysql
            - uuid: db20ce55abbf4f248b8ac40a6f5576ec
              name: 'Operations: Insert throughput'
              type: DEPENDENT
              key: 'aws.rds.insert_throughput.rate[{#SINGLETON}]'
              value_type: FLOAT
              units: Rps
              description: 'The average number of insert queries per second.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "InsertThroughput")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: operations
                - tag: engine
                  value: aurora-mysql
            - uuid: c68d9d4496a84bf883330b1a82b62171
              name: 'Login failures, rate'
              type: DEPENDENT
              key: 'aws.rds.login_failures.rate[{#SINGLETON}]'
              value_type: FLOAT
              description: 'The average number of failed login attempts per second.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "LoginFailures")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: application
                - tag: engine
                  value: aurora-mysql
            - uuid: c932d4f773c04499b045ddb4b767decb
              name: 'Binary log files, number'
              type: DEPENDENT
              key: 'aws.rds.num_binary_log_files[{#SINGLETON}]'
              value_type: FLOAT
              description: 'The number of binlog files generated.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "NumBinaryLogFiles")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: replication
                - tag: engine
                  value: aurora
                - tag: engine
                  value: mysql
            - uuid: c7a191af58644441bfe9aa8579dd9190
              name: 'Queries, rate'
              type: DEPENDENT
              key: 'aws.rds.queries.rate[{#SINGLETON}]'
              value_type: FLOAT
              description: 'The average number of queries executed per second.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "Queries")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: queries
                - tag: engine
                  value: aurora-mysql
            - uuid: 886f68d6a1eb4953aef3fc4cf1296c62
              name: 'Resultset cache hit ratio'
              type: DEPENDENT
              key: 'aws.rds.result_set_cache_hit_ratio[{#SINGLETON}]'
              value_type: FLOAT
              units: '%'
              description: 'The percentage of requests that are served by the Resultset cache.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ResultSetCacheHitRatio")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: cache
                - tag: engine
                  value: aurora-mysql
            - uuid: 3b66ac67006b4229b1d523dfe19fcb1f
              name: 'Binary log files, size'
              type: DEPENDENT
              key: 'aws.rds.sum_binary_log_files[{#SINGLETON}]'
              value_type: FLOAT
              units: B
              description: 'The total size of the binlog files.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "SumBinaryLogSize")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: replication
                - tag: engine
                  value: aurora
                - tag: engine
                  value: mysql
            - uuid: 44dcd553afe641d1b147426e614a7b41
              name: 'Operations: Update latency'
              type: DEPENDENT
              key: 'aws.rds.update_latency[{#SINGLETON}]'
              value_type: FLOAT
              units: ms
              description: 'The amount of latency for update queries.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "UpdateLatency")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: operations
                - tag: engine
                  value: aurora
                - tag: engine
                  value: mysql
            - uuid: 3a3548d63e1a4aab8853e13645f5898f
              name: 'Operations: Update throughput'
              type: DEPENDENT
              key: 'aws.rds.update_throughput.rate[{#SINGLETON}]'
              value_type: FLOAT
              units: Rps
              description: 'The average number of update queries per second.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "UpdateThroughput")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.rds.get_metrics
              tags:
                - tag: component
                  value: operations
                - tag: engine
                  value: aurora
                - tag: engine
                  value: mysql
          graph_prototypes:
            - uuid: 981fd77559f247908b58ffcf883ade78
              name: 'AWS RDS: [{#SINGLETON}]DML/DDL Latency'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'AWS RDS instance by HTTP'
                    key: 'aws.rds.ddl_latency[{#SINGLETON}]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'AWS RDS instance by HTTP'
                    key: 'aws.rds.dml_latency[{#SINGLETON}]'
            - uuid: 7277bbc0b7c0427697348c8a182b954f
              name: 'AWS RDS: [{#SINGLETON}]DML/DDL Throughput'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'AWS RDS instance by HTTP'
                    key: 'aws.rds.ddl_throughput.rate[{#SINGLETON}]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'AWS RDS instance by HTTP'
                    key: 'aws.rds.dml_throughput.rate[{#SINGLETON}]'
            - uuid: 13a9823d2a2444b7867859aacca47022
              name: 'AWS RDS: [{#SINGLETON}]Operations Latency (insert/delete/update)'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'AWS RDS instance by HTTP'
                    key: 'aws.rds.insert_latency[{#SINGLETON}]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'AWS RDS instance by HTTP'
                    key: 'aws.rds.delete_latency[{#SINGLETON}]'
                - sortorder: '2'
                  color: 00611C
                  item:
                    host: 'AWS RDS instance by HTTP'
                    key: 'aws.rds.update_latency[{#SINGLETON}]'
            - uuid: 72117fc5b5434711ab15f07f117b22bd
              name: 'AWS RDS: [{#SINGLETON}]Operations Throughput(insert/delete/update)'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'AWS RDS instance by HTTP'
                    key: 'aws.rds.insert_throughput.rate[{#SINGLETON}]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'AWS RDS instance by HTTP'
                    key: 'aws.rds.delete_throughput.rate[{#SINGLETON}]'
                - sortorder: '2'
                  color: 00611C
                  item:
                    host: 'AWS RDS instance by HTTP'
                    key: 'aws.rds.update_throughput.rate[{#SINGLETON}]'
          master_item:
            key: aws.rds.engine
          preprocessing:
            - type: JAVASCRIPT
              parameters:
                - 'return JSON.stringify((value === ''aurora-mysql'' || value === ''aurora'') ? [{ ''{#SINGLETON}'': '''' }] : []);'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 6h
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: automation
        - tag: subclass
          value: management
        - tag: target
          value: aws
        - tag: target
          value: rds
      macros:
        - macro: '{$AWS.ACCESS.KEY.ID}'
          description: 'Access key ID.'
          config:
            type: TEXT
            priority: '3'
            label: 'Access key ID'
            description: 'Access keys are long-term credentials for an IAM user.'
        - macro: '{$AWS.ASSUME.ROLE.ARN}'
          description: 'ARN assume role; add when using the `assume_role` authorization method.'
          config:
            type: TEXT
            priority: '5'
            label: 'ARN assume role'
            description: 'The ARN of the role to assume when using the assume_role authorization method.'
        - macro: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
          value: 'false'
          description: 'Add when using the `assume_role` through instance metadata or environment authorization method. Possible values: `false`, `true`.'
          config:
            type: LIST
            priority: '2'
            label: 'Assume Role Metadata Authorization'
            description: 'Chose `True` when use instance metadata service to retrieve role credentials.'
            options:
              - value: 'false'
                text: 'False'
              - value: 'true'
                text: 'True'
        - macro: '{$AWS.AUTH_TYPE}'
          value: access_key
          description: 'Authorization method. Possible values: `access_key`, `assume_role`, `role_base`.'
          config:
            type: LIST
            priority: '1'
            label: 'Authorization method'
            description: 'Authorization method used to access AWS.'
            required: 'YES'
            options:
              - value: access_key
                text: 'Access key'
              - value: assume_role
                text: AssumeRole
              - value: role_base
                text: 'Role-based access'
        - macro: '{$AWS.EBS.BYTE.CREDIT.BALANCE.MIN.WARN}'
          value: '20'
          description: 'Minimum percentage of Byte credits remaining for trigger expression.'
          config:
            type: TEXT
            priority: '21'
            section_name: Thresholds
            label: 'Minimum Byte Credit Balance Warning'
            description: 'The minimum percentage of Byte credits remaining for the warning trigger.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.EBS.IO.CREDIT.BALANCE.MIN.WARN}'
          value: '20'
          description: 'Minimum percentage of I/O credits remaining for trigger expression.'
          config:
            type: TEXT
            priority: '20'
            section_name: Thresholds
            label: 'Minimum I/O Credit Balance Warning'
            description: 'The minimum percentage of I/O credits remaining for the warning trigger.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.PROXY}'
          description: 'Sets HTTP proxy value. If this macro is empty then no proxy is used.'
          config:
            type: TEXT
            priority: '8'
            section_name: Other
            label: 'HTTP Proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AWS.RDS.BURST.CREDIT.BALANCE.MIN.WARN}'
          value: '20'
          description: 'Minimum percentage of Byte credits remaining for trigger expression.'
          config:
            type: TEXT
            priority: '22'
            section_name: Thresholds
            label: 'Minimum Burst Credit Balance Warning'
            description: 'The minimum percentage of Burst credits remaining for the warning trigger.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.RDS.CPU.CREDIT.BALANCE.MIN.WARN}'
          value: '50'
          description: 'Minimum number of free earned CPU credits for trigger expression.'
          config:
            type: TEXT
            priority: '19'
            section_name: Thresholds
            label: 'Minimum CPU Credit Balance Warning'
            description: 'The minimum number of free earned CPU credits for the warning trigger.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.RDS.CPU.UTIL.WARN.MAX}'
          value: '85'
          description: 'The warning threshold of the CPU utilization expressed in %.'
          config:
            type: TEXT
            priority: '18'
            section_name: Thresholds
            label: 'CPU Utilization Warning Threshold'
            description: 'The warning threshold for CPU utilization in percentage. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.RDS.INSTANCE.ID}'
          description: 'RDS DB Instance identifier.'
          config:
            type: TEXT
            priority: '9'
            label: 'RDS Instance ID'
            description: 'The identifier of the RDS DB instance to monitor.'
        - macro: '{$AWS.RDS.LLD.FILTER.ALARM_NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable alarms by name.'
          config:
            type: TEXT
            priority: '12'
            section_name: Filters
            label: 'Alarm Name Filter (Matches)'
            description: 'A regex to filter discoverable alarms by name.'
        - macro: '{$AWS.RDS.LLD.FILTER.ALARM_NAME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered alarms by name.'
          config:
            type: TEXT
            priority: '13'
            section_name: Filters
            label: 'Alarm Name Filter (Not Matches)'
            description: 'A regex to exclude discovered alarms by name.'
        - macro: '{$AWS.RDS.LLD.FILTER.ALARM_SERVICE_NAMESPACE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable alarms by namespace.'
          config:
            type: TEXT
            priority: '10'
            section_name: Filters
            label: 'Alarm Namespace Filter (Matches)'
            description: 'A regex to filter discoverable alarms by namespace.'
        - macro: '{$AWS.RDS.LLD.FILTER.ALARM_SERVICE_NAMESPACE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered alarms by namespace.'
          config:
            type: TEXT
            priority: '11'
            section_name: Filters
            label: 'Alarm Namespace Filter (Not Matches)'
            description: 'A regex to exclude discovered alarms by namespace.'
        - macro: '{$AWS.RDS.LLD.FILTER.EVENT_CATEGORY.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable events by category.'
          config:
            type: TEXT
            priority: '14'
            section_name: Filters
            label: 'Event Category Filter (Matches)'
            description: 'A regex to filter discoverable events by category.'
        - macro: '{$AWS.RDS.LLD.FILTER.EVENT_CATEGORY.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered events by category.'
          config:
            type: TEXT
            priority: '15'
            section_name: Filters
            label: 'Event Category Filter (Not Matches)'
            description: 'A regex to exclude discovered events by category.'
        - macro: '{$AWS.RDS.LLD.FILTER.EVENT_SOURCE_TYPE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable events by source type.'
          config:
            type: TEXT
            priority: '16'
            section_name: Filters
            label: 'Event Source Type Filter (Matches)'
            description: 'A regex to filter discoverable events by source type.'
        - macro: '{$AWS.RDS.LLD.FILTER.EVENT_SOURCE_TYPE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered events by source type.'
          config:
            type: TEXT
            priority: '17'
            section_name: Filters
            label: 'Event Source Type Filter (Not Matches)'
            description: 'A regex to exclude discovered events by source type.'
        - macro: '{$AWS.REGION}'
          value: us-west-1
          description: 'Amazon RDS Region code.'
          config:
            type: TEXT
            priority: '6'
            label: 'AWS Region'
            description: 'The AWS region where your RDS instance is located.'
        - macro: '{$AWS.SECRET.ACCESS.KEY}'
          type: SECRET_TEXT
          description: 'Secret access key.'
          config:
            type: TEXT
            priority: '4'
            label: 'Secret access key'
            description: 'Secret access key can be retrieved only at the time you create it.'
        - macro: '{$AWS.STS.REGION}'
          value: us-east-1
          description: 'Region used in assume role request.'
          config:
            type: TEXT
            priority: '7'
            label: 'STS Region'
            description: 'The AWS region for the assume role request.'
      valuemaps:
        - uuid: 4ff4cda021a4464ebbebb42b7ee02673
          name: 'Alarm state'
          mappings:
            - value: '0'
              newvalue: OK
            - value: '1'
              newvalue: 'Insufficient data'
            - value: '2'
              newvalue: Alarm
            - value: '255'
              newvalue: Unknown
        - uuid: 69bbb2cfded14be6ac596408bdd4de37
          name: 'Read replica state'
          mappings:
            - value: '0'
              newvalue: Error
            - value: '1'
              newvalue: Normal
    - uuid: a14ab6b4e80643fe8daa9d7288658f79
      template: 'AWS S3 bucket by HTTP'
      name: 'AWS S3 bucket by HTTP'
      description: |
        The template gets AWS S3 bucket 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"
      wizard_ready: 'YES'
      readme: |
        ## Overview
        
        The template to monitor AWS S3 bucket by HTTP via Zabbix that works without any external scripts.
        Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
        
        **Note:** This template uses the GetMetricData CloudWatch API calls to list and retrieve metrics.
        For more information, please refer to the [CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) page.
        
        Additional information about metrics and used API methods:
        
        * [Full metrics list related to S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/metrics-dimensions.html)
        * [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
        
        ## Setup
        
        The template gets AWS S3 metrics and uses the script item to make HTTP requests to the CloudWatch API.
        Before using the template, you need to create an IAM policy for the Zabbix role in your AWS account with the necessary permissions.
        
        ### Required Permissions
        Add the following required permissions to your Zabbix IAM policy in order to collect Amazon S3 metrics.
        
        ```json
        {
            "Version":"2012-10-17",
            "Statement":[
                {
                  "Action":[
                      "cloudwatch:DescribeAlarms",
                      "cloudwatch:GetMetricData",
                      "s3:GetMetricsConfiguration"
                  ],
                  "Effect":"Allow",
                  "Resource":"*"
                }
            ]
          }
        ```
        
        ### Access Key Authorization
        
        If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
        
        1. Create an IAM user with programmatic access.
        2. Attach the required policy to the IAM user.
        3. Generate an access key and secret key.
        4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
        
        ### Assume role authorization
        For using assume role authorization, add the appropriate permissions to the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "sts:AssumeRole",
                    "Resource": "arn:aws:iam::{Account}:user/{UserName}"
                },
                {
                    "Effect": "Allow",
                    "Action": [
                        "cloudwatch:DescribeAlarms",
                        "cloudwatch:GetMetricData",
                        "s3:GetMetricsConfiguration"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        
        #### Trust Relationships for Assume Role Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "AWS": "arn:aws:iam::{Account}:user/{UserName}"
              },
              "Action": "sts:AssumeRole"
            }
          ]
        }
        ```
        Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
        
        ### Role-Based Authorization
        If you are using role-based authorization, set the appropriate permissions:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "iam:PassRole",
                    "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
                },
                {
                    "Sid": "VisualEditor1",
                    "Effect": "Allow",
                    "Action": [
                        "cloudwatch:DescribeAlarms",
                        "cloudwatch:GetMetricData",
                        "s3:GetMetricsConfiguration",
                        "ec2:AssociateIamInstanceProfile",
                        "ec2:ReplaceIamInstanceProfileAssociation"
                    ],
                    "Resource": "*"
                }
            ]
        }
        ```
        
        #### Trust Relationships for Role-Based Authorization
        Next, add a principal to the trust relationships of the role you are using:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": [
                            "ec2.amazonaws.com"
                        ]
                    },
                    "Action": [
                        "sts:AssumeRole"
                    ]
                }
            ]
        }
        ```
        
        **Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
        
        To gather Request metrics, [enable Requests metrics](https://docs.aws.amazon.com/AmazonS3/latest/userguide/cloudwatch-monitoring.html) on your Amazon S3 buckets from the AWS console.
        
        You can also define a filter for the Request metrics using a shared prefix, object tag, or access point.
        
        Set the following fields: `Authorization method`, `S3 bucket name`.
        
        For more information about managing access keys, see [official documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).
      vendor:
        name: Zabbix
        version: 8.0-3
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 7ca108eafb0d4b65a304815ee637174e
          name: 'Get alarms check'
          type: DEPENDENT
          key: aws.s3.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.s3.get_alarms
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: a8f8a7518aad4e32b23a8611afc8f48c
              expression: 'length(last(/AWS S3 bucket by HTTP/aws.s3.alarms.check))>0'
              name: 'AWS S3: Failed to get alarms data'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Failed to get CloudWatch alarms for S3 bucket.'
              tags:
                - tag: scope
                  value: availability
        - uuid: fceb9927715443059269fa4589f90f67
          name: 'Bucket Size'
          type: DEPENDENT
          key: aws.s3.bucket_size_bytes
          value_type: FLOAT
          units: B
          description: |
            This is a daily metric for the bucket.
            The amount of data in bytes stored in a bucket in the STANDARD storage class, INTELLIGENT_TIERING storage class, Standard-Infrequent Access (STANDARD_IA) storage class, OneZone-Infrequent Access (ONEZONE_IA), Reduced Redundancy Storage (RRS) class, S3 Glacier Instant Retrieval storage class, Deep Archive Storage (S3 Glacier Deep Archive) class, or S3 Glacier Flexible Retrieval (GLACIER) storage class.
            This value is calculated by summing the size of all objects and metadata in the bucket (both current and noncurrent objects), including the size of all parts for all incomplete multipart uploads to the bucket.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.metrics[?(@.Label == "StandardStorage BucketSizeBytes")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.s3.get_metrics
          tags:
            - tag: component
              value: storage
        - uuid: 6da0ea7130e64a7fb8ae32ee02290cbf
          name: 'Get alarms data'
          type: SCRIPT
          key: aws.s3.get_alarms
          delay: 0s;m/1
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	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;
            	},
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('alarms', 'GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload)), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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];
            				});
            		}
            		['bucket_name', 'request_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];
            		});
            	},
            
            	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 (get, 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/, '');
            		if (get === 'alarms') {
            			host = service + '.' + region + '.amazonaws.com';
            		} else {
            			host = AWS.params.bucket_name + '.' + service + '.' + region + '.amazonaws.com';
            		}
            		if (AWS.params.auth_type === 'role_base' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			token = AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken;
            			var canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n' + 'x-amz-security-token:' + token + '\n',
            				signed_headers = 'content-encoding;host;x-amz-date;x-amz-security-token';
            		}
            		else {
            			var canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n',
            				signed_headers = 'content-encoding;host;x-amz-date';
            		}
            		if (get === 'location') {
            			canonical_uri = '/' + AWS.params.bucket_name;
            		} else {
            			canonical_uri = '/';
            		}
            		var 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'),
            			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('x-amz-content-sha256:' + sha256(data));
            		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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + token);
            		}
            
            		Zabbix.log(4, '[ AWS S3 ] Sending request: ' + url);
            		response = request.get(url);
            		Zabbix.log(4, '[ AWS S3 ] 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) {
            			try {
            				response = JSON.parse(XML.toJson(response));
            			}
            			catch (error) {
            				throw 'Failed to parse response received from AWS CloudWatch API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	getBucketLocation: function () {
            		var payload = {};
            		payload['location'] = '';
            
            		result = AWS.request('location', 'GET', AWS.params.request_region, 's3', AWS.prepareParams(payload));
            
            		if (typeof result !== 'object'
            			|| result.hasOwnProperty('LocationConstraint') === false
            		) {
            			throw 'Cannot get buckets region location data from AWS S3 API. Check debug log for more information.';
            		}
            
            		return result.LocationConstraint !== null ? result.LocationConstraint : 'us-east-1';
            	},
            
            	getAlarms: function (region) {
            		var payload = {
            			'Action': 'DescribeAlarms',
            			'Version': '2010-08-01',
            			'MaxRecords': 100
            		},
            			result = [];
            
            		while (payload.NextToken !== '') {
            			var alarms = AWS.getField(AWS.request('alarms', 'GET', 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;
            
            				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 === 'BucketName' && dimensions[i].Value === AWS.params.bucket_name) {
            						result.push(alarm);
            						break;
            					}
            				}
            			});
            		}
            
            		return result;
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            	var region = AWS.getBucketLocation();
            	return JSON.stringify(AWS.getAlarms(region));
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS S3 ] 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: bucket_name
              value: '{$AWS.S3.BUCKET.NAME}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: request_region
              value: '{$AWS.REQUEST.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: 598e9dc563334ad6b1d72245a6f8679f
          name: 'Get metrics data'
          type: SCRIPT
          key: aws.s3.get_metrics
          delay: 0s;h/8
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	request_period: 2 * 86400,
            	metadata: 'http://169.254.169.254/latest/',
            
            	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;
            	},
            
            
            	getRoleBaseCredentials: function () {
            		AWS.params['auth_type'] = 'role_base';
            		var request = new HttpRequest();
            		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            			request.setProxy(AWS.params.proxy);
            		}
            		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
            		var token = request.put(AWS.metadata + 'api/token');
            
            		if (request.getStatus() !== 200 || token === null || token === '') {
            			throw 'Error getting IMDSv2 session token.';
            		}
            		request.addHeader('X-aws-ec2-metadata-token: ' + token);
            		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
            
            		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
            			throw 'Error getting security credentials from instance metadata. Role not found.';
            		}
            
            		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
            			};
            			AWS.params[field] = credentials[field];
            		});
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.getRoleBaseCredentials();
            				break;
            			case 'assume_role':
            				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
            					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
            				}
            				if (params.metadata_auth === 'true') {
            					AWS.getRoleBaseCredentials();
            					AWS.params['SessionToken'] = AWS.params['Token'];
            					AWS.params['auth_type'] = 'assume_role_metadata';
            
            					['sts_region', 'role_arn'].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];
            					});
            				}
            
            				if (params.metadata_auth === 'false') {
            					AWS.params['auth_type'] = 'assume_role';
            
            					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
            					});
            				}
            
            				const role_arn_regex = /role\/(.+)$/;
            				const match = AWS.params.role_arn.match(role_arn_regex);
            				if (!match) {
            					throw 'Invalid role ARN format.';
            				}
            
            				const payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': match[1] + 'Session',
            				};
            
            				credentials = AWS.getField(AWS.request('credentials', 'GET', AWS.params.sts_region, 'sts', AWS.prepareParams(payload)), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
            
            				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
            					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
            						throw 'Required credentials are not set: "' + field + '".';
            					};
            					AWS.params[field] = credentials[field];
            				});
            				break;
            			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];
            				});
            		}
            		['bucket_name', 'request_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];
            		});
            	},
            
            	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;
            	},
            
            	renderMetricQuery: function (period, bucket_name) {
            		var metrics_list = [
            			'BucketSizeBytes:Bytes:Average:StandardStorage',
            			'NumberOfObjects:Count:Average:AllStorageTypes',
            		];
            
            		var metric_payload = [];
            		metrics_list.forEach(function (metric, index) {
            			var parts = metric.split(':', 4);
            			metric_payload.push({
            				'Id': 'm' + index,
            				'MetricStat': {
            					'Metric': {
            						'MetricName': parts[0],
            						'Namespace': 'AWS/S3',
            						'Dimensions': [
            							{
            								'Name': 'BucketName',
            								'Value': bucket_name
            							},
            							{
            								'Name': 'StorageType',
            								'Value': parts[3]
            							}
            						]
            					},
            					'Period': period,
            					'Stat': parts[2],
            					'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 (get, method, region, service, params, data) {
            		if (typeof data === 'undefined' || data === null) {
            			data = '';
            		}
            		else {
            			data = JSON.stringify(data)
            		}
            		var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''),
            			date = amzdate.replace(/T\d+Z/, '');
            
            		if (get === 'metrics' || get === 'credentials') {
            			host = service + '.' + region + '.amazonaws.com';
            		} else {
            			host = AWS.params.bucket_name + '.' + service + '.' + region + '.amazonaws.com';
            		}
            		if (AWS.params.auth_type === 'role_base' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			token = AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken;
            			var canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n' + 'x-amz-security-token:' + token + '\n',
            				signed_headers = 'content-encoding;host;x-amz-date;x-amz-security-token';
            		}
            		else {
            			var canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n',
            				signed_headers = 'content-encoding;host;x-amz-date';
            		}
            
            		var canonical_uri = '/';
            
            		switch (get) {
            			case 'location':
            				canonical_uri = '/' + AWS.params.bucket_name;
            				canonical_request = method + '\n' + canonical_uri + '\n' + params + '\n' + canonical_headers + '\n' + signed_headers + '\n' + sha256(data);
            				break;
            			case 'metrics':
            				canonical_request = method + '\n' + canonical_uri + '\n' + '\n' + canonical_headers + '\n' + signed_headers + '\n' + sha256(data);
            				break;
            			case 'filter_id':
            			case 'credentials':
            				canonical_request = method + '\n' + canonical_uri + '\n' + params + '\n' + canonical_headers + '\n' + signed_headers + '\n' + sha256(data);
            				break;
            			default:
            				throw 'Error: Invalid option "get" for request function';
            		}
            
            		var 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'),
            			request = new HttpRequest();
            
            		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/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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
            			request.addHeader('X-Amz-Security-Token: ' + token);
            		}
            
            		switch (get) {
            			case 'location':
            			case 'filter_id':
            			case 'credentials':
            				url = 'https://' + host + canonical_uri + '?' + params;
            				Zabbix.log(4, '[ AWS S3 ] Sending request: ' + url);
            				response = request.get(url);
            				Zabbix.log(4, '[ AWS S3 ] Received response with status code ' + request.getStatus() + ': ' + response);
            				if (request.getStatus() !== 200) {
            					throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            				}
            				break;
            
            			case 'metrics':
            				url = 'https://' + host + '/';
            				Zabbix.log(4, '[ AWS S3 ] Sending request: ' + url);
            				request.addHeader('X-Amz-Target: GraniteServiceVersion20100801.GetMetricData');
            				response = request.post(url, data);
            				Zabbix.log(4, '[ AWS S3 ] Received response with status code ' + request.getStatus() + ': ' + response);
            				if (request.getStatus() !== 200) {
            					throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            				}
            				break;
            
            			default:
            				throw 'Error: Invalid option "get" for request function';
            		}
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			try {
            				response = JSON.parse(XML.toJson(response));
            			}
            			catch (error) {
            				throw 'Failed to parse response received from AWS CloudWatch API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	getBucketLocation: function (bucket_name) {
            		var payload = {};
            		payload['location'] = '';
            
            		result = AWS.request('location', 'GET', AWS.params.request_region, 's3', AWS.prepareParams(payload), '', bucket_name);
            
            		if (typeof result !== 'object'
            			|| result.hasOwnProperty('LocationConstraint') === false
            		) {
            			throw 'Cannot get buckets region location data from AWS S3 API. Check debug log for more information.';
            		}
            
            		return result.LocationConstraint !== null ? result.LocationConstraint : 'us-east-1';
            	},
            
            	getBucketFilterId: function (region) {
            		var payload = {};
            		payload['metrics'] = '';
            
            		data = AWS.getField(AWS.request('filter_id', 'GET', region, 's3', AWS.prepareParams(payload), ''), 'ListMetricsConfigurationsResult');
            
            		if (typeof data === 'object' && data.hasOwnProperty('MetricsConfiguration') === true) {
            			if (!Array.isArray(data.MetricsConfiguration))
            				data.MetricsConfiguration = [data.MetricsConfiguration]
            			data.MetricsConfiguration.forEach(function (item) {
            				item.region = region;
            			});
            		} else { data.MetricsConfiguration = ['To view request metrics, create a filter'] }
            		return data.MetricsConfiguration;
            
            	},
            
            	getMetricsData: function (region) {
            		var payload = {},
            			end_time = Math.floor((new Date().getTime()) / 1000),
            			start_time = end_time - AWS.request_period;
            		payload['StartTime'] = start_time;
            		payload['EndTime'] = end_time;
            		payload['ScanBy'] = 'TimestampDescending';
            		payload['MetricDataQueries'] = AWS.renderMetricQuery(43200, AWS.params.bucket_name);
            
            		return AWS.getField(AWS.request('metrics', 'POST', region, 'monitoring', '', payload), 'MetricDataResults');
            	}
            
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            	var region = AWS.getBucketLocation(AWS.params.bucket_name),
            		metrics = AWS.getMetricsData(region),
            		filter_id = AWS.getBucketFilterId(region);
            	return JSON.stringify({ metrics, filter_id });
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS S3 ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: |
            Get bucket metrics.
            Full metrics list related to S3: https://docs.aws.amazon.com/AmazonS3/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: bucket_name
              value: '{$AWS.S3.BUCKET.NAME}'
            - name: metadata_auth
              value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: request_region
              value: '{$AWS.REQUEST.REGION}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          tags:
            - tag: component
              value: raw
        - uuid: 0e22c196ae834d2899068f25316ffed2
          name: 'Get metrics check'
          type: DEPENDENT
          key: aws.s3.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.s3.get_metrics
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: a8a0b4187f5f4e22b868dd038f53a2ba
              expression: 'length(last(/AWS S3 bucket by HTTP/aws.s3.metrics.check))>0'
              name: 'AWS S3: Failed to get metrics data'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Failed to get CloudWatch metrics for S3 bucket.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 75b467e2079c41c5b3e8f79df8c5a9ba
          name: 'Number of objects'
          type: DEPENDENT
          key: aws.s3.number_of_objects
          value_type: FLOAT
          description: |
            This is a daily metric for the bucket.
            The total number of objects stored in a bucket for all storage classes.
            This value is calculated by counting all objects in the bucket (both current and noncurrent objects) and the total number of parts for all incomplete multipart uploads to the bucket.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.metrics.[?(@.Label == "AllStorageTypes NumberOfObjects")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.s3.get_metrics
          tags:
            - tag: component
              value: storage
      discovery_rules:
        - uuid: 26c424a60a7a4975996ccc44601c4ee3
          name: 'Bucket Alarms discovery'
          type: DEPENDENT
          key: aws.s3.alarms.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.S3.LLD.FILTER.ALARM_NAME.MATCHES}'
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.S3.LLD.FILTER.ALARM_NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery of bucket alarms.'
          item_prototypes:
            - uuid: b38bd6e4566445acb52e8ecce4014f0f
              name: '[{#ALARM_NAME}]: State'
              type: DEPENDENT
              key: 'aws.s3.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:
                    - '$.[?(@.AlarmName == "{#ALARM_NAME}")].StateValue.first()'
                  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.s3.get_alarms
              tags:
                - tag: component
                  value: alarms
              trigger_prototypes:
                - uuid: 7f0ba96047784510b734c0064d434edc
                  expression: 'last(/AWS S3 bucket by HTTP/aws.s3.alarm.state["{#ALARM_NAME}"])=1'
                  name: 'AWS S3: [{#ALARM_NAME}] has ''Insufficient data'' state'
                  priority: INFO
                  description: 'Either the alarm has just started, the metric is not available, or not enough data is available for the metric to determine the alarm state.'
                  tags:
                    - tag: scope
                      value: notice
            - uuid: 7e536a43faf742058d303ffe21cd9a8c
              name: '[{#ALARM_NAME}]: State reason'
              type: DEPENDENT
              key: 'aws.s3.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:
                    - '$.[?(@.AlarmName == "{#ALARM_NAME}")].StateReason.first()'
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: aws.s3.get_alarms
              tags:
                - tag: component
                  value: alarms
          trigger_prototypes:
            - uuid: c1b94199b7ac4cc9889ff0e724f7057d
              expression: 'last(/AWS S3 bucket by HTTP/aws.s3.alarm.state["{#ALARM_NAME}"])=2 and length(last(/AWS S3 bucket by HTTP/aws.s3.alarm.state_reason["{#ALARM_NAME}"]))>0'
              name: 'AWS S3: [{#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.s3.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
                    });
                  });
                  
                  return JSON.stringify(result);
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
        - uuid: 9ff609d143ae4552b395668718c43191
          name: 'Request Metrics discovery'
          type: DEPENDENT
          key: aws.s3.configuration.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.S3.FILTER.ID.NAME}'
                value: '{$AWS.S3.LLD.FILTER.ID.NAME.MATCHES}'
              - macro: '{#AWS.S3.FILTER.ID.NAME}'
                value: '{$AWS.S3.LLD.FILTER.ID.NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery of request metrics.'
          item_prototypes:
            - uuid: 7c746594159f4f1c94e8790ed1bdf2af
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Requests: Errors, 4xx'
              type: DEPENDENT
              key: 'aws.s3.4xx_errors["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              description: |
                The number of HTTP 4xx client error status code requests made to an Amazon S3 bucket with a value of either 0 or 1.
                The average statistic shows the error rate, and the sum statistic shows the count of that type of error, during each period.
                Statistic: Average (reports per request).
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "4xxErrors")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: errors
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: 806de74ed57b4797b294ebe8fa509429
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Requests: Errors, 5xx'
              type: DEPENDENT
              key: 'aws.s3.5xx_errors["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              description: |
                The number of HTTP 5xx server error status code requests made to an Amazon S3 bucket with a value of either 0 or 1.
                The average statistic shows the error rate, and the sum statistic shows the count of that type of error, during each period.
                Statistic: Average (reports per request).
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "5xxErrors")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: errors
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: 7530d7ebe61942f4abc29a8ccb3b5516
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Requests: All'
              type: DEPENDENT
              key: 'aws.s3.all_requests["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              description: |
                The total number of HTTP requests made to an Amazon S3 bucket, regardless of type.
                If you're using a metrics configuration with a filter, then this metric only returns the HTTP requests that meet the filter's requirements.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "AllRequests")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: requests
            - uuid: 8758c16faef9477d8e3ff41426c2761b
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Requests: Bytes downloaded'
              type: DEPENDENT
              key: 'aws.s3.bytes_downloaded["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              units: B
              description: |
                The number of bytes downloaded for requests made to an Amazon S3 bucket, where the response includes a body.
                Statistic: Average (bytes per request).
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "BytesDownloaded")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: 3f5141a7448b43d288a37dfe41a52288
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Replication: Bytes pending'
              type: DEPENDENT
              key: 'aws.s3.bytes_pending_replication["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              units: B
              description: 'The total number of bytes of objects pending replication for a given replication rule.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "BytesPendingReplication")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: replication
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: 99eefab6b9be405ead0e6ea57394a7e3
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Requests: Bytes uploaded'
              type: DEPENDENT
              key: 'aws.s3.bytes_uploaded["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              units: B
              description: |
                The number of bytes uploaded that contain a request body, made to an Amazon S3 bucket.
                Statistic: Average (bytes per request).
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "BytesUploaded")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: d9deb58254be4add996d3dec97344132
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Requests: Delete'
              type: DEPENDENT
              key: 'aws.s3.delete_requests["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              description: |
                The number of HTTP DELETE requests made for objects in an Amazon S3 bucket.
                This also includes Delete Multiple Objects requests. This metric shows the number of requests, not the number of objects deleted.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "DeleteRequests")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: d8c8e91f383747e5b6e73f922f5b3278
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: First byte latency, avg'
              type: DEPENDENT
              key: 'aws.s3.first_byte_latency.avg["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              units: ms
              description: |
                The per-request time from the complete request being received by an Amazon S3 bucket to when the response starts to be returned.
                Statistic: Average.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "FirstByteLatency")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: latency
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: 55cb2316171e43a0aa94e0d203832577
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: First byte latency, p90'
              type: DEPENDENT
              key: 'aws.s3.first_byte_latency.p90["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              units: ms
              description: |
                The per-request time from the complete request being received by an Amazon S3 bucket to when the response starts to be returned.
                Statistic: 90th percentile.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "FirstByteLatency")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: latency
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: eabbd51547cb4a0484182d42601728c3
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Get request metrics'
              type: SCRIPT
              key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              delay: '{$AWS.S3.UPDATE.INTERVAL}'
              history: '0'
              value_type: TEXT
              params: |
                var AWS = {
                	params: {},
                	metadata: 'http://169.254.169.254/latest/',
                
                	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;
                	},
                
                	isFloat: function (n) {
                		n = parseFloat(n);
                		return Number(n) === n && n % 1 !== 0;
                	},
                
                	checkNumber: function checkNumber(string) {
                		if (typeof string !== "string" || isNaN(string) || AWS.isFloat(string)) {
                			throw 'Incorrect "timespan" parameter given: ' + string + ' Must be an unsigned number';
                		}
                		return string;
                	},
                
                	getRoleBaseCredentials: function () {
                		AWS.params['auth_type'] = 'role_base';
                		var request = new HttpRequest();
                		if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
                			request.setProxy(AWS.params.proxy);
                		}
                		request.addHeader('X-aws-ec2-metadata-token-ttl-seconds: 21600');
                		var token = request.put(AWS.metadata + 'api/token');
                
                		if (request.getStatus() !== 200 || token === null || token === '') {
                			throw 'Error getting IMDSv2 session token.';
                		}
                		request.addHeader('X-aws-ec2-metadata-token: ' + token);
                		var IamRoleName = request.get(AWS.metadata + 'meta-data/iam/security-credentials');
                
                		if (request.getStatus() !== 200 || IamRoleName === null || IamRoleName === '') {
                			throw 'Error getting security credentials from instance metadata. Role not found.';
                		}
                
                		credentials = request.get(AWS.metadata + 'meta-data/iam/security-credentials/' + 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 are not set: "' + field + '".';
                			};
                			AWS.params[field] = credentials[field];
                		});
                	},
                
                	setParams: function (params) {
                		AWS.params['proxy'] = params.proxy;
                		switch (AWS.getField(params, 'auth_type')) {
                			case 'role_base':
                				AWS.getRoleBaseCredentials();
                				break;
                			case 'assume_role':
                				if (typeof params.metadata_auth === 'undefined' || params.metadata_auth === '' || (params.metadata_auth !== 'true' && params.metadata_auth !== 'false')) {
                					throw 'Required param metadata_auth for assume_role is not set or has invalid value: "' + params.metadata_auth + '". Expected "true" or "false".';
                				}
                				if (params.metadata_auth === 'true') {
                					AWS.getRoleBaseCredentials();
                					AWS.params['SessionToken'] = AWS.params['Token'];
                					AWS.params['auth_type'] = 'assume_role_metadata';
                
                					['sts_region', 'role_arn'].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];
                					});
                				}
                
                				if (params.metadata_auth === 'false') {
                					AWS.params['auth_type'] = 'assume_role';
                
                					['AccessKeyId', 'SecretAccessKey', 'sts_region', 'role_arn'].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];
                					});
                				}
                
                				const role_arn_regex = /role\/(.+)$/;
                				const match = AWS.params.role_arn.match(role_arn_regex);
                				if (!match) {
                					throw 'Invalid role ARN format.';
                				}
                
                				const payload = {
                					'Action': 'AssumeRole',
                					'Version': '2011-06-15',
                					'RoleArn': AWS.params.role_arn,
                					'RoleSessionName': match[1] + 'Session',
                				};
                
                				credentials = AWS.getField(AWS.request('POST', AWS.params.sts_region, 'sts', AWS.prepareParams(payload), ''), 'AssumeRoleResponse.AssumeRoleResult.Credentials');
                
                				['AccessKeyId', 'SecretAccessKey', 'SessionToken'].forEach(function (field) {
                					if (typeof credentials !== 'object' || typeof credentials[field] === 'undefined' || credentials[field] === '') {
                						throw 'Required credentials are not set: "' + field + '".';
                					};
                					AWS.params[field] = credentials[field];
                				});
                				break;
                			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', 'bucket_name', 'filter_id'].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];
                		});
                
                		updateInterval = AWS.checkNumber('{$AWS.S3.UPDATE.INTERVAL}');
                
                		if (updateInterval > 86400 || updateInterval < 1) {
                			throw 'Incorrect "update interval" parameter given: ' + updateInterval + ' Must be between 1 and 86400 seconds.';
                		}
                	},
                
                	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;
                	},
                
                	renderMetricQuery: function (period, bucket_name, filter_id) {
                		var metrics_list = [
                			'AllRequests:Count:Sum',
                			'GetRequests:Count:Sum',
                			'PutRequests:Count:Sum',
                			'DeleteRequests:Count:Sum',
                			'HeadRequests:Count:Sum',
                			'PostRequests:Count:Sum',
                			'SelectRequests:Count:Sum',
                			'SelectBytesScanned:Bytes:Average',
                			'SelectBytesReturned:Bytes:Average',
                			'ListRequests:Count:Sum',
                			'BytesDownloaded:Bytes:Average',
                			'BytesUploaded:Bytes:Average',
                			'4xxErrors:Count:Average',
                			'5xxErrors:Count:Average',
                			'TotalRequestLatency:Milliseconds:p90',
                			'FirstByteLatency:Milliseconds:p90',
                			'ReplicationLatency:Seconds:Average',
                			'BytesPendingReplication:Bytes:Average',
                			'OperationsPendingReplication:Count:Average',
                
                		];
                
                		var metric_payload = [];
                		metrics_list.forEach(function (metric, index) {
                			var parts = metric.split(':', 3);
                			metric_payload.push({
                				'Id': 'm' + index,
                				'MetricStat': {
                					'Metric': {
                						'MetricName': parts[0],
                						'Namespace': 'AWS/S3',
                						'Dimensions': [
                							{
                								'Name': 'BucketName',
                								'Value': bucket_name
                							},
                							{
                								'Name': 'FilterId',
                								'Value': filter_id
                							}
                						]
                					},
                					'Period': period,
                					'Stat': parts[2],
                					'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 = '';
                		}
                		else {
                			data = JSON.stringify(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 = '/';
                
                		if (AWS.params.auth_type === 'role_base' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
                			token = AWS.params.auth_type === 'role_base' ? AWS.params.Token : AWS.params.SessionToken;
                			var canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n' + 'x-amz-security-token:' + token + '\n',
                				signed_headers = 'content-encoding;host;x-amz-date;x-amz-security-token';
                		}
                		else {
                			var canonical_headers = 'content-encoding:amz-1.0\n' + 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n',
                				signed_headers = 'content-encoding;host;x-amz-date';
                		}
                
                		var 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'),
                			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-Target: GraniteServiceVersion20100801.GetMetricData')
                		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' || AWS.params.auth_type === 'assume_role_metadata' || (AWS.params.auth_type === 'assume_role' & !params.includes('AssumeRole'))) {
                			request.addHeader('X-Amz-Security-Token: ' + token);
                		}
                
                		Zabbix.log(4, '[ AWS S3 ] Sending request: ' + url);
                		response = request.post(url, data);
                		Zabbix.log(4, '[ AWS S3 ] 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) {
                			try {
                				response = JSON.parse(XML.toJson(response));
                			}
                			catch (error) {
                				throw 'Failed to parse response received from AWS CloudWatch API. Check debug log for more information.';
                			}
                		}
                
                		return response;
                	},
                
                	getMetricsData: function () {
                		var payload = {},
                			end_time = Math.floor((new Date().getTime()) / 1000),
                			start_time = end_time - updateInterval;
                
                		payload['StartTime'] = start_time;
                		payload['EndTime'] = end_time;
                		payload['ScanBy'] = 'TimestampDescending';
                		payload['MetricDataQueries'] = AWS.renderMetricQuery(60, AWS.params.bucket_name, AWS.params.filter_id);
                		result = AWS.request('POST', AWS.params.region, 'monitoring', '', payload);
                		if (typeof result !== 'object' || typeof result.MetricDataResults !== 'object') {
                			throw 'Cannot get metrics data from AWS CloudWatch API. Check debug log for more information.';
                		}
                
                		return result.MetricDataResults;
                	}
                };
                
                try {
                	AWS.setParams(JSON.parse(value));
                
                	return JSON.stringify(AWS.getMetricsData());
                }
                catch (error) {
                	error += (String(error).endsWith('.')) ? '' : '.';
                	Zabbix.log(3, '[ AWS S3 ] ERROR: ' + error);
                
                	return JSON.stringify({ 'error': error });
                }
              description: |
                Get bucket request metrics filter: '{#AWS.S3.FILTER.ID.NAME}'.
                Full metrics list related to S3: https://docs.aws.amazon.com/AmazonS3/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: bucket_name
                  value: '{$AWS.S3.BUCKET.NAME}'
                - name: filter_id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
                - name: metadata_auth
                  value: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
                - name: proxy
                  value: '{$AWS.PROXY}'
                - name: region
                  value: '{#AWS.S3.REGION}'
                - name: role_arn
                  value: '{$AWS.ASSUME.ROLE.ARN}'
                - name: SecretAccessKey
                  value: '{$AWS.SECRET.ACCESS.KEY}'
                - name: sts_region
                  value: '{$AWS.STS.REGION}'
              tags:
                - tag: component
                  value: raw
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: f2cff8aa3c3c4a308296550561b02829
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Requests: Get'
              type: DEPENDENT
              key: 'aws.s3.get_requests["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              description: |
                The number of HTTP GET requests made for objects in an Amazon S3 bucket. This doesn't include list operations.
                Paginated list-oriented requests, like List Multipart Uploads, List Parts, Get Bucket Object versions, and others, are not included in this metric.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "GetRequests")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: 0d9f59f099cb47c8991cc2e353154dc7
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Requests: Head'
              type: DEPENDENT
              key: 'aws.s3.head_requests["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              description: 'The number of HTTP HEAD requests made to an Amazon S3 bucket.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "HeadRequests")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: f9b09dbbf0a44ea9b34a86853a6ebfd0
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Requests: List'
              type: DEPENDENT
              key: 'aws.s3.list_requests["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              description: 'The number of HTTP requests that list the contents of a bucket.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ListRequests")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: ad753554ca7e45629e7eb144a3595228
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Replication: Operations pending'
              type: DEPENDENT
              key: 'aws.s3.operations_pending_replication["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              description: 'The number of operations pending replication for a given replication rule.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "OperationsPendingReplication")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: replication
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: 9bb4416c7c454e5486a7ce4e4b4b90f0
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Requests: Post'
              type: DEPENDENT
              key: 'aws.s3.post_requests["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              description: |
                The number of HTTP POST requests made to an Amazon S3 bucket.
                Delete Multiple Objects and SELECT Object Content requests are not included in this metric.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "PostRequests")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: 88a67025c835410eb54d74be96cf5b4c
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Requests: Put'
              type: DEPENDENT
              key: 'aws.s3.put_requests["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              description: 'The number of HTTP PUT requests made for objects in an Amazon S3 bucket.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "PutRequests")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: ac0f6d6f6f2247379d99fa2f4f0ecc11
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Replication: Latency'
              type: DEPENDENT
              key: 'aws.s3.replication_latency["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              units: s
              description: 'The maximum number of seconds by which the replication destination region is behind the source Region for a given replication rule.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ReplicationLatency")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: replication
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: 23c13e717a2845399068e7c2e627df4f
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Requests: Select, bytes returned'
              type: DEPENDENT
              key: 'aws.s3.select_bytes_returned["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              units: B
              description: |
                The number of bytes of data returned with Amazon S3 SELECT Object Content requests in an Amazon S3 bucket.
                Statistic: Average (bytes per request).
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "SelectBytesReturned")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: 042e84dc68c54390a3d0427b87d89e47
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Requests: Select, bytes scanned'
              type: DEPENDENT
              key: 'aws.s3.select_bytes_scanned["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              units: B
              description: |
                The number of bytes of data scanned with Amazon S3 SELECT Object Content requests in an Amazon S3 bucket.
                Statistic: Average (bytes per request).
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "SelectBytesScanned")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: 616ec102597447cdbe2f21186937dcfe
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Requests: Select'
              type: DEPENDENT
              key: 'aws.s3.select_requests["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              description: 'The number of Amazon S3 SELECT Object Content requests made for objects in an Amazon S3 bucket.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "SelectRequests")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: effa8475024843249ad213d726323e72
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Total request latency, avg'
              type: DEPENDENT
              key: 'aws.s3.total_request_latency.avg["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              units: ms
              description: |
                The elapsed per-request time from the first byte received to the last byte sent to an Amazon S3 bucket.
                This includes the time taken to receive the request body and send the response body, which is not included in FirstByteLatency.
                Statistic: Average.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "TotalRequestLatency")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: latency
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
            - uuid: 886b748066834f01aa2f6f9327fceba0
              name: 'Filter [{#AWS.S3.FILTER.ID.NAME}]: Total request latency, p90'
              type: DEPENDENT
              key: 'aws.s3.total_request_latency.p90["{#AWS.S3.FILTER.ID.NAME}"]'
              value_type: FLOAT
              units: ms
              description: |
                The elapsed per-request time from the first byte received to the last byte sent to an Amazon S3 bucket.
                This includes the time taken to receive the request body and send the response body, which is not included in FirstByteLatency.
                Statistic: 90th percentile.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "TotalRequestLatency")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.s3.get_metrics["{#AWS.S3.FILTER.ID.NAME}"]'
              tags:
                - tag: component
                  value: latency
                - tag: component
                  value: requests
                - tag: filter-id
                  value: '{#AWS.S3.FILTER.ID.NAME}'
          master_item:
            key: aws.s3.get_metrics
          lld_macro_paths:
            - lld_macro: '{#AWS.S3.FILTER.ID.NAME}'
              path: $.Id
            - lld_macro: '{#AWS.S3.REGION}'
              path: $.region
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.filter_id
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
      tags:
        - tag: class
          value: cloud
        - tag: class
          value: storage
        - tag: target
          value: aws
        - tag: target
          value: s3
      macros:
        - macro: '{$AWS.ACCESS.KEY.ID}'
          description: 'Access key ID.'
          config:
            type: TEXT
            priority: '3'
            label: 'Access key ID'
            description: 'Access keys are long-term credentials for an IAM user.'
        - macro: '{$AWS.ASSUME.ROLE.ARN}'
          description: 'ARN assume role; add when using the `assume_role` authorization method.'
          config:
            type: TEXT
            priority: '5'
            label: 'Assume role ARN'
            description: 'The ARN for the assume role authorization method.'
        - macro: '{$AWS.ASSUME.ROLE.AUTH.METADATA}'
          value: 'false'
          description: 'Add when using the `assume_role` through instance metadata or environment authorization method. Possible values: `false`, `true`.'
          config:
            type: LIST
            priority: '2'
            label: 'Assume Role Metadata Authorization'
            description: 'Chose `True` when use instance metadata service to retrieve role credentials.'
            options:
              - value: 'false'
                text: 'False'
              - value: 'true'
                text: 'True'
        - macro: '{$AWS.AUTH_TYPE}'
          value: access_key
          description: 'Authorization method. Possible values: `access_key`, `assume_role`, `role_base`.'
          config:
            type: LIST
            priority: '1'
            label: 'Authorization method'
            description: 'Authorization method used to access AWS.'
            required: 'YES'
            options:
              - value: access_key
                text: 'Access key'
              - value: assume_role
                text: AssumeRole
              - value: role_base
                text: 'Role-based access'
        - macro: '{$AWS.PROXY}'
          description: 'Sets HTTP proxy value. If this macro is empty then no proxy is used.'
          config:
            type: TEXT
            priority: '8'
            section_name: Other
            label: 'HTTP proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AWS.REQUEST.REGION}'
          value: us-east-1
          description: 'Region used in GET request `ListBuckets`.'
          config:
            type: TEXT
            priority: '6'
            label: 'Request region'
            description: 'The AWS region for the GET request.'
        - macro: '{$AWS.S3.BUCKET.NAME}'
          description: 'S3 bucket name.'
          config:
            type: TEXT
            priority: '9'
            label: 'S3 bucket name'
            description: 'The name of the S3 bucket to monitor.'
        - macro: '{$AWS.S3.LLD.FILTER.ALARM_NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable alarms by name.'
          config:
            type: TEXT
            priority: '10'
            section_name: Filters
            label: 'Alarm name filter (matches)'
            description: 'A regex pattern to include alarms by name.'
        - macro: '{$AWS.S3.LLD.FILTER.ALARM_NAME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered alarms by name.'
          config:
            type: TEXT
            priority: '11'
            section_name: Filters
            label: 'Alarm name filter (not matches)'
            description: 'A regex pattern to exclude alarms by name.'
        - macro: '{$AWS.S3.LLD.FILTER.ID.NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable request metrics by filter ID name.'
          config:
            type: TEXT
            priority: '12'
            section_name: Filters
            label: 'Request metrics filter (matches)'
            description: 'A regex pattern to include request metrics by filter ID name.'
        - macro: '{$AWS.S3.LLD.FILTER.ID.NAME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered request metrics by filter ID name.'
          config:
            type: TEXT
            priority: '13'
            section_name: Filters
            label: 'Request metrics filter (not matches)'
            description: 'A regex pattern to exclude request metrics by filter ID name.'
        - macro: '{$AWS.S3.UPDATE.INTERVAL}'
          value: '1800'
          description: 'Interval in seconds for getting request metrics. Used in the metric configuration and in the JavaScript API query. Must be between 1 and 86400 seconds.'
          config:
            type: TEXT
            priority: '14'
            section_name: Other
            label: 'Update interval'
            description: 'The interval in seconds for retrieving request metrics. In the range from 1 to 86400 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.SECRET.ACCESS.KEY}'
          type: SECRET_TEXT
          description: 'Secret access key.'
          config:
            type: TEXT
            priority: '4'
            label: 'Secret access key'
            description: 'Secret access key can be retrieved only at the time you create it.'
        - macro: '{$AWS.STS.REGION}'
          value: us-east-1
          description: 'Region used in assume role request.'
          config:
            type: TEXT
            priority: '7'
            label: 'STS region'
            description: 'The AWS region for the assume role request.'
      valuemaps:
        - uuid: 5f232f40f02246ab843c9aacdcf8d5c5
          name: 'Alarm state'
          mappings:
            - value: '0'
              newvalue: OK
            - value: '1'
              newvalue: 'Insufficient data'
            - value: '2'
              newvalue: Alarm
            - value: '255'
              newvalue: Unknown
  graphs:
    - uuid: 397c46285f674ac389c59f1c828ae179
      name: 'AWS EC2: Disk read/write bytes'
      graph_items:
        - color: 199C0D
          item:
            host: 'AWS EC2 by HTTP'
            key: aws.ec2.disk.read_bytes.rate
        - sortorder: '1'
          color: F63100
          item:
            host: 'AWS EC2 by HTTP'
            key: aws.ec2.disk_write_bytes.rate
    - uuid: 21b7ec1e5e1445e287855e3d1a12c2bc
      name: 'AWS EC2: Disk read/write rates'
      graph_items:
        - color: 199C0D
          item:
            host: 'AWS EC2 by HTTP'
            key: aws.ec2.disk.read_ops.rate
        - sortorder: '1'
          color: F63100
          item:
            host: 'AWS EC2 by HTTP'
            key: aws.ec2.disk_write_ops.rate
    - uuid: a1244a6a4b6641388546988257e905dc
      name: 'AWS EC2: Network packets'
      graph_items:
        - color: 199C0D
          item:
            host: 'AWS EC2 by HTTP'
            key: aws.ec2.packets_in.rate
        - sortorder: '1'
          color: F63100
          item:
            host: 'AWS EC2 by HTTP'
            key: aws.ec2.packets_out.rate
    - uuid: 45e96dbc8dff48eeadd18c69b085863f
      name: 'AWS EC2: Network traffic'
      graph_items:
        - color: 199C0D
          item:
            host: 'AWS EC2 by HTTP'
            key: aws.ec2.network_in.rate
        - sortorder: '1'
          color: F63100
          item:
            host: 'AWS EC2 by HTTP'
            key: aws.ec2.network_out.rate
    - uuid: 22143acf16da404cbb4a770d47a16e64
      name: 'AWS ECS Cluster: CPU Utilization'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 2196F3
          item:
            host: 'AWS ECS Serverless Cluster by HTTP'
            key: aws.ecs.cpu_utilization
    - uuid: e9bb6696b7f34beb9ba207821cb9c4e1
      name: 'AWS ECS Cluster: Disk Utilization'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 2196F3
          item:
            host: 'AWS ECS Serverless Cluster by HTTP'
            key: aws.ecs.disk.utilization
    - uuid: fefa5004db6f44c4a10cbebd00a82280
      name: 'AWS ECS Cluster: Memory Utilization'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 2196F3
          item:
            host: 'AWS ECS Serverless Cluster by HTTP'
            key: aws.ecs.memory_utilization
    - uuid: b2e46c9ceafd495998fd98957e3f7414
      name: 'AWS ECS Cluster: Network'
      graph_items:
        - color: 199C0D
          item:
            host: 'AWS ECS Serverless Cluster by HTTP'
            key: aws.ecs.network.rx
        - sortorder: '1'
          color: F63100
          item:
            host: 'AWS ECS Serverless Cluster by HTTP'
            key: aws.ecs.network.tx
    - uuid: b19f7d65ad1d469d8396b03111d38e52
      name: 'AWS ELB ALB: Connection Count'
      graph_items:
        - drawtype: BOLD_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Application Load Balancer by HTTP'
            key: aws.elb.alb.active_connection_count
        - sortorder: '1'
          drawtype: BOLD_LINE
          color: F63100
          item:
            host: 'AWS ELB Application Load Balancer by HTTP'
            key: aws.elb.alb.new_connection_count
        - sortorder: '2'
          drawtype: BOLD_LINE
          color: 00611C
          item:
            host: 'AWS ELB Application Load Balancer by HTTP'
            key: aws.elb.alb.rejected_connection_count
        - sortorder: '3'
          drawtype: BOLD_LINE
          color: F7941D
          item:
            host: 'AWS ELB Application Load Balancer by HTTP'
            key: aws.elb.alb.target_connection_error_count
    - uuid: fb034590cbc34b0aa297b77c1f320684
      name: 'AWS ELB ALB: Consumed LCUs and Processed Bytes'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Application Load Balancer by HTTP'
            key: aws.elb.alb.capacity_units
        - sortorder: '1'
          drawtype: GRADIENT_LINE
          color: F63100
          yaxisside: RIGHT
          item:
            host: 'AWS ELB Application Load Balancer by HTTP'
            key: aws.elb.alb.processed_bytes
    - uuid: a711d08edbd04abe890ab2b8cdf6d41b
      name: 'AWS ELB ALB: HTTP Code'
      graph_items:
        - drawtype: BOLD_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Application Load Balancer by HTTP'
            key: aws.elb.alb.http_3xx_count
        - sortorder: '1'
          drawtype: BOLD_LINE
          color: F63100
          item:
            host: 'AWS ELB Application Load Balancer by HTTP'
            key: aws.elb.alb.http_4xx_count
        - sortorder: '2'
          drawtype: BOLD_LINE
          color: 00611C
          item:
            host: 'AWS ELB Application Load Balancer by HTTP'
            key: aws.elb.alb.http_5xx_count
    - uuid: 4ee7ac4174b74f869e04dab5d76219ab
      name: 'AWS ELB ALB: Requests Count and Response Time'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Application Load Balancer by HTTP'
            key: aws.elb.alb.requests_count
        - sortorder: '1'
          drawtype: GRADIENT_LINE
          color: F63100
          yaxisside: RIGHT
          item:
            host: 'AWS ELB Application Load Balancer by HTTP'
            key: aws.elb.alb.target_response_time
    - uuid: 07118e148b0744ec98750733d1b5284c
      name: 'AWS ELB NLB: Concurrent Flows Count'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.active_flow_count
        - sortorder: '1'
          drawtype: GRADIENT_LINE
          color: F63100
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.new_flow_count
    - uuid: a13750d46d834d65a881396ecedaa813
      name: 'AWS ELB NLB: Concurrent Flows Count TCP'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.active_flow_count_tcp
        - sortorder: '1'
          drawtype: GRADIENT_LINE
          color: F63100
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.new_flow_count_tcp
    - uuid: 3b4ccb4dc50b4bf49ef45b517a65e6e8
      name: 'AWS ELB NLB: Concurrent Flows Count TLS'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.active_flow_count_tls
        - sortorder: '1'
          drawtype: GRADIENT_LINE
          color: F63100
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.new_flow_count_tls
    - uuid: 670bad5c2264431cb60b3a0b9c5cf111
      name: 'AWS ELB NLB: Concurrent Flows Count UDP'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.active_flow_count_udp
        - sortorder: '1'
          drawtype: GRADIENT_LINE
          color: F63100
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.new_flow_count_udp
    - uuid: c16c89c1a5da4aafbd8151f982cade2d
      name: 'AWS ELB NLB: Consumed LCUs and Processed Bytes'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.capacity_units
        - sortorder: '1'
          drawtype: GRADIENT_LINE
          color: F63100
          yaxisside: RIGHT
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.processed_bytes
    - uuid: c5718fb3ddfd4642ba2dbd914a1fe6ac
      name: 'AWS ELB NLB: Consumed LCUs TCP and Processed Bytes TCP'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.capacity_units_tcp
        - sortorder: '1'
          drawtype: GRADIENT_LINE
          color: F63100
          yaxisside: RIGHT
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.processed_bytes_tcp
    - uuid: 7b5d11acc0dc4d19b4d0a797570400e7
      name: 'AWS ELB NLB: Consumed LCUs TLS and Processed Bytes TLS'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.capacity_units_tls
        - sortorder: '1'
          drawtype: GRADIENT_LINE
          color: F63100
          yaxisside: RIGHT
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.processed_bytes_tls
    - uuid: 355fb45cbaef4dfb9050ca84fbfba83b
      name: 'AWS ELB NLB: Consumed LCUs UDP and Processed Bytes UDP'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.capacity_units_udp
        - sortorder: '1'
          drawtype: GRADIENT_LINE
          color: F63100
          yaxisside: RIGHT
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.processed_bytes_udp
    - uuid: e2023c7d365b45629ccf61f853229bcb
      name: 'AWS ELB NLB: New Flow Count'
      graph_items:
        - drawtype: BOLD_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.new_flow_count
        - sortorder: '1'
          drawtype: BOLD_LINE
          color: F63100
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.new_flow_count_tcp
        - sortorder: '2'
          drawtype: BOLD_LINE
          color: 00611C
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.new_flow_count_tls
        - sortorder: '3'
          drawtype: BOLD_LINE
          color: F7941D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.new_flow_count_udp
    - uuid: 457264f4a11a4a4dbac3314875b04ac0
      name: 'AWS ELB NLB: Peak Packets per second'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.peak_packets.rate
    - uuid: 7db2aa4f6f454b06ba3c9e01259a1a24
      name: 'AWS ELB NLB: Security Group Blocked Flow Count ICMP'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.sg_blocked_inbound_icmp
        - sortorder: '1'
          drawtype: GRADIENT_LINE
          color: F63100
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.sg_blocked_outbound_icmp
    - uuid: bf724b8819804cb385f6448f2f6133ac
      name: 'AWS ELB NLB: Security Group Blocked Flow Count TCP'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.sg_blocked_inbound_tcp
        - sortorder: '1'
          drawtype: GRADIENT_LINE
          color: F63100
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.sg_blocked_outbound_tcp
    - uuid: 3162f3656a154c9280bda0539c6e102c
      name: 'AWS ELB NLB: Security Group Blocked Flow Count UDP'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.sg_blocked_inbound_udp
        - sortorder: '1'
          drawtype: GRADIENT_LINE
          color: F63100
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.sg_blocked_outbound_udp
    - uuid: 561b3f02b2964c5d8dce2b2b6d2556d4
      name: 'AWS ELB NLB: TCP Reset Count'
      graph_items:
        - drawtype: BOLD_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.tcp_client_reset_count
        - sortorder: '1'
          drawtype: BOLD_LINE
          color: F63100
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.tcp_elb_reset_count
        - sortorder: '2'
          drawtype: BOLD_LINE
          color: 00611C
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.tcp_target_reset_count
    - uuid: 87c58ec6a1ee4c9abde81e10af999d79
      name: 'AWS ELB NLB: TLS Negotiation Error Count'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 199C0D
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.client_tls_negotiation_error_count
        - sortorder: '1'
          drawtype: GRADIENT_LINE
          color: F63100
          item:
            host: 'AWS ELB Network Load Balancer by HTTP'
            key: aws.elb.nlb.target_tls_negotiation_error_count
    - uuid: af2dcb92a19a47c2a6f8d1ea78794553
      name: 'AWS Lambda: Async dropped events'
      graph_items:
        - drawtype: BOLD_LINE
          color: 199C0D
          item:
            host: 'AWS Lambda by HTTP'
            key: aws.lambda.async_events_dropped.sum
    - uuid: c6d59fa52671477db6865874acedec1b
      name: 'AWS Lambda: Async event age'
      graph_items:
        - drawtype: BOLD_LINE
          color: 199C0D
          item:
            host: 'AWS Lambda by HTTP'
            key: aws.lambda.async_event_age.avg
    - uuid: 2b98a8ff2c584419b962ed0cb3fe8809
      name: 'AWS Lambda: Asynchronous events'
      graph_items:
        - drawtype: BOLD_LINE
          color: 199C0D
          item:
            host: 'AWS Lambda by HTTP'
            key: aws.lambda.async_events_received.sum
    - uuid: 8eb1c4bbb3974048a76e4c84bdfa25a5
      name: 'AWS Lambda: Concurrent executions'
      graph_items:
        - drawtype: BOLD_LINE
          color: 199C0D
          item:
            host: 'AWS Lambda by HTTP'
            key: aws.lambda.concurrent_executions.max
    - uuid: 7e1dad2ad49d4c0487e4e724594331fa
      name: 'AWS Lambda: Duration'
      graph_items:
        - drawtype: BOLD_LINE
          color: 199C0D
          item:
            host: 'AWS Lambda by HTTP'
            key: aws.lambda.duration.avg
    - uuid: 07288fd5c2ff4806a6749e114d0cf93d
      name: 'AWS Lambda: Errors'
      graph_items:
        - drawtype: BOLD_LINE
          color: 199C0D
          item:
            host: 'AWS Lambda by HTTP'
            key: aws.lambda.errors.sum
    - uuid: cc854ebac57143629b49f1fae3598d8b
      name: 'AWS Lambda: Invocations'
      graph_items:
        - drawtype: BOLD_LINE
          color: 199C0D
          item:
            host: 'AWS Lambda by HTTP'
            key: aws.lambda.invocations.sum
    - uuid: c16f61d853474a0f9a251327873ef62e
      name: 'AWS Lambda: Throttles'
      graph_items:
        - drawtype: BOLD_LINE
          color: 199C0D
          item:
            host: 'AWS Lambda by HTTP'
            key: aws.lambda.dead_letter_errors.sum
        - sortorder: '1'
          drawtype: BOLD_LINE
          color: F63100
          item:
            host: 'AWS Lambda by HTTP'
            key: aws.lambda.throttles.sum
    - uuid: d01c132670fb4347b591ddb96900fa99
      name: 'AWS Lambda: Unreserved concurrent executions'
      graph_items:
        - drawtype: BOLD_LINE
          color: 199C0D
          item:
            host: 'AWS Lambda by HTTP'
            key: aws.lambda.unreserved_concurrent_executions.max
    - uuid: f2178fe21bc4454a9d3eee3b17ef11bc
      name: 'AWS RDS: Disk read/write IOPS'
      graph_items:
        - color: 199C0D
          item:
            host: 'AWS RDS instance by HTTP'
            key: aws.rds.read_iops.rate
        - sortorder: '1'
          color: F63100
          item:
            host: 'AWS RDS instance by HTTP'
            key: aws.rds.write_iops.rate
    - uuid: e0fbc3a0256c41cf99acb307921f448f
      name: 'AWS RDS: Disk read/write latency'
      graph_items:
        - color: 199C0D
          item:
            host: 'AWS RDS instance by HTTP'
            key: aws.rds.read_latency
        - sortorder: '1'
          color: F63100
          item:
            host: 'AWS RDS instance by HTTP'
            key: aws.rds.write_latency
    - uuid: a479a587e0c5484293e939ff56060270
      name: 'AWS RDS: Disk read/write throughput'
      graph_items:
        - color: 199C0D
          item:
            host: 'AWS RDS instance by HTTP'
            key: aws.rds.read_throughput.rate
        - sortorder: '1'
          color: F63100
          item:
            host: 'AWS RDS instance by HTTP'
            key: aws.rds.write_throughput.rate
    - uuid: 4f76da00f7ea417d9156a8ab21b2d61f
      name: 'AWS RDS: Local storage read/write IOPS'
      graph_items:
        - color: 199C0D
          item:
            host: 'AWS RDS instance by HTTP'
            key: aws.rds.write_iops_local_storage.rate
        - sortorder: '1'
          color: F63100
          item:
            host: 'AWS RDS instance by HTTP'
            key: aws.rds.read_iops_local_storage.rate
    - uuid: a38ee12797874a57bd30307d1ba7b589
      name: 'AWS RDS: Local storage read/write latency'
      graph_items:
        - color: 199C0D
          item:
            host: 'AWS RDS instance by HTTP'
            key: aws.rds.read_latency_local_storage
        - sortorder: '1'
          color: F63100
          item:
            host: 'AWS RDS instance by HTTP'
            key: aws.rds.write_latency_local_storage
    - uuid: f2a25a07efea46d1836188bf9cdb12d2
      name: 'AWS RDS: Local storage read/write throughput'
      graph_items:
        - color: 199C0D
          item:
            host: 'AWS RDS instance by HTTP'
            key: aws.rds.read_throughput_local_storage.rate
        - sortorder: '1'
          color: F63100
          item:
            host: 'AWS RDS instance by HTTP'
            key: aws.rds.write_throughput_local_storage.rate
    - uuid: 05c0cf7b37664e06a0fd74f62761fe5e
      name: 'AWS RDS: Network traffic'
      graph_items:
        - color: 199C0D
          item:
            host: 'AWS RDS instance by HTTP'
            key: aws.rds.network_receive_throughput.rate
        - sortorder: '1'
          color: F63100
          item:
            host: 'AWS RDS instance by HTTP'
            key: aws.rds.network_transmit_throughput.rate
        - sortorder: '2'
          color: 00611C
          item:
            host: 'AWS RDS instance by HTTP'
            key: aws.rds.network_throughput.rate
