import { cloneDeep, set } from 'lodash'; import * as React from 'react'; import { NumberInput, ReactSelectInput } from '@spinnaker/core'; import type { Application, ILoadBalancer } from '@spinnaker/core'; import type { ITargetTrackingPolicyCommand } from '../ScalingPolicyWriter'; import { TargetTrackingChart } from './TargetTrackingChart'; import type { IAmazonApplicationLoadBalancer, IAmazonServerGroup, ICustomizedMetricSpecification, IScalingPolicyAlarmView, ITargetGroup, } from '../../../../domain'; import { MetricSelector } from '../upsert/alarm/MetricSelector'; import './TargetMetricFields.less'; export type MetricType = 'custom' | 'predefined'; export interface ITargetMetricFieldsProps { allowDualMode?: boolean; cloudwatch?: boolean; command: ITargetTrackingPolicyCommand; isCustomMetric: boolean; app: Application; serverGroup: IAmazonServerGroup; toggleMetricType?: (type: MetricType) => void; updateCommand: (command: ITargetTrackingPolicyCommand) => void; } interface IalbArn { loadBalancerArn: string; } interface ItargetGroupArn { targetGroupArn: string; } export const TargetMetricFields = ({ allowDualMode, cloudwatch, command, isCustomMetric, app, serverGroup, toggleMetricType, updateCommand, }: ITargetMetricFieldsProps) => { const predefinedMetrics = [ 'ASGAverageCPUUtilization', 'ASGAverageNetworkOut', 'ASGAverageNetworkIn', 'ALBRequestCountPerTarget', ]; const statistics = ['Average', 'Maximum', 'Minimum', 'SampleCount', 'Sum']; const [unit, setUnit] = React.useState(null); const setCommandField = (path: string, value: any) => { const newCommand = cloneDeep(command); set(newCommand, path, value); updateCommand(newCommand); }; const updateAlarm = (newAlarm: ICustomizedMetricSpecification) => { setCommandField('targetTrackingConfiguration.customizedMetricSpecification', newAlarm); }; const onMetricTypeChange = () => { const newCommand = cloneDeep(command); if (isCustomMetric) { set(newCommand, 'targetTrackingConfiguration.predefinedMetricSpecification', { predefinedMetricType: 'ASGAverageCPUUtilization', }); set(newCommand, 'targetTrackingConfiguration.customizedMetricSpecification', null); } else { set(newCommand, 'targetTrackingConfiguration.predefinedMetricSpecification', null); set(newCommand, 'targetTrackingConfiguration.customizedMetricSpecification', { metricName: 'CPUUtilization', namespace: 'AWS/EC2', dimensions: [{ name: 'AutoScalingGroupName', value: serverGroup.name }], statistic: 'Average', }); } updateCommand(newCommand); toggleMetricType(isCustomMetric ? 'predefined' : 'custom'); }; const targetGroupOptions = () => { const loadBalancers = app.loadBalancers.data as ILoadBalancer[]; const albs = loadBalancers.filter( (lb) => lb.account === serverGroup.account && lb.region === serverGroup.region, ) as Array; const targetGroups = albs.flatMap((alb) => alb.targetGroups .filter((tg) => serverGroup.targetGroups.some((serverGroupTg) => serverGroupTg === tg.name)) .map((tg) => ({ ...tg, loadBalancerArn: alb.loadBalancerArn })), ) as Array; return targetGroups.map((tg) => ({ label: tg.name, value: `${tg.loadBalancerArn.substring(tg.loadBalancerArn.indexOf('app'))}/${tg.targetGroupArn.substring( tg.targetGroupArn.indexOf('targetgroup'), )}`, })); }; return (

With target tracking policies, Amazon will automatically adjust the size of your ASG to keep the selected metric as close as possible to the selected value.

{cloudwatch && (

Note: metrics must be sent to Amazon CloudWatch before they can be used in auto scaling. If you do not see a metric below, click "Configure available metrics" in the server group details to set up forwarding from Atlas to CloudWatch.

)}
Metric
{!isCustomMetric && ( setCommandField( 'targetTrackingConfiguration.predefinedMetricSpecification.predefinedMetricType', e.target.value, ) } inputClassName="metric-select-input" /> )} {isCustomMetric && ( )} {allowDualMode && ( {isCustomMetric ? 'Use a predefined metric' : 'Select a custom metric'} )}
{!isCustomMetric && command.targetTrackingConfiguration.predefinedMetricSpecification?.predefinedMetricType === 'ALBRequestCountPerTarget' && (
Target Group
setCommandField( 'targetTrackingConfiguration.predefinedMetricSpecification.resourceLabel', e.target.value, ) } inputClassName="metric-select-input" />
)}
Target
{isCustomMetric && (
setCommandField('targetTrackingConfiguration.customizedMetricSpecification.statistic', e.target.value) } inputClassName="form-control input-sm target-input" /> of
)}
setCommandField('targetTrackingConfiguration.targetValue', Number.parseInt(e.target.value)) } inputClassName="form-control input-sm sp-margin-xs-right" /> {unit}
setUnit(u)} />
); };