Skip to content

Commit

Permalink
refactor(amazon/titus): Convert TargetTrackingChart to React (#9592)
Browse files Browse the repository at this point in the history
* refactor(amazon/titus): TargetTrackingChart

* refactor(amazon/titus): Convert titus chart to react

refactor(amazon/titus): Convert titus chart to react

* refactor(amazon/titus): Convert titus chart to react
  • Loading branch information
caseyhebebrand committed Aug 24, 2021
1 parent 7fcb843 commit 75a614c
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 189 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import * as React from 'react';
import { Dictionary } from 'lodash';
import { Subject } from 'rxjs';

import { ICloudMetricStatistics } from '@spinnaker/core';
import { IAmazonServerGroup, IScalingPolicyAlarm, ITargetTrackingConfiguration } from '../../../../domain';
import { MetricAlarmChart } from '../chart/MetricAlarmChart';

export interface ITargetTrackingChartProps {
alarmUpdated?: Subject<void>;
config: ITargetTrackingConfiguration;
serverGroup: IAmazonServerGroup;
unit?: string;
updateUnit?: (unit: string) => void;
}

const predefinedMetricTypeMapping: Dictionary<string> = {
ASGAverageCPUUtilization: 'CPUUtilization',
ASGAverageNetworkIn: 'NetworkIn',
ASGAverageNetworkOut: 'NetworkOut',
};

export const TargetTrackingChart = ({
alarmUpdated = new Subject<void>(),
config,
serverGroup,
unit,
updateUnit,
}: ITargetTrackingChartProps) => {
const [alarm, setAlarm] = React.useState<IScalingPolicyAlarm>({
alarmName: null,
alarmArn: null,
metricName: null,
namespace: null,
statistic: 'Average',
dimensions: [],
period: 60,
threshold: config.targetValue,
comparisonOperator: 'GreaterThanThreshold',
okactions: [],
insufficientDataActions: [],
alarmActions: [],
evaluationPeriods: null,
alarmDescription: null,
unit: null,
});

const synchronizeAlarm = () => {
const customMetric = config?.customizedMetricSpecification;
const updatedAlarm = {
...alarm,
dimensions: customMetric?.dimensions || [{ name: 'AutoScalingGroupName', value: serverGroup.name }],
metricName:
customMetric?.metricName ||
predefinedMetricTypeMapping[config?.predefinedMetricSpecification?.predefinedMetricType],
namespace: customMetric?.namespace || 'AWS/EC2',
threshold: config?.targetValue,
};

if (customMetric) {
updatedAlarm.statistic = customMetric?.statistic;
}

setAlarm(updatedAlarm);
};

React.useEffect(() => {
synchronizeAlarm();
}, [config]);

const onChartLoaded = (stats: ICloudMetricStatistics) => {
if (unit) {
updateUnit(stats.unit);
}
alarmUpdated?.next();
};

return (
<MetricAlarmChart
alarm={alarm}
alarmUpdated={alarmUpdated}
onChartLoaded={onChartLoaded}
serverGroup={serverGroup}
/>
);
};
Original file line number Diff line number Diff line change
@@ -1,101 +1,16 @@
import { IComponentController, IComponentOptions, IRootScopeService, module } from 'angular';
import { Dictionary } from 'lodash';
import { Subject } from 'rxjs';

import { ICloudMetricStatistics, IServerGroup } from '@spinnaker/core';
import { IScalingPolicyAlarm, ITargetTrackingConfiguration } from '../../../../domain';

import { ITargetTrackingState } from './upsertTargetTracking.controller';

const predefinedMetricTypeMapping: Dictionary<string> = {
ASGAverageCPUUtilization: 'CPUUtilization',
ASGAverageNetworkIn: 'NetworkIn',
ASGAverageNetworkOut: 'NetworkOut',
};

class TargetTrackingChartController implements IComponentController {
public static $inject = ['$rootScope'];

constructor(public $rootScope: IRootScopeService) {}

public config: ITargetTrackingConfiguration;
public serverGroup: IServerGroup;
public state: ITargetTrackingState;
public alarmUpdated: Subject<void>;
public alarm: IScalingPolicyAlarm;

public $onInit() {
this.alarmUpdated = this.alarmUpdated || new Subject<void>();
this.alarm = this.buildChartAlarm();
this.synchronizeAlarm();
this.alarmUpdated.subscribe(() => this.synchronizeAlarm());
}

public $onDestroy() {
this.alarmUpdated.unsubscribe();
}

public onChartLoaded = (stats: ICloudMetricStatistics) => {
if (this.state) {
this.state.unit = stats.unit;
this.alarmUpdated.next();
this.$rootScope.$digest();
}
};

private synchronizeAlarm(): void {
const { config, alarm, serverGroup } = this;
if (config.customizedMetricSpecification) {
alarm.namespace = config.customizedMetricSpecification.namespace;
alarm.metricName = config.customizedMetricSpecification.metricName;
alarm.dimensions = config.customizedMetricSpecification.dimensions;
alarm.statistic = config.customizedMetricSpecification.statistic;
} else {
alarm.metricName = predefinedMetricTypeMapping[config.predefinedMetricSpecification.predefinedMetricType];
alarm.namespace = 'AWS/EC2';
alarm.dimensions = [{ name: 'AutoScalingGroupName', value: serverGroup.name }];
}
alarm.threshold = config.targetValue;
}

private buildChartAlarm(): IScalingPolicyAlarm {
return {
alarmName: null,
alarmArn: null,
metricName: null,
namespace: null,
statistic: 'Average',
dimensions: [],
period: 60,
threshold: this.config.targetValue,
comparisonOperator: 'GreaterThanThreshold',
okactions: [],
insufficientDataActions: [],
alarmActions: [],
evaluationPeriods: null,
alarmDescription: null,
unit: null,
};
}
}

const component: IComponentOptions = {
bindings: {
config: '<',
serverGroup: '<',
state: '=',
alarmUpdated: '<',
},
controller: TargetTrackingChartController,
template: `
<metric-alarm-chart
alarm="$ctrl.alarm"
server-group="$ctrl.serverGroup"
alarm-updated="$ctrl.alarmUpdated"
on-chart-loaded="$ctrl.onChartLoaded">
</metric-alarm-chart>
`,
};
import { module } from 'angular';
import { react2angular } from 'react2angular';
import { withErrorBoundary } from '@spinnaker/core';
import { TargetTrackingChart } from './TargetTrackingChart';

export const TARGET_TRACKING_CHART_COMPONENT = 'spinnaker.amazon.scalingPolicy.targetTracking.chart.component';
module(TARGET_TRACKING_CHART_COMPONENT, []).component('targetTrackingChart', component);
module(TARGET_TRACKING_CHART_COMPONENT, []).component(
'targetTrackingChart',
react2angular(withErrorBoundary(TargetTrackingChart, 'targetTrackingChart'), [
'alarmUpdated',
'config',
'serverGroup',
'unit',
'updateUnit',
]),
);
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<target-tracking-chart
config="$ctrl.policy.targetTrackingConfiguration"
state="$ctrl.state"
server-group="$ctrl.serverGroup"
></target-tracking-chart>
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ export class UpsertTargetTrackingController implements IComponentController {
}
}

public updateUnit = (unit: string) => {
this.state.unit = unit;
};

public scaleInChanged(): void {
this.state.scaleInChanged = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@ <h4 class="section-heading">Target Metric</h4>
<target-tracking-chart
config="$ctrl.command.targetTrackingConfiguration"
alarm-updated="$ctrl.alarmUpdated"
state="$ctrl.state"
server-group="$ctrl.serverGroup"
unit="$ctrl.state.unit"
update-unit="$ctrl.updateUnit"
></target-tracking-chart>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import * as React from 'react';
import { Subject } from 'rxjs';

import {
IAmazonServerGroup,
IScalingPolicyAlarm,
ITargetTrackingConfiguration,
MetricAlarmChart,
} from '@spinnaker/amazon';
import { ICloudMetricStatistics } from '@spinnaker/core';

export interface ITitusTargetTrackingChartProps {
alarmUpdated?: Subject<void>;
config: ITargetTrackingConfiguration;
serverGroup: IAmazonServerGroup;
unit?: string;
updateUnit?: (unit: string) => void;
}

export const TitusTargetTrackingChart = ({
alarmUpdated,
config,
serverGroup,
unit,
updateUnit,
}: ITitusTargetTrackingChartProps) => {
const [alarm, setAlarm] = React.useState<IScalingPolicyAlarm>({
alarmName: null,
alarmArn: null,
metricName: null,
namespace: null,
statistic: 'Average',
dimensions: [],
period: 60,
threshold: config.targetValue,
comparisonOperator: 'GreaterThanThreshold',
okactions: [],
insufficientDataActions: [],
alarmActions: [],
evaluationPeriods: null,
alarmDescription: null,
unit: null,
});

const synchronizeAlarm = () => {
const customMetric = config?.customizedMetricSpecification;
const updatedAlarm = {
...alarm,
dimensions: customMetric?.dimensions,
metricName: customMetric?.metricName,
namespace: customMetric?.namespace,
statistic: customMetric?.statistic,
threshold: config?.targetValue,
};
setAlarm(updatedAlarm);
};

React.useEffect(() => {
synchronizeAlarm();
}, [config]);

const onChartLoaded = (stats: ICloudMetricStatistics) => {
if (unit) {
updateUnit(stats.unit);
}
alarmUpdated?.next();
};

return (
<MetricAlarmChart
alarm={alarm}
alarmUpdated={alarmUpdated}
onChartLoaded={onChartLoaded}
serverGroup={serverGroup}
/>
);
};
Loading

0 comments on commit 75a614c

Please sign in to comment.