zabbix_export:
  version: '7.4'
  template_groups:
    - uuid: c2c162144c2d4c5491c8801193af4945
      name: Templates/Cloud
  host_groups:
    - uuid: a571c0d144b14fd4a87a9d9b2aa9fcd6
      name: Applications
    - uuid: 748ad4d098d447d492bb935c907f652f
      name: Databases
    - uuid: 137f19e6e2dc4219b33553b812627bc2
      name: 'Virtual machines'
  templates:
    - uuid: c60e5929ab474f67bbe67dc6b04e709d
      template: 'AWS by HTTP'
      name: 'AWS by HTTP'
      description: |
        Get AWS EC2, RDS and S3 instances, AWS ECS clusters, AWS Elastic Load Balancing. 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 is designed for the effortless deployment of AWS monitoring by Zabbix via HTTP and doesn't require any external scripts.
        - Currently, the template supports the discovery of EC2 and RDS instances, ECS clusters, ELB, Lambda and S3 buckets.
        
        ## Setup
        
        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 metrics.
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Action": [
                        "cloudwatch:DescribeAlarms",
                        "cloudwatch:GetMetricData",
                        "ec2:DescribeInstances",
                        "ec2:DescribeVolumes",
                        "ec2:DescribeRegions",
                        "rds:DescribeEvents",
                        "rds:DescribeDBInstances",
                        "ecs:DescribeClusters",
                        "ecs:ListServices",
                        "ecs:ListTasks",
                        "ecs:ListClusters",
                        "s3:ListAllMyBuckets",
                        "s3:GetBucketLocation",
                        "s3:GetMetricsConfiguration",
                        "elasticloadbalancing:DescribeLoadBalancers",
                        "elasticloadbalancing:DescribeTargetGroups",
                        "ec2:DescribeSecurityGroups",
                        "lambda:ListFunctions"
                    ],
                    "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 `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",
                        "ec2:DescribeInstances",
                        "ec2:DescribeVolumes",
                        "ec2:DescribeRegions",
                        "rds:DescribeEvents",
                        "rds:DescribeDBInstances",
                        "ecs:DescribeClusters",
                        "ecs:ListServices",
                        "ecs:ListTasks",
                        "ecs:ListClusters",
                        "s3:ListAllMyBuckets",
                        "s3:GetBucketLocation",
                        "s3:GetMetricsConfiguration",
                        "ec2:AssociateIamInstanceProfile",
                        "ec2:ReplaceIamInstanceProfileAssociation",
                        "elasticloadbalancing:DescribeLoadBalancers",
                        "elasticloadbalancing:DescribeTargetGroups",
                        "ec2:DescribeSecurityGroups",
                        "lambda:ListFunctions"
                    ],
                    "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, add the appropriate permissions:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "iam:PassRole",
                    "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
                },
                {
                    "Effect": "Allow",
                    "Action": [
                        "cloudwatch:DescribeAlarms",
                        "cloudwatch:GetMetricData",
                        "ec2:DescribeInstances",
                        "ec2:DescribeVolumes",
                        "ec2:DescribeRegions",
                        "rds:DescribeEvents",
                        "rds:DescribeDBInstances",
                        "ecs:DescribeClusters",
                        "ecs:ListServices",
                        "ecs:ListTasks",
                        "ecs:ListClusters",
                        "s3:ListAllMyBuckets",
                        "s3:GetBucketLocation",
                        "s3:GetMetricsConfiguration",
                        "ec2:AssociateIamInstanceProfile",
                        "ec2:ReplaceIamInstanceProfileAssociation",
                        "elasticloadbalancing:DescribeLoadBalancers",
                        "elasticloadbalancing:DescribeTargetGroups",
                        "ec2:DescribeSecurityGroups",
                        "lambda:ListFunctions"
                    ],
                    "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.
        
        Choose a method of authorization (field of `Authorization method`).
        
        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).
        
        Refer to the Macros section for a list of macros used for LLD filters.
        
        Additional information about the 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)
        * [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)
        * [Full metrics list related to S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/metrics-dimensions.html)
        * [Full metrics list related to ECS](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cloudwatch-metrics.html)
        * [Full metrics list related to ELB ALB](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)
        * [DescribeVolumes API method](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVolumes.html)
        * [DescribeLoadBalancers API method](https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_DescribeLoadBalancers.html)
      vendor:
        name: Zabbix
        version: 7.4-2
      groups:
        - name: Templates/Cloud
      discovery_rules:
        - uuid: c651911bad9244ad9c8d2dad5b0d70e4
          name: 'EC2 instances discovery'
          type: SCRIPT
          key: aws.ec2.discovery
          delay: 12h
          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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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];
            				});
            		}
            		['describe_region', 'region_match', 'region_not_match'].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/, ''),
            			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' & !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 API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	tagToNameInstances: function (instance) {
            		try {
            			var tags = AWS.getField(instance, 'tagSet.item'),
            				instanceName = AWS.getField(instance, 'instanceId');
            			if (!Array.isArray(tags))
            				tags = [tags]
            			tags.forEach(
            				function (tag) {
            					if (String(AWS.getField(tag, 'key')) === 'Name') {
            						instanceName = AWS.getField(tag, 'value');
            					}
            				}
            			);
            			return instanceName;
            		}
            		catch (error) {
            			return AWS.getField(instance, 'instanceId');
            		}
            	},
            
            	listRegions: function () {
            		var payload = {
            			'Action': 'DescribeRegions',
            			'Version': '2016-11-15'
            		};
            
            		regions = AWS.getField(AWS.request('GET', AWS.params.describe_region, 'ec2', AWS.prepareParams(payload)), 'DescribeRegionsResponse.regionInfo.item');
            
            		if (!Array.isArray(regions))
            			regions = [regions]
            		return regions
            	},
            
            	listInstances: function () {
            		var lld_array = [],
            			regions = AWS.listRegions(),
            			payload = {
            				'Action': 'DescribeInstances',
            				'Version': '2016-11-15'
            			};
            
            		regions.forEach(function (region) {
            			var region_name = AWS.getField(region, 'regionName');
            			if (region_name.match(AWS.params.region_match) === null ||
            				region_name.match(AWS.params.region_not_match) !== null)
            				return;
            
            			result = AWS.request('GET', region_name, 'ec2', AWS.prepareParams(payload), '');
            
            			if (typeof result !== 'object'
            				|| typeof result.DescribeInstancesResponse !== 'object'
            				|| typeof result.DescribeInstancesResponse.reservationSet !== 'object') {
            				throw 'Cannot get EC2 instance list from AWS API. Check debug log for more information.';
            			}
            
            			if (result.DescribeInstancesResponse.reservationSet === null)
            				return [];
            
            			if (typeof result.DescribeInstancesResponse.reservationSet.item !== 'object')
            				throw 'Cannot get EC2 instance list from AWS API. Check debug log for more information.';
            
            			var reservation = result.DescribeInstancesResponse.reservationSet.item
            			if (!Array.isArray(reservation))
            				reservation = [reservation]
            
            			reservation.forEach(function (res_item) {
            				var instances = AWS.getField(res_item, 'instancesSet.item')
            				if (!Array.isArray(instances))
            					instances = [instances]
            				instances.forEach(function (instance) {
            					if (AWS.getField(instance, 'instanceState.name') === 'terminated') return;
            					lld_array.push(
            						{
            							instanceId: AWS.getField(instance, 'instanceId'),
            							instanceName: AWS.tagToNameInstances(instance),
            							instanceRegion: region_name
            						}
            					)
            				});
            			});
            		});
            
            		return lld_array;
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	return JSON.stringify(AWS.listInstances());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS EC2 ] ERROR: ' + error);
            	return JSON.stringify({ 'error': error });
            }
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.EC2.INSTANCE.NAME}'
                value: '{$AWS.EC2.LLD.FILTER.NAME.MATCHES}'
              - macro: '{#AWS.EC2.INSTANCE.NAME}'
                value: '{$AWS.EC2.LLD.FILTER.NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#AWS.EC2.INSTANCE.REGION}'
                value: '{$AWS.EC2.LLD.FILTER.REGION.MATCHES}'
              - macro: '{#AWS.EC2.INSTANCE.REGION}'
                value: '{$AWS.EC2.LLD.FILTER.REGION.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Get EC2 instances.'
          host_prototypes:
            - uuid: c4c830c727294b07926c39b00cf19046
              host: '{#AWS.EC2.INSTANCE.ID}'
              name: '{#AWS.EC2.INSTANCE.NAME}'
              group_links:
                - group:
                    name: 'Virtual machines'
              templates:
                - name: 'AWS EC2 by HTTP'
              macros:
                - macro: '{$AWS.EC2.INSTANCE.ID}'
                  value: '{#AWS.EC2.INSTANCE.ID}'
                  description: 'EC2 instance ID.'
                - macro: '{$AWS.REGION}'
                  value: '{#AWS.EC2.INSTANCE.REGION}'
                  description: 'Amazon EC2 Region code.'
              tags:
                - tag: name
                  value: '{#AWS.EC2.INSTANCE.NAME}'
                - tag: region
                  value: '{#AWS.EC2.INSTANCE.REGION}'
                - tag: service
                  value: ec2
              custom_interfaces: 'YES'
              interfaces:
                - ip: '{#AWS.EC2.INSTANCE.ID}'
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: describe_region
              value: '{$AWS.DESCRIBE.REGION}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region_match
              value: '{$AWS.EC2.LLD.FILTER.REGION.MATCHES}'
            - name: region_not_match
              value: '{$AWS.EC2.LLD.FILTER.REGION.NOT_MATCHES}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          lld_macro_paths:
            - lld_macro: '{#AWS.EC2.INSTANCE.ID}'
              path: $.instanceId
            - lld_macro: '{#AWS.EC2.INSTANCE.NAME}'
              path: $.instanceName
            - lld_macro: '{#AWS.EC2.INSTANCE.REGION}'
              path: $.instanceRegion
        - uuid: 44b68894d68c45ec9a5ea787c975ae16
          name: 'ECS clusters discovery'
          type: SCRIPT
          key: aws.ecs.discovery
          delay: 12h
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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];
            				});
            		}
            		['describe_region', 'region_match', 'region_not_match'].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' & !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 API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            
            	},
            
            	listRegions: function () {
            		var payload = {
            			'Action': 'DescribeRegions',
            			'Version': '2016-11-15'
            		};
            
            		regions = AWS.getField(AWS.request('GET', AWS.params.describe_region, 'ec2', AWS.prepareParams(payload)), 'DescribeRegionsResponse.regionInfo.item');
            
            		if (!Array.isArray(regions))
            			regions = [regions]
            
            		return regions
            	},
            
            	listClusters: function () {
            		var data = [],
            			regions = AWS.listRegions(),
            			result,
            			ECSClusters,
            			payload = {
            				'Action': 'ListClusters',
            				'Version': '2014-11-13'
            			};
            
            		regions.forEach(function (region) {
            			var region_name = AWS.getField(region, 'regionName');
            			if (region_name.match(AWS.params.region_match) === null ||
            				region_name.match(AWS.params.region_not_match) !== null)
            				return;
            
            			result = AWS.request('GET', region_name, 'ecs', AWS.prepareParams(payload));
            			ECSClusters = AWS.getField(result, 'ListClustersResponse.ListClustersResult.clusterArns')
            			for (k in ECSClusters) {
            				clusters = ECSClusters[k];
            				json = {};
            				input = clusters.split('/');
            				for (var i = 1; i < input.length; i += 2) {
            					json[input[i]] = input[i + 1];
            				}
            				data.push({
            					'clusters_name': input[1],
            					'region': region_name
            				});
            			}
            		});
            
            		return data;
            	},
            
            	decribeClusters: function (cluster_name, region_name) {
            		var payload = {
            			'Action': 'DescribeClusters',
            			'Version': '2014-11-13',
            			'clusters.clusterName': cluster_name,
            			'include.statistics': 'STATISTICS'
            		};
            		result = AWS.request('GET', region_name, 'ecs', AWS.prepareParams(payload));
            
            		return result;
            
            	}
            
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            	var clusters = AWS.listClusters(),
            		infrastructure = [],
            		metrics = ['runningEC2TasksCount', 'pendingEC2TasksCount', 'activeEC2ServiceCount', 'drainingEC2ServiceCount'],
            		ECSClusters = [],
            		DescribeClusters = [];
            	DescribeClusters = clusters.map(function (cluster) {
            		ECSClusters = AWS.getField(AWS.decribeClusters(cluster.clusters_name, cluster.region), 'DescribeClustersResponse.DescribeClustersResult.clusters')
            		for (k in ECSClusters) {
            			var ECS2 = 0;
            			statistic = AWS.getField(ECSClusters[k], 'statistics');
            			statistic.forEach(function (id) {
            				for (i in metrics) {
            					if (AWS.getField(id, 'name') === metrics[i]) {
            						ECS2 += Number(AWS.getField(id, 'value'));
            					}
            				}
            			})
            			infrastructure = (ECS2 > 0) ? 'use_ecs2' : 'serverless';
            
            			return {
            				'clusterName': ECSClusters[k].clusterName,
            				'status': ECSClusters[k].status,
            				'infrastructure': infrastructure,
            				'region': cluster.region
            			}
            
            		}
            	})
            
            	return JSON.stringify(DescribeClusters);
            
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS ECS ] ERROR: ' + error);
            	return JSON.stringify({ 'error': error });
            }
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.ECS.CLUSTER.NAME}'
                value: '{$AWS.ECS.LLD.FILTER.NAME.MATCHES}'
              - macro: '{#AWS.ECS.CLUSTER.NAME}'
                value: '{$AWS.ECS.LLD.FILTER.NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#AWS.ECS.CLUSTER.REGION}'
                value: '{$AWS.ECS.LLD.FILTER.REGION.MATCHES}'
              - macro: '{#AWS.ECS.CLUSTER.REGION}'
                value: '{$AWS.ECS.LLD.FILTER.REGION.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#AWS.ECS.CLUSTER.STATUS}'
                value: '{$AWS.ECS.LLD.FILTER.STATUS.MATCHES}'
              - macro: '{#AWS.ECS.CLUSTER.STATUS}'
                value: '{$AWS.ECS.LLD.FILTER.STATUS.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Get ECS clusters.'
          host_prototypes:
            - uuid: 71072e5a149e45b293946866f8220c07
              host: '{#AWS.ECS.CLUSTER.NAME}'
              name: '{#AWS.ECS.CLUSTER.NAME}'
              group_links:
                - group:
                    name: Applications
              macros:
                - macro: '{$AWS.ECS.CLUSTER.NAME}'
                  value: '{#AWS.ECS.CLUSTER.NAME}'
                  description: 'ECS cluster name.'
                - macro: '{$AWS.REGION}'
                  value: '{#AWS.ECS.CLUSTER.REGION}'
                  description: 'ECS cluster region.'
              tags:
                - tag: name
                  value: '{#AWS.ECS.CLUSTER.NAME}'
                - tag: region
                  value: '{#AWS.ECS.CLUSTER.REGION}'
                - tag: service
                  value: ecs
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: describe_region
              value: '{$AWS.DESCRIBE.REGION}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region_match
              value: '{$AWS.ECS.LLD.FILTER.REGION.MATCHES}'
            - name: region_not_match
              value: '{$AWS.ECS.LLD.FILTER.REGION.NOT_MATCHES}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          lld_macro_paths:
            - lld_macro: '{#AWS.ECS.CLUSTER.INFRASTRUCTURE}'
              path: $.infrastructure
            - lld_macro: '{#AWS.ECS.CLUSTER.NAME}'
              path: $.clusterName
            - lld_macro: '{#AWS.ECS.CLUSTER.REGION}'
              path: $.region
            - lld_macro: '{#AWS.ECS.CLUSTER.STATUS}'
              path: $.status
          overrides:
            - name: Serverless
              step: '1'
              filter:
                conditions:
                  - macro: '{#AWS.ECS.CLUSTER.INFRASTRUCTURE}'
                    value: ^serverless$
              operations:
                - operationobject: HOST_PROTOTYPE
                  operator: REGEXP
                  templates:
                    - name: 'AWS ECS Serverless Cluster by HTTP'
            - name: 'Use EC2 Infrastructure'
              step: '2'
              filter:
                conditions:
                  - macro: '{#AWS.ECS.CLUSTER.INFRASTRUCTURE}'
                    value: ^use_ecs2$
              operations:
                - operationobject: HOST_PROTOTYPE
                  operator: REGEXP
                  templates:
                    - name: 'AWS ECS Cluster by HTTP'
        - uuid: e7ac860c53bf403f9aee8cdd4b099c05
          name: 'ELB load balancers discovery'
          type: SCRIPT
          key: aws.elb.discovery
          delay: 12h
          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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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];
            				});
            		}
            		['describe_region', 'region_match', 'region_not_match'].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/, ''),
            			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' & !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 API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	listRegions: function () {
            		var payload = {
            			'Action': 'DescribeRegions',
            			'Version': '2016-11-15'
            		};
            
            		regions = AWS.getField(AWS.request('GET', AWS.params.describe_region, 'ec2', AWS.prepareParams(payload)), 'DescribeRegionsResponse.regionInfo.item');
            
            		if (!Array.isArray(regions))
            			regions = [regions]
            		return regions
            	},
            
            	listLoadBalancers: function () {
            		var lld_array = [],
            			regions = AWS.listRegions(),
            			payload = {
            				'Action': 'DescribeLoadBalancers',
            				'Version': '2015-12-01'
            			};
            
            		regions.forEach(function (region) {
            			var region_name = AWS.getField(region, 'regionName');
            			if (region_name.match(AWS.params.region_match) === null ||
            				region_name.match(AWS.params.region_not_match) !== null)
            				return;
            			elb = AWS.getField(AWS.request('GET', region_name, 'elasticloadbalancing', AWS.prepareParams(payload)), 'DescribeLoadBalancersResponse.DescribeLoadBalancersResult.LoadBalancers');
            			if (!Array.isArray(elb))
            				elb = [elb]
            
            			elb.forEach(function (elb) {
            				lld_array.push(
            					{
            						name: AWS.getField(elb, 'LoadBalancerName'),
            						arn: AWS.getField(elb, 'LoadBalancerArn'),
            						type: AWS.getField(elb, 'Type'),
            						state: AWS.getField(elb, 'State.Code'),
            						dns_name: AWS.getField(elb, 'DNSName'),
            						region: region_name
            					}
            				)
            			});
            		});
            
            		return lld_array;
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	return JSON.stringify(AWS.listLoadBalancers());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS ELB ] ERROR: ' + error);
            	return JSON.stringify({ 'error': error });
            }
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.ELB.NAME}'
                value: '{$AWS.ELB.LLD.FILTER.NAME.MATCHES}'
              - macro: '{#AWS.ELB.NAME}'
                value: '{$AWS.ELB.LLD.FILTER.NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#AWS.ELB.REGION}'
                value: '{$AWS.ELB.LLD.FILTER.REGION.MATCHES}'
              - macro: '{#AWS.ELB.REGION}'
                value: '{$AWS.ELB.LLD.FILTER.REGION.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#AWS.ELB.STATE}'
                value: '{$AWS.ELB.LLD.FILTER.STATE.MATCHES}'
              - macro: '{#AWS.ELB.STATE}'
                value: '{$AWS.ELB.LLD.FILTER.STATE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Get ELB load balancers.'
          host_prototypes:
            - uuid: 2c31bc79209e41978f76315406339769
              host: '{#AWS.ELB.NAME}'
              name: '{#AWS.ELB.NAME}'
              group_links:
                - group:
                    name: Applications
              macros:
                - macro: '{$AWS.ELB.ARN}'
                  value: '{#AWS.ELB.ARN}'
                  description: 'The Amazon Resource Names (ARN) of the load balancers.'
                - macro: '{$AWS.ELB.NAME}'
                  value: '{#AWS.ELB.NAME}'
                  description: 'ELB load balancer name.'
                - macro: '{$AWS.REGION}'
                  value: '{#AWS.ELB.REGION}'
                  description: 'ELB load balancer region.'
              tags:
                - tag: dns-name
                  value: '{#AWS.ELB.DNS.NAME}'
                - tag: name
                  value: '{#AWS.ELB.NAME}'
                - tag: region
                  value: '{#AWS.ELB.REGION}'
                - tag: service
                  value: elb
                - tag: type
                  value: '{#AWS.ELB.TYPE}'
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: describe_region
              value: '{$AWS.DESCRIBE.REGION}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region_match
              value: '{$AWS.ELB.LLD.FILTER.REGION.MATCHES}'
            - name: region_not_match
              value: '{$AWS.ELB.LLD.FILTER.REGION.NOT_MATCHES}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          lld_macro_paths:
            - lld_macro: '{#AWS.ELB.ARN}'
              path: $.arn
            - lld_macro: '{#AWS.ELB.DNS.NAME}'
              path: $.dns_name
            - lld_macro: '{#AWS.ELB.NAME}'
              path: $.name
            - lld_macro: '{#AWS.ELB.REGION}'
              path: $.region
            - lld_macro: '{#AWS.ELB.STATE}'
              path: $.state
            - lld_macro: '{#AWS.ELB.TYPE}'
              path: $.type
          overrides:
            - name: 'Application Load Balancers'
              step: '1'
              filter:
                conditions:
                  - macro: '{#AWS.ELB.TYPE}'
                    value: ^application$
              operations:
                - operationobject: HOST_PROTOTYPE
                  operator: REGEXP
                  templates:
                    - name: 'AWS ELB Application Load Balancer by HTTP'
            - name: 'Network Load Balancers'
              step: '2'
              filter:
                conditions:
                  - macro: '{#AWS.ELB.TYPE}'
                    value: ^network$
              operations:
                - operationobject: HOST_PROTOTYPE
                  operator: REGEXP
                  templates:
                    - name: 'AWS ELB Network Load Balancer by HTTP'
        - uuid: 691d96408dbc4c5c9235932cdbe70648
          name: 'Lambda discovery'
          type: SCRIPT
          key: aws.lambda.discovery
          delay: 12h
          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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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];
            				});
            		}
            		['describe_region', 'region_match', 'region_not_match'].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, uri) {
            		if (typeof data === 'undefined' || data === null) {
            			data = '';
            		}
            
            		var amzdate = (new Date()).toISOString().replace(/\.\d+Z/, 'Z').replace(/[-:]/g, ''),
            			date = amzdate.replace(/T\d+Z/, ''),
            			canonical_uri = '/' + uri,
            			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' & !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 ] Sending request: ' + url);
            		response = request.get(url);
            		Zabbix.log(4, '[ AWS Lambda ] 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;
            	},
            
            	listRegions: function () {
            		var payload = {
            			'Action': 'DescribeRegions',
            			'Version': '2016-11-15'
            		};
            
            		regions = AWS.getField(AWS.request('GET', AWS.params.describe_region, 'ec2', AWS.prepareParams(payload), '', ''), 'DescribeRegionsResponse.regionInfo.item');
            
            		if (!Array.isArray(regions))
            			regions = [regions]
            
            		return regions
            	},
            
            	listFunctions: function () {
            		var lldArray = [],
            			regions = AWS.listRegions();
            		payload = {
            			'FunctionVersion': 'ALL',
            			'MaxItems': '10000'
            		};
            
            		regions.forEach(function (region) {
            			var region_name = AWS.getField(region, 'regionName');
            			if (region_name.match(AWS.params.region_match) === null ||
            				region_name.match(AWS.params.region_not_match) !== null)
            				return;
            			lambdaFunction = AWS.getField(AWS.request('GET', region_name, 'lambda', AWS.prepareParams(payload), '', '2015-03-31/functions'), 'Functions');
            			if (!Array.isArray(lambdaFunction))
            				lambdaFunction = [lambdaFunction]
            
            			lambdaFunction.forEach(function (lambdaFunction) {
            				lldArray.push(
            					{
            						name: AWS.getField(lambdaFunction, 'FunctionName'),
            						arn: AWS.getField(lambdaFunction, 'FunctionArn'),
            						runtime: AWS.getField(lambdaFunction, 'Runtime'),
            						version: AWS.getField(lambdaFunction, 'Version'),
            						region: region_name
            					}
            				)
            			});
            		});
            
            		return lldArray;
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	return JSON.stringify(AWS.listFunctions());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS Lambda ] ERROR: ' + error);
            	return JSON.stringify({ 'error': error });
            }
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.LAMBDA.NAME}'
                value: '{$AWS.LAMBDA.LLD.FILTER.NAME.MATCHES}'
              - macro: '{#AWS.LAMBDA.NAME}'
                value: '{$AWS.LAMBDA.LLD.FILTER.NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#AWS.LAMBDA.REGION}'
                value: '{$AWS.LAMBDA.LLD.FILTER.REGION.MATCHES}'
              - macro: '{#AWS.LAMBDA.REGION}'
                value: '{$AWS.LAMBDA.LLD.FILTER.REGION.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#AWS.LAMBDA.RUNTIME}'
                value: '{$AWS.LAMBDA.LLD.FILTER.RUNTIME.MATCHES}'
              - macro: '{#AWS.LAMBDA.RUNTIME}'
                value: '{$AWS.LAMBDA.LLD.FILTER.RUNTIME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Get Lambda functions.'
          host_prototypes:
            - uuid: 7b468bda682c402b96fd55210aa85155
              host: '{#AWS.LAMBDA.NAME}'
              name: '{#AWS.LAMBDA.NAME}'
              group_links:
                - group:
                    name: Applications
              templates:
                - name: 'AWS Lambda by HTTP'
              macros:
                - macro: '{$AWS.LAMBDA.ARN}'
                  value: '{#AWS.LAMBDA.ARN}'
                  description: 'The Amazon Resource Names (ARN) of the Lambda function.'
                - macro: '{$AWS.LAMBDA.NAME}'
                  value: '{#AWS.LAMBDA.NAME}'
                  description: 'Lambda function name.'
                - macro: '{$AWS.REGION}'
                  value: '{#AWS.LAMBDA.REGION}'
                  description: 'Lambda function region.'
              tags:
                - tag: name
                  value: '{#AWS.LAMBDA.NAME}'
                - tag: region
                  value: '{#AWS.LAMBDA.REGION}'
                - tag: runtime
                  value: '{#AWS.LAMBDA.RUNTIME}'
                - tag: service
                  value: lambda
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: describe_region
              value: '{$AWS.DESCRIBE.REGION}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region_match
              value: '{$AWS.LAMBDA.LLD.FILTER.REGION.MATCHES}'
            - name: region_not_match
              value: '{$AWS.LAMBDA.LLD.FILTER.REGION.NOT_MATCHES}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          lld_macro_paths:
            - lld_macro: '{#AWS.LAMBDA.ARN}'
              path: $.arn
            - lld_macro: '{#AWS.LAMBDA.NAME}'
              path: $.name
            - lld_macro: '{#AWS.LAMBDA.REGION}'
              path: $.region
            - lld_macro: '{#AWS.LAMBDA.RUNTIME}'
              path: $.runtime
            - lld_macro: '{#AWS.LAMBDA.VERSION}'
              path: $.version
        - uuid: c1127e674b7548b2802cd8771f3a4768
          name: 'RDS instances discovery'
          type: SCRIPT
          key: aws.rds.discovery
          delay: 12h
          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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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];
            				});
            		}
            		['describe_region', 'region_match', 'region_not_match'].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/, ''),
            			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' & !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 API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	listRegions: function () {
            		var payload = {
            			'Action': 'DescribeRegions',
            			'Version': '2016-11-15'
            		};
            
            		regions = AWS.getField(AWS.request('GET', AWS.params.describe_region, 'ec2', AWS.prepareParams(payload)), 'DescribeRegionsResponse.regionInfo.item');
            
            		if (!Array.isArray(regions))
            			regions = [regions]
            		return regions
            	},
            
            	listInstances: function () {
            		var lld_array = [],
            			regions = AWS.listRegions(),
            			payload = {
            				'Action': 'DescribeDBInstances',
            				'Version': '2014-10-31'
            			};
            
            		regions.forEach(function (region) {
            			var region_name = AWS.getField(region, 'regionName');
            			if (region_name.match(AWS.params.region_match) === null ||
            				region_name.match(AWS.params.region_not_match) !== null)
            				return;
            
            			result = AWS.request('GET', region_name, 'rds', AWS.prepareParams(payload));
            
            			databases = AWS.getField(result, 'DescribeDBInstancesResponse.DescribeDBInstancesResult.DBInstances')
            			if (!Array.isArray(databases))
            				databases = [databases]
            
            			databases.forEach(function (db) {
            				lld_array.push(
            					{
            						DBInstanceIdentifier: AWS.getField(db, 'DBInstanceIdentifier'),
            						instanceRegion: region_name
            					}
            				)
            			});
            		});
            
            		return lld_array;
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	return JSON.stringify(AWS.listInstances());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS RDS ] ERROR: ' + error);
            	return JSON.stringify({ 'error': error });
            }
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.RDS.INSTANCE.ID}'
                value: '{$AWS.RDS.LLD.FILTER.NAME.MATCHES}'
              - macro: '{#AWS.RDS.INSTANCE.ID}'
                value: '{$AWS.RDS.LLD.FILTER.NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#AWS.RDS.REGION}'
                value: '{$AWS.RDS.LLD.FILTER.REGION.MATCHES}'
              - macro: '{#AWS.RDS.REGION}'
                value: '{$AWS.RDS.LLD.FILTER.REGION.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Get RDS instances.'
          host_prototypes:
            - uuid: 799663c52a644f78aa3b3c14d4cc7235
              host: '{#AWS.RDS.INSTANCE.ID}'
              name: '{#AWS.RDS.INSTANCE.ID}'
              group_links:
                - group:
                    name: Databases
              templates:
                - name: 'AWS RDS instance by HTTP'
              macros:
                - macro: '{$AWS.RDS.INSTANCE.ID}'
                  value: '{#AWS.RDS.INSTANCE.ID}'
                  description: 'RDS instance ID.'
                - macro: '{$AWS.REGION}'
                  value: '{#AWS.RDS.REGION}'
                  description: 'RDS instance region.'
              tags:
                - tag: name
                  value: '{#AWS.RDS.INSTANCE.ID}'
                - tag: region
                  value: '{#AWS.RDS.REGION}'
                - tag: service
                  value: rds
              custom_interfaces: 'YES'
              interfaces:
                - ip: '{#AWS.RDS.INSTANCE.ID}'
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: describe_region
              value: '{$AWS.DESCRIBE.REGION}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region_match
              value: '{$AWS.RDS.LLD.FILTER.REGION.MATCHES}'
            - name: region_not_match
              value: '{$AWS.RDS.LLD.FILTER.REGION.NOT_MATCHES}'
            - name: role_arn
              value: '{$AWS.ASSUME.ROLE.ARN}'
            - name: SecretAccessKey
              value: '{$AWS.SECRET.ACCESS.KEY}'
            - name: sts_region
              value: '{$AWS.STS.REGION}'
          lld_macro_paths:
            - lld_macro: '{#AWS.RDS.INSTANCE.ID}'
              path: $.DBInstanceIdentifier
            - lld_macro: '{#AWS.RDS.REGION}'
              path: $.instanceRegion
        - uuid: ab6a97a108fb4dbc9fd1e07378721ffe
          name: 'S3 buckets discovery'
          type: SCRIPT
          key: aws.s3.discovery
          delay: 12h
          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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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];
            				});
            		}
            		['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 (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';
            
            		if (AWS.params.auth_type === 'role_base' || (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-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' & !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 API. Check debug log for more information.';
            			}
            		}
            
            		return response;
            	},
            
            	listBuckets: function () {
            		var payload = {
            			'Action': 'ListBuckets',
            			'Version': '2006-03-01'
            		};
            
            		var result = AWS.getField(AWS.request('GET', AWS.params.request_region, 's3', AWS.prepareParams(payload)), 'ListAllMyBucketsResult.Buckets');
            
            		if (result === null) {
            			return [];
            		}
            		result = AWS.getField(result, 'Bucket');
            
            		return Array.isArray(result) ? result : [result];
            
            	}
            
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	return JSON.stringify(AWS.listBuckets());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS S3 ] ERROR: ' + error);
            	return JSON.stringify({ 'error': error });
            }
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.S3.NAME}'
                value: '{$AWS.S3.LLD.FILTER.NAME.MATCHES}'
              - macro: '{#AWS.S3.NAME}'
                value: '{$AWS.S3.LLD.FILTER.NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Get S3 bucket instances.'
          host_prototypes:
            - uuid: e45bd9810ea14718b17b875aad3fc544
              host: '{#AWS.S3.NAME}'
              name: '{#AWS.S3.NAME}'
              group_links:
                - group:
                    name: Applications
              templates:
                - name: 'AWS S3 bucket by HTTP'
              macros:
                - macro: '{$AWS.S3.BUCKET.NAME}'
                  value: '{#AWS.S3.NAME}'
                  description: 'S3 bucket name.'
                - macro: '{$AWS.S3.FILTER.ID}'
                  value: '1'
                  description: 'S3 bucket requests filter identifier.'
              tags:
                - tag: name
                  value: '{#AWS.S3.NAME}'
                - tag: service
                  value: s3
              custom_interfaces: 'YES'
              interfaces:
                - ip: '{#AWS.S3.NAME}'
          timeout: '{$AWS.DATA.TIMEOUT}'
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - 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}'
          lld_macro_paths:
            - lld_macro: '{#AWS.S3.NAME}'
              path: $.Name
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: automation
        - tag: subclass
          value: computing
        - tag: subclass
          value: containers
        - tag: subclass
          value: deploy
        - tag: subclass
          value: security
        - tag: subclass
          value: virtualization
        - tag: target
          value: aws
      macros:
        - macro: '{$AWS.ACCESS.KEY.ID}'
          description: 'Access key ID.'
          config:
            type: TEXT
            priority: '2'
            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: '4'
            label: 'ARN assume role'
            description: 'ARN assume role; add when using the `assume_role` authorization method.'
        - 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'
            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: 'A response timeout for an API.'
          config:
            type: TEXT
            priority: '9'
            section_name: Other
            label: 'Response timeout'
            description: 'A response timeout for an API.'
        - macro: '{$AWS.DESCRIBE.REGION}'
          value: us-east-1
          description: 'Region used in POST request `DescribeRegions`.'
          config:
            type: TEXT
            priority: '7'
            label: 'Region `DescribeRegions`'
            description: 'Region Used in POST request `DescribeRegions`.'
        - macro: '{$AWS.EC2.LLD.FILTER.NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable EC2 instances by namespace.'
          config:
            type: TEXT
            priority: '10'
            section_name: Filters
            label: 'EC2 filter by namespace'
            description: 'Filter of discoverable EC2 instances by namespace.'
        - macro: '{$AWS.EC2.LLD.FILTER.NAME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered EC2 instances by namespace.'
          config:
            type: TEXT
            priority: '11'
            section_name: Filters
            label: 'EC2 filter by namespace (exclude)'
            description: 'Filter to exclude discovered EC2 instances by namespace.'
        - macro: '{$AWS.EC2.LLD.FILTER.REGION.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable EC2 instances by region.'
          config:
            type: TEXT
            priority: '12'
            section_name: Filters
            label: 'EC2 filter by region'
            description: 'Filter of discoverable EC2 instances by region.'
        - macro: '{$AWS.EC2.LLD.FILTER.REGION.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered EC2 instances by region.'
          config:
            type: TEXT
            priority: '13'
            section_name: Filters
            label: 'EC2 filter by region (exclude)'
            description: 'Filter to exclude discovered EC2 instances by region.'
        - macro: '{$AWS.ECS.LLD.FILTER.NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable ECS clusters by name.'
          config:
            type: TEXT
            priority: '14'
            section_name: Filters
            label: 'ECS filter by name'
            description: 'Filter of discoverable ECS clusters by name.'
        - macro: '{$AWS.ECS.LLD.FILTER.NAME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered ECS clusters by name.'
          config:
            type: TEXT
            priority: '15'
            section_name: Filters
            label: 'ECS filter by name (exclude)'
            description: 'Filter to exclude discovered ECS clusters by name.'
        - macro: '{$AWS.ECS.LLD.FILTER.REGION.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable ECS clusters by region.'
          config:
            type: TEXT
            priority: '24'
            section_name: Filters
            label: 'ECS filter by region'
            description: 'Filter of discoverable ECS clusters by region.'
        - macro: '{$AWS.ECS.LLD.FILTER.REGION.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered ECS clusters by region.'
          config:
            type: TEXT
            priority: '25'
            section_name: Filters
            label: 'ECS filter by region (exclude)'
            description: 'Filter to exclude discovered ECS clusters by region.'
        - macro: '{$AWS.ECS.LLD.FILTER.STATUS.MATCHES}'
          value: ACTIVE
          description: 'Filter of discoverable ECS clusters by status.'
          config:
            type: TEXT
            priority: '16'
            section_name: Filters
            label: 'ECS filter by status'
            description: 'Filter of discoverable ECS clusters by status.'
        - macro: '{$AWS.ECS.LLD.FILTER.STATUS.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered ECS clusters by status.'
          config:
            type: TEXT
            priority: '17'
            section_name: Filters
            label: 'ECS filter by status (exclude)'
            description: 'Filter to exclude discovered ECS clusters by status.'
        - macro: '{$AWS.ELB.LLD.FILTER.NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable ELB load balancers by name.'
          config:
            type: TEXT
            priority: '26'
            section_name: Filters
            label: 'ELB filter by name'
            description: 'Filter of discoverable ELB load balancers by name.'
        - macro: '{$AWS.ELB.LLD.FILTER.NAME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered ELB load balancers by name.'
          config:
            type: TEXT
            priority: '27'
            section_name: Filters
            label: 'ELB filter by name (exclude)'
            description: 'Filter to exclude discovered ELB load balancers by name.'
        - macro: '{$AWS.ELB.LLD.FILTER.REGION.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable ELB load balancers by region.'
          config:
            type: TEXT
            priority: '28'
            section_name: Filters
            label: 'ELB filter by region'
            description: 'Filter of discoverable ELB load balancers by region.'
        - macro: '{$AWS.ELB.LLD.FILTER.REGION.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered ELB load balancers by region.'
          config:
            type: TEXT
            priority: '29'
            section_name: Filters
            label: 'ELB filter by region (exclude)'
            description: 'Filter to exclude discovered ELB load balancers by region.'
        - macro: '{$AWS.ELB.LLD.FILTER.STATE.MATCHES}'
          value: active
          description: 'Filter of discoverable ELB load balancers by status.'
          config:
            type: TEXT
            priority: '30'
            section_name: Filters
            label: 'ELB filter by status'
            description: 'Filter of discoverable ELB load balancers by status.'
        - macro: '{$AWS.ELB.LLD.FILTER.STATE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered ELB load balancer by status.'
          config:
            type: TEXT
            priority: '31'
            section_name: Filters
            label: 'ELB filter by status (exclude)'
            description: 'Filter to exclude discovered ELB load balancer by status.'
        - macro: '{$AWS.LAMBDA.LLD.FILTER.NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable Lambda functions by name.'
          config:
            type: TEXT
            priority: '36'
            section_name: Filters
            label: 'Lambda filter by name'
            description: 'Filter of discoverable Lambda functions by name.'
        - macro: '{$AWS.LAMBDA.LLD.FILTER.NAME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered Lambda functions by name.'
          config:
            type: TEXT
            priority: '37'
            section_name: Filters
            label: 'Lambda filter by name (exclude)'
            description: 'Filter to exclude discovered Lambda functions by name.'
        - macro: '{$AWS.LAMBDA.LLD.FILTER.REGION.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable Lambda functions by region.'
          config:
            type: TEXT
            priority: '32'
            section_name: Filters
            label: 'Lambda filter by region'
            description: 'Filter of discoverable Lambda functions by region.'
        - macro: '{$AWS.LAMBDA.LLD.FILTER.REGION.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered Lambda functions by region.'
          config:
            type: TEXT
            priority: '33'
            section_name: Filters
            label: 'Lambda filter by region (exclude)'
            description: 'Filter to exclude discovered Lambda functions by region.'
        - macro: '{$AWS.LAMBDA.LLD.FILTER.RUNTIME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable Lambda functions by Runtime.'
          config:
            type: TEXT
            priority: '34'
            section_name: Filters
            label: 'Lambda filter by Runtime'
            description: 'Filter of discoverable Lambda functions by Runtime.'
        - macro: '{$AWS.LAMBDA.LLD.FILTER.RUNTIME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered Lambda functions by Runtime.'
          config:
            type: TEXT
            priority: '35'
            section_name: Filters
            label: 'Lambda filter by Runtime (exclude)'
            description: 'Filter to exclude discovered Lambda functions by Runtime.'
        - macro: '{$AWS.PROXY}'
          description: 'Sets HTTP proxy value. If this macro is empty then no proxy is used.'
          config:
            type: TEXT
            priority: '5'
            section_name: Other
            label: 'HTTP proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AWS.RDS.LLD.FILTER.NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable RDS instances by namespace.'
          config:
            type: TEXT
            priority: '20'
            section_name: Filters
            label: 'RDS filter by namespace'
            description: 'Filter of discoverable RDS instances by namespace.'
        - macro: '{$AWS.RDS.LLD.FILTER.NAME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered RDS instances by namespace.'
          config:
            type: TEXT
            priority: '21'
            section_name: Filters
            label: 'RDS filter by namespace (exclude)'
            description: 'Filter to exclude discovered RDS instances by namespace.'
        - macro: '{$AWS.RDS.LLD.FILTER.REGION.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable RDS instances by region.'
          config:
            type: TEXT
            priority: '22'
            section_name: Filters
            label: 'RDS filter by region'
            description: 'Filter of discoverable RDS instances by region.'
        - macro: '{$AWS.RDS.LLD.FILTER.REGION.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered RDS instances by region.'
          config:
            type: TEXT
            priority: '23'
            section_name: Filters
            label: 'RDS filter by region (exclude)'
            description: 'Filter to exclude discovered RDS instances by region.'
        - macro: '{$AWS.REQUEST.REGION}'
          value: us-east-1
          description: 'Region used in GET request `ListBuckets`.'
          config:
            type: TEXT
            priority: '6'
            label: 'Region `ListBuckets`'
            description: 'Region Used in GET request `ListBuckets`.'
        - macro: '{$AWS.S3.LLD.FILTER.NAME.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable S3 buckets by namespace.'
          config:
            type: TEXT
            priority: '18'
            section_name: Filters
            label: 'S3 filter by namespace'
            description: 'Filter of discoverable S3 buckets by namespace.'
        - macro: '{$AWS.S3.LLD.FILTER.NAME.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered S3 buckets by namespace.'
          config:
            type: TEXT
            priority: '19'
            section_name: Filters
            label: 'S3 filter by namespace (exclude)'
            description: 'Filter to exclude discovered S3 buckets by namespace.'
        - macro: '{$AWS.SECRET.ACCESS.KEY}'
          type: SECRET_TEXT
          description: 'Secret access key.'
          config:
            type: TEXT
            priority: '3'
            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: 'Region Used in assume role request.'
    - uuid: dce23cdaef364e139efa580d8a304ffe
      template: 'AWS Cost Explorer by HTTP'
      name: 'AWS Cost Explorer by HTTP'
      description: |
        The template gets AWS Cost Explorer metrics and uses the script item to make HTTP requests to the Cost Explorer API.
        The Cost Explorer API can access the historical data over up to 12 months and the data for current month.
        Don't forget to read the README.md for the correct setup of the template.
        
        You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
        
        Generated by official Zabbix template tool "Templator"
      wizard_ready: 'YES'
      readme: |
        ## Overview
        
        The template to monitor AWS Cost Explorer by HTTP via Zabbix, which 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 Cost Explorer API calls to list and retrieve metrics.
        For more information, please refer to the [Cost Explorer pricing](https://aws.amazon.com/aws-cost-management/aws-cost-explorer/pricing/) page.
        
        
        ## Setup
        
        Before using the template, you need to create an IAM policy for the Zabbix role in your AWS account with the necessary permissions.
        
        * [IAM policies for AWS Cost Management](https://docs.aws.amazon.com/cost-management/latest/userguide/billing-permissions-ref.html)
        
        ### Required Permissions
        Add the following required permissions to your Zabbix IAM policy in order to collect metrics.
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Action": [
                        "ce:GetDimensionValues",
                        "ce:GetCostAndUsage"
                    ],
                    "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 `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": [
                        "ce:GetDimensionValues",
                        "ce:GetCostAndUsage"
                    ],
                    "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, add the appropriate permissions:
        
        ```json
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": "iam:PassRole",
                    "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
                },
                {
                    "Effect": "Allow",
                    "Action": [
                        "ce:GetDimensionValues",
                        "ce:GetCostAndUsage",
                        "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.
        
        Choose a method of authorization (field of `Authorization method`).
        
        For more information about managing access keys, see the [official documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).
        
        Also, see the Macros section for a list of macros used in LLD filters.
        
        Additional information about metrics and used API methods:
        
        * [Describe AWS Cost Explore API actions](https://docs.aws.amazon.com/aws-cost-management/latest/APIReference/API_Operations.html)
      vendor:
        name: Zabbix
        version: 7.4-2
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 5bfda2617dfc43edbe524a5c44b39f18
          name: 'Get daily costs'
          type: SCRIPT
          key: aws.get.daily.costs
          delay: 0s;h/6
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: "' + field + '".';
            			}
            			AWS.params[field] = params[field];
            		});
            
            		today = new Date();
            		AWS.params.end_date = today.toDateString();
            		today.setDate(today.getDate() - 1);
            		AWS.params.start_time = today.toDateString();
            	},
            
            	sign: function (key, message) {
            		var hex = hmac('sha256', key, message);
            
            		if ((hex.length % 2) === 1) {
            			throw 'Invalid length of a hex string!';
            		}
            
            		var result = new Int8Array(hex.length / 2);
            		for (var i = 0, b = 0; i < hex.length; i += 2, b++) {
            			result[b] = parseInt(hex.substring(i, i + 2), 16);
            		}
            
            		return result;
            	},
            
            	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('&');
            	},
            
            	getField: function (data, path) {
            		var steps = path.split('.');
            		for (var i = 0; i < steps.length; i++) {
            			var step = steps[i];
            			if (typeof data !== 'object' || typeof data[step] === 'undefined') {
            				throw 'Required field was not found: ' + path;
            			}
            			data = data[step];
            		}
            
            		return data;
            
            	},
            
            	request: function (method, region, service, params, data, target) {
            		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/, ''),
            			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-amz-json-1.1');
            		request.addHeader('Content-Encoding: amz-1.0');
            		request.addHeader('X-Amz-Target: ' + target);
            		request.addHeader('Authorization: ' + 'AWS4-HMAC-SHA256 Credential=' + AWS.params.AccessKeyId + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + hmac('sha256', key, request_string));
            		if (AWS.params.auth_type === 'role_base' || (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 Billing ] Sending request: ' + url);
            		response = request.post(url, data);
            		Zabbix.log(4, '[ AWS Billing ] Received response with the status code ' + request.getStatus() + ': ' + response);
            
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with the status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse the response received from AWS API. Check debug log for more information.';
            		}
            
            		return response;
            	},
            
            	getDimensionValues: function () {
            		var body_raw_dimension = {
            			'TimePeriod': {
            				'Start': AWS.params.start_time,
            				'End': AWS.params.end_date
            			},
            			'Dimension': 'SERVICE'
            		};
            		return AWS.getField(AWS.request('POST', AWS.params.region, 'ce', '', body_raw_dimension, 'AWSInsightsIndexService.GetDimensionValues'), 'DimensionValues');
            
            	},
            
            	getCostAndUsage: function () {
            		var body_raw_cost = {
            
            			'TimePeriod': {
            				'Start': AWS.params.start_time,
            				'End': AWS.params.end_date
            			},
            			'Granularity': 'DAILY',
            			'DimensionValues': AWS.getDimensionValues(),
            			'GroupBy': [
            				{
            					'Type': 'DIMENSION',
            					'Key': 'SERVICE'
            				}
            			],
            			'Metrics': ['BlendedCost']
            		};
            
            		return AWS.getField(AWS.request('POST', AWS.params.region, 'ce', '', body_raw_cost, 'AWSInsightsIndexService.GetCostAndUsage'), 'ResultsByTime');
            
            	}
            
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	return JSON.stringify(AWS.getCostAndUsage());
            
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS Billing ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: 'Get raw data on the daily costs by service.'
          preprocessing:
            - type: CHECK_NOT_SUPPORTED
              parameters:
                - '-1'
          timeout: 15s
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.BILLING.REGION}'
            - name: 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: 7139ce562d3c439e9686ad5b17ed0f1c
          name: 'Get monthly costs'
          type: SCRIPT
          key: aws.get.monthly.costs
          delay: 0s;h9
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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', 'month'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: "' + field + '".';
            			}
            			AWS.params[field] = params[field];
            		});
            
            		today = new Date();
            		AWS.params.end_date = today.toDateString();
            		month = today.getMonth();
            		today.setMonth(month - params.month);
            		AWS.params.start_time = new Date(today.getFullYear(), today.getMonth()).toDateString();
            	},
            
            	sign: function (key, message) {
            		var hex = hmac('sha256', key, message);
            
            		if ((hex.length % 2) === 1) {
            			throw 'Invalid length of a hex string!';
            		}
            
            		var result = new Int8Array(hex.length / 2);
            		for (var i = 0, b = 0; i < hex.length; i += 2, b++) {
            			result[b] = parseInt(hex.substring(i, i + 2), 16);
            		}
            
            		return result;
            	},
            
            	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('&');
            	},
            
            	getField: function (data, path) {
            		var steps = path.split('.');
            		for (var i = 0; i < steps.length; i++) {
            			var step = steps[i];
            			if (typeof data !== 'object' || typeof data[step] === 'undefined') {
            				throw 'Required field was not found: ' + path;
            			}
            			data = data[step];
            		}
            
            		return data;
            
            	},
            
            	request: function (method, region, service, params, data, target) {
            		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/, ''),
            			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-amz-json-1.1');
            		request.addHeader('Content-Encoding: amz-1.0');
            		request.addHeader('X-Amz-Target: ' + target);
            		request.addHeader('Authorization: ' + 'AWS4-HMAC-SHA256 Credential=' + AWS.params.AccessKeyId + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + hmac('sha256', key, request_string));
            		if (AWS.params.auth_type === 'role_base' || (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 Billing ] Sending request: ' + url);
            		response = request.post(url, data);
            		Zabbix.log(4, '[ AWS Billing ] Received response with the status code ' + request.getStatus() + ': ' + response);
            
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with the status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse the response received from AWS API. Check debug log for more information.';
            		}
            
            		return response;
            	},
            
            	getDimensionValues: function () {
            		var body_raw_dimension = {
            			'TimePeriod': {
            				'Start': AWS.params.start_time,
            				'End': AWS.params.end_date
            			},
            			'Dimension': 'SERVICE'
            		};
            		return AWS.getField(AWS.request('POST', AWS.params.region, 'ce', '', body_raw_dimension, 'AWSInsightsIndexService.GetDimensionValues'), 'DimensionValues');
            
            	},
            
            	getCostMonth: function () {
            		var body_raw_cost = {
            			'TimePeriod': {
            				'Start': AWS.params.start_time,
            				'End': AWS.params.end_date
            			},
            			'Granularity': 'MONTHLY',
            			'Metrics': ['BlendedCost']
            		};
            		result = AWS.getField(AWS.request('POST', AWS.params.region, 'ce', '', body_raw_cost, 'AWSInsightsIndexService.GetCostAndUsage'), 'ResultsByTime');
            
            		return result.map(function (data) {
            			return {
            				'amount': AWS.getField(data, 'Total.BlendedCost.Amount'),
            				'unit': AWS.getField(data, 'Total.BlendedCost.Unit'),
            				'month': AWS.getField(data, 'TimePeriod.Start').slice(0, 7)
            			};
            		});
            	},
            
            	getCostMonthService: function () {
            		var body_raw_cost = {
            			'TimePeriod': {
            				'Start': AWS.params.start_time,
            				'End': AWS.params.end_date
            			},
            			'DimensionValues': AWS.getDimensionValues(),
            			'GroupBy': [
            				{
            					'Type': 'DIMENSION',
            					'Key': 'SERVICE'
            				}
            			],
            			'Granularity': 'MONTHLY',
            			'Metrics': ['BlendedCost']
            		};
            		MetricData = AWS.getField(AWS.request('POST', AWS.params.region, 'ce', '', body_raw_cost, 'AWSInsightsIndexService.GetCostAndUsage'), 'ResultsByTime');
            		var services = [];
            		MetricData.forEach(function (data) {
            			month = AWS.getField(data, 'TimePeriod.Start').slice(0, 7);
            			groups = AWS.getField(data, 'Groups');
            			groups.forEach(function (group) {
            				group.month = month;
            				services.push(group);
            			})
            		});
            
            		return services;
            
            	}
            
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	monthly_costs = AWS.getCostMonth();
            	monthly_service_costs = AWS.getCostMonthService();
            
            	return JSON.stringify({ monthly_costs, monthly_service_costs });
            
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS Billing ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: 'Get raw data on the monthly costs by service.'
          preprocessing:
            - type: CHECK_NOT_SUPPORTED
              parameters:
                - '-1'
          timeout: 15s
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: month
              value: '{$AWS.BILLING.MONTH}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.BILLING.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
      discovery_rules:
        - uuid: 5773c41da90d4a38aff02fccec733741
          name: 'AWS monthly costs by services discovery'
          type: DEPENDENT
          key: aws.cost.service.monthly.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.BILLING.SERVICE.NAME}'
                value: '{$AWS.BILLING.LLD.FILTER.SERVICE.MATCHES}'
              - macro: '{#AWS.BILLING.SERVICE.NAME}'
                value: '{$AWS.BILLING.LLD.FILTER.SERVICE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery of monthly costs by services.'
          item_prototypes:
            - uuid: d01ee8df0e204f1a857b8188df47402a
              name: '[{#AWS.BILLING.SERVICE.NAME}]: Month [{#AWS.BILLING.MONTH}] Blended cost'
              type: DEPENDENT
              key: 'aws.monthly.service.cost["{#AWS.BILLING.SERVICE.NAME}", "{#AWS.BILLING.MONTH}"]'
              value_type: FLOAT
              units: '{#AWS.BILLING.UNIT}'
              description: 'The monthly cost by service {#AWS.BILLING.SERVICE.NAME}.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.monthly_service_costs.[?(@.month == "{#AWS.BILLING.MONTH}")]'
                  error_handler: DISCARD_VALUE
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Keys =~ "{#AWS.BILLING.SERVICE.NAME}")]..Metrics.BlendedCost.Amount.first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.get.monthly.costs
              tags:
                - tag: component
                  value: billing
                - tag: month
                  value: '{#AWS.BILLING.MONTH}'
                - tag: service
                  value: '{#AWS.BILLING.SERVICE.NAME}'
          graph_prototypes:
            - uuid: b267e0ae08d34a7dae730848577aea68
              name: 'AWS Cost: [{#AWS.BILLING.SERVICE.NAME}]: Month [{#AWS.BILLING.MONTH}] Blended cost'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2E7D32
                  item:
                    host: 'AWS Cost Explorer by HTTP'
                    key: 'aws.monthly.service.cost["{#AWS.BILLING.SERVICE.NAME}", "{#AWS.BILLING.MONTH}"]'
          master_item:
            key: aws.get.monthly.costs
          lld_macro_paths:
            - lld_macro: '{#AWS.BILLING.MONTH}'
              path: $..month.first()
            - lld_macro: '{#AWS.BILLING.SERVICE.NAME}'
              path: $..Keys.first().first()
            - lld_macro: '{#AWS.BILLING.UNIT}'
              path: $..Metrics.BlendedCost.Unit.first()
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.monthly_service_costs
        - uuid: 6e65d15251ea4355ac41ed7956f9e5b0
          name: 'AWS daily costs by services discovery'
          type: DEPENDENT
          key: aws.daily.services.costs.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.BILLING.SERVICE.NAME}'
                value: '{$AWS.BILLING.LLD.FILTER.SERVICE.MATCHES}'
              - macro: '{#AWS.BILLING.SERVICE.NAME}'
                value: '{$AWS.BILLING.LLD.FILTER.SERVICE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery of daily blended costs by services.'
          item_prototypes:
            - uuid: b6e121c3a1eb49858e942beab12660e2
              name: 'Service [{#AWS.BILLING.SERVICE.NAME}]: Blended daily cost'
              type: DEPENDENT
              key: 'aws.daily.service.cost["{#AWS.BILLING.SERVICE.NAME}"]'
              value_type: FLOAT
              units: '{#AWS.BILLING.UNIT}'
              description: 'The daily blended cost of the {#AWS.BILLING.SERVICE.NAME} service for the previous day.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$..Groups..[?(@.Keys =~ "{#AWS.BILLING.SERVICE.NAME}")]..Metrics.BlendedCost.Amount.first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.get.daily.costs
              tags:
                - tag: component
                  value: billing
                - tag: service
                  value: '{#AWS.BILLING.SERVICE.NAME}'
          graph_prototypes:
            - uuid: 71646982ab55405dbc10f200e8050c93
              name: 'AWS Cost: Service [{#AWS.BILLING.SERVICE.NAME}]: Blended daily cost'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2E7D32
                  item:
                    host: 'AWS Cost Explorer by HTTP'
                    key: 'aws.daily.service.cost["{#AWS.BILLING.SERVICE.NAME}"]'
          master_item:
            key: aws.get.daily.costs
          lld_macro_paths:
            - lld_macro: '{#AWS.BILLING.SERVICE.NAME}'
              path: $..Keys.first().first()
            - lld_macro: '{#AWS.BILLING.UNIT}'
              path: $..Metrics.BlendedCost.Unit.first()
          preprocessing:
            - type: JSONPATH
              parameters:
                - $..Groups.first()
        - uuid: b554f00ba68e4ea391f7c7d029efde4f
          name: 'AWS monthly costs discovery'
          type: DEPENDENT
          key: aws.monthly.cost.discovery
          description: 'Discovery of monthly costs.'
          item_prototypes:
            - uuid: aaf85a53d1804c858fc20189f0483bad
              name: '[{#AWS.BILLING.MONTH}]: Blended cost per month'
              type: DEPENDENT
              key: 'aws.monthly.cost["{#AWS.BILLING.MONTH}"]'
              value_type: FLOAT
              units: '{#AWS.BILLING.UNIT}'
              description: 'The blended cost by month {#AWS.BILLING.MONTH}.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.monthly_costs.[?(@.month == "{#AWS.BILLING.MONTH}")].amount.first()'
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: aws.get.monthly.costs
              tags:
                - tag: component
                  value: billing
                - tag: month
                  value: '{#AWS.BILLING.MONTH}'
          graph_prototypes:
            - uuid: 3e01a98ed70149e3a6a083bb103aa496
              name: 'AWS Cost: [{#AWS.BILLING.MONTH}]: Monthly blended cost'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2E7D32
                  item:
                    host: 'AWS Cost Explorer by HTTP'
                    key: 'aws.monthly.cost["{#AWS.BILLING.MONTH}"]'
          master_item:
            key: aws.get.monthly.costs
          lld_macro_paths:
            - lld_macro: '{#AWS.BILLING.MONTH}'
              path: $..month.first()
            - lld_macro: '{#AWS.BILLING.UNIT}'
              path: $..unit.first()
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.monthly_costs
      tags:
        - tag: class
          value: cloud
        - tag: target
          value: aws
      macros:
        - macro: '{$AWS.ACCESS.KEY.ID}'
          description: 'Access key ID.'
          config:
            type: TEXT
            priority: '2'
            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: '4'
            label: 'ARN assume role'
            description: 'The ARN of the role to assume when using the assume_role method.'
        - 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'
            required: 'YES'
            options:
              - value: access_key
                text: 'Access key'
              - value: assume_role
                text: AssumeRole
              - value: role_base
                text: 'Role-based access'
        - macro: '{$AWS.BILLING.LLD.FILTER.SERVICE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable discovered billing service by name.'
          config:
            type: TEXT
            priority: '9'
            section_name: Filters
            label: 'Service Filter (Matches)'
            description: 'A regex pattern to include services in discovery.'
        - macro: '{$AWS.BILLING.LLD.FILTER.SERVICE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered billing service by name.'
          config:
            type: TEXT
            priority: '10'
            section_name: Filters
            label: 'Service Filter (Not Matches)'
            description: 'A regex pattern to exclude services from discovery.'
        - macro: '{$AWS.BILLING.MONTH}'
          value: '11'
          description: 'Months to get historical data from AWS Cost Explore API, no more than 12 months.'
          config:
            type: TEXT
            priority: '8'
            label: 'Billing Month'
            description: 'The number of months to retrieve historical billing data (maximum 12). In the range from 1 to 12 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AWS.BILLING.REGION}'
          value: us-east-1
          description: 'Amazon Billing region code.'
          config:
            type: TEXT
            priority: '7'
            label: 'Billing Region'
            description: 'The AWS region for billing data retrieval.'
        - macro: '{$AWS.PROXY}'
          description: 'Sets HTTP proxy value. If this macro is empty, then no proxy is used.'
          config:
            type: TEXT
            priority: '5'
            section_name: Other
            label: 'HTTP Proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AWS.SECRET.ACCESS.KEY}'
          type: SECRET_TEXT
          description: 'Secret access key.'
          config:
            type: TEXT
            priority: '3'
            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: '6'
            label: 'STS Region'
            description: 'The AWS region for the assume role request.'
      dashboards:
        - uuid: e1e4edbf129142b4b27a9471db1ed8e2
          name: 'Overview AWS Costs'
          pages:
            - name: 'Monthly costs'
              widgets:
                - type: graphprototype
                  width: '72'
                  height: '25'
                  fields:
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'AWS Cost Explorer by HTTP'
                        name: 'AWS Cost: [{#AWS.BILLING.MONTH}]: Monthly blended cost'
                    - type: STRING
                      name: reference
                      value: AAAAA
                    - type: INTEGER
                      name: rows
                      value: '6'
            - name: 'Monthly costs by service'
              widgets:
                - type: graphprototype
                  width: '72'
                  height: '25'
                  fields:
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'AWS Cost Explorer by HTTP'
                        name: 'AWS Cost: [{#AWS.BILLING.SERVICE.NAME}]: Month [{#AWS.BILLING.MONTH}] Blended cost'
                    - type: STRING
                      name: reference
                      value: AAAAB
                    - type: INTEGER
                      name: rows
                      value: '6'
            - name: 'Daily costs by service'
              widgets:
                - type: graphprototype
                  width: '72'
                  height: '20'
                  fields:
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'AWS Cost Explorer by HTTP'
                        name: 'AWS Cost: Service [{#AWS.BILLING.SERVICE.NAME}]: Blended daily cost'
                    - type: STRING
                      name: reference
                      value: AAAAC
                    - type: INTEGER
                      name: rows
                      value: '5'
    - 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 macros `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 manage access keys, see [official documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys)
        
        Also, see the Macros section for a list of macros used for LLD filters.
      vendor:
        name: Zabbix
        version: 7.4-2
      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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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;
                	},
                
                	setParams: function (params) {
                		AWS.params['proxy'] = params.proxy;
                		switch (AWS.getField(params, 'auth_type')) {
                			case 'role_base':
                				AWS.params['auth_type'] = 'role_base';
                				var request = new HttpRequest();
                				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
                					request.setProxy(AWS.params.proxy);
                				}
                				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];
                				});
                				break;
                			case 'assume_role':
                				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];
                				});
                
                				role_arn_regex = /role\/(.+)$/;
                
                				var payload = {
                					'Action': 'AssumeRole',
                					'Version': '2011-06-15',
                					'RoleArn': AWS.params.role_arn,
                					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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: '2'
            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: '4'
            label: 'ARN assume role'
            description: 'The ARN of the role to assume when using the assume_role authorization method.'
        - 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'
            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: '20'
            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: '19'
            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: '18'
            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: '16'
            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: '17'
            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: '15'
            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: '8'
            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: '13'
            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: '14'
            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: '11'
            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: '12'
            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: '9'
            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: '10'
            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: '7'
            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: '5'
            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: '3'
            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: '6'
            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: c94105c23220452baed03ba87f09ca12
      template: 'AWS ECS Cluster by HTTP'
      name: 'AWS ECS Cluster by HTTP'
      description: |
        The template gets AWS ECS Cluster metrics and uses the script item to make HTTP requests to the CloudWatch API.
        Don't forget to read the README.md for the correct setup of the template.
        
        You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
        
        Generated by official Zabbix template tool "Templator"
      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 macros `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 macros `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)
        
        Refer to the Macros section for a list of macros used for LLD filters.
      vendor:
        name: Zabbix
        version: 7.4-2
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 9c4a894d46174d679c58c9a1339dec2f
          name: 'Get alarms check'
          type: DEPENDENT
          key: aws.ecs.alarms.check
          value_type: CHAR
          description: 'Data collection check.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.ecs.get_alarms
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: f8ff542b35a345e490910323d5dee19c
              expression: 'length(last(/AWS ECS Cluster by HTTP/aws.ecs.alarms.check))>0'
              name: 'AWS ECS Cluster: 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: c9d2dff2619d41c1a0d1a528fecab461
          name: 'Container Instance Count'
          type: DEPENDENT
          key: aws.ecs.container_instance_count
          value_type: FLOAT
          description: 'The number of EC2 instances running the Amazon ECS agent that are registered with a cluster.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.MetricData[?(@.Label == "ContainerInstanceCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: system
        - uuid: 161886f00f91479597db4bfaae27db46
          name: 'CPU Reserved'
          type: DEPENDENT
          key: aws.ecs.cpu_reserved
          value_type: FLOAT
          description: |
            A number of CPU units reserved by tasks in the resource that is specified by the dimension set that you're using.
            This metric is only collected for tasks that have a defined CPU reservation in their task definition.
          valuemap:
            name: 'CPU Reserved'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.[?(@.Label == "CpuReserved")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: cpu
        - uuid: fc4c44d533304ac3a4f59773c7424324
          name: 'CPU Utilization'
          type: DEPENDENT
          key: aws.ecs.cpu_utilization
          value_type: FLOAT
          units: '%'
          description: 'Cluster CPU utilization'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.CPUUtilization
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: cpu
          triggers:
            - uuid: 5395c1d6d27c495a8972d2ea8ca8b02a
              expression: 'min(/AWS ECS Cluster by HTTP/aws.ecs.cpu_utilization,15m)>{$AWS.ECS.CLUSTER.CPU.UTIL.WARN}'
              name: 'AWS ECS Cluster: High CPU utilization'
              event_name: 'AWS ECS Cluster: High CPU utilization (over {$AWS.ECS.CLUSTER.CPU.UTIL.WARN}% for 15m)'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The CPU utilization is too high. The system might be slow to respond.'
              tags:
                - tag: scope
                  value: capacity
                - tag: scope
                  value: performance
        - uuid: 9aefed8b23ee41a7941e41f33fc95ebe
          name: 'Get alarms data'
          type: SCRIPT
          key: aws.ecs.get_alarms
          delay: 0s;m/1
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	getField: function (data, path) {
            		var steps = path.split('.');
            		for (var i = 0; i < steps.length; i++) {
            			var step = steps[i];
            			if (typeof data !== 'object' || typeof data[step] === 'undefined') {
            				throw 'Required field was not found: ' + path;
            			}
            
            			data = data[step];
            		}
            
            		return data;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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: fa8f1dc24615438e98cbad686d40eaf7
          name: 'Get cluster services'
          type: SCRIPT
          key: aws.ecs.get_cluster_services
          delay: 5m
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	metadata: 'http://169.254.169.254/latest/',
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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',
            			'cluster': AWS.params.cluster_name
            		},
            			services = [];
            
            		ECSClusters_Services = AWS.getField(AWS.request('GET', AWS.params.region, 'ecs', AWS.prepareParams(payload)), 'ListServicesResponse.ListServicesResult.serviceArns');
            
            		for (k in ECSClusters_Services) {
            			id = ECSClusters_Services[k];
            
            			json = {};
            			input = id.split(AWS.params.cluster_name + '/');
            			for (var i = 1; i < input.length; i += 2) {
            				json[input[i]] = input[i + 1];
            			}
            			services.push({
            				'service_name': input[1],
            			});
            		}
            
            		if (Array.isArray(services))
            			return services;
            		else
            			return [services];
            	}
            };
            
            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: 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: f45389a638c645f8905dc69d6cafb8b3
          name: 'Get cluster metrics'
          type: SCRIPT
          key: aws.ecs.get_metrics
          delay: 0s;m/1
          history: '0'
          value_type: TEXT
          params: |
            var AWS = {
            	params: {},
            	request_period: 600,
            	metadata: 'http://169.254.169.254/latest/',
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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'
            		];
            
            		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' & !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'],
            			end_time = new Date(timestamp).toISOString().replace(/\.\d+Z/, 'Z'),
            			start_time = new Date(timestamp - AWS.request_period * 1000).toISOString().replace(/\.\d+Z/, 'Z'),
            			payload = AWS.prepareRecursive('MetricDataQueries', AWS.renderPayload(AWS.request_period, AWS.params.cluster_name));
            
            		payload['Action'] = 'GetMetricData';
            		payload['Version'] = '2010-08-01';
            		payload['StartTime'] = start_time;
            		payload['EndTime'] = end_time;
            		payload['ScanBy'] = 'TimestampDescending';
            
            		result = AWS.request('GET', AWS.params.region, 'monitoring', AWS.prepareParams(payload));
            		MetricData = AWS.getField(result, 'GetMetricDataResponse.GetMetricDataResult.MetricDataResults')
            
            		MetricData.forEach(function (id) {
            			for (i in metrics) {
            				if (AWS.getField(id, 'Label') === metrics[i]) {
            					obj[metrics[i]] = AWS.getField(id, 'Values');
            				}
            			}
            		});
            		CPUUtilization = Math.abs(obj.CpuUtilized * 100 / obj.CpuReserved);
            		MemoryUtilization = Math.abs(obj.MemoryUtilized * 100 / obj.MemoryReserved);
            		return ({ MetricData, MemoryUtilization, CPUUtilization, DiskUtilization });
            	}
            };
            
            try {
            	AWS.setParams(JSON.parse(value));
            
            	return JSON.stringify(AWS.getMetricsData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AWS ECS ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: |
            Get cluster metrics.
            Full metrics list related to ECS: https://docs.aws.amazon.com/AmazonECS/latest/userguide/metrics-dimensions.html
          preprocessing:
            - type: CHECK_NOT_SUPPORTED
              parameters:
                - '-1'
          timeout: 15s
          parameters:
            - name: AccessKeyId
              value: '{$AWS.ACCESS.KEY.ID}'
            - name: auth_type
              value: '{$AWS.AUTH_TYPE}'
            - name: cluster_name
              value: '{$AWS.ECS.CLUSTER.NAME}'
            - name: proxy
              value: '{$AWS.PROXY}'
            - name: region
              value: '{$AWS.REGION}'
            - name: 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: 0e1c53da0225410ea835f5d471afac13
          name: 'Memory Utilization'
          type: DEPENDENT
          key: aws.ecs.memory_utilization
          value_type: FLOAT
          units: '%'
          description: |
            The memory being used by tasks in the resource that is specified by the dimension set that you're using.
            This metric is only collected for tasks that have a defined memory reservation in their task definition.
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.MemoryUtilization
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: memory
          triggers:
            - uuid: a7df755466704f339e5479aeeca3fe30
              expression: 'min(/AWS ECS Cluster by HTTP/aws.ecs.memory_utilization,15m)>{$AWS.ECS.CLUSTER.MEMORY.UTIL.WARN}'
              name: 'AWS ECS Cluster: High memory utilization'
              event_name: 'AWS ECS Cluster: High memory utilization (over {$AWS.ECS.CLUSTER.MEMORY.UTIL.WARN}% for 15m)'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The system is running out of free memory.'
              tags:
                - tag: scope
                  value: capacity
                - tag: scope
                  value: performance
        - uuid: a214cef0377b4901afc2cb90186e5e46
          name: 'Get metrics check'
          type: DEPENDENT
          key: aws.ecs.metrics.check
          value_type: CHAR
          description: 'Data collection check.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: b475c468dbe0477f92b40122321235b0
              expression: 'length(last(/AWS ECS Cluster by HTTP/aws.ecs.metrics.check))>0'
              name: 'AWS ECS Cluster: 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: 4daa5e7b1bc64b3cbd54d9addea571cd
          name: 'Network rx bytes'
          type: DEPENDENT
          key: aws.ecs.network.rx
          value_type: FLOAT
          units: Bps
          description: |
            The number of bytes received by the resource that is specified by the dimensions that you're using.
            This metric is only available for containers in tasks using the awsvpc or bridge network modes.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.MetricData[?(@.Label == "NetworkRxBytes")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: network
        - uuid: 59882985019d42009a1993bf8bfd1a31
          name: 'Network tx bytes'
          type: DEPENDENT
          key: aws.ecs.network.tx
          value_type: FLOAT
          units: Bps
          description: |
            The number of bytes transmitted by the resource that is specified by the dimensions that you're using.
            This metric is only available for containers in tasks using the awsvpc or bridge network modes.
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.MetricData[?(@.Label == "NetworkTxBytes")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: network
        - uuid: 26970ea823294cf2b87a158d8feee872
          name: 'Service Count'
          type: DEPENDENT
          key: aws.ecs.service_count
          value_type: FLOAT
          description: 'The number of services in the cluster.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.MetricData[?(@.Label == "ServiceCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: system
        - uuid: 3cc6d826052c4da49bd8891a99ec2816
          name: 'Task Count'
          type: DEPENDENT
          key: aws.ecs.task_count
          value_type: FLOAT
          description: 'The number of tasks running in the cluster.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.MetricData[?(@.Label == "TaskCount")].Values.first().first()'
              error_handler: DISCARD_VALUE
          master_item:
            key: aws.ecs.get_metrics
          tags:
            - tag: component
              value: system
      discovery_rules:
        - uuid: 5e1b53e77fd74b61864ed8437c635346
          name: 'Cluster Alarms discovery'
          type: DEPENDENT
          key: aws.ecs.alarms.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.ECS.LLD.FILTER.ALARM_NAME.MATCHES}'
              - macro: '{#ALARM_NAME}'
                value: '{$AWS.ECS.LLD.FILTER.ALARM_NAME.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#ALARM_SERVICE_NAMESPACE}'
                value: '{$AWS.ECS.LLD.FILTER.ALARM_SERVICE_NAMESPACE.MATCHES}'
              - macro: '{#ALARM_SERVICE_NAMESPACE}'
                value: '{$AWS.ECS.LLD.FILTER.ALARM_SERVICE_NAMESPACE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery instance alarms.'
          item_prototypes:
            - uuid: 98d3f64416f746639055abdda6dfc374
              name: '[{#ALARM_NAME}]: Get metrics'
              type: DEPENDENT
              key: 'aws.ecs.alarm.get_metrics["{#ALARM_NAME}"]'
              history: '0'
              value_type: TEXT
              description: 'Get alarm metrics about the state and its reason.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.AlarmName == "{#ALARM_NAME}")].first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: aws.ecs.get_alarms
              tags:
                - tag: component
                  value: raw
            - uuid: 8a862dd5444f459b88f91a9fdb2ddc5e
              name: '[{#ALARM_NAME}]: State'
              type: DEPENDENT
              key: 'aws.ecs.alarm.state["{#ALARM_NAME}"]'
              description: |
                The state value for the alarm. Possible values: 0 (OK), 1 (INSUFFICIENT_DATA), 2 (ALARM).
                Alarm description:
                {#ALARM_DESCRIPTION}
              valuemap:
                name: 'Alarm state'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.StateValue
                  error_handler: CUSTOM_VALUE
                  error_handler_params: '3'
                - type: JAVASCRIPT
                  parameters:
                    - |
                      var state = ['OK', 'INSUFFICIENT_DATA', 'ALARM'];
                      
                      return state.indexOf(value.trim()) === -1 ? 255 : state.indexOf(value.trim());
              master_item:
                key: 'aws.ecs.alarm.get_metrics["{#ALARM_NAME}"]'
              tags:
                - tag: component
                  value: alarms
              trigger_prototypes:
                - uuid: 50061fea24e744298732167898c34e5f
                  expression: 'last(/AWS ECS Cluster by HTTP/aws.ecs.alarm.state["{#ALARM_NAME}"])=1'
                  name: 'AWS ECS Cluster: [{#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: eacb27b638924fa289e7c119f97879d8
              name: '[{#ALARM_NAME}]: State reason'
              type: DEPENDENT
              key: 'aws.ecs.alarm.state_reason["{#ALARM_NAME}"]'
              value_type: TEXT
              description: |
                An explanation for the alarm state, in text format.
                Alarm description:
                {#ALARM_DESCRIPTION}
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.StateReason
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'aws.ecs.alarm.get_metrics["{#ALARM_NAME}"]'
              tags:
                - tag: component
                  value: alarms
          trigger_prototypes:
            - uuid: 25d14cc75ade4f7881825d5ab7864ca0
              expression: 'last(/AWS ECS Cluster by HTTP/aws.ecs.alarm.state["{#ALARM_NAME}"])=2 and length(last(/AWS ECS Cluster by HTTP/aws.ecs.alarm.state_reason["{#ALARM_NAME}"]))>0'
              name: 'AWS ECS Cluster: [{#ALARM_NAME}] has ''Alarm'' state'
              priority: AVERAGE
              description: |
                Alarm "{#ALARM_NAME}" has `Alarm` state.
                Reason: {ITEM.LASTVALUE2}
              tags:
                - tag: scope
                  value: availability
          master_item:
            key: aws.ecs.get_alarms
          preprocessing:
            - type: JAVASCRIPT
              parameters:
                - |
                  var result = [];
                  var alarms = JSON.parse(value);
                  
                  alarms.forEach(function(alarm) {
                  
                   result.push({
                  '{#ALARM_DESCRIPTION}': alarm.AlarmDescription !== null ? alarm.AlarmDescription : 'None' ,
                  '{#ALARM_NAME}': alarm.AlarmName,
                  '{#ALARM_PERIOD}': alarm.Period,
                  '{#METRIC_NAME}': alarm.MetricName,
                  '{#ALARM_SERVICE_NAMESPACE}': alarm.Namespace !== null ? alarm.Namespace : 'None'
                    });
                  });
                  
                  return JSON.stringify(result);
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 3h
        - uuid: 7ab2cc38ab6f4400b42bee282a7e25e1
          name: 'Cluster Services discovery'
          type: DEPENDENT
          key: aws.ecs.services.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AWS.ECS.SERVICE.NAME}'
                value: '{$AWS.ECS.LLD.FILTER.SERVICE.MATCHES}'
              - macro: '{#AWS.ECS.SERVICE.NAME}'
                value: '{$AWS.ECS.LLD.FILTER.SERVICE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery {$AWS.ECS.CLUSTER.NAME} services.'
          item_prototypes:
            - uuid: 51de81c8bdcb4359b347e9d9226fcb4b
              name: '[{#AWS.ECS.SERVICE.NAME}]: CPU Utilization'
              type: DEPENDENT
              key: 'aws.ecs.services.cpu.utilization["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: '%'
              description: |
                A number of CPU units used by tasks in the resource that is specified by the dimension set that you're using.
                This metric is only collected for tasks that have a defined CPU reservation in their task definition.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "AWS/ECS CPUUtilization")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: cpu
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
              trigger_prototypes:
                - uuid: 3e8d8d35d5ad4f70ad792fe943a499d2
                  expression: 'min(/AWS ECS Cluster by HTTP/aws.ecs.services.cpu.utilization["{#AWS.ECS.SERVICE.NAME}"],15m)>{$AWS.ECS.CLUSTER.SERVICE.CPU.UTIL.WARN}'
                  name: 'AWS ECS Cluster: [{#AWS.ECS.SERVICE.NAME}]: High CPU utilization'
                  event_name: 'AWS ECS Cluster: [{#AWS.ECS.SERVICE.NAME}]: High CPU utilization (over {$AWS.ECS.CLUSTER.SERVICE.CPU.UTIL.WARN}% for 15m)'
                  opdata: 'Current utilization: {ITEM.LASTVALUE1}'
                  priority: WARNING
                  description: 'The CPU utilization is too high. The system might be slow to respond.'
                  tags:
                    - tag: scope
                      value: capacity
                    - tag: scope
                      value: performance
                    - tag: service
                      value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: ba01726f96354fe681fb4d916d461460
              name: '[{#AWS.ECS.SERVICE.NAME}]: CPU Reserved'
              type: DEPENDENT
              key: 'aws.ecs.services.cpu_reserved["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              description: |
                A number of CPU units reserved by tasks in the resource that is specified by the dimension set that you're using.
                This metric is only collected for tasks that have a defined CPU reservation in their task definition.
              valuemap:
                name: 'CPU Reserved'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights CpuReserved")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: cpu
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 785fd19ab3344e749ce486e4601f4d8e
              name: '[{#AWS.ECS.SERVICE.NAME}]: Desired Task'
              type: DEPENDENT
              key: 'aws.ecs.services.desired.task["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              description: 'The desired number of tasks for an {#AWS.ECS.SERVICE.NAME} service.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights DesiredTaskCount")].Values.first().first()'
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: d12aae43f0f3446d96e2141a0bf303b8
              name: '[{#AWS.ECS.SERVICE.NAME}]: Get metrics'
              type: SCRIPT
              key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              delay: 0s;m/5
              history: '0'
              value_type: TEXT
              params: |
                var AWS = {
                	params: {},
                	request_period: 600,
                	metadata: 'http://169.254.169.254/latest/',
                
                	setParams: function (params) {
                		AWS.params['proxy'] = params.proxy;
                		switch (AWS.getField(params, 'auth_type')) {
                			case 'role_base':
                				AWS.params['auth_type'] = 'role_base';
                				var request = new HttpRequest();
                				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
                					request.setProxy(AWS.params.proxy);
                				}
                				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];
                				});
                				break;
                			case 'assume_role':
                				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];
                				});
                
                				role_arn_regex = /role\/(.+)$/;
                
                				var payload = {
                					'Action': 'AssumeRole',
                					'Version': '2011-06-15',
                					'RoleArn': AWS.params.role_arn,
                					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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: 685671b8a8c34f35ada959c2c6aca1e3
              name: '[{#AWS.ECS.SERVICE.NAME}]: Memory utilization'
              type: DEPENDENT
              key: 'aws.ecs.services.memory.utilization["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: '%'
              description: |
                The memory being used by tasks in the resource that is specified by the dimension set that you're using.
                This metric is only collected for tasks that have a defined memory reservation in their task definition.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "AWS/ECS MemoryUtilization")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: memory
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
              trigger_prototypes:
                - uuid: a1116a5e75f24b50864a0fb5ea7ad99d
                  expression: 'min(/AWS ECS Cluster by HTTP/aws.ecs.services.memory.utilization["{#AWS.ECS.SERVICE.NAME}"],15m)>{$AWS.ECS.CLUSTER.SERVICE.MEMORY.UTIL.WARN}'
                  name: 'AWS ECS Cluster: [{#AWS.ECS.SERVICE.NAME}]: High memory utilization'
                  event_name: 'AWS ECS Cluster: [{#AWS.ECS.SERVICE.NAME}]: High memory utilization (over {$AWS.ECS.CLUSTER.SERVICE.MEMORY.UTIL.WARN}% for 15m)'
                  opdata: 'Current utilization: {ITEM.LASTVALUE1}'
                  priority: WARNING
                  description: 'The system is running out of free memory.'
                  tags:
                    - tag: scope
                      value: capacity
                    - tag: scope
                      value: performance
                    - tag: service
                      value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 538e0157704e40ffa124d6b74208f71b
              name: '[{#AWS.ECS.SERVICE.NAME}]: Memory reserved'
              type: DEPENDENT
              key: 'aws.ecs.services.memory_reserved["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: B
              description: |
                The memory that is reserved by tasks in the resource that is specified by the dimension set that you're using.
                This metric is only collected for tasks that have a defined memory reservation in their task definition.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights MemoryReserved")].Values.first().first()'
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '1048576'
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: memory
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 80471d41639f4e7a87174cad13f7f3a4
              name: '[{#AWS.ECS.SERVICE.NAME}]: Memory utilized'
              type: DEPENDENT
              key: 'aws.ecs.services.memory_utilized["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: B
              description: |
                The memory being used by tasks in the resource that is specified by the dimension set that you're using.
                This metric is only collected for tasks that have a defined memory reservation in their task definition.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights MemoryUtilized")].Values.first().first()'
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '1048576'
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: memory
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 52c14dd824174368acc0918d1c4670e4
              name: '[{#AWS.ECS.SERVICE.NAME}]: Network rx bytes'
              type: DEPENDENT
              key: 'aws.ecs.services.network.rx["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: Bps
              description: |
                The number of bytes received by the resource that is specified by the dimensions that you're using.
                This metric is only available for containers in tasks using the awsvpc or bridge network modes.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights NetworkRxBytes")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: network
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 598337e977b2460ca3ce0844061a619c
              name: '[{#AWS.ECS.SERVICE.NAME}]: Network tx bytes'
              type: DEPENDENT
              key: 'aws.ecs.services.network.tx["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              units: Bps
              description: |
                The number of bytes transmitted by the resource that is specified by the dimensions that you're using.
                This metric is only available for containers in tasks using the awsvpc or bridge network modes.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights NetworkTxBytes")].Values.first().first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: network
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 38d4200dad444b42b77e3fd1fe355007
              name: '[{#AWS.ECS.SERVICE.NAME}]: Pending Task'
              type: DEPENDENT
              key: 'aws.ecs.services.pending.task["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              description: 'The number of tasks currently in the `pending` state.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights PendingTaskCount")].Values.first().first()'
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 3e1538ea18d7417889536bfce39bc22c
              name: '[{#AWS.ECS.SERVICE.NAME}]: Running Task'
              type: DEPENDENT
              key: 'aws.ecs.services.running.task["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              description: 'The number of tasks currently in the `running` state.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights RunningTaskCount")].Values.first().first()'
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
            - uuid: 46b30a391af44cc5b9a70832189ffb2b
              name: '[{#AWS.ECS.SERVICE.NAME}]: Task Set'
              type: DEPENDENT
              key: 'aws.ecs.services.task.set["{#AWS.ECS.SERVICE.NAME}"]'
              value_type: FLOAT
              description: 'The number of task sets in the {#AWS.ECS.SERVICE.NAME} service.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.Label == "ECS/ContainerInsights TaskSetCount")].Values.first().first()'
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'aws.ecs.services.get_metrics["{#AWS.ECS.SERVICE.NAME}"]'
              tags:
                - tag: component
                  value: services
                - tag: service
                  value: '{#AWS.ECS.SERVICE.NAME}'
          graph_prototypes:
            - uuid: e4034a72c2834434b5b15f96469e97ff
              name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: CPU Utilization'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2196F3
                  item:
                    host: 'AWS ECS Cluster by HTTP'
                    key: 'aws.ecs.services.cpu.utilization["{#AWS.ECS.SERVICE.NAME}"]'
            - uuid: 5c5da1e0886740ed80d43597c2b6ee96
              name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: Memory Utilization'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2196F3
                  item:
                    host: 'AWS ECS Cluster by HTTP'
                    key: 'aws.ecs.services.memory.utilization["{#AWS.ECS.SERVICE.NAME}"]'
            - uuid: 2057845fb9b641299c7406f1c1127710
              name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: Network'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'AWS ECS Cluster by HTTP'
                    key: 'aws.ecs.services.network.rx["{#AWS.ECS.SERVICE.NAME}"]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'AWS ECS Cluster by HTTP'
                    key: 'aws.ecs.services.network.tx["{#AWS.ECS.SERVICE.NAME}"]'
          master_item:
            key: aws.ecs.get_cluster_services
          lld_macro_paths:
            - lld_macro: '{#AWS.ECS.SERVICE.NAME}'
              path: $.service_name
          preprocessing:
            - type: 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: '2'
            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: '4'
            label: 'ARN assume role'
            description: 'The ARN of the role to assume when using the assume_role authorization method.'
        - 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'
            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: '15'
            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: '16'
            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: '8'
            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: '17'
            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: '18'
            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: '9'
            section_name: Filters
            label: 'Alarm Name Filter (Matches)'
            description: 'A regex pattern to include 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: '10'
            section_name: Filters
            label: 'Alarm Name Filter (Not Matches)'
            description: 'A regex pattern to exclude alarms by name.'
        - macro: '{$AWS.ECS.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 pattern to include 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: '12'
            section_name: Filters
            label: 'Alarm Namespace Filter (Not Matches)'
            description: 'A regex pattern to exclude alarms by namespace.'
        - macro: '{$AWS.ECS.LLD.FILTER.SERVICE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable services by name.'
          config:
            type: TEXT
            priority: '13'
            section_name: Filters
            label: 'Service Name Filter (Matches)'
            description: 'A regex pattern to include 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: '14'
            section_name: Filters
            label: 'Service Name Filter (Not Matches)'
            description: 'A regex pattern to exclude 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: '7'
            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: '5'
            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: '3'
            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: '6'
            label: 'STS Region'
            description: 'The AWS region for the assume role request.'
      dashboards:
        - uuid: d06afc9b9488445d887659b67d955384
          name: 'Overview AWS ECS Cluster'
          pages:
            - name: Cluster
              widgets:
                - type: item
                  name: 'Service count'
                  width: '24'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        key: aws.ecs.service_count
                    - type: INTEGER
                      name: show.0
                      value: '2'
                - type: graph
                  'y': '5'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        name: 'AWS ECS Cluster: CPU Utilization'
                    - type: STRING
                      name: reference
                      value: AAAAC
                - type: graph
                  'y': '10'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        name: 'AWS ECS Cluster: Memory Utilization'
                    - type: STRING
                      name: reference
                      value: AAAAB
                - type: graph
                  'y': '15'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        name: 'AWS ECS Cluster: Network'
                    - type: STRING
                      name: reference
                      value: AAAAA
                - type: item
                  name: 'Task count'
                  x: '24'
                  width: '24'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        key: aws.ecs.task_count
                    - type: INTEGER
                      name: show.0
                      value: '2'
                - type: item
                  name: 'Container instance count'
                  x: '48'
                  width: '24'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        key: aws.ecs.container_instance_count
                    - type: INTEGER
                      name: show.0
                      value: '2'
            - name: Services
              widgets:
                - type: graphprototype
                  width: '72'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: columns
                      value: '1'
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: CPU Utilization'
                    - type: STRING
                      name: reference
                      value: AAAAD
                - type: graphprototype
                  'y': '5'
                  width: '72'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: columns
                      value: '1'
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: Memory Utilization'
                    - type: STRING
                      name: reference
                      value: AAAAE
                - type: graphprototype
                  'y': '10'
                  width: '72'
                  height: '5'
                  fields:
                    - type: INTEGER
                      name: columns
                      value: '1'
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'AWS ECS Cluster by HTTP'
                        name: 'AWS ECS Cluster Service: [{#AWS.ECS.SERVICE.NAME}]: Network'
                    - type: STRING
                      name: reference
                      value: AAAAF
      valuemaps:
        - uuid: 6b0f40b56f1c49f0beb66ffb85009c15
          name: 'Alarm state'
          mappings:
            - value: '0'
              newvalue: OK
            - value: '1'
              newvalue: 'Insufficient data'
            - value: '2'
              newvalue: Alarm
            - value: '255'
              newvalue: Unknown
        - uuid: bb1024c6e5a14c05a8a91ea36aff6d99
          name: 'CPU Reserved'
          mappings:
            - value: '256'
              newvalue: '.25 vCPU'
            - value: '512'
              newvalue: '.5 vCPU'
            - value: '1024'
              newvalue: '1 vCPU'
            - value: '2048'
              newvalue: '2 vCPU'
            - value: '4096'
              newvalue: '4 vCPU'
            - value: '8192'
              newvalue: '8 vCPU'
            - value: '16384'
              newvalue: '16 vCPU'
            - value: '32768'
              newvalue: '32 vCPU'
    - 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 macros `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 macros `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)
        
        Refer to the Macros section for a list of macros used for LLD filters.
      vendor:
        name: Zabbix
        version: 7.4-2
      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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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/',
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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',
            			'cluster': AWS.params.cluster_name
            		},
            			services = [];
            
            		ECSClusters_Services = AWS.getField(AWS.request('GET', AWS.params.region, 'ecs', AWS.prepareParams(payload)), 'ListServicesResponse.ListServicesResult.serviceArns');
            
            		for (k in ECSClusters_Services) {
            			id = ECSClusters_Services[k];
            
            			json = {};
            			input = id.split(AWS.params.cluster_name + '/');
            			for (var i = 1; i < input.length; i += 2) {
            				json[input[i]] = input[i + 1];
            			}
            			services.push({
            				'service_name': input[1],
            			});
            		}
            
            		if (Array.isArray(services))
            			return services;
            		else
            			return [services];
            	}
            };
            
            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: 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/',
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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/',
                
                	setParams: function (params) {
                		AWS.params['proxy'] = params.proxy;
                		switch (AWS.getField(params, 'auth_type')) {
                			case 'role_base':
                				AWS.params['auth_type'] = 'role_base';
                				var request = new HttpRequest();
                				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
                					request.setProxy(AWS.params.proxy);
                				}
                				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];
                				});
                				break;
                			case 'assume_role':
                				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];
                				});
                
                				role_arn_regex = /role\/(.+)$/;
                
                				var payload = {
                					'Action': 'AssumeRole',
                					'Version': '2011-06-15',
                					'RoleArn': AWS.params.role_arn,
                					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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: '2'
            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: '4'
            label: 'ARN assume role'
            description: 'The ARN of the role to assume when using the assume_role authorization method.'
        - 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'
            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: '15'
            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: '16'
            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: '8'
            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: '17'
            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: '18'
            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: '9'
            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: '10'
            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: '11'
            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: '12'
            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: '13'
            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: '14'
            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: '7'
            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: '5'
            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: '3'
            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: '6'
            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 macros `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).
        
        See the section below for a list of macros used for LLD filters.
      vendor:
        name: Zabbix
        version: 7.4-2
      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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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;
                	},
                
                	setParams: function (params) {
                		AWS.params['proxy'] = params.proxy;
                		switch (AWS.getField(params, 'auth_type')) {
                			case 'role_base':
                				AWS.params['auth_type'] = 'role_base';
                				var request = new HttpRequest();
                				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
                					request.setProxy(AWS.params.proxy);
                				}
                				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];
                				});
                				break;
                			case 'assume_role':
                				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];
                				});
                
                				role_arn_regex = /role\/(.+)$/;
                
                				var payload = {
                					'Action': 'AssumeRole',
                					'Version': '2011-06-15',
                					'RoleArn': AWS.params.role_arn,
                					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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: '2'
            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: '4'
            label: 'ARN assume role'
            description: 'The ARN for the assume role when using the `assume_role` method.'
        - 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'
            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: '6'
            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: '9'
            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: '16'
            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: '17'
            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: '14'
            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: '15'
            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: '12'
            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: '13'
            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: '10'
            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: '11'
            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: '7'
            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: '5'
            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: '3'
            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: 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 macros `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).
        
        See the section below for a list of macros used for LLD filters.
      vendor:
        name: Zabbix
        version: 7.4-2
      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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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;
                	},
                
                	setParams: function (params) {
                		AWS.params['proxy'] = params.proxy;
                		switch (AWS.getField(params, 'auth_type')) {
                			case 'role_base':
                				AWS.params['auth_type'] = 'role_base';
                				var request = new HttpRequest();
                				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
                					request.setProxy(AWS.params.proxy);
                				}
                				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];
                				});
                				break;
                			case 'assume_role':
                				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];
                				});
                
                				role_arn_regex = /role\/(.+)$/;
                
                				var payload = {
                					'Action': 'AssumeRole',
                					'Version': '2011-06-15',
                					'RoleArn': AWS.params.role_arn,
                					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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: '2'
            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: '4'
            label: 'ARN assume role'
            description: 'The ARN for the assume role when using the `assume_role` method.'
        - 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'
            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: '8'
            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: '9'
            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: '14'
            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: '15'
            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: '12'
            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: '13'
            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: '10'
            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: '11'
            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: '16'
            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: '6'
            section_name: Other
            label: 'HTTP Proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AWS.REGION}'
          value: us-west-1
          description: 'AWS Application Load Balancer region code.'
          config:
            type: TEXT
            priority: '5'
            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: '3'
            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: 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 macros `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).
        
        See the section below for a list of macros used for LLD filters.
      vendor:
        name: Zabbix
        version: 7.4-2
      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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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: '2'
            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: '4'
            label: 'ARN assume role'
            description: 'ARN for the assume role when using the assume_role authorization method.'
        - 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'
            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: '8'
            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: '9'
            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: '12'
            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: '13'
            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: '10'
            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: '11'
            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: '6'
            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: '5'
            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: '3'
            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: 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 macros `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 manage access keys, see [official documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys)
        
        Also, see the Macros section for a list of macros used for LLD filters.
      vendor:
        name: Zabbix
        version: 7.4-2
      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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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: 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: '2'
            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: '4'
            label: 'ARN assume role'
            description: 'The ARN of the role to assume when using the assume_role authorization method.'
        - 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'
            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: '20'
            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: '19'
            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: '7'
            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: '21'
            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: '18'
            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: '17'
            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: '8'
            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: '11'
            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: '12'
            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: '9'
            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: '10'
            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: '13'
            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: '14'
            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: '15'
            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: '16'
            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: '5'
            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: '3'
            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: '6'
            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 macros `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 manage access keys, see [official documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys)
        
        Also, see the Macros section for a list of macros used for LLD filters.
      vendor:
        name: Zabbix
        version: 7.4-2
      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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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' & !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: 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;
            	},
            
            	setParams: function (params) {
            		AWS.params['proxy'] = params.proxy;
            		switch (AWS.getField(params, 'auth_type')) {
            			case 'role_base':
            				AWS.params['auth_type'] = 'role_base';
            				var request = new HttpRequest();
            				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
            					request.setProxy(AWS.params.proxy);
            				}
            				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];
            				});
            				break;
            			case 'assume_role':
            				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];
            				});
            
            				role_arn_regex = /role\/(.+)$/;
            
            				var payload = {
            					'Action': 'AssumeRole',
            					'Version': '2011-06-15',
            					'RoleArn': AWS.params.role_arn,
            					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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' & !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: 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;
                	},
                
                	setParams: function (params) {
                		AWS.params['proxy'] = params.proxy;
                		switch (AWS.getField(params, 'auth_type')) {
                			case 'role_base':
                				AWS.params['auth_type'] = 'role_base';
                				var request = new HttpRequest();
                				if (typeof AWS.params.proxy !== 'undefined' && AWS.params.proxy !== '') {
                					request.setProxy(AWS.params.proxy);
                				}
                				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];
                				});
                				break;
                			case 'assume_role':
                				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];
                				});
                
                				role_arn_regex = /role\/(.+)$/;
                
                				var payload = {
                					'Action': 'AssumeRole',
                					'Version': '2011-06-15',
                					'RoleArn': AWS.params.role_arn,
                					'RoleSessionName': AWS.params.role_arn.match(role_arn_regex)[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' & !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' & !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: 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: '2'
            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: '4'
            label: 'Assume role ARN'
            description: 'The ARN for the assume role authorization method.'
        - 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'
            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: '7'
            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: '5'
            label: 'Request region'
            description: 'The AWS region for the GET request.'
        - macro: '{$AWS.S3.BUCKET.NAME}'
          description: 'S3 bucket name.'
          config:
            type: TEXT
            priority: '8'
            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: '9'
            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: '10'
            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: '11'
            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: '12'
            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: '13'
            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: '3'
            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: '6'
            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
    - uuid: 3d527f609e344ed8a4ec19762c31c619
      template: 'Azure Backup Jobs by HTTP'
      name: 'Azure Backup Jobs by HTTP'
      description: |
        This template is designed to monitor Azure Backup Jobs via HTTP.
        It works without any external scripts and uses the script item.
        
        Setup:
          1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
            `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
            See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
          2. Link the template to a host.
          3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
        
        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 is designed to monitor Microsoft Azure Backup Jobs via HTTP.
        It works without any external scripts and uses the script item.
        
        ## Setup
        
        1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
        
              `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
        
        > See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
        
        2. Link the template to a host.
        3. Configure the macros: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, `Azure Vault ID` and `Backup jobs period`.
      vendor:
        name: Zabbix
        version: 7.4-1
      groups:
        - name: Templates/Cloud
      items:
        - uuid: b733302413d54250ba053b017367c6d6
          name: 'Availability status detailed'
          type: DEPENDENT
          key: azure.vault.availability.details
          value_type: CHAR
          description: 'The summary description of the availability status.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.summary
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.vault.data.get
          tags:
            - tag: component
              value: health
        - uuid: 1dc10b5b07f648d4a75f614573bb8da5
          name: 'Availability state'
          type: DEPENDENT
          key: azure.vault.availability.state
          description: |
            The availability status of the resource.
            0 - Available - no events detected that affect the health of the resource.
            1 - Degraded  - your resource detected a loss in performance, although it's still available for use.
            2 - Unavailable - the service detected an ongoing platform or non-platform event that affects the health of the resource.
            3 - Unknown - Resource Health hasn't received information about the resource for more than 10 minutes.
          valuemap:
            name: 'Azure resource health state'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.availabilityState
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: STR_REPLACE
              parameters:
                - Available
                - '0'
            - type: STR_REPLACE
              parameters:
                - Degraded
                - '1'
            - type: STR_REPLACE
              parameters:
                - Unavailable
                - '2'
            - type: STR_REPLACE
              parameters:
                - Unknown
                - '3'
            - type: IN_RANGE
              parameters:
                - '0'
                - '3'
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.vault.data.get
          tags:
            - tag: component
              value: health
          triggers:
            - uuid: 68ee9193a98c40778ee57ab2256082ec
              expression: 'last(/Azure Backup Jobs by HTTP/azure.vault.availability.state)=1'
              name: 'Azure backup jobs: Azure vault is degraded'
              opdata: 'Current state: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The resource is in a degraded state.'
              tags:
                - tag: scope
                  value: availability
            - uuid: 40b756bf271d46da94d3a9de2b892d88
              expression: 'last(/Azure Backup Jobs by HTTP/azure.vault.availability.state)=3'
              name: 'Azure backup jobs: Azure vault is in unknown state'
              opdata: 'Current state: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The resource state is unknown.'
              tags:
                - tag: scope
                  value: availability
            - uuid: cecb9bb0945f4f21bb2ad3df02307641
              expression: 'last(/Azure Backup Jobs by HTTP/azure.vault.availability.state)=2'
              name: 'Azure backup jobs: Azure vault is unavailable'
              opdata: 'Current state: {ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The resource state is unavailable.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 00848eb26866420282b2afdfc4334484
          name: 'Get errors'
          type: DEPENDENT
          key: azure.vault.data.errors
          value_type: TEXT
          description: 'A list of errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.vault.data.get
          tags:
            - tag: component
              value: error
          triggers:
            - uuid: d70f2e4edb38492ea019abbfc1cbb82a
              expression: 'length(last(/Azure Backup Jobs by HTTP/azure.vault.data.errors))>0'
              name: 'Azure backup jobs: There are errors in requests to API'
              opdata: 'Error: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 57d191150c06423daa1674d09c846dc7
          name: 'Get data'
          type: SCRIPT
          key: azure.vault.data.get
          history: '0'
          value_type: TEXT
          params: |
            var Azure = {
            	params: {},
            	token: null,
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id', 'resource_id', 'period'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            
            		Azure.params = params;
            	},
            
            	login: function () {
            		var response, login = new HttpRequest();
            
            		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
            			login.setProxy(Azure.params.proxy);
            		}
            
            		login.addHeader('Content-Type: application/x-www-form-urlencoded');
            		response = login.post(
            			'https://login.microsoftonline.com/' + encodeURIComponent(Azure.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(Azure.params.app_id) + '&client_secret=' + encodeURIComponent(Azure.params.password)
            		);
            
            		if (login.getStatus() !== 200) {
            			throw 'Login failed with status code ' + login.getStatus() + ': ' + response;
            		}
            
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse login session response.';
            		}
            
            		if (!response.hasOwnProperty('access_token')) {
            			throw 'Authentication response does not contain access token.';
            		}
            
            		Azure.token = response['access_token'];
            	},
            
            	request: function (url) {
            		var response, request = new HttpRequest();
            
            		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
            			request.setProxy(Azure.params.proxy);
            		}
            
            		if (!Azure.token) {
            			throw 'Request does not contain access token.';
            		}
            
            		request.addHeader('Content-Type: application/json');
            		request.addHeader('Authorization: Bearer ' + Azure.token);
            		Zabbix.log(4, '[ Azure Vault ] request url: ' + url);
            
            		response = request.get(url);
            
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	},
            
            	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;
            	},
            
            	getMetricsData: function () {
            		var data = {},
            			end_date = new Date(),
            			start_date = new Date();
            
            		function formatDate(date) {
            			var year = date.getFullYear(),
            				month = (date.getMonth() + 1),
            				day = date.getDate(),
            				hours = date.getHours(),
            				minutes = date.getMinutes(),
            				seconds = date.getSeconds(),
            				ampm = hours >= 12 ? 'PM' : 'AM';
            
            			hours = hours % 12 || 12;
            			month = month < 10 ? '0' + month : month;
            			day = day < 10 ? '0' + day : day;
            			hours = hours < 10 ? '0' + hours : hours;
            			minutes = minutes < 10 ? '0' + minutes : minutes;
            			seconds = seconds < 10 ? '0' + seconds : seconds;
            
            			formatted_date = year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds + ' ' + ampm;
            
            			return formatted_date
            		};
            
            		start_date.setDate(start_date.getDate() - Azure.params.period);
            		end_date = encodeURIComponent('\'' + formatDate(end_date) + '\'');
            		start_date = encodeURIComponent('\'' + formatDate(start_date) + '\'');
            		date_filter = '&$filter=' + encodeURIComponent('startTime eq ') + start_date + encodeURIComponent(' and endTime eq ') + end_date;
            
            		data.health = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + '/providers/Microsoft.ResourceHealth/availabilityStatuses?api-version=2020-05-01'), 'value.0.properties');
            		data.jobs = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + '/backupjobs?api-version=2025-01-01' + date_filter), 'value');
            
            		return data
            	}
            };
            
            try {
            	Azure.setParams(JSON.parse(value));
            	Azure.login();
            	return JSON.stringify(Azure.getMetricsData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ Azure Vault ] ERROR: ' + error);
            	return JSON.stringify({ 'error': error });
            }
          description: 'Gathers data of the Azure vault.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: period
              value: '{$AZURE.VAULT.PERIOD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: resource_id
              value: '{$AZURE.RESOURCE.ID}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: c5eb6f559a544be89f51ea3f8eee6dab
          name: 'Jobs: Backup'
          type: DEPENDENT
          key: azure.vault.jobs.backup
          description: 'The number of backup jobs over the period of `{$AZURE.VAULT.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.jobs[?(@.properties.operation == "Backup")].length()'
          master_item:
            key: azure.vault.data.get
          tags:
            - tag: component
              value: backup
        - uuid: 78a30e56155c4a9c8af1fe54999276fd
          name: 'Jobs: Configuring backup'
          type: DEPENDENT
          key: azure.vault.jobs.backup.config
          description: 'The number of backup configuration jobs over the period of `{$AZURE.VAULT.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.jobs[?(@.properties.operation == "ConfigureBackup")].length()'
          master_item:
            key: azure.vault.data.get
          tags:
            - tag: component
              value: backup
          triggers:
            - uuid: 881f3faf12da40458266c62f047c3c1e
              expression: 'change(/Azure Backup Jobs by HTTP/azure.vault.jobs.backup.config)>0'
              recovery_mode: NONE
              name: 'Azure backup jobs: Backup configuration job has appeared'
              opdata: 'Current amount: {ITEM.LASTVALUE1}'
              priority: INFO
              description: 'New backup configuration job has appeared.'
              manual_close: 'YES'
              tags:
                - tag: scope
                  value: notice
        - uuid: 7b6e5f9eb7e74524bf4fa856225ad107
          name: 'Jobs: Deleting backup data'
          type: DEPENDENT
          key: azure.vault.jobs.backup.delete
          description: 'The number of backup data deletion jobs over the period of `{$AZURE.VAULT.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.jobs[?(@.properties.operation == "DeleteBackupData")].length()'
          master_item:
            key: azure.vault.data.get
          tags:
            - tag: component
              value: backup
          triggers:
            - uuid: 7d4a36701e3c4384991858c34017b04f
              expression: 'change(/Azure Backup Jobs by HTTP/azure.vault.jobs.backup.delete)>0'
              recovery_mode: NONE
              name: 'Azure backup jobs: Backup data deletion job has appeared'
              opdata: 'Current amount: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'New backup data deletion job has appeared.'
              manual_close: 'YES'
              tags:
                - tag: scope
                  value: notice
        - uuid: 7a8af0d3852546e9aa49a3754af4e1f3
          name: 'Jobs: Cancelled'
          type: DEPENDENT
          key: azure.vault.jobs.cancelled
          description: 'The number of cancelled jobs over the period of `{$AZURE.VAULT.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.jobs[?(@.properties.status == "Cancelled")].length()'
          master_item:
            key: azure.vault.data.get
          tags:
            - tag: component
              value: backup
        - uuid: 1b2f4f764b2c4a65b824e816094117d5
          name: 'Jobs: Completed'
          type: DEPENDENT
          key: azure.vault.jobs.completed
          description: 'The number of completed jobs over the period of `{$AZURE.VAULT.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.jobs[?(@.properties.status == "Completed")].length()'
          master_item:
            key: azure.vault.data.get
          tags:
            - tag: component
              value: backup
        - uuid: 90a112a3ef2b42d2a372b8b4fb5c95fb
          name: 'Jobs: Failed'
          type: DEPENDENT
          key: azure.vault.jobs.failed
          description: 'The number of failed jobs over the period of `{$AZURE.VAULT.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.jobs[?(@.properties.status == "Failed")].length()'
          master_item:
            key: azure.vault.data.get
          tags:
            - tag: component
              value: backup
        - uuid: 5b9b00fad0364710b82ed05595848e82
          name: 'Jobs: In progress'
          type: DEPENDENT
          key: azure.vault.jobs.in_progress
          description: 'The number of jobs in progress over the period of `{$AZURE.VAULT.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.jobs[?(@.properties.status == "InProgress")].length()'
          master_item:
            key: azure.vault.data.get
          tags:
            - tag: component
              value: backup
        - uuid: 482582a2ac6045dc97be5d2fc19bbe8f
          name: 'Jobs: Restore'
          type: DEPENDENT
          key: azure.vault.jobs.restore
          description: 'The number of restore jobs over the period of `{$AZURE.VAULT.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.jobs[?(@.properties.operation == "Restore")].length()'
          master_item:
            key: azure.vault.data.get
          tags:
            - tag: component
              value: backup
          triggers:
            - uuid: 04f76f2f21a043169ac1fa11d42f72f3
              expression: 'change(/Azure Backup Jobs by HTTP/azure.vault.jobs.restore)>0'
              recovery_mode: NONE
              name: 'Azure backup jobs: 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: 3024516bc255403b8aaa765b4d376835
          name: 'Jobs: Total'
          type: DEPENDENT
          key: azure.vault.jobs.total
          description: 'The number of jobs over the period of `{$AZURE.VAULT.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.jobs.length()
          master_item:
            key: azure.vault.data.get
          tags:
            - tag: component
              value: backup
        - uuid: 4ac88439754f426090b0aa454ea4a5ed
          name: 'Jobs: Completed with warnings'
          type: DEPENDENT
          key: azure.vault.jobs.with_warning
          description: 'The number of jobs completed with warnings over the period of `{$AZURE.VAULT.PERIOD}` day(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - '$.jobs[?(@.properties.status == "CompletedWithWarnings")].length()'
          master_item:
            key: azure.vault.data.get
          tags:
            - tag: component
              value: backup
      discovery_rules:
        - uuid: e37ff9885d014939b9ea182ce2087e05
          name: 'Azure backup job discovery'
          type: DEPENDENT
          key: azure.vault.job.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#JOB.FRIENDLY.NAME}'
                value: '{$AZURE.JOBS.FRIENDLY.NAME.MATCHES}'
              - macro: '{#JOB.FRIENDLY.NAME}'
                value: '{$AZURE.JOBS.FRIENDLY.NAME.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#JOB.OPERATION}'
                value: '{$AZURE.JOBS.OPERATION.MATCHES}'
              - macro: '{#JOB.OPERATION}'
                value: '{$AZURE.JOBS.OPERATION.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#JOB.STATUS}'
                value: '{$AZURE.JOBS.STATUS.MATCHES}'
              - macro: '{#JOB.STATUS}'
                value: '{$AZURE.JOBS.STATUS.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
          lifetime: '0'
          description: 'List of backup jobs in the vault.'
          item_prototypes:
            - uuid: 9a46651633ad45d69a2a931259d381ac
              name: 'Job status [{#JOB.FRIENDLY.NAME}, {#JOB.NAME}]'
              type: DEPENDENT
              key: 'azure.vault.job.status[{#JOB.NAME}]'
              description: |
                Job status.
                Possible values:
                0 - Unknown
                1 - In progress
                2 - Queued
                3 - Completed
                4 - Completed with warnings
                5 - Failed
                6 - Cancelled
                7 - Expired
              valuemap:
                name: 'Azure backup job status'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.jobs[?(@.name == ''{#JOB.NAME}'')].properties.status.first()'
                - type: JAVASCRIPT
                  parameters:
                    - |
                      const idx = {
                      	'InProgress': 1,
                      	'Queued': 2,
                      	'Completed': 3,
                      	'CompletedWithWarnings': 4,
                      	'Failed': 5,
                      	'Cancelled': 6,
                      	'Expired': 7
                        };
                      
                        return typeof idx[value] === 'undefined' ? 0 : idx[value];
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 1h
              master_item:
                key: azure.vault.data.get
              tags:
                - tag: component
                  value: health
                - tag: resource
                  value: '{#JOB.FRIENDLY.NAME}'
              trigger_prototypes:
                - uuid: a3a8cb87e41546b0a6550375578cc651
                  expression: 'last(/Azure Backup Jobs by HTTP/azure.vault.job.status[{#JOB.NAME}])=6'
                  name: 'Azure backup jobs: Job cancelled [{#JOB.NAME}]'
                  event_name: 'Azure backup jobs: Job type [{#JOB.OPERATION}] for [{#JOB.FRIENDLY.NAME}] with ID [{#JOB.NAME}] has cancelled.'
                  opdata: 'Current status: {ITEM.LASTVALUE1}'
                  priority: AVERAGE
                  description: 'Job has received "Cancelled" status.'
                  manual_close: 'YES'
                  tags:
                    - tag: scope
                      value: notice
                - uuid: 475a62e73f9c4a2abef6320c6909e7fa
                  expression: 'last(/Azure Backup Jobs by HTTP/azure.vault.job.status[{#JOB.NAME}])=4'
                  name: 'Azure backup jobs: Job completed with warnings [{#JOB.NAME}]'
                  event_name: 'Azure backup jobs: Job type [{#JOB.OPERATION}] for [{#JOB.FRIENDLY.NAME}] with ID [{#JOB.NAME}] has completed with warnings.'
                  opdata: 'Current status: {ITEM.LASTVALUE1}'
                  priority: WARNING
                  description: 'Job has received "Completed with warnings" status.'
                  manual_close: 'YES'
                  tags:
                    - tag: scope
                      value: notice
                - uuid: b7e43dbcd4914f228bb0687f585951ea
                  expression: 'last(/Azure Backup Jobs by HTTP/azure.vault.job.status[{#JOB.NAME}])=7'
                  name: 'Azure backup jobs: Job expired [{#JOB.NAME}]'
                  event_name: 'Azure backup jobs: Job type [{#JOB.OPERATION}] for [{#JOB.FRIENDLY.NAME}] with ID [{#JOB.NAME}] has  expired.'
                  opdata: 'Current status: {ITEM.LASTVALUE1}'
                  priority: AVERAGE
                  description: 'Job has received "Expired" status.'
                  manual_close: 'YES'
                  tags:
                    - tag: scope
                      value: notice
                - uuid: f340de23cd004f1b94239dbcf7ec136e
                  expression: 'last(/Azure Backup Jobs by HTTP/azure.vault.job.status[{#JOB.NAME}])=5'
                  name: 'Azure backup jobs: Job failed [{#JOB.NAME}]'
                  event_name: 'Azure backup jobs: Job type [{#JOB.OPERATION}] for [{#JOB.FRIENDLY.NAME}] with ID [{#JOB.NAME}] has failed.'
                  opdata: 'Current status: {ITEM.LASTVALUE1}'
                  priority: HIGH
                  description: 'Job has received "Failed" status.'
                  manual_close: 'YES'
                  tags:
                    - tag: scope
                      value: notice
                - uuid: 860b6d8bbefd4daba537e517dfb94007
                  expression: 'last(/Azure Backup Jobs by HTTP/azure.vault.job.status[{#JOB.NAME}])=0'
                  name: 'Azure backup jobs: Job status unknown [{#JOB.NAME}]'
                  event_name: 'Azure backup jobs: Job type [{#JOB.OPERATION}] for [{#JOB.FRIENDLY.NAME}] with ID [{#JOB.NAME}] is in unknown status.'
                  opdata: 'Current status: {ITEM.LASTVALUE1}'
                  priority: AVERAGE
                  description: 'Job has received "Unknown" status.'
                  manual_close: 'YES'
                  tags:
                    - tag: scope
                      value: notice
          master_item:
            key: azure.vault.data.get
          lld_macro_paths:
            - lld_macro: '{#JOB.FRIENDLY.NAME}'
              path: $.entity_friendly_name
            - lld_macro: '{#JOB.NAME}'
              path: $.name
            - lld_macro: '{#JOB.OPERATION}'
              path: $.operation
            - lld_macro: '{#JOB.STATUS}'
              path: $.status
          preprocessing:
            - type: JAVASCRIPT
              parameters:
                - |
                  const job_list = JSON.parse(value);
                  
                  const result = job_list.jobs.map(function (job) {
                  	return {
                  	  'name': job.name,
                  	  'entity_friendly_name': job.properties.entityFriendlyName,
                  	  'status': job.properties.status,
                  	  'operation': job.properties.operation
                  	};
                  });
                  
                  return JSON.stringify(result);
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: backup
        - tag: target
          value: azure
      macros:
        - macro: '{$AZURE.APP.ID}'
          description: 'The App ID of Microsoft Azure.'
          config:
            type: TEXT
            priority: '3'
            label: 'Azure App ID'
            required: 'YES'
        - macro: '{$AZURE.DATA.TIMEOUT}'
          value: 15s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '7'
            section_name: Other
            label: 'API timeout'
            description: 'API response timeout, in seconds.'
        - macro: '{$AZURE.JOBS.FRIENDLY.NAME.MATCHES}'
          value: '.*'
          description: 'Set the regex string to include backup jobs based on `entityFriendlyName`.'
          config:
            type: TEXT
            priority: '9'
            section_name: Filters
            label: 'Include backup job filter'
            description: 'Regex string to include discovered Azure backup jobs by `entityFriendlyName`.'
        - macro: '{$AZURE.JOBS.FRIENDLY.NAME.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Set the regex string to exclude backup jobs based on `entityFriendlyName`.'
          config:
            type: TEXT
            priority: '10'
            section_name: Filters
            label: 'Exclude backup job filter'
            description: 'Regex string to exclude discovered Azure backup jobs by `entityFriendlyName`.'
        - macro: '{$AZURE.JOBS.OPERATION.MATCHES}'
          value: '.*'
          description: 'Set the regex string to include backup jobs based on operation type.'
          config:
            type: TEXT
            priority: '13'
            section_name: Filters
            label: 'Include backup job operation type filter'
            description: 'Regex string to include discovered Azure backup jobs by operation type.'
        - macro: '{$AZURE.JOBS.OPERATION.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Set the regex string to exclude backup jobs based on operation type.'
          config:
            type: TEXT
            priority: '14'
            section_name: Filters
            label: 'Exclude backup job operation type filter'
            description: 'Regex string to exclude discovered Azure backup jobs by operation type.'
        - macro: '{$AZURE.JOBS.STATUS.MATCHES}'
          value: '.*'
          description: 'Set the regex string to include backup jobs based on status.'
          config:
            type: TEXT
            priority: '11'
            section_name: Filters
            label: 'Include backup job status filter'
            description: 'Regex string to include discovered Azure backup jobs by status.'
        - macro: '{$AZURE.JOBS.STATUS.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Set the regex string to exclude backup jobs based on status.'
          config:
            type: TEXT
            priority: '12'
            section_name: Filters
            label: 'Exclude backup job status filter'
            description: 'Regex string to exclude discovered Azure backup jobs by status.'
        - macro: '{$AZURE.PASSWORD}'
          type: SECRET_TEXT
          description: 'Microsoft Azure password.'
          config:
            type: TEXT
            priority: '4'
            label: 'Azure password'
            required: 'YES'
        - macro: '{$AZURE.PROXY}'
          description: 'Sets the 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: '{$AZURE.RESOURCE.ID}'
          description: 'Microsoft Azure vault resource ID.'
          config:
            type: TEXT
            priority: '5'
            label: 'Azure Vault ID'
            description: 'Vault resource ID.'
            required: 'YES'
        - macro: '{$AZURE.SUBSCRIPTION.ID}'
          description: 'Microsoft Azure subscription ID.'
          config:
            type: TEXT
            priority: '1'
            label: 'Azure subscription ID'
            required: 'YES'
        - macro: '{$AZURE.TENANT.ID}'
          description: 'Microsoft Azure tenant ID.'
          config:
            type: TEXT
            priority: '2'
            label: 'Azure tenant ID'
            required: 'YES'
        - macro: '{$AZURE.VAULT.PERIOD}'
          value: '7'
          description: 'The number of days over which to retrieve backup jobs.'
          config:
            type: TEXT
            priority: '6'
            label: 'Backup jobs period'
            description: 'Number of days over which to retrieve backup jobs. No less than 0.'
            required: 'YES'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
      dashboards:
        - uuid: dd616732edf646cba117f8de257bafba
          name: 'Azure backup jobs'
          pages:
            - name: 'Backup job overview'
              widgets:
                - type: item
                  name: 'Total jobs'
                  width: '15'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Backup Jobs by HTTP'
                        key: azure.vault.jobs.total
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: item
                  name: 'Backup jobs'
                  'y': '2'
                  width: '15'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Backup Jobs by HTTP'
                        key: azure.vault.jobs.backup
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: itemnavigator
                  name: 'Jobs grouped by resource'
                  'y': '4'
                  width: '22'
                  height: '7'
                  fields:
                    - type: INTEGER
                      name: group_by.0.attribute
                      value: '3'
                    - type: STRING
                      name: group_by.0.tag_name
                      value: resource
                    - type: STRING
                      name: items.0
                      value: 'Job status [*]'
                    - type: STRING
                      name: reference
                      value: EBACA
                - type: item
                  name: 'Selected job'
                  'y': '11'
                  width: '22'
                  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: EBACA._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: 'In progress jobs'
                  x: '15'
                  width: '14'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Backup Jobs by HTTP'
                        key: azure.vault.jobs.in_progress
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: thresholds.0.color
                      value: 00A1FF
                    - type: STRING
                      name: thresholds.0.threshold
                      value: '1'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: item
                  name: 'Restore jobs'
                  x: '15'
                  'y': '2'
                  width: '14'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Backup Jobs by HTTP'
                        key: azure.vault.jobs.restore
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: thresholds.0.color
                      value: FF465C
                    - type: STRING
                      name: thresholds.0.threshold
                      value: '1'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: honeycomb
                  name: 'Job statuses'
                  x: '22'
                  'y': '4'
                  width: '50'
                  height: '7'
                  fields:
                    - type: STRING
                      name: items.0
                      value: 'Job status [*]'
                    - type: STRING
                      name: reference
                      value: AFAEA
                    - type: STRING
                      name: secondary_label
                      value: '{{ITEM.NAME}.regsub("(Job status \[)(.*)(,.*\])","\2")}'
                    - type: INTEGER
                      name: secondary_label_type
                      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: 00A1FF
                    - 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: 0EC9AC
                    - 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: FF465C
                    - type: STRING
                      name: thresholds.5.threshold
                      value: '5'
                    - type: STRING
                      name: thresholds.6.color
                      value: BF00FF
                    - type: STRING
                      name: thresholds.6.threshold
                      value: '6'
                    - type: STRING
                      name: thresholds.7.color
                      value: BAE37D
                    - type: STRING
                      name: thresholds.7.threshold
                      value: '7'
                - type: item
                  name: 'Selected job'
                  x: '22'
                  'y': '11'
                  width: '50'
                  height: '1'
                  hide_header: 'YES'
                  fields:
                    - type: STRING
                      name: description
                      value: '{{ITEM.NAME}.regsub("(Job status \[)(.*)(, )(.*)(\])","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: AFAEA._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: 'Failed jobs'
                  x: '29'
                  width: '14'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Backup Jobs by HTTP'
                        key: azure.vault.jobs.failed
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: thresholds.0.color
                      value: FF465C
                    - type: STRING
                      name: thresholds.0.threshold
                      value: '1'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: item
                  name: 'Deleting backup data jobs'
                  x: '29'
                  'y': '2'
                  width: '14'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Backup Jobs by HTTP'
                        key: azure.vault.jobs.backup.delete
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: thresholds.0.color
                      value: FFD54F
                    - type: STRING
                      name: thresholds.0.threshold
                      value: '1'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: item
                  name: 'Cancelled jobs'
                  x: '43'
                  width: '14'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Backup Jobs by HTTP'
                        key: azure.vault.jobs.cancelled
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: thresholds.0.color
                      value: BF00FF
                    - type: STRING
                      name: thresholds.0.threshold
                      value: '1'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: item
                  name: 'Configuring backup jobs'
                  x: '43'
                  'y': '2'
                  width: '14'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Backup Jobs by HTTP'
                        key: azure.vault.jobs.backup.config
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: thresholds.0.color
                      value: 6AC8FF
                    - type: STRING
                      name: thresholds.0.threshold
                      value: '1'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: item
                  name: 'Completed jobs'
                  x: '57'
                  width: '15'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Backup Jobs by HTTP'
                        key: azure.vault.jobs.completed
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: thresholds.0.color
                      value: 0EC9AC
                    - type: STRING
                      name: thresholds.0.threshold
                      value: '1'
                    - type: INTEGER
                      name: value_size
                      value: '60'
                - type: item
                  name: 'Completed with warning jobs'
                  x: '57'
                  'y': '2'
                  width: '15'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Backup Jobs by HTTP'
                        key: azure.vault.jobs.with_warning
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: thresholds.0.color
                      value: FFD54F
                    - type: STRING
                      name: thresholds.0.threshold
                      value: '1'
                    - type: INTEGER
                      name: value_size
                      value: '60'
      valuemaps:
        - uuid: f79314c2d4bb458caf510b85f65cae81
          name: 'Azure backup job status'
          mappings:
            - value: '0'
              newvalue: Unknown
            - value: '1'
              newvalue: InProgress
            - value: '2'
              newvalue: Queued
            - value: '3'
              newvalue: Completed
            - value: '4'
              newvalue: CompletedWithWarnings
            - value: '5'
              newvalue: Failed
            - value: '6'
              newvalue: Cancelled
            - value: '7'
              newvalue: Expired
        - uuid: 7bca76cc48c3468ca67b924f59003e4a
          name: 'Azure resource health state'
          mappings:
            - value: '0'
              newvalue: Available
            - value: '1'
              newvalue: Degraded
            - value: '2'
              newvalue: Unavailable
            - value: '3'
              newvalue: Unknown
    - uuid: fa58228fee8a4e34a7c6503950d1c615
      template: 'Azure by HTTP'
      name: 'Azure by HTTP'
      description: |
        This template is designed to monitor Microsoft Azure by HTTP.
        It works without any external scripts and uses the script item.
        Currently the template supports the discovery of virtual machines (VMs), Cosmos DB for MongoDB, storage accounts, Microsoft SQL, MySQL, and PostgreSQL servers.
        
        Setup:
          1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
            `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
            See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
          2. Link the template to a host.
          3. Configure the macros: `{$AZURE.APP.ID}`, `{$AZURE.PASSWORD}`, `{$AZURE.TENANT.ID}`, and `{$AZURE.SUBSCRIPTION.ID}`.
        
        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 is designed to monitor Microsoft Azure by HTTP.
        - It works without any external scripts and uses the script item.
        - Currently, the template supports the discovery of virtual machines (VMs), VM scale sets, Cosmos DB for MongoDB, storage accounts, Microsoft SQL, MySQL, and PostgreSQL servers.
        
        ## Setup
        
        1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
        
              `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
        
        > See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
        
        2. Link the template to a host.
        3. Configure the macros: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`.
      vendor:
        name: Zabbix
        version: 7.4-4
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 7b2fe9a7ee164718933eb456b0068fea
          name: 'Get errors'
          type: DEPENDENT
          key: azure.get.errors
          value_type: TEXT
          description: 'A list of errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.errors
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.get.resources
          tags:
            - tag: component
              value: raw
          triggers:
            - uuid: 502cb582546046a29267715763c46bff
              expression: 'length(last(/Azure by HTTP/azure.get.errors))>0'
              name: 'Azure: There are errors in requests to API'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              tags:
                - tag: scope
                  value: availability
        - uuid: fb6abf3631b240b08357ea9ce9ba89a4
          name: 'Get resources'
          type: SCRIPT
          key: azure.get.resources
          delay: 10m
          history: '0'
          value_type: TEXT
          params: |
            var Azure = {
            	params: {},
            	token: null,
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            
            		Azure.params = params;
            	},
            
            	request: function (url, data) {
            		if (typeof data === 'undefined' || data === null) {
            			data = '';
            		}
            		var response, request = new HttpRequest();
            		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
            			request.setProxy(Azure.params.proxy);
            		}
            		if (Azure.token) {
            			request.addHeader('Accept: application/json');
            			request.addHeader('Authorization: Bearer ' + Azure.token);
            		}
            
            		Zabbix.log(4, '[ Azure ] Sending request: ' + url);
            
            		if (data !== '') {
            			request.addHeader('Content-Type: application/x-www-form-urlencoded');
            			response = request.post(url, data);
            		}
            		else {
            			response = request.get(url);
            		}
            
            		Zabbix.log(4, '[ Azure ] Received response with status code ' + request.getStatus() + ': ' + response);
            
            		if (request.getStatus() !== 200 || response === null) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	},
            
            	nextlink: function (data) {
            		next_data = data;
            		while ('nextLink' in next_data) {
            			next_data = Azure.request(next_data.nextLink);
            			next_data.value.forEach(function (value) {
            				data.value.push(value);
            			});
            		}
            
            		return data;
            	}
            };
            
            var result,
            	data = {},
            	types = [
            		{"method": "Microsoft.Compute/virtualMachines", "version": "2022-03-01"},
            		{"method": "Microsoft.DBforMySQL/flexibleServers", "version": "2021-05-01"},
            		{"method": "Microsoft.DBforMySQL/servers", "version": "2017-12-01"},
            		{"method": "Microsoft.DBforPostgreSQL/flexibleServers", "version": "2021-06-01"},
            		{"method": "Microsoft.DBforPostgreSQL/servers", "version": "2017-12-01"},
            		{"method": "Microsoft.Sql/servers", "version": "2022-05-01-preview"},
            		{"method": "Microsoft.DocumentDB/databaseAccounts", "version": "2022-11-15-preview"},
            		{"method": "Microsoft.Compute/virtualMachineScaleSets", "version": "2024-03-01"},
            		{"method": "Microsoft.Sql/managedInstances", "version": "2024-05-01-preview"},
            		{"method": "Microsoft.DataProtection/backupVaults", "version": "2025-01-01"},
            		{"method": "Microsoft.RecoveryServices/vaults", "version": "2025-02-28-preview"}
            	];
            	data['errors'] = {},
            	data['resources'] = {};
            	data.resources.value = [];
            
            try {
            	Azure.setParams(JSON.parse(value));
            
            	try {
            		result = Azure.request(
            			'https://login.microsoftonline.com/' + encodeURIComponent(Azure.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(Azure.params.app_id) + '&client_secret=' + encodeURIComponent(Azure.params.password)
            		);
            
            		if ('access_token' in result) {
            			Azure.token = result['access_token'];
            		} else {
            			throw 'Auth response does not contain access token.';
            		}
            	}
            	catch (error) {
            		data.errors.auth = error.toString();
            	}
            
            	if (!('auth' in data.errors)) {
            		try {
            			for (var i in types) {
            				if (types[i].method === "Microsoft.Sql/servers") {
            					mssql_servers = Azure.request('https://management.azure.com/subscriptions/' + encodeURIComponent(Azure.params.subscription_id) + '/providers/' + types[i].method + '?api-version=' + types[i].version);
            
            					if ('nextLink' in mssql_servers) {
            						mssql_servers = Azure.nextlink(mssql_servers);
            					}
            
            					if ('value' in mssql_servers && mssql_servers.value.length > 0) {
            						for (j in mssql_servers.value) {
            							mssql_dbs = Azure.request('https://management.azure.com' + mssql_servers.value[j].id + '/databases?api-version=' + types[i].version);
            
            							if ('nextLink' in mssql_dbs) {
            								mssql_dbs = Azure.nextlink(mssql_dbs);
            							}
            
            							mssql_dbs.value.forEach(function (value) {
            								raw_data.value.push(value);
            							});
            						}
            					}
            				}
            				else {
            					raw_data = Azure.request('https://management.azure.com/subscriptions/' + encodeURIComponent(Azure.params.subscription_id) + '/providers/' + types[i].method + '?api-version=' + types[i].version);
            
            					if ('nextLink' in raw_data) {
            						raw_data = Azure.nextlink(raw_data);
            					}
            				}
            
            				raw_data.value.forEach(function (value) {
            					value.resourceGroup = value.id.split("/")[4];
            					data.resources.value.push(value);
            				});
            			}
            		}
            		catch (error) {
            			data.errors.resources = error.toString();
            		}
            	}
            }
            catch (error) {
            	data.errors.params = error.toString();
            }
            
            if (Object.keys(data.errors).length !== 0) {
            	errors = 'Failed to receive data:';
            	for (var error in data.errors) {
            		errors += '\n' + error + ' : ' + data.errors[error];
            	}
            	data.errors = errors;
            }
            else {
            	data.errors = '';
            }
            
            return JSON.stringify(data);
          description: 'The result of API requests is expressed in the JSON.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: 91b2290d65b949ad9ea801763c35cf40
          name: 'Get storage accounts'
          type: SCRIPT
          key: azure.get.storage.acc
          delay: 10m
          history: '0'
          value_type: TEXT
          params: |
            var Azure = {
            	params: {},
            	token: '',
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            
            		Azure.params = params;
            	},
            
            	login: function () {
            		var response, login = new HttpRequest();
            		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
            			login.setProxy(Azure.params.proxy);
            		}
            		login.addHeader('Content-Type: application/x-www-form-urlencoded');
            		response = login.post(
            			'https://login.microsoftonline.com/' + encodeURIComponent(Azure.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(Azure.params.app_id) + '&client_secret=' + encodeURIComponent(Azure.params.password)
            		);
            
            		if (login.getStatus() !== 200) {
            			throw 'Login failed with status code ' + login.getStatus() + ': ' + response;
            		}
            		try {
            			response = JSON.parse(response);
            			if (!response.hasOwnProperty('access_token')) {
            				throw null;
            			}
            		}
            		catch (error) {
            			throw 'Authentication response does not contain access token.';
            		}
            
            		Azure.token = response['access_token'];
            	},
            
            	request: function (url) {
            		var response, request = new HttpRequest();
            		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
            			request.setProxy(Azure.params.proxy);
            		}
            		if (!Azure.token) {
            			throw 'Request does not contain access token.';
            		}
            		request.addHeader('Accept: application/json');
            		request.addHeader('Authorization: Bearer ' + Azure.token);
            		response = request.get(url);
            
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	},
            
            	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;
            	},
            
            	getMetricsData: function () {
            		var metric = Azure.request('https://management.azure.com/subscriptions/' + encodeURIComponent(Azure.params.subscription_id) + '/providers/Microsoft.Storage/storageAccounts?api-version=2021-05-01'),
            			data = [];
            
            		if (!metric.hasOwnProperty('value')) {
            			throw 'Failed getting required field. Check debug log for more information.';
            		}
            		for (k in metric.value) {
            			id = Azure.getField(metric.value[k], 'id');
            			json = {};
            			input = id.split('/');
            			for (var i = 1; i < input.length; i += 2) {
            				json[input[i]] = input[i + 1];
            			}
            			data.push({
            				'name': Azure.getField(metric.value[k], 'name'),
            				'id': id,
            				'resourceGroup': Azure.getField(json, 'resourceGroups'),
            				'location': Azure.getField(metric.value[k], 'location'),
            				'token': Azure.token
            			});
            		}
            
            		return data;
            	}
            };
            
            try {
            	Azure.setParams(JSON.parse(value));
            	Azure.login();
            	return JSON.stringify(Azure.getMetricsData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ Azure ] ERROR: ' + error);
            	return JSON.stringify({'error': error});
            }
          description: 'The result of API requests is expressed in the JSON.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: 2e425a9ef8d34ea68f7998ceed30ebc4
          name: 'Get storage accounts errors'
          type: DEPENDENT
          key: azure.get.storage.acc.errors
          value_type: TEXT
          description: 'The errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.get.storage.acc
          tags:
            - tag: component
              value: status
          triggers:
            - uuid: 253f0835cd134d2591bb2be1b9dc9b29
              expression: 'length(last(/Azure by HTTP/azure.get.storage.acc.errors))>0'
              name: 'Azure: There are errors in storages requests to API'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              dependencies:
                - name: 'Azure: There are errors in requests to API'
                  expression: 'length(last(/Azure by HTTP/azure.get.errors))>0'
              tags:
                - tag: scope
                  value: availability
      discovery_rules:
        - uuid: 3bfbfc8d770a4c77a17d62aaebb55e64
          name: 'Cosmos DB account discovery'
          type: DEPENDENT
          key: azure.cosmos.mongo.db.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.MATCHES}'
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#LOCATION}'
                value: '{$AZURE.COSMOS.MONGO.DB.LOCATION.MATCHES}'
              - macro: '{#LOCATION}'
                value: '{$AZURE.COSMOS.MONGO.DB.LOCATION.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#NAME}'
                value: '{$AZURE.COSMOS.MONGO.DB.NAME.MATCHES}'
              - macro: '{#NAME}'
                value: '{$AZURE.COSMOS.MONGO.DB.NAME.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#TYPE}'
                value: ^Microsoft.DocumentDB/databaseAccounts
          description: 'The list of Cosmos databases provided by the subscription.'
          host_prototypes:
            - uuid: 16eec30e921e4627b3599b4d06e48072
              host: 'Azure Cosmos DB {#NAME}'
              name: 'Azure Cosmos DB {#NAME}'
              group_links:
                - group:
                    name: Databases
              macros:
                - macro: '{$AZURE.RESOURCE.ID}'
                  value: '{#ID}'
              tags:
                - tag: location
                  value: '{#LOCATION}'
                - tag: resource-group
                  value: '{#GROUP}'
                - tag: version
                  value: '{#VERSION}'
          master_item:
            key: azure.get.resources
          lld_macro_paths:
            - lld_macro: '{#GROUP}'
              path: $.resourceGroup
            - lld_macro: '{#ID}'
              path: $.id
            - lld_macro: '{#LOCATION}'
              path: $.location
            - lld_macro: '{#NAME}'
              path: $.name
            - lld_macro: '{#TYPE}'
              path: $.type
            - lld_macro: '{#VERSION}'
              path: $.kind
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.resources.value
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 6h
          overrides:
            - name: MongoDB
              step: '1'
              filter:
                conditions:
                  - macro: '{#VERSION}'
                    value: ^MongoDB$
              operations:
                - operationobject: HOST_PROTOTYPE
                  operator: REGEXP
                  templates:
                    - name: 'Azure Cosmos DB for MongoDB by HTTP'
        - uuid: c875a410ddd84ccfbc5b407cd6e34803
          name: 'Microsoft SQL databases discovery'
          type: DEPENDENT
          key: azure.mssql.databases.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.MATCHES}'
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#LOCATION}'
                value: '{$AZURE.MSSQL.DB.LOCATION.MATCHES}'
              - macro: '{#LOCATION}'
                value: '{$AZURE.MSSQL.DB.LOCATION.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#NAME}'
                value: '{$AZURE.MSSQL.DB.NAME.MATCHES}'
              - macro: '{#NAME}'
                value: '{$AZURE.MSSQL.DB.NAME.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#SIZE}'
                value: '{$AZURE.MSSQL.DB.SIZE.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#TYPE}'
                value: ^Microsoft.Sql/servers/databases
          description: 'The list of Microsoft SQL databases provided by the subscription.'
          host_prototypes:
            - uuid: 2aaf7dc7e9f04ccf9dd91fcd803fa076
              host: 'Azure Microsoft SQL database {#NAME}'
              name: 'Azure Microsoft SQL database {#NAME}'
              group_links:
                - group:
                    name: Databases
              macros:
                - macro: '{$AZURE.RESOURCE.ID}'
                  value: '{#ID}'
              tags:
                - tag: location
                  value: '{#LOCATION}'
                - tag: resource-group
                  value: '{#GROUP}'
                - tag: size
                  value: '{#SIZE}'
                - tag: version
                  value: '{#VERSION}'
          master_item:
            key: azure.get.resources
          lld_macro_paths:
            - lld_macro: '{#GROUP}'
              path: $.resourceGroup
            - lld_macro: '{#ID}'
              path: $.id
            - lld_macro: '{#LOCATION}'
              path: $.location
            - lld_macro: '{#NAME}'
              path: $.name
            - lld_macro: '{#SIZE}'
              path: $.sku.name
            - lld_macro: '{#TYPE}'
              path: $.type
            - lld_macro: '{#VERSION}'
              path: $.kind
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.resources.value
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 6h
          overrides:
            - name: Serverless
              step: '1'
              filter:
                conditions:
                  - macro: '{#VERSION}'
                    value: '^(?=.*serverless)(?=.*vcore).*$'
              operations:
                - operationobject: HOST_PROTOTYPE
                  operator: REGEXP
                  templates:
                    - name: 'Azure Microsoft SQL Serverless Database by HTTP'
            - name: Server
              step: '2'
              filter:
                conditions:
                  - macro: '{#VERSION}'
                    value: '^(?!.*serverless)(?=.*vcore).*$'
              operations:
                - operationobject: HOST_PROTOTYPE
                  operator: REGEXP
                  templates:
                    - name: 'Azure Microsoft SQL Database by HTTP'
            - name: DTU-based
              step: '3'
              filter:
                conditions:
                  - macro: '{#VERSION}'
                    value: '^(?!.*serverless)(?!.*vcore).*$'
              operations:
                - operationobject: HOST_PROTOTYPE
                  operator: REGEXP
                  templates:
                    - name: 'Azure Microsoft SQL DTU Database by HTTP'
        - uuid: 7fafbef68f8b46d083eb43da7cd1e2cc
          name: 'MySQL servers discovery'
          type: DEPENDENT
          key: azure.mysql.servers.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.MATCHES}'
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#LOCATION}'
                value: '{$AZURE.MYSQL.DB.LOCATION.MATCHES}'
              - macro: '{#LOCATION}'
                value: '{$AZURE.MYSQL.DB.LOCATION.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#NAME}'
                value: '{$AZURE.MYSQL.DB.NAME.MATCHES}'
              - macro: '{#NAME}'
                value: '{$AZURE.MYSQL.DB.NAME.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#TYPE}'
                value: ^Microsoft.DBforMySQL
          description: 'The list of MySQL servers provided by the subscription.'
          host_prototypes:
            - uuid: 55b87078c14c4561b53e64af5ed77d61
              host: 'Azure MySQL server {#NAME}'
              name: 'Azure MySQL server {#NAME}'
              group_links:
                - group:
                    name: Databases
              macros:
                - macro: '{$AZURE.RESOURCE.ID}'
                  value: '{#ID}'
              tags:
                - tag: location
                  value: '{#LOCATION}'
                - tag: resource-group
                  value: '{#GROUP}'
                - tag: size
                  value: '{#SIZE}'
                - tag: version
                  value: '{#VERSION}'
          master_item:
            key: azure.get.resources
          lld_macro_paths:
            - lld_macro: '{#GROUP}'
              path: $.resourceGroup
            - lld_macro: '{#ID}'
              path: $.id
            - lld_macro: '{#LOCATION}'
              path: $.location
            - lld_macro: '{#NAME}'
              path: $.name
            - lld_macro: '{#SIZE}'
              path: $.sku.name
            - lld_macro: '{#TYPE}'
              path: $.type
            - lld_macro: '{#VERSION}'
              path: $.properties.version
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.resources.value
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 6h
          overrides:
            - name: 'Flexible server'
              step: '1'
              filter:
                conditions:
                  - macro: '{#TYPE}'
                    value: Microsoft.DBforMySQL/flexibleServers
              operations:
                - operationobject: HOST_PROTOTYPE
                  operator: REGEXP
                  templates:
                    - name: 'Azure MySQL Flexible Server by HTTP'
            - name: 'Single server'
              step: '2'
              filter:
                conditions:
                  - macro: '{#TYPE}'
                    value: Microsoft.DBforMySQL/servers
              operations:
                - operationobject: HOST_PROTOTYPE
                  operator: REGEXP
                  templates:
                    - name: 'Azure MySQL Single Server by HTTP'
        - uuid: a4b35b5fe8c04b52a9640f2f41013230
          name: 'PostgreSQL servers discovery'
          type: DEPENDENT
          key: azure.pgsql.servers.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.MATCHES}'
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#LOCATION}'
                value: '{$AZURE.PGSQL.DB.LOCATION.MATCHES}'
              - macro: '{#LOCATION}'
                value: '{$AZURE.PGSQL.DB.LOCATION.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#NAME}'
                value: '{$AZURE.PGSQL.DB.NAME.MATCHES}'
              - macro: '{#NAME}'
                value: '{$AZURE.PGSQL.DB.NAME.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#TYPE}'
                value: ^Microsoft.DBforPostgreSQL
          description: 'The list of PostgreSQL servers provided by the subscription.'
          host_prototypes:
            - uuid: 54f0e0ec288f4feb9a2dc58a8726bd1d
              host: 'Azure PostgreSQL server {#NAME}'
              name: 'Azure PostgreSQL server {#NAME}'
              group_links:
                - group:
                    name: Databases
              macros:
                - macro: '{$AZURE.RESOURCE.ID}'
                  value: '{#ID}'
              tags:
                - tag: location
                  value: '{#LOCATION}'
                - tag: resource-group
                  value: '{#GROUP}'
                - tag: size
                  value: '{#SIZE}'
                - tag: version
                  value: '{#VERSION}'
          master_item:
            key: azure.get.resources
          lld_macro_paths:
            - lld_macro: '{#GROUP}'
              path: $.resourceGroup
            - lld_macro: '{#ID}'
              path: $.id
            - lld_macro: '{#LOCATION}'
              path: $.location
            - lld_macro: '{#NAME}'
              path: $.name
            - lld_macro: '{#SIZE}'
              path: $.sku.name
            - lld_macro: '{#TYPE}'
              path: $.type
            - lld_macro: '{#VERSION}'
              path: $.properties.version
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.resources.value
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 6h
          overrides:
            - name: 'Flexible server'
              step: '1'
              filter:
                conditions:
                  - macro: '{#TYPE}'
                    value: Microsoft.DBforPostgreSQL/flexibleServers
              operations:
                - operationobject: HOST_PROTOTYPE
                  operator: REGEXP
                  templates:
                    - name: 'Azure PostgreSQL Flexible Server by HTTP'
            - name: 'Single server'
              step: '2'
              filter:
                conditions:
                  - macro: '{#TYPE}'
                    value: Microsoft.DBforPostgreSQL/servers
              operations:
                - operationobject: HOST_PROTOTYPE
                  operator: REGEXP
                  templates:
                    - name: 'Azure PostgreSQL Single Server by HTTP'
        - uuid: 006fc1e9e61d45c5a795a251a3237983
          name: 'Virtual machine scale set discovery'
          type: DEPENDENT
          key: azure.scaleset.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.MATCHES}'
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#LOCATION}'
                value: '{$AZURE.SCALESET.LOCATION.MATCHES}'
              - macro: '{#LOCATION}'
                value: '{$AZURE.SCALESET.LOCATION.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#NAME}'
                value: '{$AZURE.SCALESET.NAME.MATCHES}'
              - macro: '{#NAME}'
                value: '{$AZURE.SCALESET.NAME.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#TYPE}'
                value: ^Microsoft.Compute/virtualMachineScaleSets$
          description: 'The list of virtual machine scale sets provided by the subscription.'
          host_prototypes:
            - uuid: 1cbeb513fe3648b6829836800952c9c7
              host: 'Azure VM scale set {#NAME}'
              name: 'Azure VM scale set {#NAME}'
              group_links:
                - group:
                    name: 'Virtual machines'
              templates:
                - name: 'Azure VM Scale Set by HTTP'
              macros:
                - macro: '{$AZURE.RESOURCE.ID}'
                  value: '{#ID}'
              tags:
                - tag: location
                  value: '{#LOCATION}'
                - tag: orchestration
                  value: '{#ORCHESTRATION}'
                - tag: os
                  value: '{#OS}'
                - tag: resource-group
                  value: '{#GROUP}'
          master_item:
            key: azure.get.resources
          lld_macro_paths:
            - lld_macro: '{#GROUP}'
              path: $.resourceGroup
            - lld_macro: '{#ID}'
              path: $.id
            - lld_macro: '{#LOCATION}'
              path: $.location
            - lld_macro: '{#NAME}'
              path: $.name
            - lld_macro: '{#ORCHESTRATION}'
              path: $.properties.orchestrationMode
            - lld_macro: '{#OS}'
              path: $.properties.virtualMachineProfile.storageProfile.osDisk.osType
            - lld_macro: '{#TYPE}'
              path: $.type
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.resources.value
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 6h
        - uuid: 34e88b4d994f436e93381e41f5ba2bde
          name: 'Azure SQL managed instance discovery'
          type: DEPENDENT
          key: azure.sql_inst.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.MATCHES}'
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#LOCATION}'
                value: '{$AZURE.SQL.INST.LOCATION.MATCHES}'
              - macro: '{#LOCATION}'
                value: '{$AZURE.SQL.INST.LOCATION.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#NAME}'
                value: '{$AZURE.SQL.INST.NAME.MATCHES}'
              - macro: '{#NAME}'
                value: '{$AZURE.SQL.INST.NAME.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#TYPE}'
                value: ^Microsoft.Sql/managedInstances$
          description: 'The list of Azure SQL managed instances provided by the subscription.'
          host_prototypes:
            - uuid: 5211d232275145598294fc35bac96075
              host: 'Azure SQL managed instance {#NAME}'
              name: 'Azure SQL managed instance {#NAME}'
              group_links:
                - group:
                    name: Databases
              templates:
                - name: 'Azure SQL Managed Instance by HTTP'
              macros:
                - macro: '{$AZURE.RESOURCE.ID}'
                  value: '{#ID}'
              tags:
                - tag: location
                  value: '{#LOCATION}'
                - tag: resource-group
                  value: '{#GROUP}'
          master_item:
            key: azure.get.resources
          lld_macro_paths:
            - lld_macro: '{#GROUP}'
              path: $.resourceGroup
            - lld_macro: '{#ID}'
              path: $.id
            - lld_macro: '{#LOCATION}'
              path: $.location
            - lld_macro: '{#NAME}'
              path: $.name
            - lld_macro: '{#TYPE}'
              path: $.type
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.resources.value
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 6h
        - uuid: 3b9bde32dd6b4e3aa2dd8d7949f655e9
          name: 'Storage accounts discovery'
          type: DEPENDENT
          key: azure.storage.acc.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.MATCHES}'
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#LOCATION}'
                value: '{$AZURE.STORAGE.ACC.LOCATION.MATCHES}'
              - macro: '{#LOCATION}'
                value: '{$AZURE.STORAGE.ACC.LOCATION.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#NAME}'
                value: '{$AZURE.STORAGE.ACC.NAME.MATCHES}'
              - macro: '{#NAME}'
                value: '{$AZURE.STORAGE.ACC.NAME.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'The list of all storage accounts available under the subscription.'
          item_prototypes:
            - uuid: 3361508a601748f5aca339f952430889
              name: 'Storage account [{#NAME}]: Get data'
              type: SCRIPT
              key: 'azure.get.storage.acc[{#NAME}]'
              history: '0'
              value_type: TEXT
              params: |
                var AzureStorage = {
                	params: {},
                
                	setParams: function (params) {
                		['token', 'id'].forEach(function (field) {
                			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
                				throw 'Required param is not set: ' + field + '.';
                			}
                		});
                
                		AzureStorage.params = params;
                	},
                
                	request: function (url) {
                		var response, request = new HttpRequest();
                		if (typeof AzureStorage.params.proxy !== 'undefined' && AzureStorage.params.proxy !== '') {
                			request.setProxy(AzureStorage.params.proxy);
                		}
                		request.addHeader('Accept: application/json');
                		request.addHeader('Authorization: Bearer ' + AzureStorage.params.token);
                		Zabbix.log(4, '[ Azure ] Sending request: ' + url);
                		response = request.get(url);
                		if (request.getStatus() !== 200) {
                			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
                		}
                		try {
                			return JSON.parse(response);
                		}
                		catch (error) {
                			throw 'Failed to parse response received from API.';
                		}
                	},
                
                	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 + ' input data: ' + JSON.stringify(data);
                			}
                
                			data = data[step];
                		}
                
                		return data;
                	},
                
                	getMetricsData: function () {
                		var data = {};
                		start_date = new Date((new Date().getTime()) - 4200000).toISOString().replace(/\.\d+/, '');
                		end_date = new Date((new Date().getTime()) - 600000).toISOString().replace(/\.\d+/, '');
                		endpoints = {
                			'tableServices': '/tableServices/default/providers/Microsoft.Insights/metrics?metricnames=TableCapacity,TableCount,TableEntityCount,Transactions,Ingress,Egress,SuccessServerLatency,SuccessE2ELatency,Availability&api-version=2021-05-01&interval=PT1H&timespan=' + encodeURIComponent(start_date) + '/' + encodeURIComponent(end_date),
                			'blobServices': '/blobServices/default/providers/Microsoft.Insights/metrics?metricnames=BlobCapacity,BlobCount,ContainerCount,IndexCapacity,Transactions,Ingress,Egress,SuccessServerLatency,SuccessE2ELatency,Availability&api-version=2021-05-01&interval=PT1H&timespan=' + encodeURIComponent(start_date) + '/' + encodeURIComponent(end_date),
                			'fileServices': '/fileServices/default/providers/Microsoft.Insights/metrics?metricnames=FileCapacity,FileCount,FileShareCount,FileShareSnapshotCount,FileShareSnapshotSize,FileShareCapacityQuota,Transactions,Ingress,Egress,SuccessServerLatency,SuccessE2ELatency,Availability&api-version=2021-05-01&interval=PT1H&timespan=' + encodeURIComponent(start_date) + '/' + encodeURIComponent(end_date),
                			'storageAccount': '/providers/Microsoft.Insights/metrics?metricnames=UsedCapacity,Transactions,Ingress,Egress,SuccessServerLatency,SuccessE2ELatency,Availability&api-version=2021-05-01&interval=PT1H&timespan=' + encodeURIComponent(start_date) + '/' + encodeURIComponent(end_date),
                			'queueServices': '/queueServices/default/providers/Microsoft.Insights/metrics?metricnames=QueueCapacity,QueueCount,QueueMessageCount,Transactions,Ingress,Egress,SuccessServerLatency,SuccessE2ELatency,Availability&api-version=2021-05-01&interval=PT1H&timespan=' + encodeURIComponent(start_date) + '/' + encodeURIComponent(end_date)
                		};
                
                		Object.keys(endpoints).forEach(function (field) {
                			data[field] = {};
                			metrics = AzureStorage.request('https://management.azure.com' + AzureStorage.params.id + endpoints[field]);
                
                			if (!metrics.hasOwnProperty('value')) {
                				throw 'Failed getting required field. Check debug log for more information.';
                			}
                
                			for (k in metrics.value) {
                				key = AzureStorage.getField(metrics.value[k], 'name.value')
                				if (metrics.value[k].timeseries.length === 0) {
                					metrics.value[k].timeseries.push({ 'data': ['nodata'] })
                				}
                				data[field][key] = AzureStorage.getField(metrics.value[k], 'timeseries.0.data.0');
                			}
                		});
                		return data
                	}
                
                };
                
                try {
                	AzureStorage.setParams(JSON.parse(value));
                	return JSON.stringify(AzureStorage.getMetricsData());
                }
                catch (error) {
                	error += (String(error).endsWith('.')) ? '' : '.';
                	Zabbix.log(3, '[ Azure ] ERROR: ' + error);
                	return JSON.stringify({ 'error': error });
                }
              description: 'The HTTP API endpoint that returns storage metrics with the name `[{#NAME}]`.'
              timeout: '{$AZURE.DATA.TIMEOUT}'
              parameters:
                - name: id
                  value: '{#ID}'
                - name: proxy
                  value: '{$AZURE.PROXY}'
                - name: token
                  value: '{#TOKEN}'
              tags:
                - tag: component
                  value: raw
                - tag: component
                  value: storages
                - tag: storage
                  value: '{#NAME}'
            - uuid: 08ce66b39b084182bdb60a5556b88c88
              name: 'Storage account [{#NAME}]: Availability'
              type: DEPENDENT
              key: 'azure.storage.availability[{#NAME}]'
              value_type: FLOAT
              units: '%'
              description: |
                The percentage of availability for the storage service or a specified API operation.
                Availability is calculated by taking the `TotalBillableRequests` value and dividing it by the number of applicable requests, including those that produced unexpected errors.
                All unexpected errors result in reduced availability for the storage service or the specified API operation.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.storageAccount.Availability.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: common
                - tag: storage
                  value: '{#NAME}'
              trigger_prototypes:
                - uuid: 6a0b3edebded4d848ad76f86f8152377
                  expression: '(min(/Azure by HTTP/azure.storage.availability[{#NAME}],#3))<{$AZURE.STORAGE.ACC.AVAILABILITY:"{#NAME}"}'
                  name: 'Azure: Storage account [{#NAME}]: Availability is low'
                  event_name: 'Azure: Storage account [{#NAME} availability is too low (less than {$AZURE.STORAGE.ACC.AVAILABILITY:"{#NAME}"}%)'
                  opdata: '{ITEM.LASTVALUE1}'
                  priority: WARNING
                  tags:
                    - tag: scope
                      value: availability
            - uuid: 9ae0af76a37047f5ba84de2f43dfb5c4
              name: 'Storage account [{#NAME}]: Blob Availability'
              type: DEPENDENT
              key: 'azure.storage.blob.availability[{#NAME}]'
              value_type: FLOAT
              units: '%'
              description: |
                The percentage of availability for the storage service or a specified API operation.
                Availability is calculated by taking the `TotalBillableRequests` value and dividing it by the number of applicable requests, including those that produced unexpected errors.
                All unexpected errors result in reduced availability for the storage service or the specified API operation.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.blobServices.Availability.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: blob
                - tag: storage
                  value: '{#NAME}'
              trigger_prototypes:
                - uuid: 4cd8ac56b50c4120bf9de56bb1f06245
                  expression: '(min(/Azure by HTTP/azure.storage.blob.availability[{#NAME}],#3))<{$AZURE.STORAGE.ACC.BLOB.AVAILABILITY:"{#NAME}"}'
                  name: 'Azure: Storage account [{#NAME}]: Blob Availability is low'
                  event_name: 'Azure: Storage account [{#NAME} blob availability are too low (less than {$AZURE.STORAGE.ACC.BLOB.AVAILABILITY:"{#NAME}"}%)'
                  opdata: '{ITEM.LASTVALUE1}'
                  priority: WARNING
                  tags:
                    - tag: scope
                      value: availability
            - uuid: c6437ade4fee44f783ab379fb179508d
              name: 'Storage account [{#NAME}]: Blob Capacity'
              type: DEPENDENT
              key: 'azure.storage.blob.capacity[{#NAME}]'
              value_type: FLOAT
              units: B
              description: 'The amount of storage used by the blob service of the storage account with the name `[{#NAME}]`, expressed in bytes.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.blobServices.BlobCapacity.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: blob
                - tag: storage
                  value: '{#NAME}'
            - uuid: 707be15f02a141548ce5f89097c303a0
              name: 'Storage account [{#NAME}]: Blob Container Count'
              type: DEPENDENT
              key: 'azure.storage.blob.container.count[{#NAME}]'
              description: 'The number of containers in the storage account with the name `[{#NAME}]`.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.blobServices.ContainerCount.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: blob
                - tag: storage
                  value: '{#NAME}'
            - uuid: 9bd8b8f1b5844298a245d449548de46e
              name: 'Storage account [{#NAME}]: Blob Count'
              type: DEPENDENT
              key: 'azure.storage.blob.count[{#NAME}]'
              description: 'The number of blob objects stored in the storage account with the name `[{#NAME}]`.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.blobServices.BlobCount.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: blob
                - tag: storage
                  value: '{#NAME}'
            - uuid: ae28bbd289644619b20b1907212d8293
              name: 'Storage account [{#NAME}]: Blob Egress'
              type: DEPENDENT
              key: 'azure.storage.blob.engress[{#NAME}]'
              value_type: FLOAT
              units: B
              description: |
                The amount of egress data. This number includes egress to external client from Azure Storage and also egress within Azure.
                As a result, this number does not reflect billable egress.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.blobServices.Egress.total
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: blob
                - tag: storage
                  value: '{#NAME}'
            - uuid: 8e73a2aba92444dd9c02c6f94227a4e5
              name: 'Storage account [{#NAME}]: Blob Index Capacity'
              type: DEPENDENT
              key: 'azure.storage.blob.index.capacity[{#NAME}]'
              value_type: FLOAT
              units: B
              description: 'The amount of storage with the name `[{#NAME}]` used by the Azure Data Lake Storage Gen2 hierarchical index.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.blobServices.IndexCapacity.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: blob
                - tag: storage
                  value: '{#NAME}'
            - uuid: ff40325efb174839bef7bc775049837e
              name: 'Storage account [{#NAME}]: Blob Ingress'
              type: DEPENDENT
              key: 'azure.storage.blob.ingress[{#NAME}]'
              value_type: FLOAT
              units: B
              description: 'The amount of ingress data, expressed in bytes. This number includes ingress from an external client into Azure Storage and also ingress within Azure.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.blobServices.Ingress.total
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: blob
                - tag: storage
                  value: '{#NAME}'
            - uuid: e17d6f2ed79c4b5eaa54730c82d6840f
              name: 'Storage account [{#NAME}]: Blob Success E2E Latency'
              type: DEPENDENT
              key: 'azure.storage.blob.success.e2e.latency[{#NAME}]'
              value_type: FLOAT
              units: s
              description: |
                The average end-to-end latency of successful requests made to a storage service or the specified API operation, expressed in milliseconds.
                This value includes the required processing time within Azure Storage to read the request, send the response, and receive acknowledgment of the response.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.blobServices.SuccessE2ELatency.average
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '0.001'
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: blob
                - tag: storage
                  value: '{#NAME}'
            - uuid: 727fb792fe5c4229995f7aa5bbb681ed
              name: 'Storage account [{#NAME}]: Blob Success Server Latency'
              type: DEPENDENT
              key: 'azure.storage.blob.success.server.latency[{#NAME}]'
              value_type: FLOAT
              units: s
              description: |
                The average time used to process a successful request by Azure Storage.
                This value does not include the network latency specified in `SuccessE2ELatency`.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.blobServices.SuccessServerLatency.average
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '0.001'
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: blob
                - tag: storage
                  value: '{#NAME}'
            - uuid: 48ecb880def34474b73a03eb895db3ea
              name: 'Storage account [{#NAME}]: Blob Transactions'
              type: DEPENDENT
              key: 'azure.storage.blob.transactions[{#NAME}]'
              description: |
                The number of requests made to the storage service or a specified API operation.
                This number includes successful and failed requests and also requests that produced errors.
                Use `ResponseType` dimension for the number of different types of responses.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.blobServices.Transactions.total
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: blob
                - tag: storage
                  value: '{#NAME}'
            - uuid: 4198807e1e08439a9009481ddcfd3bab
              name: 'Storage account [{#NAME}]: Egress'
              type: DEPENDENT
              key: 'azure.storage.engress[{#NAME}]'
              value_type: FLOAT
              units: B
              description: |
                The amount of egress data. This number includes egress to external client from Azure Storage and also egress within Azure.
                As a result, this number does not reflect billable egress.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.storageAccount.Egress.total
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: common
                - tag: storage
                  value: '{#NAME}'
            - uuid: 43069f165849449d8403d1a8c82fe634
              name: 'Storage account [{#NAME}]: File Capacity'
              type: DEPENDENT
              key: 'azure.storage.file.capacity[{#NAME}]'
              value_type: FLOAT
              units: B
              description: 'The amount of file storage used by the storage account with the name `[{#NAME}]`, expressed in bytes.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.fileServices.FileCapacity.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: file
                - tag: storage
                  value: '{#NAME}'
            - uuid: 3483741c11a141c2866ea58a74a91135
              name: 'Storage account [{#NAME}]: File Count'
              type: DEPENDENT
              key: 'azure.storage.file.count[{#NAME}]'
              description: 'The number of files in the storage account with the name `[{#NAME}]`.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.fileServices.FileCount.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: file
                - tag: storage
                  value: '{#NAME}'
            - uuid: 7f6d01573bf24d9889f41a14cb581075
              name: 'Storage account [{#NAME}]: File Egress'
              type: DEPENDENT
              key: 'azure.storage.file.engress[{#NAME}]'
              value_type: FLOAT
              units: B
              description: |
                The amount of egress data. This number includes egress to external client from Azure Storage and also egress within Azure.
                As a result, this number does not reflect billable egress.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.fileServices.Egress.total
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: file
                - tag: storage
                  value: '{#NAME}'
            - uuid: 9f9b6772f9d9478ba3be3a93c5408ba2
              name: 'Storage account [{#NAME}]: File Ingress'
              type: DEPENDENT
              key: 'azure.storage.file.ingress[{#NAME}]'
              value_type: FLOAT
              units: B
              description: 'The amount of ingress data, expressed in bytes. This number includes ingress from an external client into Azure Storage and also ingress within Azure.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.fileServices.Ingress.total
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: file
                - tag: storage
                  value: '{#NAME}'
            - uuid: 4cb60e5473ce46a08bc962dc97c1f4db
              name: 'Storage account [{#NAME}]: File Share Capacity Quota'
              type: DEPENDENT
              key: 'azure.storage.file.share.capacity.quota[{#NAME}]'
              units: B
              description: 'The upper limit on the amount of storage that can be used by Azure Files Service, in bytes.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.fileServices.FileShareCapacityQuota.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: file
                - tag: storage
                  value: '{#NAME}'
            - uuid: 220673a2e99a4108b034d04d79108231
              name: 'Storage account [{#NAME}]: File Share Count'
              type: DEPENDENT
              key: 'azure.storage.file.share.count[{#NAME}]'
              description: 'The number of file shares in the storage account.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.fileServices.FileShareCount.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: file
                - tag: storage
                  value: '{#NAME}'
            - uuid: 47c48f39b9744a92ac13e9db69f6e629
              name: 'Storage account [{#NAME}]: File Share Snapshot Size'
              type: DEPENDENT
              key: 'azure.storage.file.share.snapshot.size[{#NAME}]'
              units: B
              description: 'The amount of storage used by the snapshots in storage account''s File service, in bytes.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.fileServices.FileShareSnapshotSize.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: file
                - tag: storage
                  value: '{#NAME}'
            - uuid: f0394f8f2d55471c8ab557045349a6ec
              name: 'Storage account [{#NAME}]: File Share Snapshot Count'
              type: DEPENDENT
              key: 'azure.storage.file.shares.snapshot.count[{#NAME}]'
              description: 'The number of snapshots present on the share in storage account''s Files Service.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.fileServices.FileShareSnapshotCount.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: file
                - tag: storage
                  value: '{#NAME}'
            - uuid: 431a6c51418d401697d105a0d9b62d23
              name: 'Storage account [{#NAME}]: File Success E2E Latency'
              type: DEPENDENT
              key: 'azure.storage.file.success.e2e.latency[{#NAME}]'
              value_type: FLOAT
              units: s
              description: |
                The average end-to-end latency of successful requests made to a storage service or the specified API operation, expressed in milliseconds.
                This value includes the required processing time within Azure Storage to read the request, send the response, and receive acknowledgment of the response.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.fileServices.file.SuccessE2ELatency.average
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '0.001'
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: file
                - tag: storage
                  value: '{#NAME}'
            - uuid: 43b6c0b948f64d9daada7aaac520c839
              name: 'Storage account [{#NAME}]: File Success Server Latency'
              type: DEPENDENT
              key: 'azure.storage.file.success.server.latency[{#NAME}]'
              value_type: FLOAT
              units: s
              description: |
                The average time used to process a successful request by Azure Storage.
                This value does not include the network latency specified in `SuccessE2ELatency`.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.fileServices.SuccessServerLatency.average
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '0.001'
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: file
                - tag: storage
                  value: '{#NAME}'
            - uuid: ed4b7ac10368493ba01c7cbeffba3042
              name: 'Storage account [{#NAME}]: File Transactions'
              type: DEPENDENT
              key: 'azure.storage.file.transactions[{#NAME}]'
              description: |
                The number of requests made to the storage service or a specified API operation.
                This number includes successful and failed requests and also requests that produced errors.
                Use `ResponseType` dimension for the number of different types of responses.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.fileServices.Transactions.total
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: file
                - tag: storage
                  value: '{#NAME}'
            - uuid: caeaa6805904471a8b18480f34ef9807
              name: 'Storage account [{#NAME}]: Ingress'
              type: DEPENDENT
              key: 'azure.storage.ingress[{#NAME}]'
              value_type: FLOAT
              units: B
              description: 'The amount of ingress data, expressed in bytes. This number includes ingress from an external client into Azure Storage and also ingress within Azure.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.storageAccount.Ingress.total
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: common
                - tag: storage
                  value: '{#NAME}'
            - uuid: be8b82396ff243e8a52864069b192dea
              name: 'Storage account [{#NAME}]: Queue Capacity'
              type: DEPENDENT
              key: 'azure.storage.queue.capacity[{#NAME}]'
              value_type: FLOAT
              units: B
              description: 'The amount of queue storage used by the storage account with the name `[{#NAME}]`, expressed in bytes.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.queueServices.QueueCapacity.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: queue
                - tag: storage
                  value: '{#NAME}'
            - uuid: 9174d372235e4d14a4896a79ddcbc051
              name: 'Storage account [{#NAME}]: Queue Count'
              type: DEPENDENT
              key: 'azure.storage.queue.count[{#NAME}]'
              description: 'The number of queues in the storage account with the name `[{#NAME}]`.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.queueServices.QueueCount.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: queue
                - tag: storage
                  value: '{#NAME}'
            - uuid: b8cff599c4194b4abd74f4a27ca93284
              name: 'Storage account [{#NAME}]: Queue Egress'
              type: DEPENDENT
              key: 'azure.storage.queue.engress[{#NAME}]'
              value_type: FLOAT
              units: B
              description: |
                The amount of egress data. This number includes egress to external client from Azure Storage and also egress within Azure.
                As a result, this number does not reflect billable egress.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.queueServices.Egress.total
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: queue
                - tag: storage
                  value: '{#NAME}'
            - uuid: 599f612c3cc64e81a53d507ae0078ab1
              name: 'Storage account [{#NAME}]: Queue Ingress'
              type: DEPENDENT
              key: 'azure.storage.queue.ingress[{#NAME}]'
              value_type: FLOAT
              units: B
              description: 'The amount of ingress data, expressed in bytes. This number includes ingress from an external client into Azure Storage and also ingress within Azure.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.queueServices.Ingress.total
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: queue
                - tag: storage
                  value: '{#NAME}'
            - uuid: 70c7b436a03145c5ab694b3a20ac52b1
              name: 'Storage account [{#NAME}]: Queue Message Count'
              type: DEPENDENT
              key: 'azure.storage.queue.message.count[{#NAME}]'
              description: 'The number of unexpired queue messages in the storage account with the name `[{#NAME}]`.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.queueServices.QueueMessageCount.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: queue
                - tag: storage
                  value: '{#NAME}'
            - uuid: eccdbf48412e4c28afc3bbf87c545cc2
              name: 'Storage account [{#NAME}]: Queue Success E2E Latency'
              type: DEPENDENT
              key: 'azure.storage.queue.success.e2e.latency[{#NAME}]'
              value_type: FLOAT
              units: s
              description: |
                The average end-to-end latency of successful requests made to a storage service or the specified API operation, expressed in milliseconds.
                This value includes the required processing time within Azure Storage to read the request, send the response, and receive acknowledgment of the response.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.queueServices.queue.SuccessE2ELatency.average
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '0.001'
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: queue
                - tag: storage
                  value: '{#NAME}'
            - uuid: 4d9aa2753d944690b01a23bcd44fd52d
              name: 'Storage account [{#NAME}]: Queue Success Server Latency'
              type: DEPENDENT
              key: 'azure.storage.queue.success.server.latency[{#NAME}]'
              value_type: FLOAT
              units: s
              description: |
                The average time used to process a successful request by Azure Storage.
                This value does not include the network latency specified in `SuccessE2ELatency`.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.queueServices.SuccessServerLatency.average
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '0.001'
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: queue
                - tag: storage
                  value: '{#NAME}'
            - uuid: e472739df4634b55be2466bd91af9886
              name: 'Storage account [{#NAME}]: Queue Transactions'
              type: DEPENDENT
              key: 'azure.storage.queue.transactions[{#NAME}]'
              description: |
                The number of requests made to the storage service or a specified API operation.
                This number includes successful and failed requests and also requests that produced errors.
                Use `ResponseType` dimension for the number of different types of responses.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.queueServices.Transactions.total
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: queue
                - tag: storage
                  value: '{#NAME}'
            - uuid: 48437de0bdca4f5392c295ca8b82bd0a
              name: 'Storage account [{#NAME}]: Success E2E Latency'
              type: DEPENDENT
              key: 'azure.storage.success.e2e.latency[{#NAME}]'
              value_type: FLOAT
              units: s
              description: |
                The average end-to-end latency of successful requests made to a storage service or the specified API operation, expressed in milliseconds.
                This value includes the required processing time within Azure Storage to read the request, send the response, and receive acknowledgment of the response.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.storageAccount.SuccessE2ELatency.average
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '0.001'
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: common
                - tag: storage
                  value: '{#NAME}'
            - uuid: 7076dbfb45cd49828b96064aa892e8e4
              name: 'Storage account [{#NAME}]: Success Server Latency'
              type: DEPENDENT
              key: 'azure.storage.success.server.latency[{#NAME}]'
              value_type: FLOAT
              units: s
              description: |
                The average time used to process a successful request by Azure Storage.
                This value does not include the network latency specified in `SuccessE2ELatency`.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.storageAccount.SuccessServerLatency.average
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '0.001'
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: common
                - tag: storage
                  value: '{#NAME}'
            - uuid: 918f1d1c70964e7c9f5521cf99bbb21d
              name: 'Storage account [{#NAME}]: Table Availability'
              type: DEPENDENT
              key: 'azure.storage.table.availability[{#NAME}]'
              value_type: FLOAT
              units: '%'
              description: |
                The percentage of availability for the storage service or a specified API operation.
                Availability is calculated by taking the `TotalBillableRequests` value and dividing it by the number of applicable requests, including those that produced unexpected errors.
                All unexpected errors result in reduced availability for the storage service or the specified API operation.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.tableServices.Availability.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: table
                - tag: storage
                  value: '{#NAME}'
              trigger_prototypes:
                - uuid: bfb1e82685224048ba8082447cad57ca
                  expression: '(min(/Azure by HTTP/azure.storage.table.availability[{#NAME}],#3))<{$AZURE.STORAGE.ACC.TABLE.AVAILABILITY:"{#NAME}"}'
                  name: 'Azure: Storage account [{#NAME}]: Table Availability is low'
                  event_name: 'Azure: Storage account [{#NAME} table availability is too low (less than {$AZURE.STORAGE.ACC.TABLE.AVAILABILITY:"{#NAME}"}%)'
                  opdata: '{ITEM.LASTVALUE1}'
                  priority: WARNING
                  tags:
                    - tag: scope
                      value: availability
            - uuid: ee19a3857a7a4650952eb855193991ee
              name: 'Storage account [{#NAME}]: Table Capacity'
              type: DEPENDENT
              key: 'azure.storage.table.capacity[{#NAME}]'
              value_type: FLOAT
              units: B
              description: 'The amount of storage used by the table service of the storage account with the name `[{#NAME}]`, expressed in bytes.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.tableServices.TableCapacity.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: table
                - tag: storage
                  value: '{#NAME}'
            - uuid: a3d11321b1cc4c1b9c322c0a7162e76e
              name: 'Storage account [{#NAME}]: Table Count'
              type: DEPENDENT
              key: 'azure.storage.table.count[{#NAME}]'
              description: 'The number of tables in the storage account with the name `[{#NAME}]`.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.tableServices.TableCount.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: table
                - tag: storage
                  value: '{#NAME}'
            - uuid: d75bd57fdd9f4377aea7c1e52a109c18
              name: 'Storage account [{#NAME}]: Table Egress'
              type: DEPENDENT
              key: 'azure.storage.table.engress[{#NAME}]'
              value_type: FLOAT
              units: B
              description: |
                The amount of egress data. This number includes egress to external client from Azure Storage and also egress within Azure.
                As a result, this number does not reflect billable egress.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.tableServices.Egress.total
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: table
                - tag: storage
                  value: '{#NAME}'
            - uuid: f2911504457b4d329ae7cf7d7a24594a
              name: 'Storage account [{#NAME}]: Table Entity Count'
              type: DEPENDENT
              key: 'azure.storage.table.entity.count[{#NAME}]'
              description: 'The number of table entities in the storage account with the name `[{#NAME}]`.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.tableServices.TableEntityCount.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: table
                - tag: storage
                  value: '{#NAME}'
            - uuid: 993ca2e5bcd74d27b19998d77f0abec8
              name: 'Storage account [{#NAME}]: Table Ingress'
              type: DEPENDENT
              key: 'azure.storage.table.ingress[{#NAME}]'
              value_type: FLOAT
              units: B
              description: 'The amount of ingress data, expressed in bytes. This number includes ingress from an external client into Azure Storage and also ingress within Azure.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.tableServices.Ingress.total
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: table
                - tag: storage
                  value: '{#NAME}'
            - uuid: 00c441cc77f4447584d4bffbefc304e0
              name: 'Storage account [{#NAME}]: Table Success E2E Latency'
              type: DEPENDENT
              key: 'azure.storage.table.success.e2e.latency[{#NAME}]'
              value_type: FLOAT
              units: s
              description: |
                The average end-to-end latency of successful requests made to a storage service or the specified API operation, expressed in milliseconds.
                This value includes the required processing time within Azure Storage to read the request, send the response, and receive acknowledgment of the response.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.tableServices.SuccessE2ELatency.average
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '0.001'
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: table
                - tag: storage
                  value: '{#NAME}'
            - uuid: f29e3ad4be034f38932cb85654397926
              name: 'Storage account [{#NAME}]: Table Success Server Latency'
              type: DEPENDENT
              key: 'azure.storage.table.success.server.latency[{#NAME}]'
              value_type: FLOAT
              units: s
              description: |
                The average time used to process a successful request by Azure Storage.
                This value does not include the network latency specified in `SuccessE2ELatency`.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.tableServices.SuccessServerLatency.average
                  error_handler: DISCARD_VALUE
                - type: MULTIPLIER
                  parameters:
                    - '0.001'
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: table
                - tag: storage
                  value: '{#NAME}'
            - uuid: 9ba25e87c5bb466a99855a9fb893283d
              name: 'Storage account [{#NAME}]: Table Transactions'
              type: DEPENDENT
              key: 'azure.storage.table.transactions[{#NAME}]'
              description: |
                The number of requests made to the storage service or a specified API operation.
                This number includes successful and failed requests and also requests that produced errors.
                Use `ResponseType` dimension for the number of different types of responses.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.tableServices.Transactions.total
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: table
                - tag: storage
                  value: '{#NAME}'
            - uuid: 6f68f0d8a63640ffa549fde44e8fe56c
              name: 'Storage account [{#NAME}]: Transactions'
              type: DEPENDENT
              key: 'azure.storage.transactions[{#NAME}]'
              description: |
                The number of requests made to the storage service or a specified API operation.
                This number includes successful and failed requests and also requests that produced errors.
                Use `ResponseType` dimension for the number of different types of responses.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.storageAccount.Transactions.total
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: common
                - tag: storage
                  value: '{#NAME}'
            - uuid: 08ef07d874db4823bd167482bf049916
              name: 'Storage account [{#NAME}]: Used Capacity'
              type: DEPENDENT
              key: 'azure.storage.used.capacity[{#NAME}]'
              value_type: FLOAT
              units: B
              description: |
                The amount of storage used by the storage account with the name `[{#NAME}]`, expressed in bytes.
                For standard storage accounts, it's the sum of capacity used by blob, table, file, and queue.
                For premium storage accounts and blob storage accounts, it is the same as BlobCapacity or FileCapacity.
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - $.storageAccount.UsedCapacity.average
                  error_handler: DISCARD_VALUE
                - type: DISCARD_UNCHANGED_HEARTBEAT
                  parameters:
                    - 3h
              master_item:
                key: 'azure.get.storage.acc[{#NAME}]'
              tags:
                - tag: component
                  value: storages
                - tag: metrics
                  value: common
                - tag: storage
                  value: '{#NAME}'
          graph_prototypes:
            - uuid: d569e0daf1974df58584432805f95557
              name: 'Azure: Capacity by storage [{#NAME}]'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.used.capacity[{#NAME}]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.blob.capacity[{#NAME}]'
                - sortorder: '2'
                  color: 00611C
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.table.capacity[{#NAME}]'
                - sortorder: '3'
                  color: F7941D
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.file.capacity[{#NAME}]'
                - sortorder: '4'
                  color: FC6EA3
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.queue.capacity[{#NAME}]'
            - uuid: 6bae0cf983104e0fada61468902949e1
              name: 'Azure: Storage account [{#NAME}] egress'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.engress[{#NAME}]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.blob.engress[{#NAME}]'
                - sortorder: '2'
                  color: 00611C
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.table.engress[{#NAME}]'
                - sortorder: '3'
                  color: F7941D
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.file.engress[{#NAME}]'
                - sortorder: '4'
                  color: FC6EA3
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.queue.engress[{#NAME}]'
            - uuid: 8860c37426104045a7f9feb6cc370db4
              name: 'Azure: Storage account [{#NAME}] ingress'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.ingress[{#NAME}]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.blob.ingress[{#NAME}]'
                - sortorder: '2'
                  color: 00611C
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.table.ingress[{#NAME}]'
                - sortorder: '3'
                  color: F7941D
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.file.ingress[{#NAME}]'
                - sortorder: '4'
                  color: FC6EA3
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.queue.ingress[{#NAME}]'
            - uuid: 9c87dfb9ed7e4c1ea32c8e35c6e23381
              name: 'Azure: Transactions by storage [{#NAME}]'
              graph_items:
                - color: 199C0D
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.transactions[{#NAME}]'
                - sortorder: '1'
                  color: F63100
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.blob.transactions[{#NAME}]'
                - sortorder: '2'
                  color: 00611C
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.table.transactions[{#NAME}]'
                - sortorder: '3'
                  color: F7941D
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.file.transactions[{#NAME}]'
                - sortorder: '4'
                  color: FC6EA3
                  item:
                    host: 'Azure by HTTP'
                    key: 'azure.storage.queue.transactions[{#NAME}]'
          master_item:
            key: azure.get.storage.acc
          lld_macro_paths:
            - lld_macro: '{#GROUP}'
              path: $.resourceGroup
            - lld_macro: '{#ID}'
              path: $.id
            - lld_macro: '{#LOCATION}'
              path: $.location
            - lld_macro: '{#NAME}'
              path: $.name
            - lld_macro: '{#TOKEN}'
              path: $.token
          preprocessing:
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 6h
        - uuid: b00b92f713724eaa9f028acf244527a6
          name: 'Azure Vault discovery'
          type: DEPENDENT
          key: azure.vault.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.MATCHES}'
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#LOCATION}'
                value: '{$AZURE.VAULT.LOCATION.MATCHES}'
              - macro: '{#LOCATION}'
                value: '{$AZURE.VAULT.LOCATION.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#NAME}'
                value: '{$AZURE.VAULT.NAME.MATCHES}'
              - macro: '{#NAME}'
                value: '{$AZURE.VAULT.NAME.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#TYPE}'
                value: '^Microsoft.*(v|V)aults$'
          description: 'The list of Azure Recovery Services and Backup vaults provided by the subscription.'
          host_prototypes:
            - uuid: fb057eebe3fb4d2483c8a3e7fe4c7b07
              host: 'Azure vault {#NAME}'
              name: 'Azure vault {#NAME}'
              group_links:
                - group:
                    name: Applications
              templates:
                - name: 'Azure Backup Jobs by HTTP'
              macros:
                - macro: '{$AZURE.RESOURCE.ID}'
                  value: '{#ID}'
              tags:
                - tag: location
                  value: '{#LOCATION}'
                - tag: resource-group
                  value: '{#GROUP}'
          master_item:
            key: azure.get.resources
          lld_macro_paths:
            - lld_macro: '{#GROUP}'
              path: $.resourceGroup
            - lld_macro: '{#ID}'
              path: $.id
            - lld_macro: '{#LOCATION}'
              path: $.location
            - lld_macro: '{#NAME}'
              path: $.name
            - lld_macro: '{#TYPE}'
              path: $.type
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.resources.value
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 6h
        - uuid: f9386233186648ce828f406c52972ce5
          name: 'Virtual machines discovery'
          type: DEPENDENT
          key: azure.vm.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.MATCHES}'
              - macro: '{#GROUP}'
                value: '{$AZURE.RESOURCE.GROUP.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#LOCATION}'
                value: '{$AZURE.VM.LOCATION.MATCHES}'
              - macro: '{#LOCATION}'
                value: '{$AZURE.VM.LOCATION.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#NAME}'
                value: '{$AZURE.VM.NAME.MATCHES}'
              - macro: '{#NAME}'
                value: '{$AZURE.VM.NAME.NOT.MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#SCALESET}'
                operator: NOT_EXISTS
              - macro: '{#TYPE}'
                value: ^Microsoft.Compute/virtualMachines$
          description: 'The list of virtual machines provided by the subscription.'
          host_prototypes:
            - uuid: d08c0ee33c924b28bf1fed571da6c7f4
              host: 'Azure virtual machine {#NAME}'
              name: 'Azure virtual machine {#NAME}'
              group_links:
                - group:
                    name: 'Virtual machines'
              templates:
                - name: 'Azure Virtual Machine by HTTP'
              macros:
                - macro: '{$AZURE.RESOURCE.ID}'
                  value: '{#ID}'
              tags:
                - tag: location
                  value: '{#LOCATION}'
                - tag: os
                  value: '{#OS}'
                - tag: resource-group
                  value: '{#GROUP}'
                - tag: size
                  value: '{#SIZE}'
          master_item:
            key: azure.get.resources
          lld_macro_paths:
            - lld_macro: '{#GROUP}'
              path: $.resourceGroup
            - lld_macro: '{#ID}'
              path: $.id
            - lld_macro: '{#LOCATION}'
              path: $.location
            - lld_macro: '{#NAME}'
              path: $.name
            - lld_macro: '{#OS}'
              path: $.properties.storageProfile.osDisk.osType
            - lld_macro: '{#SCALESET}'
              path: $.properties.virtualMachineScaleSet
            - lld_macro: '{#SIZE}'
              path: $.properties.hardwareProfile.vmSize
            - lld_macro: '{#TYPE}'
              path: $.type
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.resources.value
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 6h
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: automation
        - tag: subclass
          value: computing
        - tag: subclass
          value: containers
        - tag: subclass
          value: deploy
        - tag: subclass
          value: security
        - tag: subclass
          value: virtualization
        - tag: target
          value: azure
      macros:
        - macro: '{$AZURE.APP.ID}'
          description: 'The App ID of Microsoft Azure.'
          config:
            type: TEXT
            priority: '3'
            label: 'Azure App ID'
            required: 'YES'
        - macro: '{$AZURE.COSMOS.MONGO.DB.LOCATION.MATCHES}'
          value: '.*'
          description: 'This macro is used in Microsoft Cosmos DB account discovery rule.'
          config:
            type: TEXT
            priority: '47'
            section_name: Filters
            label: 'Include Cosmos DB account location filter'
            description: 'Regex string to include discovered Cosmos DB account locations by name.'
        - macro: '{$AZURE.COSMOS.MONGO.DB.LOCATION.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in Microsoft Cosmos DB account discovery rule.'
          config:
            type: TEXT
            priority: '48'
            section_name: Filters
            label: 'Exclude Cosmos DB account location filter'
            description: 'Regex string to exclude discovered Cosmos DB account locations by name.'
        - macro: '{$AZURE.COSMOS.MONGO.DB.NAME.MATCHES}'
          value: '.*'
          description: 'This macro is used in Microsoft Cosmos DB account discovery rule.'
          config:
            type: TEXT
            priority: '45'
            section_name: Filters
            label: 'Include Cosmos DB account filter'
            description: 'Regex string to include discovered Cosmos DB accounts by name.'
        - macro: '{$AZURE.COSMOS.MONGO.DB.NAME.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in Microsoft Cosmos DB account discovery rule.'
          config:
            type: TEXT
            priority: '46'
            section_name: Filters
            label: 'Exclude Cosmos DB account filter'
            description: 'Regex string to exclude discovered Cosmos DB accounts by name.'
        - macro: '{$AZURE.DATA.TIMEOUT}'
          value: 15s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '5'
            section_name: Other
            label: 'API timeout'
            description: 'API response timeout, in seconds.'
        - macro: '{$AZURE.MSSQL.DB.LOCATION.MATCHES}'
          value: '.*'
          description: 'This macro is used in Microsoft SQL databases discovery rule.'
          config:
            type: TEXT
            priority: '42'
            section_name: Filters
            label: 'Include MSSQL database location filter'
            description: 'Regex string to include discovered MSSQL database locations by name.'
        - macro: '{$AZURE.MSSQL.DB.LOCATION.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in Microsoft SQL databases discovery rule.'
          config:
            type: TEXT
            priority: '43'
            section_name: Filters
            label: 'Exclude MSSQL database location filter'
            description: 'Regex string to exclude discovered MSSQL database locations by name.'
        - macro: '{$AZURE.MSSQL.DB.NAME.MATCHES}'
          value: '.*'
          description: 'This macro is used in Microsoft SQL databases discovery rule.'
          config:
            type: TEXT
            priority: '40'
            section_name: Filters
            label: 'Include MSSQL database filter'
            description: 'Regex string to include discovered MSSQL databases by name.'
        - macro: '{$AZURE.MSSQL.DB.NAME.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in Microsoft SQL databases discovery rule.'
          config:
            type: TEXT
            priority: '41'
            section_name: Filters
            label: 'Exclude MSSQL database filter'
            description: 'Regex string to exclude discovered MSSQL databases by name.'
        - macro: '{$AZURE.MSSQL.DB.SIZE.NOT.MATCHES}'
          value: ^System$
          description: 'This macro is used in Microsoft SQL databases discovery rule.'
          config:
            type: TEXT
            priority: '44'
            section_name: Filters
            label: 'Exclude MSSQL database SKU type filter'
            description: 'Regex string to exclude discovered MSSQL database locations by SKU type.'
        - macro: '{$AZURE.MYSQL.DB.LOCATION.MATCHES}'
          value: '.*'
          description: 'This macro is used in MySQL servers discovery rule.'
          config:
            type: TEXT
            priority: '34'
            section_name: Filters
            label: 'Include MySQL server location filter'
            description: 'Regex string to include discovered MySQL server locations by name.'
        - macro: '{$AZURE.MYSQL.DB.LOCATION.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in MySQL servers discovery rule.'
          config:
            type: TEXT
            priority: '35'
            section_name: Filters
            label: 'Exclude MySQL server location filter'
            description: 'Regex string to exclude discovered MySQL server locations by name.'
        - macro: '{$AZURE.MYSQL.DB.NAME.MATCHES}'
          value: '.*'
          description: 'This macro is used in MySQL servers discovery rule.'
          config:
            type: TEXT
            priority: '32'
            section_name: Filters
            label: 'Include MySQL server filter'
            description: 'Regex string to include discovered MySQL servers by name.'
        - macro: '{$AZURE.MYSQL.DB.NAME.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in MySQL servers discovery rule.'
          config:
            type: TEXT
            priority: '33'
            section_name: Filters
            label: 'Exclude MySQL server filter'
            description: 'Regex string to exclude discovered MySQL servers by name.'
        - macro: '{$AZURE.PASSWORD}'
          type: SECRET_TEXT
          description: 'Microsoft Azure password.'
          config:
            type: TEXT
            priority: '4'
            label: 'Azure password'
            required: 'YES'
        - macro: '{$AZURE.PGSQL.DB.LOCATION.MATCHES}'
          value: '.*'
          description: 'This macro is used in PostgreSQL servers discovery rule.'
          config:
            type: TEXT
            priority: '38'
            section_name: Filters
            label: 'Include PostgreSQL server location filter'
            description: 'Regex string to include discovered PostgreSQL server locations by name.'
        - macro: '{$AZURE.PGSQL.DB.LOCATION.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in PostgreSQL servers discovery rule.'
          config:
            type: TEXT
            priority: '39'
            section_name: Filters
            label: 'Exclude PostgreSQL server location filter'
            description: 'Regex string to exclude discovered PostgreSQL server locations by name.'
        - macro: '{$AZURE.PGSQL.DB.NAME.MATCHES}'
          value: '.*'
          description: 'This macro is used in PostgreSQL servers discovery rule.'
          config:
            type: TEXT
            priority: '36'
            section_name: Filters
            label: 'Include PostgreSQL server filter'
            description: 'Regex string to include discovered PostgreSQL servers by name.'
        - macro: '{$AZURE.PGSQL.DB.NAME.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in PostgreSQL servers discovery rule.'
          config:
            type: TEXT
            priority: '37'
            section_name: Filters
            label: 'Exclude PostgreSQL server filter'
            description: 'Regex string to exclude discovered PostgreSQL servers by name.'
        - macro: '{$AZURE.PROXY}'
          description: 'Sets the HTTP proxy value. If this macro is empty, then no proxy is used.'
          config:
            type: TEXT
            priority: '6'
            section_name: Other
            label: 'HTTP proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AZURE.RESOURCE.GROUP.MATCHES}'
          value: '.*'
          description: 'This macro is used in discovery rules.'
          config:
            type: TEXT
            priority: '30'
            section_name: Filters
            label: 'Include resource group filter'
            description: 'Regex string to include discovered resource groups by name.'
        - macro: '{$AZURE.RESOURCE.GROUP.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in discovery rules.'
          config:
            type: TEXT
            priority: '31'
            section_name: Filters
            label: 'Exclude resource group filter'
            description: 'Regex string to exclude discovered resource groups by name.'
        - macro: '{$AZURE.SCALESET.LOCATION.MATCHES}'
          value: '.*'
          description: 'This macro is used in virtual machine scale sets discovery rule.'
          config:
            type: TEXT
            priority: '13'
            section_name: Filters
            label: 'Include VM scale set location filter'
            description: 'Regex string to include discovered VM scale set locations by name.'
        - macro: '{$AZURE.SCALESET.LOCATION.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in virtual machine scale sets discovery rule.'
          config:
            type: TEXT
            priority: '14'
            section_name: Filters
            label: 'Exclude VM scale set location filter'
            description: 'Regex string to exclude discovered VM scale set locations by name.'
        - macro: '{$AZURE.SCALESET.NAME.MATCHES}'
          value: '.*'
          description: 'This macro is used in virtual machine scale sets discovery rule.'
          config:
            type: TEXT
            priority: '11'
            section_name: Filters
            label: 'Include VM scale set filter'
            description: 'Regex string to include discovered VM scale sets by name.'
        - macro: '{$AZURE.SCALESET.NAME.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in virtual machine scale sets discovery rule.'
          config:
            type: TEXT
            priority: '12'
            section_name: Filters
            label: 'Exclude VM scale set filter'
            description: 'Regex string to exclude discovered VM scale sets by name.'
        - macro: '{$AZURE.SQL.INST.LOCATION.MATCHES}'
          value: '.*'
          description: 'This macro is used in Azure SQL Managed Instance discovery rule.'
          config:
            type: TEXT
            priority: '17'
            section_name: Filters
            label: 'Include SQL instance location filter'
            description: 'Regex string to include discovered Azure SQL managed instance locations by name.'
        - macro: '{$AZURE.SQL.INST.LOCATION.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in Azure SQL Managed Instance discovery rule.'
          config:
            type: TEXT
            priority: '18'
            section_name: Filters
            label: 'Exclude SQL instance location filter'
            description: 'Regex string to exclude discovered Azure SQL managed instance locations by name.'
        - macro: '{$AZURE.SQL.INST.NAME.MATCHES}'
          value: '.*'
          description: 'This macro is used in Azure SQL Managed Instance discovery rule.'
          config:
            type: TEXT
            priority: '15'
            section_name: Filters
            label: 'Include SQL instance filter'
            description: 'Regex string to include discovered Azure SQL managed instances by name.'
        - macro: '{$AZURE.SQL.INST.NAME.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in Azure SQL Managed Instance discovery rule.'
          config:
            type: TEXT
            priority: '16'
            section_name: Filters
            label: 'Exclude SQL instance filter'
            description: 'Regex string to exclude discovered Azure SQL managed instances by name.'
        - macro: '{$AZURE.STORAGE.ACC.AVAILABILITY}'
          value: '70'
          description: 'The warning threshold of the storage account availability.'
          config:
            type: TEXT
            priority: '27'
            section_name: Thresholds
            label: 'Storage account availability warning threshold'
            description: 'Warning threshold of the storage account availability, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.STORAGE.ACC.BLOB.AVAILABILITY}'
          value: '70'
          description: 'The warning threshold of the storage account blob services availability.'
          config:
            type: TEXT
            priority: '28'
            section_name: Thresholds
            label: 'Blob services availability warning threshold'
            description: 'Warning threshold of the storage account blob services availability, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.STORAGE.ACC.LOCATION.MATCHES}'
          value: '.*'
          description: 'This macro is used in storage accounts discovery rule.'
          config:
            type: TEXT
            priority: '25'
            section_name: Filters
            label: 'Include storage account location filter'
            description: 'Regex string to include discovered storage account locations by name.'
        - macro: '{$AZURE.STORAGE.ACC.LOCATION.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in storage accounts discovery rule.'
          config:
            type: TEXT
            priority: '26'
            section_name: Filters
            label: 'Exclude storage account location filter'
            description: 'Regex string to exclude discovered storage account locations by name.'
        - macro: '{$AZURE.STORAGE.ACC.NAME.MATCHES}'
          value: '.*'
          description: 'This macro is used in storage accounts discovery rule.'
          config:
            type: TEXT
            priority: '23'
            section_name: Filters
            label: 'Include storage account filter'
            description: 'Regex string to include discovered storage accounts by name.'
        - macro: '{$AZURE.STORAGE.ACC.NAME.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in storage accounts discovery rule.'
          config:
            type: TEXT
            priority: '24'
            section_name: Filters
            label: 'Exclude storage account filter'
            description: 'Regex string to exclude discovered storage accounts by name.'
        - macro: '{$AZURE.STORAGE.ACC.TABLE.AVAILABILITY}'
          value: '70'
          description: 'The warning threshold of the storage account table services availability.'
          config:
            type: TEXT
            priority: '29'
            section_name: Thresholds
            label: 'Table services availability warning threshold'
            description: 'Warning threshold of the storage account table services availability, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.SUBSCRIPTION.ID}'
          description: 'Microsoft Azure subscription ID.'
          config:
            type: TEXT
            priority: '1'
            label: 'Azure subscription ID'
            required: 'YES'
        - macro: '{$AZURE.TENANT.ID}'
          description: 'Microsoft Azure tenant ID.'
          config:
            type: TEXT
            priority: '2'
            label: 'Azure tenant ID'
            required: 'YES'
        - macro: '{$AZURE.VAULT.LOCATION.MATCHES}'
          value: '.*'
          description: 'This macro is used in Azure Vault discovery rule.'
          config:
            type: TEXT
            priority: '21'
            section_name: Filters
            label: 'Include vault location filter'
            description: 'Regex string to include discovered Azure Vault locations by name.'
        - macro: '{$AZURE.VAULT.LOCATION.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in Azure Vault discovery rule.'
          config:
            type: TEXT
            priority: '22'
            section_name: Filters
            label: 'Exclude vault location filter'
            description: 'Regex string to exclude discovered Azure Vault locations by name.'
        - macro: '{$AZURE.VAULT.NAME.MATCHES}'
          value: '.*'
          description: 'This macro is used in Azure Vault discovery rule.'
          config:
            type: TEXT
            priority: '19'
            section_name: Filters
            label: 'Include vaults filter'
            description: 'Regex string to include discovered Azure Vaults by name.'
        - macro: '{$AZURE.VAULT.NAME.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in Azure Vault discovery rule.'
          config:
            type: TEXT
            priority: '20'
            section_name: Filters
            label: 'Exclude vaults filter'
            description: 'Regex string to exclude discovered Azure Vaults by name.'
        - macro: '{$AZURE.VM.LOCATION.MATCHES}'
          value: '.*'
          description: 'This macro is used in virtual machines discovery rule.'
          config:
            type: TEXT
            priority: '9'
            section_name: Filters
            label: 'Include VM location filter'
            description: 'Regex string to include discovered virtual machine locations by name.'
        - macro: '{$AZURE.VM.LOCATION.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in virtual machines discovery rule.'
          config:
            type: TEXT
            priority: '10'
            section_name: Filters
            label: 'Exclude VM location filter'
            description: 'Regex string to exclude discovered virtual machine locations by name.'
        - macro: '{$AZURE.VM.NAME.MATCHES}'
          value: '.*'
          description: 'This macro is used in virtual machines discovery rule.'
          config:
            type: TEXT
            priority: '7'
            section_name: Filters
            label: 'Include virtual machines filter'
            description: 'Regex string to include discovered virtual machines by name.'
        - macro: '{$AZURE.VM.NAME.NOT.MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'This macro is used in virtual machines discovery rule.'
          config:
            type: TEXT
            priority: '8'
            section_name: Filters
            label: 'Exclude virtual machines filter'
            description: 'Regex string to exclude discovered virtual machines by name.'
      dashboards:
        - uuid: d30c78be41fe421cb98cedd7683a11f0
          name: 'Overview Azure Storage accounts'
          pages:
            - name: 'Storage transactions'
              widgets:
                - type: graphprototype
                  width: '72'
                  height: '25'
                  fields:
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'Azure by HTTP'
                        name: 'Azure: Transactions by storage [{#NAME}]'
                    - type: STRING
                      name: reference
                      value: AAAAA
                    - type: INTEGER
                      name: rows
                      value: '6'
            - name: 'Storage engress'
              widgets:
                - type: graphprototype
                  width: '72'
                  height: '25'
                  fields:
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'Azure by HTTP'
                        name: 'Azure: Storage account [{#NAME}] egress'
                    - type: STRING
                      name: reference
                      value: AAAAB
                    - type: INTEGER
                      name: rows
                      value: '6'
            - name: 'Storage ingress'
              widgets:
                - type: graphprototype
                  width: '72'
                  height: '20'
                  fields:
                    - type: GRAPH_PROTOTYPE
                      name: graphid.0
                      value:
                        host: 'Azure by HTTP'
                        name: 'Azure: Storage account [{#NAME}] ingress'
                    - type: STRING
                      name: reference
                      value: AAAAC
                    - type: INTEGER
                      name: rows
                      value: '5'
    - uuid: 29325098807848aa928b4192ad5e020f
      template: 'Azure Cosmos DB for MongoDB by HTTP'
      name: 'Azure Cosmos DB for MongoDB by HTTP'
      description: |
        This template is designed to monitor Microsoft Azure Cosmos DB for MongoDB by HTTP.
        It works without any external scripts and uses the script item.
        
        Setup:
          1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
            `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
            See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
          2. Link the template to a host.
          3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
        
        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: |
        ## Setup
        
        1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
        
              `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
        
        > See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
        
        2. Link the template to a host.
        3. Configure the macros: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure Cosmos DB ID`.
      vendor:
        name: Zabbix
        version: 7.4-1
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 9e247bdb17f44630b9440b59d5ef251b
          name: 'Autoscale max throughput'
          type: DEPENDENT
          key: azure.cosmosdb.autoscale.max.throughput
          description: 'The autoscale max throughput.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.AutoscaleMaxThroughput.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 35a7d2c96990407f937e07fd160266a9
          name: 'Get errors'
          type: DEPENDENT
          key: azure.cosmosdb.data.errors
          value_type: TEXT
          description: 'A list of errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: raw
          triggers:
            - uuid: dfd484aa8a4e4b759e4e34c5318c7176
              expression: 'length(last(/Azure Cosmos DB for MongoDB by HTTP/azure.cosmosdb.data.errors))>0'
              name: 'Azure Cosmos DB: There are errors in requests to API'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 647faea1597c4da6a3cd78694be8e77e
          name: 'Get data'
          type: SCRIPT
          key: azure.cosmosdb.data.get
          history: '0'
          value_type: TEXT
          params: |
            var AzureCosmosDB = {
            	params: {},
            	token: null,
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id', 'resource_id'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            
            		AzureCosmosDB.params = params;
            	},
            
            	login: function () {
            		var response, login = new HttpRequest();
            		if (typeof AzureCosmosDB.params.proxy !== 'undefined' && AzureCosmosDB.params.proxy !== '') {
            			login.setProxy(AzureCosmosDB.params.proxy);
            		}
            		login.addHeader('Content-Type: application/x-www-form-urlencoded');
            		response = login.post(
            			'https://login.microsoftonline.com/' + encodeURIComponent(AzureCosmosDB.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(AzureCosmosDB.params.app_id) + '&client_secret=' + encodeURIComponent(AzureCosmosDB.params.password)
            		);
            
            		if (login.getStatus() !== 200) {
            			throw 'Login failed with status code ' + login.getStatus() + ': ' + response;
            		}
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse login session response.';
            		}
            		if (!response.hasOwnProperty('access_token')) {
            			throw 'Authentication response does not contain access token.';
            		}
            		AzureCosmosDB.token = response['access_token'];
            	},
            
            	request: function (url) {
            		var response, request = new HttpRequest();
            		if (typeof AzureCosmosDB.params.proxy !== 'undefined' && AzureCosmosDB.params.proxy !== '') {
            			request.setProxy(AzureCosmosDB.params.proxy);
            		}
            		if (!AzureCosmosDB.token) {
            			throw 'Request does not contain access token.';
            		}
            		request.addHeader('Accept: application/json');
            		request.addHeader('Authorization: Bearer ' + AzureCosmosDB.token);
            		Zabbix.log(4, '[ AzureCosmosDB ] request url: ' + url);
            		response = request.get(url);
            
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	},
            
            	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;
            	},
            
            	getMetricsData: function () {
            		var data = {};
            		start_date = new Date((new Date().getTime()) - 600000).toISOString().replace(/\.\d+/, '');
            		end_date = new Date(new Date().getTime()).toISOString().replace(/\.\d+/, '');
            		endpoints = {
            			'availability': '/providers/Microsoft.Insights/metrics?metricnames=ServiceAvailability&api-version=2021-05-01&interval=PT1H&timespan=' + encodeURIComponent(start_date) + '/' + encodeURIComponent(end_date),
            			'requests': '/providers/Microsoft.Insights/metrics?metricnames=DataUsage,IndexUsage,DocumentQuota,AvailableStorage,DocumentCount,NormalizedRUConsumption,PhysicalPartitionThroughputInfo,PhysicalPartitionSizeInfo,AutoscaleMaxThroughput,ProvisionedThroughput,TotalRequests,TotalRequestUnits,MetadataRequests,MongoRequests,MongoRequestCharge,ServerSideLatency,ServerSideLatencyGateway,ServerSideLatencyDirect,ReplicationLatency&api-version=2021-05-01&timespan=' + encodeURIComponent(start_date) + '/' + encodeURIComponent(end_date),
            		};
            
            		Object.keys(endpoints).forEach(function (field) {
            			data[field] = {};
            			try {
            				metrics = AzureCosmosDB.request('https://management.azure.com' + AzureCosmosDB.params.resource_id + endpoints[field]);
            				if (!metrics.hasOwnProperty('value')) {
            					throw 'Failed getting required field. Check debug log for more information.';
            				}
            
            				for (k in metrics.value) {
            					key = AzureCosmosDB.getField(metrics.value[k], 'name.value')
            					if (metrics.value[k].timeseries.length === 0) {
            						metrics.value[k].timeseries.push({ 'data': ['nodata'] })
            					}
            					data[field][key] = AzureCosmosDB.getField(metrics.value[k], 'timeseries.0.data.0');
            				}
            			}
            			catch (error) {
            				data.error = error.toString();
            			}
            		});
            		return data
            	}
            
            };
            
            try {
            	AzureCosmosDB.setParams(JSON.parse(value));
            	AzureCosmosDB.login();
            	return JSON.stringify(AzureCosmosDB.getMetricsData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AzureCosmosDB ] ERROR: ' + error);
            	return JSON.stringify({ 'error': error });
            }
          description: 'The result of API requests is expressed in the JSON.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: resource_id
              value: '{$AZURE.RESOURCE.ID}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: 947a2eb530754a609fa81c59e29fe7b7
          name: 'Data usage'
          type: DEPENDENT
          key: azure.cosmosdb.data.usage
          units: B
          description: 'The total data usage.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.DataUsage.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 0bf3da9168144016b663c9b8e76447fa
          name: 'Document count'
          type: DEPENDENT
          key: azure.cosmosdb.document.count
          description: 'The total document count.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.DocumentCount.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 7fa0f59f8cfa4d9e83086b203e4f71ea
          name: 'Document quota'
          type: DEPENDENT
          key: azure.cosmosdb.document.quota
          units: B
          description: 'The total storage quota.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.DocumentQuota.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: storage
        - uuid: b09f9445d960415185457b89b6a73452
          name: 'Index usage'
          type: DEPENDENT
          key: azure.cosmosdb.index.usage
          units: B
          description: 'The total index usage.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.IndexUsage.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: storage
        - uuid: cd35f04b180542cda50dc5d4e979e54e
          name: 'Metadata requests'
          type: DEPENDENT
          key: azure.cosmosdb.metadata.requests
          description: |
            The count of metadata requests.
            Cosmos DB maintains system metadata collection for each account, which allows you to enumerate collections, databases, etc., and their configurations, free of charge.
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.MetadataRequests.count
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: storage
        - uuid: e42cf83e456a490295a84cfe9eb288ef
          name: 'Mongo requests'
          type: DEPENDENT
          key: azure.cosmosdb.mongo.requests
          description: 'The number of Mongo requests made.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.MongoRequests.count
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 8fd4068986af444799ae64c6bc8f16a6
          name: 'Mongo request charge'
          type: DEPENDENT
          key: azure.cosmosdb.mongo.requests.charge
          description: 'The Mongo request units consumed.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.MongoRequestCharge.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: storage
        - uuid: fda6b39ce6ef4b8c8418b2e123ecdd17
          name: 'Normalized RU consumption'
          type: DEPENDENT
          key: azure.cosmosdb.normalized.ru.consumption
          units: '%'
          description: 'The max RU consumption percentage per minute.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.NormalizedRUConsumption.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: storage
        - uuid: be6800214a0443e899c40f8a4b6c3f21
          name: 'Physical partition size'
          type: DEPENDENT
          key: azure.cosmosdb.physical.partition.size
          units: B
          description: 'The physical partition size in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.PhysicalPartitionSizeInfo.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: storage
        - uuid: e30d5eadde15427484e7a0d1cb38e9e3
          name: 'Physical partition throughput'
          type: DEPENDENT
          key: azure.cosmosdb.physical.partition.throughput
          description: 'The physical partition throughput.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.PhysicalPartitionThroughputInfo.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 49311bbfb2584a46b42ed1a7d8fcfd94
          name: 'Provisioned throughput'
          type: DEPENDENT
          key: azure.cosmosdb.provisioned.throughput
          description: 'The provisioned throughput.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.ProvisionedThroughput.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 6d7175e27d10406191c883dc2e5949e4
          name: 'Replication latency, P99'
          type: DEPENDENT
          key: azure.cosmosdb.replication.latency
          value_type: FLOAT
          units: s
          description: 'The P99 replication latency across source and target regions for geo-enabled account.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.ReplicationLatency.average
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '0.001'
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: network
        - uuid: d9b5af0c71874114b48464ce20f8cf3d
          name: 'Server side latency'
          type: DEPENDENT
          key: azure.cosmosdb.server.side.latency
          value_type: FLOAT
          units: s
          description: 'The server side latency.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.ServerSideLatency.average
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '0.001'
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: network
        - uuid: 7587d3750d1643f085db5931670dc2f3
          name: 'Server side latency, direct'
          type: DEPENDENT
          key: azure.cosmosdb.server.side.latency.direct
          value_type: FLOAT
          units: s
          description: 'The server side latency in direct connection mode.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.ServerSideLatencyDirect.average
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '0.001'
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: network
        - uuid: 0aefdc3101fe4bcba4743d6e32671554
          name: 'Server side latency, gateway'
          type: DEPENDENT
          key: azure.cosmosdb.server.side.latency.gateway
          value_type: FLOAT
          units: s
          description: 'The server side latency in gateway connection mode.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.ServerSideLatencyGateway.average
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '0.001'
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: network
        - uuid: 42bd03c1753b4f19bc9793b03834cd3d
          name: 'Service availability'
          type: DEPENDENT
          key: azure.cosmosdb.service.availability
          value_type: FLOAT
          units: '%'
          description: 'The account requests availability at one hour granularity.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.availability.ServiceAvailability.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: health
          triggers:
            - uuid: c7649cd317f04a3d8fec0eebe3df6766
              expression: '(min(/Azure Cosmos DB for MongoDB by HTTP/azure.cosmosdb.service.availability,#3))<{$AZURE.DB.COSMOS.MONGO.AVAILABILITY}'
              name: 'Azure Cosmos DB: Cosmos DB for MongoDB account: Availability is low'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              tags:
                - tag: scope
                  value: availability
        - uuid: f4d4d2def5e945ab9048ada4813b7f04
          name: 'Total request units'
          type: DEPENDENT
          key: azure.cosmosdb.total.request.units
          value_type: FLOAT
          description: 'The request units consumed per minute.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.TotalRequestUnits.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 3dd2cd4edb7746edb9d917c83b280ca3
          name: 'Total requests'
          type: DEPENDENT
          key: azure.cosmosdb.total.requests
          description: 'Number of requests per minute.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.requests.TotalRequests.count
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.cosmosdb.data.get
          tags:
            - tag: component
              value: storage
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: management
        - tag: subclass
          value: nosql
        - tag: target
          value: azure
        - tag: target
          value: cosmosdb
        - tag: target
          value: mongodb
      macros:
        - macro: '{$AZURE.APP.ID}'
          description: 'The App ID of Microsoft Azure.'
          config:
            type: TEXT
            priority: '3'
            label: 'Azure App ID'
            required: 'YES'
        - macro: '{$AZURE.DATA.TIMEOUT}'
          value: 15s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '7'
            section_name: Other
            label: 'API timeout'
            description: 'API response timeout, in seconds.'
        - macro: '{$AZURE.DB.COSMOS.MONGO.AVAILABILITY}'
          value: '70'
          description: 'The warning threshold of the Cosmos DB for MongoDB service availability.'
          config:
            type: TEXT
            priority: '6'
            section_name: Other
            label: 'Cosmos DB warning threshold'
            description: 'Warning threshold of the Cosmos DB for MongoDB service availability. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.PASSWORD}'
          type: SECRET_TEXT
          description: 'Microsoft Azure password.'
          config:
            type: TEXT
            priority: '4'
            label: 'Azure password'
            required: 'YES'
        - macro: '{$AZURE.PROXY}'
          description: 'Sets the 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: '{$AZURE.RESOURCE.ID}'
          description: 'Microsoft Azure Cosmos DB ID.'
          config:
            type: TEXT
            priority: '5'
            label: 'Azure Cosmos DB ID'
            required: 'YES'
        - macro: '{$AZURE.SUBSCRIPTION.ID}'
          description: 'Microsoft Azure subscription ID.'
          config:
            type: TEXT
            priority: '1'
            label: 'Azure subscription ID'
            required: 'YES'
        - macro: '{$AZURE.TENANT.ID}'
          description: 'Microsoft Azure tenant ID.'
          config:
            type: TEXT
            priority: '2'
            label: 'Azure tenant ID'
            required: 'YES'
      dashboards:
        - uuid: 323fb91b388a44bfbd4b7d634f6e6b6c
          name: 'Overview Azure Cosmos DB for MongoDB'
          pages:
            - widgets:
                - type: item
                  name: 'Service Availability'
                  width: '18'
                  height: '4'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: STRING
                      name: down_color
                      value: FF0000
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Cosmos DB for MongoDB by HTTP'
                        key: azure.cosmosdb.service.availability
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: show.1
                      value: '4'
                    - type: STRING
                      name: units
                      value: '%'
                    - type: STRING
                      name: units_color
                      value: 66BB6A
                    - type: STRING
                      name: up_color
                      value: 4CAF50
                    - type: STRING
                      name: value_color
                      value: 66BB6A
                - type: graph
                  'y': '4'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Cosmos DB for MongoDB by HTTP'
                        name: 'Azure MongoDB: Usage'
                    - type: STRING
                      name: reference
                      value: AAAAC
                - type: graph
                  'y': '9'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Cosmos DB for MongoDB by HTTP'
                        name: 'Azure MongoDB: Requests'
                    - type: STRING
                      name: reference
                      value: AAAAB
                - type: graph
                  'y': '14'
                  width: '72'
                  height: '5'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Cosmos DB for MongoDB by HTTP'
                        name: 'Azure MongoDB: Latency'
                    - type: STRING
                      name: reference
                      value: AAAAA
                - type: item
                  name: 'Provisioned Throughput'
                  x: '18'
                  width: '18'
                  height: '4'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Cosmos DB for MongoDB by HTTP'
                        key: azure.cosmosdb.provisioned.throughput
                    - type: INTEGER
                      name: show.0
                      value: '2'
                - type: item
                  name: 'Normalized RU Consumption'
                  x: '36'
                  width: '18'
                  height: '4'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Cosmos DB for MongoDB by HTTP'
                        key: azure.cosmosdb.normalized.ru.consumption
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Document Count'
                  x: '54'
                  width: '18'
                  height: '4'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Cosmos DB for MongoDB by HTTP'
                        key: azure.cosmosdb.document.count
                    - type: INTEGER
                      name: show.0
                      value: '2'
    - uuid: c0263df8d8c14d30b24afcf45a6a354f
      template: 'Azure Cost Management by HTTP'
      name: 'Azure Cost Management by HTTP'
      description: |
        This template is designed to monitor Microsoft Cost Management by HTTP.
        It works without any external scripts and uses the script item.
        
        Setup:
          1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
            `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
            See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
          2. Link the template to a host.
          3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}.
        
        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 is designed to monitor Microsoft Cost Management by HTTP.
        It works without any external scripts and uses the script item.
        
        ## Setup
        
        1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
        
              `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
        
        > See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
        
        2. Link the template to a host.
        3. Configure the macros: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`.
      vendor:
        name: Zabbix
        version: 7.4-2
      groups:
        - name: Templates/Cloud
      items:
        - uuid: f50c96da86654a25b937756cc7f7010e
          name: 'Get daily costs'
          type: SCRIPT
          key: azure.get.daily.costs
          delay: 0s;h/5m/30
          history: '0'
          value_type: TEXT
          params: |
            var AzureCost = {
            	params: {},
            	token: null,
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            		AzureCost.params = params;
            	},
            
            	login: function () {
            		var response,
            			login = new HttpRequest();
            
            		if (typeof AzureCost.params.proxy !== 'undefined' && AzureCost.params.proxy !== '') {
            			login.setProxy(AzureCost.params.proxy);
            		}
            
            		login.addHeader('Content-Type: application/x-www-form-urlencoded');
            		response = login.post(
            			'https://login.microsoftonline.com/' + encodeURIComponent(AzureCost.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(AzureCost.params.app_id) + '&client_secret=' + encodeURIComponent(AzureCost.params.password)
            		);
            
            		if (login.getStatus() !== 200) {
            			throw 'Login failed with status code ' + login.getStatus() + ': ' + response;
            		}
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse login session response.';
            		}
            		if (!response.hasOwnProperty('access_token')) {
            			throw 'Authentication response does not contain access token.';
            		}
            
            		AzureCost.token = response['access_token'];
            	},
            
            	request: function (url, body) {
            		if (typeof body === 'undefined' || body === null) {
            			body = '';
            		}
            		var response,
            			headers,
            			regex = /-retry-after":"(\d+)"/,
            			ratelimit,
            			request = new HttpRequest();
            
            		if (typeof AzureCost.params.proxy !== 'undefined' && AzureCost.params.proxy !== '') {
            			request.setProxy(AzureCost.params.proxy);
            		}
            		if (!AzureCost.token) {
            			throw 'Request does not contain access token.';
            		}
            		request.addHeader('Accept: application/json');
            		request.addHeader('Content-Type: application/json');
            		request.addHeader('Authorization: Bearer ' + AzureCost.token);
            
            		Zabbix.log(4, '[ AzureCost ] request url: ' + url);
            
            		response = request.post(url, body);
            		headers = JSON.stringify(request.getHeaders());
            
            		if (headers.match(regex) !== null && request.getStatus() === 429) {
            			ratelimit = headers.match(regex)[1];
            			Zabbix.log(4, '[ AzureCost ] Microsoft Cost Management have rate limit requests per 1 minute, retrying after ' + ratelimit + ' seconds');
            			Zabbix.sleep(ratelimit * 1010);
            			response = request.post(url, body);
            		}
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	},
            
            	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;
            	},
            
            	getCost: function () {
            		var metricData = {},
            			today = new Date(),
            			start_date = new Date(today);
            		start_date.setDate(today.getDate() - 1);
            
            		bodyRawCost = {
            			type: 'Usage',
            			'timeframe': 'Custom',
            			'timePeriod': {
            				'from': start_date,
            				'to': start_date
            			},
            			dataset: {
            				granularity: 'Daily',
            				aggregation: {
            					totalCost: {
            						name: 'PreTaxCost',
            						function: 'Sum'
            					}
            				},
            				grouping: [
            					{
            						type: 'Dimension',
            						name: 'Meter',
            					},
            					{
            						type: 'Dimension',
            						name: 'MeterSubcategory',
            					},
            					{
            						type: 'Dimension',
            						name: 'ResourceGroup',
            					},
            					{
            						type: 'Dimension',
            						name: 'ServiceName',
            					},
            					{
            						type: 'Dimension',
            						name: 'ResourceLocation',
            					}
            				]
            			}
            		};
            		metricData = AzureCost.request('https://management.azure.com/subscriptions/' + AzureCost.params.subscription_id + '/providers/Microsoft.CostManagement/query?api-version=2023-11-01', JSON.stringify(bodyRawCost));
            
            		var columns = AzureCost.getField(metricData, 'properties.columns');
            
            		return transformedData = {
            			data: AzureCost.getField(metricData, 'properties.rows').map(function (row) {
            				rowData = {};
            				columns.forEach(function (column, i) {
            					columnName = columns[i].name;
            					columnType = columns[i].type;
            					cellValue = row[i];
            					rowData[columnName] = column.type === "Number" ? cellValue.toString() : cellValue;
            				});
            				rowData.UsageDate = rowData.UsageDate.replace(/(\d{4})(\d{2})(\d{2})/, "$1-$2-$3");
            
            				return rowData;
            			})
            		};
            	}
            };
            
            try {
            	AzureCost.setParams(JSON.parse(value));
            	AzureCost.login();
            
            	return JSON.stringify(AzureCost.getCost());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AzureCost ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: 'The result of API requests is expressed in the JSON.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: dc9824169b414303a75c5d98421bd6f8
          name: 'Azure Cost: Get daily costs errors'
          type: DEPENDENT
          key: azure.get.daily.costs.errors
          value_type: TEXT
          description: 'A list of errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.get.daily.costs
          tags:
            - tag: component
              value: raw
          triggers:
            - uuid: 503b3d5d008e4ad7b11384a3bd0c991c
              expression: 'length(last(/Azure Cost Management by HTTP/azure.get.daily.costs.errors))>0'
              name: 'Azure Cost: There are errors in requests to API'
              event_name: 'Azure Cost: Error in daily costs requests to API'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              tags:
                - tag: scope
                  value: availability
        - uuid: bbf6a0b136464d76a535ca016dcb8ae1
          name: 'Get monthly costs'
          type: SCRIPT
          key: azure.get.monthly.costs
          delay: 0s;h/12
          history: '0'
          value_type: TEXT
          params: |
            var AzureCost = {
            	params: {},
            	token: null,
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id', 'month'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            		AzureCost.params = params;
            
            		today = new Date();
            		AzureCost.params.end_date = today.toISOString();
            		month = today.getMonth();
            		today.setMonth(month - params.month);
            		AzureCost.params.start_time = new Date(today.getFullYear(), today.getMonth()).toISOString();
            	},
            
            	login: function () {
            		var response,
            			login = new HttpRequest();
            
            		if (typeof AzureCost.params.proxy !== 'undefined' && AzureCost.params.proxy !== '') {
            			login.setProxy(AzureCost.params.proxy);
            		}
            
            		login.addHeader('Content-Type: application/x-www-form-urlencoded');
            		response = login.post(
            			'https://login.microsoftonline.com/' + encodeURIComponent(AzureCost.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(AzureCost.params.app_id) + '&client_secret=' + encodeURIComponent(AzureCost.params.password)
            		);
            
            		if (login.getStatus() !== 200) {
            			throw 'Login failed with status code ' + login.getStatus() + ': ' + response;
            		}
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse login session response.';
            		}
            		if (!response.hasOwnProperty('access_token')) {
            			throw 'Authentication response does not contain access token.';
            		}
            
            		AzureCost.token = response['access_token'];
            	},
            
            	request: function (url, body) {
            		if (typeof body === 'undefined' || body === null) {
            			body = '';
            		}
            		var response,
            			headers,
            			regex = /-retry-after":"(\d+)"/,
            			ratelimit,
            			request = new HttpRequest();
            
            		if (typeof AzureCost.params.proxy !== 'undefined' && AzureCost.params.proxy !== '') {
            			request.setProxy(AzureCost.params.proxy);
            		}
            		if (!AzureCost.token) {
            			throw 'Request does not contain access token.';
            		}
            		request.addHeader('Accept: application/json');
            		request.addHeader('Content-Type: application/json');
            		request.addHeader('Authorization: Bearer ' + AzureCost.token);
            
            		Zabbix.log(4, '[ AzureCost ] request url: ' + url);
            
            		response = request.post(url, body);
            		headers = JSON.stringify(request.getHeaders());
            
            		if (headers.match(regex) !== null && request.getStatus() === 429) {
            			ratelimit = headers.match(regex)[1];
            			Zabbix.log(4, '[ AzureCost ] Microsoft Cost Management have rate limit requests per 1 minute, retrying after ' + ratelimit + ' seconds');
            			Zabbix.sleep(ratelimit * 1010);
            			response = request.post(url, body);
            		}
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	},
            
            	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;
            	},
            
            	getCost: function (grouping) {
            		var metricData = {},
            			bodyRawCost = {
            				type: 'Usage',
            				timeframe: 'Custom',
            				timePeriod: {
            					from: AzureCost.params.start_time,
            					to: AzureCost.params.end_date
            				},
            				dataset: {
            					aggregation: {
            						totalCost: {
            							name: 'PreTaxCost',
            							function: 'Sum'
            						}
            					},
            					grouping: [
            						{
            							type: 'Dimension',
            							name: 'BillingMonth'
            						},
            						{
            							type: 'Dimension',
            							name: grouping
            						},
            					]
            				}
            			};
            
            		metricData = AzureCost.request('https://management.azure.com/subscriptions/' + AzureCost.params.subscription_id + '/providers/Microsoft.CostManagement/query?api-version=2023-11-01', JSON.stringify(bodyRawCost));
            
            		var columns = AzureCost.getField(metricData, 'properties.columns');
            
            		return transformedData = {
            			data: AzureCost.getField(metricData, 'properties.rows').map(function (row) {
            				rowData = {};
            				columns.forEach(function (column, i) {
            					columnName = columns[i].name;
            					cellValue = row[i];
            					rowData[columnName] = column.type === "Number" ? cellValue.toString() : cellValue;
            				});
            				rowData.BillingMonth = rowData.BillingMonth.slice(0, 7);
            
            				return rowData;
            			})
            		};
            	}
            };
            
            try {
            	AzureCost.setParams(JSON.parse(value));
            	AzureCost.login();
            
            	serviceCost = AzureCost.getCost('ServiceName');
            	resourceGroupCost = AzureCost.getCost('ResourceGroup');
            	resourceLocationCost = AzureCost.getCost('ResourceLocation');
            	monthCost = AzureCost.getCost('SubscriptionId');
            
            	return JSON.stringify({ resourceGroupCost, resourceLocationCost, serviceCost, monthCost });
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AzureCost ] ERROR: ' + error);
            
            	return JSON.stringify({ 'error': error });
            }
          description: 'The result of API requests is expressed in the JSON.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: month
              value: '{$AZURE.BILLING.MONTH}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: 30dae868261844f39c811cdba93628eb
          name: 'Azure Cost: Get monthly costs errors'
          type: DEPENDENT
          key: azure.get.monthly.costs.errors
          value_type: TEXT
          description: 'A list of errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.get.monthly.costs
          tags:
            - tag: component
              value: raw
          triggers:
            - uuid: 2ea11e17fd734dee80219e22a8073e01
              expression: 'length(last(/Azure Cost Management by HTTP/azure.get.monthly.costs.errors))>0'
              name: 'Azure Cost: There are errors in requests to API'
              event_name: 'Azure Cost: Error in monthly costs requests to API'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              tags:
                - tag: scope
                  value: availability
      discovery_rules:
        - uuid: 1220188c7a1c4df8b75e9021c4515149
          name: 'Azure daily costs by services discovery'
          type: DEPENDENT
          key: azure.daily.services.costs.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AZURE.RESOURCE.GROUP}'
                value: '{$AZURE.LLD.FILTER.RESOURCE.GROUP.MATCHES}'
              - macro: '{#AZURE.RESOURCE.GROUP}'
                value: '{$AZURE.LLD.FILTER.RESOURCE.GROUP.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#AZURE.RESOURCE.LOCATION}'
                value: '{$AZURE.LLD.FILTER.RESOURCE.LOCATION.MATCHES}'
              - macro: '{#AZURE.RESOURCE.LOCATION}'
                value: '{$AZURE.LLD.FILTER.RESOURCE.LOCATION.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
              - macro: '{#AZURE.SERVICE.NAME}'
                value: '{$AZURE.LLD.FILTER.SERVICE.MATCHES}'
              - macro: '{#AZURE.SERVICE.NAME}'
                value: '{$AZURE.LLD.FILTER.SERVICE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery of daily costs by services.'
          item_prototypes:
            - uuid: 848ccd4cec2c4902990aa25f90f502a8
              name: 'Service ["{#AZURE.SERVICE.NAME}"]: Meter ["{#AZURE.BILLING.METER}"]: Subcategory ["{#AZURE.BILLING.METER.SUBCATEGORY}"] daily cost'
              type: DEPENDENT
              key: 'azure.daily.cost["{#AZURE.SERVICE.NAME}", "{#AZURE.BILLING.METER}", "{#AZURE.BILLING.METER.SUBCATEGORY}","{#AZURE.RESOURCE.GROUP}"]'
              value_type: FLOAT
              units: '!{#AZURE.BILLING.UNIT}'
              description: 'The daily cost by service {#AZURE.SERVICE.NAME}, meter {#AZURE.BILLING.METER}, subcategory {#AZURE.BILLING.METER.SUBCATEGORY}.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.data.[?(@.ServiceName == "{#AZURE.SERVICE.NAME}" && @.Meter == "{#AZURE.BILLING.METER}" && @.MeterSubcategory == "{#AZURE.BILLING.METER.SUBCATEGORY}")].PreTaxCost.first()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: azure.get.daily.costs
              tags:
                - tag: component
                  value: cost
                - tag: location
                  value: '{#AZURE.RESOURCE.LOCATION}'
                - tag: meter
                  value: '{#AZURE.BILLING.METER}'
                - tag: resource-group
                  value: '{#AZURE.RESOURCE.GROUP}'
                - tag: service
                  value: '{#AZURE.SERVICE.NAME}'
          graph_prototypes:
            - uuid: 2a1e03e65b1c40cba783493871e245d5
              name: 'Daily Cost: "{#AZURE.SERVICE.NAME}","{#AZURE.BILLING.METER}","{#AZURE.BILLING.METER.SUBCATEGORY}","{#AZURE.RESOURCE.GROUP}"'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2E7D32
                  item:
                    host: 'Azure Cost Management by HTTP'
                    key: 'azure.daily.cost["{#AZURE.SERVICE.NAME}", "{#AZURE.BILLING.METER}", "{#AZURE.BILLING.METER.SUBCATEGORY}","{#AZURE.RESOURCE.GROUP}"]'
          master_item:
            key: azure.get.daily.costs
          lld_macro_paths:
            - lld_macro: '{#AZURE.BILLING.METER.SUBCATEGORY}'
              path: $.MeterSubcategory
            - lld_macro: '{#AZURE.BILLING.METER}'
              path: $.Meter
            - lld_macro: '{#AZURE.BILLING.UNIT}'
              path: $.Currency
            - lld_macro: '{#AZURE.RESOURCE.GROUP}'
              path: $.ResourceGroup
            - lld_macro: '{#AZURE.RESOURCE.LOCATION}'
              path: $.ResourceLocation
            - lld_macro: '{#AZURE.SERVICE.NAME}'
              path: $.ServiceName
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.data
              error_handler: DISCARD_VALUE
        - uuid: 9c65b60a8e1840dd81367aefe6b0de18
          name: 'Azure monthly costs discovery'
          type: DEPENDENT
          key: azure.monthly.costs.discovery
          description: 'Discovery of monthly costs.'
          item_prototypes:
            - uuid: f91a60d2c1124eb6b297539b0a115c66
              name: 'Month ["{#AZURE.BILLING.MONTH}"] cost'
              type: DEPENDENT
              key: 'azure.monthly.cost["{#AZURE.BILLING.MONTH}"]'
              value_type: FLOAT
              units: '!{#AZURE.BILLING.UNIT}'
              description: 'The monthly cost.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.monthCost.data.[?(@.BillingMonth == "{#AZURE.BILLING.MONTH}")].PreTaxCost.sum()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: azure.get.monthly.costs
              tags:
                - tag: component
                  value: cost
                - tag: month
                  value: '{#AZURE.BILLING.MONTH}'
          graph_prototypes:
            - uuid: 347342d3d0cc478bab33036872570cdb
              name: 'Azure Cost: Month ["{#AZURE.BILLING.MONTH}"] cost'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2E7D32
                  item:
                    host: 'Azure Cost Management by HTTP'
                    key: 'azure.monthly.cost["{#AZURE.BILLING.MONTH}"]'
          master_item:
            key: azure.get.monthly.costs
          lld_macro_paths:
            - lld_macro: '{#AZURE.BILLING.MONTH}'
              path: $.BillingMonth
            - lld_macro: '{#AZURE.BILLING.UNIT}'
              path: $.Currency
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.monthCost.data
              error_handler: DISCARD_VALUE
        - uuid: e9a4bf192feb4472aedd40ba2371d286
          name: 'Azure monthly costs by location discovery'
          type: DEPENDENT
          key: azure.monthly.location.costs.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AZURE.RESOURCE.LOCATION}'
                value: '{$AZURE.LLD.FILTER.RESOURCE.LOCATION.MATCHES}'
              - macro: '{#AZURE.RESOURCE.LOCATION}'
                value: '{$AZURE.LLD.FILTER.RESOURCE.LOCATION.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery of monthly costs by location.'
          item_prototypes:
            - uuid: 7fb097f81a8445acaa6b17bdc4daaaa6
              name: 'Location: ["{#AZURE.RESOURCE.LOCATION}"]: Month ["{#AZURE.BILLING.MONTH}"] cost'
              type: DEPENDENT
              key: 'azure.monthly.location.cost["{#AZURE.RESOURCE.LOCATION}", "{#AZURE.BILLING.MONTH}"]'
              value_type: FLOAT
              units: '!{#AZURE.BILLING.UNIT}'
              description: 'The monthly cost by location {#AZURE.RESOURCE.LOCATION}.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.resourceLocationCost.data.[?(@.BillingMonth == "{#AZURE.BILLING.MONTH}")]'
                  error_handler: DISCARD_VALUE
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.ResourceLocation == "{#AZURE.RESOURCE.LOCATION}")].PreTaxCost.sum()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: azure.get.monthly.costs
              tags:
                - tag: component
                  value: cost
                - tag: location
                  value: '{#AZURE.RESOURCE.LOCATION}'
                - tag: month
                  value: '{#AZURE.BILLING.MONTH}'
          graph_prototypes:
            - uuid: e3df27afabb147d3ae07e1a2fa36e89a
              name: 'Azure Cost: ["{#AZURE.RESOURCE.LOCATION}"]: Month ["{#AZURE.BILLING.MONTH}"] cost'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2E7D32
                  item:
                    host: 'Azure Cost Management by HTTP'
                    key: 'azure.monthly.location.cost["{#AZURE.RESOURCE.LOCATION}", "{#AZURE.BILLING.MONTH}"]'
          master_item:
            key: azure.get.monthly.costs
          lld_macro_paths:
            - lld_macro: '{#AZURE.BILLING.MONTH}'
              path: $.BillingMonth
            - lld_macro: '{#AZURE.BILLING.UNIT}'
              path: $.Currency
            - lld_macro: '{#AZURE.RESOURCE.LOCATION}'
              path: $.ResourceLocation
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.resourceLocationCost.data
              error_handler: DISCARD_VALUE
        - uuid: 4dfa3b60721e463d97f2f820106f816d
          name: 'Azure monthly costs by resource group discovery'
          type: DEPENDENT
          key: azure.monthly.resource.group.costs.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AZURE.RESOURCE.GROUP}'
                value: '{$AZURE.LLD.FILTER.RESOURCE.GROUP.MATCHES}'
              - macro: '{#AZURE.RESOURCE.GROUP}'
                value: '{$AZURE.LLD.FILTER.RESOURCE.GROUP.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery of monthly costs by resource group.'
          item_prototypes:
            - uuid: 9a5ed573ac374c08abf81f2b7296f260
              name: 'Resource group: ["{#AZURE.RESOURCE.GROUP}"]: Month ["{#AZURE.BILLING.MONTH}"] cost'
              type: DEPENDENT
              key: 'azure.monthly.resource.group.cost["{#AZURE.RESOURCE.GROUP}", "{#AZURE.BILLING.MONTH}"]'
              value_type: FLOAT
              units: '!{#AZURE.BILLING.UNIT}'
              description: 'The monthly cost by resource group {#AZURE.RESOURCE.GROUP}.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.resourceGroupCost.data.[?(@.BillingMonth == "{#AZURE.BILLING.MONTH}")]'
                  error_handler: DISCARD_VALUE
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.ResourceGroup == "{#AZURE.RESOURCE.GROUP}")].PreTaxCost.sum()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: azure.get.monthly.costs
              tags:
                - tag: component
                  value: cost
                - tag: month
                  value: '{#AZURE.BILLING.MONTH}'
                - tag: resource-group
                  value: '{#AZURE.RESOURCE.GROUP}'
          graph_prototypes:
            - uuid: fab17244d2c648e089c57c99615af537
              name: 'Azure Cost: ["{#AZURE.RESOURCE.GROUP}"]: Month ["{#AZURE.BILLING.MONTH}"] cost'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2E7D32
                  item:
                    host: 'Azure Cost Management by HTTP'
                    key: 'azure.monthly.resource.group.cost["{#AZURE.RESOURCE.GROUP}", "{#AZURE.BILLING.MONTH}"]'
          master_item:
            key: azure.get.monthly.costs
          lld_macro_paths:
            - lld_macro: '{#AZURE.BILLING.MONTH}'
              path: $.BillingMonth
            - lld_macro: '{#AZURE.BILLING.UNIT}'
              path: $.Currency
            - lld_macro: '{#AZURE.RESOURCE.GROUP}'
              path: $.ResourceGroup
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.resourceGroupCost.data
              error_handler: DISCARD_VALUE
        - uuid: b9b024a7e42540f0b8387af77367b15c
          name: 'Azure monthly costs by services discovery'
          type: DEPENDENT
          key: azure.monthly.services.costs.discovery
          filter:
            evaltype: AND
            conditions:
              - macro: '{#AZURE.SERVICE.NAME}'
                value: '{$AZURE.LLD.FILTER.SERVICE.MATCHES}'
              - macro: '{#AZURE.SERVICE.NAME}'
                value: '{$AZURE.LLD.FILTER.SERVICE.NOT_MATCHES}'
                operator: NOT_MATCHES_REGEX
          description: 'Discovery of monthly costs by services.'
          item_prototypes:
            - uuid: dbad6436c70e41268e3b59c2a7f0e2a2
              name: 'Service ["{#AZURE.SERVICE.NAME}"]: Month ["{#AZURE.BILLING.MONTH}"] cost'
              type: DEPENDENT
              key: 'azure.monthly.service.cost["{#AZURE.SERVICE.NAME}", "{#AZURE.BILLING.MONTH}"]'
              value_type: FLOAT
              units: '!{#AZURE.BILLING.UNIT}'
              description: 'The monthly cost by service {#AZURE.SERVICE.NAME}.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$.serviceCost.data.[?(@.BillingMonth == "{#AZURE.BILLING.MONTH}")]'
                  error_handler: DISCARD_VALUE
                - type: JSONPATH
                  parameters:
                    - '$.[?(@.ServiceName == "{#AZURE.SERVICE.NAME}")].PreTaxCost.sum()'
                  error_handler: DISCARD_VALUE
              master_item:
                key: azure.get.monthly.costs
              tags:
                - tag: component
                  value: cost
                - tag: month
                  value: '{#AZURE.BILLING.MONTH}'
                - tag: service
                  value: '{#AZURE.SERVICE.NAME}'
          graph_prototypes:
            - uuid: 31f1e30f99ed426d81b48411cc7ffd7f
              name: 'Azure Cost: ["{#AZURE.SERVICE.NAME}"]: Month ["{#AZURE.BILLING.MONTH}"] cost'
              graph_items:
                - drawtype: GRADIENT_LINE
                  color: 2E7D32
                  item:
                    host: 'Azure Cost Management by HTTP'
                    key: 'azure.monthly.service.cost["{#AZURE.SERVICE.NAME}", "{#AZURE.BILLING.MONTH}"]'
          master_item:
            key: azure.get.monthly.costs
          lld_macro_paths:
            - lld_macro: '{#AZURE.BILLING.MONTH}'
              path: $.BillingMonth
            - lld_macro: '{#AZURE.BILLING.UNIT}'
              path: $.Currency
            - lld_macro: '{#AZURE.SERVICE.NAME}'
              path: $.ServiceName
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.serviceCost.data
              error_handler: DISCARD_VALUE
      tags:
        - tag: class
          value: cloud
        - tag: target
          value: azure
        - tag: target
          value: cost
      macros:
        - macro: '{$AZURE.APP.ID}'
          description: 'The App ID of Microsoft Azure.'
          config:
            type: TEXT
            priority: '3'
            label: 'Azure App ID'
            required: 'YES'
        - macro: '{$AZURE.BILLING.MONTH}'
          value: '11'
          description: 'Months to get historical data from Azure Cost Management API, no more than 11 (plus current month). The time period for pulling the data cannot exceed 1 year.'
          config:
            type: TEXT
            priority: '5'
            label: 'Billing months'
            description: 'Months to get historical data from Azure Cost Management API, no more than 11 (plus current month). In the range from 0 to 11 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DATA.TIMEOUT}'
          value: 60s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '12'
            section_name: Other
            label: 'API timeout'
            description: 'API response timeout, in seconds.'
        - macro: '{$AZURE.LLD.FILTER.RESOURCE.GROUP.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable resource groups by name.'
          config:
            type: TEXT
            priority: '10'
            section_name: Filters
            label: 'Include resource groups filter'
            description: 'Regex string to include discoverable resource groups by name.'
        - macro: '{$AZURE.LLD.FILTER.RESOURCE.GROUP.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered resource groups by name.'
          config:
            type: TEXT
            priority: '11'
            section_name: Filters
            label: 'Exclude locations filter'
            description: 'Regex string to exclude discovered resource groups by name.'
        - macro: '{$AZURE.LLD.FILTER.RESOURCE.LOCATION.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable locations by name.'
          config:
            type: TEXT
            priority: '8'
            section_name: Filters
            label: 'Include locations filter'
            description: 'Regex string to include discoverable locations by name.'
        - macro: '{$AZURE.LLD.FILTER.RESOURCE.LOCATION.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered locations by name.'
          config:
            type: TEXT
            priority: '9'
            section_name: Filters
            label: 'Exclude locations filter'
            description: 'Regex string to exclude discovered locations by name.'
        - macro: '{$AZURE.LLD.FILTER.SERVICE.MATCHES}'
          value: '.*'
          description: 'Filter of discoverable services by name.'
          config:
            type: TEXT
            priority: '6'
            section_name: Filters
            label: 'Include services filter'
            description: 'Regex string to include discovered services by name.'
        - macro: '{$AZURE.LLD.FILTER.SERVICE.NOT_MATCHES}'
          value: CHANGE_IF_NEEDED
          description: 'Filter to exclude discovered services by name.'
          config:
            type: TEXT
            priority: '7'
            section_name: Filters
            label: 'Exclude services filter'
            description: 'Regex string to exclude discovered services by name.'
        - macro: '{$AZURE.PASSWORD}'
          type: SECRET_TEXT
          description: 'Microsoft Azure password.'
          config:
            type: TEXT
            priority: '4'
            label: 'Azure password'
            required: 'YES'
        - macro: '{$AZURE.PROXY}'
          description: 'Sets the HTTP proxy value. If this macro is empty, then no proxy is used.'
          config:
            type: TEXT
            priority: '13'
            section_name: Other
            label: 'HTTP proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AZURE.SUBSCRIPTION.ID}'
          description: 'Microsoft Azure subscription ID.'
          config:
            type: TEXT
            priority: '1'
            label: 'Azure subscription ID'
            required: 'YES'
        - macro: '{$AZURE.TENANT.ID}'
          description: 'Microsoft Azure tenant ID.'
          config:
            type: TEXT
            priority: '2'
            label: 'Azure tenant ID'
            required: 'YES'
      dashboards:
        - uuid: a1c2ce224f07483b865ce48090338dc4
          name: 'Overview Azure Costs'
          pages:
            - name: 'Monthly costs'
              widgets:
                - type: itemnavigator
                  name: Month
                  width: '20'
                  height: '6'
                  fields:
                    - type: INTEGER
                      name: group_by.0.attribute
                      value: '3'
                    - type: STRING
                      name: group_by.0.tag_name
                      value: month
                    - type: STRING
                      name: items.0
                      value: 'Month ["*"] cost'
                    - type: STRING
                      name: reference
                      value: JZQAJ
                - type: itemnavigator
                  name: Service
                  'y': '6'
                  width: '20'
                  height: '6'
                  fields:
                    - type: INTEGER
                      name: group_by.0.attribute
                      value: '3'
                    - type: STRING
                      name: group_by.0.tag_name
                      value: service
                    - type: INTEGER
                      name: group_by.1.attribute
                      value: '3'
                    - type: STRING
                      name: group_by.1.tag_name
                      value: month
                    - type: STRING
                      name: items.0
                      value: 'Service ["*"]: Month ["*"] cost'
                    - type: STRING
                      name: reference
                      value: AJICL
                    - type: INTEGER
                      name: show_lines
                      value: '200'
                - type: piechart
                  name: 'Month costs'
                  x: '20'
                  width: '32'
                  height: '12'
                  hide_header: 'YES'
                  fields:
                    - type: INTEGER
                      name: draw_type
                      value: '1'
                    - type: STRING
                      name: ds.0.color.0
                      value: 4CAF50
                    - type: INTEGER
                      name: ds.0.dataset_type
                      value: '0'
                    - type: STRING
                      name: ds.0.itemids.0._reference
                      value: JZQAJ._itemid
                    - type: INTEGER
                      name: ds.0.type.0
                      value: '0'
                    - type: STRING
                      name: ds.1.color.0
                      value: 1565C0
                    - type: INTEGER
                      name: ds.1.dataset_type
                      value: '0'
                    - type: STRING
                      name: ds.1.itemids.0._reference
                      value: AJICL._itemid
                    - type: INTEGER
                      name: ds.1.type.0
                      value: '0'
                    - type: STRING
                      name: ds.2.color.0
                      value: '795548'
                    - type: INTEGER
                      name: ds.2.dataset_type
                      value: '0'
                    - type: STRING
                      name: ds.2.itemids.0._reference
                      value: PEIIF._itemid
                    - type: INTEGER
                      name: ds.2.type.0
                      value: '0'
                    - type: STRING
                      name: ds.3.color.0
                      value: E65100
                    - type: INTEGER
                      name: ds.3.dataset_type
                      value: '0'
                    - type: STRING
                      name: ds.3.itemids.0._reference
                      value: JRCGU._itemid
                    - type: INTEGER
                      name: ds.3.type.0
                      value: '0'
                    - type: INTEGER
                      name: legend_lines
                      value: '4'
                    - type: INTEGER
                      name: legend_value
                      value: '1'
                    - type: INTEGER
                      name: space
                      value: '2'
                    - type: INTEGER
                      name: stroke
                      value: '2'
                - type: itemnavigator
                  name: Location
                  x: '52'
                  width: '20'
                  height: '6'
                  fields:
                    - type: INTEGER
                      name: group_by.0.attribute
                      value: '3'
                    - type: STRING
                      name: group_by.0.tag_name
                      value: location
                    - type: INTEGER
                      name: group_by.1.attribute
                      value: '3'
                    - type: STRING
                      name: group_by.1.tag_name
                      value: month
                    - type: STRING
                      name: items.0
                      value: 'Location: ["*"]: Month ["*"] cost'
                    - type: STRING
                      name: reference
                      value: PEIIF
                    - type: INTEGER
                      name: show_lines
                      value: '200'
                - type: itemnavigator
                  name: 'Resource group'
                  x: '52'
                  'y': '6'
                  width: '20'
                  height: '6'
                  fields:
                    - type: INTEGER
                      name: group_by.0.attribute
                      value: '3'
                    - type: STRING
                      name: group_by.0.tag_name
                      value: resource-group
                    - type: INTEGER
                      name: group_by.1.attribute
                      value: '3'
                    - type: STRING
                      name: group_by.1.tag_name
                      value: month
                    - type: STRING
                      name: items.0
                      value: 'Resource group: ["*"]: Month ["*"] cost'
                    - type: STRING
                      name: reference
                      value: JRCGU
                    - type: INTEGER
                      name: show_lines
                      value: '200'
            - name: 'Daily costs by service'
              widgets:
                - type: itemnavigator
                  name: Service
                  width: '25'
                  height: '7'
                  fields:
                    - type: INTEGER
                      name: group_by.0.attribute
                      value: '3'
                    - type: STRING
                      name: group_by.0.tag_name
                      value: service
                    - type: INTEGER
                      name: group_by.1.attribute
                      value: '3'
                    - type: STRING
                      name: group_by.1.tag_name
                      value: resource-group
                    - type: STRING
                      name: items.0
                      value: 'Service ["*"]: Meter ["*"]: Subcategory ["*"] daily cost'
                    - type: STRING
                      name: reference
                      value: TOVAT
                - type: svggraph
                  name: 'Daily cost'
                  x: '25'
                  width: '47'
                  height: '7'
                  hide_header: 'YES'
                  fields:
                    - type: STRING
                      name: ds.0.color.0
                      value: 6A1B9A
                    - type: INTEGER
                      name: ds.0.dataset_type
                      value: '0'
                    - type: STRING
                      name: ds.0.itemids.0._reference
                      value: TOVAT._itemid
                    - type: INTEGER
                      name: ds.0.transparency
                      value: '4'
                    - type: INTEGER
                      name: ds.0.width
                      value: '2'
                    - type: STRING
                      name: reference
                      value: AMNYP
                    - type: INTEGER
                      name: righty
                      value: '0'
    - uuid: 2d8b9329b5d04cdf85bf17d2d0db2b29
      template: 'Azure Microsoft SQL Database by HTTP'
      name: 'Azure Microsoft SQL Database by HTTP'
      description: |
        This template is designed to monitor Microsoft SQL databases by HTTP.
        It works without any external scripts and uses the script item.
        
        Setup:
          1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
            `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
            See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
          2. Link the template to a host.
          3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
        
        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 is designed to monitor Microsoft SQL databases by HTTP.
        It works without any external scripts and uses the script item.
        
        ## Setup
        
        1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
        
              `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
        
        > See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
        
        2. Link the template to a host.
        3. Configure the macros: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure MSSQL database ID`.
      vendor:
        name: Zabbix
        version: 7.4-1
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 2ff1f479e0b447f2b85e75e99bc011fe
          name: 'Availability status detailed'
          type: DEPENDENT
          key: azure.db.mssql.availability.details
          value_type: CHAR
          description: 'The summary description of the availability status.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.summary
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: health
        - uuid: f15e8075ac9a4f1ca6e95106940b246e
          name: 'Availability state'
          type: DEPENDENT
          key: azure.db.mssql.availability.state
          description: 'The availability status of the resource.'
          valuemap:
            name: 'Azure resource health state'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.availabilityState
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: STR_REPLACE
              parameters:
                - Available
                - '0'
            - type: STR_REPLACE
              parameters:
                - Degraded
                - '1'
            - type: STR_REPLACE
              parameters:
                - Unavailable
                - '2'
            - type: STR_REPLACE
              parameters:
                - Unknown
                - '3'
            - type: IN_RANGE
              parameters:
                - '0'
                - '3'
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: health
          triggers:
            - uuid: 5156f35b82084fd3b1d1a11c35757993
              expression: 'last(/Azure Microsoft SQL Database by HTTP/azure.db.mssql.availability.state)=1'
              name: 'Azure MSSQL: Microsoft SQL database is degraded'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The resource is in a degraded state.'
              tags:
                - tag: scope
                  value: availability
            - uuid: 0cf3cce995c241838e13df12d5908b61
              expression: 'last(/Azure Microsoft SQL Database by HTTP/azure.db.mssql.availability.state)=3'
              name: 'Azure MSSQL: Microsoft SQL database is in unknown state'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The resource state is unknown.'
              tags:
                - tag: scope
                  value: availability
            - uuid: 2130dc83dee94fdfad87894127c6a578
              expression: 'last(/Azure Microsoft SQL Database by HTTP/azure.db.mssql.availability.state)=2'
              name: 'Azure MSSQL: Microsoft SQL database is unavailable'
              opdata: '{ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The resource state is unavailable.'
              tags:
                - tag: scope
                  value: availability
        - uuid: ce744d69ed12435db781fbc6100d97ab
          name: 'Connections failed: System errors'
          type: DEPENDENT
          key: azure.db.mssql.connections.failed.system
          value_type: FLOAT
          description: 'The count of failed connections with system errors.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.connection_failed.total
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 8ec27240f59947858c41762a266cab25
          name: 'Connections successful'
          type: DEPENDENT
          key: azure.db.mssql.connections.successful
          value_type: FLOAT
          description: 'The count of successful connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.connection_successful.total
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 04737f2746444d2fb348a9444964dc7a
          name: 'CPU limit'
          type: DEPENDENT
          key: azure.db.mssql.cpu.limit
          value_type: FLOAT
          description: 'The CPU limit. Applies to the vCore-based databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.cpu_limit.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: cpu
        - uuid: e55a199cc0bd4749a69478da8268785d
          name: 'Percentage CPU'
          type: DEPENDENT
          key: azure.db.mssql.cpu.percentage
          value_type: FLOAT
          units: '%'
          description: 'The CPU percent of a host.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.cpu_percent.average
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: cpu
          triggers:
            - uuid: 506c034e707442519792a4366bc0879d
              expression: 'min(/Azure Microsoft SQL Database by HTTP/azure.db.mssql.cpu.percentage,5m)>{$AZURE.DB.CPU.UTIL.CRIT}'
              name: 'Azure MSSQL: High CPU utilization'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The CPU utilization is too high. The system might be slow to respond.'
              tags:
                - tag: scope
                  value: performance
        - uuid: 9a4a948f41e4434e9a94b3d9546df896
          name: 'CPU used'
          type: DEPENDENT
          key: azure.db.mssql.cpu.used
          value_type: FLOAT
          description: 'The CPU used. Applies to the vCore-based databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.cpu_used.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: cpu
        - uuid: e8aa1b70a7384ffead05cd2e95a6f10a
          name: 'Get errors'
          type: DEPENDENT
          key: azure.db.mssql.data.errors
          value_type: TEXT
          description: 'A list of errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.errors
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: raw
          triggers:
            - uuid: 62d08fe430bd45e890c81547860d5c3d
              expression: 'length(last(/Azure Microsoft SQL Database by HTTP/azure.db.mssql.data.errors))>0'
              name: 'Azure MSSQL: There are errors in requests to API'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 741cc1ec6a824e429f06b3d12a8a7082
          name: 'Get data'
          type: SCRIPT
          key: azure.db.mssql.data.get
          history: '0'
          value_type: TEXT
          params: |
            var AzureDB = {
            	params: {},
            	token: null,
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id', 'resource_id'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            
            		AzureDB.params = params;
            	},
            
            
            	request: function (url, data) {
            		if (typeof data === 'undefined' || data === null) {
            			data = '';
            		}
            
            		var response, request = new HttpRequest();
            		if (typeof AzureDB.params.proxy !== 'undefined' && AzureDB.params.proxy !== '') {
            			request.setProxy(AzureDB.params.proxy);
            		}
            		if (AzureDB.token) {
            			request.addHeader('Accept: application/json');
            			request.addHeader('Authorization: Bearer ' + AzureDB.token);
            		}
            
            		Zabbix.log(4, '[ Azure ] Sending request: ' + url);
            
            		if (data !== '') {
            			request.addHeader('Content-Type: application/x-www-form-urlencoded');
            			response = request.post(url, data);
            		}
            		else {
            			response = request.get(url);
            		}
            
            		Zabbix.log(4, '[ Azure ] Received response with status code ' + request.getStatus() + ': ' + response);
            
            		if (request.getStatus() !== 200 || response === null) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	}
            
            };
            
            var metrics = [
            	'cpu_percent',
            	'physical_data_read_percent',
            	'log_write_percent',
            	'storage',
            	'connection_successful',
            	'connection_failed',
            	'blocked_by_firewall',
            	'deadlock',
            	'storage_percent',
            	'xtp_storage_percent',
            	'workers_percent',
            	'sessions_percent',
            	'sessions_count',
            	'cpu_limit',
            	'cpu_used',
            	'sqlserver_process_core_percent',
            	'sqlserver_process_memory_percent',
            	'tempdb_data_size',
            	'tempdb_log_size',
            	'tempdb_log_used_percent',
            	'allocated_data_storage'
            ],
            	day_metrics = 'full_backup_size_bytes,diff_backup_size_bytes,log_backup_size_bytes',
            	prepared_metrics = [],
            	data = {};
            	data['errors'] = {};
            	data['metrics'] = {};
            
            try {
            	AzureDB.setParams(JSON.parse(value));
            
            	try {
            		result = AzureDB.request(
            			'https://login.microsoftonline.com/' + encodeURIComponent(AzureDB.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(AzureDB.params.app_id) + '&client_secret=' + encodeURIComponent(AzureDB.params.password)
            		);
            
            		if ('access_token' in result) {
            			AzureDB.token = result['access_token'];
            		} else {
            			throw 'Auth response does not contain access token.';
            		}
            	}
            	catch (error) {
            		data.errors.auth = error.toString();
            	}
            
            	if (!('auth' in data.errors)) {
            		try {
            			health = AzureDB.request('https://management.azure.com' + AzureDB.params.resource_id + '/providers/Microsoft.ResourceHealth/availabilityStatuses?api-version=2020-05-01');
            			if ('value' in health && Array.isArray(health.value) && health.value.length > 0 && 'properties' in health.value[0] && typeof health.value[0].properties === 'object') {
            				data.health = health.value[0].properties;
            			}
            		}
            		catch (error) {
            			data.errors.health = error.toString();
            		}
            
            		for (var i = 0; i < metrics.length; i += 20) {
            			var chunk = metrics.slice(i, i + 20);
            
            			prepared_metrics.push(
            				chunk.map(function (element) {
            					return encodeURIComponent(element);
            				}).join(',')
            			);
            		}
            
            		start_date = new Date((new Date().getTime()) - 300000).toISOString().replace(/\.\d+/, '');
            		end_date = new Date().toISOString().replace(/\.\d+/, '');
            
            		for (var j in prepared_metrics) {
            			try {
            				metrics_data = AzureDB.request('https://management.azure.com' + AzureDB.params.resource_id + '/providers/Microsoft.Insights/metrics?metricnames=' + prepared_metrics[j] + '&timespan=' + encodeURIComponent(start_date) + '/' + encodeURIComponent(end_date) + '&api-version=2021-05-01');
            				if ('value' in metrics_data && Array.isArray(metrics_data.value) && metrics_data.value.length > 0) {
            					for (k in metrics_data.value) {
            						if ('name' in metrics_data.value[k] && typeof metrics_data.value[k].name === 'object' && 'value' in metrics_data.value[k].name && typeof metrics_data.value[k].name.value === 'string' && 'timeseries' in metrics_data.value[k] && Array.isArray(metrics_data.value[k].timeseries) && metrics_data.value[k].timeseries.length > 0 && 'data' in metrics_data.value[k].timeseries[0] && Array.isArray(metrics_data.value[k].timeseries[0].data) && metrics_data.value[k].timeseries[0].data.length > 0) {
            							data.metrics[metrics_data.value[k].name.value.replace(/(\s|\/)+/g, '')] = metrics_data.value[k].timeseries[0].data[metrics_data.value[k].timeseries[0].data.length - 1];
            						}
            					}
            				}
            			}
            			catch (error) {
            				data.errors[prepared_metrics[j]] = error.toString();
            			}
            		}
            		start_date = new Date((new Date().getTime()) - 86400000).toISOString().replace(/\.\d+/, '');
            		end_date = new Date().toISOString().replace(/\.\d+/, '');
            		try {
            			metrics_data = AzureDB.request('https://management.azure.com' + AzureDB.params.resource_id + '/providers/Microsoft.Insights/metrics?metricnames=' + day_metrics + '&timespan=' + encodeURIComponent(start_date) + '/' + encodeURIComponent(end_date) + '&api-version=2021-05-01');
            			if ('value' in metrics_data && Array.isArray(metrics_data.value) && metrics_data.value.length > 0) {
            				for (l in metrics_data.value) {
            					if ('name' in metrics_data.value[l] && typeof metrics_data.value[l].name === 'object' && 'value' in metrics_data.value[l].name && typeof metrics_data.value[l].name.value === 'string' && 'timeseries' in metrics_data.value[l] && Array.isArray(metrics_data.value[l].timeseries) && metrics_data.value[l].timeseries.length > 0 && 'data' in metrics_data.value[l].timeseries[0] && Array.isArray(metrics_data.value[l].timeseries[0].data) && metrics_data.value[l].timeseries[0].data.length > 0) {
            						data.metrics[metrics_data.value[l].name.value.replace(/(\s|\/)+/g, '')] = metrics_data.value[l].timeseries[0].data[metrics_data.value[l].timeseries[0].data.length - 1];
            					}
            				}
            			}
            		}
            		catch (error) {
            			data.errors[day_metrics] = error.toString();
            		}
            	}
            }
            catch (error) {
            	data.errors.params = error.toString();
            }
            
            if (Object.keys(data.errors).length !== 0) {
            	errors = 'Failed to receive data:';
            	for (var error in data.errors) {
            		errors += '\n' + error + ' : ' + data.errors[error];
            	}
            	data.errors = errors;
            }
            else {
            	data.errors = '';
            }
            
            return JSON.stringify(data);
          description: 'The result of API requests is expressed in the JSON.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: resource_id
              value: '{$AZURE.RESOURCE.ID}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: 75d9288a8240425782cce8701c1bdfa8
          name: 'Data IO percentage'
          type: DEPENDENT
          key: azure.db.mssql.data.read.percentage
          value_type: FLOAT
          units: '%'
          description: 'The percentage of physical data read.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.physical_data_read_percent.average
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: operations
        - uuid: 81f87d35131c426299b233279f8f6c4b
          name: Deadlocks
          type: DEPENDENT
          key: azure.db.mssql.deadlocks
          value_type: FLOAT
          description: 'The count of deadlocks. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.deadlock.total
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 4d78e4691b6f4ab095849e6af2713638
          name: 'Connections blocked by firewall'
          type: DEPENDENT
          key: azure.db.mssql.firewall.blocked
          value_type: FLOAT
          description: 'The count of connections blocked by firewall.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.blocked_by_firewall.total
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 324c16e5da5b40c78d687f1f41a9d180
          name: 'Log IO percentage'
          type: DEPENDENT
          key: azure.db.mssql.log.write.percentage
          value_type: FLOAT
          units: '%'
          description: 'The percentage of I/O log. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.log_write_percent.average
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: operations
        - uuid: f417464b2de14e3292d68442570b931d
          name: 'SQL Server process core percent'
          type: DEPENDENT
          key: azure.db.mssql.server.cpu.percent
          value_type: FLOAT
          units: '%'
          description: 'The CPU usage as a percentage of the SQL DB process. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.sqlserver_process_core_percent.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: cpu
            - tag: component
              value: server
        - uuid: b39aa0798a824dafb3f3871b6406106a
          name: 'SQL Server process memory percent'
          type: DEPENDENT
          key: azure.db.mssql.server.memory.percent
          value_type: FLOAT
          units: '%'
          description: 'Memory usage as a percentage of the SQL DB process. Not applicable to data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.sqlserver_process_memory_percent.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: memory
            - tag: component
              value: server
        - uuid: 754b453cdf464f73b09eced3dd3e5859
          name: 'Sessions count'
          type: DEPENDENT
          key: azure.db.mssql.sessions.count
          value_type: FLOAT
          description: 'The number of active sessions. Not applicable to Synapse DW Analytics.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.sessions_count.average
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: sessions
        - uuid: b6696ac3d83841e2a001cdad1aeaea89
          name: 'Sessions percentage'
          type: DEPENDENT
          key: azure.db.mssql.sessions.percent
          value_type: FLOAT
          units: '%'
          description: 'The percentage of sessions. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.sessions_percent.average
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: sessions
        - uuid: fddff3dcbcf44c408314946f01f26a79
          name: 'Data space allocated'
          type: DEPENDENT
          key: azure.db.mssql.storage.allocated
          value_type: FLOAT
          units: B
          description: 'The allocated data storage. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.allocated_data_storage.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 3d492b552468462ba17524a9c6951dd7
          name: 'Differential backup storage size'
          type: DEPENDENT
          key: azure.db.mssql.storage.backup.diff.size
          value_type: FLOAT
          units: B
          description: 'Cumulative differential backup storage size. Applies to the vCore-based databases. Not applicable to the Hyperscale databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.diff_backup_size_bytes.maximum
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1d
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: e8cd0339a82248e3ad777374f219552e
          name: 'Log backup storage size'
          type: DEPENDENT
          key: azure.db.mssql.storage.backup.log.size
          value_type: FLOAT
          units: B
          description: 'Cumulative log backup storage size. Applies to the vCore-based and Hyperscale databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.log_backup_size_bytes.maximum
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1d
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: c92867a096ad4d89b31a2dba7e560df1
          name: 'Full backup storage size'
          type: DEPENDENT
          key: azure.db.mssql.storage.backup.size
          value_type: FLOAT
          units: B
          description: 'Cumulative full backup storage size. Applies to the vCore-based databases. Not applicable to the Hyperscale databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.full_backup_size_bytes.maximum
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1d
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 6eb5dc0a0b864c0bb35634612472ed38
          name: 'Data space used percent'
          type: DEPENDENT
          key: azure.db.mssql.storage.percent
          value_type: FLOAT
          units: '%'
          description: 'Data space used percent. Not applicable to the data warehouses or Hyperscale databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_percent.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
          triggers:
            - uuid: a2d6cf9ac67d4d0eb312e9536299b345
              expression: 'last(/Azure Microsoft SQL Database by HTTP/azure.db.mssql.storage.percent)>{$AZURE.DB.STORAGE.PUSED.CRIT}'
              name: 'Azure MSSQL: Storage space is critically low'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Critical utilization of the storage space.'
              tags:
                - tag: scope
                  value: capacity
            - uuid: 6dbf1d3aeb8b44b8bd96a9ca75f5249e
              expression: 'last(/Azure Microsoft SQL Database by HTTP/azure.db.mssql.storage.percent)>{$AZURE.DB.STORAGE.PUSED.WARN}'
              name: 'Azure MSSQL: Storage space is low'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'High utilization of the storage space.'
              tags:
                - tag: scope
                  value: capacity
        - uuid: a0335bde6f3546cdad5bbd2db8fa50b1
          name: 'Data space used'
          type: DEPENDENT
          key: azure.db.mssql.storage.used
          value_type: FLOAT
          units: B
          description: 'Data space used. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 6ff07a9a680749bfa3deabbec508b7c3
          name: 'In-Memory OLTP storage percent'
          type: DEPENDENT
          key: azure.db.mssql.storage.xtp.percent
          value_type: FLOAT
          units: '%'
          description: 'In-Memory OLTP storage percent. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.xtp_storage_percent.average
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 76da2f210c084546a19ce156e0aee1d6
          name: 'Tempdb data file size'
          type: DEPENDENT
          key: azure.db.mssql.tempdb.data.size
          value_type: FLOAT
          units: B
          description: 'The space used in `tempdb` data files, expressed in bytes. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.tempdb_data_size.maximum
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '1024'
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: dd2986cc6ce441fe9b3ab9b44b5fc103
          name: 'Tempdb log used percent'
          type: DEPENDENT
          key: azure.db.mssql.tempdb.log.percent
          value_type: FLOAT
          units: '%'
          description: 'The percentage of space used in `tempdb` transaction log file. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.tempdb_log_used_percent.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 51212e2af3854079950064bd9d16da83
          name: 'Tempdb log file size'
          type: DEPENDENT
          key: azure.db.mssql.tempdb.log.size
          value_type: FLOAT
          units: B
          description: 'The space used in `tempdb` transaction log file, expressed in bytes. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.tempdb_log_size.maximum
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '1024'
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: b5d63b2cbcb1470d8559a90cb3df0002
          name: 'Workers percentage'
          type: DEPENDENT
          key: azure.db.mssql.workers.percent
          value_type: FLOAT
          units: '%'
          description: 'The percentage of workers. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.workers_percent.average
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: workers
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: sql
        - tag: target
          value: azure
        - tag: target
          value: mssql
      macros:
        - macro: '{$AZURE.APP.ID}'
          description: 'The App ID of Microsoft Azure.'
          config:
            type: TEXT
            priority: '3'
            label: 'Azure App ID'
            required: 'YES'
        - macro: '{$AZURE.DATA.TIMEOUT}'
          value: 15s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '10'
            section_name: Other
            label: 'API timeout'
            description: 'API response timeout, in seconds.'
        - macro: '{$AZURE.DB.CPU.UTIL.CRIT}'
          value: '90'
          description: 'The critical threshold of CPU utilization, expressed in %.'
          config:
            type: TEXT
            priority: '6'
            section_name: Thresholds
            label: 'CPU utilization critical threshold'
            description: 'Critical threshold of CPU utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.MEMORY.UTIL.CRIT}'
          value: '90'
          description: 'The critical threshold of memory utilization, expressed in %.'
          config:
            type: TEXT
            priority: '7'
            section_name: Thresholds
            label: 'Memory utilization critical threshold'
            description: 'Critical threshold of memory utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.STORAGE.PUSED.CRIT}'
          value: '90'
          description: 'The critical threshold of storage utilization, expressed in %.'
          config:
            type: TEXT
            priority: '9'
            section_name: Thresholds
            label: 'Storage utilization critical threshold'
            description: 'Critical threshold of storage utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.STORAGE.PUSED.WARN}'
          value: '80'
          description: 'The warning threshold of storage utilization, expressed in %.'
          config:
            type: TEXT
            priority: '8'
            section_name: Thresholds
            label: 'Storage utilization warning threshold'
            description: 'Warning threshold of storage utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.PASSWORD}'
          type: SECRET_TEXT
          description: 'Microsoft Azure password.'
          config:
            type: TEXT
            priority: '4'
            label: 'Azure password'
            required: 'YES'
        - macro: '{$AZURE.PROXY}'
          description: 'Sets the HTTP proxy value. If this macro is empty, then no proxy is used.'
          config:
            type: TEXT
            priority: '11'
            section_name: Other
            label: 'HTTP proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AZURE.RESOURCE.ID}'
          description: 'Microsoft Azure Microsoft SQL database ID.'
          config:
            type: TEXT
            priority: '5'
            label: 'Azure MSSQL database ID'
            required: 'YES'
        - macro: '{$AZURE.SUBSCRIPTION.ID}'
          description: 'Microsoft Azure subscription ID.'
          config:
            type: TEXT
            priority: '1'
            label: 'Azure subscription ID'
            required: 'YES'
        - macro: '{$AZURE.TENANT.ID}'
          description: 'Microsoft Azure tenant ID.'
          config:
            type: TEXT
            priority: '2'
            label: 'Azure tenant ID'
            required: 'YES'
      dashboards:
        - uuid: 72b6f0916b9245adadb3445327aed633
          name: 'Overview Azure Microsoft SQL Database'
          pages:
            - widgets:
                - type: item
                  name: Deadlocks
                  width: '12'
                  height: '3'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        key: azure.db.mssql.deadlocks
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'SQL Server process memory percent'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        key: azure.db.mssql.server.memory.percent
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'CPU limit'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        key: azure.db.mssql.cpu.limit
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Data space allocated'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        key: azure.db.mssql.storage.allocated
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Connections successful'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        key: azure.db.mssql.connections.successful
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Availability state'
                  x: '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        key: azure.db.mssql.availability.state
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: up_color
                      value: FF0000
                - type: item
                  name: 'SQL Server process core percent'
                  x: '12'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        key: azure.db.mssql.server.cpu.percent
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'CPU used'
                  x: '12'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        key: azure.db.mssql.cpu.used
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Data space used'
                  x: '12'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        key: azure.db.mssql.storage.used
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Connections failed: System errors'
                  x: '12'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        key: azure.db.mssql.connections.failed.system
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: itemhistory
                  name: 'Availability status detailed'
                  x: '24'
                  width: '48'
                  height: '3'
                  fields:
                    - type: INTEGER
                      name: columns.0.display
                      value: '4'
                    - type: ITEM
                      name: columns.0.itemid
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        key: azure.db.mssql.availability.details
                    - type: INTEGER
                      name: columns.0.monospace_font
                      value: '1'
                    - type: STRING
                      name: columns.0.name
                      value: 'Azure Microsoft SQL: Availability status detailed'
                    - type: STRING
                      name: reference
                      value: BAAAG
                    - type: INTEGER
                      name: show_timestamp
                      value: '1'
                - type: item
                  name: 'Sessions count'
                  x: '24'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        key: azure.db.mssql.sessions.count
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: graph
                  name: 'Percentage CPU'
                  x: '24'
                  'y': '6'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        name: 'Azure Microsoft SQL: CPU usage'
                    - type: STRING
                      name: reference
                      value: AAAAA
                - type: graph
                  name: 'Storage utilization'
                  x: '24'
                  'y': '9'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        name: 'Azure Microsoft SQL: Storage utilization'
                    - type: STRING
                      name: reference
                      value: AAAAB
                - type: graph
                  name: Connections
                  x: '24'
                  'y': '12'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        name: 'Azure Microsoft SQL: Connections'
                    - type: STRING
                      name: reference
                      value: AAAAC
                - type: item
                  name: 'Workers percentage'
                  x: '36'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        key: azure.db.mssql.workers.percent
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'Full backup storage size'
                  x: '48'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        key: azure.db.mssql.storage.backup.size
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Data IO percentage'
                  x: '60'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Database by HTTP'
                        key: azure.db.mssql.data.read.percentage
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
      valuemaps:
        - uuid: 6f9c01899d9e45c9a1316ee081718e9e
          name: 'Azure resource health state'
          mappings:
            - value: '0'
              newvalue: Available
            - value: '1'
              newvalue: Degraded
            - value: '2'
              newvalue: Unavailable
            - value: '3'
              newvalue: Unknown
    - uuid: c3a9fa0e07be4c1bbe19ae65c3375d17
      template: 'Azure Microsoft SQL DTU Database by HTTP'
      name: 'Azure Microsoft SQL DTU Database by HTTP'
      description: |
        This template is designed to monitor Microsoft SQL DTU-based databases via HTTP.
        It works without any external scripts and uses the script item.
        
        Setup:
          1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
            `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
            See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
          2. Link the template to a host.
          3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID} and {$AZURE.RESOURCE.ID}.
        
        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 is designed to monitor Microsoft SQL DTU-based databases via HTTP.
        It works without any external scripts and uses the script item.
        
        ## Setup
        
        1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
        
              `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
        
        > See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
        
        2. Link the template to a host.
        3. Configure the macros: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID` and `Azure SQL DTU-based database ID`.
      vendor:
        name: Zabbix
        version: 7.4-1
      groups:
        - name: Templates/Cloud
      items:
        - uuid: d13b970f51c64553942d04043dd3f8b5
          name: 'Availability status detailed'
          type: DEPENDENT
          key: azure.db.mssql.availability.details
          value_type: CHAR
          description: 'A detailed summary of the availability status.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.summary
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: health
        - uuid: 96a795438e244fefa2218fcd73542201
          name: 'Availability state'
          type: DEPENDENT
          key: azure.db.mssql.availability.state
          description: 'The availability status of the resource.'
          valuemap:
            name: 'Azure resource health state'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.availabilityState
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: STR_REPLACE
              parameters:
                - Available
                - '0'
            - type: STR_REPLACE
              parameters:
                - Degraded
                - '1'
            - type: STR_REPLACE
              parameters:
                - Unavailable
                - '2'
            - type: STR_REPLACE
              parameters:
                - Unknown
                - '3'
            - type: IN_RANGE
              parameters:
                - '0'
                - '3'
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: health
          triggers:
            - uuid: 6bf8f84c7b494c4da90ef5e47fa75627
              expression: 'last(/Azure Microsoft SQL DTU Database by HTTP/azure.db.mssql.availability.state)=1'
              name: 'Azure MSSQL DTU: Microsoft SQL database is degraded'
              opdata: 'Current state: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The resource is in a degraded state.'
              tags:
                - tag: scope
                  value: availability
            - uuid: 4196d310e6e84c61a0a7115116f10854
              expression: 'last(/Azure Microsoft SQL DTU Database by HTTP/azure.db.mssql.availability.state)=3'
              name: 'Azure MSSQL DTU: Microsoft SQL database is in unknown state'
              opdata: 'Current state: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The resource state is unknown.'
              tags:
                - tag: scope
                  value: availability
            - uuid: b6f356182f3d4b0c88f52d88fce580b9
              expression: 'last(/Azure Microsoft SQL DTU Database by HTTP/azure.db.mssql.availability.state)=2'
              name: 'Azure MSSQL DTU: Microsoft SQL database is unavailable'
              opdata: 'Current state: {ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The resource state is unavailable.'
              tags:
                - tag: scope
                  value: availability
        - uuid: adc84144c91c4e4091e10e2f07d3e026
          name: 'Connections failed: System errors'
          type: DEPENDENT
          key: azure.db.mssql.connections.failed.system
          value_type: FLOAT
          description: 'The number of failed connections with system errors.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.connection_failed.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: network
        - uuid: f55c3fcf1a4b4539a6770496453e3ee8
          name: 'Connections successful'
          type: DEPENDENT
          key: azure.db.mssql.connections.successful
          value_type: FLOAT
          description: 'The number of successful connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.connection_successful.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: network
        - uuid: fb2f97642cb647afaf5f52bb14b6a91c
          name: 'CPU percentage'
          type: DEPENDENT
          key: azure.db.mssql.cpu.percentage
          value_type: FLOAT
          units: '%'
          description: 'The average percentage of CPU usage on a host.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.cpu_percent.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: cpu
          triggers:
            - uuid: 97caae1175be4c21b2fd5a53d5be25d2
              expression: 'min(/Azure Microsoft SQL DTU Database by HTTP/azure.db.mssql.cpu.percentage,5m)>{$AZURE.DB.CPU.UTIL.CRIT}'
              name: 'Azure MSSQL DTU: High CPU utilization'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The CPU utilization is too high. The system might be slow to respond.'
              tags:
                - tag: scope
                  value: performance
        - uuid: 86c709baa2e54477b483eb9289b7ae78
          name: 'Get errors'
          type: DEPENDENT
          key: azure.db.mssql.data.errors
          value_type: TEXT
          description: 'A list of errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.errors
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: raw
          triggers:
            - uuid: a21b8c56bd914548949c277c77efbd4b
              expression: 'length(last(/Azure Microsoft SQL DTU Database by HTTP/azure.db.mssql.data.errors))>0'
              name: 'Azure MSSQL DTU: There are errors in requests to API'
              opdata: 'Current error: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 4349f68c08a548d19d9ce58e66557ce5
          name: 'Get data'
          type: SCRIPT
          key: azure.db.mssql.data.get
          history: '0'
          value_type: TEXT
          params: |
            var Azure = {
            	params: {},
            	token: null,
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id', 'resource_id'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            
            		Azure.params = params;
            	},
            
            	login: function () {
            		var response, login = new HttpRequest();
            
            		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
            			login.setProxy(Azure.params.proxy);
            		}
            
            		login.addHeader('Content-Type: application/x-www-form-urlencoded');
            		response = login.post(
            			'https://login.microsoftonline.com/' + encodeURIComponent(Azure.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(Azure.params.app_id) + '&client_secret=' + encodeURIComponent(Azure.params.password)
            		);
            
            		if (login.getStatus() !== 200) {
            			throw 'Login failed with status code ' + login.getStatus() + ': ' + response;
            		}
            
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse login session response.';
            		}
            
            		if (!response.hasOwnProperty('access_token')) {
            			throw 'Authentication response does not contain access token.';
            		}
            
            		Azure.token = response['access_token'];
            	},
            
            	request: function (url) {
            		var response, request = new HttpRequest();
            
            		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
            			request.setProxy(Azure.params.proxy);
            		}
            
            		if (!Azure.token) {
            			throw 'Request does not contain access token.';
            		}
            
            		request.addHeader('Content-Type: application/json');
            		request.addHeader('Authorization: Bearer ' + Azure.token);
            		Zabbix.log(4, '[ Azure DTU DB ] request url: ' + url);
            
            		response = request.get(url);
            
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	},
            
            	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;
            	},
            
            	getMetricsData: function () {
            		var data = {},
            			metric_endpoints = {
            				'metrics_main': '/providers/Microsoft.Insights/metrics?metricnames=' + encodeURIComponent('allocated_data_storage,availability,blocked_by_firewall,connection_failed,connection_successful,cpu_percent,deadlock,dtu_consumption_percent,dtu_limit,dtu_used,log_write_percent,physical_data_read_percent,sessions_count,sessions_percent,sql_instance_cpu_percent,sql_instance_memory_percent,storage,storage_percent') + '&api-version=2021-05-01&timespan=PT5M',
            				'metrics_secondary': '/providers/Microsoft.Insights/metrics?metricnames=' + encodeURIComponent('tempdb_data_size,tempdb_log_size,tempdb_log_used_percent,workers_percent,xtp_storage_percent') + '&api-version=2021-05-01&timespan=PT5M',
            			};
            
            		data.metrics = {};
            
            		Object.keys(metric_endpoints).forEach(function (field) {
            			metrics = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + metric_endpoints[field]), 'value');
            
            			for (k in metrics) {
            				key = Azure.getField(metrics[k], 'name.value').replace(/(\s|\/)+/g, '');
            
            				if (metrics[k].timeseries.length === 0) {
            					metrics[k].timeseries.push({ 'data': ['nodata'] })
            				}
            
            				values = Azure.getField(metrics[k], 'timeseries.0.data');
            
            				for (var i = values.length - 1; i >= 0; i--) {
            
            					dataseriesKeys = Object.keys(values[i]);
            					aggregation = dataseriesKeys[1];
            
            					if (typeof (values[i][aggregation]) !== 'undefined') {
            						data.metrics[key] = values[i];
            						break;
            					}
            				}
            			}
            		});
            
            		data.health = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + '/providers/Microsoft.ResourceHealth/availabilityStatuses?api-version=2020-05-01'), 'value.0.properties');
            
            		return data
            	}
            };
            
            try {
            	Azure.setParams(JSON.parse(value));
            	Azure.login();
            	return JSON.stringify(Azure.getMetricsData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ Azure DTU DB ] ERROR: ' + error);
            	return JSON.stringify({ 'error': error });
            }
          description: 'The result of API requests is expressed in JSON format.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: resource_id
              value: '{$AZURE.RESOURCE.ID}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: 447d6c462a384e87860eeba0b1e17787
          name: 'Data IO percentage'
          type: DEPENDENT
          key: azure.db.mssql.data.read.percentage
          value_type: FLOAT
          units: '%'
          description: 'The average percentage of physical data read.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.physical_data_read_percent.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: operations
        - uuid: 192a5d5a4c6541b1a2e6394dc4e6961d
          name: Deadlocks
          type: DEPENDENT
          key: azure.db.mssql.deadlocks
          value_type: FLOAT
          description: 'The number of deadlocks. Not applicable to data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.deadlock.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 1b9a19283e9f4f5c9ec386edbfd99d86
          name: 'DTU limit'
          type: DEPENDENT
          key: azure.db.mssql.dtu.limit
          value_type: FLOAT
          description: 'The DTU limit. Applicable to DTU-based databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.dtu_limit.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: dtu
        - uuid: 35daacf9b481454bbf017841c3b4acf6
          name: 'DTU percentage'
          type: DEPENDENT
          key: azure.db.mssql.dtu.percentage
          value_type: FLOAT
          units: '%'
          description: 'The average percentage of DTU consumption for a DTU-based database.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.dtu_consumption_percent.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: dtu
          triggers:
            - uuid: eceb245b910841ceb8078ea8b3dbad1b
              expression: 'min(/Azure Microsoft SQL DTU Database by HTTP/azure.db.mssql.dtu.percentage,5m)>{$AZURE.DB.DTU.UTIL.CRIT}'
              name: 'Azure MSSQL DTU: High DTU utilization'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The DTU utilization is too high. The system might be slow to respond.'
              tags:
                - tag: scope
                  value: performance
        - uuid: 9bd9b5d0fc1d439ebfdfac51f6eb3487
          name: 'DTU used'
          type: DEPENDENT
          key: azure.db.mssql.dtu.used
          value_type: FLOAT
          description: 'The DTU used. Applicable to DTU-based databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.dtu_used.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: dtu
        - uuid: 4a0b3146d95742b1a30950da3fb6dcc5
          name: 'Connections blocked by firewall'
          type: DEPENDENT
          key: azure.db.mssql.firewall.blocked
          value_type: FLOAT
          description: 'The number of connections blocked by the firewall.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.blocked_by_firewall.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 0f71327c99054e5d8ebf432eccc0a536
          name: 'Log IO percentage'
          type: DEPENDENT
          key: azure.db.mssql.log.write.percentage
          value_type: FLOAT
          units: '%'
          description: 'The percentage of I/O used for log writes. Not applicable to data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.log_write_percent.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: operations
        - uuid: 218525cc5d474d249d62db21ca08d7c6
          name: 'SQL instance CPU percent'
          type: DEPENDENT
          key: azure.db.mssql.server.cpu.percent
          value_type: FLOAT
          units: '%'
          description: 'CPU usage from all user and system workloads. Not applicable to data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.sql_instance_cpu_percent.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: cpu
            - tag: component
              value: server
        - uuid: d6d0d99c736f4ecea48c3cb5d920ee72
          name: 'SQL instance memory percent'
          type: DEPENDENT
          key: azure.db.mssql.server.memory.percent
          value_type: FLOAT
          units: '%'
          description: 'The percentage of memory used by the database engine instance. Not applicable to data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.sql_instance_cpu_percent.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: memory
            - tag: component
              value: server
        - uuid: b9d6045642de46e08c45cca9b619bf75
          name: 'Sessions count'
          type: DEPENDENT
          key: azure.db.mssql.sessions.count
          value_type: FLOAT
          description: 'The number of active sessions. Not applicable to Synapse DW Analytics.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.sessions_count.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: sessions
        - uuid: 62298388449448e18fb0efb5b139b79c
          name: 'Sessions percentage'
          type: DEPENDENT
          key: azure.db.mssql.sessions.percent
          value_type: FLOAT
          units: '%'
          description: 'The percentage of sessions. Not applicable to data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.sessions_percent.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: sessions
        - uuid: e5cec53daadf40f79f580af1df77c35c
          name: 'Data space allocated'
          type: DEPENDENT
          key: azure.db.mssql.storage.allocated
          value_type: FLOAT
          units: B
          description: 'The allocated data storage. Not applicable to data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.allocated_data_storage.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 7c66b3e9b28043098a1d942c48fc0369
          name: 'Log backup storage size'
          type: DEPENDENT
          key: azure.db.mssql.storage.backup.log.size
          value_type: FLOAT
          units: B
          description: 'The cumulative log backup storage size. Applies to vCore-based and Hyperscale databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.log_backup_size_bytes.maximum
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1d
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 6a09939f232f4a078aa088f0dbcf370c
          name: 'Data space used percent'
          type: DEPENDENT
          key: azure.db.mssql.storage.percent
          value_type: FLOAT
          units: '%'
          description: 'Data space used in percent. Not applicable to data warehouses or Hyperscale databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_percent.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
          triggers:
            - uuid: b13d1ed5b1144e0095dca50bcbba37ae
              expression: 'last(/Azure Microsoft SQL DTU Database by HTTP/azure.db.mssql.storage.percent)>{$AZURE.DB.STORAGE.PUSED.CRIT}'
              name: 'Azure MSSQL DTU: Storage space is critically low'
              opdata: 'Current space used: {ITEM.LASTVALUE1}%'
              priority: AVERAGE
              description: 'Critical utilization of the storage space.'
              tags:
                - tag: scope
                  value: capacity
            - uuid: 74c7b9f109924177a37bc7717c6f39e0
              expression: 'last(/Azure Microsoft SQL DTU Database by HTTP/azure.db.mssql.storage.percent)>{$AZURE.DB.STORAGE.PUSED.WARN}'
              name: 'Azure MSSQL DTU: Storage space is low'
              opdata: 'Current space used: {ITEM.LASTVALUE1}%'
              priority: WARNING
              description: 'High utilization of the storage space.'
              dependencies:
                - name: 'Azure MSSQL DTU: Storage space is critically low'
                  expression: 'last(/Azure Microsoft SQL DTU Database by HTTP/azure.db.mssql.storage.percent)>{$AZURE.DB.STORAGE.PUSED.CRIT}'
              tags:
                - tag: scope
                  value: capacity
        - uuid: 829a31cfbd58473fb6aca227623dd374
          name: 'Data space used'
          type: DEPENDENT
          key: azure.db.mssql.storage.used
          value_type: FLOAT
          units: B
          description: 'Data space used. Not applicable to data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 154d7dd42d2849be9d3cf92e11a6f923
          name: 'In-Memory OLTP storage percent'
          type: DEPENDENT
          key: azure.db.mssql.storage.xtp.percent
          value_type: FLOAT
          units: '%'
          description: 'In-Memory OLTP storage percent. Not applicable to data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.xtp_storage_percent.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: d9a7c8558eb7418eb1113342d0c6225a
          name: 'Tempdb data file size'
          type: DEPENDENT
          key: azure.db.mssql.tempdb.data.size
          value_type: FLOAT
          units: B
          description: 'The space used in `tempdb` data files, expressed in bytes. Not applicable to data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.tempdb_data_size.maximum
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '1024'
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: a3d555807a4247e9ba3c388ae75bb5ce
          name: 'Tempdb log used percent'
          type: DEPENDENT
          key: azure.db.mssql.tempdb.log.percent
          value_type: FLOAT
          units: '%'
          description: 'The percentage of space used in the `tempdb` transaction log file. Not applicable to data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.tempdb_log_used_percent.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 3e64483271b347ceb300288079451f3e
          name: 'Tempdb log file size'
          type: DEPENDENT
          key: azure.db.mssql.tempdb.log.size
          value_type: FLOAT
          units: B
          description: 'The space used in the `tempdb` transaction log file, expressed in bytes. Not applicable to data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.tempdb_log_size.maximum
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '1024'
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 75ad7da5a2c74022ace6f28fed2c8ef2
          name: 'Workers percentage'
          type: DEPENDENT
          key: azure.db.mssql.workers.percent
          value_type: FLOAT
          units: '%'
          description: 'The percentage of workers. Not applicable to data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.workers_percent.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: workers
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: sql
        - tag: target
          value: azure
        - tag: target
          value: mssql
      macros:
        - macro: '{$AZURE.APP.ID}'
          description: 'The App ID of Microsoft Azure.'
          config:
            type: TEXT
            priority: '3'
            label: 'Azure App ID'
            required: 'YES'
        - macro: '{$AZURE.DATA.TIMEOUT}'
          value: 15s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '10'
            section_name: Other
            label: 'API timeout'
            description: 'API response timeout, in seconds.'
        - macro: '{$AZURE.DB.CPU.UTIL.CRIT}'
          value: '90'
          description: 'The critical threshold of CPU utilization, expressed in %.'
          config:
            type: TEXT
            priority: '6'
            section_name: Thresholds
            label: 'CPU utilization critical threshold'
            description: 'Critical threshold of CPU utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.MEMORY.UTIL.CRIT}'
          value: '90'
          description: 'The critical threshold of memory utilization, expressed in %.'
          config:
            type: TEXT
            priority: '7'
            section_name: Thresholds
            label: 'Memory utilization critical threshold'
            description: 'Critical threshold of memory utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.STORAGE.PUSED.CRIT}'
          value: '90'
          description: 'The critical threshold of storage utilization, expressed in %.'
          config:
            type: TEXT
            priority: '9'
            section_name: Thresholds
            label: 'Storage utilization critical threshold'
            description: 'Critical threshold of storage utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.STORAGE.PUSED.WARN}'
          value: '80'
          description: 'The warning threshold of storage utilization, expressed in %.'
          config:
            type: TEXT
            priority: '8'
            section_name: Thresholds
            label: 'Storage utilization warning threshold'
            description: 'Warning threshold of storage utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.PASSWORD}'
          type: SECRET_TEXT
          description: 'Microsoft Azure password.'
          config:
            type: TEXT
            priority: '4'
            label: 'Azure password'
            required: 'YES'
        - macro: '{$AZURE.PROXY}'
          description: 'Sets the HTTP proxy value. If this macro is empty, then no proxy is used.'
          config:
            type: TEXT
            priority: '11'
            section_name: Other
            label: 'HTTP proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AZURE.RESOURCE.ID}'
          description: 'Microsoft Azure SQL DTU-based database ID.'
          config:
            type: TEXT
            priority: '5'
            label: 'Azure SQL DTU-based database ID'
            required: 'YES'
        - macro: '{$AZURE.SUBSCRIPTION.ID}'
          description: 'Microsoft Azure subscription ID.'
          config:
            type: TEXT
            priority: '1'
            label: 'Azure subscription ID'
            required: 'YES'
        - macro: '{$AZURE.TENANT.ID}'
          description: 'Microsoft Azure tenant ID.'
          config:
            type: TEXT
            priority: '2'
            label: 'Azure tenant ID'
            required: 'YES'
      dashboards:
        - uuid: 0e19ba53f50c48c3bce738d5420096cb
          name: 'Overview Azure Microsoft SQL Database'
          pages:
            - widgets:
                - type: item
                  name: Deadlocks
                  width: '12'
                  height: '3'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        key: azure.db.mssql.deadlocks
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'SQL Server process memory percent'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        key: azure.db.mssql.server.memory.percent
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'DTU limit'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        key: azure.db.mssql.dtu.limit
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Data space allocated'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        key: azure.db.mssql.storage.allocated
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Connections successful'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        key: azure.db.mssql.connections.successful
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Availability state'
                  x: '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        key: azure.db.mssql.availability.state
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: up_color
                      value: FF0000
                - type: item
                  name: 'SQL Server process core percent'
                  x: '12'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        key: azure.db.mssql.server.cpu.percent
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'DTU used'
                  x: '12'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        key: azure.db.mssql.dtu.used
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Data space used'
                  x: '12'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        key: azure.db.mssql.storage.used
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Connections failed: System errors'
                  x: '12'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        key: azure.db.mssql.connections.failed.system
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: itemhistory
                  name: 'Availability status detailed'
                  x: '24'
                  width: '48'
                  height: '3'
                  fields:
                    - type: INTEGER
                      name: columns.0.display
                      value: '4'
                    - type: ITEM
                      name: columns.0.itemid
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        key: azure.db.mssql.availability.details
                    - type: INTEGER
                      name: columns.0.monospace_font
                      value: '1'
                    - type: STRING
                      name: columns.0.name
                      value: 'Azure Microsoft SQL: Availability status detailed'
                    - type: STRING
                      name: reference
                      value: BAAAG
                    - type: INTEGER
                      name: show_timestamp
                      value: '1'
                - type: item
                  name: 'Sessions count'
                  x: '24'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        key: azure.db.mssql.sessions.count
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: graph
                  name: 'DTU percentage'
                  x: '24'
                  'y': '6'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        name: 'Azure Microsoft SQL: DTU usage'
                    - type: STRING
                      name: reference
                      value: AAAAA
                - type: graph
                  name: 'Storage utilization'
                  x: '24'
                  'y': '9'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        name: 'Azure Microsoft SQL: Storage utilization'
                    - type: STRING
                      name: reference
                      value: AAAAB
                - type: graph
                  name: Connections
                  x: '24'
                  'y': '12'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        name: 'Azure Microsoft SQL: Connections'
                    - type: STRING
                      name: reference
                      value: AAAAC
                - type: item
                  name: 'Workers percentage'
                  x: '36'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        key: azure.db.mssql.workers.percent
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'CPU percentage'
                  x: '48'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        key: azure.db.mssql.cpu.percentage
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'Data IO percentage'
                  x: '60'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL DTU Database by HTTP'
                        key: azure.db.mssql.data.read.percentage
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
      valuemaps:
        - uuid: 34874b4cf9cb4ce2863a5698ff308126
          name: 'Azure resource health state'
          mappings:
            - value: '0'
              newvalue: Available
            - value: '1'
              newvalue: Degraded
            - value: '2'
              newvalue: Unavailable
            - value: '3'
              newvalue: Unknown
    - uuid: 5175afdf713744d9a81ce53864ccfc1d
      template: 'Azure Microsoft SQL Serverless Database by HTTP'
      name: 'Azure Microsoft SQL Serverless Database by HTTP'
      description: |
        This template is designed to monitor Microsoft SQL serverless databases by HTTP.
        It works without any external scripts and uses the script item.
        
        Setup:
          1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
            `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
            See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
          2. Link the template to a host.
          3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
        
        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 is designed to monitor Microsoft SQL serverless databases by HTTP.
        It works without any external scripts and uses the script item.
        
        ## Setup
        
        1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
        
              `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
        
        > See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
        
        2. Link the template to a host.
        3. Configure the macros: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure MSSQL database ID`.
      vendor:
        name: Zabbix
        version: 7.4-1
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 7c11fcc4f4b349f8b98fac93ae5e32be
          name: 'App CPU billed'
          type: DEPENDENT
          key: azure.db.mssql.app.cpu.billed
          value_type: FLOAT
          description: 'App CPU billed. Applies to serverless databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.app_cpu_billed.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: cpu
        - uuid: 6e67a868b2d84838803d3cb464ae9648
          name: 'App CPU percentage'
          type: DEPENDENT
          key: azure.db.mssql.app.cpu.percent
          value_type: FLOAT
          units: '%'
          description: 'App CPU percentage. Applies to serverless databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.app_cpu_percent.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: cpu
        - uuid: a38a887341914e75a01c7527c40b678f
          name: 'App memory percentage'
          type: DEPENDENT
          key: azure.db.mssql.app.memory.percent
          value_type: FLOAT
          units: '%'
          description: 'App memory percentage. Applies to serverless databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.app_memory_percent.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: memory
        - uuid: c2d3bc4ff95b4e05898dccee3d73a349
          name: 'Availability status detailed'
          type: DEPENDENT
          key: azure.db.mssql.availability.details
          value_type: CHAR
          description: 'The summary description of the availability status.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.summary
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: health
        - uuid: 9a3f2e99a768492c859c8f368c6a5cd3
          name: 'Availability state'
          type: DEPENDENT
          key: azure.db.mssql.availability.state
          description: 'The availability status of the resource.'
          valuemap:
            name: 'Azure resource health state'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.availabilityState
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: STR_REPLACE
              parameters:
                - Available
                - '0'
            - type: STR_REPLACE
              parameters:
                - Degraded
                - '1'
            - type: STR_REPLACE
              parameters:
                - Unavailable
                - '2'
            - type: STR_REPLACE
              parameters:
                - Unknown
                - '3'
            - type: IN_RANGE
              parameters:
                - '0'
                - '3'
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: health
          triggers:
            - uuid: 37c52a28908a45378266f68acdf5c308
              expression: 'last(/Azure Microsoft SQL Serverless Database by HTTP/azure.db.mssql.availability.state)=1'
              name: 'Azure MSSQL Serverless: Microsoft SQL database is degraded'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The resource is in a degraded state.'
              tags:
                - tag: scope
                  value: availability
            - uuid: 20bd79f05f3241a9950a83dcd9e325ba
              expression: 'last(/Azure Microsoft SQL Serverless Database by HTTP/azure.db.mssql.availability.state)=3'
              name: 'Azure MSSQL Serverless: Microsoft SQL database is in unknown state'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The resource state is unknown.'
              tags:
                - tag: scope
                  value: availability
            - uuid: 124813388e9844e8aae5ce474a66a774
              expression: 'last(/Azure Microsoft SQL Serverless Database by HTTP/azure.db.mssql.availability.state)=2'
              name: 'Azure MSSQL Serverless: Microsoft SQL database is unavailable'
              opdata: '{ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The resource state is unavailable.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 2457708a49d141faa16bd7b4ceb2c0a4
          name: 'Connections failed: System errors'
          type: DEPENDENT
          key: azure.db.mssql.connections.failed.system
          value_type: FLOAT
          description: 'The count of failed connections with system errors.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.connection_failed.total
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 59e028a7323d4222a4efd727314327c1
          name: 'Connections successful'
          type: DEPENDENT
          key: azure.db.mssql.connections.successful
          value_type: FLOAT
          description: 'The count of successful connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.connection_successful.total
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 0dc1cf6302574c1fbb51583e03409713
          name: 'CPU limit'
          type: DEPENDENT
          key: azure.db.mssql.cpu.limit
          value_type: FLOAT
          description: 'The CPU limit. Applies to the vCore-based databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.cpu_limit.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: cpu
        - uuid: 53be31ecfd48472c8edfe223107c0b07
          name: 'Percentage CPU'
          type: DEPENDENT
          key: azure.db.mssql.cpu.percentage
          value_type: FLOAT
          units: '%'
          description: 'The CPU percent of a host.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.cpu_percent.average
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: cpu
          triggers:
            - uuid: 933a04a1455b4a89b1527f9ce7848259
              expression: 'min(/Azure Microsoft SQL Serverless Database by HTTP/azure.db.mssql.cpu.percentage,5m)>{$AZURE.DB.CPU.UTIL.CRIT}'
              name: 'Azure MSSQL Serverless: High CPU utilization'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The CPU utilization is too high. The system might be slow to respond.'
              tags:
                - tag: scope
                  value: performance
        - uuid: ec0fc85904e149939836c2818a6ca66a
          name: 'CPU used'
          type: DEPENDENT
          key: azure.db.mssql.cpu.used
          value_type: FLOAT
          description: 'The CPU used. Applies to the vCore-based databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.cpu_used.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: cpu
        - uuid: d933dbacb2b94e40a757e15f13d51d2d
          name: 'Get errors'
          type: DEPENDENT
          key: azure.db.mssql.data.errors
          value_type: TEXT
          description: 'A list of errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.errors
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: raw
          triggers:
            - uuid: f56b125a8eff49d2aa002609c7df8b34
              expression: 'length(last(/Azure Microsoft SQL Serverless Database by HTTP/azure.db.mssql.data.errors))>0'
              name: 'Azure MSSQL Serverless: There are errors in requests to API'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              tags:
                - tag: scope
                  value: availability
        - uuid: e1c668773b974deeaf64c0d51d1cb02d
          name: 'Get data'
          type: SCRIPT
          key: azure.db.mssql.data.get
          history: '0'
          value_type: TEXT
          params: |
            var AzureDB = {
            	params: {},
            	token: null,
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id', 'resource_id'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            
            		AzureDB.params = params;
            	},
            
            
            	request: function (url, data) {
            		if (typeof data === 'undefined' || data === null) {
            			data = '';
            		}
            		var response, request = new HttpRequest();
            		if (typeof AzureDB.params.proxy !== 'undefined' && AzureDB.params.proxy !== '') {
            			request.setProxy(AzureDB.params.proxy);
            		}
            		if (AzureDB.token) {
            			request.addHeader('Accept: application/json');
            			request.addHeader('Authorization: Bearer ' + AzureDB.token);
            		}
            
            		Zabbix.log(4, '[ Azure ] Sending request: ' + url);
            
            		if (data !== '') {
            			request.addHeader('Content-Type: application/x-www-form-urlencoded');
            			response = request.post(url, data);
            		}
            		else {
            			response = request.get(url);
            		}
            
            		Zabbix.log(4, '[ Azure ] Received response with status code ' + request.getStatus() + ': ' + response);
            
            		if (request.getStatus() !== 200 || response === null) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	}
            
            };
            
            var metrics = [
            	'cpu_percent',
            	'physical_data_read_percent',
            	'log_write_percent',
            	'storage',
            	'connection_successful',
            	'connection_failed',
            	'blocked_by_firewall',
            	'deadlock',
            	'storage_percent',
            	'xtp_storage_percent',
            	'workers_percent',
            	'sessions_percent',
            	'cpu_limit',
            	'cpu_used',
            	'sqlserver_process_core_percent',
            	'sqlserver_process_memory_percent',
            	'tempdb_data_size',
            	'tempdb_log_size',
            	'tempdb_log_used_percent',
            	'app_cpu_billed',
            	'app_cpu_percent',
            	'app_memory_percent',
            	'allocated_data_storage'
            ],
            	prepared_metrics = [],
            	data = {};
            	data['errors'] = {};
            	data['metrics'] = {};
            
            try {
            	AzureDB.setParams(JSON.parse(value));
            
            	try {
            		result = AzureDB.request(
            			'https://login.microsoftonline.com/' + encodeURIComponent(AzureDB.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(AzureDB.params.app_id) + '&client_secret=' + encodeURIComponent(AzureDB.params.password)
            		);
            
            		if ('access_token' in result) {
            			AzureDB.token = result['access_token'];
            		} else {
            			throw 'Auth response does not contain access token.';
            		}
            	}
            	catch (error) {
            		data.errors.auth = error.toString();
            	}
            
            	if (!('auth' in data.errors)) {
            		try {
            			health = AzureDB.request('https://management.azure.com' + AzureDB.params.resource_id + '/providers/Microsoft.ResourceHealth/availabilityStatuses?api-version=2020-05-01');
            			if ('value' in health && Array.isArray(health.value) && health.value.length > 0 && 'properties' in health.value[0] && typeof health.value[0].properties === 'object') {
            				data.health = health.value[0].properties;
            			}
            		}
            		catch (error) {
            			data.errors.health = error.toString();
            		}
            
            		for (var i = 0; i < metrics.length; i += 20) {
            			var chunk = metrics.slice(i, i + 20);
            
            			prepared_metrics.push(
            				chunk.map(function (element) {
            					return encodeURIComponent(element);
            				}).join(',')
            			);
            		}
            
            		start_date = new Date((new Date().getTime()) - 300000).toISOString().replace(/\.\d+/, '');
            		end_date = new Date().toISOString().replace(/\.\d+/, '');
            
            		for (var j in prepared_metrics) {
            			try {
            				metrics_data = AzureDB.request('https://management.azure.com' + AzureDB.params.resource_id + '/providers/Microsoft.Insights/metrics?metricnames=' + prepared_metrics[j] + '&timespan=' + encodeURIComponent(start_date) + '/' + encodeURIComponent(end_date) + '&api-version=2021-05-01');
            				if ('value' in metrics_data && Array.isArray(metrics_data.value) && metrics_data.value.length > 0) {
            					for (k in metrics_data.value) {
            						if ('name' in metrics_data.value[k] && typeof metrics_data.value[k].name === 'object' && 'value' in metrics_data.value[k].name && typeof metrics_data.value[k].name.value === 'string' && 'timeseries' in metrics_data.value[k] && Array.isArray(metrics_data.value[k].timeseries) && metrics_data.value[k].timeseries.length > 0 && 'data' in metrics_data.value[k].timeseries[0] && Array.isArray(metrics_data.value[k].timeseries[0].data) && metrics_data.value[k].timeseries[0].data.length > 0) {
            							data.metrics[metrics_data.value[k].name.value.replace(/(\s|\/)+/g, '')] = metrics_data.value[k].timeseries[0].data[metrics_data.value[k].timeseries[0].data.length - 1];
            						}
            					}
            				}
            			}
            			catch (error) {
            				data.errors[prepared_metrics[j]] = error.toString();
            			}
            		}
            	}
            }
            catch (error) {
            	data.errors.params = error.toString();
            }
            
            if (Object.keys(data.errors).length !== 0) {
            	errors = 'Failed to receive data:';
            	for (var error in data.errors) {
            		errors += '\n' + error + ' : ' + data.errors[error];
            	}
            	data.errors = errors;
            }
            else {
            	data.errors = '';
            }
            
            return JSON.stringify(data);
          description: 'The result of API requests is expressed in the JSON.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: resource_id
              value: '{$AZURE.RESOURCE.ID}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: 40b15dd3d7a943d99f1bbe7fb34a9f48
          name: 'Data IO percentage'
          type: DEPENDENT
          key: azure.db.mssql.data.read.percentage
          value_type: FLOAT
          units: '%'
          description: 'The physical data read percentage.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.physical_data_read_percent.average
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: operations
        - uuid: 25b97b67d87945b48ae5c44b1db20187
          name: Deadlocks
          type: DEPENDENT
          key: azure.db.mssql.deadlocks
          value_type: FLOAT
          description: 'The count of deadlocks. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.deadlock.total
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: network
        - uuid: de91693b0a3345b4ad2c9aafd2af5325
          name: 'Connections blocked by firewall'
          type: DEPENDENT
          key: azure.db.mssql.firewall.blocked
          value_type: FLOAT
          description: 'The count of connections blocked by firewall.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.blocked_by_firewall.total
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: network
        - uuid: b41292705c284a77847856c2818d7145
          name: 'Log IO percentage'
          type: DEPENDENT
          key: azure.db.mssql.log.write.percentage
          value_type: FLOAT
          units: '%'
          description: 'The percentage of I/O log. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.log_write_percent.average
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: operations
        - uuid: 7b772170199f41d4ab614dee66176630
          name: 'SQL Server process core percent'
          type: DEPENDENT
          key: azure.db.mssql.server.cpu.percent
          value_type: FLOAT
          units: '%'
          description: 'The CPU usage as a percentage of the SQL DB process. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.sqlserver_process_core_percent.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: cpu
            - tag: component
              value: server
        - uuid: 5c0a5b745c094475b1e7a0d4f17a5627
          name: 'SQL Server process memory percent'
          type: DEPENDENT
          key: azure.db.mssql.server.memory.percent
          value_type: FLOAT
          units: '%'
          description: 'Memory usage as a percentage of the SQL DB process. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.sqlserver_process_memory_percent.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: memory
            - tag: component
              value: server
        - uuid: 924d96d212764c3ab18e5c14daa58840
          name: 'Sessions percentage'
          type: DEPENDENT
          key: azure.db.mssql.sessions.percent
          value_type: FLOAT
          units: '%'
          description: 'The percentage of sessions. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.sessions_percent.average
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: sessions
        - uuid: a87fd8ac96944e57ac58b39a18f6ad41
          name: 'Data space allocated'
          type: DEPENDENT
          key: azure.db.mssql.storage.allocated
          value_type: FLOAT
          units: B
          description: 'The allocated data storage. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.allocated_data_storage.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 2f95fd2dd48c4664afc5cd62d02b0b0a
          name: 'Data space used percent'
          type: DEPENDENT
          key: azure.db.mssql.storage.percent
          value_type: FLOAT
          units: '%'
          description: 'The percentage of used data space. Not applicable to the data warehouses or Hyperscale databases.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_percent.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
          triggers:
            - uuid: 4638130e599243fba3206abc85a7447f
              expression: 'last(/Azure Microsoft SQL Serverless Database by HTTP/azure.db.mssql.storage.percent)>{$AZURE.DB.STORAGE.PUSED.CRIT}'
              name: 'Azure MSSQL Serverless: Storage space is critically low'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Critical utilization of the storage space.'
              tags:
                - tag: scope
                  value: capacity
            - uuid: 4732eab4aabf439fa0b2d80b63e821e5
              expression: 'last(/Azure Microsoft SQL Serverless Database by HTTP/azure.db.mssql.storage.percent)>{$AZURE.DB.STORAGE.PUSED.WARN}'
              name: 'Azure MSSQL Serverless: Storage space is low'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'High utilization of the storage space.'
              tags:
                - tag: scope
                  value: capacity
        - uuid: 3b1fb8f993e74795b38abd56eceace0a
          name: 'Data space used'
          type: DEPENDENT
          key: azure.db.mssql.storage.used
          value_type: FLOAT
          units: B
          description: 'Data space used. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: fbd572ca3d3f42eea794ce78a5a27ec1
          name: 'In-Memory OLTP storage percent'
          type: DEPENDENT
          key: azure.db.mssql.storage.xtp.percent
          value_type: FLOAT
          units: '%'
          description: 'In-Memory OLTP storage percent. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.xtp_storage_percent.average
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: cea8a8ea0eaa4d26a28721882c19d9cd
          name: 'Tempdb data file size'
          type: DEPENDENT
          key: azure.db.mssql.tempdb.data.size
          value_type: FLOAT
          units: B
          description: 'Space used in `tempdb` data files, expressed in bytes. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.tempdb_data_size.maximum
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '1024'
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 6c8196751a504b82920b7ffa5314a2fc
          name: 'Tempdb log used percent'
          type: DEPENDENT
          key: azure.db.mssql.tempdb.log.percent
          value_type: FLOAT
          units: '%'
          description: 'The percentage of space used in `tempdb` transaction log files. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.tempdb_log_used_percent.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: b83992d1001c41b6ad3d13dbb227a733
          name: 'Tempdb log file size'
          type: DEPENDENT
          key: azure.db.mssql.tempdb.log.size
          value_type: FLOAT
          units: B
          description: 'Space used in `tempdb` transaction log files, expressed in bytes. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.tempdb_log_size.maximum
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '1024'
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: a4f597ab784a4e31aedc82bfb34feeb7
          name: 'Workers percentage'
          type: DEPENDENT
          key: azure.db.mssql.workers.percent
          value_type: FLOAT
          units: '%'
          description: 'The percentage of workers. Not applicable to the data warehouses.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.workers_percent.average
          master_item:
            key: azure.db.mssql.data.get
          tags:
            - tag: component
              value: workers
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: sql
        - tag: target
          value: azure
        - tag: target
          value: mssql
      macros:
        - macro: '{$AZURE.APP.ID}'
          description: 'The App ID of Microsoft Azure.'
          config:
            type: TEXT
            priority: '3'
            label: 'Azure App ID'
            required: 'YES'
        - macro: '{$AZURE.DATA.TIMEOUT}'
          value: 15s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '10'
            section_name: Other
            label: 'API timeout'
            description: 'API response timeout, in seconds.'
        - macro: '{$AZURE.DB.CPU.UTIL.CRIT}'
          value: '90'
          description: 'The critical threshold of CPU utilization, expressed in %.'
          config:
            type: TEXT
            priority: '6'
            section_name: Thresholds
            label: 'CPU utilization critical threshold'
            description: 'Critical threshold of CPU utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.MEMORY.UTIL.CRIT}'
          value: '90'
          description: 'The critical threshold of memory utilization, expressed in %.'
          config:
            type: TEXT
            priority: '7'
            section_name: Thresholds
            label: 'Memory utilization critical threshold'
            description: 'Critical threshold of memory utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.STORAGE.PUSED.CRIT}'
          value: '90'
          description: 'The critical threshold of storage utilization, expressed in %.'
          config:
            type: TEXT
            priority: '9'
            section_name: Thresholds
            label: 'Storage utilization critical threshold'
            description: 'Critical threshold of storage utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.STORAGE.PUSED.WARN}'
          value: '80'
          description: 'The warning threshold of storage utilization, expressed in %.'
          config:
            type: TEXT
            priority: '8'
            section_name: Thresholds
            label: 'Storage utilization warning threshold'
            description: 'Warning threshold of storage utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.PASSWORD}'
          type: SECRET_TEXT
          description: 'Microsoft Azure password.'
          config:
            type: TEXT
            priority: '4'
            label: 'Azure password'
            required: 'YES'
        - macro: '{$AZURE.PROXY}'
          description: 'Sets the HTTP proxy value. If this macro is empty, then no proxy is used.'
          config:
            type: TEXT
            priority: '11'
            section_name: Other
            label: 'HTTP proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AZURE.RESOURCE.ID}'
          description: 'Microsoft Azure Microsoft SQL database ID.'
          config:
            type: TEXT
            priority: '5'
            label: 'Azure MSSQL database ID'
            required: 'YES'
        - macro: '{$AZURE.SUBSCRIPTION.ID}'
          description: 'Microsoft Azure subscription ID.'
          config:
            type: TEXT
            priority: '1'
            label: 'Azure subscription ID'
            required: 'YES'
        - macro: '{$AZURE.TENANT.ID}'
          description: 'Microsoft Azure tenant ID.'
          config:
            type: TEXT
            priority: '2'
            label: 'Azure tenant ID'
            required: 'YES'
      dashboards:
        - uuid: 7a1b55d933ba4a529f2fccef44e5cff7
          name: 'Overview Azure Microsoft SQL Serverless Database'
          pages:
            - widgets:
                - type: item
                  name: Deadlocks
                  width: '12'
                  height: '3'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        key: azure.db.mssql.deadlocks
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'SQL Server process memory percent'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        key: azure.db.mssql.server.memory.percent
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'CPU limit'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        key: azure.db.mssql.cpu.limit
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Data space allocated'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        key: azure.db.mssql.storage.allocated
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Connections successful'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        key: azure.db.mssql.connections.successful
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Availability state'
                  x: '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        key: azure.db.mssql.availability.state
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: up_color
                      value: FF0000
                - type: item
                  name: 'SQL Server process core percent'
                  x: '12'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        key: azure.db.mssql.server.cpu.percent
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'CPU used'
                  x: '12'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        key: azure.db.mssql.cpu.used
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Data space used'
                  x: '12'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        key: azure.db.mssql.storage.used
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Connections failed: System errors'
                  x: '12'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        key: azure.db.mssql.connections.failed.system
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: itemhistory
                  name: 'Availability status detailed'
                  x: '24'
                  width: '48'
                  height: '3'
                  fields:
                    - type: INTEGER
                      name: columns.0.display
                      value: '4'
                    - type: ITEM
                      name: columns.0.itemid
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        key: azure.db.mssql.availability.details
                    - type: INTEGER
                      name: columns.0.monospace_font
                      value: '1'
                    - type: STRING
                      name: columns.0.name
                      value: 'Azure Microsoft SQL: Availability status detailed'
                    - type: STRING
                      name: reference
                      value: BAAAF
                    - type: INTEGER
                      name: show_timestamp
                      value: '1'
                - type: item
                  name: 'Sessions percentage'
                  x: '24'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        key: azure.db.mssql.sessions.percent
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: graph
                  name: 'Percentage CPU'
                  x: '24'
                  'y': '6'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        name: 'Azure Microsoft SQL: CPU usage'
                    - type: STRING
                      name: reference
                      value: AAAAA
                - type: graph
                  name: 'Storage utilization'
                  x: '24'
                  'y': '9'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        name: 'Azure Microsoft SQL: Storage utilization'
                    - type: STRING
                      name: reference
                      value: AAAAB
                - type: graph
                  name: Connections
                  x: '24'
                  'y': '12'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        name: 'Azure Microsoft SQL: Connections'
                    - type: STRING
                      name: reference
                      value: AAAAC
                - type: item
                  name: 'Workers percentage'
                  x: '36'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        key: azure.db.mssql.workers.percent
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'App memory percentage'
                  x: '48'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        key: azure.db.mssql.app.memory.percent
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'Data IO percentage'
                  x: '60'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Microsoft SQL Serverless Database by HTTP'
                        key: azure.db.mssql.data.read.percentage
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
      valuemaps:
        - uuid: c87b2eaeb88c4932ad63c73fcafa5331
          name: 'Azure resource health state'
          mappings:
            - value: '0'
              newvalue: Available
            - value: '1'
              newvalue: Degraded
            - value: '2'
              newvalue: Unavailable
            - value: '3'
              newvalue: Unknown
    - uuid: ec92c7b0b1d14946b6ac61de89357199
      template: 'Azure MySQL Flexible Server by HTTP'
      name: 'Azure MySQL Flexible Server by HTTP'
      description: |
        This template is designed to monitor Microsoft Azure MySQL flexible servers by HTTP.
        It works without any external scripts and uses the script item.
        
        Setup:
          1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
            `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
            See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
          2. Link the template to a host.
          3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
        
        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 is designed to monitor Microsoft Azure MySQL flexible servers by HTTP.
        It works without any external scripts and uses the script item.
        
        ## Setup
        
        1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
        
              `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
        
        > See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
        
        2. Link the template to a host.
        3. Configure the macros: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure MySQL server ID.`.
      vendor:
        name: Zabbix
        version: 7.4-1
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 9c87cde45e984ce282d8ba9fbe184f9b
          name: 'Availability status detailed'
          type: DEPENDENT
          key: azure.db.mysql.availability.details
          value_type: CHAR
          description: 'The summary description of the availability status.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.summary
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: health
        - uuid: 7f2d8e8d94ae4c87ba0480a2d9518f65
          name: 'Availability state'
          type: DEPENDENT
          key: azure.db.mysql.availability.state
          description: 'The availability status of the resource.'
          valuemap:
            name: 'Azure resource health state'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.availabilityState
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: STR_REPLACE
              parameters:
                - Available
                - '0'
            - type: STR_REPLACE
              parameters:
                - Degraded
                - '1'
            - type: STR_REPLACE
              parameters:
                - Unavailable
                - '2'
            - type: STR_REPLACE
              parameters:
                - Unknown
                - '3'
            - type: IN_RANGE
              parameters:
                - '0'
                - '3'
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: health
          triggers:
            - uuid: e822fd2214fb41db9b57cdb8eec0444a
              expression: 'last(/Azure MySQL Flexible Server by HTTP/azure.db.mysql.availability.state)=1'
              name: 'Azure MySQL Flexible: MySQL server is degraded'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The resource is in a degraded state.'
              tags:
                - tag: scope
                  value: availability
            - uuid: ebb35037a5b646a0bd2c6be44bb1f3c6
              expression: 'last(/Azure MySQL Flexible Server by HTTP/azure.db.mysql.availability.state)=3'
              name: 'Azure MySQL Flexible: MySQL server is in unknown state'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The resource state is unknown.'
              tags:
                - tag: scope
                  value: availability
            - uuid: 240b861c09a94e209036782b6c7496fa
              expression: 'last(/Azure MySQL Flexible Server by HTTP/azure.db.mysql.availability.state)=2'
              name: 'Azure MySQL Flexible: MySQL server is unavailable'
              opdata: '{ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The resource state is unavailable.'
              tags:
                - tag: scope
                  value: availability
        - uuid: cab6ac822f2c4e118b030e49cc15eaa2
          name: 'Connections aborted'
          type: DEPENDENT
          key: azure.db.mysql.connections.aborted
          value_type: FLOAT
          description: 'The count of aborted connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.aborted_connections.total
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: network
          triggers:
            - uuid: 3346ea2331c14fa18658eb33e461ec7c
              expression: 'min(/Azure MySQL Flexible Server by HTTP/azure.db.mysql.connections.aborted,5m)>{$AZURE.DB.ABORTED.CONN.MAX.WARN}'
              name: 'Azure MySQL Flexible: Server has aborted connections'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The number of failed attempts to connect to the MySQL server is more than `{$AZURE.DB.ABORTED.CONN.MAX.WARN}`.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 71b33f0a5d37498dbb57d185ac0f2741
          name: 'Connections active'
          type: DEPENDENT
          key: azure.db.mysql.connections.active
          value_type: FLOAT
          description: 'The count of active connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.active_connections.maximum
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 1993ae276fe44db6a89451291749f703
          name: 'Connections total'
          type: DEPENDENT
          key: azure.db.mysql.connections.total
          value_type: FLOAT
          description: 'The count of total connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.total_connections.total
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: network
        - uuid: b235666b98954555ae5e75e757bba707
          name: 'CPU credits consumed'
          type: DEPENDENT
          key: azure.db.mysql.cpu.credits.consumed
          value_type: FLOAT
          description: 'The consumed CPU credits.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.cpu_credits_consumed.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: cpu
        - uuid: 4f591346d3d34d49b37cfff2a169f57e
          name: 'CPU credits remaining'
          type: DEPENDENT
          key: azure.db.mysql.cpu.credits.remaining
          value_type: FLOAT
          description: 'The remaining CPU credits.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.cpu_credits_remaining.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: cpu
        - uuid: afe4d11c2f474428acc00d153ad2a6e5
          name: 'Percentage CPU'
          type: DEPENDENT
          key: azure.db.mysql.cpu.percentage
          value_type: FLOAT
          units: '%'
          description: 'The CPU percent of a host.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.cpu_percent.maximum
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: cpu
          triggers:
            - uuid: 5af82cc95239479c86c7ab3dabcfb592
              expression: 'min(/Azure MySQL Flexible Server by HTTP/azure.db.mysql.cpu.percentage,5m)>{$AZURE.DB.CPU.UTIL.CRIT}'
              name: 'Azure MySQL Flexible: High CPU utilization'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The CPU utilization is too high. The system might be slow to respond.'
              tags:
                - tag: scope
                  value: performance
        - uuid: f960e7667571497c96454b5c4b7b69ff
          name: 'Get errors'
          type: DEPENDENT
          key: azure.db.mysql.data.errors
          value_type: TEXT
          description: 'A list of errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.errors
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: raw
          triggers:
            - uuid: 98c1b86b79e9469cac2870fb2ba42949
              expression: 'length(last(/Azure MySQL Flexible Server by HTTP/azure.db.mysql.data.errors))>0'
              name: 'Azure MySQL Flexible: There are errors in requests to API'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              tags:
                - tag: scope
                  value: availability
        - uuid: de712334db1440309fa68f9252d4f9bc
          name: 'Get data'
          type: SCRIPT
          key: azure.db.mysql.data.get
          history: '0'
          value_type: TEXT
          params: |
            var AzureDB = {
            	params: {},
            	token: null,
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id', 'resource_id'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            
            		AzureDB.params = params;
            	},
            
            
            	request: function (url, data) {
            		if (typeof data === 'undefined' || data === null) {
            			data = '';
            		}
            
            		var response, request = new HttpRequest();
            		if (typeof AzureDB.params.proxy !== 'undefined' && AzureDB.params.proxy !== '') {
            			request.setProxy(AzureDB.params.proxy);
            		}
            		if (AzureDB.token) {
            			request.addHeader('Accept: application/json');
            			request.addHeader('Authorization: Bearer ' + AzureDB.token);
            		}
            
            		Zabbix.log(4, '[ Azure ] Sending request: ' + url);
            
            		if (data !== '') {
            			request.addHeader('Content-Type: application/x-www-form-urlencoded');
            			response = request.post(url, data);
            		}
            		else {
            			response = request.get(url);
            		}
            
            		Zabbix.log(4, '[ Azure ] Received response with status code ' + request.getStatus() + ': ' + response);
            
            		if (request.getStatus() !== 200 || response === null) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	}
            
            };
            
            var metrics = [
            	'cpu_percent',
            	'memory_percent',
            	'network_bytes_egress',
            	'network_bytes_ingress',
            	'active_connections',
            	'total_connections',
            	'aborted_connections',
            	'Queries',
            	'io_consumption_percent',
            	'storage_percent',
            	'storage_used',
            	'storage_limit',
            	'backup_storage_used',
            	'replication_lag',
            	'cpu_credits_remaining',
            	'cpu_credits_consumed'
            ],
            	prepared_metrics = [],
            	data = {};
            	data['errors'] = {};
            	data['metrics'] = {};
            
            try {
            	AzureDB.setParams(JSON.parse(value));
            
            	try {
            		result = AzureDB.request(
            			'https://login.microsoftonline.com/' + encodeURIComponent(AzureDB.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(AzureDB.params.app_id) + '&client_secret=' + encodeURIComponent(AzureDB.params.password)
            		);
            
            		if ('access_token' in result) {
            			AzureDB.token = result['access_token'];
            		} else {
            			throw 'Auth response does not contain access token.';
            		}
            	}
            	catch (error) {
            		data.errors.auth = error.toString();
            	}
            
            	if (!('auth' in data.errors)) {
            		try {
            			health = AzureDB.request('https://management.azure.com' + AzureDB.params.resource_id + '/providers/Microsoft.ResourceHealth/availabilityStatuses?api-version=2020-05-01');
            			if ('value' in health && Array.isArray(health.value) && health.value.length > 0 && 'properties' in health.value[0] && typeof health.value[0].properties === 'object') {
            				data.health = health.value[0].properties;
            			}
            		}
            		catch (error) {
            			data.errors.health = error.toString();
            		}
            
            		for (var i = 0; i < metrics.length; i += 20) {
            			var chunk = metrics.slice(i, i + 20);
            
            			prepared_metrics.push(
            				chunk.map(function (element) {
            					return encodeURIComponent(element);
            				}).join(',')
            			);
            		}
            
            		start_date = new Date((new Date().getTime()) - 300000).toISOString().replace(/\.\d+/, '');
            		end_date = new Date().toISOString().replace(/\.\d+/, '');
            
            		for (var j in prepared_metrics) {
            			try {
            				metrics_data = AzureDB.request('https://management.azure.com' + AzureDB.params.resource_id + '/providers/Microsoft.Insights/metrics?metricnames=' + prepared_metrics[j] + '&timespan=' + encodeURIComponent(start_date) + '/' + encodeURIComponent(end_date) + '&api-version=2021-05-01');
            				if ('value' in metrics_data && Array.isArray(metrics_data.value) && metrics_data.value.length > 0) {
            					for (k in metrics_data.value) {
            						if ('name' in metrics_data.value[k] && typeof metrics_data.value[k].name === 'object' && 'value' in metrics_data.value[k].name && typeof metrics_data.value[k].name.value === 'string' && 'timeseries' in metrics_data.value[k] && Array.isArray(metrics_data.value[k].timeseries) && metrics_data.value[k].timeseries.length > 0 && 'data' in metrics_data.value[k].timeseries[0] && Array.isArray(metrics_data.value[k].timeseries[0].data) && metrics_data.value[k].timeseries[0].data.length > 0) {
            							data.metrics[metrics_data.value[k].name.value.replace(/(\s|\/)+/g, '')] = metrics_data.value[k].timeseries[0].data[metrics_data.value[k].timeseries[0].data.length - 1];
            						}
            					}
            				}
            			}
            			catch (error) {
            				data.errors[prepared_metrics[j]] = error.toString();
            			}
            		}
            	}
            }
            catch (error) {
            	data.errors.params = error.toString();
            }
            
            if (Object.keys(data.errors).length !== 0) {
            	errors = 'Failed to receive data:';
            	for (var error in data.errors) {
            		errors += '\n' + error + ' : ' + data.errors[error];
            	}
            	data.errors = errors;
            }
            else {
            	data.errors = '';
            }
            
            return JSON.stringify(data);
          description: 'The result of API requests is expressed in the JSON.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: resource_id
              value: '{$AZURE.RESOURCE.ID}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: b4a6363aac734b6c8d043718ca667c09
          name: 'IO consumption percent'
          type: DEPENDENT
          key: azure.db.mysql.io.consumption.percent
          value_type: FLOAT
          units: '%'
          description: 'The consumption percent of I/O.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.io_consumption_percent.maximum
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: operations
        - uuid: f0f56a67942a40509d6835f3da9eb7e2
          name: 'Memory utilization'
          type: DEPENDENT
          key: azure.db.mysql.memory.percentage
          value_type: FLOAT
          units: '%'
          description: 'The memory percent of a host.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.memory_percent.maximum
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: memory
        - uuid: 84f3d2b152784993944a2d4c3fad1a59
          name: 'Network out'
          type: DEPENDENT
          key: azure.db.mysql.network.egress
          value_type: FLOAT
          units: bps
          description: 'Network egress of a host, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.network_bytes_egress.total
            - type: MULTIPLIER
              parameters:
                - '0.0088'
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 5f38b6b4e3a849d09022bd34c4347088
          name: 'Network in'
          type: DEPENDENT
          key: azure.db.mysql.network.ingress
          value_type: FLOAT
          units: bps
          description: 'Network ingress of a host, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.network_bytes_ingress.total
            - type: MULTIPLIER
              parameters:
                - '0.0088'
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 05329dcdb2e14080a43d1bf7553037f6
          name: Queries
          type: DEPENDENT
          key: azure.db.mysql.queries
          value_type: FLOAT
          description: 'The count of queries.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.Queries.total
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: queries
        - uuid: 80a05247fec04e39a99ccafaefbd0441
          name: 'Replication lag'
          type: DEPENDENT
          key: azure.db.mysql.replication.lag
          value_type: FLOAT
          units: s
          description: 'The replication lag, expressed in seconds.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.replication_lag.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: replication
        - uuid: 8d5cd0d3cd0744a5a260a8a0485f6735
          name: 'Backup storage used'
          type: DEPENDENT
          key: azure.db.mysql.storage.backup.used
          value_type: FLOAT
          units: B
          description: 'Used backup storage, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.backup_storage_used.maximum
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 78f3e03b5caf4f85a3c61513cf242f76
          name: 'Storage limit'
          type: DEPENDENT
          key: azure.db.mysql.storage.limit
          value_type: FLOAT
          units: B
          description: 'The storage limit, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_limit.maximum
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: ced51184b59643adaa51bef90710166b
          name: 'Storage percent'
          type: DEPENDENT
          key: azure.db.mysql.storage.percent
          value_type: FLOAT
          units: '%'
          description: 'The storage utilization, expressed in %.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_percent.maximum
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: storage
          triggers:
            - uuid: 1703edc1553644e5aa25d35928c5eafd
              expression: 'last(/Azure MySQL Flexible Server by HTTP/azure.db.mysql.storage.percent)>{$AZURE.DB.STORAGE.PUSED.CRIT}'
              name: 'Azure MySQL Flexible: Storage space is critically low'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Critical utilization of the storage space.'
              tags:
                - tag: scope
                  value: capacity
            - uuid: a2ec23a5e77c40aa9e45d214f4e06ca1
              expression: 'last(/Azure MySQL Flexible Server by HTTP/azure.db.mysql.storage.percent)>{$AZURE.DB.STORAGE.PUSED.WARN}'
              name: 'Azure MySQL Flexible: Storage space is low'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'High utilization of the storage space.'
              tags:
                - tag: scope
                  value: capacity
        - uuid: 9f96e947eee646f890742676e9f9a22a
          name: 'Storage used'
          type: DEPENDENT
          key: azure.db.mysql.storage.used
          value_type: FLOAT
          units: B
          description: 'Used storage space, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_used.maximum
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: storage
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: sql
        - tag: target
          value: azure
        - tag: target
          value: mysql
      macros:
        - macro: '{$AZURE.APP.ID}'
          description: 'The App ID of Microsoft Azure.'
          config:
            type: TEXT
            priority: '3'
            label: 'Azure App ID'
            required: 'YES'
        - macro: '{$AZURE.DATA.TIMEOUT}'
          value: 15s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '10'
            section_name: Other
            label: 'API timeout'
            description: 'API response timeout, in seconds.'
        - macro: '{$AZURE.DB.ABORTED.CONN.MAX.WARN}'
          value: '25'
          description: 'The number of failed attempts to connect to the MySQL server for a trigger expression.'
          config:
            type: TEXT
            priority: '9'
            section_name: Thresholds
            label: 'Failed connection attempts threshold'
            description: 'Number of failed attempts to connect to the MySQL server for a trigger expression. No less than 0.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.CPU.UTIL.CRIT}'
          value: '90'
          description: 'The critical threshold of CPU utilization, expressed in %.'
          config:
            type: TEXT
            priority: '6'
            section_name: Thresholds
            label: 'CPU utilization critical threshold'
            description: 'Critical threshold of CPU utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.STORAGE.PUSED.CRIT}'
          value: '90'
          description: 'The critical threshold of the storage utilization, expressed in %.'
          config:
            type: TEXT
            priority: '8'
            section_name: Thresholds
            label: 'Storage utilization critical threshold'
            description: 'Critical threshold of the storage utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.STORAGE.PUSED.WARN}'
          value: '80'
          description: 'The warning threshold of the storage utilization, expressed in %.'
          config:
            type: TEXT
            priority: '7'
            section_name: Thresholds
            label: 'Storage utilization warning threshold'
            description: 'Warning threshold of the storage utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.PASSWORD}'
          type: SECRET_TEXT
          description: 'Microsoft Azure password.'
          config:
            type: TEXT
            priority: '4'
            label: 'Azure password'
            required: 'YES'
        - macro: '{$AZURE.PROXY}'
          description: 'Sets the HTTP proxy value. If this macro is empty, then no proxy is used.'
          config:
            type: TEXT
            priority: '11'
            section_name: Other
            label: 'HTTP proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AZURE.RESOURCE.ID}'
          description: 'Microsoft Azure MySQL server ID.'
          config:
            type: TEXT
            priority: '5'
            label: 'Azure MySQL server ID'
            required: 'YES'
        - macro: '{$AZURE.SUBSCRIPTION.ID}'
          description: 'Microsoft Azure subscription ID.'
          config:
            type: TEXT
            priority: '1'
            label: 'Azure subscription ID'
            required: 'YES'
        - macro: '{$AZURE.TENANT.ID}'
          description: 'Microsoft Azure tenant ID.'
          config:
            type: TEXT
            priority: '2'
            label: 'Azure tenant ID'
            required: 'YES'
      dashboards:
        - uuid: 12974ad6fc5a42ba9683af06f9166cef
          name: 'Overview Azure MySQL Flexible Server'
          pages:
            - widgets:
                - type: item
                  name: 'Memory utilization'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.memory.percentage
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'CPU credits consumed'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.cpu.credits.consumed
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Storage used'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.storage.used
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Network in'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.network.ingress
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Connections active'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.connections.active
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Percentage CPU'
                  x: '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.cpu.percentage
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'CPU credits remaining'
                  x: '12'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.cpu.credits.remaining
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Storage limit'
                  x: '12'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.storage.limit
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Network out'
                  x: '12'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.network.egress
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Connections total'
                  x: '12'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.connections.total
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Availability state'
                  x: '24'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.availability.state
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: up_color
                      value: FF0000
                - type: item
                  name: 'Backup storage used'
                  x: '24'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.storage.backup.used
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: graph
                  name: 'Storage utilization'
                  x: '24'
                  'y': '6'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        name: 'Azure MySQL: Storage utilization'
                    - type: STRING
                      name: reference
                      value: AAAAA
                - type: graph
                  name: 'Network traffic'
                  x: '24'
                  'y': '9'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        name: 'Azure MySQL: Network traffic'
                    - type: STRING
                      name: reference
                      value: AAAAB
                - type: graph
                  name: Connections
                  x: '24'
                  'y': '12'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        name: 'Azure MySQL: Connections'
                    - type: STRING
                      name: reference
                      value: AAAAC
                - type: itemhistory
                  name: 'Availability status detailed'
                  x: '36'
                  width: '36'
                  height: '3'
                  fields:
                    - type: INTEGER
                      name: columns.0.display
                      value: '4'
                    - type: ITEM
                      name: columns.0.itemid
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.availability.details
                    - type: INTEGER
                      name: columns.0.monospace_font
                      value: '1'
                    - type: STRING
                      name: columns.0.name
                      value: 'Azure MySQL: Availability status detailed'
                    - type: STRING
                      name: reference
                      value: BAAAB
                    - type: INTEGER
                      name: show_timestamp
                      value: '1'
                - type: item
                  name: Queries
                  x: '36'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.queries
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'IO consumption percent'
                  x: '48'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.io.consumption.percent
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'Replication lag'
                  x: '60'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Flexible Server by HTTP'
                        key: azure.db.mysql.replication.lag
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
      valuemaps:
        - uuid: 4eec167b4d69441398b96b8e375d6825
          name: 'Azure resource health state'
          mappings:
            - value: '0'
              newvalue: Available
            - value: '1'
              newvalue: Degraded
            - value: '2'
              newvalue: Unavailable
            - value: '3'
              newvalue: Unknown
    - uuid: c1396bf1e8cf46f6a407e88ddceef0b8
      template: 'Azure MySQL Single Server by HTTP'
      name: 'Azure MySQL Single Server by HTTP'
      description: |
        This template is designed to monitor Microsoft Azure MySQL single servers by HTTP.
        It works without any external scripts and uses the script item.
        
        Setup:
          1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
            `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
            See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
          2. Link the template to a host.
          3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
        
        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 is designed to monitor Microsoft Azure MySQL single servers by HTTP.
        It works without any external scripts and uses the script item.
        
        ## Setup
        
        1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
        
              `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
        
        > See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
        
        2. Link the template to a host.
        3. Configure the macros: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure MySQL server ID`.
      vendor:
        name: Zabbix
        version: 7.4-1
      groups:
        - name: Templates/Cloud
      items:
        - uuid: c7771aa67d3c424490d8de2d6c2d609a
          name: 'Availability status detailed'
          type: DEPENDENT
          key: azure.db.mysql.availability.details
          value_type: CHAR
          description: 'The summary description of the availability status.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.summary
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: health
        - uuid: c325b977b26e4e00acc3ea8703895f05
          name: 'Availability state'
          type: DEPENDENT
          key: azure.db.mysql.availability.state
          description: 'The availability status of the resource.'
          valuemap:
            name: 'Azure resource health state'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.availabilityState
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: STR_REPLACE
              parameters:
                - Available
                - '0'
            - type: STR_REPLACE
              parameters:
                - Degraded
                - '1'
            - type: STR_REPLACE
              parameters:
                - Unavailable
                - '2'
            - type: STR_REPLACE
              parameters:
                - Unknown
                - '3'
            - type: IN_RANGE
              parameters:
                - '0'
                - '3'
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: health
          triggers:
            - uuid: 91a32645266547d78df3a70b44c7782b
              expression: 'last(/Azure MySQL Single Server by HTTP/azure.db.mysql.availability.state)=1'
              name: 'Azure MySQL Single: MySQL server is degraded'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The resource is in a degraded state.'
              tags:
                - tag: scope
                  value: availability
            - uuid: 852aba88476a40aeb2170b933726b7d8
              expression: 'last(/Azure MySQL Single Server by HTTP/azure.db.mysql.availability.state)=3'
              name: 'Azure MySQL Single: MySQL server is in unknown state'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The resource state is unknown.'
              tags:
                - tag: scope
                  value: availability
            - uuid: 5f2d2254dfc24f5481207585bed0d933
              expression: 'last(/Azure MySQL Single Server by HTTP/azure.db.mysql.availability.state)=2'
              name: 'Azure MySQL Single: MySQL server is unavailable'
              opdata: '{ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The resource state is unavailable.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 69aba8caa6874c9d9423926a2ee78e99
          name: 'Connections active'
          type: DEPENDENT
          key: azure.db.mysql.connections.active
          value_type: FLOAT
          description: 'The count of active connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.active_connections.average
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: network
        - uuid: e185b56984914507bc40c07c55153967
          name: 'Connections failed'
          type: DEPENDENT
          key: azure.db.mysql.connections.failed
          value_type: FLOAT
          description: 'The count of failed connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.connections_failed.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: network
          triggers:
            - uuid: 5b3a09ca04704e6a9972ee4865d358cd
              expression: 'min(/Azure MySQL Single Server by HTTP/azure.db.mysql.connections.failed,5m)>{$AZURE.DB.FAILED.CONN.MAX.WARN}'
              name: 'Azure MySQL Single: Server has failed connections'
              opdata: 'Current value: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The number of failed attempts to connect to the MySQL server is more than `{$AZURE.DB.FAILED.CONN.MAX.WARN}`.'
              tags:
                - tag: scope
                  value: availability
        - uuid: d0b5864a56094166b76fbc58a5e05c7c
          name: 'Percentage CPU'
          type: DEPENDENT
          key: azure.db.mysql.cpu.percentage
          value_type: FLOAT
          units: '%'
          description: 'The CPU percent of a host.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.cpu_percent.average
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: cpu
          triggers:
            - uuid: 7115fb320e2b4cc1ad1739c8a6cee155
              expression: 'min(/Azure MySQL Single Server by HTTP/azure.db.mysql.cpu.percentage,5m)>{$AZURE.DB.CPU.UTIL.CRIT}'
              name: 'Azure MySQL Single: High CPU utilization'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The CPU utilization is too high. The system might be slow to respond.'
              tags:
                - tag: scope
                  value: performance
        - uuid: 2fc253a20100478d91cac13590a64bfc
          name: 'Get errors'
          type: DEPENDENT
          key: azure.db.mysql.data.errors
          value_type: TEXT
          description: 'A list of errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.errors
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: raw
          triggers:
            - uuid: df5fa33f8c13413bb9d61ea4470b9b2d
              expression: 'length(last(/Azure MySQL Single Server by HTTP/azure.db.mysql.data.errors))>0'
              name: 'Azure MySQL Single: There are errors in requests to API'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              tags:
                - tag: scope
                  value: availability
        - uuid: cd62d92ef0384ea9acf0cae71c88ebc6
          name: 'Get data'
          type: SCRIPT
          key: azure.db.mysql.data.get
          history: '0'
          value_type: TEXT
          params: |
            var AzureDB = {
            	params: {},
            	token: null,
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id', 'resource_id'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            
            		AzureDB.params = params;
            	},
            
            
            	request: function (url, data) {
            		if (typeof data === 'undefined' || data === null) {
            			data = '';
            		}
            
            		var response, request = new HttpRequest();
            		if (typeof AzureDB.params.proxy !== 'undefined' && AzureDB.params.proxy !== '') {
            			request.setProxy(AzureDB.params.proxy);
            		}
            		if (AzureDB.token) {
            			request.addHeader('Accept: application/json');
            			request.addHeader('Authorization: Bearer ' + AzureDB.token);
            		}
            
            		Zabbix.log(4, '[ Azure ] Sending request: ' + url);
            
            		if (data !== '') {
            			request.addHeader('Content-Type: application/x-www-form-urlencoded');
            			response = request.post(url, data);
            		}
            		else {
            			response = request.get(url);
            		}
            
            		Zabbix.log(4, '[ Azure ] Received response with status code ' + request.getStatus() + ': ' + response);
            
            		if (request.getStatus() !== 200 || response === null) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	}
            
            };
            
            var metrics = [
            	'cpu_percent',
            	'memory_percent',
            	'io_consumption_percent',
            	'storage_percent',
            	'storage_used',
            	'storage_limit',
            	'serverlog_storage_percent',
            	'serverlog_storage_usage',
            	'serverlog_storage_limit',
            	'active_connections',
            	'connections_failed',
            	'seconds_behind_master',
            	'backup_storage_used',
            	'network_bytes_egress',
            	'network_bytes_ingress'
            ],
            	prepared_metrics = [],
            	data = {};
            data['errors'] = {};
            data['metrics'] = {};
            
            try {
            	AzureDB.setParams(JSON.parse(value));
            
            	try {
            		result = AzureDB.request(
            			'https://login.microsoftonline.com/' + encodeURIComponent(AzureDB.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(AzureDB.params.app_id) + '&client_secret=' + encodeURIComponent(AzureDB.params.password)
            		);
            
            		if ('access_token' in result) {
            			AzureDB.token = result['access_token'];
            		} else {
            			throw 'Auth response does not contain access token.';
            		}
            	}
            	catch (error) {
            		data.errors.auth = error.toString();
            	}
            
            	if (!('auth' in data.errors)) {
            		try {
            			health = AzureDB.request('https://management.azure.com' + AzureDB.params.resource_id + '/providers/Microsoft.ResourceHealth/availabilityStatuses?api-version=2020-05-01');
            			if ('value' in health && Array.isArray(health.value) && health.value.length > 0 && 'properties' in health.value[0] && typeof health.value[0].properties === 'object') {
            				data.health = health.value[0].properties;
            			}
            		}
            		catch (error) {
            			data.errors.health = error.toString();
            		}
            
            		for (var i = 0; i < metrics.length; i += 20) {
            			var chunk = metrics.slice(i, i + 20);
            
            			prepared_metrics.push(
            				chunk.map(function (element) {
            					return encodeURIComponent(element);
            				}).join(',')
            			);
            		}
            
            		start_date = new Date((new Date().getTime()) - 300000).toISOString().replace(/\.\d+/, '');
            		end_date = new Date().toISOString().replace(/\.\d+/, '');
            
            		for (var j in prepared_metrics) {
            			try {
            				metrics_data = AzureDB.request('https://management.azure.com' + AzureDB.params.resource_id + '/providers/Microsoft.Insights/metrics?metricnames=' + prepared_metrics[j] + '&timespan=' + encodeURIComponent(start_date) + '/' + encodeURIComponent(end_date) + '&api-version=2021-05-01');
            				if ('value' in metrics_data && Array.isArray(metrics_data.value) && metrics_data.value.length > 0) {
            					for (k in metrics_data.value) {
            						if ('name' in metrics_data.value[k] && typeof metrics_data.value[k].name === 'object' && 'value' in metrics_data.value[k].name && typeof metrics_data.value[k].name.value === 'string' && 'timeseries' in metrics_data.value[k] && Array.isArray(metrics_data.value[k].timeseries) && metrics_data.value[k].timeseries.length > 0 && 'data' in metrics_data.value[k].timeseries[0] && Array.isArray(metrics_data.value[k].timeseries[0].data) && metrics_data.value[k].timeseries[0].data.length > 0) {
            							data.metrics[metrics_data.value[k].name.value.replace(/(\s|\/)+/g, '')] = metrics_data.value[k].timeseries[0].data[metrics_data.value[k].timeseries[0].data.length - 1];
            						}
            					}
            				}
            			}
            			catch (error) {
            				data.errors[prepared_metrics[j]] = error.toString();
            			}
            		}
            	}
            }
            catch (error) {
            	data.errors.params = error.toString();
            }
            
            if (Object.keys(data.errors).length !== 0) {
            	errors = 'Failed to receive data:';
            	for (var error in data.errors) {
            		errors += '\n' + error + ' : ' + data.errors[error];
            	}
            	data.errors = errors;
            }
            else {
            	data.errors = '';
            }
            
            return JSON.stringify(data);
          description: 'The result of API requests is expressed in the JSON.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: resource_id
              value: '{$AZURE.RESOURCE.ID}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: a17c365253eb4821841ec82ac8f61106
          name: 'IO consumption percent'
          type: DEPENDENT
          key: azure.db.mysql.io.consumption.percent
          value_type: FLOAT
          units: '%'
          description: 'The consumption percent of I/O.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.io_consumption_percent.average
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: operations
        - uuid: 5c19c08912634993b1f96fb11e5d1ae2
          name: 'Memory utilization'
          type: DEPENDENT
          key: azure.db.mysql.memory.percentage
          value_type: FLOAT
          units: '%'
          description: 'The memory percent of a host.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.memory_percent.average
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: memory
          triggers:
            - uuid: a67b35f1ac674d6692b0b2bcd6f89bd8
              expression: 'min(/Azure MySQL Single Server by HTTP/azure.db.mysql.memory.percentage,5m)>{$AZURE.DB.MEMORY.UTIL.CRIT}'
              name: 'Azure MySQL Single: High memory utilization'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The system is running out of free memory.'
              tags:
                - tag: scope
                  value: performance
        - uuid: fe1b9846a634412aaa6a76fc05dbe46a
          name: 'Network out'
          type: DEPENDENT
          key: azure.db.mysql.network.egress
          value_type: FLOAT
          units: bps
          description: 'The network outbound traffic across the active connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.network_bytes_egress.total
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '0.0088'
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 1cc97817bda5470887e3d5d9f2d78650
          name: 'Network in'
          type: DEPENDENT
          key: azure.db.mysql.network.ingress
          value_type: FLOAT
          units: bps
          description: 'The network inbound traffic across the active connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.network_bytes_ingress.total
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '0.0088'
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 8e60794282ea42c7bad1573811b2e498
          name: 'Replication lag'
          type: DEPENDENT
          key: azure.db.mysql.replication.lag
          value_type: FLOAT
          units: s
          description: 'The replication lag, expressed in seconds.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.seconds_behind_master.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: replication
        - uuid: 1303a659d17a4e4fa9fa03cef35fef5a
          name: 'Backup storage used'
          type: DEPENDENT
          key: azure.db.mysql.storage.backup.used
          value_type: FLOAT
          units: B
          description: 'Used backup storage, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.backup_storage_used.average
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 4aed6d0c01d1458fbd1f7c7ea5386303
          name: 'Storage limit'
          type: DEPENDENT
          key: azure.db.mysql.storage.limit
          value_type: FLOAT
          units: B
          description: 'The storage limit, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_limit.maximum
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 5b1b350be6f0409fb7ab842571c3f086
          name: 'Storage percent'
          type: DEPENDENT
          key: azure.db.mysql.storage.percent
          value_type: FLOAT
          units: '%'
          description: 'The storage utilization, expressed in %.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_percent.average
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: storage
          triggers:
            - uuid: 3afcb840e8004822a2dada2a89971f69
              expression: 'last(/Azure MySQL Single Server by HTTP/azure.db.mysql.storage.percent)>{$AZURE.DB.STORAGE.PUSED.CRIT}'
              name: 'Azure MySQL Single: Storage space is critically low'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Critical utilization of the storage space.'
              tags:
                - tag: scope
                  value: capacity
            - uuid: 2e605f906b284f769e7c880d4e642b43
              expression: 'last(/Azure MySQL Single Server by HTTP/azure.db.mysql.storage.percent)>{$AZURE.DB.STORAGE.PUSED.WARN}'
              name: 'Azure MySQL Single: Storage space is low'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'High utilization of the storage space.'
              tags:
                - tag: scope
                  value: capacity
        - uuid: 7f553d8a0898477b87a2828e51efcfcc
          name: 'Server log storage limit'
          type: DEPENDENT
          key: azure.db.mysql.storage.server.log.limit
          value_type: FLOAT
          units: B
          description: 'The storage limit of server log, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.serverlog_storage_limit.maximum
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: cf5a77306c554a24b3741ef065b6d27a
          name: 'Server log storage percent'
          type: DEPENDENT
          key: azure.db.mysql.storage.server.log.percent
          value_type: FLOAT
          units: '%'
          description: 'The storage utilization by server log, expressed in %.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.serverlog_storage_percent.average
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 8ed99a951e264185b1e0f343d7ea0aec
          name: 'Server log storage used'
          type: DEPENDENT
          key: azure.db.mysql.storage.server.log.used
          value_type: FLOAT
          units: B
          description: 'The storage space used by server log, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.serverlog_storage_usage.average
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 0c9a5496d9884c8e9a434fb232b3208f
          name: 'Storage used'
          type: DEPENDENT
          key: azure.db.mysql.storage.used
          value_type: FLOAT
          units: B
          description: 'Used storage space, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_used.average
          master_item:
            key: azure.db.mysql.data.get
          tags:
            - tag: component
              value: storage
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: sql
        - tag: target
          value: azure
        - tag: target
          value: mysql
      macros:
        - macro: '{$AZURE.APP.ID}'
          description: 'The App ID of Microsoft Azure.'
          config:
            type: TEXT
            priority: '3'
            label: 'Azure App ID'
            required: 'YES'
        - macro: '{$AZURE.DATA.TIMEOUT}'
          value: 15s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '11'
            section_name: Other
            label: 'API timeout'
            description: 'API response timeout, in seconds.'
        - macro: '{$AZURE.DB.CPU.UTIL.CRIT}'
          value: '90'
          description: 'The critical threshold of CPU utilization, expressed in %.'
          config:
            type: TEXT
            priority: '6'
            section_name: Thresholds
            label: 'CPU utilization critical threshold'
            description: 'Critical threshold of CPU utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.FAILED.CONN.MAX.WARN}'
          value: '25'
          description: 'The number of failed attempts to connect to the MySQL server for trigger expression.'
          config:
            type: TEXT
            priority: '10'
            section_name: Thresholds
            label: 'Failed connection attempts threshold'
            description: 'Number of failed attempts to connect to the MySQL server for a trigger expression. No less than 0.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.MEMORY.UTIL.CRIT}'
          value: '90'
          description: 'The critical threshold of memory utilization, expressed in %.'
          config:
            type: TEXT
            priority: '7'
            section_name: Thresholds
            label: 'Memory utilization critical threshold'
            description: 'Critical threshold of memory utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.STORAGE.PUSED.CRIT}'
          value: '90'
          description: 'The critical threshold of storage utilization, expressed in %.'
          config:
            type: TEXT
            priority: '9'
            section_name: Thresholds
            label: 'Storage utilization critical threshold'
            description: 'Critical threshold of the storage utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.STORAGE.PUSED.WARN}'
          value: '80'
          description: 'The warning threshold of storage utilization, expressed in %.'
          config:
            type: TEXT
            priority: '8'
            section_name: Thresholds
            label: 'Storage utilization warning threshold'
            description: 'Warning threshold of the storage utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.PASSWORD}'
          type: SECRET_TEXT
          description: 'Microsoft Azure password.'
          config:
            type: TEXT
            priority: '4'
            label: 'Azure password'
            required: 'YES'
        - macro: '{$AZURE.PROXY}'
          description: 'Sets the HTTP proxy value. If this macro is empty, then no proxy is used.'
          config:
            type: TEXT
            priority: '12'
            section_name: Other
            label: 'HTTP proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AZURE.RESOURCE.ID}'
          description: 'Microsoft Azure MySQL server ID.'
          config:
            type: TEXT
            priority: '5'
            label: 'Azure MySQL server ID'
            required: 'YES'
        - macro: '{$AZURE.SUBSCRIPTION.ID}'
          description: 'Microsoft Azure subscription ID.'
          config:
            type: TEXT
            priority: '1'
            label: 'Azure subscription ID'
            required: 'YES'
        - macro: '{$AZURE.TENANT.ID}'
          description: 'Microsoft Azure tenant ID.'
          config:
            type: TEXT
            priority: '2'
            label: 'Azure tenant ID'
            required: 'YES'
      dashboards:
        - uuid: 8760f5409fbd488d8b8e8ba24d9077ae
          name: 'Overview Azure MySQL Single Server'
          pages:
            - widgets:
                - type: item
                  name: 'Memory utilization'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        key: azure.db.mysql.memory.percentage
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'Network in'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        key: azure.db.mysql.network.ingress
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Server log storage limit'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        key: azure.db.mysql.storage.server.log.limit
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Storage limit'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        key: azure.db.mysql.storage.limit
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Connections active'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        key: azure.db.mysql.connections.active
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Percentage CPU'
                  x: '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        key: azure.db.mysql.cpu.percentage
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'Network out'
                  x: '12'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        key: azure.db.mysql.network.egress
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Server log storage used'
                  x: '12'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        key: azure.db.mysql.storage.server.log.used
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Storage used'
                  x: '12'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        key: azure.db.mysql.storage.used
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Connections failed'
                  x: '12'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        key: azure.db.mysql.connections.failed
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Availability state'
                  x: '24'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        key: azure.db.mysql.availability.state
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: up_color
                      value: FF0000
                - type: graph
                  name: 'Network traffic'
                  x: '24'
                  'y': '3'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        name: 'Azure MySQL: Network traffic'
                    - type: STRING
                      name: reference
                      value: AAAAA
                - type: graph
                  name: 'Server log storage utilization'
                  x: '24'
                  'y': '6'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        name: 'Azure MySQL: Server log storage utilization'
                    - type: STRING
                      name: reference
                      value: AAAAB
                - type: graph
                  name: 'Storage utilization'
                  x: '24'
                  'y': '9'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        name: 'Azure MySQL: Storage utilization'
                    - type: STRING
                      name: reference
                      value: AAAAC
                - type: graph
                  name: Connections
                  x: '24'
                  'y': '12'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        name: 'Azure MySQL: Connections'
                    - type: STRING
                      name: reference
                      value: AAAAD
                - type: itemhistory
                  name: 'Availability status detailed'
                  x: '36'
                  width: '36'
                  height: '3'
                  fields:
                    - type: INTEGER
                      name: columns.0.display
                      value: '4'
                    - type: ITEM
                      name: columns.0.itemid
                      value:
                        host: 'Azure MySQL Single Server by HTTP'
                        key: azure.db.mysql.availability.details
                    - type: INTEGER
                      name: columns.0.monospace_font
                      value: '1'
                    - type: STRING
                      name: columns.0.name
                      value: 'Azure MySQL: Availability status detailed'
                    - type: STRING
                      name: reference
                      value: BAAAC
                    - type: INTEGER
                      name: show_timestamp
                      value: '1'
      valuemaps:
        - uuid: 323a5259fb854724891515767f341540
          name: 'Azure resource health state'
          mappings:
            - value: '0'
              newvalue: Available
            - value: '1'
              newvalue: Degraded
            - value: '2'
              newvalue: Unavailable
            - value: '3'
              newvalue: Unknown
    - uuid: 35ef29f24158444097272d2ea7fa6044
      template: 'Azure PostgreSQL Flexible Server by HTTP'
      name: 'Azure PostgreSQL Flexible Server by HTTP'
      description: |
        This template is designed to monitor Microsoft Azure PostgreSQL flexible servers by HTTP.
        It works without any external scripts and uses the script item.
        
        Setup:
          1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
            `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
            See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
          2. Link the template to a host.
          3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
        
        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 is designed to monitor Microsoft Azure PostgreSQL flexible servers by HTTP.
        It works without any external scripts and uses the script item.
        
        ## Setup
        
        1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
        
              `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
        
        > See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
        
        2. Link the template to a host.
        3. Configure the macros: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure PostgreSQL server ID`.
      vendor:
        name: Zabbix
        version: 7.4-1
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 7f7deae517e54cf582ae758a6988037b
          name: 'Availability status detailed'
          type: DEPENDENT
          key: azure.db.pgsql.availability.details
          value_type: CHAR
          description: 'The summary description of the availability status.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.summary
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: health
        - uuid: cd9072a3895c42dab794707f3bcaf743
          name: 'Availability state'
          type: DEPENDENT
          key: azure.db.pgsql.availability.state
          description: 'The availability status of the resource.'
          valuemap:
            name: 'Azure resource health state'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.availabilityState
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: STR_REPLACE
              parameters:
                - Available
                - '0'
            - type: STR_REPLACE
              parameters:
                - Degraded
                - '1'
            - type: STR_REPLACE
              parameters:
                - Unavailable
                - '2'
            - type: STR_REPLACE
              parameters:
                - Unknown
                - '3'
            - type: IN_RANGE
              parameters:
                - '0'
                - '3'
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: health
          triggers:
            - uuid: 65b5c39b48e248c4866c511bbba91e1b
              expression: 'last(/Azure PostgreSQL Flexible Server by HTTP/azure.db.pgsql.availability.state)=1'
              name: 'Azure PostgreSQL Flexible: PostgreSQL server is degraded'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The resource is in a degraded state.'
              tags:
                - tag: scope
                  value: availability
            - uuid: d8ce86c853064cba80c9883052ed1403
              expression: 'last(/Azure PostgreSQL Flexible Server by HTTP/azure.db.pgsql.availability.state)=3'
              name: 'Azure PostgreSQL Flexible: PostgreSQL server is in unknown state'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The resource state is unknown.'
              tags:
                - tag: scope
                  value: availability
            - uuid: 9572c9e56a6b44368bcf2d8a17a220d8
              expression: 'last(/Azure PostgreSQL Flexible Server by HTTP/azure.db.pgsql.availability.state)=2'
              name: 'Azure PostgreSQL Flexible: PostgreSQL server is unavailable'
              opdata: '{ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The resource state is unavailable.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 05ada75c666e45269c3c36159f9902cc
          name: 'Connections active'
          type: DEPENDENT
          key: azure.db.pgsql.connections.active
          value_type: FLOAT
          description: 'The count of active connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.active_connections.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 00d1116141874dbfb204ebfe96c203f1
          name: 'Connections failed'
          type: DEPENDENT
          key: azure.db.pgsql.connections.failed
          value_type: FLOAT
          description: 'The count of failed connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.connections_failed.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: network
        - uuid: f422f01bf1c9484e880581f31f70e120
          name: 'Connections succeeded'
          type: DEPENDENT
          key: azure.db.pgsql.connections.succeeded
          value_type: FLOAT
          description: 'The count of succeeded connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.connections_succeeded.total
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 1f1270c6981b4d08864572410fdeccde
          name: 'CPU credits consumed'
          type: DEPENDENT
          key: azure.db.pgsql.cpu.credits.consumed
          value_type: FLOAT
          description: 'The total number of credits consumed by the database server.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.cpu_credits_consumed.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: cpu
        - uuid: e55082c4a278435286335cebd2ae1cac
          name: 'CPU credits remaining'
          type: DEPENDENT
          key: azure.db.pgsql.cpu.credits.remaining
          value_type: FLOAT
          description: 'The total number of credits available to burst.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.cpu_credits_remaining.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: cpu
        - uuid: 8d85c5c73c894cdda6324832a703fea2
          name: 'Percentage CPU'
          type: DEPENDENT
          key: azure.db.pgsql.cpu.percentage
          value_type: FLOAT
          units: '%'
          description: 'The CPU percent of a host.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.cpu_percent.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: cpu
          triggers:
            - uuid: f8672e4488b740a9a17395689c3d853c
              expression: 'min(/Azure PostgreSQL Flexible Server by HTTP/azure.db.pgsql.cpu.percentage,5m)>{$AZURE.DB.CPU.UTIL.CRIT}'
              name: 'Azure PostgreSQL Flexible: High CPU utilization'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The CPU utilization is too high. The system might be slow to respond.'
              tags:
                - tag: scope
                  value: performance
        - uuid: 06c4226667ec4c4489e6d3ad31c3135f
          name: 'Get errors'
          type: DEPENDENT
          key: azure.db.pgsql.data.errors
          value_type: TEXT
          description: 'A list of errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.errors
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: raw
          triggers:
            - uuid: 55962f0d8a4c44c9a6b09da705e94c59
              expression: 'length(last(/Azure PostgreSQL Flexible Server by HTTP/azure.db.pgsql.data.errors))>0'
              name: 'Azure PostgreSQL Flexible: There are errors in requests to API'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 1792c0566e8a438dad5e299d8f5b9094
          name: 'Get data'
          type: SCRIPT
          key: azure.db.pgsql.data.get
          history: '0'
          value_type: TEXT
          params: |
            var AzureDB = {
            	params: {},
            	token: null,
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id', 'resource_id'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            
            		AzureDB.params = params;
            	},
            
            
            	request: function (url, data) {
            		if (typeof data === 'undefined' || data === null) {
            			data = '';
            		}
            
            		var response, request = new HttpRequest();
            		if (typeof AzureDB.params.proxy !== 'undefined' && AzureDB.params.proxy !== '') {
            			request.setProxy(AzureDB.params.proxy);
            		}
            		if (AzureDB.token) {
            			request.addHeader('Accept: application/json');
            			request.addHeader('Authorization: Bearer ' + AzureDB.token);
            		}
            
            		Zabbix.log(4, '[ Azure ] Sending request: ' + url);
            
            		if (data !== '') {
            			request.addHeader('Content-Type: application/x-www-form-urlencoded');
            			response = request.post(url, data);
            		}
            		else {
            			response = request.get(url);
            		}
            
            		Zabbix.log(4, '[ Azure ] Received response with status code ' + request.getStatus() + ': ' + response);
            
            		if (request.getStatus() !== 200 || response === null) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	}
            
            };
            
            var metrics = [
            	'cpu_percent',
            	'memory_percent',
            	'iops',
            	'disk_queue_depth',
            	'read_throughput',
            	'write_throughput',
            	'read_iops',
            	'write_iops',
            	'network_bytes_egress',
            	'network_bytes_ingress',
            	'active_connections',
            	'connections_failed',
            	'connections_succeeded',
            	'storage_percent',
            	'storage_used',
            	'storage_free',
            	'txlogs_storage_used',
            	'backup_storage_used',
            	'maximum_used_transactionIDs',
            	'cpu_credits_remaining',
            	'cpu_credits_consumed'
            ],
            	prepared_metrics = [],
            	data = {};
            	data['errors'] = {};
            	data['metrics'] = {};
            
            try {
            	AzureDB.setParams(JSON.parse(value));
            
            	try {
            		result = AzureDB.request(
            			'https://login.microsoftonline.com/' + encodeURIComponent(AzureDB.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(AzureDB.params.app_id) + '&client_secret=' + encodeURIComponent(AzureDB.params.password)
            		);
            
            		if ('access_token' in result) {
            			AzureDB.token = result['access_token'];
            		} else {
            			throw 'Auth response does not contain access token.';
            		}
            	}
            	catch (error) {
            		data.errors.auth = error.toString();
            	}
            
            	if (!('auth' in data.errors)) {
            		try {
            			health = AzureDB.request('https://management.azure.com' + AzureDB.params.resource_id + '/providers/Microsoft.ResourceHealth/availabilityStatuses?api-version=2020-05-01');
            			if ('value' in health && Array.isArray(health.value) && health.value.length > 0 && 'properties' in health.value[0] && typeof health.value[0].properties === 'object') {
            				data.health = health.value[0].properties;
            			}
            		}
            		catch (error) {
            			data.errors.health = error.toString();
            		}
            
            		for (var i = 0; i < metrics.length; i += 20) {
            			var chunk = metrics.slice(i, i + 20);
            
            			prepared_metrics.push(
            				chunk.map(function (element) {
            					return encodeURIComponent(element);
            				}).join(',')
            			);
            		}
            
            		start_date = new Date((new Date().getTime()) - 600000).toISOString().replace(/\.\d+/, '');
            		end_date = new Date().toISOString().replace(/\.\d+/, '');
            
            		for (var j in prepared_metrics) {
            			try {
            				metrics_data = AzureDB.request('https://management.azure.com' + AzureDB.params.resource_id + '/providers/Microsoft.Insights/metrics?metricnames=' + prepared_metrics[j] + '&timespan=' + encodeURIComponent(start_date) + '/' + encodeURIComponent(end_date) + '&api-version=2021-05-01');
            				if ('value' in metrics_data && Array.isArray(metrics_data.value) && metrics_data.value.length > 0) {
            					for (k in metrics_data.value) {
            						if ('name' in metrics_data.value[k] && typeof metrics_data.value[k].name === 'object' && 'value' in metrics_data.value[k].name && typeof metrics_data.value[k].name.value === 'string' && 'timeseries' in metrics_data.value[k] && Array.isArray(metrics_data.value[k].timeseries) && metrics_data.value[k].timeseries.length > 0 && 'data' in metrics_data.value[k].timeseries[0] && Array.isArray(metrics_data.value[k].timeseries[0].data) && metrics_data.value[k].timeseries[0].data.length > 0) {
            							if (metrics_data.value[k].name.value === 'disk_queue_depth' ||
            								metrics_data.value[k].name.value === 'read_throughput' ||
            								metrics_data.value[k].name.value === 'write_throughput' ||
            								metrics_data.value[k].name.value === 'read_iops' ||
            								metrics_data.value[k].name.value === 'write_iops') {
            									data.metrics[metrics_data.value[k].name.value.replace(/(\s|\/)+/g, '')] = metrics_data.value[k].timeseries[0].data[metrics_data.value[k].timeseries[0].data.length - 6];
            							} else {
            								data.metrics[metrics_data.value[k].name.value.replace(/(\s|\/)+/g, '')] = metrics_data.value[k].timeseries[0].data[metrics_data.value[k].timeseries[0].data.length - 1];
            							}
            						}
            					}
            				}
            			}
            			catch (error) {
            				data.errors[prepared_metrics[j]] = error.toString();
            			}
            		}
            	}
            }
            catch (error) {
            	data.errors.params = error.toString();
            }
            
            if (Object.keys(data.errors).length !== 0) {
            	errors = 'Failed to receive data:';
            	for (var error in data.errors) {
            		errors += '\n' + error + ' : ' + data.errors[error];
            	}
            	data.errors = errors;
            }
            else {
            	data.errors = '';
            }
            
            return JSON.stringify(data);
          description: 'The result of API requests is expressed in the JSON.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: resource_id
              value: '{$AZURE.RESOURCE.ID}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: 9fc7a458995d4ac8a4c1d8550177471d
          name: 'Data disk read Bps'
          type: DEPENDENT
          key: azure.db.pgsql.disk.bps.read
          value_type: FLOAT
          units: Bps
          description: 'Bytes read per second from the data disk during the monitoring period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.read_throughput.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 46c500b44164430c952be3a1b2008fb8
          name: 'Data disk write Bps'
          type: DEPENDENT
          key: azure.db.pgsql.disk.bps.write
          value_type: FLOAT
          units: Bps
          description: 'Bytes written per second to the data disk during the monitoring period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.write_throughput.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: b8812461d49a4ff5a2177c2990969c38
          name: 'Data disk queue depth'
          type: DEPENDENT
          key: azure.db.pgsql.disk.queue.depth
          value_type: FLOAT
          description: 'The number of outstanding I/O operations to the data disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.disk_queue_depth.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 10dd8ed658d8442ca39ac1decf9bc2f8
          name: 'Data disk IOPS'
          type: DEPENDENT
          key: azure.db.pgsql.iops
          value_type: FLOAT
          units: '!ops'
          description: 'I/O operations per second.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.iops.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: dee65b110a4842ccba8e74eefc097304
          name: 'Data disk read IOPS'
          type: DEPENDENT
          key: azure.db.pgsql.iops.read
          value_type: FLOAT
          units: '!ops'
          description: 'The number of the data disk I/O read operations per second.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.read_iops.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 805dfa040c0a4700acac4b5b1f8a4d11
          name: 'Data disk write IOPS'
          type: DEPENDENT
          key: azure.db.pgsql.iops.write
          value_type: FLOAT
          units: '!ops'
          description: 'The number of the data disk I/O write operations per second.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.write_iops.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: d1d909c2dd0d42649094ec8339e08881
          name: 'Memory utilization'
          type: DEPENDENT
          key: azure.db.pgsql.memory.percentage
          value_type: FLOAT
          units: '%'
          description: 'The memory percent of a host.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.memory_percent.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: memory
          triggers:
            - uuid: aac52a89709044ed987a365a1d5af17b
              expression: 'min(/Azure PostgreSQL Flexible Server by HTTP/azure.db.pgsql.memory.percentage,5m)>{$AZURE.DB.MEMORY.UTIL.CRIT}'
              name: 'Azure PostgreSQL Flexible: High memory utilization'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The system is running out of free memory.'
              tags:
                - tag: scope
                  value: performance
        - uuid: 040898e15a26455a9992c603ca2d45df
          name: 'Network out'
          type: DEPENDENT
          key: azure.db.pgsql.network.egress
          value_type: FLOAT
          units: bps
          description: 'The network outbound traffic across the active connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.network_bytes_egress.total
            - type: MULTIPLIER
              parameters:
                - '0.1333'
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 8e398d8b33444a148760ec33622755a6
          name: 'Network in'
          type: DEPENDENT
          key: azure.db.pgsql.network.ingress
          value_type: FLOAT
          units: bps
          description: 'The network inbound traffic across the active connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.network_bytes_ingress.total
            - type: MULTIPLIER
              parameters:
                - '0.1333'
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: network
        - uuid: ebebf8b3a2884576abb250fdc2385c6f
          name: 'Backup storage used'
          type: DEPENDENT
          key: azure.db.pgsql.storage.backup.used
          value_type: FLOAT
          units: B
          description: 'Used backup storage, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.backup_storage_used.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 9bbfba89a1834798b71260536fedab55
          name: 'Storage free'
          type: DEPENDENT
          key: azure.db.pgsql.storage.free
          value_type: FLOAT
          units: B
          description: 'Free storage space, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_free.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: d9d97e728d1741568fce925c0fca33a8
          name: 'Storage percent'
          type: DEPENDENT
          key: azure.db.pgsql.storage.percent
          value_type: FLOAT
          units: '%'
          description: 'The storage utilization, expressed in %.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_percent.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
          triggers:
            - uuid: de3142bed28340d9abe518cd3967b024
              expression: 'last(/Azure PostgreSQL Flexible Server by HTTP/azure.db.pgsql.storage.percent)>{$AZURE.DB.STORAGE.PUSED.CRIT}'
              name: 'Azure PostgreSQL Flexible: Storage space is critically low'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Critical utilization of the storage space.'
              tags:
                - tag: scope
                  value: capacity
            - uuid: e948600affaa4ff4a0ab4e50f4858c0a
              expression: 'last(/Azure PostgreSQL Flexible Server by HTTP/azure.db.pgsql.storage.percent)>{$AZURE.DB.STORAGE.PUSED.WARN}'
              name: 'Azure PostgreSQL Flexible: Storage space is low'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'High utilization of the storage space.'
              tags:
                - tag: scope
                  value: capacity
        - uuid: 4dae6c2c1dbf4492a73fd1834cae6aad
          name: 'Transaction log storage used'
          type: DEPENDENT
          key: azure.db.pgsql.storage.txlogs.used
          value_type: FLOAT
          units: B
          description: 'The storage space used by transaction log, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.txlogs_storage_used.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 7a85b5223ec44ff8bc996c9df1673611
          name: 'Storage used'
          type: DEPENDENT
          key: azure.db.pgsql.storage.used
          value_type: FLOAT
          units: B
          description: 'Used storage space, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_used.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 6df77ed1d4614ca793df56dbc70d821c
          name: 'Maximum used transaction IDs'
          type: DEPENDENT
          key: azure.db.pgsql.txid.used.max
          value_type: FLOAT
          description: 'The maximum number of used transaction IDs.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.maximum_used_transactionIDs.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: sql
        - tag: target
          value: azure
        - tag: target
          value: postgresql
      macros:
        - macro: '{$AZURE.APP.ID}'
          description: 'The App ID of Microsoft Azure.'
          config:
            type: TEXT
            priority: '3'
            label: 'Azure App ID'
            required: 'YES'
        - macro: '{$AZURE.DATA.TIMEOUT}'
          value: 15s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '10'
            section_name: Other
            label: 'API timeout'
            description: 'API response timeout, in seconds.'
        - macro: '{$AZURE.DB.CPU.UTIL.CRIT}'
          value: '90'
          description: 'The critical threshold of CPU utilization, expressed in %.'
          config:
            type: TEXT
            priority: '6'
            section_name: Thresholds
            label: 'CPU utilization critical threshold'
            description: 'Critical threshold of CPU utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.MEMORY.UTIL.CRIT}'
          value: '90'
          description: 'The critical threshold of memory utilization, expressed in %.'
          config:
            type: TEXT
            priority: '7'
            section_name: Thresholds
            label: 'Memory utilization critical threshold'
            description: 'Critical threshold of memory utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.STORAGE.PUSED.CRIT}'
          value: '90'
          description: 'The critical threshold of storage utilization, expressed in %.'
          config:
            type: TEXT
            priority: '9'
            section_name: Thresholds
            label: 'Storage utilization critical threshold'
            description: 'Critical threshold of storage utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.STORAGE.PUSED.WARN}'
          value: '80'
          description: 'The warning threshold of storage utilization, expressed in %.'
          config:
            type: TEXT
            priority: '8'
            section_name: Thresholds
            label: 'Storage utilization warning threshold'
            description: 'Warning threshold of storage utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.PASSWORD}'
          type: SECRET_TEXT
          description: 'Microsoft Azure password.'
          config:
            type: TEXT
            priority: '4'
            label: 'Azure password'
            required: 'YES'
        - macro: '{$AZURE.PROXY}'
          description: 'Sets the HTTP proxy value. If this macro is empty, then no proxy is used.'
          config:
            type: TEXT
            priority: '11'
            section_name: Other
            label: 'HTTP proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AZURE.RESOURCE.ID}'
          description: 'Microsoft Azure PostgreSQL server ID.'
          config:
            type: TEXT
            priority: '5'
            label: 'Azure PostgreSQL server ID'
            required: 'YES'
        - macro: '{$AZURE.SUBSCRIPTION.ID}'
          description: 'Microsoft Azure subscription ID.'
          config:
            type: TEXT
            priority: '1'
            label: 'Azure subscription ID'
            required: 'YES'
        - macro: '{$AZURE.TENANT.ID}'
          description: 'Microsoft Azure tenant ID.'
          config:
            type: TEXT
            priority: '2'
            label: 'Azure tenant ID'
            required: 'YES'
      dashboards:
        - uuid: 89588d831e7348b6b41b47a2cca79190
          name: 'Overview Azure PostgreSQL Flexible Server'
          pages:
            - widgets:
                - type: item
                  name: 'Memory utilization'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.memory.percentage
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'Data disk queue depth'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.disk.queue.depth
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Storage free'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.storage.free
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Network in'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.network.ingress
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Connections active'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.connections.active
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Percentage CPU'
                  x: '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.cpu.percentage
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'Data disk IOPS'
                  x: '12'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.iops
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Storage used'
                  x: '12'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.storage.used
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Network out'
                  x: '12'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.network.egress
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Connections failed'
                  x: '12'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.connections.failed
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Availability state'
                  x: '24'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.availability.state
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: up_color
                      value: FF0000
                - type: item
                  name: 'Data disk read IOPS'
                  x: '24'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.iops.read
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: graph
                  name: 'Storage utilization'
                  x: '24'
                  'y': '6'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        name: 'Azure PostgreSQL: Storage utilization'
                    - type: STRING
                      name: reference
                      value: AAAAA
                - type: graph
                  name: 'Network traffic'
                  x: '24'
                  'y': '9'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        name: 'Azure PostgreSQL: Network traffic'
                    - type: STRING
                      name: reference
                      value: AAAAB
                - type: graph
                  name: Connections
                  x: '24'
                  'y': '12'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        name: 'Azure PostgreSQL: Connections'
                    - type: STRING
                      name: reference
                      value: AAAAC
                - type: itemhistory
                  name: 'Availability status detailed'
                  x: '36'
                  width: '36'
                  height: '3'
                  fields:
                    - type: INTEGER
                      name: columns.0.display
                      value: '4'
                    - type: ITEM
                      name: columns.0.itemid
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.availability.details
                    - type: INTEGER
                      name: columns.0.monospace_font
                      value: '1'
                    - type: STRING
                      name: columns.0.name
                      value: 'Azure PostgreSQL: Availability status detailed'
                    - type: STRING
                      name: reference
                      value: BAAAD
                    - type: INTEGER
                      name: show_timestamp
                      value: '1'
                - type: item
                  name: 'Data disk write IOPS'
                  x: '36'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.iops.write
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Data disk read Bps'
                  x: '48'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.disk.bps.read
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Data disk write Bps'
                  x: '60'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Flexible Server by HTTP'
                        key: azure.db.pgsql.disk.bps.write
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
      valuemaps:
        - uuid: f208cf6141c44659a2c6904ec4cd7ac3
          name: 'Azure resource health state'
          mappings:
            - value: '0'
              newvalue: Available
            - value: '1'
              newvalue: Degraded
            - value: '2'
              newvalue: Unavailable
            - value: '3'
              newvalue: Unknown
    - uuid: d023e2cd326c486f908e3e361d1fe157
      template: 'Azure PostgreSQL Single Server by HTTP'
      name: 'Azure PostgreSQL Single Server by HTTP'
      description: |
        This template is designed to monitor Microsoft Azure PostgreSQL servers by HTTP.
        It works without any external scripts and uses the script item.
        
        Setup:
          1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
            `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
            See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
          2. Link the template to a host.
          3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
        
        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 is designed to monitor Microsoft Azure PostgreSQL servers by HTTP.
        It works without any external scripts and uses the script item.
        
        ## Setup
        
        1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
        
              `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
        
        > See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
        
        2. Link the template to a host.
        3. Configure the macros: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure PostgreSQL server ID`.
      vendor:
        name: Zabbix
        version: 7.4-1
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 9eb43a5ffb0d4e07be8d1fccfdecd2aa
          name: 'Availability status detailed'
          type: DEPENDENT
          key: azure.db.pgsql.availability.details
          value_type: CHAR
          description: 'The summary description of the availability status.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.summary
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: health
        - uuid: df4c66646f864f79b5f5e9f71dbefe82
          name: 'Availability state'
          type: DEPENDENT
          key: azure.db.pgsql.availability.state
          description: 'The availability status of the resource.'
          valuemap:
            name: 'Azure resource health state'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.availabilityState
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: STR_REPLACE
              parameters:
                - Available
                - '0'
            - type: STR_REPLACE
              parameters:
                - Degraded
                - '1'
            - type: STR_REPLACE
              parameters:
                - Unavailable
                - '2'
            - type: STR_REPLACE
              parameters:
                - Unknown
                - '3'
            - type: IN_RANGE
              parameters:
                - '0'
                - '3'
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: health
          triggers:
            - uuid: 699ca12c916746b1bf1e121261771cc3
              expression: 'last(/Azure PostgreSQL Single Server by HTTP/azure.db.pgsql.availability.state)=1'
              name: 'Azure PostgreSQL Single: PostgreSQL server is degraded'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The resource is in a degraded state.'
              tags:
                - tag: scope
                  value: availability
            - uuid: 14e45ba0bc26409a89d92edfda152947
              expression: 'last(/Azure PostgreSQL Single Server by HTTP/azure.db.pgsql.availability.state)=3'
              name: 'Azure PostgreSQL Single: PostgreSQL server is in unknown state'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The resource state is unknown.'
              tags:
                - tag: scope
                  value: availability
            - uuid: 4dc9113f8a914ac098d8736dba5aed4a
              expression: 'last(/Azure PostgreSQL Single Server by HTTP/azure.db.pgsql.availability.state)=2'
              name: 'Azure PostgreSQL Single: PostgreSQL server is unavailable'
              opdata: '{ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The resource state is unavailable.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 3d0d3e1fe77740e4bd7b720368707214
          name: 'Connections active'
          type: DEPENDENT
          key: azure.db.pgsql.connections.active
          value_type: FLOAT
          description: 'The count of active connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.active_connections.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 353a6ba543a84b32b16a5809ae63b4e1
          name: 'Connections failed'
          type: DEPENDENT
          key: azure.db.pgsql.connections.failed
          value_type: FLOAT
          description: 'The count of failed connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.connections_failed.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 537330b2372b434ebcea8a77a809c2f3
          name: 'Percentage CPU'
          type: DEPENDENT
          key: azure.db.pgsql.cpu.percentage
          value_type: FLOAT
          units: '%'
          description: 'The CPU percent of a host.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.cpu_percent.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: cpu
          triggers:
            - uuid: 33bd2ef88ad3468b9f0b2b1358cc7448
              expression: 'min(/Azure PostgreSQL Single Server by HTTP/azure.db.pgsql.cpu.percentage,5m)>{$AZURE.DB.CPU.UTIL.CRIT}'
              name: 'Azure PostgreSQL Single: High CPU utilization'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The CPU utilization is too high. The system might be slow to respond.'
              tags:
                - tag: scope
                  value: performance
        - uuid: 5b132ff050c94daa92b252529a52c535
          name: 'Get errors'
          type: DEPENDENT
          key: azure.db.pgsql.data.errors
          value_type: TEXT
          description: 'A list of errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.errors
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: raw
          triggers:
            - uuid: dd3d0be997204f8b9968ef5839fb7a9b
              expression: 'length(last(/Azure PostgreSQL Single Server by HTTP/azure.db.pgsql.data.errors))>0'
              name: 'Azure PostgreSQL Single: There are errors in requests to API'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              tags:
                - tag: scope
                  value: availability
        - uuid: e47d863822e64e6292bfa3e684bc2839
          name: 'Get data'
          type: SCRIPT
          key: azure.db.pgsql.data.get
          history: '0'
          value_type: TEXT
          params: |
            var AzureDB = {
            	params: {},
            	token: null,
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id', 'resource_id'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            
            		AzureDB.params = params;
            	},
            
            
            	request: function (url, data) {
            		if (typeof data === 'undefined' || data === null) {
            			data = '';
            		}
            
            		var response, request = new HttpRequest();
            		if (typeof AzureDB.params.proxy !== 'undefined' && AzureDB.params.proxy !== '') {
            			request.setProxy(AzureDB.params.proxy);
            		}
            		if (AzureDB.token) {
            			request.addHeader('Accept: application/json');
            			request.addHeader('Authorization: Bearer ' + AzureDB.token);
            		}
            
            		Zabbix.log(4, '[ Azure ] Sending request: ' + url);
            
            		if (data !== '') {
            			request.addHeader('Content-Type: application/x-www-form-urlencoded');
            			response = request.post(url, data);
            		}
            		else {
            			response = request.get(url);
            		}
            
            		Zabbix.log(4, '[ Azure ] Received response with status code ' + request.getStatus() + ': ' + response);
            
            		if (request.getStatus() !== 200 || response === null) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	}
            
            };
            
            var metrics = [
            	'cpu_percent',
            	'memory_percent',
            	'io_consumption_percent',
            	'storage_percent',
            	'storage_used',
            	'storage_limit',
            	'serverlog_storage_percent',
            	'serverlog_storage_usage',
            	'serverlog_storage_limit',
            	'active_connections',
            	'connections_failed',
            	'backup_storage_used',
            	'network_bytes_egress',
            	'network_bytes_ingress',
            	'pg_replica_log_delay_in_seconds',
            	'pg_replica_log_delay_in_bytes'
            ],
            	prepared_metrics = [],
            	data = {};
            	data['errors'] = {};
            	data['metrics'] = {};
            
            try {
            	AzureDB.setParams(JSON.parse(value));
            
            	try {
            		result = AzureDB.request(
            			'https://login.microsoftonline.com/' + encodeURIComponent(AzureDB.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(AzureDB.params.app_id) + '&client_secret=' + encodeURIComponent(AzureDB.params.password)
            		);
            
            		if ('access_token' in result) {
            			AzureDB.token = result['access_token'];
            		} else {
            			throw 'Auth response does not contain access token.';
            		}
            	}
            	catch (error) {
            		data.errors.auth = error.toString();
            	}
            
            	if (!('auth' in data.errors)) {
            		try {
            			health = AzureDB.request('https://management.azure.com' + AzureDB.params.resource_id + '/providers/Microsoft.ResourceHealth/availabilityStatuses?api-version=2020-05-01');
            			if ('value' in health && Array.isArray(health.value) && health.value.length > 0 && 'properties' in health.value[0] && typeof health.value[0].properties === 'object') {
            				data.health = health.value[0].properties;
            			}
            		}
            		catch (error) {
            			data.errors.health = error.toString();
            		}
            
            		for (var i = 0; i < metrics.length; i += 20) {
            			var chunk = metrics.slice(i, i + 20);
            
            			prepared_metrics.push(
            				chunk.map(function (element) {
            					return encodeURIComponent(element);
            				}).join(',')
            			);
            		}
            
            		start_date = new Date((new Date().getTime()) - 300000).toISOString().replace(/\.\d+/, '');
            		end_date = new Date().toISOString().replace(/\.\d+/, '');
            
            		for (var j in prepared_metrics) {
            			try {
            				metrics_data = AzureDB.request('https://management.azure.com' + AzureDB.params.resource_id + '/providers/Microsoft.Insights/metrics?metricnames=' + prepared_metrics[j] + '&timespan=' + encodeURIComponent(start_date) + '/' + encodeURIComponent(end_date) + '&api-version=2021-05-01');
            				if ('value' in metrics_data && Array.isArray(metrics_data.value) && metrics_data.value.length > 0) {
            					for (k in metrics_data.value) {
            						if ('name' in metrics_data.value[k] && typeof metrics_data.value[k].name === 'object' && 'value' in metrics_data.value[k].name && typeof metrics_data.value[k].name.value === 'string' && 'timeseries' in metrics_data.value[k] && Array.isArray(metrics_data.value[k].timeseries) && metrics_data.value[k].timeseries.length > 0 && 'data' in metrics_data.value[k].timeseries[0] && Array.isArray(metrics_data.value[k].timeseries[0].data) && metrics_data.value[k].timeseries[0].data.length > 0) {
            							data.metrics[metrics_data.value[k].name.value.replace(/(\s|\/)+/g, '')] = metrics_data.value[k].timeseries[0].data[metrics_data.value[k].timeseries[0].data.length - 1];
            						}
            					}
            				}
            			}
            			catch (error) {
            				data.errors[prepared_metrics[j]] = error.toString();
            			}
            		}
            	}
            }
            catch (error) {
            	data.errors.params = error.toString();
            }
            
            if (Object.keys(data.errors).length !== 0) {
            	errors = 'Failed to receive data:';
            	for (var error in data.errors) {
            		errors += '\n' + error + ' : ' + data.errors[error];
            	}
            	data.errors = errors;
            }
            else {
            	data.errors = '';
            }
            
            return JSON.stringify(data);
          description: 'The result of API requests is expressed in the JSON.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: resource_id
              value: '{$AZURE.RESOURCE.ID}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: 9eade85c49bc462aab33b03e37581d87
          name: 'IO consumption percent'
          type: DEPENDENT
          key: azure.db.pgsql.io.consumption.percent
          value_type: FLOAT
          units: '%'
          description: 'The consumption percent of I/O.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.io_consumption_percent.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: operations
        - uuid: e2ee4882b08f45788e6abb698265810e
          name: 'Memory utilization'
          type: DEPENDENT
          key: azure.db.pgsql.memory.percentage
          value_type: FLOAT
          units: '%'
          description: 'The memory percent of a host.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.memory_percent.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: memory
          triggers:
            - uuid: 3119f21167a546369c05d31cda2e0147
              expression: 'min(/Azure PostgreSQL Single Server by HTTP/azure.db.pgsql.memory.percentage,5m)>{$AZURE.DB.MEMORY.UTIL.CRIT}'
              name: 'Azure PostgreSQL Single: High memory utilization'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The system is running out of free memory.'
              tags:
                - tag: scope
                  value: performance
        - uuid: f81eeb98d5e942f296c360ff71e8bf8d
          name: 'Network out'
          type: DEPENDENT
          key: azure.db.pgsql.network.egress
          value_type: FLOAT
          units: bps
          description: 'The network outbound traffic across the active connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.network_bytes_egress.total
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '0.1333'
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 51f7e35042d04ddb88c7703d1b015d3b
          name: 'Network in'
          type: DEPENDENT
          key: azure.db.pgsql.network.ingress
          value_type: FLOAT
          units: bps
          description: 'The network inbound traffic across the active connections.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.network_bytes_ingress.total
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '0.1333'
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: network
        - uuid: 1db9e470b527476fae1d26d4b67f855b
          name: 'Replication lag'
          type: DEPENDENT
          key: azure.db.pgsql.replica.log.delay
          value_type: FLOAT
          units: s
          description: 'The replication lag, expressed in seconds.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.pg_replica_log_delay_in_seconds.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: replication
        - uuid: 6cdfda8f9e6640f8a8536f88729d75d6
          name: 'Max lag across replicas in bytes'
          type: DEPENDENT
          key: azure.db.pgsql.replica.log.delay.bytes
          value_type: FLOAT
          units: B
          description: 'Lag for the most lagging replica, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.pg_replica_log_delay_in_bytes.maximum
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: replication
        - uuid: 6b06fb0e008640839dc3cda5bcc3f91a
          name: 'Backup storage used'
          type: DEPENDENT
          key: azure.db.pgsql.storage.backup.used
          value_type: FLOAT
          units: B
          description: 'Used backup storage, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.backup_storage_used.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: b8d5ac0b049a4d73b2f35f59c7e7609c
          name: 'Storage limit'
          type: DEPENDENT
          key: azure.db.pgsql.storage.limit
          value_type: FLOAT
          units: B
          description: 'The storage limit, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_limit.maximum
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 750b4d3438614cc992694136d309c3cb
          name: 'Storage percent'
          type: DEPENDENT
          key: azure.db.pgsql.storage.percent
          value_type: FLOAT
          units: '%'
          description: 'The storage utilization, expressed in %.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_percent.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
          triggers:
            - uuid: 6538d2c8ed774feb951204308f1458ce
              expression: 'last(/Azure PostgreSQL Single Server by HTTP/azure.db.pgsql.storage.percent)>{$AZURE.DB.STORAGE.PUSED.CRIT}'
              name: 'Azure PostgreSQL Single: Storage space is critically low'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Critical utilization of the storage space.'
              tags:
                - tag: scope
                  value: capacity
            - uuid: 7f7a004cfc2a492092dd74c475888e8b
              expression: 'last(/Azure PostgreSQL Single Server by HTTP/azure.db.pgsql.storage.percent)>{$AZURE.DB.STORAGE.PUSED.WARN}'
              name: 'Azure PostgreSQL Single: Storage space is low'
              opdata: 'Current utilization: {ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'High utilization of the storage space.'
              tags:
                - tag: scope
                  value: capacity
        - uuid: 399ef67426494a5cb7a820d056dfd4d5
          name: 'Server log storage limit'
          type: DEPENDENT
          key: azure.db.pgsql.storage.server.log.limit
          value_type: FLOAT
          units: B
          description: 'The storage limit of server log, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.serverlog_storage_limit.maximum
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: ef6890330ebe4fe09f46b0d2f6d3f827
          name: 'Server log storage percent'
          type: DEPENDENT
          key: azure.db.pgsql.storage.server.log.percent
          value_type: FLOAT
          units: '%'
          description: 'The storage utilization by server log, expressed in %.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.serverlog_storage_percent.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 36bd10a959964083ae47349dd83ec695
          name: 'Server log storage used'
          type: DEPENDENT
          key: azure.db.pgsql.storage.server.log.used
          value_type: FLOAT
          units: B
          description: 'The storage space used by server log, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.serverlog_storage_usage.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
        - uuid: dcbb87d442a04938b23e68f739f1e36f
          name: 'Storage used'
          type: DEPENDENT
          key: azure.db.pgsql.storage.used
          value_type: FLOAT
          units: B
          description: 'Used storage space, expressed in bytes.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_used.average
          master_item:
            key: azure.db.pgsql.data.get
          tags:
            - tag: component
              value: storage
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: sql
        - tag: target
          value: azure
        - tag: target
          value: postgresql
      macros:
        - macro: '{$AZURE.APP.ID}'
          description: 'The App ID of Microsoft Azure.'
          config:
            type: TEXT
            priority: '3'
            label: 'Azure App ID'
            required: 'YES'
        - macro: '{$AZURE.DATA.TIMEOUT}'
          value: 15s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '10'
            section_name: Other
            label: 'API timeout'
            description: 'API response timeout, in seconds.'
        - macro: '{$AZURE.DB.CPU.UTIL.CRIT}'
          value: '90'
          description: 'The critical threshold of CPU utilization, expressed in %.'
          config:
            type: TEXT
            priority: '6'
            section_name: Thresholds
            label: 'CPU utilization critical threshold'
            description: 'Critical threshold of CPU utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.MEMORY.UTIL.CRIT}'
          value: '90'
          description: 'The critical threshold of memory utilization, expressed in %.'
          config:
            type: TEXT
            priority: '7'
            section_name: Thresholds
            label: 'Memory utilization critical threshold'
            description: 'Critical threshold of memory utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.STORAGE.PUSED.CRIT}'
          value: '90'
          description: 'The critical threshold of storage utilization, expressed in %.'
          config:
            type: TEXT
            priority: '9'
            section_name: Thresholds
            label: 'Storage utilization critical threshold'
            description: 'Critical threshold of storage utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.DB.STORAGE.PUSED.WARN}'
          value: '80'
          description: 'The warning threshold of storage utilization, expressed in %.'
          config:
            type: TEXT
            priority: '8'
            section_name: Thresholds
            label: 'Storage utilization warning threshold'
            description: 'Warning threshold of storage utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.PASSWORD}'
          type: SECRET_TEXT
          description: 'Microsoft Azure password.'
          config:
            type: TEXT
            priority: '4'
            label: 'Azure password'
            required: 'YES'
        - macro: '{$AZURE.PROXY}'
          description: 'Sets the HTTP proxy value. If this macro is empty, then no proxy is used.'
          config:
            type: TEXT
            priority: '11'
            section_name: Other
            label: 'HTTP proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AZURE.RESOURCE.ID}'
          description: 'Microsoft Azure PostgreSQL server ID.'
          config:
            type: TEXT
            priority: '5'
            label: 'Azure PostgreSQL server ID'
            required: 'YES'
        - macro: '{$AZURE.SUBSCRIPTION.ID}'
          description: 'Microsoft Azure subscription ID.'
          config:
            type: TEXT
            priority: '1'
            label: 'Azure subscription ID'
            required: 'YES'
        - macro: '{$AZURE.TENANT.ID}'
          description: 'Microsoft Azure tenant ID.'
          config:
            type: TEXT
            priority: '2'
            label: 'Azure tenant ID'
            required: 'YES'
      dashboards:
        - uuid: 9ef73571560743379fa0b4929370e1b4
          name: 'Overview Azure PostgreSQL Single Server'
          pages:
            - widgets:
                - type: item
                  name: 'Memory utilization'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        key: azure.db.pgsql.memory.percentage
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'Network in'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        key: azure.db.pgsql.network.ingress
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Server log storage limit'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        key: azure.db.pgsql.storage.server.log.limit
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Storage limit'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        key: azure.db.pgsql.storage.limit
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Connections active'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        key: azure.db.pgsql.connections.active
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Percentage CPU'
                  x: '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        key: azure.db.pgsql.cpu.percentage
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: units
                      value: '%'
                - type: item
                  name: 'Network out'
                  x: '12'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        key: azure.db.pgsql.network.egress
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Server log storage used'
                  x: '12'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        key: azure.db.pgsql.storage.server.log.used
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Storage used'
                  x: '12'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        key: azure.db.pgsql.storage.used
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Connections failed'
                  x: '12'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        key: azure.db.pgsql.connections.failed
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Availability state'
                  x: '24'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        key: azure.db.pgsql.availability.state
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: up_color
                      value: FF0000
                - type: graph
                  name: 'Network traffic'
                  x: '24'
                  'y': '3'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        name: 'Azure PostgreSQL: Network traffic'
                    - type: STRING
                      name: reference
                      value: AAAAA
                - type: graph
                  name: 'Server log storage utilization'
                  x: '24'
                  'y': '6'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        name: 'Azure PostgreSQL: Server log storage utilization'
                    - type: STRING
                      name: reference
                      value: AAAAB
                - type: graph
                  name: 'Storage utilization'
                  x: '24'
                  'y': '9'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        name: 'Azure PostgreSQL: Storage utilization'
                    - type: STRING
                      name: reference
                      value: AAAAC
                - type: graph
                  name: Connections
                  x: '24'
                  'y': '12'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        name: 'Azure PostgreSQL: Connections'
                    - type: STRING
                      name: reference
                      value: AAAAD
                - type: itemhistory
                  name: 'Availability status detailed'
                  x: '36'
                  width: '36'
                  height: '3'
                  fields:
                    - type: INTEGER
                      name: columns.0.display
                      value: '4'
                    - type: ITEM
                      name: columns.0.itemid
                      value:
                        host: 'Azure PostgreSQL Single Server by HTTP'
                        key: azure.db.pgsql.availability.details
                    - type: INTEGER
                      name: columns.0.monospace_font
                      value: '1'
                    - type: STRING
                      name: columns.0.name
                      value: 'Azure PostgreSQL: Availability status detailed'
                    - type: STRING
                      name: reference
                      value: BAAAE
                    - type: INTEGER
                      name: show_timestamp
                      value: '1'
      valuemaps:
        - uuid: 61fc206aaae04abda4012e031f0e27ac
          name: 'Azure resource health state'
          mappings:
            - value: '0'
              newvalue: Available
            - value: '1'
              newvalue: Degraded
            - value: '2'
              newvalue: Unavailable
            - value: '3'
              newvalue: Unknown
    - uuid: a93f57ccc68e442da79bf4a20fe46570
      template: 'Azure SQL Managed Instance by HTTP'
      name: 'Azure SQL Managed Instance by HTTP'
      description: |
        This template is designed to monitor Azure SQL Managed Instance by HTTP.
        It works without any external scripts and uses the script item.
        
        Setup:
          1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
            `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
            See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
          2. Link the template to a host.
          3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
        
        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 is designed to monitor Microsoft Azure SQL Managed Instance by HTTP.
        It works without any external scripts and uses the script item.
        
        ## Setup
        
        1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
        
              `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
        
        > See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
        
        2. Link the template to a host.
        3. Configure the macros: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure SQL managed instance ID`.
      vendor:
        name: Zabbix
        version: 7.4-2
      groups:
        - name: Templates/Cloud
      items:
        - uuid: dd047204951f449496ab9b4938dd0a3a
          name: 'Availability status detailed'
          type: DEPENDENT
          key: azure.sql_inst.availability.details
          value_type: CHAR
          description: 'The summary description of the availability status.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.summary
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.sql_inst.data.get
          tags:
            - tag: component
              value: health
        - uuid: be4a868809374a80a9ed3150e098f470
          name: 'Availability state'
          type: DEPENDENT
          key: azure.sql_inst.availability.state
          description: |
            The availability status of the resource.
            0 - Available - no events detected that affect the health of the resource.
            1 - Degraded  - your resource detected a loss in performance, although it's still available for use.
            2 - Unavailable - the service detected an ongoing platform or non-platform event that affects the health of the resource.
            3 - Unknown - Resource Health hasn't received information about the resource for more than 10 minutes.
          valuemap:
            name: 'Azure resource health state'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.availabilityState
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: STR_REPLACE
              parameters:
                - Available
                - '0'
            - type: STR_REPLACE
              parameters:
                - Degraded
                - '1'
            - type: STR_REPLACE
              parameters:
                - Unavailable
                - '2'
            - type: STR_REPLACE
              parameters:
                - Unknown
                - '3'
            - type: IN_RANGE
              parameters:
                - '0'
                - '3'
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.sql_inst.data.get
          tags:
            - tag: component
              value: health
          triggers:
            - uuid: 68d6f9d594f64579a7c6be464e126629
              expression: 'last(/Azure SQL Managed Instance by HTTP/azure.sql_inst.availability.state)=1'
              name: 'Azure SQL instance: Azure SQL managed instance is degraded'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The resource is in a degraded state.'
              tags:
                - tag: scope
                  value: availability
            - uuid: 9a7ebcccf4684fad8523866fb489e06b
              expression: 'last(/Azure SQL Managed Instance by HTTP/azure.sql_inst.availability.state)=3'
              name: 'Azure SQL instance: Azure SQL managed instance is in unknown state'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The resource state is unknown.'
              tags:
                - tag: scope
                  value: availability
            - uuid: 4a08e72f744e4a0faee2d2e29714d8b8
              expression: 'last(/Azure SQL Managed Instance by HTTP/azure.sql_inst.availability.state)=2'
              name: 'Azure SQL instance: Azure SQL managed instance is unavailable'
              opdata: '{ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The resource state is unavailable.'
              tags:
                - tag: scope
                  value: availability
        - uuid: de4033c537154bf1ae4c33f802f5d923
          name: 'IO bytes read'
          type: DEPENDENT
          key: azure.sql_inst.bytes.read
          units: B
          description: 'Bytes read by the managed instance.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.io_bytes_read.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.sql_inst.data.get
          tags:
            - tag: component
              value: performance
        - uuid: 230b2e3632274288aa9b4f8667ad5586
          name: 'IO bytes write'
          type: DEPENDENT
          key: azure.sql_inst.bytes.write
          units: B
          description: 'Bytes written by the managed instance.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.io_bytes_written.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.sql_inst.data.get
          tags:
            - tag: component
              value: performance
        - uuid: 8ef68ff7b24a462b903960a66c5e3acb
          name: 'Instance collation'
          type: DEPENDENT
          key: azure.sql_inst.collation
          value_type: CHAR
          description: 'Collation of the managed instance.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.instance.properties.collation
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1d
          master_item:
            key: azure.sql_inst.data.get
          tags:
            - tag: component
              value: database
          triggers:
            - uuid: 5c8068386b0a47438713d2b4bd54954a
              expression: 'change(/Azure SQL Managed Instance by HTTP/azure.sql_inst.collation)=1'
              name: 'Azure SQL instance: Instance collation has changed'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Azure SQL managed instance collation has changed.'
              tags:
                - tag: scope
                  value: notice
        - uuid: 4020903b19234e7b83b725d0c56caa82
          name: 'Virtual core count'
          type: DEPENDENT
          key: azure.sql_inst.core.count
          description: 'Virtual core count available to the managed instance.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.virtual_core_count.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.sql_inst.data.get
          tags:
            - tag: component
              value: performance
        - uuid: 62fd264c07fe410ca8f43970c8ecdaef
          name: 'Average CPU utilization'
          type: DEPENDENT
          key: azure.sql_inst.cpu
          value_type: FLOAT
          units: '%'
          description: 'Average CPU utilization of the instance.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.avg_cpu_percent.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.sql_inst.data.get
          tags:
            - tag: component
              value: cpu
          triggers:
            - uuid: 553333ffdbf142539799e7a7b6e8af2b
              expression: 'min(/Azure SQL Managed Instance by HTTP/azure.sql_inst.cpu, 10m)>={$AZURE.SQL.INST.CPU.CRIT}'
              name: 'Azure SQL instance: Critically high CPU utilization'
              event_name: 'Azure SQL instance: Critically high CPU utilization: (over >= {$AZURE.SQL.INST.CPU.CRIT}% over last 10m)'
              opdata: 'Current utilization: {ITEM.LASTVALUE}'
              priority: AVERAGE
              description: 'CPU utilization is critically high.'
              dependencies:
                - name: 'Azure SQL instance: High CPU utilization'
                  expression: 'min(/Azure SQL Managed Instance by HTTP/azure.sql_inst.cpu, 10m)>={$AZURE.SQL.INST.CPU.WARN}'
              tags:
                - tag: scope
                  value: performance
            - uuid: 7c5876872c644f8598a1fd275d4763d2
              expression: 'min(/Azure SQL Managed Instance by HTTP/azure.sql_inst.cpu, 10m)>={$AZURE.SQL.INST.CPU.WARN}'
              name: 'Azure SQL instance: High CPU utilization'
              event_name: 'Azure SQL instance: High CPU utilization: (over >= {$AZURE.SQL.INST.CPU.WARN}% over last 10m)'
              opdata: 'Current utilization: {ITEM.LASTVALUE}'
              priority: WARNING
              description: 'CPU utilization is too high.'
              tags:
                - tag: scope
                  value: performance
        - uuid: 0d4e2f5863474225a5584fbcbb7e51d1
          name: 'Get errors'
          type: DEPENDENT
          key: azure.sql_inst.data.errors
          value_type: TEXT
          description: 'A list of errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.sql_inst.data.get
          tags:
            - tag: component
              value: error
          triggers:
            - uuid: 35ec346076ca4c979897e91389d23eb7
              expression: 'length(last(/Azure SQL Managed Instance by HTTP/azure.sql_inst.data.errors))>0'
              name: 'Azure SQL instance: There are errors in requests to API'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 4dc91ae07bd048128a34da5b7ba090e8
          name: 'Get data'
          type: SCRIPT
          key: azure.sql_inst.data.get
          history: '0'
          value_type: TEXT
          params: |
            var Azure = {
            	params: {},
            	token: null,
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id', 'resource_id'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            
            		Azure.params = params;
            	},
            
            	login: function () {
            		var response, login = new HttpRequest();
            
            		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
            			login.setProxy(Azure.params.proxy);
            		}
            
            		login.addHeader('Content-Type: application/x-www-form-urlencoded');
            		response = login.post(
            			'https://login.microsoftonline.com/' + encodeURIComponent(Azure.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(Azure.params.app_id) + '&client_secret=' + encodeURIComponent(Azure.params.password)
            		);
            
            		if (login.getStatus() !== 200) {
            			throw 'Login failed with status code ' + login.getStatus() + ': ' + response;
            		}
            
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse login session response.';
            		}
            
            		if (!response.hasOwnProperty('access_token')) {
            			throw 'Authentication response does not contain access token.';
            		}
            
            		Azure.token = response['access_token'];
            	},
            
            	request: function (url) {
            		var response, request = new HttpRequest();
            
            		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
            			request.setProxy(Azure.params.proxy);
            		}
            
            		if (!Azure.token) {
            			throw 'Request does not contain access token.';
            		}
            
            		request.addHeader('Content-Type: application/json');
            		request.addHeader('Authorization: Bearer ' + Azure.token);
            		Zabbix.log(4, '[ Azure SQL instance ] request url: ' + url);
            
            		response = request.get(url);
            
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	},
            
            	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;
            	},
            
            	getMetricsData: function () {
            		var data = {},
            			metric_endpoints = {
            				'main_metrics': '/providers/Microsoft.Insights/metrics?metricnames=' + encodeURIComponent('virtual_core_count,avg_cpu_percent,reserved_storage_mb,storage_space_used_mb,io_requests,io_bytes_read,io_bytes_written') + '&api-version=2021-05-01&timespan=PT5M',
            			};
            
            		data.metrics = {};
            
            		Object.keys(metric_endpoints).forEach(function (field) {
            			metrics = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + metric_endpoints[field]), 'value');
            			for (k in metrics) {
            				key = Azure.getField(metrics[k], 'name.value').replace(/(\s|\/)+/g, '');
            				if (metrics[k].timeseries.length === 0) {
            					metrics[k].timeseries.push({ 'data': ['nodata'] })
            				}
            				values = Azure.getField(metrics[k], 'timeseries.0.data');
            				for (var i = values.length - 1; i >= 0; i--) {
            					if (typeof (values[i].average) !== 'undefined') {
            						data.metrics[key] = values[i];
            						break;
            					}
            				}
            			}
            		});
            
            		data.health = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + '/providers/Microsoft.ResourceHealth/availabilityStatuses?api-version=2020-05-01'), 'value.0.properties');
            		data.instance = Azure.request('https://management.azure.com' + Azure.params.resource_id + '?api-version=2024-05-01-preview');
            
            		return data
            	}
            };
            
            try {
            	Azure.setParams(JSON.parse(value));
            	Azure.login();
            	return JSON.stringify(Azure.getMetricsData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ Azure SQL instance ] ERROR: ' + error);
            	return JSON.stringify({ 'error': error });
            }
          description: 'Gathers data of the Azure SQL managed instance.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: resource_id
              value: '{$AZURE.RESOURCE.ID}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: 953ba49d81a048dcbed882b955606c96
          name: 'Instance provisioning state'
          type: DEPENDENT
          key: azure.sql_inst.provision
          description: 'Provisioning state of the managed instance.'
          valuemap:
            name: 'Azure SQL instance provisioning state'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.instance.properties.provisioningState
              error_handler: DISCARD_VALUE
            - type: JAVASCRIPT
              parameters:
                - |
                  const idx = {
                  	'Unknown': 0,
                  	'Accepted': 1,
                  	'Canceled': 2,
                  	'Created': 3,
                  	'Creating': 4,
                  	'Deleted': 5,
                  	'Deleting': 6,
                  	'Failed': 7,
                  	'NotSpecified': 8,
                  	'Registering': 9,
                  	'Running': 10,
                  	'Succeeded': 11,
                  	'TimedOut': 12,
                  	'Unrecognized': 13,
                  	'Updating': 14
                  };
                  
                  return typeof idx[value] === 'undefined' ? 0 : idx[value];
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.sql_inst.data.get
          tags:
            - tag: component
              value: health
          triggers:
            - uuid: 08a59eccbb854b6db1711c9141231e94
              expression: 'change(/Azure SQL Managed Instance by HTTP/azure.sql_inst.provision)<>0'
              name: 'Azure SQL instance: Instance provisioning state has changed'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Azure SQL managed instance provisioning state has changed.'
              tags:
                - tag: scope
                  value: notice
        - uuid: d311532917fa409e909c34f3a2d9032b
          name: 'IO request count'
          type: DEPENDENT
          key: azure.sql_inst.requests
          description: 'IO request count by the managed instance.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.io_requests.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.sql_inst.data.get
          tags:
            - tag: component
              value: performance
        - uuid: e72ef80733cb4dff9722ea1ef73c59d1
          name: 'Instance state'
          type: DEPENDENT
          key: azure.sql_inst.state
          value_type: CHAR
          description: 'State of the managed instance.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.instance.properties.state
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.sql_inst.data.get
          tags:
            - tag: component
              value: health
          triggers:
            - uuid: 9a51e2286f354820b89cd0d35586b99a
              expression: 'change(/Azure SQL Managed Instance by HTTP/azure.sql_inst.state)=1'
              name: 'Azure SQL instance: Instance state has changed'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'Azure SQL managed instance state has changed.'
              tags:
                - tag: scope
                  value: availability
        - uuid: 960e4282247f4ea0bc947e2f35182ec2
          name: 'Storage space reserved'
          type: DEPENDENT
          key: azure.sql_inst.storage.reserved
          units: B
          description: 'Storage space reserved by the managed instance.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.reserved_storage_mb.average
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '1048576'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.sql_inst.data.get
          tags:
            - tag: component
              value: storage
        - uuid: dd1af2bc16c94b2f8636d24a1aedca0b
          name: 'Storage space used'
          type: DEPENDENT
          key: azure.sql_inst.storage.used
          units: B
          description: 'Storage space used by the managed instance.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.storage_space_used_mb.average
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '1048576'
          master_item:
            key: azure.sql_inst.data.get
          tags:
            - tag: component
              value: storage
        - uuid: b3ea1180eb174fb38656c9696fa9d9a7
          name: 'Storage space utilization'
          type: CALCULATED
          key: azure.sql_inst.storage.utilization
          units: '%'
          params: 'last(//azure.sql_inst.storage.used) * 100 / last(//azure.sql_inst.storage.reserved)'
          description: 'Managed instance storage space utilization, in percent.'
          tags:
            - tag: component
              value: storage
          triggers:
            - uuid: ed8c37e4f62b471385402e0bcf6cc47e
              expression: 'min(/Azure SQL Managed Instance by HTTP/azure.sql_inst.storage.utilization,5m)>{$AZURE.SQL.INST.SPACE.CRIT}'
              name: 'Azure SQL instance: Storage free space is critically low'
              event_name: 'Azure SQL instance: The free storage space is critically low (below {$AZURE.SQL.INST.SPACE.CRIT}% for 5m)'
              opdata: 'Space free: {ITEM.LASTVALUE}'
              priority: AVERAGE
              description: 'The free storage space has been less than `{$AZURE.SQL.INST.SPACE.CRIT}`% for 5m.'
              manual_close: 'YES'
              dependencies:
                - name: 'Azure SQL instance: Storage free space is low'
                  expression: 'min(/Azure SQL Managed Instance by HTTP/azure.sql_inst.storage.utilization,5m)>{$AZURE.SQL.INST.SPACE.WARN}'
              tags:
                - tag: scope
                  value: capacity
            - uuid: bf8c527a0566490d829ae7654057a1ec
              expression: 'min(/Azure SQL Managed Instance by HTTP/azure.sql_inst.storage.utilization,5m)>{$AZURE.SQL.INST.SPACE.WARN}'
              name: 'Azure SQL instance: Storage free space is low'
              event_name: 'Azure SQL instance: The free storage space is low (below {$AZURE.SQL.INST.SPACE.WARN}% for 5m)'
              opdata: 'Space free: {ITEM.LASTVALUE}'
              priority: WARNING
              description: 'The free storage space has been less than `{$AZURE.SQL.INST.SPACE.WARN}`% for 5m.'
              manual_close: 'YES'
              tags:
                - tag: scope
                  value: capacity
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: sql
        - tag: target
          value: azure
      macros:
        - macro: '{$AZURE.APP.ID}'
          description: 'The App ID of Microsoft Azure.'
          config:
            type: TEXT
            priority: '3'
            label: 'Azure App ID'
            required: 'YES'
        - macro: '{$AZURE.DATA.TIMEOUT}'
          value: 15s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '10'
            section_name: Other
            label: 'API timeout'
            description: 'API response timeout, in seconds.'
        - macro: '{$AZURE.PASSWORD}'
          type: SECRET_TEXT
          description: 'Microsoft Azure password.'
          config:
            type: TEXT
            priority: '4'
            label: 'Azure password'
            required: 'YES'
        - macro: '{$AZURE.PROXY}'
          description: 'Sets the HTTP proxy value. If this macro is empty, then no proxy is used.'
          config:
            type: TEXT
            priority: '11'
            section_name: Other
            label: 'HTTP proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AZURE.RESOURCE.ID}'
          description: 'Microsoft Azure SQL managed instance ID.'
          config:
            type: TEXT
            priority: '5'
            label: 'Azure SQL managed instance ID'
            required: 'YES'
        - macro: '{$AZURE.SQL.INST.CPU.CRIT}'
          value: '90'
          description: 'CPU utilization critical threshold, expressed in %.'
          config:
            type: TEXT
            priority: '7'
            section_name: Thresholds
            label: 'CPU utilization critical threshold'
            description: 'CPU utilization critical threshold, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.SQL.INST.CPU.WARN}'
          value: '80'
          description: 'CPU utilization warning threshold, expressed in %.'
          config:
            type: TEXT
            priority: '6'
            section_name: Thresholds
            label: 'CPU utilization warning threshold'
            description: 'CPU utilization warning threshold, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.SQL.INST.SPACE.CRIT}'
          value: '90'
          description: 'Storage space critical threshold, expressed in %.'
          config:
            type: TEXT
            priority: '9'
            section_name: Thresholds
            label: 'Storage space critical threshold'
            description: 'Storage space critical threshold, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.SQL.INST.SPACE.WARN}'
          value: '80'
          description: 'Storage space warning threshold, expressed in %.'
          config:
            type: TEXT
            priority: '8'
            section_name: Thresholds
            label: 'Storage space warning threshold'
            description: 'Storage space warning threshold, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.SUBSCRIPTION.ID}'
          description: 'Microsoft Azure subscription ID.'
          config:
            type: TEXT
            priority: '1'
            label: 'Azure subscription ID'
            required: 'YES'
        - macro: '{$AZURE.TENANT.ID}'
          description: 'Microsoft Azure tenant ID.'
          config:
            type: TEXT
            priority: '2'
            label: 'Azure tenant ID'
            required: 'YES'
      dashboards:
        - uuid: 28e6b463ca7b429ca356cb61b5394841
          name: 'Azure SQL managed instance'
          pages:
            - name: Overview
              widgets:
                - type: item
                  name: 'Availability state'
                  width: '18'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure SQL Managed Instance by HTTP'
                        key: azure.sql_inst.availability.state
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: value_size
                      value: '50'
                - type: gauge
                  name: 'Average CPU utilization'
                  'y': '2'
                  width: '18'
                  height: '4'
                  fields:
                    - type: INTEGER
                      name: angle
                      value: '270'
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: STRING
                      name: empty_color
                      value: 0EC9AC
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure SQL Managed Instance by HTTP'
                        key: azure.sql_inst.cpu
                    - type: INTEGER
                      name: show.0
                      value: '3'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: INTEGER
                      name: show.2
                      value: '5'
                    - type: STRING
                      name: value_arc_color
                      value: ED1248
                - type: gauge
                  name: 'Storage space utilization'
                  'y': '6'
                  width: '18'
                  height: '4'
                  fields:
                    - type: INTEGER
                      name: angle
                      value: '270'
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: STRING
                      name: empty_color
                      value: 0EC9AC
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure SQL Managed Instance by HTTP'
                        key: azure.sql_inst.storage.utilization
                    - type: INTEGER
                      name: show.0
                      value: '3'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: INTEGER
                      name: show.2
                      value: '5'
                    - type: STRING
                      name: value_arc_color
                      value: ED1248
                - type: svggraph
                  name: 'IO bytes read/write'
                  'y': '10'
                  width: '72'
                  height: '4'
                  fields:
                    - type: STRING
                      name: ds.0.color.0
                      value: 524BBC
                    - type: INTEGER
                      name: ds.0.dataset_type
                      value: '0'
                    - type: INTEGER
                      name: ds.0.fill
                      value: '0'
                    - type: ITEM
                      name: ds.0.itemids.0
                      value:
                        host: 'Azure SQL Managed Instance by HTTP'
                        key: azure.sql_inst.bytes.read
                    - type: INTEGER
                      name: ds.0.missingdatafunc
                      value: '3'
                    - type: INTEGER
                      name: ds.0.width
                      value: '2'
                    - type: STRING
                      name: ds.1.color.0
                      value: ED1248
                    - type: INTEGER
                      name: ds.1.dataset_type
                      value: '0'
                    - type: INTEGER
                      name: ds.1.fill
                      value: '0'
                    - type: ITEM
                      name: ds.1.itemids.0
                      value:
                        host: 'Azure SQL Managed Instance by HTTP'
                        key: azure.sql_inst.bytes.write
                    - type: INTEGER
                      name: ds.1.missingdatafunc
                      value: '3'
                    - type: INTEGER
                      name: ds.1.width
                      value: '2'
                    - type: INTEGER
                      name: legend_lines
                      value: '2'
                    - type: INTEGER
                      name: legend_statistic
                      value: '1'
                    - type: STRING
                      name: reference
                      value: FDADE
                - type: item
                  name: 'Instance state'
                  x: '18'
                  width: '18'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure SQL Managed Instance by HTTP'
                        key: azure.sql_inst.state
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: value_size
                      value: '50'
                - type: svggraph
                  name: 'Average CPU utilization'
                  x: '18'
                  'y': '2'
                  width: '54'
                  height: '4'
                  fields:
                    - type: STRING
                      name: ds.0.color.0
                      value: 0EC9AC
                    - type: INTEGER
                      name: ds.0.dataset_type
                      value: '0'
                    - type: INTEGER
                      name: ds.0.fill
                      value: '0'
                    - type: ITEM
                      name: ds.0.itemids.0
                      value:
                        host: 'Azure SQL Managed Instance by HTTP'
                        key: azure.sql_inst.cpu
                    - type: INTEGER
                      name: ds.0.missingdatafunc
                      value: '3'
                    - type: INTEGER
                      name: ds.0.width
                      value: '2'
                    - type: STRING
                      name: lefty_max
                      value: '100'
                    - type: STRING
                      name: lefty_min
                      value: '0'
                    - type: INTEGER
                      name: legend_statistic
                      value: '1'
                    - type: STRING
                      name: reference
                      value: FBADE
                - type: svggraph
                  name: 'Storage space utilization'
                  x: '18'
                  'y': '6'
                  width: '54'
                  height: '4'
                  fields:
                    - type: STRING
                      name: ds.0.color.0
                      value: 0EC9AC
                    - type: INTEGER
                      name: ds.0.dataset_type
                      value: '0'
                    - type: INTEGER
                      name: ds.0.fill
                      value: '0'
                    - type: ITEM
                      name: ds.0.itemids.0
                      value:
                        host: 'Azure SQL Managed Instance by HTTP'
                        key: azure.sql_inst.storage.utilization
                    - type: INTEGER
                      name: ds.0.missingdatafunc
                      value: '3'
                    - type: INTEGER
                      name: ds.0.width
                      value: '2'
                    - type: INTEGER
                      name: ds.1.axisy
                      value: '1'
                    - type: STRING
                      name: ds.1.color.0
                      value: ED1248
                    - type: INTEGER
                      name: ds.1.dataset_type
                      value: '0'
                    - type: INTEGER
                      name: ds.1.fill
                      value: '0'
                    - type: ITEM
                      name: ds.1.itemids.0
                      value:
                        host: 'Azure SQL Managed Instance by HTTP'
                        key: azure.sql_inst.storage.used
                    - type: INTEGER
                      name: ds.1.missingdatafunc
                      value: '3'
                    - type: INTEGER
                      name: ds.1.width
                      value: '2'
                    - type: STRING
                      name: lefty_max
                      value: '100'
                    - type: STRING
                      name: lefty_min
                      value: '0'
                    - type: INTEGER
                      name: legend_lines
                      value: '2'
                    - type: INTEGER
                      name: legend_statistic
                      value: '1'
                    - type: STRING
                      name: reference
                      value: FDABE
                - type: item
                  name: 'Instance provisioning state'
                  x: '36'
                  width: '18'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure SQL Managed Instance by HTTP'
                        key: azure.sql_inst.provision
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: value_size
                      value: '50'
                - type: item
                  name: 'IO request count'
                  x: '54'
                  width: '18'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure SQL Managed Instance by HTTP'
                        key: azure.sql_inst.requests
                    - type: INTEGER
                      name: show.0
                      value: '2'
                    - type: INTEGER
                      name: value_size
                      value: '50'
      valuemaps:
        - uuid: 9bb00a69069d4c22a0b75b745da0de73
          name: 'Azure resource health state'
          mappings:
            - value: '0'
              newvalue: Available
            - value: '1'
              newvalue: Degraded
            - value: '2'
              newvalue: Unavailable
            - value: '3'
              newvalue: Unknown
        - uuid: aae2eec109b649d38e80684cdeb9458c
          name: 'Azure SQL instance provisioning state'
          mappings:
            - value: '0'
              newvalue: Unknown
            - value: '1'
              newvalue: Accepted
            - value: '2'
              newvalue: Canceled
            - value: '3'
              newvalue: Created
            - value: '4'
              newvalue: Creating
            - value: '5'
              newvalue: Deleted
            - value: '6'
              newvalue: Deleting
            - value: '7'
              newvalue: Failed
            - value: '8'
              newvalue: NotSpecified
            - value: '9'
              newvalue: Registering
            - value: '10'
              newvalue: Running
            - value: '11'
              newvalue: Succeeded
            - value: '12'
              newvalue: TimedOut
            - value: '13'
              newvalue: Unrecognized
            - value: '14'
              newvalue: Updating
    - uuid: 820fa4a1565c43e4aac07a691a5bface
      template: 'Azure Virtual Machine by HTTP'
      name: 'Azure Virtual Machine by HTTP'
      description: |
        This template is designed to monitor Microsoft Azure virtual machines (VMs) by HTTP.
        It works without any external scripts and uses the script item.
        
        Setup:
          1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
            `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
            See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
          2. Link the template to a host.
          3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
        
        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 is designed to monitor Microsoft Azure virtual machines (VMs) by HTTP.
        It works without any external scripts and uses the script item.
        
        ## Setup
        
        1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
        
              `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
        
        > See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
        
        2. Link the template to a host.
        3. Configure the macros: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure virtual machine ID`.
      vendor:
        name: Zabbix
        version: 7.4-1
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 86f996df859a445994ed671feab6012f
          name: 'VM availability metric'
          type: DEPENDENT
          key: azure.vm.availability
          value_type: FLOAT
          description: 'Measure of availability of virtual machine over time.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.VmAvailabilityMetric.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: health
        - uuid: c299999d69904340acd44fead6c7672c
          name: 'Availability status detailed'
          type: DEPENDENT
          key: azure.vm.availability.details
          value_type: CHAR
          description: 'The summary description of availability status.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.summary
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: health
        - uuid: 25e2af44bfbf4e9083ce493d85232088
          name: 'Availability state'
          type: DEPENDENT
          key: azure.vm.availability.state
          description: |
            The availability status of the resource.
            0 - Available - no events detected that affect the health of the resource.
            1 - Degraded  - your resource detected a loss in performance, although it's still available for use.
            2 - Unavailable - the service detected an ongoing platform or non-platform event that affects the health of the resource.
            3 - Unknown - Resource Health hasn't received information about the resource for more than 10 minutes.
          valuemap:
            name: 'Azure resource health state'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.availabilityState
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: STR_REPLACE
              parameters:
                - Available
                - '0'
            - type: STR_REPLACE
              parameters:
                - Degraded
                - '1'
            - type: STR_REPLACE
              parameters:
                - Unavailable
                - '2'
            - type: STR_REPLACE
              parameters:
                - Unknown
                - '3'
            - type: IN_RANGE
              parameters:
                - '0'
                - '3'
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: health
          triggers:
            - uuid: c0170d8a09ae460da923fe773b2b0bd0
              expression: 'last(/Azure Virtual Machine by HTTP/azure.vm.availability.state)=1'
              name: 'Azure VM: Virtual machine is degraded'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The resource is in a degraded state.'
              tags:
                - tag: scope
                  value: availability
            - uuid: e1b85765b83445ebbf15f02d782b9858
              expression: 'last(/Azure Virtual Machine by HTTP/azure.vm.availability.state)=3'
              name: 'Azure VM: Virtual machine is in unknown state'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The resource state is unknown.'
              tags:
                - tag: scope
                  value: availability
            - uuid: b3d764ff735e44f8806cc4d29090719e
              expression: 'last(/Azure Virtual Machine by HTTP/azure.vm.availability.state)=2'
              name: 'Azure VM: Virtual machine is unavailable'
              opdata: '{ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The resource state is unavailable.'
              tags:
                - tag: scope
                  value: availability
        - uuid: a93308573303437487d151de340fcaed
          name: 'VM cached bandwidth consumed'
          type: DEPENDENT
          key: azure.vm.cached.bandwidth.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of the cached disk bandwidth consumed by the VM.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.VMCachedBandwidthConsumedPercentage.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 989dec26d97d44b6bd4a84fdbd37dec5
          name: 'VM cached IOPS consumed'
          type: DEPENDENT
          key: azure.vm.cached.iops.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of the cached disk IOPS consumed by the VM.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.VMCachedIOPSConsumedPercentage.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: fb0641ca8f104cf1bebdced63cd6af16
          name: 'CPU credits consumed'
          type: DEPENDENT
          key: azure.vm.cpu.credits.consumed
          value_type: FLOAT
          description: 'Total number of credits consumed by the virtual machine. Only available on B-series burstable VMs.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.CPUCreditsConsumed.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: cpu
        - uuid: 963752cbaba046cab1f05b0cbcff3137
          name: 'CPU credits remaining'
          type: DEPENDENT
          key: azure.vm.cpu.credits.remaining
          value_type: FLOAT
          description: 'Total number of credits available to burst. Available only on B-series burstable VMs.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.CPUCreditsRemaining.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: cpu
        - uuid: 492edacf92544a95a5aa7b034efa7931
          name: 'CPU utilization'
          type: DEPENDENT
          key: azure.vm.cpu.utilization
          value_type: FLOAT
          units: '%'
          description: 'Percentage of allocated compute units that are currently in use by virtual machine.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.PercentageCPU.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: cpu
          triggers:
            - uuid: 9e6d9394570641418b4291befb1e38e5
              expression: 'min(/Azure Virtual Machine by HTTP/azure.vm.cpu.utilization,5m)>{$AZURE.VM.CPU.UTIL.CRIT}'
              name: 'Azure VM: High CPU utilization'
              event_name: 'Azure VM: CPU utilization is high (over {$AZURE.VM.CPU.UTIL.CRIT}% for last 5m)'
              opdata: '{ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The CPU utilization is too high. The system might be slow to respond.'
              tags:
                - tag: scope
                  value: performance
        - uuid: 68c730e4904f402cb12fb71b45fede02
          name: 'Data disk used burst BPS credits'
          type: DEPENDENT
          key: azure.vm.data.disk.bandwidth.burst.used
          value_type: FLOAT
          units: '%'
          description: 'Percentage of the data disk burst bandwidth credits used so far.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskUsedBurstBPSCreditsPercentage.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 47cda13c203e4f1e9918eb73fd8afa20
          name: 'Data disk bandwidth consumed'
          type: DEPENDENT
          key: azure.vm.data.disk.bandwidth.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of the data disk bandwidth consumed per minute.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskBandwidthConsumedPercentage.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: d0fb23206d564e1da746bff3369056c1
          name: 'Data disk max burst bandwidth'
          type: DEPENDENT
          key: azure.vm.data.disk.bandwidth.max
          value_type: FLOAT
          units: Bps
          description: 'Maximum byte-per-second throughput that the data disk can achieve with bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskMaxBurstBandwidth.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: c61ad4af97c243cca75bbece40eea795
          name: 'Data disk target bandwidth'
          type: DEPENDENT
          key: azure.vm.data.disk.bandwidth.target
          value_type: FLOAT
          units: Bps
          description: 'Baseline byte-per-second throughput that the data disk can achieve without bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskTargetBandwidth.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 731a82833bdd42c59c453adf8625e3b4
          name: 'Data disk used burst IO credits'
          type: DEPENDENT
          key: azure.vm.data.disk.iops.burst.used
          value_type: FLOAT
          units: '%'
          description: 'Percentage of the data disk burst I/O credits used so far.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskUsedBurstIOCreditsPercentage.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 3121980d3319431691ed9e98d176430b
          name: 'Data disk IOPS consumed'
          type: DEPENDENT
          key: azure.vm.data.disk.iops.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of the data disk input/output (I/O) consumed per minute.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskIOPSConsumedPercentage.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 6afcbb02c53243faa341670f155678e4
          name: 'Data disk max burst IOPS'
          type: DEPENDENT
          key: azure.vm.data.disk.iops.max
          value_type: FLOAT
          units: '!iops'
          description: 'Maximum IOPS that the data disk can achieve with bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskMaxBurstIOPS.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 9370988456e74b889700ea5798d17092
          name: 'Data disk target IOPS'
          type: DEPENDENT
          key: azure.vm.data.disk.iops.target
          value_type: FLOAT
          units: '!iops'
          description: 'Baseline IOPS that the data disk can achieve without bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskTargetIOPS.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: b81f304bbc2a42df9b0550ecdc1ec6b7
          name: 'Data disk queue depth'
          type: DEPENDENT
          key: azure.vm.data.disk.queue.depth
          value_type: FLOAT
          description: 'The number of outstanding IO requests that are waiting to be performed on a disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskQueueDepth.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 021d92f3075544319191d6f85a701222
          name: 'Data disk read rate'
          type: DEPENDENT
          key: azure.vm.data.disk.read.bps
          value_type: FLOAT
          units: Bps
          description: 'Bytes per second read from a single disk during the monitoring period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskReadBytessec.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: cc31283ab96548b7bdcc88e89dfae53c
          name: 'Data disk IOPS read'
          type: DEPENDENT
          key: azure.vm.data.disk.read.ops
          value_type: FLOAT
          units: '!iops'
          description: 'Read IOPS from a single disk during the monitoring period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskReadOperationsSec.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: b8712f8fd60a43f6b099d9eafed19945
          name: 'Data disk write rate'
          type: DEPENDENT
          key: azure.vm.data.disk.write.bps
          value_type: FLOAT
          units: Bps
          description: 'Bytes per second written to a single disk during the monitoring period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskWriteBytessec.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 87794f5a502b4e2db91f820483e38fb3
          name: 'Data disk IOPS write'
          type: DEPENDENT
          key: azure.vm.data.disk.write.ops
          value_type: FLOAT
          units: '!iops'
          description: 'Write IOPS from a single disk during the monitoring period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskWriteOperationsSec.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: e253c2a908944be1a033fc3df550d979
          name: 'Get errors'
          type: DEPENDENT
          key: azure.vm.data.errors
          value_type: TEXT
          description: 'A list of errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.errors
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: error
          triggers:
            - uuid: 87236c99652643ba800601a461d66d94
              expression: 'length(last(/Azure Virtual Machine by HTTP/azure.vm.data.errors))>0'
              name: 'Azure VM: There are errors in requests to API'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              tags:
                - tag: scope
                  value: availability
        - uuid: cff54514d795495da8bc1152e02631aa
          name: 'Get data'
          type: SCRIPT
          key: azure.vm.data.get
          history: '0'
          value_type: TEXT
          params: |
            var Azure = {
            	params: {},
            	token: null,
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id', 'resource_id'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            
            		Azure.params = params;
            	},
            
            	login: function () {
            		var response, login = new HttpRequest();
            
            		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
            			login.setProxy(Azure.params.proxy);
            		}
            
            		login.addHeader('Content-Type: application/x-www-form-urlencoded');
            		response = login.post(
            			'https://login.microsoftonline.com/' + encodeURIComponent(Azure.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(Azure.params.app_id) + '&client_secret=' + encodeURIComponent(Azure.params.password)
            		);
            
            		if (login.getStatus() !== 200) {
            			throw 'Login failed with status code ' + login.getStatus() + ': ' + response;
            		}
            
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse login session response.';
            		}
            
            		if (!response.hasOwnProperty('access_token')) {
            			throw 'Authentication response does not contain access token.';
            		}
            
            		Azure.token = response['access_token'];
            	},
            
            	request: function (url) {
            		var response, request = new HttpRequest();
            
            		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
            			request.setProxy(Azure.params.proxy);
            		}
            
            		if (!Azure.token) {
            			throw 'Request does not contain access token.';
            		}
            
            		request.addHeader('Content-Type: application/json');
            		request.addHeader('Authorization: Bearer ' + Azure.token);
            		Zabbix.log(4, '[ AzureVM ] request url: ' + url);
            
            		response = request.get(url);
            
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	},
            
            	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;
            	},
            
            	getMetricsData: function () {
            		var data = {},
            			metric_endpoints = {
            				'main_and_premium_metrics': '/providers/Microsoft.Insights/metrics?metricnames=' + encodeURIComponent('Percentage CPU,CPU Credits Remaining,CPU Credits Consumed,VmAvailabilityMetric,Available Memory Bytes,Network In Total,Network Out Total,Inbound Flows,Outbound Flows,Inbound Flows Maximum Creation Rate,Outbound Flows Maximum Creation Rate,Premium Data Disk Cache Read Hit,Premium Data Disk Cache Read Miss,Premium OS Disk Cache Read Hit,Premium OS Disk Cache Read Miss,VM Cached Bandwidth Consumed Percentage,VM Cached IOPS Consumed Percentage,VM Uncached Bandwidth Consumed Percentage,VM Uncached IOPS Consumed Percentage') + '&api-version=2024-02-01&timespan=PT1M',
            				'disks_metrics': '/providers/Microsoft.Insights/metrics?metricnames=' + encodeURIComponent('Disk Read Bytes,Disk Write Bytes,Disk Read Operations/Sec,Disk Write Operations/Sec,Data Disk Latency,Data Disk Read Bytes/sec,Data Disk Write Bytes/sec,Data Disk Read Operations/Sec,Data Disk Write Operations/Sec,Data Disk Queue Depth,Data Disk Bandwidth Consumed Percentage,Data Disk IOPS Consumed Percentage,Data Disk Target Bandwidth,Data Disk Target IOPS,Data Disk Max Burst Bandwidth,Data Disk Max Burst IOPS,Data Disk Used Burst BPS Credits Percentage,Data Disk Used Burst IO Credits Percentage') + '&api-version=2024-02-01&timespan=PT1M',
            				'os_disk_metrics': '/providers/Microsoft.Insights/metrics?metricnames=' + encodeURIComponent('OS Disk Latency,OS Disk Read Bytes/sec,OS Disk Write Bytes/sec,OS Disk Read Operations/Sec,OS Disk Write Operations/Sec,OS Disk Queue Depth,OS Disk Bandwidth Consumed Percentage,OS Disk IOPS Consumed Percentage,OS Disk Target Bandwidth,OS Disk Target IOPS,OS Disk Max Burst Bandwidth,OS Disk Max Burst IOPS,OS Disk Used Burst BPS Credits Percentage,OS Disk Used Burst IO Credits Percentage,Temp Disk Latency,Temp Disk Read Bytes/sec,Temp Disk Write Bytes/sec,Temp Disk Read Operations/Sec,Temp Disk Write Operations/Sec,Temp Disk Queue Depth') + '&api-version=2024-02-01&timespan=PT1M'
            			};
            		data.metrics = {};
            
            		Object.keys(metric_endpoints).forEach(function (field) {
            			metrics = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + metric_endpoints[field]), 'value');
            			for (k in metrics) {
            				key = Azure.getField(metrics[k], 'name.value').replace(/(\s|\/)+/g, '');
            				if (metrics[k].timeseries.length === 0) {
            					metrics[k].timeseries.push({ 'data': ['nodata'] })
            				}
            				data.metrics[key] = Azure.getField(metrics[k], 'timeseries.0.data.0');
            			}
            		});
            
            		data.health = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + '/providers/Microsoft.ResourceHealth/availabilityStatuses?api-version=2020-05-01'), 'value.0.properties');
            
            		return data
            	}
            };
            
            try {
            	Azure.setParams(JSON.parse(value));
            	Azure.login();
            	return JSON.stringify(Azure.getMetricsData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AzureVM ] ERROR: ' + error);
            	return JSON.stringify({ 'error': error });
            }
          description: 'The result of API requests is expressed in the JSON.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: resource_id
              value: '{$AZURE.RESOURCE.ID}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: 903b8b2724924d5e8627253d851f09e5
          name: 'Data disk latency'
          type: DEPENDENT
          key: azure.vm.disk.latency
          value_type: FLOAT
          units: s
          description: 'Average time to complete each IO during the monitoring period for Data Disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskLatency.average
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '0.001'
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 1dc9f8d45b6f48a38f701f089cbcb279
          name: 'Disk read'
          type: DEPENDENT
          key: azure.vm.disk.read.bytes
          value_type: FLOAT
          units: B
          description: 'Bytes read from the disk during the monitoring period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DiskReadBytes.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: cd3240d31a4f42a89b5c9817ea288b5a
          name: 'Disk IOPS read'
          type: DEPENDENT
          key: azure.vm.disk.read.ops
          value_type: FLOAT
          units: '!iops'
          description: 'The count of read operations from the disk per second.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DiskReadOperationsSec.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: b5e2070bde1444ea809ba4e0a29b05d9
          name: 'Disk write'
          type: DEPENDENT
          key: azure.vm.disk.write.bytes
          value_type: FLOAT
          units: B
          description: 'Bytes written to the disk during the monitoring period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DiskWriteBytes.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 0d93d1b510614c1f83418bd481f1e7cb
          name: 'Disk IOPS write'
          type: DEPENDENT
          key: azure.vm.disk.write.ops
          value_type: FLOAT
          units: '!iops'
          description: 'The count of write operations to the disk per second.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DiskWriteOperationsSec.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 3a30a59aabd54c8b8feb1f4a8ba06db5
          name: 'Inbound flows'
          type: DEPENDENT
          key: azure.vm.flows.inbound
          value_type: FLOAT
          description: 'The number of current flows in the inbound direction (the traffic going into the VM).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.InboundFlows.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: network
        - uuid: 3964ffbb7ea949f69863edcf91f5c555
          name: 'Inbound flows max creation rate'
          type: DEPENDENT
          key: azure.vm.flows.inbound.max
          value_type: FLOAT
          description: 'Maximum creation rate of the inbound flows (the traffic going into the VM).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.InboundFlowsMaximumCreationRate.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: network
        - uuid: 2084cb1d010a4ab494c0826c458d922a
          name: 'Outbound flows'
          type: DEPENDENT
          key: azure.vm.flows.outbound
          value_type: FLOAT
          description: 'The number of current flows in the outbound direction (the traffic going out of the VM).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OutboundFlows.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: network
        - uuid: eac3e6b53d394e3289fc03bf5772799c
          name: 'Outbound flows max creation rate'
          type: DEPENDENT
          key: azure.vm.flows.outbound.max
          value_type: FLOAT
          description: 'Maximum creation rate of the outbound flows (the traffic going out of the VM).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OutboundFlowsMaximumCreationRate.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: network
        - uuid: 0a354c9b104b468d9749adfd28d1373e
          name: 'Available memory'
          type: DEPENDENT
          key: azure.vm.memory.available
          value_type: FLOAT
          units: B
          description: 'Amount of physical memory, in bytes, immediately available for the allocation to a process or for a system use in the virtual machine.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.AvailableMemoryBytes.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: memory
        - uuid: 411c5f6fcb374c4c90e2951a546c0c08
          name: 'Network in total'
          type: DEPENDENT
          key: azure.vm.network.in.total
          value_type: FLOAT
          units: B
          description: 'The number of bytes received by the VM via all network interfaces (incoming traffic).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.NetworkInTotal.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: network
        - uuid: ee2ef1d1e2844ae8be2a5f04c86631ba
          name: 'Network out total'
          type: DEPENDENT
          key: azure.vm.network.out.total
          value_type: FLOAT
          units: B
          description: 'The number of bytes sent by the VM via all network interfaces (outgoing traffic).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.NetworkOutTotal.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: network
        - uuid: 9d42609950864c899a0d63b94f1d2235
          name: 'OS disk used burst BPS credits'
          type: DEPENDENT
          key: azure.vm.os.disk.bandwidth.burst.used
          value_type: FLOAT
          units: '%'
          description: 'Percentage of the OS disk burst bandwidth credits used so far.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskUsedBurstBPSCreditsPercentage.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 24c58e473c5c4b8388a0e78ae38378fc
          name: 'OS disk bandwidth consumed'
          type: DEPENDENT
          key: azure.vm.os.disk.bandwidth.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of the operating system disk bandwidth consumed per minute.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskBandwidthConsumedPercentage.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 7d0ca132bc264ac08e3c55809bdc40d1
          name: 'OS disk max burst bandwidth'
          type: DEPENDENT
          key: azure.vm.os.disk.bandwidth.max
          value_type: FLOAT
          units: Bps
          description: 'Maximum byte-per-second throughput that the OS disk can achieve with bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskMaxBurstBandwidth.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 5cc422b7da3145fa885a88bb6165e3b9
          name: 'OS disk target bandwidth'
          type: DEPENDENT
          key: azure.vm.os.disk.bandwidth.target
          value_type: FLOAT
          units: Bps
          description: 'Baseline byte-per-second throughput that the OS disk can achieve without bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskTargetBandwidth.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: c08f45df2e594e1fab01ba63df7da05b
          name: 'OS disk used burst IO credits'
          type: DEPENDENT
          key: azure.vm.os.disk.iops.burst.used
          value_type: FLOAT
          units: '%'
          description: 'Percentage of the OS disk burst I/O credits used so far.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskUsedBurstIOCreditsPercentage.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 33a7fff9758046e3be07dad6c0a710ca
          name: 'OS disk IOPS consumed'
          type: DEPENDENT
          key: azure.vm.os.disk.iops.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of the operating system disk I/Os consumed per minute.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskIOPSConsumedPercentage.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 8374282688dc4fabb770c07eb335c666
          name: 'OS disk max burst IOPS'
          type: DEPENDENT
          key: azure.vm.os.disk.iops.max
          value_type: FLOAT
          units: '!iops'
          description: 'Maximum IOPS that the OS disk can achieve with bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskMaxBurstIOPS.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 556941b1df5d470f8de628230b085623
          name: 'OS disk target IOPS'
          type: DEPENDENT
          key: azure.vm.os.disk.iops.target
          value_type: FLOAT
          units: '!iops'
          description: 'Baseline IOPS that the OS disk can achieve without bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskTargetIOPS.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 3932b607cff14ee0a891c96587438807
          name: 'OS disk latency'
          type: DEPENDENT
          key: azure.vm.os.disk.latency
          value_type: FLOAT
          units: s
          description: 'Average time to complete each IO during the monitoring period for OS Disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskLatency.average
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '0.001'
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: ca8fe9d0ea58482c9bb8b83a716362a2
          name: 'OS disk queue depth'
          type: DEPENDENT
          key: azure.vm.os.disk.queue.depth
          value_type: FLOAT
          description: 'The OS disk queue depth (or queue length).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskQueueDepth.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 30265aac759d45769769eae081f570ac
          name: 'OS disk read rate'
          type: DEPENDENT
          key: azure.vm.os.disk.read.bps
          value_type: FLOAT
          units: Bps
          description: 'Bytes/sec read from a single disk during the monitoring period - for an OS disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskReadBytessec.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: f11fcbbd63234993a9c301dc8bac3e80
          name: 'OS disk IOPS read'
          type: DEPENDENT
          key: azure.vm.os.disk.read.ops
          value_type: FLOAT
          units: '!iops'
          description: 'Read IOPS from a single disk during the monitoring period - for an OS disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskReadOperationsSec.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 7645519a786b42908f1ec693128899c2
          name: 'OS disk write rate'
          type: DEPENDENT
          key: azure.vm.os.disk.write.bps
          value_type: FLOAT
          units: Bps
          description: 'Bytes/sec written to a single disk during the monitoring period - for an OS disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskWriteBytessec.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 1e9392bc0c934e7d93f743c86e36e23e
          name: 'OS disk IOPS write'
          type: DEPENDENT
          key: azure.vm.os.disk.write.ops
          value_type: FLOAT
          units: '!iops'
          description: 'Write IOPS from a single disk during the monitoring period - for an OS disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskWriteOperationsSec.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: d6fcff826cfa486d945f33708be2f630
          name: 'Premium data disk cache read hit in %'
          type: DEPENDENT
          key: azure.vm.premium.data.disk.cache.read.hit
          value_type: FLOAT
          units: '%'
          description: 'Percentage of premium data disk cache read hit.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.PremiumDataDiskCacheReadHit.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 288853ee5d08442fa43f8df1dfcc7823
          name: 'Premium data disk cache read miss in %'
          type: DEPENDENT
          key: azure.vm.premium.data.disk.cache.read.miss
          value_type: FLOAT
          units: '%'
          description: 'Percentage of premium data disk cache read miss.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.PremiumDataDiskCacheReadMiss.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 66b629ae3d7e4abeaf0282414c91876f
          name: 'Premium OS disk cache read hit in %'
          type: DEPENDENT
          key: azure.vm.premium.os.disk.cache.read.hit
          value_type: FLOAT
          units: '%'
          description: 'Percentage of premium OS disk cache read hit.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.PremiumOSDiskCacheReadHit.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 3927f34d5d0649d7ac29703f64054dbf
          name: 'Premium OS disk cache read miss in %'
          type: DEPENDENT
          key: azure.vm.premium.os.disk.cache.read.miss
          value_type: FLOAT
          units: '%'
          description: 'Percentage of premium OS disk cache read miss.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.PremiumOSDiskCacheReadMiss.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 7d2ca29fce9a4c9ba60279f07de73089
          name: 'Temp disk latency'
          type: DEPENDENT
          key: azure.vm.temp.disk.latency
          value_type: FLOAT
          units: s
          description: 'Average time to complete each IO during the monitoring period for temp disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.TempDiskLatency.average
              error_handler: DISCARD_VALUE
            - type: MULTIPLIER
              parameters:
                - '0.001'
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 67638ce2228e4f5d9f4aae44d9c4a47f
          name: 'Temp disk queue depth'
          type: DEPENDENT
          key: azure.vm.temp.disk.queue.depth
          value_type: FLOAT
          description: 'Temp Disk queue depth (or queue length).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.TempDiskQueueDepth.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: f07200debf2d49dba3c0a63102258c6c
          name: 'Temp disk read rate'
          type: DEPENDENT
          key: azure.vm.temp.disk.read.bps
          value_type: FLOAT
          units: Bps
          description: 'Bytes/Sec read from a single disk during the monitoring period for temp disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.TempDiskReadBytessec.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 4b7b661391ac46179913a0e1bf012e76
          name: 'Temp disk IOPS read'
          type: DEPENDENT
          key: azure.vm.temp.disk.read.ops
          value_type: FLOAT
          units: '!iops'
          description: 'Read IOPS from a single disk during the monitoring period for temp disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.TempDiskReadOperationsSec.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: dc3601128000423b8b46ef1046562105
          name: 'Temp disk write rate'
          type: DEPENDENT
          key: azure.vm.temp.disk.write.bps
          value_type: FLOAT
          units: Bps
          description: 'Bytes/Sec written to a single disk during the monitoring period for temp disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.TempDiskWriteBytessec.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: d03cdea05ae549ffb63c6db4a7e40c13
          name: 'Temp disk IOPS write'
          type: DEPENDENT
          key: azure.vm.temp.disk.write.ops
          value_type: FLOAT
          units: '!iops'
          description: 'Bytes/Sec written to a single disk during the monitoring period for temp disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.TempDiskWriteOperationsSec.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: d6e85395e34b4288988a5287d287f182
          name: 'VM uncached bandwidth consumed'
          type: DEPENDENT
          key: azure.vm.uncached.bandwidth.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of the uncached disk bandwidth consumed by the VM.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.VMUncachedBandwidthConsumedPercentage.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 124203560922429bb32b76c45f24b2b9
          name: 'VM uncached IOPS consumed'
          type: DEPENDENT
          key: azure.vm.uncached.iops.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of the uncached disk IOPS consumed by the VM.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.VMUncachedIOPSConsumedPercentage.average
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.vm.data.get
          tags:
            - tag: component
              value: storage
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: virtualization
        - tag: target
          value: azure
      macros:
        - macro: '{$AZURE.APP.ID}'
          description: 'The App ID of Microsoft Azure.'
          config:
            type: TEXT
            priority: '3'
            label: 'Azure App ID'
            required: 'YES'
        - macro: '{$AZURE.DATA.TIMEOUT}'
          value: 15s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '7'
            section_name: Other
            label: 'API timeout'
            description: 'API response timeout, in seconds.'
        - macro: '{$AZURE.PASSWORD}'
          type: SECRET_TEXT
          description: 'Microsoft Azure password.'
          config:
            type: TEXT
            priority: '4'
            label: 'Azure password'
            required: 'YES'
        - macro: '{$AZURE.PROXY}'
          description: 'Sets the 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: '{$AZURE.RESOURCE.ID}'
          description: 'Microsoft Azure virtual machine ID.'
          config:
            type: TEXT
            priority: '5'
            label: 'Azure virtual machine ID'
            required: 'YES'
        - macro: '{$AZURE.SUBSCRIPTION.ID}'
          description: 'Microsoft Azure subscription ID.'
          config:
            type: TEXT
            priority: '1'
            label: 'Azure subscription ID'
            required: 'YES'
        - macro: '{$AZURE.TENANT.ID}'
          description: 'Microsoft Azure tenant ID.'
          config:
            type: TEXT
            priority: '2'
            label: 'Azure tenant ID'
            required: 'YES'
        - macro: '{$AZURE.VM.CPU.UTIL.CRIT}'
          value: '90'
          description: 'The critical threshold of CPU utilization, expressed in %.'
          config:
            type: TEXT
            priority: '6'
            section_name: Other
            label: 'CPU utilization critical threshold'
            description: 'Critical threshold of CPU utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
      dashboards:
        - uuid: 527e3c432d3842d0968480d8f91a712e
          name: 'Overview Azure Virtual Machine'
          pages:
            - widgets:
                - type: clock
                  name: 'Local time'
                  width: '12'
                  height: '3'
                - type: item
                  name: 'CPU credits consumed'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        key: azure.vm.cpu.credits.consumed
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Network in'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        key: azure.vm.network.in.total
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Disk read rate'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        key: azure.vm.disk.read.bytes
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'OS disk read operations/sec'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        key: azure.vm.os.disk.read.ops
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Inbound flows'
                  'y': '15'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        key: azure.vm.flows.inbound
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Available memory'
                  x: '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        key: azure.vm.memory.available
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'CPU credits remaining'
                  x: '12'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        key: azure.vm.cpu.credits.remaining
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Network out'
                  x: '12'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        key: azure.vm.network.out.total
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Disk write rate'
                  x: '12'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        key: azure.vm.disk.write.bytes
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'OS disk write operations/sec'
                  x: '12'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        key: azure.vm.os.disk.write.ops
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Outbound flows'
                  x: '12'
                  'y': '15'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        key: azure.vm.flows.outbound
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Availability state'
                  x: '24'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        key: azure.vm.availability.state
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: up_color
                      value: FF0000
                - type: graph
                  name: 'Percentage CPU'
                  x: '24'
                  'y': '3'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        name: 'Azure: Percentage CPU'
                    - type: STRING
                      name: reference
                      value: AAAAA
                - type: graph
                  name: 'Network traffic'
                  x: '24'
                  'y': '6'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        name: 'Azure: Network traffic'
                    - type: STRING
                      name: reference
                      value: AAAAB
                - type: graph
                  name: 'Disk read/write bytes'
                  x: '24'
                  'y': '9'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        name: 'Azure: Disk read/write bytes'
                    - type: STRING
                      name: reference
                      value: AAAAC
                - type: graph
                  name: 'OS disk read/write rates'
                  x: '24'
                  'y': '12'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        name: 'Azure: OS disk read/write IOPS'
                    - type: STRING
                      name: reference
                      value: AAAAD
                - type: graph
                  name: Flows
                  x: '24'
                  'y': '15'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        name: 'Azure: Flows'
                    - type: STRING
                      name: reference
                      value: AAAAE
                - type: itemhistory
                  name: 'Availability status detailed'
                  x: '36'
                  width: '36'
                  height: '3'
                  fields:
                    - type: INTEGER
                      name: columns.0.display
                      value: '4'
                    - type: ITEM
                      name: columns.0.itemid
                      value:
                        host: 'Azure Virtual Machine by HTTP'
                        key: azure.vm.availability.details
                    - type: INTEGER
                      name: columns.0.monospace_font
                      value: '1'
                    - type: STRING
                      name: columns.0.name
                      value: 'Azure: Availability status detailed'
                    - type: STRING
                      name: reference
                      value: BAAAA
                    - type: INTEGER
                      name: show_timestamp
                      value: '1'
      valuemaps:
        - uuid: 38c8ce1516704ec2a6f1ea9686db56b9
          name: 'Azure resource health state'
          mappings:
            - value: '0'
              newvalue: Available
            - value: '1'
              newvalue: Degraded
            - value: '2'
              newvalue: Unavailable
            - value: '3'
              newvalue: Unknown
    - uuid: d0fd5d346b1740dda9d3a976371789dd
      template: 'Azure VM Scale Set by HTTP'
      name: 'Azure VM Scale Set by HTTP'
      description: |
        This template is designed to monitor Microsoft Azure virtual machine scale sets by HTTP.
        It works without any external scripts and uses the script item.
        
        Setup:
          1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
            `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
            See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
          2. Link the template to a host.
          3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
        
        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 is designed to monitor Microsoft Azure virtual machine scale sets by HTTP.
        It works without any external scripts and uses the script item.
        
        ## Setup
        
        1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
        
              `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/<subscription_id>`
        
        > See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
        
        2. Link the template to a host.
        3. Configure the macros: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure scale set ID`.
      vendor:
        name: Zabbix
        version: 7.4-1
      groups:
        - name: Templates/Cloud
      items:
        - uuid: eea82baaa0684ba688a69da62bf1eec5
          name: 'VM availability metric'
          type: DEPENDENT
          key: azure.scaleset.availability
          value_type: FLOAT
          description: 'Measure of availability of the virtual machines over time.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.VmAvailabilityMetric.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: health
        - uuid: 21740af2abca461f88a81f07ba297929
          name: 'Availability status detailed'
          type: DEPENDENT
          key: azure.scaleset.availability.details
          value_type: CHAR
          description: 'The summary description of availability status.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.summary
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: health
        - uuid: 65e1ca0b38e04adca069388a4c5e3869
          name: 'Availability state'
          type: DEPENDENT
          key: azure.scaleset.availability.state
          description: |
            The availability status of the resource.
            0 - Available - no events detected that affect the health of the resource.
            1 - Degraded  - your resource detected a loss in performance, although it's still available for use.
            2 - Unavailable - the service detected an ongoing platform or non-platform event that affects the health of the resource.
            3 - Unknown - Resource Health hasn't received information about the resource for more than 10 minutes.
          valuemap:
            name: 'Azure resource health state'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.health.availabilityState
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: STR_REPLACE
              parameters:
                - Available
                - '0'
            - type: STR_REPLACE
              parameters:
                - Degraded
                - '1'
            - type: STR_REPLACE
              parameters:
                - Unavailable
                - '2'
            - type: STR_REPLACE
              parameters:
                - Unknown
                - '3'
            - type: IN_RANGE
              parameters:
                - '0'
                - '3'
              error_handler: CUSTOM_VALUE
              error_handler_params: '3'
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: health
          triggers:
            - uuid: a1aadc807a6d40bd8dd2049c0ead6e38
              expression: 'last(/Azure VM Scale Set by HTTP/azure.scaleset.availability.state)=1'
              name: 'Azure VM Scale: Virtual machine scale set is degraded'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'The resource is in a degraded state.'
              tags:
                - tag: scope
                  value: availability
            - uuid: c09bb8da8bb54c45b6d424a63ec892ae
              expression: 'last(/Azure VM Scale Set by HTTP/azure.scaleset.availability.state)=3'
              name: 'Azure VM Scale: Virtual machine scale set is in unknown state'
              opdata: '{ITEM.LASTVALUE1}'
              priority: WARNING
              description: 'The resource state is unknown.'
              tags:
                - tag: scope
                  value: availability
            - uuid: eff890c95f574ad09af82ad79803e733
              expression: 'last(/Azure VM Scale Set by HTTP/azure.scaleset.availability.state)=2'
              name: 'Azure VM Scale: Virtual machine scale set is unavailable'
              opdata: '{ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The resource state is unavailable.'
              tags:
                - tag: scope
                  value: availability
        - uuid: dd6bac4dda51446e9a16450c61b8e23e
          name: 'CPU credits consumed'
          type: DEPENDENT
          key: azure.scaleset.cpu.credits.consumed
          value_type: FLOAT
          description: 'Total number of credits consumed by the virtual machine. Only available on B-series burstable VMs.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.CPUCreditsConsumed.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: cpu
        - uuid: e05426408c9f448a9f8df40a52b6502a
          name: 'CPU credits remaining'
          type: DEPENDENT
          key: azure.scaleset.cpu.credits.remaining
          value_type: FLOAT
          description: 'Total number of credits available to burst. Only available on B-series burstable VMs.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.CPUCreditsRemaining.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: cpu
        - uuid: 0883913383d54b81b5c67b65dc595ae3
          name: 'CPU utilization'
          type: DEPENDENT
          key: azure.scaleset.cpu.utilization
          value_type: FLOAT
          units: '%'
          description: 'The percentage of allocated compute units that are currently in use by the virtual machine(s).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.PercentageCPU.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: cpu
          triggers:
            - uuid: a3706a6c3349429b89b6915a6b0fb5c1
              expression: 'min(/Azure VM Scale Set by HTTP/azure.scaleset.cpu.utilization,5m)>{$AZURE.SCALESET.CPU.UTIL.CRIT}'
              name: 'Azure VM Scale: High CPU utilization'
              event_name: 'Azure VM Scale: CPU utilization is high (over {$AZURE.SCALESET.CPU.UTIL.CRIT}% for last 5m)'
              opdata: '{ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'The CPU utilization is too high. The system might be slow to respond.'
              tags:
                - tag: scope
                  value: performance
        - uuid: bc342d5b3c42487887df3a82cd65e265
          name: 'Data disk max burst bandwidth'
          type: DEPENDENT
          key: azure.scaleset.data.disk.bandwidth.burst.max
          value_type: FLOAT
          units: Bps
          description: 'Maximum byte-per-second throughput the data disk can achieve with bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskMaxBurstBandwidth.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 1d19657c420b4a0a9e601a4effefa58f
          name: 'Data disk used burst BPS credits'
          type: DEPENDENT
          key: azure.scaleset.data.disk.bandwidth.burst.used
          value_type: FLOAT
          units: '%'
          description: 'Percentage of data disk burst bandwidth credits used so far.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskUsedBurstBPSCreditsPercentage.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 76a0d87846b74a128d63f62da04050ab
          name: 'Data disk bandwidth consumed'
          type: DEPENDENT
          key: azure.scaleset.data.disk.bandwidth.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of data disk bandwidth consumed per minute.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskBandwidthConsumedPercentage.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: dd3994c9e83f48d395e61c91aae2f17d
          name: 'Data disk target bandwidth'
          type: DEPENDENT
          key: azure.scaleset.data.disk.bandwidth.target
          value_type: FLOAT
          units: Bps
          description: 'Baseline byte-per-second throughput the data disk can achieve without bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskTargetBandwidth.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 53ab6e4d0dcd46d48c6ede579ca00366
          name: 'Data disk max burst IOPS'
          type: DEPENDENT
          key: azure.scaleset.data.disk.iops.burst.max
          value_type: FLOAT
          units: '!iops'
          description: 'Maximum IOPS the data disk can achieve with bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskMaxBurstIOPS.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: e4bfd5f8c13d44e69facf507a10db553
          name: 'Data disk used burst IO credits'
          type: DEPENDENT
          key: azure.scaleset.data.disk.iops.burst.used
          value_type: FLOAT
          units: '%'
          description: 'Percentage of data disk burst I/O credits used so far.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskUsedBurstIOCreditsPercentage.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: d7633aaf087741ec8558198dc382df1a
          name: 'Data disk IOPS consumed'
          type: DEPENDENT
          key: azure.scaleset.data.disk.iops.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of data disk I/Os consumed per minute.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskIOPSConsumedPercentage.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 86123a1bff83403a8190fc5f61c4edd7
          name: 'Data disk target IOPS'
          type: DEPENDENT
          key: azure.scaleset.data.disk.iops.target
          value_type: FLOAT
          units: '!iops'
          description: 'Baseline IOPS the data disk can achieve without bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskTargetIOPS.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 72cadbd3a3ae409b8f192217c2ff6cb1
          name: 'Data disk queue depth'
          type: DEPENDENT
          key: azure.scaleset.data.disk.queue.depth
          description: 'Data disk queue depth (or queue length).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskQueueDepth.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: d42c402ec613423287335538136bcd05
          name: 'Data disk read rate'
          type: DEPENDENT
          key: azure.scaleset.data.disk.read.bps
          value_type: FLOAT
          units: Bps
          description: 'Bytes/sec read from a single disk during the monitoring period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskReadBytessec.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 2e265f80dccd4542a0f4b0adf462fec0
          name: 'Data disk IOPS read'
          type: DEPENDENT
          key: azure.scaleset.data.disk.read.ops
          value_type: FLOAT
          units: '!iops'
          description: 'Read IOPS from a single disk during the monitoring period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskReadOperationsSec.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 99b8c634131d49b7828e88a44342e2b6
          name: 'Data disk write rate'
          type: DEPENDENT
          key: azure.scaleset.data.disk.write.bps
          value_type: FLOAT
          units: Bps
          description: 'Bytes/sec written to a single disk during the monitoring period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskWriteBytessec.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 0c46306040db41af895ab9a82d55ad31
          name: 'Data disk IOPS write'
          type: DEPENDENT
          key: azure.scaleset.data.disk.write.ops
          value_type: FLOAT
          units: '!iops'
          description: 'Write IOPS from a single disk during the monitoring period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DataDiskWriteOperationsSec.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 14a25a861b9f491194ea055c189cc2f9
          name: 'Get errors'
          type: DEPENDENT
          key: azure.scaleset.data.errors
          value_type: TEXT
          description: 'A list of errors from API requests.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.error
              error_handler: CUSTOM_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: error
          triggers:
            - uuid: 1d114800a6534498b52a2dd25e93d719
              expression: 'length(last(/Azure VM Scale Set by HTTP/azure.scaleset.data.errors))>0'
              name: 'Azure VM Scale: There are errors in requests to API'
              opdata: '{ITEM.LASTVALUE1}'
              priority: AVERAGE
              description: 'Zabbix has received errors in response to API requests.'
              tags:
                - tag: scope
                  value: availability
        - uuid: f783d047862144f2baed76bb281cec5b
          name: 'Get data'
          type: SCRIPT
          key: azure.scaleset.data.get
          history: '0'
          value_type: TEXT
          params: |
            var Azure = {
            	params: {},
            	token: null,
            
            	setParams: function (params) {
            		['app_id', 'password', 'tenant_id', 'subscription_id', 'resource_id'].forEach(function (field) {
            			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
            				throw 'Required param is not set: ' + field + '.';
            			}
            		});
            
            		Azure.params = params;
            	},
            
            	login: function () {
            		var response, login = new HttpRequest();
            
            		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
            			login.setProxy(Azure.params.proxy);
            		}
            
            		login.addHeader('Content-Type: application/x-www-form-urlencoded');
            		response = login.post(
            			'https://login.microsoftonline.com/' + encodeURIComponent(Azure.params.tenant_id) + '/oauth2/token',
            			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(Azure.params.app_id) + '&client_secret=' + encodeURIComponent(Azure.params.password)
            		);
            
            		if (login.getStatus() !== 200) {
            			throw 'Login failed with status code ' + login.getStatus() + ': ' + response;
            		}
            
            		try {
            			response = JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse login session response.';
            		}
            
            		if (!response.hasOwnProperty('access_token')) {
            			throw 'Authentication response does not contain access token.';
            		}
            
            		Azure.token = response['access_token'];
            	},
            
            	request: function (url) {
            		var response, request = new HttpRequest();
            
            		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
            			request.setProxy(Azure.params.proxy);
            		}
            
            		if (!Azure.token) {
            			throw 'Request does not contain access token.';
            		}
            
            		request.addHeader('Content-Type: application/json');
            		request.addHeader('Authorization: Bearer ' + Azure.token);
            		Zabbix.log(4, '[ AzureVMSS ] request url: ' + url);
            
            		response = request.get(url);
            
            		if (request.getStatus() !== 200) {
            			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
            		}
            
            		try {
            			return JSON.parse(response);
            		}
            		catch (error) {
            			throw 'Failed to parse response received from API.';
            		}
            	},
            
            	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;
            	},
            
            	getMetricsData: function () {
            		var data = {},
            			metric_endpoints = {
            				'main_metrics': '/providers/Microsoft.Insights/metrics?metricnames=' + encodeURIComponent('Available Memory Bytes,CPU Credits Consumed,CPU Credits Remaining,Percentage CPU,Inbound Flows,Inbound Flows Maximum Creation Rate,Network In,Network In Total,Network Out,Network Out Total,Outbound Flows,Outbound Flows Maximum Creation Rate,VmAvailabilityMetric') + '&api-version=2021-05-01&timespan=PT1M',
            				'disks_metrics': '/providers/Microsoft.Insights/metrics?metricnames=' + encodeURIComponent('Data Disk Bandwidth Consumed Percentage,Data Disk IOPS Consumed Percentage,Data Disk Max Burst Bandwidth,Data Disk Max Burst IOPS,Data Disk Queue Depth,Data Disk Read Bytes/sec,Data Disk Read Operations/Sec,Data Disk Target Bandwidth,Data Disk Target IOPS,Data Disk Used Burst BPS Credits Percentage,Data Disk Used Burst IO Credits Percentage,Data Disk Write Bytes/sec,Data Disk Write Operations/Sec,Disk Read Bytes,Disk Read Operations/Sec,Disk Write Bytes,Disk Write Operations/Sec') + '&api-version=2021-05-01&timespan=PT1M',
            				'os_disk_metrics': '/providers/Microsoft.Insights/metrics?metricnames=' + encodeURIComponent('OS Disk Bandwidth Consumed Percentage,OS Disk IOPS Consumed Percentage,OS Disk Max Burst Bandwidth,OS Disk Max Burst IOPS,OS Disk Queue Depth,OS Disk Read Bytes/sec,OS Disk Read Operations/Sec,OS Disk Target Bandwidth,OS Disk Target IOPS,OS Disk Used Burst BPS Credits Percentage,OS Disk Used Burst IO Credits Percentage,OS Disk Write Bytes/sec,OS Disk Write Operations/Sec') + '&api-version=2021-05-01&timespan=PT1M',
            				'premium_and_vm_metrics': '/providers/Microsoft.Insights/metrics?metricnames=' + encodeURIComponent('Premium Data Disk Cache Read Hit,Premium Data Disk Cache Read Miss,Premium OS Disk Cache Read Hit,Premium OS Disk Cache Read Miss,VM Cached Bandwidth Consumed Percentage,VM Cached IOPS Consumed Percentage,VM Local Used Burst BPS Credits Percentage,VM Local Used Burst IO Credits Percentage,VM Remote Used Burst BPS Credits Percentage,VM Remote Used Burst IO Credits Percentage,VM Uncached Bandwidth Consumed Percentage,VM Uncached IOPS Consumed Percentage') + '&api-version=2021-05-01&timespan=PT1M'
            			};
            
            		data.metrics = {};
            
            		Object.keys(metric_endpoints).forEach(function (field) {
            			metrics = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + metric_endpoints[field]), 'value');
            			for (k in metrics) {
            				key = Azure.getField(metrics[k], 'name.value').replace(/(\s|\/)+/g, '');
            				if (metrics[k].timeseries.length === 0) {
            					metrics[k].timeseries.push({ 'data': ['nodata'] })
            				}
            				data.metrics[key] = Azure.getField(metrics[k], 'timeseries.0.data.0');
            			}
            		});
            
            		data.capacity = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + '?api-version=2024-03-01'), 'sku.capacity');
            		data.health = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + '/providers/Microsoft.ResourceHealth/availabilityStatuses?api-version=2020-05-01'), 'value.0.properties');
            
            		return data
            	}
            };
            
            try {
            	Azure.setParams(JSON.parse(value));
            	Azure.login();
            	return JSON.stringify(Azure.getMetricsData());
            }
            catch (error) {
            	error += (String(error).endsWith('.')) ? '' : '.';
            	Zabbix.log(3, '[ AzureVMSS ] ERROR: ' + error);
            	return JSON.stringify({ 'error': error });
            }
          description: 'Gathers data of the virtual machine scale set.'
          timeout: '{$AZURE.DATA.TIMEOUT}'
          parameters:
            - name: app_id
              value: '{$AZURE.APP.ID}'
            - name: password
              value: '{$AZURE.PASSWORD}'
            - name: proxy
              value: '{$AZURE.PROXY}'
            - name: resource_id
              value: '{$AZURE.RESOURCE.ID}'
            - name: subscription_id
              value: '{$AZURE.SUBSCRIPTION.ID}'
            - name: tenant_id
              value: '{$AZURE.TENANT.ID}'
          tags:
            - tag: component
              value: raw
        - uuid: aa8675f8f0fa454db27d46308ab92c79
          name: 'Disk read'
          type: DEPENDENT
          key: azure.scaleset.disk.read
          value_type: FLOAT
          units: B
          description: 'Bytes read from the disk during the monitoring period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DiskReadBytes.total
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 39f1d8154bc540b78f3d1c04ea68144f
          name: 'Disk IOPS read'
          type: DEPENDENT
          key: azure.scaleset.disk.read.ops
          value_type: FLOAT
          units: '!iops'
          description: 'Disk read IOPS.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DiskReadOperationsSec.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: a419f2280662418abe7692d22a5344fb
          name: 'Disk write'
          type: DEPENDENT
          key: azure.scaleset.disk.write
          value_type: FLOAT
          units: B
          description: 'Bytes written to the disk during the monitoring period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DiskWriteBytes.total
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 96ac2287bae3415cae1b0a8590954d02
          name: 'Disk IOPS write'
          type: DEPENDENT
          key: azure.scaleset.disk.write.ops
          value_type: FLOAT
          units: '!iops'
          description: 'Write IOPS from a single disk during the monitoring period.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.DiskWriteOperationsSec.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 7f0cb52d4db84c2b8d8ef8f82cc6d77b
          name: 'Inbound flows'
          type: DEPENDENT
          key: azure.scaleset.flows.inbound
          value_type: FLOAT
          description: 'Inbound Flows are the number of current flows in the inbound direction (traffic going into the VMs).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.InboundFlows.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: network
        - uuid: dacfd47b3c3142ce9ca043ebda4e7614
          name: 'Inbound flow maximum creation rate'
          type: DEPENDENT
          key: azure.scaleset.flows.inbound.max
          value_type: FLOAT
          description: 'The maximum creation rate of inbound flows (traffic going into the VM).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.InboundFlowsMaximumCreationRate.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: network
        - uuid: 8ef6bb3bc1884426ab3fe9998acf4e25
          name: 'Outbound flows'
          type: DEPENDENT
          key: azure.scaleset.flows.outbound
          value_type: FLOAT
          description: 'Outbound Flows are the number of current flows in the outbound direction (traffic going out of the VMs).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OutboundFlows.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: network
        - uuid: 15b8f8fde6e4458e8904428537a8b32a
          name: 'Outbound flow maximum creation rate'
          type: DEPENDENT
          key: azure.scaleset.flows.outbound.max
          value_type: FLOAT
          description: 'The maximum creation rate of outbound flows (traffic going out of the VM).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OutboundFlowsMaximumCreationRate.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: network
        - uuid: 4025ada5ba4940b88b48b7b71efbe07b
          name: 'Network in total'
          type: DEPENDENT
          key: azure.scaleset.network.in.total
          value_type: FLOAT
          units: B
          description: 'The number of bytes received on all network interfaces by the virtual machine(s) (incoming traffic).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.NetworkInTotal.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: network
        - uuid: 6bca5eeb39194c5f83f83863f1e6b4c6
          name: 'Network out total'
          type: DEPENDENT
          key: azure.scaleset.network.out.total
          value_type: FLOAT
          units: B
          description: 'The number of bytes out on all network interfaces by the virtual machine(s) (outgoing traffic).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.NetworkOutTotal.total
              error_handler: DISCARD_VALUE
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: network
        - uuid: d81be2d243124ebd8efd5fa4fd79d3f6
          name: 'OS disk used burst BPS credits'
          type: DEPENDENT
          key: azure.scaleset.os.disk.bandwidth.burst.used
          value_type: FLOAT
          units: '%'
          description: 'Percentage of OS Disk burst bandwidth credits used so far.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskUsedBurstBPSCreditsPercentage.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: b66ff8f85e614b9c9db479e8452a3acb
          name: 'OS disk bandwidth consumed'
          type: DEPENDENT
          key: azure.scaleset.os.disk.bandwidth.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of operating system disk bandwidth consumed per minute.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskBandwidthConsumedPercentage.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: b5f5c9d4040c4b889287658532aec890
          name: 'OS disk max burst bandwidth'
          type: DEPENDENT
          key: azure.scaleset.os.disk.bandwidth.max
          value_type: FLOAT
          units: Bps
          description: 'Maximum byte-per-second throughput the OS Disk can achieve with bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskMaxBurstBandwidth.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 4f28508261554a11a858f905160a5db2
          name: 'OS disk target bandwidth'
          type: DEPENDENT
          key: azure.scaleset.os.disk.bandwidth.target
          value_type: FLOAT
          units: Bps
          description: 'Baseline byte-per-second throughput the OS Disk can achieve without bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskTargetBandwidth.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 97005b2f1be1455f8002b3f777898163
          name: 'OS disk used burst IO credits'
          type: DEPENDENT
          key: azure.scaleset.os.disk.iops.burst.used
          value_type: FLOAT
          units: '%'
          description: 'Percentage of OS Disk burst I/O credits used so far.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskUsedBurstIOCreditsPercentage.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 87e51f85e00646d4bfe12840f444e47a
          name: 'OS disk IOPS consumed'
          type: DEPENDENT
          key: azure.scaleset.os.disk.iops.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of operating system disk I/Os consumed per minute.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskIOPSConsumedPercentage.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 1ff472b5cca24332abea886bff44435f
          name: 'OS disk max burst IOPS'
          type: DEPENDENT
          key: azure.scaleset.os.disk.iops.max
          value_type: FLOAT
          units: '!iops'
          description: 'Maximum IOPS the OS Disk can achieve with bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskMaxBurstIOPS.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 72b19174782d4905be402e2825098f17
          name: 'OS disk target IOPS'
          type: DEPENDENT
          key: azure.scaleset.os.disk.iops.target
          value_type: FLOAT
          units: '!iops'
          description: 'Baseline IOPS the OS disk can achieve without bursting.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskTargetIOPS.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 3bbb425e37894415b002e026e34259a2
          name: 'OS disk queue depth'
          type: DEPENDENT
          key: azure.scaleset.os.disk.queue.depth
          value_type: FLOAT
          description: 'OS Disk queue depth (or queue length).'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskQueueDepth.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 7879801b929249d0b266ae905307beee
          name: 'OS disk read rate'
          type: DEPENDENT
          key: azure.scaleset.os.disk.read.bps
          value_type: FLOAT
          units: Bps
          description: 'Bytes/sec read from a single disk during the monitoring period - for an OS disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskReadBytessec.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 542881bbbb694b1a84befbb772ded703
          name: 'OS disk IOPS read'
          type: DEPENDENT
          key: azure.scaleset.os.disk.read.ops
          value_type: FLOAT
          units: '!iops'
          description: 'Read IOPS from a single disk during the monitoring period - for an OS disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskReadOperationsSec.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: c86371d6f8224b418f003a7fdefe9884
          name: 'OS disk write rate'
          type: DEPENDENT
          key: azure.scaleset.os.disk.write.bps
          value_type: FLOAT
          units: Bps
          description: 'Bytes/sec written to a single disk during the monitoring period - for an OS disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskWriteBytessec.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 77d95de6fdbd49ba9bae68e75f792560
          name: 'OS disk IOPS write'
          type: DEPENDENT
          key: azure.scaleset.os.disk.write.ops
          value_type: FLOAT
          units: '!iops'
          description: 'Write IOPS from a single disk during the monitoring period - for an OS disk.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.OSDiskWriteOperationsSec.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 25915ce6d37740bf83f656c5cc7b9960
          name: 'Premium data disk cache read hit in %'
          type: DEPENDENT
          key: azure.scaleset.premium.data.disk.cache.read.hit
          value_type: FLOAT
          units: '%'
          description: 'Percentage of premium data disk cache read hit.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.PremiumDataDiskCacheReadHit.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: f04f8f7e59ec4786b5ea8765cbf69b82
          name: 'Premium data disk cache read miss in %'
          type: DEPENDENT
          key: azure.scaleset.premium.data.disk.cache.read.miss
          value_type: FLOAT
          units: '%'
          description: 'Percentage of premium data disk cache read miss.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.PremiumDataDiskCacheReadMiss.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 65442659fe944842811638ac04dc998a
          name: 'Premium OS disk cache read hit in %'
          type: DEPENDENT
          key: azure.scaleset.premium.os.disk.cache.read.hit
          value_type: FLOAT
          units: '%'
          description: 'Percentage of premium OS disk cache read hit.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.PremiumOSDiskCacheReadHit.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 981c83a8623c481ca040c66f5d5738ec
          name: 'Premium OS disk cache read miss in %'
          type: DEPENDENT
          key: azure.scaleset.premium.os.disk.cache.read.miss
          value_type: FLOAT
          units: '%'
          description: 'Percentage of premium OS disk cache read miss.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.PremiumOSDiskCacheReadMiss.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 8bfbc99e09314aeea7c0d0563d148c11
          name: 'VM cached bandwidth consumed'
          type: DEPENDENT
          key: azure.scaleset.vm.cached.bandwidth.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of cached disk bandwidth consumed by the VM.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.VMCachedBandwidthConsumedPercentage.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: ae97e2890b5844749913f3a1d650091d
          name: 'VM cached IOPS consumed'
          type: DEPENDENT
          key: azure.scaleset.vm.cached.iops.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of cached disk IOPS consumed by the VM.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.VMCachedIOPSConsumedPercentage.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: 7124d8d7d2b246feaa8959fd6d5aba0f
          name: 'Virtual machine count'
          type: DEPENDENT
          key: azure.scaleset.vm.count
          description: 'Current amount of virtual machines in the scale set.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.capacity
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: health
          triggers:
            - uuid: cd77906ed04a42f28bb702bc513504a0
              expression: 'min(/Azure VM Scale Set by HTTP/azure.scaleset.vm.count,5m)>{$AZURE.SCALESET.VM.COUNT.CRIT}'
              name: 'Azure VM Scale: High amount of VMs in the scale set'
              event_name: 'Azure VM Scale: Number of VMs is high (over {$AZURE.SCALESET.VM.COUNT.CRIT} for last 5m)'
              opdata: '{ITEM.LASTVALUE1}'
              priority: HIGH
              description: 'High amount of VMs in the scale set.'
              tags:
                - tag: scope
                  value: performance
        - uuid: 31f742e4476f4ab09d3a2bd46f820098
          name: 'Available memory'
          type: DEPENDENT
          key: azure.scaleset.vm.memory
          value_type: FLOAT
          units: B
          description: 'Amount of physical memory, in bytes, immediately available for allocation to a process or for system use in the virtual machine.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.AvailableMemoryBytes.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: memory
        - uuid: 8271a3a47a744e23bd239919760fb9b4
          name: 'VM uncached bandwidth consumed'
          type: DEPENDENT
          key: azure.scaleset.vm.uncached.bandwidth.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of uncached disk bandwidth consumed by the VM.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.VMUncachedBandwidthConsumedPercentage.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
        - uuid: dd8f8111b6914ba38f6fe2f707dbb9f1
          name: 'VM uncached IOPS consumed'
          type: DEPENDENT
          key: azure.scaleset.vm.uncached.iops.consumed
          value_type: FLOAT
          units: '%'
          description: 'Percentage of uncached disk IOPS consumed by the VM.'
          preprocessing:
            - type: JSONPATH
              parameters:
                - $.metrics.VMUncachedIOPSConsumedPercentage.average
              error_handler: DISCARD_VALUE
            - type: DISCARD_UNCHANGED_HEARTBEAT
              parameters:
                - 1h
          master_item:
            key: azure.scaleset.data.get
          tags:
            - tag: component
              value: storage
      tags:
        - tag: class
          value: cloud
        - tag: subclass
          value: automation
        - tag: subclass
          value: virtualization
        - tag: target
          value: azure
      macros:
        - macro: '{$AZURE.APP.ID}'
          description: 'The App ID of Microsoft Azure.'
          config:
            type: TEXT
            priority: '3'
            label: 'Azure App ID'
            required: 'YES'
        - macro: '{$AZURE.DATA.TIMEOUT}'
          value: 15s
          description: 'API response timeout.'
          config:
            type: TEXT
            priority: '8'
            section_name: Other
            label: 'API timeout'
            description: 'API response timeout, in seconds.'
        - macro: '{$AZURE.PASSWORD}'
          type: SECRET_TEXT
          description: 'Microsoft Azure password.'
          config:
            type: TEXT
            priority: '4'
            label: 'Azure password'
            required: 'YES'
        - macro: '{$AZURE.PROXY}'
          description: 'Sets the HTTP proxy value. If this macro is empty, then no proxy is used.'
          config:
            type: TEXT
            priority: '9'
            section_name: Other
            label: 'HTTP proxy'
            description: 'HTTP proxy to use for requests.'
        - macro: '{$AZURE.RESOURCE.ID}'
          description: 'Microsoft Azure scale set ID.'
          config:
            type: TEXT
            priority: '5'
            label: 'Azure scale set ID'
            required: 'YES'
        - macro: '{$AZURE.SCALESET.CPU.UTIL.CRIT}'
          value: '90'
          description: 'The critical threshold of CPU utilization, expressed in %.'
          config:
            type: TEXT
            priority: '7'
            section_name: Thresholds
            label: 'CPU utilization critical threshold'
            description: 'Critical threshold of CPU utilization, expressed in %. In the range from 0 to 100 inclusive.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.SCALESET.VM.COUNT.CRIT}'
          value: '100'
          description: 'The critical amount of virtual machines in the scale set.'
          config:
            type: TEXT
            priority: '6'
            section_name: Thresholds
            label: 'Critical amount of VMs'
            description: 'Critical amount of virtual machines in the scale set. No less than 0.'
            regex: '^-?([0-9]+|(([0-9]+)\.([0-9]+)))$'
        - macro: '{$AZURE.SUBSCRIPTION.ID}'
          description: 'Microsoft Azure subscription ID.'
          config:
            type: TEXT
            priority: '1'
            label: 'Azure subscription ID'
            required: 'YES'
        - macro: '{$AZURE.TENANT.ID}'
          description: 'Microsoft Azure tenant ID.'
          config:
            type: TEXT
            priority: '2'
            label: 'Azure tenant ID'
            required: 'YES'
      dashboards:
        - uuid: 1a38b3783a6b41cca3e5cfadd64d4534
          name: 'Overview Azure VM Scale Set'
          pages:
            - widgets:
                - type: item
                  name: 'Virtual machine count'
                  width: '12'
                  height: '3'
                  fields:
                    - type: INTEGER
                      name: decimal_places
                      value: '0'
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        key: azure.scaleset.vm.count
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'CPU credits consumed'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        key: azure.scaleset.cpu.credits.consumed
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Network in'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        key: azure.scaleset.network.in.total
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Disk read'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        key: azure.scaleset.disk.read
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'OS disk read operations/sec'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        key: azure.scaleset.disk.read.ops
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Inbound flows'
                  'y': '15'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        key: azure.scaleset.flows.inbound
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Available memory'
                  x: '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        key: azure.scaleset.vm.memory
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'CPU credits remaining'
                  x: '12'
                  'y': '3'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        key: azure.scaleset.cpu.credits.remaining
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Network out'
                  x: '12'
                  'y': '6'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        key: azure.scaleset.network.out.total
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Disk write'
                  x: '12'
                  'y': '9'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        key: azure.scaleset.disk.write
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'OS disk write operations/sec'
                  x: '12'
                  'y': '12'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        key: azure.scaleset.disk.write.ops
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Outbound flows'
                  x: '12'
                  'y': '15'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        key: azure.scaleset.flows.outbound
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                - type: item
                  name: 'Availability state'
                  x: '24'
                  width: '12'
                  height: '3'
                  fields:
                    - type: ITEM
                      name: itemid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        key: azure.scaleset.availability.state
                    - type: INTEGER
                      name: show.0
                      value: '4'
                    - type: INTEGER
                      name: show.1
                      value: '2'
                    - type: STRING
                      name: up_color
                      value: FF0000
                - type: graph
                  name: 'CPU Utilization'
                  x: '24'
                  'y': '3'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        name: 'CPU Utilization'
                    - type: STRING
                      name: reference
                      value: AAAAA
                - type: graph
                  name: 'Network traffic'
                  x: '24'
                  'y': '6'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        name: 'Network traffic, bytes'
                    - type: STRING
                      name: reference
                      value: AAAAB
                - type: graph
                  name: 'Disk read/write bytes'
                  x: '24'
                  'y': '9'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        name: 'Disk read/write bytes'
                    - type: STRING
                      name: reference
                      value: AAAAC
                - type: graph
                  name: 'OS disk read/write rates'
                  x: '24'
                  'y': '12'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        name: 'OS disk IOPS read/write'
                    - type: STRING
                      name: reference
                      value: AAAAD
                - type: graph
                  name: Flows
                  x: '24'
                  'y': '15'
                  width: '48'
                  height: '3'
                  fields:
                    - type: GRAPH
                      name: graphid.0
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        name: Flows
                    - type: STRING
                      name: reference
                      value: AAAAE
                - type: itemhistory
                  name: 'Availability status detailed'
                  x: '36'
                  width: '36'
                  height: '3'
                  fields:
                    - type: INTEGER
                      name: columns.0.display
                      value: '4'
                    - type: ITEM
                      name: columns.0.itemid
                      value:
                        host: 'Azure VM Scale Set by HTTP'
                        key: azure.scaleset.availability.details
                    - type: INTEGER
                      name: columns.0.monospace_font
                      value: '1'
                    - type: STRING
                      name: columns.0.name
                      value: '|'
                    - type: STRING
                      name: reference
                      value: BAAAA
                    - type: INTEGER
                      name: show_column_header
                      value: '0'
                    - type: INTEGER
                      name: show_timestamp
                      value: '1'
      valuemaps:
        - uuid: fc7ca60876144ac8b240db81537920a6
          name: 'Azure resource health state'
          mappings:
            - value: '0'
              newvalue: Available
            - value: '1'
              newvalue: Degraded
            - value: '2'
              newvalue: Unavailable
            - value: '3'
              newvalue: Unknown
  graphs:
    - uuid: 73faeee0b6934fb4983c035b60782ca7
      name: 'Average CPU percentage'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure SQL Managed Instance by HTTP'
            key: azure.sql_inst.cpu
    - 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: e962b86d53c749b6914c3d50fb8757ff
      name: 'AWS ECS Cluster: CPU Utilization'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 2196F3
          item:
            host: 'AWS ECS Cluster by HTTP'
            key: aws.ecs.cpu_utilization
    - uuid: 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: 5f9d5878b5954d59bee0ca5d977f3dc7
      name: 'AWS ECS Cluster: Memory Utilization'
      graph_items:
        - drawtype: GRADIENT_LINE
          color: 2196F3
          item:
            host: 'AWS ECS Cluster by HTTP'
            key: aws.ecs.memory_utilization
    - uuid: 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: 503c0a606b1440f4bc02f115196ef9ad
      name: 'AWS ECS Cluster: Network'
      graph_items:
        - color: 199C0D
          item:
            host: 'AWS ECS Cluster by HTTP'
            key: aws.ecs.network.rx
        - sortorder: '1'
          color: F63100
          item:
            host: 'AWS ECS Cluster by HTTP'
            key: aws.ecs.network.tx
    - 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
    - uuid: 781dd83ed494465bbf2c16efbc753a51
      name: 'Azure: Data disk read/write Bps'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.data.disk.read.bps
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.data.disk.write.bps
    - uuid: 7d198b2f6186498ab39ece80f3f7b30e
      name: 'Azure: Data disk read/write IOPS'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.data.disk.read.ops
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.data.disk.write.ops
    - uuid: a2d0eb282276486896067f8a30f8ea51
      name: 'Azure: Disk read/write bytes'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.disk.read.bytes
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.disk.write.bytes
    - uuid: 58a8c6942314408ab0e88b15d53f67e5
      name: 'Azure: Disk read/write IOPS'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.disk.read.ops
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.disk.write.ops
    - uuid: b427ad3dbb8d4f8caf1edfb0cab04733
      name: 'Azure: Flows'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.flows.inbound
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.flows.outbound
        - sortorder: '2'
          color: 00611C
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.flows.inbound.max
        - sortorder: '3'
          color: F7941D
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.flows.outbound.max
    - uuid: f0f37dc8840a45ba8e8cb62f5fea6804
      name: 'Azure: Network traffic'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.network.in.total
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.network.out.total
    - uuid: 41bd1642704c4d3fbe4fb34c8c389320
      name: 'Azure: OS disk read/write Bps'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.os.disk.read.bps
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.os.disk.write.bps
    - uuid: df77fe1de4ae46f98744ff73ed427b3b
      name: 'Azure: OS disk read/write IOPS'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.os.disk.read.ops
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.os.disk.write.ops
    - uuid: 39ca70fc12cf4c6d9fdc23e8562b2f13
      name: 'Azure: Percentage CPU'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.cpu.utilization
    - uuid: 3051d683b44b48ee94030465254abc7f
      name: 'Azure: Premium data disk cache read'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.premium.data.disk.cache.read.hit
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.premium.data.disk.cache.read.miss
    - uuid: d727dc11deaa46b282892552c9b03752
      name: 'Azure: Premium OS disk cache read'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.premium.os.disk.cache.read.hit
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Virtual Machine by HTTP'
            key: azure.vm.premium.os.disk.cache.read.miss
    - uuid: 3b278de1b81a4be7acc865568962c323
      name: 'Azure Microsoft SQL: Connections'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Microsoft SQL Database by HTTP'
            key: azure.db.mssql.connections.successful
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Microsoft SQL Database by HTTP'
            key: azure.db.mssql.connections.failed.system
        - sortorder: '2'
          color: 00611C
          item:
            host: 'Azure Microsoft SQL Database by HTTP'
            key: azure.db.mssql.firewall.blocked
    - uuid: a266fd856e0f49288ee96b98c6fce4b9
      name: 'Azure Microsoft SQL: Connections'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Microsoft SQL DTU Database by HTTP'
            key: azure.db.mssql.connections.successful
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Microsoft SQL DTU Database by HTTP'
            key: azure.db.mssql.connections.failed.system
        - sortorder: '2'
          color: 00611C
          item:
            host: 'Azure Microsoft SQL DTU Database by HTTP'
            key: azure.db.mssql.firewall.blocked
    - uuid: 62a9a5e1fb044a52a0b534bd4eeea914
      name: 'Azure Microsoft SQL: Connections'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Microsoft SQL Serverless Database by HTTP'
            key: azure.db.mssql.connections.successful
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Microsoft SQL Serverless Database by HTTP'
            key: azure.db.mssql.connections.failed.system
        - sortorder: '2'
          color: 00611C
          item:
            host: 'Azure Microsoft SQL Serverless Database by HTTP'
            key: azure.db.mssql.firewall.blocked
    - uuid: fe250a5f509d45babea9fcd12accbcac
      name: 'Azure Microsoft SQL: CPU usage'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Microsoft SQL Database by HTTP'
            key: azure.db.mssql.cpu.limit
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Microsoft SQL Database by HTTP'
            key: azure.db.mssql.cpu.used
    - uuid: 083d307db8954fc59e8e5cfccefc16c1
      name: 'Azure Microsoft SQL: CPU usage'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Microsoft SQL Serverless Database by HTTP'
            key: azure.db.mssql.cpu.limit
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Microsoft SQL Serverless Database by HTTP'
            key: azure.db.mssql.cpu.used
    - uuid: 0849698704cb40cab4ce62d3eb093717
      name: 'Azure Microsoft SQL: DTU usage'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Microsoft SQL DTU Database by HTTP'
            key: azure.db.mssql.dtu.limit
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Microsoft SQL DTU Database by HTTP'
            key: azure.db.mssql.dtu.used
    - uuid: ec5714017c744484be8c264d24a0e694
      name: 'Azure Microsoft SQL: Storage utilization'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Microsoft SQL Database by HTTP'
            key: azure.db.mssql.storage.used
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Microsoft SQL Database by HTTP'
            key: azure.db.mssql.storage.allocated
    - uuid: 3aebd39180de4314a7129d2c5deb6b6a
      name: 'Azure Microsoft SQL: Storage utilization'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Microsoft SQL DTU Database by HTTP'
            key: azure.db.mssql.storage.used
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Microsoft SQL DTU Database by HTTP'
            key: azure.db.mssql.storage.allocated
    - uuid: f541b6591683433aba4b3e58a8ad1e5c
      name: 'Azure Microsoft SQL: Storage utilization'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Microsoft SQL Serverless Database by HTTP'
            key: azure.db.mssql.storage.used
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Microsoft SQL Serverless Database by HTTP'
            key: azure.db.mssql.storage.allocated
    - uuid: 89256a1eba8c49d2b7469a68ff050ac5
      name: 'Azure MongoDB: Latency'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Cosmos DB for MongoDB by HTTP'
            key: azure.cosmosdb.server.side.latency.gateway
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Cosmos DB for MongoDB by HTTP'
            key: azure.cosmosdb.server.side.latency
        - sortorder: '2'
          color: 00611C
          item:
            host: 'Azure Cosmos DB for MongoDB by HTTP'
            key: azure.cosmosdb.server.side.latency.direct
        - sortorder: '3'
          color: F7941D
          item:
            host: 'Azure Cosmos DB for MongoDB by HTTP'
            key: azure.cosmosdb.replication.latency
    - uuid: a1225fc27d334c5bbb5043e3d468bf02
      name: 'Azure MongoDB: Requests'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Cosmos DB for MongoDB by HTTP'
            key: azure.cosmosdb.total.requests
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Cosmos DB for MongoDB by HTTP'
            key: azure.cosmosdb.total.request.units
        - sortorder: '2'
          color: 00611C
          item:
            host: 'Azure Cosmos DB for MongoDB by HTTP'
            key: azure.cosmosdb.metadata.requests
        - sortorder: '3'
          color: F7941D
          item:
            host: 'Azure Cosmos DB for MongoDB by HTTP'
            key: azure.cosmosdb.mongo.requests
        - sortorder: '4'
          color: FC6EA3
          item:
            host: 'Azure Cosmos DB for MongoDB by HTTP'
            key: azure.cosmosdb.mongo.requests.charge
    - uuid: 07168aaf3abb42f6b61746cc6e2d2910
      name: 'Azure MongoDB: Usage'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure Cosmos DB for MongoDB by HTTP'
            key: azure.cosmosdb.data.usage
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure Cosmos DB for MongoDB by HTTP'
            key: azure.cosmosdb.index.usage
        - sortorder: '2'
          color: 00611C
          item:
            host: 'Azure Cosmos DB for MongoDB by HTTP'
            key: azure.cosmosdb.document.quota
    - uuid: 750ae48e6ef749c19a06f4bbe716f92f
      name: 'Azure MySQL: Connections'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure MySQL Flexible Server by HTTP'
            key: azure.db.mysql.connections.active
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure MySQL Flexible Server by HTTP'
            key: azure.db.mysql.connections.total
        - sortorder: '2'
          color: 00611C
          item:
            host: 'Azure MySQL Flexible Server by HTTP'
            key: azure.db.mysql.connections.aborted
    - uuid: 360a24b56be74cf48df3135008437824
      name: 'Azure MySQL: Connections'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure MySQL Single Server by HTTP'
            key: azure.db.mysql.connections.active
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure MySQL Single Server by HTTP'
            key: azure.db.mysql.connections.failed
    - uuid: f929f47602734f82a79f22a5f4446f61
      name: 'Azure MySQL: Network traffic'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure MySQL Flexible Server by HTTP'
            key: azure.db.mysql.network.egress
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure MySQL Flexible Server by HTTP'
            key: azure.db.mysql.network.ingress
    - uuid: dc6840162405481ebc1c3c98fdfcaef1
      name: 'Azure MySQL: Network traffic'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure MySQL Single Server by HTTP'
            key: azure.db.mysql.network.egress
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure MySQL Single Server by HTTP'
            key: azure.db.mysql.network.ingress
    - uuid: 3fcf43fd338e4902874d940fc0bec8b9
      name: 'Azure MySQL: Server log storage utilization'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure MySQL Single Server by HTTP'
            key: azure.db.mysql.storage.server.log.used
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure MySQL Single Server by HTTP'
            key: azure.db.mysql.storage.server.log.limit
    - uuid: 4210e6b4ed8744589dce88217e961a56
      name: 'Azure MySQL: Storage utilization'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure MySQL Flexible Server by HTTP'
            key: azure.db.mysql.storage.used
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure MySQL Flexible Server by HTTP'
            key: azure.db.mysql.storage.limit
    - uuid: bdc178e6faaa4850badc0c60c7c80d40
      name: 'Azure MySQL: Storage utilization'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure MySQL Single Server by HTTP'
            key: azure.db.mysql.storage.used
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure MySQL Single Server by HTTP'
            key: azure.db.mysql.storage.limit
    - uuid: 2b60e8b1fd7c43f4ac61812e43c0e1ca
      name: 'Azure PostgreSQL: Connections'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure PostgreSQL Flexible Server by HTTP'
            key: azure.db.pgsql.connections.active
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure PostgreSQL Flexible Server by HTTP'
            key: azure.db.pgsql.connections.succeeded
        - sortorder: '2'
          color: 00611C
          item:
            host: 'Azure PostgreSQL Flexible Server by HTTP'
            key: azure.db.pgsql.connections.failed
    - uuid: c76cf8ec6a584af6be815ec4a9257a8c
      name: 'Azure PostgreSQL: Connections'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure PostgreSQL Single Server by HTTP'
            key: azure.db.pgsql.connections.active
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure PostgreSQL Single Server by HTTP'
            key: azure.db.pgsql.connections.failed
    - uuid: a4679d243b574bea84397c980723c68b
      name: 'Azure PostgreSQL: Network traffic'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure PostgreSQL Flexible Server by HTTP'
            key: azure.db.pgsql.network.egress
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure PostgreSQL Flexible Server by HTTP'
            key: azure.db.pgsql.network.ingress
    - uuid: 8bc17d843775414ea971e640e1fe5ec0
      name: 'Azure PostgreSQL: Network traffic'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure PostgreSQL Single Server by HTTP'
            key: azure.db.pgsql.network.egress
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure PostgreSQL Single Server by HTTP'
            key: azure.db.pgsql.network.ingress
    - uuid: 9e750a5a462b4429ac5a36a72bd60c66
      name: 'Azure PostgreSQL: Server log storage utilization'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure PostgreSQL Single Server by HTTP'
            key: azure.db.pgsql.storage.server.log.used
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure PostgreSQL Single Server by HTTP'
            key: azure.db.pgsql.storage.server.log.limit
    - uuid: 5fa13cfbdd784475818fae06ff94f879
      name: 'Azure PostgreSQL: Storage utilization'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure PostgreSQL Flexible Server by HTTP'
            key: azure.db.pgsql.storage.used
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure PostgreSQL Flexible Server by HTTP'
            key: azure.db.pgsql.storage.free
    - uuid: 9ecd071a77364c4486fa5f63125cd985
      name: 'Azure PostgreSQL: Storage utilization'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure PostgreSQL Single Server by HTTP'
            key: azure.db.pgsql.storage.used
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure PostgreSQL Single Server by HTTP'
            key: azure.db.pgsql.storage.limit
    - uuid: 36ff6447ea4f403eb0f13dc6322c99ea
      name: 'CPU Utilization'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.cpu.utilization
    - uuid: 66b7d2f063064a1b8912e2b2e57d2d40
      name: 'Data disk IOPS read/write'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.data.disk.read.ops
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.data.disk.write.ops
    - uuid: 9bbdd448793e41b6b8aef38c7cad41c6
      name: 'Data disk read/write Bps'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.data.disk.read.bps
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.data.disk.write.bps
    - uuid: 2d0a30934cf7444f89fe031178599abc
      name: 'Disk IOPS read/write'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.disk.read.ops
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.disk.write.ops
    - uuid: 7b724a3805d84dbb99fcbf5c2fd633b4
      name: 'Disk read/write bytes'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.disk.read
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.disk.write
    - uuid: e4d6ccffbf274347a3fdade920467ae2
      name: Flows
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.flows.inbound
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.flows.outbound
        - sortorder: '2'
          color: 00611C
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.flows.inbound.max
        - sortorder: '3'
          color: F7941D
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.flows.outbound.max
    - uuid: bcc8df046b3646ed8a14d462b761885e
      name: 'IO bytes read/write'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure SQL Managed Instance by HTTP'
            key: azure.sql_inst.bytes.read
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure SQL Managed Instance by HTTP'
            key: azure.sql_inst.bytes.write
    - uuid: ac14ada6a3164e26b81686912e0b10a9
      name: 'IO request count'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure SQL Managed Instance by HTTP'
            key: azure.sql_inst.requests
    - uuid: 9109c16ec3b540118aff0e458fb00580
      name: 'Network traffic, bytes'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.network.in.total
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.network.out.total
    - uuid: 079e812dd9af48cda80993ad9b3a59d0
      name: 'OS disk IOPS read/write'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.os.disk.read.ops
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.os.disk.write.ops
    - uuid: de643aefc3b340e3a4cd81216a78709d
      name: 'OS disk read/write Bps'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.os.disk.read.bps
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.os.disk.write.bps
    - uuid: dd3b9363272949d8a1fef02f6c14229d
      name: 'Premium data disk cache read'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.premium.data.disk.cache.read.hit
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.premium.data.disk.cache.read.miss
    - uuid: 8a432a338a9540b4888f9f019164acdb
      name: 'Premium OS disk cache read'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.premium.os.disk.cache.read.hit
        - sortorder: '1'
          color: F63100
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.premium.os.disk.cache.read.miss
    - uuid: 32f7809d7cae4a61a603b6b8d4161570
      name: 'Storage space used'
      ymax_type_1: ITEM
      ymax_item_1:
        host: 'Azure SQL Managed Instance by HTTP'
        key: azure.sql_inst.storage.reserved
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure SQL Managed Instance by HTTP'
            key: azure.sql_inst.storage.used
    - uuid: 2e1c34a01d3a4501be1ed64d45332424
      name: 'Storage space utilization'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure SQL Managed Instance by HTTP'
            key: azure.sql_inst.storage.utilization
    - uuid: 4f14da1ce6d041ff8bdcc06a172f2734
      name: 'Virtual core count'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure SQL Managed Instance by HTTP'
            key: azure.sql_inst.core.count
    - uuid: 8d04afa2c9d2459e926a9c20af37e4f8
      name: 'Virtual machine count'
      graph_items:
        - color: 199C0D
          item:
            host: 'Azure VM Scale Set by HTTP'
            key: azure.scaleset.vm.count
